diff --git a/.gitignore b/.gitignore index 4af24f06..8b8fee88 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ Store_vue/.specstory/ Store_vue/unpackage/ Store_vue/.vscode/ SuperAdmin/.specstory/ +Cunkebao/dist diff --git a/Cunkebao/.env.local b/Cunkebao/.env.local new file mode 100644 index 00000000..19e89e7e --- /dev/null +++ b/Cunkebao/.env.local @@ -0,0 +1 @@ +NEXT_PUBLIC_API_BASE_URL= http://yishi.com \ No newline at end of file diff --git a/Cunkebao/dist/.vite/manifest.json b/Cunkebao/dist/.vite/manifest.json deleted file mode 100644 index 994665e2..00000000 --- a/Cunkebao/dist/.vite/manifest.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "_charts-B449e2xS.js": { - "file": "assets/charts-B449e2xS.js", - "name": "charts", - "imports": [ - "_ui-DDu9FCjt.js", - "_vendor-0WYR1k4q.js" - ] - }, - "_ui-D0C0OGrH.css": { - "file": "assets/ui-D0C0OGrH.css", - "src": "_ui-D0C0OGrH.css" - }, - "_ui-DDu9FCjt.js": { - "file": "assets/ui-DDu9FCjt.js", - "name": "ui", - "imports": [ - "_vendor-0WYR1k4q.js" - ], - "css": [ - "assets/ui-D0C0OGrH.css" - ] - }, - "_utils-DC06x9DY.js": { - "file": "assets/utils-DC06x9DY.js", - "name": "utils", - "imports": [ - "_vendor-0WYR1k4q.js" - ] - }, - "_vendor-0WYR1k4q.js": { - "file": "assets/vendor-0WYR1k4q.js", - "name": "vendor" - }, - "index.html": { - "file": "assets/index-DzNmnMYg.js", - "name": "index", - "src": "index.html", - "isEntry": true, - "imports": [ - "_vendor-0WYR1k4q.js", - "_ui-DDu9FCjt.js", - "_utils-DC06x9DY.js", - "_charts-B449e2xS.js" - ], - "css": [ - "assets/index-QrS4Cvyc.css" - ] - } -} \ No newline at end of file diff --git a/Cunkebao/dist/assets/ui-D0C0OGrH.css b/Cunkebao/dist/assets/ui-D0C0OGrH.css deleted file mode 100644 index b0473f5b..00000000 --- a/Cunkebao/dist/assets/ui-D0C0OGrH.css +++ /dev/null @@ -1 +0,0 @@ -:root{--adm-radius-s: .25rem;--adm-radius-m: .5rem;--adm-radius-l: .75rem;--adm-font-size-1: .5625rem;--adm-font-size-2: .625rem;--adm-font-size-3: .6875rem;--adm-font-size-4: .75rem;--adm-font-size-5: .8125rem;--adm-font-size-6: .875rem;--adm-font-size-7: .9375rem;--adm-font-size-8: 1rem;--adm-font-size-9: 1.0625rem;--adm-font-size-10: 1.125rem;--adm-color-primary: #1677ff;--adm-color-success: #00b578;--adm-color-warning: #ff8f1f;--adm-color-danger: #ff3141;--adm-color-yellow: #ff9f18;--adm-color-orange: #ff6430;--adm-color-wathet: #e7f1ff;--adm-color-text: #333333;--adm-color-text-secondary: #666666;--adm-color-weak: #999999;--adm-color-light: #cccccc;--adm-color-border: #eeeeee;--adm-color-background: #ffffff;--adm-color-highlight: var(--adm-color-danger);--adm-color-white: #ffffff;--adm-color-box: #f5f5f5;--adm-color-text-light-solid: var(--adm-color-white);--adm-color-text-dark-solid: #000000;--adm-color-fill-content: var(--adm-color-box);--adm-font-size-main: var(--adm-font-size-5);--adm-font-family: -apple-system, blinkmacsystemfont, "Helvetica Neue", helvetica, segoe ui, arial, roboto, "PingFang SC", "miui", "Hiragino Sans GB", "Microsoft Yahei", sans-serif;--adm-border-color: var(--adm-color-border)}html[data-prefers-color-scheme=dark]{--adm-color-primary: #3086ff;--adm-color-success: #34b368;--adm-color-warning: #ffa930;--adm-color-danger: #ff4a58;--adm-color-yellow: #ffa930;--adm-color-orange: #e65a2b;--adm-color-wathet: #0d2543;--adm-color-text: #e6e6e6;--adm-color-text-secondary: #b3b3b3;--adm-color-weak: #808080;--adm-color-light: #4d4d4d;--adm-color-border: #2b2b2b;--adm-color-box: #0a0a0a;--adm-color-background: #1a1a1a;--adm-color-background-body: var(--adm-color-background);--adm-border-color: var(--adm-color-border)}:root{-webkit-tap-highlight-color:rgba(0,0,0,0)}html{background-color:var(--adm-color-background-body)}body{color:var(--adm-color-text);font-size:var(--adm-font-size-main);font-family:var(--adm-font-family)}a,button{cursor:pointer}a{color:var(--adm-color-primary);transition:opacity ease-in-out .2s}a:active{opacity:.8}.adm-plain-anchor{color:unset;transition:none}.adm-plain-anchor:active{opacity:unset}body.adm-overflow-hidden{overflow:hidden!important}div.adm-px-tester{--size: 1;height:calc(var(--size) / 2 * .125rem);width:0;position:fixed;left:-100vw;top:-100vh;-webkit-user-select:none;user-select:none;pointer-events:none}.adm-action-sheet-popup>.adm-popup-body{border-top-left-radius:.5rem;border-top-right-radius:.5rem;overflow:hidden}.adm-action-sheet-extra{display:flex;justify-content:center;color:var(--adm-color-weak);font-size:var(--adm-font-size-7);padding:1.125rem .75rem;border-bottom:.0625rem solid var(--adm-color-border)}.adm-action-sheet-button-list,.adm-action-sheet-button-item-wrapper{border-bottom:.0625rem solid var(--adm-color-border)}.adm-action-sheet-button-item-wrapper:last-child{border-bottom:none}.adm-action-sheet-button-item{text-align:center;display:block;background-color:var(--adm-color-background);padding:1rem}.adm-action-sheet-button-item:active{background-color:var(--adm-color-border)}.adm-action-sheet-button-item-disabled{cursor:not-allowed;pointer-events:none;opacity:.4}.adm-action-sheet-button-item-name{color:var(--adm-color-text);font-size:var(--adm-font-size-10)}.adm-action-sheet-button-item-description{font-size:var(--adm-font-size-6);color:var(--adm-color-weak);padding-top:.25rem}.adm-action-sheet-button-item-danger .adm-action-sheet-button-item-name{color:var(--adm-color-danger)}.adm-action-sheet-button-item-bold .adm-action-sheet-button-item-name{font-weight:700}.adm-action-sheet-cancel{background-color:var(--adm-color-fill-content);padding-top:.5rem}.adm-popup{--z-index: var(--adm-popup-z-index, 1000);position:fixed;z-index:var(--z-index)}.adm-popup-body{position:fixed;background-color:var(--adm-color-background);z-index:calc(var(--z-index) + 10)}.adm-popup-body .adm-popup-close-icon{position:absolute;z-index:100}.adm-popup-body-position-bottom{width:100%;bottom:0;left:0}.adm-popup-body-position-bottom .adm-popup-close-icon{right:.5rem;top:.5rem}.adm-popup-body-position-top{width:100%;top:0;left:0}.adm-popup-body-position-top .adm-popup-close-icon{right:.5rem;bottom:.5rem}.adm-popup-body-position-left{height:100%;top:0;left:0}.adm-popup-body-position-left .adm-popup-close-icon{right:.5rem;top:.5rem}.adm-popup-body-position-right{height:100%;top:0;right:0}.adm-popup-body-position-right .adm-popup-close-icon{left:.5rem;top:.5rem}.adm-popup-close-icon{cursor:pointer;padding:.25rem;font-size:1.125rem;line-height:1;color:var(--adm-color-weak)}.adm-mask{--z-index: var(--adm-mask-z-index, 1000);position:fixed;top:0;left:0;z-index:var(--z-index);display:block;width:100%;height:100%}.adm-mask-aria-button{position:absolute;top:0;left:0;z-index:0;width:100%;height:100%;pointer-events:none}.adm-mask-content{z-index:1}.adm-safe-area{--multiple: var(--adm-safe-area-multiple, 1);display:block;width:100%}.adm-safe-area-position-top{padding-top:calc(env(safe-area-inset-top) * var(--multiple))}.adm-safe-area-position-bottom{padding-bottom:calc(env(safe-area-inset-bottom) * var(--multiple))}.adm-auto-center{display:flex;justify-content:center}.adm-auto-center-content{flex:0 1 auto}.adm-avatar{--size: var(--adm-avatar-size, 44px);--border-radius: var(--adm-avatar-border-radius, 4px);border-radius:var(--border-radius)}.adm-avatar.adm-image{--width: var(--size);--height: var(--size)}.adm-avatar-fallback{height:100%;width:100%;display:block}.adm-image{--width: var(--adm-image-width, auto);--height: var(--adm-image-height, auto);width:var(--width);height:var(--height);display:block;overflow:hidden}.adm-image-img{width:100%;height:100%}.adm-image-tip{position:relative;background-color:var(--adm-color-fill-content);height:100%;min-height:1.5rem;min-width:1.5rem}.adm-image-tip>svg{width:1.5rem;height:1.5rem;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);color:var(--adm-color-weak)}.adm-badge-wrapper{display:inline-block;position:relative}.adm-badge{display:inline-flex;vertical-align:middle;box-sizing:content-box;border-radius:6.25rem;background-color:var(--color);--right: 0;--top: 0;--color: var(--adm-badge-color, var(--adm-color-highlight))}.adm-badge-content{color:var(--adm-color-text-light-solid);box-sizing:border-box;min-width:.5rem;padding:.0625rem .25rem;font-size:var(--adm-font-size-1);line-height:.75rem;white-space:nowrap;font-weight:400;text-align:center}.adm-badge-fixed{position:absolute;right:var(--right);top:var(--top);transform:translate(50%,-50%)}.adm-badge-dot{min-width:.625rem;width:.625rem;height:.625rem;border-radius:.3125rem}.adm-badge-bordered{border:solid .0625rem var(--adm-color-text-light-solid)}.adm-button{--color: var(--adm-color-text-light-solid);--text-color: var(--adm-button-text-color, var(--adm-color-text));--background-color: var(--adm-button-background-color, var(--adm-color-background));--border-radius: var(--adm-button-border-radius, 4px);--border-width: var(--adm-button-border-width, 1px);--border-style: var(--adm-button-border-style, solid);--border-color: var(--adm-button-border-color, var(--adm-color-border));color:var(--text-color);background-color:var(--background-color);position:relative;display:inline-block;box-sizing:border-box;height:auto;padding:.4375rem .75rem;margin:0;font-size:var(--adm-font-size-9);line-height:1.4;text-align:center;border:var(--border-width) var(--border-style) var(--border-color);border-radius:var(--border-radius);cursor:pointer;transition:opacity ease .15s;-webkit-user-select:none;user-select:none}.adm-button:focus{outline:none}.adm-button:before{position:absolute;top:0;left:0;transform:translate(calc(var(--border-width) * -1),calc(var(--border-width) * -1));width:100%;height:100%;background-color:var(--adm-color-text-dark-solid);border:var(--border-width) var(--border-style) var(--adm-color-text-dark-solid);border-radius:var(--border-radius);opacity:0;content:" ";box-sizing:content-box}.adm-button:active:before{opacity:.08}.adm-button-default.adm-button-fill-outline{--background-color: transparent;--border-color: var(--adm-color-text)}.adm-button-default.adm-button-fill-none{--background-color: transparent;--border-width: 0}.adm-button:not(.adm-button-default){--text-color: var(--adm-color-text-light-solid);--background-color: var(--color);--border-color: var(--color)}.adm-button:not(.adm-button-default).adm-button-fill-outline{--text-color: var(--color);--background-color: transparent}.adm-button:not(.adm-button-default).adm-button-fill-none{--text-color: var(--color);--background-color: transparent;--border-width: 0}.adm-button-primary{--color: var(--adm-color-primary)}.adm-button-success{--color: var(--adm-color-success)}.adm-button-danger{--color: var(--adm-color-danger)}.adm-button-warning{--color: var(--adm-color-warning)}.adm-button-block{display:block;width:100%}.adm-button-disabled{cursor:not-allowed;opacity:.4}.adm-button-disabled:active:before{display:none}.adm-button.adm-button-mini{padding-top:.1875rem;padding-bottom:.1875rem;font-size:var(--adm-font-size-main)}.adm-button.adm-button-mini.adm-button-shape-rounded{padding-left:.5625rem;padding-right:.5625rem}.adm-button.adm-button-small{padding-top:.1875rem;padding-bottom:.1875rem;font-size:var(--adm-font-size-7)}.adm-button.adm-button-large{padding-top:.6875rem;padding-bottom:.6875rem;font-size:var(--adm-font-size-10)}.adm-button.adm-button-shape-rounded{--border-radius: 62.5rem}.adm-button.adm-button-shape-rectangular{--border-radius: 0}.adm-button-loading{vertical-align:bottom}.adm-button-loading-wrapper{display:flex;height:1.4em;align-items:center;justify-content:center}.adm-button-loading-wrapper>.adm-loading{opacity:.6}.adm-dot-loading{display:inline-block}.adm-calendar .adm-calendar-header{display:flex;flex-direction:row;align-items:center;justify-content:space-between;padding-top:.25rem}.adm-calendar .adm-calendar-header a.adm-calendar-arrow-button{padding:.25rem .5rem;display:block;flex:none}.adm-calendar .adm-calendar-header a.adm-calendar-arrow-button svg{height:1.375rem}.adm-calendar .adm-calendar-header a.adm-calendar-arrow-button.adm-calendar-arrow-button-right svg{transform:rotate(180deg)}.adm-calendar .adm-calendar-header .adm-calendar-title{font-size:var(--adm-font-size-10);flex:auto;text-align:center}.adm-calendar .adm-calendar-body{display:flex;flex-wrap:wrap}.adm-calendar-cells{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:stretch;padding:.5rem .5rem .25rem}.adm-calendar-cell{flex:none;box-sizing:border-box;width:calc(100% / 7);height:3rem;margin-bottom:.25rem;padding:.125rem;color:var(--adm-color-text);cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:flex-end}.adm-calendar-cell.adm-calendar-cell-today{color:var(--adm-color-primary)}.adm-calendar-cell.adm-calendar-cell-disabled,.adm-calendar-cell.adm-calendar-cell-disabled .adm-calendar-cell-bottom{color:var(--adm-color-light)}.adm-calendar-cell.adm-calendar-cell-selected.adm-calendar-cell.adm-calendar-cell-selected{background:var(--adm-color-primary);color:var(--adm-color-white)}.adm-calendar-cell.adm-calendar-cell-selected .adm-calendar-cell-bottom{color:var(--adm-color-white)}.adm-calendar-cell.adm-calendar-cell-selected.adm-calendar-cell.adm-calendar-cell-selected-begin{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.adm-calendar-cell.adm-calendar-cell-selected.adm-calendar-cell.adm-calendar-cell-selected-end{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.adm-calendar-cell.adm-calendar-cell-disabled.adm-calendar-cell.adm-calendar-cell-selected{color:var(--adm-color-light)}.adm-calendar-cell .adm-calendar-cell-top{flex:none;font-size:var(--adm-font-size-10)}.adm-calendar-cell .adm-calendar-cell-bottom{flex:none;font-size:var(--adm-font-size-4);height:.75rem;line-height:.75rem;color:var(--adm-color-weak)}.adm-calendar-mark{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;border-bottom:solid .0625rem var(--adm-color-border);height:2.8125rem;box-sizing:border-box;font-size:var(--adm-font-size-7);padding:0 .5rem}.adm-calendar-mark .adm-calendar-mark-cell{flex:1;text-align:center}.adm-calendar-picker .adm-calendar-picker-title,.adm-calendar-picker .adm-calendar-picker-view-title,.adm-calendar-picker .adm-calendar-picker-popup-title,.adm-calendar-picker-view .adm-calendar-picker-title,.adm-calendar-picker-view .adm-calendar-picker-view-title,.adm-calendar-picker-view .adm-calendar-picker-popup-title,.adm-calendar-picker-popup .adm-calendar-picker-title,.adm-calendar-picker-popup .adm-calendar-picker-view-title,.adm-calendar-picker-popup .adm-calendar-picker-popup-title{flex:auto;font-size:var(--adm-font-size-10)}.adm-calendar-picker .adm-calendar-picker-header,.adm-calendar-picker .adm-calendar-picker-view-header,.adm-calendar-picker .adm-calendar-picker-popup-header,.adm-calendar-picker-view .adm-calendar-picker-header,.adm-calendar-picker-view .adm-calendar-picker-view-header,.adm-calendar-picker-view .adm-calendar-picker-popup-header,.adm-calendar-picker-popup .adm-calendar-picker-header,.adm-calendar-picker-popup .adm-calendar-picker-view-header,.adm-calendar-picker-popup .adm-calendar-picker-popup-header{padding:.75rem;border-bottom:.0625rem solid var(--adm-color-border)}.adm-calendar-picker .adm-calendar-picker-header .adm-calendar-picker-view-title,.adm-calendar-picker .adm-calendar-picker-view-header .adm-calendar-picker-view-title,.adm-calendar-picker .adm-calendar-picker-popup-header .adm-calendar-picker-view-title,.adm-calendar-picker-view .adm-calendar-picker-header .adm-calendar-picker-view-title,.adm-calendar-picker-view .adm-calendar-picker-view-header .adm-calendar-picker-view-title,.adm-calendar-picker-view .adm-calendar-picker-popup-header .adm-calendar-picker-view-title,.adm-calendar-picker-popup .adm-calendar-picker-header .adm-calendar-picker-view-title,.adm-calendar-picker-popup .adm-calendar-picker-view-header .adm-calendar-picker-view-title,.adm-calendar-picker-popup .adm-calendar-picker-popup-header .adm-calendar-picker-view-title{text-align:center}.adm-calendar-picker .adm-calendar-picker-body,.adm-calendar-picker .adm-calendar-picker-view-body,.adm-calendar-picker .adm-calendar-picker-popup-body,.adm-calendar-picker-view .adm-calendar-picker-body,.adm-calendar-picker-view .adm-calendar-picker-view-body,.adm-calendar-picker-view .adm-calendar-picker-popup-body,.adm-calendar-picker-popup .adm-calendar-picker-body,.adm-calendar-picker-popup .adm-calendar-picker-view-body,.adm-calendar-picker-popup .adm-calendar-picker-popup-body{height:64vh;overflow:auto}.adm-calendar-picker .adm-calendar-picker-body::-webkit-scrollbar,.adm-calendar-picker .adm-calendar-picker-view-body::-webkit-scrollbar,.adm-calendar-picker .adm-calendar-picker-popup-body::-webkit-scrollbar,.adm-calendar-picker-view .adm-calendar-picker-body::-webkit-scrollbar,.adm-calendar-picker-view .adm-calendar-picker-view-body::-webkit-scrollbar,.adm-calendar-picker-view .adm-calendar-picker-popup-body::-webkit-scrollbar,.adm-calendar-picker-popup .adm-calendar-picker-body::-webkit-scrollbar,.adm-calendar-picker-popup .adm-calendar-picker-view-body::-webkit-scrollbar,.adm-calendar-picker-popup .adm-calendar-picker-popup-body::-webkit-scrollbar{display:none}.adm-calendar-picker .adm-calendar-picker-body .adm-calendar-picker-view-title,.adm-calendar-picker .adm-calendar-picker-view-body .adm-calendar-picker-view-title,.adm-calendar-picker .adm-calendar-picker-popup-body .adm-calendar-picker-view-title,.adm-calendar-picker-view .adm-calendar-picker-body .adm-calendar-picker-view-title,.adm-calendar-picker-view .adm-calendar-picker-view-body .adm-calendar-picker-view-title,.adm-calendar-picker-view .adm-calendar-picker-popup-body .adm-calendar-picker-view-title,.adm-calendar-picker-popup .adm-calendar-picker-body .adm-calendar-picker-view-title,.adm-calendar-picker-popup .adm-calendar-picker-view-body .adm-calendar-picker-view-title,.adm-calendar-picker-popup .adm-calendar-picker-popup-body .adm-calendar-picker-view-title{position:-webkit-sticky;position:sticky;top:0;padding:.5rem 1.25rem;background-color:var(--adm-color-box)}.adm-calendar-picker .adm-calendar-picker-footer-bottom,.adm-calendar-picker .adm-calendar-picker-view-footer-bottom,.adm-calendar-picker .adm-calendar-picker-popup-footer-bottom,.adm-calendar-picker-view .adm-calendar-picker-footer-bottom,.adm-calendar-picker-view .adm-calendar-picker-view-footer-bottom,.adm-calendar-picker-view .adm-calendar-picker-popup-footer-bottom,.adm-calendar-picker-popup .adm-calendar-picker-footer-bottom,.adm-calendar-picker-popup .adm-calendar-picker-view-footer-bottom,.adm-calendar-picker-popup .adm-calendar-picker-popup-footer-bottom{padding:0 1.25rem 1rem}.adm-calendar-picker .adm-calendar-picker-footer .adm-divider,.adm-calendar-picker .adm-calendar-picker-view-footer .adm-divider,.adm-calendar-picker .adm-calendar-picker-popup-footer .adm-divider,.adm-calendar-picker-view .adm-calendar-picker-footer .adm-divider,.adm-calendar-picker-view .adm-calendar-picker-view-footer .adm-divider,.adm-calendar-picker-view .adm-calendar-picker-popup-footer .adm-divider,.adm-calendar-picker-popup .adm-calendar-picker-footer .adm-divider,.adm-calendar-picker-popup .adm-calendar-picker-view-footer .adm-divider,.adm-calendar-picker-popup .adm-calendar-picker-popup-footer .adm-divider{margin-top:0}.adm-calendar-picker .adm-calendar-picker-footer .adm-button,.adm-calendar-picker .adm-calendar-picker-view-footer .adm-button,.adm-calendar-picker .adm-calendar-picker-popup-footer .adm-button,.adm-calendar-picker-view .adm-calendar-picker-footer .adm-button,.adm-calendar-picker-view .adm-calendar-picker-view-footer .adm-button,.adm-calendar-picker-view .adm-calendar-picker-popup-footer .adm-button,.adm-calendar-picker-popup .adm-calendar-picker-footer .adm-button,.adm-calendar-picker-popup .adm-calendar-picker-view-footer .adm-button,.adm-calendar-picker-popup .adm-calendar-picker-popup-footer .adm-button{width:100%}.adm-calendar-picker-cells,.adm-calendar-picker-view-cells,.adm-calendar-picker-popup-cells{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:stretch;padding:.25rem .5rem}.adm-calendar-picker-cell,.adm-calendar-picker-view-cell,.adm-calendar-picker-popup-cell{flex:none;box-sizing:border-box;width:calc(100% / 7);min-height:3.4375rem;margin-bottom:.25rem;padding:.125rem;color:var(--adm-color-text);cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center}.adm-calendar-picker-cell.adm-calendar-picker-cell-today,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-today,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-today,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-today,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-today,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-today,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-today,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-today,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-today{color:var(--adm-color-primary)}.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled,.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled .adm-calendar-picker-view-cell-top,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled .adm-calendar-picker-view-cell-top,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled .adm-calendar-picker-view-cell-top,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled .adm-calendar-picker-view-cell-top,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled .adm-calendar-picker-view-cell-top,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled .adm-calendar-picker-view-cell-top,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled .adm-calendar-picker-view-cell-top,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled .adm-calendar-picker-view-cell-top,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled .adm-calendar-picker-view-cell-top,.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled .adm-calendar-picker-view-cell-bottom{color:var(--adm-color-light)}.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected{background:#1677ff1a;color:var(--adm-color-text)}.adm-calendar-picker-cell.adm-calendar-picker-cell-selected .adm-calendar-picker-view-cell-top,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected .adm-calendar-picker-view-cell-top,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected .adm-calendar-picker-view-cell-top,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected .adm-calendar-picker-view-cell-top,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected .adm-calendar-picker-view-cell-top,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected .adm-calendar-picker-view-cell-top,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected .adm-calendar-picker-view-cell-top,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected .adm-calendar-picker-view-cell-top,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected .adm-calendar-picker-view-cell-top,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected .adm-calendar-picker-view-cell-bottom{color:var(--adm-color-white)}.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-begin,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-begin{background:var(--adm-color-primary);color:var(--adm-color-white);border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected-end,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected-end{background:var(--adm-color-primary);color:var(--adm-color-white);border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-view-cell.adm-calendar-picker-popup-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-view-cell-selected,.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-disabled.adm-calendar-picker-popup-cell.adm-calendar-picker-popup-cell-selected{color:var(--adm-color-light)}.adm-calendar-picker-cell .adm-calendar-picker-cell-date,.adm-calendar-picker-cell .adm-calendar-picker-view-cell-date,.adm-calendar-picker-cell .adm-calendar-picker-popup-cell-date,.adm-calendar-picker-view-cell .adm-calendar-picker-cell-date,.adm-calendar-picker-view-cell .adm-calendar-picker-view-cell-date,.adm-calendar-picker-view-cell .adm-calendar-picker-popup-cell-date,.adm-calendar-picker-popup-cell .adm-calendar-picker-cell-date,.adm-calendar-picker-popup-cell .adm-calendar-picker-view-cell-date,.adm-calendar-picker-popup-cell .adm-calendar-picker-popup-cell-date{flex:none;line-height:1.375rem;font-size:var(--adm-font-size-8)}.adm-calendar-picker-cell .adm-calendar-picker-cell-top,.adm-calendar-picker-cell .adm-calendar-picker-view-cell-top,.adm-calendar-picker-cell .adm-calendar-picker-popup-cell-top,.adm-calendar-picker-view-cell .adm-calendar-picker-cell-top,.adm-calendar-picker-view-cell .adm-calendar-picker-view-cell-top,.adm-calendar-picker-view-cell .adm-calendar-picker-popup-cell-top,.adm-calendar-picker-popup-cell .adm-calendar-picker-cell-top,.adm-calendar-picker-popup-cell .adm-calendar-picker-view-cell-top,.adm-calendar-picker-popup-cell .adm-calendar-picker-popup-cell-top,.adm-calendar-picker-cell .adm-calendar-picker-cell-bottom,.adm-calendar-picker-cell .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-cell .adm-calendar-picker-popup-cell-bottom,.adm-calendar-picker-view-cell .adm-calendar-picker-cell-bottom,.adm-calendar-picker-view-cell .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-view-cell .adm-calendar-picker-popup-cell-bottom,.adm-calendar-picker-popup-cell .adm-calendar-picker-cell-bottom,.adm-calendar-picker-popup-cell .adm-calendar-picker-view-cell-bottom,.adm-calendar-picker-popup-cell .adm-calendar-picker-popup-cell-bottom{flex:none;font-size:var(--adm-font-size-1);height:.875rem;line-height:.875rem;color:var(--adm-color-weak)}.adm-calendar-picker-mark,.adm-calendar-picker-view-mark,.adm-calendar-picker-popup-mark{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;border-bottom:solid .0625rem var(--adm-color-border);height:2.8125rem;box-sizing:border-box;font-size:var(--adm-font-size-6);padding:0 .5rem}.adm-calendar-picker-mark .adm-calendar-picker-mark-cell,.adm-calendar-picker-mark .adm-calendar-picker-view-mark-cell,.adm-calendar-picker-mark .adm-calendar-picker-popup-mark-cell,.adm-calendar-picker-view-mark .adm-calendar-picker-mark-cell,.adm-calendar-picker-view-mark .adm-calendar-picker-view-mark-cell,.adm-calendar-picker-view-mark .adm-calendar-picker-popup-mark-cell,.adm-calendar-picker-popup-mark .adm-calendar-picker-mark-cell,.adm-calendar-picker-popup-mark .adm-calendar-picker-view-mark-cell,.adm-calendar-picker-popup-mark .adm-calendar-picker-popup-mark-cell{flex:1;text-align:center}.adm-divider-horizontal{display:flex;align-items:center;margin:1rem 0;border-width:0;border-color:var(--adm-color-border);border-style:solid;color:var(--adm-color-weak);font-size:.875rem}.adm-divider-left.adm-divider-horizontal:before{max-width:10%}.adm-divider-right.adm-divider-horizontal:after{max-width:10%}.adm-divider-horizontal:after,.adm-divider-horizontal:before{flex:auto;display:block;content:"";border-style:inherit;border-color:inherit;border-width:.0625rem 0 0}.adm-divider-horizontal .adm-divider-content{flex:none;padding:0 1rem}.adm-divider-vertical{position:relative;top:-.06em;display:inline-block;height:.9em;margin:0 1rem;vertical-align:middle;border-top:0;border-left:.0625rem solid var(--adm-color-border)}.adm-capsule-tabs{position:relative;min-width:0}.adm-capsule-tabs-header{position:relative;padding:.75rem .375rem;border-bottom:solid .0625rem var(--adm-color-border)}.adm-capsule-tabs-tab-list{display:flex;flex-wrap:nowrap;justify-content:flex-start;align-items:center;position:relative;overflow-x:scroll;scrollbar-width:none}.adm-capsule-tabs-tab-list::-webkit-scrollbar{display:none}.adm-capsule-tabs-tab-wrapper{flex:auto;padding:0 .375rem}.adm-capsule-tabs-tab{position:relative;padding:.5rem 1.25rem;margin:0 auto;border-radius:1.25rem;cursor:pointer;font-size:var(--adm-font-size-7);text-align:center;white-space:nowrap;background-color:var(--adm-color-fill-content)}.adm-capsule-tabs-tab-active{color:var(--adm-color-text-light-solid);background-color:var(--adm-color-primary)}.adm-capsule-tabs-tab-disabled{opacity:.5;cursor:not-allowed}.adm-capsule-tabs-content{padding:.75rem}.adm-scroll-mask{position:absolute;top:0;bottom:0;z-index:1;width:1.875rem;height:100%;pointer-events:none}.adm-scroll-mask-left{left:0;background:linear-gradient(to right,var(--adm-color-background),rgba(255,255,255,0))}.adm-scroll-mask-right{right:0;background:linear-gradient(to left,var(--adm-color-background),rgba(255,255,255,0))}.adm-card{background:var(--adm-color-background);border-radius:var(--adm-card-border-radius, 8px);padding:0 var(--adm-card-padding-inline, 12px)}.adm-card-header{position:relative;display:flex;justify-content:space-between;align-items:center;gap:var(--adm-card-header-gap, 8px);box-sizing:border-box;padding:var(--adm-card-header-padding-block, 12px) 0}.adm-card-header:not(:last-child){border-bottom:solid var(--adm-card-header-border-width, .5px) var(--adm-card-header-border-color, var(--adm-color-border))}.adm-card-header-title{font-size:var(--adm-font-size-7);line-height:1.4;font-weight:700}.adm-card-body{padding:var(--adm-card-body-padding-block, 12px) 0}.adm-picker{--header-button-font-size: var(--adm-font-size-7);--title-font-size: var(--adm-font-size-7);--item-font-size: var(--adm-font-size-8);--item-height: 2.125rem;width:100%;height:18.75rem;overflow:hidden;position:relative;display:flex;flex-direction:column;---item-font-size: var(--item-font-size);---item-height: var(--item-height)}.adm-picker .adm-picker-view.adm-picker-view{--item-font-size: var(---item-font-size);--item-height: var(---item-height)}.adm-picker-header{flex-shrink:0;border-bottom:solid .0625rem var(--adm-color-border);display:flex;justify-content:space-between;align-items:center;padding:.25rem}.adm-picker-header-button{font-size:var(--header-button-font-size);display:inline-block;padding:.5rem}.adm-picker-header-button-disabled,.adm-picker-header-button-disabled:active{opacity:.4;cursor:not-allowed}.adm-picker-header-title{padding:.25rem;font-size:var(--title-font-size);color:var(--adm-color-text);text-align:center;flex:1}.adm-picker-body{flex:1;width:100%;height:100%}.adm-picker-body>.adm-picker-view{--height: 100%}.adm-picker-popup .adm-popup-body{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.adm-spin-loading{--color: var(--adm-color-weak);--size: 2rem;width:var(--size);height:var(--size)}.adm-spin-loading-svg{width:100%;height:100%;animation:adm-spin-loading-rotate .8s infinite linear}.adm-spin-loading-svg>.adm-spin-loading-fill{stroke:var(--color)}@keyframes adm-spin-loading-rotate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.adm-picker-view{--height: 15rem;--item-height: 2.125rem;--item-font-size: var(--adm-font-size-8);height:var(--height);width:100%;display:flex;position:relative;overflow:hidden;background:var(--adm-color-background)}.adm-picker-view-column{height:100%;flex:1;-webkit-user-select:none;user-select:none;touch-action:none;position:relative;z-index:0}.adm-picker-view-column-wheel{width:100%;cursor:-webkit-grab;cursor:grab;position:absolute;top:calc(50% - var(--item-height) / 2);left:0}.adm-picker-view-column-wheel:before{content:" ";display:block;position:absolute;width:100%;height:100vh;top:-100vh}.adm-picker-view-column-wheel:after{content:" ";display:block;position:absolute;width:100%;height:100vh;bottom:-100vh}.adm-picker-view-column-item{font-size:var(--item-font-size);padding:0 .375rem;height:var(--item-height);display:flex;justify-content:center;align-items:center}.adm-picker-view-column-item-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.adm-picker-view-column-accessible{width:100%;height:100%;pointer-events:none;opacity:0;display:flex;flex-direction:column;position:relative;top:calc(var(--item-height) * -1);z-index:0;padding-bottom:.0625rem}.adm-picker-view-column-accessible>*{flex:1;text-overflow:ellipsis}.adm-picker-view-column-accessible-current{position:absolute;width:100%;height:100%}.adm-picker-view-column-accessible-button{width:100%;height:100%}.adm-picker-view-mask{position:absolute;z-index:10000;left:0;top:0;width:100%;height:100%;display:flex;flex-direction:column;pointer-events:none}.adm-picker-view-mask-top,.adm-picker-view-mask-bottom{flex:auto}.adm-picker-view-mask-middle{height:var(--item-height);box-sizing:border-box;flex:none;border-top:solid .0625rem var(--adm-color-border);border-bottom:solid .0625rem var(--adm-color-border)}.adm-picker-view-mask-top{background:var(--adm-color-background);-webkit-mask:linear-gradient(0deg,rgba(0,0,0,.6) 0%,rgba(0,0,0,.8) 50%,#000000 100%);mask:linear-gradient(0deg,rgba(0,0,0,.6) 0%,rgba(0,0,0,.8) 50%,#000000 100%)}.adm-picker-view-mask-bottom{background:var(--adm-color-background);-webkit-mask:linear-gradient(180deg,rgba(0,0,0,.6) 0%,rgba(0,0,0,.8) 50%,#000000 100%);mask:linear-gradient(180deg,rgba(0,0,0,.6) 0%,rgba(0,0,0,.8) 50%,#000000 100%)}.adm-picker-view-loading-content{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.adm-picker-view-item-height-measure{position:relative;left:0;top:0;height:var(--item-height);width:0;pointer-events:none}.adm-cascader-view{--height: auto}.adm-cascader-view-tabs.adm-tabs{--title-font-size: var(--adm-font-size-6);--content-padding: none}.adm-cascader-view-header-title{max-width:5.25rem;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.adm-cascader-view-content{height:var(--height);overflow-y:auto}.adm-cascader-view-content>.adm-check-list{--border-inner: none;--border-bottom: none;--border-top: none}.adm-cascader-view-item{font-size:var(--adm-font-size-6)}.adm-cascader-view-item-active{color:var(--adm-color-primary)}.adm-cascader-view .adm-list-inner{margin-bottom:0}.adm-cascader-view-skeleton{padding:1rem .75rem}.adm-cascader-view-skeleton .adm-skeleton{margin-bottom:1rem;--height: 1.125rem;--width: 80%;--border-radius: .125rem}.adm-cascader-view-skeleton .adm-skeleton.adm-cascader-view-skeleton-line-3{--width: 90%}.adm-cascader-view-skeleton .adm-skeleton.adm-cascader-view-skeleton-line-4{--width: 60%}.adm-tabs{--title-font-size: var(--adm-font-size-9);--content-padding: .75rem;--active-line-height: .125rem;--active-line-border-radius: var(--active-line-height);--active-line-color: var(--adm-color-primary);--active-title-color: var(--adm-color-primary);position:relative;min-width:0}.adm-tabs-header{position:relative;border-bottom:solid .0625rem var(--adm-color-border)}.adm-tabs-tab-list{display:flex;flex-wrap:nowrap;justify-content:flex-start;align-items:center;position:relative;overflow-x:scroll;scrollbar-width:none}.adm-tabs-tab-list::-webkit-scrollbar{display:none}.adm-tabs-tab-wrapper{padding:0 .75rem}.adm-tabs-tab-wrapper-stretch{flex:auto}.adm-tabs-tab{white-space:nowrap;padding:.5rem 0 .625rem;width:-webkit-min-content;width:min-content;margin:0 auto;font-size:var(--title-font-size);position:relative;cursor:pointer}.adm-tabs-tab-active{color:var(--active-title-color)}.adm-tabs-tab-disabled{opacity:.5;cursor:not-allowed}.adm-tabs-tab-line{position:absolute;bottom:0;height:var(--active-line-height);background:var(--active-line-color);border-radius:var(--active-line-border-radius)}.adm-tabs-content{padding:var(--content-padding)}.adm-tabs-header-mask{position:absolute;top:0;bottom:0;z-index:1;width:1.875rem;height:100%;pointer-events:none}.adm-tabs-header-mask-left{left:0;background:linear-gradient(to right,var(--adm-color-background),rgba(255,255,255,0))}.adm-tabs-header-mask-right{right:0;background:linear-gradient(to left,var(--adm-color-background),rgba(255,255,255,0))}.adm-check-list-item-extra{font-size:var(--adm-font-size-10);line-height:1;color:var(--adm-color-primary)}.adm-check-list-item-readonly{cursor:unset}.adm-list{--header-font-size: var(--adm-font-size-7);--prefix-width: "auto";--prefix-padding-right: .75rem;--align-items: center;--active-background-color: var(--adm-color-border);--border-inner: solid .0625rem var(--adm-color-border);--border-top: solid .0625rem var(--adm-color-border);--border-bottom: solid .0625rem var(--adm-color-border);--padding-left: .75rem;--padding-right: .75rem;--font-size: var(--adm-font-size-9);--extra-max-width: 70%}.adm-list-header{color:var(--adm-color-weak);font-size:var(--header-font-size);padding:.5rem var(--padding-right) .5rem var(--padding-left)}.adm-list-body{background-color:var(--adm-color-background);overflow:hidden;font-size:var(--font-size)}.adm-list-body-inner{margin-top:-.0625rem}.adm-list-default .adm-list-body{border-top:var(--border-top);border-bottom:var(--border-bottom)}.adm-list-card{margin:.75rem}.adm-list-card .adm-list-body{border-radius:.5rem}.adm-list-card .adm-list-header{padding-left:0}.adm-list-item{display:block;padding-left:var(--padding-left);position:relative;background-color:var(--adm-color-background);line-height:1.5}.adm-list-item-title,.adm-list-item-description{color:var(--adm-color-weak);font-size:var(--adm-font-size-main)}.adm-list-item-content{display:flex;align-items:var(--align-items);justify-content:flex-start;border-top:var(--border-inner);padding-right:var(--padding-right)}.adm-list-item-content-prefix{width:var(--prefix-width);flex:none;padding-right:var(--prefix-padding-right)}.adm-list-item-content-main{flex:auto;padding:.75rem 0}.adm-list-item-content-extra{flex:none;padding-left:.75rem;font-size:var(--adm-font-size-7);color:var(--adm-color-weak);max-width:var(--extra-max-width)}.adm-list-item-content-arrow{flex:none;display:flex;align-items:center;margin-left:.25rem;color:var(--adm-color-light);font-size:1.1875rem}.adm-list-item-disabled{cursor:not-allowed}.adm-list-item-disabled.adm-list-item-disabled>.adm-list-item-content>*{opacity:.4;pointer-events:none}a.adm-list-item:active:not(.adm-list-item-disabled){background-color:var(--active-background-color)}a.adm-list-item:active:not(.adm-list-item-disabled):after{content:" ";display:block;position:absolute;width:100%;bottom:-.0625rem;left:0;border-bottom:var(--border-inner)}.adm-skeleton{--width: 100%;--height: 0;--border-radius: 0;background-color:#bebebe33;border-radius:var(--border-radius);width:var(--width);height:var(--height);display:block}.adm-skeleton.adm-skeleton-animated{background:linear-gradient(90deg,#bebebe33 25%,#8181813d 37%,#bebebe33 63%);background-size:400% 100%;animation:adm-skeleton-loading 1.4s ease infinite}.adm-skeleton.adm-skeleton-title{--width: 45%;--height: 2rem;--border-radius: .125rem;margin-bottom:1rem;margin-top:1rem}.adm-skeleton.adm-skeleton-paragraph-line{--height: 1.125rem;--border-radius: .125rem;margin-top:.75rem;margin-bottom:.75rem}.adm-skeleton.adm-skeleton-paragraph-line:last-child{--width: 65%}@keyframes adm-skeleton-loading{0%{background-position:100% 50%}to{background-position:0 50%}}.adm-cascader{width:100%;overflow:hidden;position:relative;display:flex;flex-direction:column}.adm-cascader-header{flex:none;display:flex;justify-content:space-between;align-items:center;padding:.375rem .5rem}.adm-cascader-header-button{font-size:var(--adm-font-size-7);display:inline-block;padding:.25rem}.adm-cascader-header-title{padding:.25rem;font-size:var(--adm-font-size-7);color:var(--adm-color-text);text-align:center;flex:1}.adm-cascader-body{flex:auto;height:100%;width:100%}.adm-cascader-body>.adm-cascader-view{--height: 19.375rem}.adm-center-popup{--background-color: var(--adm-center-popup-background-color, var(--adm-color-background));--border-radius: var(--adm-center-popup-border-radius, 8px);--max-width: var(--adm-center-popup-max-width, 75vw);--min-width: var(--adm-center-popup-min-width, 280px);--z-index: var(--adm-center-popup-z-index, 1000);position:fixed;z-index:var(--z-index)}.adm-center-popup .adm-center-popup-mask{z-index:0}.adm-center-popup-wrap{position:fixed;z-index:1;top:50%;left:50%;width:auto;min-width:var(--min-width);max-width:var(--max-width);transform:translate(-50%,-50%)}.adm-center-popup-body{background-color:var(--background-color);border-radius:var(--border-radius)}.adm-center-popup-close{position:absolute;z-index:100;right:.5rem;top:.5rem;cursor:pointer;padding:.25rem;font-size:1.125rem;color:var(--adm-color-weak)}.adm-checkbox{--icon-size: 1.375rem;--font-size: var(--adm-font-size-9);--gap: .5rem;display:inline-flex;vertical-align:text-bottom;justify-content:flex-start;align-items:center;cursor:pointer}.adm-checkbox input{display:none}.adm-checkbox .adm-checkbox-icon{flex:none;border:.0625rem solid var(--adm-color-light);border-radius:var(--icon-size);box-sizing:border-box;width:var(--icon-size);height:var(--icon-size);color:var(--adm-color-text-light-solid)}.adm-checkbox .adm-checkbox-icon>svg{display:block;width:100%;height:100%}.adm-checkbox.adm-checkbox-block{display:flex}.adm-checkbox.adm-checkbox-checked .adm-checkbox-icon{border-color:var(--adm-color-primary);background-color:var(--adm-color-primary)}.adm-checkbox.adm-checkbox-disabled{cursor:not-allowed}.adm-checkbox.adm-checkbox-disabled .adm-checkbox-content{opacity:.4}.adm-checkbox.adm-checkbox-disabled .adm-checkbox-icon.adm-checkbox-icon{color:var(--adm-color-light);border-color:var(--adm-color-light);background-color:var(--adm-color-fill-content)}.adm-checkbox .adm-checkbox-custom-icon{font-size:var(--icon-size)}.adm-checkbox.adm-checkbox-indeterminate .adm-checkbox-icon{background-color:var(--adm-color-background);color:var(--adm-color-primary)}.adm-checkbox-content{flex:0 1 auto;font-size:var(--font-size);padding-left:var(--gap)}.adm-collapse-panel-header .adm-list-item-content-main{padding:.75rem 0}.adm-collapse-arrow{transform:rotate(0);transition:all ease .3s}.adm-collapse-arrow-active{transform:rotate(-180deg)}.adm-collapse-panel-content{font-size:var(--adm-font-size-main);color:var(--adm-color-weak);overflow:hidden}.adm-dialog{--z-index: var(--adm-dialog-z-index, 1000);---z-index: var(--z-index)}.adm-dialog .adm-center-popup{--z-index: var(---z-index)}.adm-dialog-body{width:100%;max-height:70vh;font-size:var(--adm-font-size-6);overflow:hidden;display:flex;flex-direction:column}.adm-dialog-body>*{flex:none}.adm-dialog-body>.adm-dialog-content{flex:auto}.adm-dialog-body:not(.adm-dialog-with-image){padding-top:1.25rem}.adm-dialog-image-container{margin-bottom:.75rem;max-height:40vh}.adm-dialog-header{margin-bottom:.5rem;padding:0 .75rem}.adm-dialog-title{margin-bottom:.5rem;padding:0 .75rem;font-weight:700;font-size:var(--adm-font-size-10);line-height:1.5625rem;text-align:center}.adm-dialog-content{padding:0 .75rem 1.25rem;max-height:70vh;overflow-x:hidden;overflow-y:auto;font-size:var(--adm-font-size-7);line-height:1.4;color:var(--adm-color-text)}.adm-dialog-content-empty{padding:0;height:.75rem}.adm-dialog-footer{-webkit-user-select:none;user-select:none}.adm-dialog-footer .adm-dialog-action-row{display:flex;align-items:stretch;border-top:.03125rem solid var(--adm-color-border)}.adm-dialog-footer .adm-dialog-action-row>*{flex:1}.adm-dialog-footer .adm-dialog-action-row>.adm-dialog-button{padding:.625rem;font-size:var(--adm-font-size-10);line-height:1.5625rem;border-radius:0;border-right:solid .03125rem var(--adm-color-border)}.adm-dialog-footer .adm-dialog-action-row>.adm-dialog-button-bold{font-weight:700}.adm-dialog-footer .adm-dialog-action-row>.adm-dialog-button:last-child{border-right:none}.adm-dialog-image-container{overflow-y:auto}.adm-dropdown{background-color:var(--adm-color-background)}.adm-dropdown .adm-dropdown-nav{display:flex;border-bottom:.0625rem solid transparent}.adm-dropdown-open .adm-dropdown-nav{border-bottom-color:var(--adm-color-border)}.adm-dropdown-item{display:flex;flex:1;justify-content:center;min-width:0;cursor:pointer}.adm-dropdown-item .adm-dropdown-item-title{display:flex;align-items:center;position:relative;max-width:100%;font-size:var(--adm-font-size-main);padding:.75rem}.adm-dropdown-item .adm-dropdown-item-title-text{margin-right:.3125rem;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.adm-dropdown-item .adm-dropdown-item-title-arrow{color:var(--adm-color-light);font-size:.5625rem;transform:rotate(0) translateY(.0625rem);transition:all ease .2s}.adm-dropdown-item .adm-dropdown-item-title-arrow-active{transform:rotate(-180deg) translateY(-.0625rem)}.adm-dropdown-item .adm-dropdown-item-title:active{opacity:.7}.adm-dropdown-item-highlight{color:var(--adm-color-primary)}.adm-dropdown-item-active .adm-dropdown-item-title:after{margin-top:-.0625rem;transform:rotate(135deg)}.adm-dropdown-item-content{width:100%;background:var(--adm-color-background)}.adm-dropdown-item-content-hidden{display:none}.adm-dropdown-popup{position:fixed;overflow:hidden;width:100%;right:0;bottom:0;left:0}.adm-dropdown-popup .adm-dropdown-popup-mask,.adm-dropdown-popup .adm-dropdown-popup-body{position:absolute}.adm-ellipsis{overflow:hidden;line-height:1.5;word-break:break-word}.adm-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:1.5rem 0}.adm-empty-image-container{display:flex;justify-content:center}.adm-empty-image-container .adm-empty-image{width:4rem;height:intrinsic}.adm-empty-description{margin-top:.5rem;font-size:var(--adm-font-size-6);color:var(--adm-color-light)}.adm-error-block{--color: var(--adm-color-text);--image-height: var(--adm-error-block-image-height, 100px);--image-height-full-page: var(--adm-error-block-image-height-full-page, 200px);--image-width: var(--adm-error-block-image-width, auto);--image-width-full-page: var(--adm-error-block-image-width-full-page, auto);box-sizing:border-box;text-align:center}.adm-error-block-image{height:var(--image-height);width:var(--image-width);max-width:100%}.adm-error-block-image svg,.adm-error-block-image img{height:100%}.adm-error-block-description{font-size:var(--adm-font-size-4);color:var(--adm-color-weak);line-height:1.4;margin-top:.75rem}.adm-error-block-description-title{font-size:var(--adm-font-size-7)}.adm-error-block-description-subtitle{margin-top:.5rem}.adm-error-block-content{margin-top:.75rem}.adm-error-block-full-page{padding-top:calc(50vh - var(--image-height-full-page))}.adm-error-block-full-page .adm-error-block-image{height:var(--image-height-full-page);width:var(--image-width-full-page)}.adm-error-block-full-page .adm-error-block-description{margin-top:1.25rem;font-size:var(--adm-font-size-main)}.adm-error-block-full-page .adm-error-block-description-title{font-size:1.25rem;color:var(--adm-color-text)}.adm-floating-bubble{--initial-position-left: var(--initial-position-left);--initial-position-right: var(--initial-position-right);--initial-position-top: var(--initial-position-top);--initial-position-bottom: var(--initial-position-bottom);--z-index: 1;--edge-distance: 0;--size: 3rem;--border-radius: 50%;--background: var(--adm-color-primary)}.adm-floating-bubble-boundary-outer{position:fixed;left:0;top:0;width:100vw;height:100vh;padding:var(--edge-distance);box-sizing:border-box;pointer-events:none}.adm-floating-bubble-boundary{position:relative;width:100%;height:100%}.adm-floating-bubble-button{position:fixed;top:var(--initial-position-top);bottom:var(--initial-position-bottom);left:var(--initial-position-left);right:var(--initial-position-right);box-sizing:border-box;width:var(--size);height:var(--size);display:flex;justify-content:center;align-items:center;overflow:hidden;cursor:pointer;transition:opacity ease .15s;-webkit-user-select:none;user-select:none;touch-action:none;background:var(--background);color:var(--adm-color-white);border-radius:var(--border-radius);z-index:var(--z-index)}.adm-floating-panel{--border-radius: .5rem;--header-height: 1.75rem;--z-index: var(--adm-floating-panel-z-index, 900);position:fixed;z-index:var(--z-index);left:0;width:100vw;display:flex;flex-direction:column;touch-action:none}.adm-floating-panel-mask{display:block;width:100%;height:100vh;position:absolute;left:0;top:-100vh;background:transparent}.adm-floating-panel:after{content:"";display:block;position:absolute;height:100vh;width:100vw;background:var(--adm-color-background)}.adm-floating-panel .adm-floating-panel-header{flex:none;height:var(--header-height);display:flex;justify-content:center;align-items:center;cursor:-webkit-grab;cursor:grab;-webkit-user-select:none;user-select:none;background-color:var(--adm-color-background);border-top-left-radius:var(--border-radius);border-top-right-radius:var(--border-radius)}.adm-floating-panel .adm-floating-panel-header .adm-floating-panel-bar{height:.1875rem;width:1.25rem;border-radius:.625rem;background:var(--adm-color-light)}.adm-floating-panel .adm-floating-panel-content{flex:1;overflow-y:scroll;background:var(--adm-color-background)}.adm-floating-panel-top{top:0}.adm-floating-panel-top:after{top:-100vh}.adm-floating-panel-bottom{bottom:0}.adm-floating-panel-bottom:after{bottom:-100vh}.adm-form{--border-inner: solid .0625rem var(--adm-border-color);--border-top: solid .0625rem var(--adm-border-color);--border-bottom: solid .0625rem var(--adm-border-color);--prefix-width: 6.8em;---border-inner: var(--border-inner);---border-top: var(--border-top);---border-bottom: var(--border-bottom);---prefix-width: var(--prefix-width)}.adm-form .adm-list.adm-list{--padding-left: 1rem;--padding-right: .75rem;--border-inner: var(---border-inner);--border-top: var(---border-top);--border-bottom: var(---border-bottom)}.adm-form .adm-form-footer{padding:1.25rem .75rem}.adm-form .adm-form-item-horizontal.adm-list-item{--prefix-width: var(---prefix-width)}.adm-form-list-operation{text-align:center;color:var(--adm-color-primary)}.adm-form-item+.adm-form-item{border-top:none}.adm-form-item-label{display:block;height:100%;line-height:1.5;box-sizing:border-box;position:relative;color:var(--adm-color-text-secondary)}.adm-form-item-label .adm-form-item-required-asterisk{position:absolute;left:-.6em;top:0;font-family:SimSun,sans-serif;color:var(--adm-color-danger);-webkit-user-select:none;user-select:none}.adm-form-item-label .adm-form-item-required-text{margin-left:.25rem;color:var(--adm-color-weak)}.adm-form-item-label-help{margin-left:.25rem;cursor:pointer}.adm-form-item-child{display:flex}.adm-form-item-child-position-normal{justify-content:normal}.adm-form-item-child-position-normal>*{flex:auto}.adm-form-item-child-position-right{justify-content:flex-end}.adm-form-item-child-position-right>*{flex:none}.adm-form-item-feedback-error{color:var(--adm-color-danger);margin-top:.25rem}.adm-form-item-feedback-warning{color:var(--adm-color-warning);margin-top:.25rem}.adm-form-item.adm-form-item-hidden{display:none}.adm-form-item.adm-form-item-horizontal.adm-list-item{--align-items: stretch}.adm-form-item.adm-form-item-horizontal .adm-list-item-content-prefix{padding-top:.75rem;padding-bottom:.75rem}.adm-form-item.adm-form-item-horizontal .adm-list-item-content-extra{align-self:center}.adm-form-item.adm-form-item-vertical .adm-form-item-label{font-size:var(--adm-font-size-7);margin-bottom:.25rem}.adm-popover{--z-index: var(--adm-popover-z-index, 1030);--background: #ffffff;--arrow-size: .5rem;--content-padding: .5rem .75rem;color:var(--adm-color-text);position:absolute;top:0;left:0;z-index:var(--z-index);white-space:normal;text-align:left;cursor:auto;-webkit-user-select:text;user-select:text;animation:none}.adm-popover.adm-popover-dark{--background: rgba(0, 0, 0, .75);--adm-color-text: #ffffff;color:#fff}.adm-popover.adm-popover-dark .adm-popover-inner{box-shadow:none}.adm-popover:after{position:absolute;background:#ffffff03;content:""}.adm-popover-hidden{display:none}.adm-popover-inner{background-color:var(--background);background-clip:padding-box;border-radius:.5rem;box-shadow:0 0 1.875rem #3333;font-size:var(--adm-font-size-7);width:-webkit-max-content;width:max-content;min-width:2rem;max-width:calc(100vw - 1.5rem);overflow-y:hidden}.adm-popover-inner-content{padding:var(--content-padding)}.adm-popover-arrow{position:absolute;display:block;height:var(--arrow-size);width:var(--arrow-size);overflow:visible;background:transparent}.adm-popover-arrow-icon{display:block;height:var(--arrow-size);width:calc(var(--arrow-size) / 8 * 15);position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) rotate(var(--arrow-icon-rotate))}.adm-popover .adm-popover-arrow{color:var(--background)}.adm-popover-menu{--border-color: var(--adm-color-border)}.adm-popover-menu.adm-popover{--content-padding: 0}.adm-popover-menu-list{overflow:hidden;min-width:7.5rem}.adm-popover-menu-list-inner{margin-top:-.0625rem}.adm-popover-menu-list-scroll{padding-right:.125rem;overflow-y:scroll;-webkit-overflow-scrolling:auto}.adm-popover-menu-list-scroll::-webkit-scrollbar{-webkit-appearance:none;width:.25rem}.adm-popover-menu-list-scroll::-webkit-scrollbar-thumb{border-radius:.25rem;background-color:#ddd}.adm-popover-menu-item{display:flex;padding-left:1.25rem;justify-content:flex-start;align-items:center;position:relative}.adm-popover-menu-item-icon{flex:none;padding-right:.5rem;font-size:1.25rem}.adm-popover-menu-item-text{flex:auto;padding:.875rem 1.25rem .875rem 0;border-top:solid .0625rem var(--border-color)}.adm-popover-menu-item-disabled{cursor:not-allowed}.adm-popover-menu-item-disabled>*{opacity:.4}.adm-popover-menu-item:active:not(.adm-popover-menu-item-disabled){background-color:var(--border-color)}.adm-popover-menu-item:active:not(.adm-popover-menu-item-disabled):after{content:" ";display:block;position:absolute;width:100%;bottom:-.0625rem;left:0;border-bottom:solid .0625rem var(--border-color)}.adm-popover.adm-popover-dark.adm-popover-menu{--border-color: var(--adm-color-text);--background: rgba(0, 0, 0, .9)}.adm-grid{--gap: 0;--gap-horizontal: var(--gap);--gap-vertical: var(--gap);display:grid;grid-gap:.625rem;-webkit-column-gap:var(--gap-horizontal);column-gap:var(--gap-horizontal);row-gap:var(--gap-vertical);grid-template-columns:repeat(var(--columns),minmax(0,1fr));align-items:stretch}.adm-grid-item{grid-column-end:span var(--item-span)}.adm-image-viewer-content{width:100vw;height:100vh;touch-action:none;-webkit-user-select:none;user-select:none}.adm-image-viewer-footer{position:absolute;width:100%;bottom:0;z-index:1}.adm-image-viewer-slides{height:100%;position:relative;z-index:1;cursor:-webkit-grab;cursor:grab;touch-action:none}.adm-image-viewer-slides-inner{height:100%;white-space:nowrap}.adm-image-viewer-slides-inner>*{margin-right:1rem}.adm-image-viewer-slide{position:relative;width:100%;height:100%;display:inline-block}.adm-image-viewer-control{position:absolute;z-index:1;left:0;top:0;width:100%;height:100%;cursor:-webkit-grab;cursor:grab;touch-action:none}.adm-image-viewer-image-wrapper{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.adm-image-viewer-image-wrapper img{display:block;max-width:100%;max-height:100%}.adm-image-viewer-indicator{position:absolute;z-index:2;left:50%;top:.75rem;transform:translate(-50%);color:var(--adm-color-border);font-size:var(--adm-font-size-6)}.adm-space-item{flex:none}.adm-space{display:inline-flex;--gap: .5rem;--gap-vertical: var(--gap);--gap-horizontal: var(--gap)}.adm-space-vertical{flex-direction:column}.adm-space-vertical>.adm-space-item{margin-bottom:var(--gap-vertical)}.adm-space-vertical>.adm-space-item:last-child{margin-bottom:0}.adm-space-horizontal{flex-direction:row}.adm-space-horizontal:not(:empty){margin-right:calc(var(--gap-horizontal) * -1)}.adm-space-horizontal>.adm-space-item{margin-right:var(--gap-horizontal)}.adm-space-horizontal.adm-space-wrap{flex-wrap:wrap;margin-bottom:calc(var(--gap-vertical) * -1)}.adm-space-horizontal.adm-space-wrap>.adm-space-item{padding-bottom:var(--gap-vertical)}.adm-space.adm-space-block{display:flex}.adm-space-align-center{align-items:center}.adm-space-align-start{align-items:flex-start}.adm-space-align-end{align-items:flex-end}.adm-space-align-baseline{align-items:baseline}.adm-space-justify-center{justify-content:center}.adm-space-justify-start{justify-content:flex-start}.adm-space-justify-end{justify-content:flex-end}.adm-space-justify-between{justify-content:space-between}.adm-space-justify-around{justify-content:space-around}.adm-space-justify-evenly{justify-content:space-evenly}.adm-space-justify-stretch{justify-content:stretch}.adm-image-uploader{--cell-size: 5rem;--gap: .75rem;---gap: var(--gap);---gap-horizontal: var(--gap-horizontal, var(--gap));---gap-vertical: var(--gap-vertical, var(--gap))}.adm-image-uploader-grid,.adm-image-uploader-space{--gap: var(---gap);--gap-horizontal: var(---gap-horizontal);--gap-vertical: var(---gap-vertical)}.adm-image-uploader-cell{position:relative;width:var(--cell-size);height:var(--cell-size);border-radius:.25rem;overflow:hidden}.adm-image-uploader-cell-fail{border:red solid .0625rem;box-sizing:border-box}.adm-image-uploader-cell-delete{position:absolute;top:0;right:0;width:.875rem;height:.875rem;background-color:#000000b3;border-radius:0 0 0 .75rem;font-size:.5rem;color:var(--adm-color-white);cursor:pointer}.adm-image-uploader-cell-delete-icon{position:absolute;left:.25rem;top:.1875rem}.adm-image-uploader-cell-mask{position:absolute;inset:0;color:var(--adm-color-white);background-color:#323233e0}.adm-image-uploader-cell-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;box-sizing:border-box;padding-top:.5rem}.adm-image-uploader-cell-mask-message{display:inline-block;padding:.375rem .25rem;font-size:var(--adm-font-size-4)}.adm-image-uploader-cell-image{width:var(--cell-size);height:var(--cell-size)}.adm-image-uploader-upload-button-wrap{position:relative}.adm-image-uploader-upload-button-wrap .adm-image-uploader-upload-button{background-color:var(--adm-color-box);text-align:center;line-height:var(--cell-size);display:block}.adm-image-uploader-upload-button-wrap .adm-image-uploader-upload-button-icon{color:var(--adm-color-weak);font-size:2rem}.adm-image-uploader-upload-button-wrap .adm-image-uploader-input{cursor:pointer;position:absolute;opacity:0;left:0;top:0;width:100%;height:100%;border-radius:.25rem}.adm-image-uploader .adm-image-uploader-gap-measure{position:absolute;left:0;top:0;height:var(--gap-horizontal);width:0}.adm-index-bar{--color: var(--adm-color-text);overflow:hidden;height:100%;position:relative;background-color:var(--adm-color-background);--sticky-offset-top: 0}.adm-index-bar-body{overflow:scroll;height:100%;width:100%}.adm-index-bar-body::-webkit-scrollbar{display:none}.adm-index-bar-anchor-title{display:flex;flex-direction:column;justify-content:center;height:2.1875rem;padding:0 .75rem;color:var(--adm-color-weak);font-size:var(--adm-font-size-main);background-color:var(--adm-color-fill-content)}.adm-index-bar-sidebar{position:absolute;top:50%;right:0;transform:translateY(-50%);z-index:910;overflow:visible;color:var(--adm-color-weak);font-size:var(--adm-font-size-4);-webkit-user-select:none;user-select:none;touch-action:none}.adm-index-bar-sidebar-bubble{position:absolute;top:50%;right:3.75rem;width:2.9375rem;height:2.9375rem;color:var(--adm-color-text-light-solid);font-size:1.5625rem;line-height:2.9375rem;text-align:center;background:var(--adm-color-light);border-radius:50%;transform:translateY(-50%)}.adm-index-bar-sidebar-row{cursor:pointer;width:auto;text-align:right;position:relative;padding:0 .75rem}.adm-index-bar-sidebar-row>*{pointer-events:none}.adm-index-bar-sidebar-item{display:inline-flex;width:1rem;height:1rem;line-height:1rem;justify-content:center;align-items:center}.adm-index-bar-sidebar-item-active{color:var(--adm-color-text-light-solid);background-color:var(--adm-color-primary);border-radius:50%}.adm-index-bar-sidebar-interacting{width:100%}.adm-index-bar-sticky .adm-index-bar-anchor-title{position:-webkit-sticky;position:sticky;z-index:900;top:var(--sticky-offset-top);left:0}.adm-infinite-scroll{color:var(--adm-color-weak);padding:1.125rem;display:flex;justify-content:center;align-items:center;font-size:var(--adm-font-size-main)}.adm-infinite-scroll-failed-text{display:inline-block;margin-right:.5rem}.adm-input{--font-size: var(--adm-font-size-9);--color: var(--adm-color-text);--placeholder-color: var(--adm-color-light);--text-align: left;--background-color: transparent;display:flex;justify-content:flex-start;align-items:center;width:100%;max-width:100%;max-height:100%;min-height:1.5rem;background-color:var(--background-color)}.adm-input-disabled{opacity:.4;cursor:not-allowed}.adm-input-element{flex:auto;display:inline-block;box-sizing:border-box;width:100%;max-width:100%;max-height:100%;padding:0;margin:0;color:var(--color);font-size:var(--font-size);line-height:1.5;background:transparent;border:0;outline:none;-webkit-appearance:none;appearance:none;min-height:1.5em;text-align:var(--text-align)}.adm-input-element::-webkit-input-placeholder{color:var(--placeholder-color);font-family:inherit}.adm-input-element::placeholder{color:var(--placeholder-color);font-family:inherit}.adm-input-element:-webkit-autofill{background-color:transparent}.adm-input-element:read-only{cursor:default}.adm-input-element:invalid{box-shadow:none}.adm-input-element::-ms-clear{display:none}.adm-input-element::-ms-reveal{display:none}.adm-input-element::-webkit-search-cancel-button{display:none}.adm-input-element::-webkit-search-decoration{display:none}.adm-input-element:disabled{opacity:1}.adm-input-element[type=date],.adm-input-element[type=time],.adm-input-element[type=datetime-local]{min-height:1.5em}.adm-input-element[type=search]{-webkit-appearance:none}.adm-input-element[readonly]{pointer-events:none}.adm-input-clear{flex:none;margin-left:.5rem;color:var(--adm-color-light);padding:.25rem;cursor:pointer}.adm-input-clear:active{color:var(--adm-color-weak)}.adm-input-clear .antd-mobile-icon{display:block;font-size:var(--adm-font-size-7)}.adm-jumbo-tabs{--gap: .5rem;position:relative;min-width:0}.adm-jumbo-tabs-header{position:relative;border-bottom:solid .0625rem var(--adm-color-border)}.adm-jumbo-tabs-tab-list{display:flex;flex-wrap:nowrap;justify-content:flex-start;align-items:center;position:relative;overflow-x:scroll;padding:0 var(--gap);scrollbar-width:none}.adm-jumbo-tabs-tab-list::-webkit-scrollbar{display:none}.adm-jumbo-tabs-tab-wrapper{flex:auto;padding:0 calc(var(--gap) / 2);text-align:center}.adm-jumbo-tabs-tab{display:flex;flex-direction:column;align-items:center;position:relative;width:-webkit-min-content;width:min-content;margin:0 auto;padding:.75rem 0;cursor:pointer;font-size:var(--adm-font-size-9);white-space:nowrap}.adm-jumbo-tabs-tab-title{line-height:1.5rem;padding:0 .25rem}.adm-jumbo-tabs-tab-description{width:-webkit-min-content;width:min-content;padding:0 .5rem;border-radius:.625rem;color:var(--adm-color-weak);font-size:var(--adm-font-size-main);background-color:var(--adm-color-fill-content)}.adm-jumbo-tabs-tab-active{color:var(--adm-color-primary)}.adm-jumbo-tabs-tab-active .adm-jumbo-tabs-tab-description{color:var(--adm-color-text-light-solid);background-color:var(--adm-color-primary)}.adm-jumbo-tabs-tab-disabled{opacity:.5;cursor:not-allowed}.adm-jumbo-tabs-content{padding:.75rem}.adm-modal{--z-index: var(--adm-modal-z-index, 1000);---z-index: var(--z-index)}.adm-modal .adm-center-popup{--z-index: var(---z-index)}.adm-modal-body{width:100%;max-height:70vh;font-size:var(--adm-font-size-6);overflow:hidden;display:flex;flex-direction:column}.adm-modal-body>*{flex:none}.adm-modal-body>.adm-modal-content{flex:auto}.adm-modal-body:not(.adm-modal-with-image){padding-top:1.25rem}.adm-modal-image-container{margin-bottom:.75rem;max-height:40vh;overflow-y:scroll}.adm-modal-header{margin-bottom:.5rem;padding:0 .75rem}.adm-modal-title{margin-bottom:.5rem;padding:0 .75rem;font-weight:700;font-size:var(--adm-font-size-10);line-height:1.5625rem;text-align:center}.adm-modal-content{padding:0 .75rem .75rem;max-height:70vh;overflow-x:hidden;overflow-y:auto;font-size:var(--adm-font-size-7);line-height:1.4;color:var(--adm-color-text)}.adm-modal-footer{-webkit-user-select:none;user-select:none;padding:.5rem .75rem .75rem}.adm-modal-footer-empty{padding:0;height:.5rem}.adm-modal-footer.adm-space{--gap-vertical: 1.25rem}.adm-modal-footer .adm-modal-button{font-size:var(--adm-font-size-10);line-height:1.5625rem}.adm-modal-footer .adm-modal-button:not(.adm-modal-button-primary){padding-top:0;padding-bottom:0}.adm-modal-footer .adm-modal-button:not(.adm-modal-button-primary):before{display:none}.adm-modal-footer .adm-modal-button:not(.adm-modal-button-primary):active{opacity:.7}.adm-nav-bar{--height: 2.8125rem;--border-bottom: none;display:flex;align-items:center;height:var(--height);border-bottom:var(--border-bottom);padding:0 .75rem;white-space:nowrap}.adm-nav-bar-left,.adm-nav-bar-right{flex:1}.adm-nav-bar-title{flex:auto;text-align:center;overflow:hidden;text-overflow:ellipsis}.adm-nav-bar-back{display:flex;align-items:center;margin-right:1rem;padding:.375rem 0;cursor:pointer}.adm-nav-bar-back-arrow{font-size:1.5rem;margin-right:.25rem}.adm-nav-bar-left{font-size:var(--adm-font-size-7);display:flex;justify-content:flex-start;align-items:center}.adm-nav-bar-title{justify-content:center;white-space:nowrap;font-size:var(--adm-font-size-10);padding:0 .75rem}.adm-nav-bar-right{text-align:right}.adm-notice-bar{--background-color: var(--adm-color-weak);--border-color: var(--adm-color-weak);--text-color: var(--adm-color-text-light-solid);--font-size: var(--adm-font-size-7);--icon-font-size: var(--adm-font-size-10);--height: 2.5rem;--adm-notice-bar-border-radius: .25rem;--adm-notice-bar-border-width: .0625rem;height:var(--height);box-sizing:border-box;font-size:var(--font-size);padding:0 .75rem;display:flex;align-items:center;justify-content:space-between;border:solid var(--adm-notice-bar-border-width) var(--border-color);border-left-width:0;border-right-width:0;background-color:var(--background-color);color:var(--text-color)}.adm-notice-bar>span[role=img]{color:var(--text-color)}.adm-notice-bar.adm-notice-bar-alert{--background-color: #fff9ed;--border-color: #fff3e9;--text-color: var(--adm-color-orange)}.adm-notice-bar.adm-notice-bar-error{--background-color: var(--adm-color-danger);--border-color: #d9281e;--text-color: #fff}.adm-notice-bar.adm-notice-bar-info{--background-color: #d0e4ff;--border-color: #bcd8ff;--text-color: var(--adm-color-primary)}.adm-notice-bar.adm-notice-bar-success{--background-color: #d1fff0;--border-color: #a8f0d8;--text-color: var(--adm-color-success)}.adm-notice-bar .adm-notice-bar-left{flex-shrink:0;margin-right:.5rem;font-size:var(--icon-font-size)}.adm-notice-bar .adm-notice-bar-content{flex:1;overflow:hidden;position:relative;height:100%;display:flex;align-items:center}.adm-notice-bar .adm-notice-bar-content .adm-notice-bar-content-inner{width:auto;transition-timing-function:linear;white-space:nowrap}.adm-notice-bar-wrap.adm-notice-bar .adm-notice-bar-content .adm-notice-bar-content-inner{white-space:normal}.adm-notice-bar .adm-notice-bar-right{display:flex;align-items:center;flex-shrink:0;margin-left:.75rem}.adm-notice-bar-close{width:1.5rem;height:1.5rem;margin-right:-.1875rem;display:flex;align-items:center;justify-content:center;font-size:var(--adm-font-size-10)}.adm-notice-bar-wrap{height:auto;align-items:flex-start;padding-top:.5rem;padding-bottom:.5rem;line-height:1.375rem}.adm-notice-bar-neutral{border-radius:var(--adm-notice-bar-border-radius)}.adm-notice-bar-rounded{border-radius:62.5rem}.adm-notice-bar-bordered{border-left-width:var(--adm-notice-bar-border-width);border-right-width:var(--adm-notice-bar-border-width)}.adm-notice-bar-without-border{border-top-width:0;border-bottom-width:0}.adm-number-keyboard-main{display:flex;flex-wrap:wrap;flex:1}.adm-number-keyboard-main.adm-number-keyboard-main-confirmed-style .adm-number-keyboard-key-sign{background-color:var(--adm-color-background)}.adm-number-keyboard-popup.adm-popup{width:100%;-webkit-user-select:none;user-select:none;z-index:1050}.adm-number-keyboard-popup.adm-popup .adm-popup-body{background-color:var(--adm-color-box)}.adm-number-keyboard-wrapper{display:flex}.adm-number-keyboard-header{height:2.125rem;line-height:2.125rem;border-top:solid .0625rem var(--adm-color-border);display:flex;justify-content:center;align-items:center;padding:0 .75rem;color:var(--adm-color-weak);background-color:var(--adm-color-background)}.adm-number-keyboard-header-close-button{padding:0 .75rem;font-size:1rem}.adm-number-keyboard-header.adm-number-keyboard-header-with-title{justify-content:space-between}.adm-number-keyboard-header.adm-number-keyboard-header-with-title .adm-number-keyboard-header-close-button{padding-right:0}.adm-number-keyboard-footer{background:var(--adm-color-white)}.adm-number-keyboard-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.adm-number-keyboard-confirm{width:25%}.adm-number-keyboard-key{flex:1 33.33%;position:relative;display:flex;align-items:center;justify-content:center;height:3rem;font-size:1.375rem;box-sizing:border-box;border:solid .0625rem var(--adm-color-border);border-bottom:none;border-left:none}.adm-number-keyboard-key:nth-child(3n),.adm-number-keyboard-key:last-child{border-right:none}.adm-number-keyboard-key:before{position:absolute;top:50%;left:50%;width:100%;height:100%;background-color:var(--adm-color-text-dark-solid);border:inherit;border-color:var(--adm-color-text-dark-solid);border-radius:inherit;transform:translate(-50%,-50%);opacity:0;content:" ";box-sizing:content-box}.adm-number-keyboard-key.adm-number-keyboard-key-mid{flex-basis:66.67%}.adm-number-keyboard-key.adm-number-keyboard-key-sign:active:before{opacity:.1}.adm-number-keyboard-key.adm-number-keyboard-key-extra{border-left:solid .0625rem var(--adm-color-border);border-right:none}.adm-number-keyboard-key.adm-number-keyboard-key-extra,.adm-number-keyboard-key.adm-number-keyboard-key-number{background-color:var(--adm-color-background)}.adm-number-keyboard-key.adm-number-keyboard-key-extra:active:before,.adm-number-keyboard-key.adm-number-keyboard-key-number:active:before{opacity:.1}.adm-number-keyboard-key.adm-number-keyboard-key-ok{background-color:var(--adm-color-primary);color:var(--adm-color-white);height:9rem;font-size:1rem;border:none}.adm-page-indicator{display:flex;width:auto;--dot-color: var(--adm-color-light);--active-dot-color: var(--adm-color-primary);--dot-size: .1875rem;--active-dot-size: .8125rem;--dot-border-radius: .0625rem;--active-dot-border-radius: var(--dot-border-radius);--dot-spacing: .1875rem}.adm-page-indicator-dot{display:block;width:var(--dot-size);height:var(--dot-size);border-radius:var(--dot-border-radius);background:var(--dot-color)}.adm-page-indicator-dot:last-child{margin-right:0}.adm-page-indicator-dot-active{border-radius:var(--active-dot-border-radius);background:var(--active-dot-color)}.adm-page-indicator-color-white{--dot-color: rgba(255, 255, 255, .5);--active-dot-color: var(--adm-color-text-light-solid)}.adm-page-indicator-horizontal{flex-direction:row}.adm-page-indicator-horizontal .adm-page-indicator-dot{margin-right:var(--dot-spacing)}.adm-page-indicator-horizontal .adm-page-indicator-dot-active{width:var(--active-dot-size)}.adm-page-indicator-vertical{flex-direction:column}.adm-page-indicator-vertical .adm-page-indicator-dot{margin-bottom:var(--dot-spacing)}.adm-page-indicator-vertical .adm-page-indicator-dot-active{height:var(--active-dot-size)}.adm-passcode-input{position:relative;display:inline-block;--cell-size: 2.5rem;--cell-gap: .375rem;--dot-size: .625rem;--border-color: var(--adm-color-border);--border-radius: .5rem}.adm-passcode-input-cell-container{display:inline-flex;vertical-align:top}.adm-passcode-input-cell{flex:none;display:flex;align-items:center;justify-content:center;box-sizing:border-box;font-size:var(--adm-font-size-10);width:var(--cell-size);height:var(--cell-size);background:var(--adm-color-background)}.adm-passcode-input:not(.adm-passcode-input-seperated){border-radius:var(--border-radius);overflow:hidden;border:.0625rem solid var(--border-color)}.adm-passcode-input:not(.adm-passcode-input-seperated) .adm-passcode-input-cell:not(:last-child){border-right:.0625rem solid var(--border-color)}.adm-passcode-input:not(.adm-passcode-input-seperated).adm-passcode-input-focused{border-color:var(--adm-color-primary);box-shadow:0 0 .125rem 0 var(--adm-color-primary);outline:none}.adm-passcode-input:not(.adm-passcode-input-seperated).adm-passcode-input-error{border-color:var(--adm-color-danger);box-shadow:0 0 .125rem 0 var(--adm-color-danger);animation:.1s ease-in-out 0s 3 normal none running adm-shake-horizontal}.adm-passcode-input.adm-passcode-input-seperated .adm-passcode-input-cell{border-radius:var(--border-radius);border:.0625rem solid var(--border-color)}.adm-passcode-input.adm-passcode-input-seperated .adm-passcode-input-cell:not(:last-child){margin-right:var(--cell-gap)}.adm-passcode-input.adm-passcode-input-seperated .adm-passcode-input-cell-focused{border-color:var(--adm-color-primary);box-shadow:0 0 .125rem 0 var(--adm-color-primary)}.adm-passcode-input-seperated.adm-passcode-input-focused{outline:none}.adm-passcode-input.adm-passcode-input-seperated.adm-passcode-input-error{animation:.1s ease-in-out 0s 3 normal none running adm-shake-horizontal}.adm-passcode-input.adm-passcode-input-seperated.adm-passcode-input-error .adm-passcode-input-cell{border-color:var(--adm-color-danger);box-shadow:0 0 .125rem 0 var(--adm-color-danger)}.adm-passcode-input-cell-dot:before{content:"";width:var(--dot-size);height:var(--dot-size);border-radius:100%;background:var(--adm-color-text)}.adm-passcode-input-cell-caret:after{content:"";width:.125rem;height:1.1em;margin-left:.0625rem;background:var(--adm-color-primary);animation:1s linear infinite adm-caret-blink}.adm-passcode-input>.adm-passcode-input-native-input{position:absolute;left:-200vw;top:0;display:block;width:3.125rem;height:1.25rem;opacity:.5}@keyframes adm-shake-horizontal{0%{transform:translate(0)}10%{transform:translate(-.25rem)}20%{transform:translate(.3125rem)}30%{transform:translate(-.0625rem)}40%{transform:translate(.5rem)}50%{transform:translate(0)}60%{transform:translate(-.5rem)}70%{transform:translate(.0625rem)}80%{transform:translate(-.3125rem)}90%{transform:translate(.25rem)}to{transform:translate(0)}}.adm-progress-bar{--track-width: var(--adm-progress-bar-track-width, 8px);--track-color: var(--adm-progress-bar-track-color, var(--adm-color-border));--fill-color: var(--adm-progress-bar-fill-color, var(--adm-color-primary));--text-width: var(--adm-progress-bar-text-width, 40px);display:flex;align-items:center}.adm-progress-bar-trail{flex:auto;background:var(--track-color);overflow:hidden;height:var(--track-width)}.adm-progress-bar-fill{transition:width .3s;background:var(--fill-color);height:var(--track-width)}.adm-progress-bar-text{flex:none;width:calc(var(--text-width) + .5rem);padding-left:.5rem;color:var(--adm-color-weak)}.adm-progress-bar-rounded .adm-progress-bar-trail,.adm-progress-bar-rounded .adm-progress-bar-fill{border-radius:var(--track-width)}.adm-progress-circle{--track-width: var(--adm-progress-circle-track-width, 3px);--size: var(--adm-progress-circle-size, 50px);--track-color: var(--adm-progress-circle-track-color, var(--adm-color-border));--fill-color: var(--adm-progress-circle-fill-color, var(--adm-color-primary));--percent: 0;--pi: 3.14159265;--radius: calc(var(--size) / 2 - var(--track-width) / 2);--circumference: calc(var(--radius) * var(--pi) * 2);display:inline-block;width:var(--size);height:var(--size)}.adm-progress-circle-svg{width:100%;height:100%}.adm-progress-circle-svg>.adm-progress-circle-track,.adm-progress-circle-svg .adm-progress-circle-fill{stroke-width:var(--track-width);r:var(--radius);cx:calc(var(--size) / 2);cy:calc(var(--size) / 2);transform:rotate(-90deg);transform-origin:50% 50%}.adm-progress-circle-svg>.adm-progress-circle-track{stroke:var(--track-color)}.adm-progress-circle-svg>.adm-progress-circle-fill{transition:stroke-dashoffset .35s;stroke:var(--fill-color);stroke-dasharray:var(--circumference);stroke-dashoffset:calc(var(--circumference) * (1 - var(--percent) / 100));stroke-linecap:round}.adm-progress-circle-content{position:relative;margin:auto;width:100%;height:100%}.adm-progress-circle-info{position:absolute;width:100%;top:50%;left:50%;text-align:center;transform:translate(-50%,-50%)}.adm-pull-to-refresh-head{overflow:hidden;position:relative}.adm-pull-to-refresh-head-content{position:absolute;bottom:0;left:0;width:100%;color:var(--adm-color-weak);display:flex;justify-content:center;align-items:center}.adm-radio{--icon-size: 1.375rem;--font-size: var(--adm-font-size-9);--gap: .5rem;display:inline-flex;vertical-align:text-bottom;justify-content:flex-start;align-items:center;cursor:pointer}.adm-radio input[type=radio]{display:none}.adm-radio .adm-radio-icon{flex:none;border:.0625rem solid var(--adm-color-light);border-radius:var(--icon-size);box-sizing:border-box;width:var(--icon-size);height:var(--icon-size);color:var(--adm-color-text-light-solid)}.adm-radio .adm-radio-icon>svg{display:block;width:100%;height:100%}.adm-radio.adm-radio-block{display:flex}.adm-radio.adm-radio-checked .adm-radio-icon{border-color:var(--adm-color-primary);background-color:var(--adm-color-primary)}.adm-radio.adm-radio-disabled{cursor:not-allowed}.adm-radio.adm-radio-disabled .adm-radio-content{opacity:.4}.adm-radio.adm-radio-disabled .adm-radio-icon{color:var(--adm-color-light);border-color:var(--adm-color-light);background-color:var(--adm-color-fill-content)}.adm-radio .adm-radio-custom-icon{font-size:var(--icon-size)}.adm-radio-content{flex:0 1 auto;font-size:var(--font-size);padding-left:var(--gap)}.adm-rate{--star-size: 1.5rem;--active-color: var(--adm-color-yellow);--inactive-color: var(--adm-color-border);--inactive-color-half: var(--adm-color-border);display:inline-flex;touch-action:pan-y;-webkit-user-select:none;user-select:none}.adm-rate-box{position:relative}.adm-rate-star{padding:.125em;line-height:var(--star-size);font-size:var(--star-size);color:var(--inactive-color);text-align:center;overflow:hidden;cursor:pointer;box-sizing:border-box;transition:all .3s}.adm-rate-star-half{padding-right:0;width:50%;position:absolute;left:0;top:0}.adm-rate-star-active{color:var(--active-color)}.adm-rate-star-readonly{cursor:unset}.adm-rate.adm-rate-half .adm-rate-star-half:not(.adm-rate-star-active){color:var(--inactive-color-half)}.adm-result{padding:2rem .75rem;background-color:var(--adm-color-background)}.adm-result-icon{box-sizing:border-box;width:4rem;height:4rem;margin:0 auto 1.25rem;padding:.375rem}.adm-result-icon .antd-mobile-icon{font-size:3.25rem}.adm-result-title{color:var(--adm-color-text);font-size:var(--adm-font-size-10);line-height:1.4;text-align:center}.adm-result-description{margin-top:.5rem;color:var(--adm-color-weak);font-size:var(--adm-font-size-main);line-height:1.4;text-align:center}.adm-result-success .adm-result-icon .antd-mobile-icon{color:var(--adm-color-primary)}.adm-result-error .adm-result-icon .antd-mobile-icon{color:var(--adm-color-danger)}.adm-result-info .adm-result-icon .antd-mobile-icon{color:var(--adm-color-primary)}.adm-result-waiting .adm-result-icon .antd-mobile-icon{color:var(--adm-color-success)}.adm-result-warning .adm-result-icon .antd-mobile-icon{color:var(--adm-color-warning)}.adm-result-page{--background-color: var(--adm-color-primary);position:relative;background-color:var(--adm-color-box);min-height:100vh;width:100%}.adm-result-page-header{display:flex;align-items:center;flex-direction:column;background-color:transparent;position:relative;padding:1.25rem 1.25rem 6.25rem;z-index:1;overflow:hidden}.adm-result-page-icon{color:var(--adm-color-text-light-solid);box-sizing:border-box;padding:.125rem;margin-bottom:.5rem}.adm-result-page-icon .antd-mobile-icon{font-size:2rem}.adm-result-page-title{font-size:var(--adm-font-size-10);color:var(--adm-color-text-light-solid);line-height:1.4;text-align:center}.adm-result-page-description{margin-top:.5rem;margin-bottom:1.5rem;font-size:var(--adm-font-size-6);color:#fff9;line-height:1.4;text-align:center}.adm-result-page-details{width:100%}.adm-result-page-detail{width:100%;display:flex;flex-direction:row;justify-content:space-between;margin-bottom:.3125rem;color:var(--adm-color-text-light-solid);font-size:var(--adm-font-size-6)}.adm-result-page-detail-bold{font-weight:600}.adm-result-page-collapse{opacity:.6;width:.625rem;height:.625rem;margin:auto;margin-bottom:.3125rem;border-top:.125rem solid var(--adm-color-text-light-solid);border-right:.125rem solid var(--adm-color-text-light-solid);transform:rotate(135deg)}.adm-result-page-collapse-active{transform:rotate(-45deg)}.adm-result-page-bgWrapper{position:relative;align-self:flex-start;top:3.375rem}.adm-result-page-bg{--width: 440vw;position:absolute;height:var(--width);width:var(--width);left:calc((var(--width) - 100vw) * -1 / 2 - 1.25rem);top:calc(var(--width) * -1 + 1vw);border-radius:50%;background-color:var(--background-color);z-index:-1}.adm-result-page-content{position:relative;padding:.75rem;top:-6.5rem;z-index:2}.adm-result-page-footer{position:fixed;bottom:0;width:100%;padding:.75rem .75rem 1.5rem;display:flex;justify-content:center;background-color:var(--adm-color-box);z-index:3;box-sizing:border-box}.adm-result-page-footer-btn{flex:1;max-width:calc((100vw - 2.25rem)/2)}.adm-result-page-footer-space{width:.75rem}.adm-result-page-card{border-radius:.5rem;background-color:var(--adm-color-background)}.adm-search-bar{--height: 2rem;--padding-left: .5rem;--background: var(--adm-color-fill-content);--border-radius: .375rem;--placeholder-color: var(--adm-color-weak);---placeholder-color: var(--placeholder-color);display:flex;justify-content:center;align-items:center;height:var(--height)}.adm-search-bar .adm-search-bar-input-box{flex:auto;background:var(--background);border-radius:var(--border-radius);border:solid .0625rem transparent;display:flex;justify-content:center;align-items:center;padding-left:var(--padding-left)}.adm-search-bar .adm-search-bar-input-box .adm-search-bar-input-box-icon{flex:none;color:var(--adm-color-light);font-size:var(--adm-font-size-8)}.adm-search-bar .adm-search-bar-input-box .adm-search-bar-input{flex:auto;padding:.25rem .5rem .25rem .25rem;height:calc(var(--height) - .125rem);box-sizing:border-box}.adm-search-bar .adm-search-bar-input-box .adm-search-bar-input.adm-input{--placeholder-color: var(---placeholder-color);--font-size: var(--adm-font-size-7)}.adm-search-bar .adm-search-bar-input-box .adm-search-bar-input .adm-input-element{line-height:1.1875rem}.adm-search-bar .adm-search-bar-input-box .adm-search-bar-input.adm-search-bar-input-without-icon{padding-left:.5rem}.adm-search-bar .adm-search-bar-suffix{flex:none;margin-left:.25rem}.adm-search-bar .adm-search-bar-cancel-button.adm-button{padding:.1875rem .75rem}.adm-search-bar-active .adm-input.adm-input.adm-input{--placeholder-color: var(--adm-color-light)}.adm-search-bar-active .adm-search-bar-input-box{border-color:var(--adm-color-primary);background:var(--adm-color-background)}.adm-segmented{--segmented-background: var(--adm-color-fill-content);--segmented-item-color: var(--adm-color-text-secondary);--segmented-item-selected-background: var(--adm-color-background);--segmented-item-selected-color: var(--adm-color-text);--segmented-item-disabled-color: var(--adm-color-weak);--transition-time-function: cubic-bezier(.645, .045, .355, 1);display:inline-block;padding:.125rem;color:var(--segmented-item-color);background-color:var(--segmented-background);border-radius:.125rem;transition:all .3s var(--transition-time-function)}.adm-segmented-group{position:relative;display:flex;align-items:stretch;justify-items:flex-start;width:100%}.adm-segmented.adm-segmented-block{display:flex}.adm-segmented.adm-segmented-block .adm-segmented-item{flex:1;min-width:0}.adm-segmented-item{position:relative;text-align:center;cursor:pointer;transition:color .3s var(--transition-time-function)}.adm-segmented-item-selected{background-color:var(--segmented-item-selected-background);border-radius:.125rem;box-shadow:0 .125rem .5rem -.125rem #0000000d,0 .0625rem .25rem -.0625rem #00000012,0 0 .0625rem #00000014;color:var(--segmented-item-selected-color)}.adm-segmented-item-label{min-height:.625rem;padding:0 .6875rem;line-height:1.75rem;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;word-break:keep-all}.adm-segmented-item-icon+*{margin-left:.375rem}.adm-segmented-item-input{position:absolute;top:0;left:0;width:0;height:0;opacity:0;pointer-events:none}.adm-segmented-item-disabled{color:var(--segmented-item-disabled-color);cursor:not-allowed}.adm-segmented-thumb{background-color:var(--segmented-item-selected-background);border-radius:.125rem;box-shadow:0 .125rem .5rem -.125rem #0000000d,0 .0625rem .25rem -.0625rem #00000012,0 0 .0625rem #00000014;position:absolute;top:0;left:0;width:0;height:100%;padding:.25rem 0}.adm-segmented-thumb-motion-appear-active{transition:transform .3s var(--transition-time-function),width .3s var(--transition-time-function);will-change:transform,width}.segmented-disabled-item{color:var(--segmented-item-disabled-color);cursor:not-allowed}.segmented-item-selected{background-color:var(--segmented-item-selected-background);border-radius:.125rem;box-shadow:0 .125rem .5rem -.125rem #0000000d,0 .0625rem .25rem -.0625rem #00000012,0 0 .0625rem #00000014}.segmented-text-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;word-break:keep-all}.adm-selector{--color: var(--adm-color-fill-content);--checked-color: var(--adm-color-wathet);--text-color: var(--adm-color-text);--checked-text-color: var(--adm-color-primary);--border: none;--checked-border: none;--border-radius: .125rem;--padding: .5rem 1rem;--gap: .5rem;---gap: var(--gap);---gap-horizontal: var(--gap-horizontal, var(--gap));---gap-vertical: var(--gap-vertical, var(--gap));overflow:hidden;font-size:var(--adm-font-size-7);line-height:1.4}.adm-selector .adm-space.adm-space{--gap: .75rem}.adm-selector .adm-grid{--gap: var(---gap);--gap-horizontal: var(---gap-horizontal);--gap-vertical: var(---gap-vertical)}.adm-selector-item{padding:var(--padding);position:relative;background-color:var(--color);border:var(--border);border-radius:var(--border-radius);color:var(--text-color);opacity:1;cursor:pointer;display:inline-block;text-align:center;overflow:hidden;vertical-align:top}.adm-selector-item-description{font-size:var(--adm-font-size-main);color:var(--adm-color-weak)}.adm-selector-item-active,.adm-selector-item-multiple-active{color:var(--checked-text-color);background-color:var(--checked-color);border:var(--checked-border)}.adm-selector-item .adm-selector-check-mark-wrapper{position:absolute;right:0;bottom:0;width:0;height:0;border-top:solid .5rem transparent;border-bottom:solid .5rem var(--adm-color-primary);border-left:solid .625rem transparent;border-right:solid .625rem var(--adm-color-primary)}.adm-selector-item .adm-selector-check-mark-wrapper>svg{position:absolute;left:0;top:0;height:.375rem;width:.5rem}.adm-selector-item-disabled{cursor:not-allowed;opacity:.4}.adm-side-bar{--height: 100%;--width: 6.5625rem;--item-border-radius: .5rem;--background-color: var(--adm-color-fill-content);width:var(--width);height:var(--height);box-sizing:border-box;font-size:var(--adm-font-size-main);overflow-y:auto;transform:translateZ(0);-webkit-transform:translateZ(0);background-color:var(--background-color);display:flex;flex-direction:column}.adm-side-bar-items{flex:none;overflow:hidden}.adm-side-bar-extra-space{flex:auto;overflow:hidden;position:relative}.adm-side-bar-item{display:flex;align-items:center;box-sizing:border-box;padding:1rem .75rem;position:relative;cursor:pointer;background-color:var(--background-color);overflow:visible}.adm-side-bar-item-highlight{position:absolute;height:100%;width:.125rem;left:-.75rem;top:0;background:var(--adm-color-primary);border-radius:.125rem}.adm-side-bar-item-active{color:var(--adm-color-primary);background-color:var(--adm-color-background);position:relative}.adm-side-bar-item-corner{width:var(--item-border-radius);height:var(--item-border-radius);position:absolute;z-index:100;right:0;-webkit-user-select:none;user-select:none;pointer-events:none}.adm-side-bar-item-corner-top{top:0;transform:rotate(-90deg)}.adm-side-bar-item-corner-bottom{bottom:0}.adm-side-bar-item-disabled{cursor:not-allowed}.adm-side-bar-item-disabled .adm-side-bar-item-title{opacity:.4}.adm-side-bar-badge.adm-badge{--right: -.25rem}.adm-slider{--fill-color: var(--adm-color-primary);padding:.3125rem .875rem;list-style:none;-webkit-user-select:none;user-select:none}.adm-slider-track-container{padding:.5rem 0}.adm-slider-track{position:relative;width:100%;height:.1875rem;background-color:var(--adm-color-fill-content);border-radius:.1875rem}.adm-slider-fill{position:absolute;z-index:1;height:.1875rem;border-radius:.1875rem;background-color:var(--fill-color)}.adm-slider-ticks{position:absolute;width:100%;height:.1875rem;background:transparent}.adm-slider-tick{position:absolute;top:-.125rem;width:.4375rem;height:.4375rem;margin-left:-.1875rem;background-color:var(--adm-color-fill-content);border-radius:50%}.adm-slider-tick-active{background-color:var(--fill-color)}.adm-slider-thumb{width:1.75rem;height:1.75rem;margin:.125rem;border-radius:50%;text-align:center;line-height:1.75rem;background:var(--adm-color-text-light-solid);box-shadow:0 .125rem .3125rem #0000001f;color:var(--fill-color)}.adm-slider-thumb:focus{outline:none}.adm-slider-thumb-icon{width:.75rem;height:.75rem;margin:.5rem;-webkit-user-select:none;user-select:none}.adm-slider-thumb-container{cursor:-webkit-grab;cursor:grab;touch-action:none;position:absolute;z-index:2;width:2rem;height:2rem;border-radius:50%;top:50%;transform:translate(-50%,-50%)}.adm-slider-mark{position:relative;width:100%;overflow:visible;font-size:var(--adm-font-size-3);height:.6875rem;margin-top:.625rem}.adm-slider-mark-text{position:absolute;display:inline-block;line-height:1;color:var(--adm-color-text);text-align:center;word-break:keep-all;-webkit-user-select:none;user-select:none;transform:translate(-50%)}.adm-slider-disabled .adm-slider-mark,.adm-slider-disabled .adm-slider-thumb-icon{opacity:.4}.adm-slider-disabled .adm-slider-tick-active:after,.adm-slider-disabled .adm-slider-fill:after{content:"";position:absolute;inset:0;border-radius:inherit;background-color:#fff9}.adm-slider-disabled .adm-slider-thumb{cursor:not-allowed;box-shadow:0 .125rem .3125rem #0000000f}.adm-slider-disabled .adm-slider-mark-text,.adm-slider-disabled .adm-slider-tick{cursor:not-allowed;box-shadow:none}.adm-stepper{--height: 1.75rem;--input-width: 2.75rem;--input-font-size: var(--adm-font-size-main);--input-font-color: var(--adm-color-text);--input-background-color: var(--adm-color-fill-content);--border-radius: .125rem;--border: none;--border-inner: solid .125rem transparent;--active-border: var(--border);--button-font-size: var(--adm-font-size-7);--button-text-color: var(--adm-color-primary);--button-background-color: var(--adm-color-fill-content);--button-width: var(--height);display:flex;align-items:center;box-sizing:border-box;position:relative;overflow:hidden;width:calc(var(--input-width) + 2 * var(--button-width));border:var(--border);border-radius:var(--border-radius)}.adm-stepper-active{border:var(--active-border)}.adm-stepper-middle{flex:1;border-left:var(--border-inner);border-right:var(--border-inner)}.adm-stepper .adm-stepper-input{height:var(--height);--background-color: var(--input-background-color);--font-size: var(--input-font-size);--color: var(--input-font-color);--text-align: center}.adm-stepper-minus,.adm-stepper-plus{width:var(--button-width);height:var(--height);padding:0;color:var(--button-text-color);background-color:var(--button-background-color);font-size:var(--button-font-size);--border-width: 0}.adm-stepper-minus:disabled,.adm-stepper-plus:disabled{color:var(--adm-color-weak)}.adm-stepper-minus svg,.adm-stepper-plus svg{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.adm-stepper-minus,.adm-stepper-plus{border-radius:0}.adm-step{--line-to-next-color: var(--adm-color-border);--icon-color: var(--adm-color-border);position:relative;z-index:0}.adm-step .adm-step-indicator{position:relative}.adm-step .adm-step-indicator:after{content:"";position:absolute;z-index:0;background-color:var(--line-to-next-color)}.adm-step .adm-step-indicator .adm-step-icon-container{position:absolute;z-index:1;color:var(--icon-color)}.adm-step .adm-step-indicator .adm-step-icon-container>.antd-mobile-icon{display:block}.adm-step:last-child .adm-step-indicator:after{display:none}.adm-step-status-finish{--line-to-next-color: var(--adm-color-primary)}.adm-step-status-wait{--icon-color: var(--adm-color-border)}.adm-step-status-wait .adm-step-title{color:var(--adm-color-weak)}.adm-step-status-process{--icon-color: var(--adm-color-primary)}.adm-step-status-process .adm-step-title{color:var(--adm-color-primary)}.adm-step-status-finish{--icon-color: var(--adm-color-primary)}.adm-step-status-error{--icon-color: var(--adm-color-danger)}.adm-step-status-error .adm-step-title{color:var(--adm-color-danger)}.adm-steps{--title-font-size: var(--adm-font-size-main);--description-font-size: var(--adm-font-size-4);--indicator-margin-right: 0;--icon-size: 1.125rem;width:100%;box-sizing:border-box}.adm-steps-horizontal{display:flex;justify-content:space-around;padding:.5rem 0}.adm-steps-horizontal .adm-step{flex:1}.adm-steps-horizontal .adm-step .adm-step-indicator{width:100%;height:1.5rem}.adm-steps-horizontal .adm-step .adm-step-indicator:after{left:50%;top:50%;height:.0625rem;transform:translateY(-50%);width:100%}.adm-steps-horizontal .adm-step .adm-step-indicator .adm-step-icon-container{left:50%;top:50%;transform:translate(-50%,-50%)}.adm-steps-horizontal .adm-step-content{text-align:center;font-size:var(--description-font-size);padding:.125rem .5rem 0}.adm-steps-horizontal .adm-step-content .adm-step-title{font-size:var(--title-font-size)}.adm-steps-horizontal .adm-step-content .adm-step-description{margin-top:.25rem;color:var(--adm-color-weak)}.adm-steps-vertical{padding:.5rem 1rem}.adm-steps-vertical .adm-step{display:flex;align-items:stretch}.adm-steps-vertical .adm-step .adm-step-indicator{flex:none;width:1.5rem;margin-right:var(--indicator-margin-right)}.adm-steps-vertical .adm-step .adm-step-indicator:after{left:50%;top:calc(var(--title-font-size) * 1.5 / 2);width:.0625rem;transform:translate(-50%);height:100%}.adm-steps-vertical .adm-step .adm-step-indicator .adm-step-icon-container{top:calc(var(--title-font-size) * 1.5 / 2);left:50%;transform:translate(-50%,-50%)}.adm-steps-vertical .adm-step:last-child .adm-step-content{padding-bottom:0}.adm-steps-vertical .adm-step .adm-step-content{flex:auto;padding-bottom:1.5rem}.adm-steps-vertical .adm-step .adm-step-content .adm-step-title{font-size:var(--title-font-size);line-height:1.5}.adm-steps-vertical .adm-step .adm-step-content .adm-step-description{padding-top:.25rem;font-size:var(--description-font-size);color:var(--adm-color-weak)}.adm-step-icon-container{font-size:var(--icon-size)}.adm-step-icon-dot{display:block;width:.5rem;height:.5rem;background:currentColor;border-radius:.25rem}.adm-swipe-action{--background: var(--adm-color-background);background:var(--background);cursor:-webkit-grab;cursor:grab;overflow:hidden;touch-action:pan-y}.adm-swipe-action-track{position:relative;overflow:visible}.adm-swipe-action-actions{position:absolute;display:flex;justify-content:center;align-items:stretch;width:auto;white-space:nowrap}.adm-swipe-action-actions-right{left:100%;top:0;height:100%}.adm-swipe-action-actions-left{right:100%;top:0;height:100%}.adm-swipe-action-action-button.adm-button{--border-radius: 0;--border-width: 0;--text-color: var(--adm-color-text-light-solid);padding-left:1.25rem;padding-right:1.25rem}.adm-swiper{--height: auto;--width: 100%;--border-radius: 0;--track-padding: 0;--slide-size: 100%;--track-offset: 0%;display:block;width:var(--width);height:var(--height);position:relative;border-radius:var(--border-radius);z-index:0;overflow:hidden}.adm-swiper-track{width:100%;height:100%;white-space:nowrap;padding:var(--track-padding)}.adm-swiper-track-allow-touch-move{cursor:-webkit-grab;cursor:grab}.adm-swiper-track-inner{width:100%;height:100%;overflow:visible;position:relative;display:flex;flex-wrap:nowrap}.adm-swiper-slide,.adm-swiper-slide-placeholder{width:100%;height:100%;display:block;position:relative;white-space:unset;flex:none}.adm-swiper-item{display:block;width:100%;height:100%;white-space:normal}.adm-swiper-horizontal .adm-swiper-track-allow-touch-move{touch-action:pan-y}.adm-swiper-horizontal .adm-swiper-indicator{position:absolute;bottom:.375rem;left:50%;transform:translate(-50%)}.adm-swiper-horizontal .adm-swiper-track{transform:translate(var(--track-offset))}.adm-swiper-horizontal .adm-swiper-track-inner{flex-direction:row;width:var(--slide-size)}.adm-swiper-vertical .adm-swiper-track-allow-touch-move{touch-action:pan-x}.adm-swiper-vertical .adm-swiper-indicator{position:absolute;right:.375rem;top:50%;transform:translateY(-50%)}.adm-swiper-vertical .adm-swiper-track{transform:translateY(var(--track-offset))}.adm-swiper-vertical .adm-swiper-track-inner{flex-direction:column;height:var(--slide-size)}@keyframes loading-rotate{to{transform:rotate(1turn)}}.adm-switch{--checked-color: var(--adm-color-primary);--height: 1.9375rem;--width: 3.1875rem;--border-width: .125rem;display:inline-block;vertical-align:middle;box-sizing:border-box;position:relative;align-self:center;cursor:pointer}.adm-switch input{display:none}.adm-switch-checkbox{min-width:var(--width);height:var(--height);box-sizing:border-box;border-radius:1.9375rem;background:var(--adm-color-border);z-index:0;overflow:hidden;line-height:var(--height)}.adm-switch-checkbox:before{content:" ";position:absolute;left:var(--border-width);top:var(--border-width);width:calc(100% - 2 * var(--border-width));height:calc(var(--height) - 2 * var(--border-width));border-radius:calc(var(--height) - 2 * var(--border-width));box-sizing:border-box;background:var(--adm-color-background);z-index:1;transition:all .2s;transform:scale(1)}.adm-switch-handle{display:flex;justify-content:center;align-items:center;width:calc(var(--height) - 2 * var(--border-width));height:calc(var(--height) - 2 * var(--border-width));border-radius:calc(var(--height) - 2 * var(--border-width));background:var(--adm-color-text-light-solid);position:absolute;z-index:2;top:var(--border-width);left:var(--border-width);transition:all .2s;box-shadow:0 0 .125rem #0003,0 .125rem .71875rem #00000014,-.0625rem .125rem .125rem #0000001a}.adm-switch-inner{position:relative;z-index:1;display:flex;justify-content:center;align-items:center;margin:0 .5rem 0 calc(var(--height) - var(--border-width) + .3125rem);height:100%;color:var(--adm-color-weak);transition:margin .2s;font-size:var(--adm-font-size-7)}.adm-switch.adm-switch-checked .adm-switch-checkbox{background:var(--checked-color)}.adm-switch.adm-switch-checked .adm-switch-checkbox:before{transform:scale(0)}.adm-switch.adm-switch-checked .adm-switch-handle{left:calc(100% - (var(--height) - var(--border-width)))}.adm-switch.adm-switch-checked .adm-switch-inner{margin:0 calc(var(--height) - var(--border-width) + .3125rem) 0 .5rem;color:var(--adm-color-text-light-solid)}.adm-switch.adm-switch-disabled{cursor:not-allowed;opacity:.4}.adm-switch-spin-icon{width:.875rem;height:.875rem;animation:loading-rotate 1s linear infinite}.adm-tab-bar-wrap{display:flex;flex-wrap:nowrap;justify-content:flex-start;align-items:stretch;overflow:hidden;min-height:3rem}.adm-tab-bar-item{flex:1;color:var(--adm-color-text-secondary);white-space:nowrap;padding:.25rem .5rem;width:-webkit-min-content;width:min-content;position:relative;cursor:pointer;display:flex;align-items:center;justify-content:center;flex-direction:column}.adm-tab-bar-item-icon{font-size:1.5rem;height:1.5rem;line-height:1}.adm-tab-bar-item-title{font-size:var(--adm-font-size-2);line-height:.9375rem}.adm-tab-bar-item-title-with-icon{margin-top:.125rem}.adm-tab-bar-item-active{color:var(--adm-color-primary)}.adm-tab-bar-icon-badge{--top: .375rem}.adm-tab-bar-title-badge{--right: -.125rem;--top: -.125rem}.adm-tag{--border-radius: var(--adm-tag-border-radius, 2px);padding:.125rem .25rem;font-size:var(--adm-font-size-3);line-height:1;font-weight:400;background:var(--background-color);color:var(--text-color);display:inline-block;white-space:nowrap;border-radius:var(--border-radius);border:.0625rem solid var(--border-color);box-sizing:border-box}.adm-tag-round{border-radius:6.25rem}.adm-text-area{--font-size: var(--adm-font-size-9);--color: var(--adm-color-text);--placeholder-color: var(--adm-color-light);--disabled-color: var(--adm-color-weak);--text-align: left;--count-text-align: right;position:relative;width:100%;max-width:100%;max-height:100%}.adm-text-area-element{font-family:var(--adm-font-family);resize:none;flex:auto;display:block;box-sizing:border-box;width:100%;max-width:100%;max-height:100%;padding:0;margin:0;color:var(--color);font-size:var(--font-size);line-height:1.5;background:transparent;border:0;outline:none;-webkit-appearance:none;appearance:none;min-height:1.5em;text-align:var(--text-align)}.adm-text-area-element::-webkit-input-placeholder{color:var(--placeholder-color);font-family:inherit}.adm-text-area-element::placeholder{color:var(--placeholder-color);font-family:inherit}.adm-text-area-element:-webkit-autofill{background-color:transparent}.adm-text-area-element:disabled{color:var(--disabled-color);cursor:not-allowed;opacity:1;-webkit-text-fill-color:var(--disabled-color)}.adm-text-area-element:read-only{cursor:default}.adm-text-area-element:invalid{box-shadow:none}.adm-text-area-element::-ms-clear{display:none}.adm-text-area-element-hidden{visibility:hidden;position:absolute;top:0;left:0;z-index:-1000}.adm-text-area-count{text-align:var(--count-text-align);color:var(--adm-color-weak);font-size:var(--adm-font-size-9);padding-top:.5rem}.adm-toast-mask .adm-toast-wrap{position:fixed;top:0;left:0;width:100%;height:100%;text-align:center}.adm-toast-mask .adm-toast-main{display:inline-block;position:relative;top:50%;transform:translateY(-50%);width:auto;max-width:12.75rem;max-height:70%;overflow:auto;color:#fff;word-break:break-all;background-color:#000000b3;border-radius:.5rem;pointer-events:all;font-size:var(--adm-font-size-7);line-height:1.5;box-sizing:border-box;text-align:initial}.adm-toast-mask .adm-toast-main-text{padding:.75rem;min-width:0}.adm-toast-mask .adm-toast-main-icon{padding:2.1875rem .75rem;min-width:9.375rem}.adm-toast-mask .adm-toast-main-icon .adm-toast-icon{text-align:center;margin-bottom:.5rem;font-size:2.25rem;line-height:1}.adm-toast-loading{--size: 3rem;margin:0 auto .5rem}.adm-tree-select,.adm-tree-select-multiple{display:flex;height:100%;font-size:var(--adm-font-size-main);background-color:var(--adm-color-white)}.adm-tree-select-column,.adm-tree-select-multiple-column{overflow-y:auto;transform:translateZ(0);-webkit-transform:translateZ(0)}.adm-tree-select-column:first-child,.adm-tree-select-multiple-column:first-child{background-color:var(--adm-color-box)}.adm-tree-select-column:nth-child(2),.adm-tree-select-multiple-column:nth-child(2){background-color:var(--adm-color-box)}.adm-tree-select-item,.adm-tree-select-multiple-item{display:flex;align-items:center;min-height:3.125rem;box-sizing:border-box;padding:.375rem .75rem;position:relative}.adm-tree-select-item-active,.adm-tree-select-multiple-item-expand{color:var(--adm-color-primary);font-weight:700;background-color:#fff}.adm-tree-select-multiple-item-checkbox{margin-right:.5rem}.adm-tree-select-multiple-dot{position:absolute;top:50%;margin-top:-.1875rem;right:.5rem;width:.375rem;height:.375rem;background:var(--adm-color-primary);border-radius:.1875rem}.adm-virtual-input{--font-size: var(--adm-font-size-9);--color: var(--adm-color-text);--placeholder-color: var(--adm-color-light);--disabled-color: var(--adm-color-weak);--text-align: left;--caret-width: var(--adm-virtual-input-caret-width, 2px);--caret-color: var(--adm-virtual-input-caret-color, var(--adm-color-primary));display:flex;justify-content:flex-start;align-items:center;position:relative;text-align:var(--text-align);font-size:var(--font-size);line-height:1.5;white-space:nowrap;color:var(--color)}.adm-virtual-input>*{vertical-align:top}.adm-virtual-input-content{flex:auto;display:inline-block;position:relative;z-index:1;width:100%;max-width:100%;min-height:1.5em;overflow-y:hidden;overflow-x:scroll;letter-spacing:.0625rem;scrollbar-width:none}.adm-virtual-input-content::-webkit-scrollbar{display:none}.adm-virtual-input-placeholder{display:block;position:absolute;z-index:0;left:0;top:0;width:100%;overflow:hidden;text-align:var(--text-align);color:var(--placeholder-color)}.adm-virtual-input-caret-container{display:inline-block;width:var(--caret-width);height:1.3em;vertical-align:top;margin-right:.0625rem;position:absolute}.adm-virtual-input-caret{width:100%;height:100%;background-color:var(--caret-color);position:relative;top:5%}.adm-virtual-input:focus{outline:none}.adm-virtual-input:focus .adm-virtual-input-caret{display:block;animation-name:adm-caret-blink;animation-duration:1s;animation-timing-function:linear;animation-iteration-count:infinite}.adm-virtual-input-disabled{color:var(--disabled-color)}@keyframes adm-caret-blink{0%{opacity:1}60%{opacity:1}80%{opacity:0}to{opacity:0}}.adm-virtual-input-clear{flex:none;margin-left:.5rem;color:var(--placeholder-color);padding:.1875rem;cursor:pointer}.adm-virtual-input-clear .antd-mobile-icon{display:block;font-size:var(--adm-font-size-6)}.adm-water-mark{--z-index: var(--adm-water-mark-z-index, 2000);position:absolute;z-index:var(--z-index);inset:0;pointer-events:none;background-repeat:repeat}.adm-water-mark-full-page{position:fixed}.adm-footer{--background-color: var(--adm-color-background);color:var(--adm-color-text);display:flex;flex-direction:column;align-items:center;background-color:var(--background-color)}.adm-footer-label{width:100%}.adm-footer-label .adm-divider.adm-divider{color:var(--adm-color-light)}.adm-footer-links{margin:.5rem 0;color:var(--adm-color-primary);white-space:nowrap}.adm-footer-links a{text-decoration:none}.adm-footer-content{display:flex;align-items:center;margin:.5rem 0;color:var(--adm-color-light)}.adm-footer-chips{display:flex;align-items:center;white-space:nowrap;margin:.5rem 0}.adm-footer-chip{white-space:nowrap;margin-right:1.25rem;font-size:.75rem;background-color:var(--adm-color-fill-content);color:var(--adm-color-weak);padding:.25rem .75rem;border-radius:6.25rem}.adm-footer-chip-link{cursor:pointer;background-color:var(--adm-color-wathet);color:var(--adm-color-primary)}.adm-footer-chip:last-child{margin-right:0} diff --git a/Cunkebao/dist/index.html b/Cunkebao/dist/index.html deleted file mode 100644 index 0eea1718..00000000 --- a/Cunkebao/dist/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 存客宝 - - - - - - - - - - - - -
- - diff --git a/Cunkebao/dist/logo.png b/Cunkebao/dist/logo.png deleted file mode 100644 index 40daafb0..00000000 Binary files a/Cunkebao/dist/logo.png and /dev/null differ diff --git a/Cunkebao/dist/manifest.json b/Cunkebao/dist/manifest.json deleted file mode 100644 index fc1e9f5a..00000000 --- a/Cunkebao/dist/manifest.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "Cunkebao", - "short_name": "Cunkebao", - "description": "Cunkebao Mobile App", - "theme_color": "#ffffff", - "background_color": "#ffffff", - "display": "standalone", - "orientation": "portrait", - "scope": "/", - "start_url": "/", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "any maskable" - }, - { - "src": "logo.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "any maskable" - } - ] -} \ No newline at end of file diff --git a/Cunkebao/dist/websdk.js b/Cunkebao/dist/websdk.js deleted file mode 100644 index 99870fa4..00000000 --- a/Cunkebao/dist/websdk.js +++ /dev/null @@ -1,308 +0,0 @@ -!(function (e, n) { - "object" == typeof exports && "undefined" != typeof module - ? (module.exports = n()) - : "function" == typeof define && define.amd - ? define(n) - : ((e = e || self).uni = n()); -})(this, function () { - "use strict"; - try { - var e = {}; - (Object.defineProperty(e, "passive", { - get: function () { - !0; - }, - }), - window.addEventListener("test-passive", null, e)); - } catch (e) {} - var n = Object.prototype.hasOwnProperty; - function i(e, i) { - return n.call(e, i); - } - var t = []; - function o() { - return window.__dcloud_weex_postMessage || window.__dcloud_weex_; - } - function a() { - return window.__uniapp_x_postMessage || window.__uniapp_x_; - } - var r = function (e, n) { - var i = { options: { timestamp: +new Date() }, name: e, arg: n }; - if (a()) { - if ("postMessage" === e) { - var r = { data: n }; - return window.__uniapp_x_postMessage - ? window.__uniapp_x_postMessage(r) - : window.__uniapp_x_.postMessage(JSON.stringify(r)); - } - var d = { - type: "WEB_INVOKE_APPSERVICE", - args: { data: i, webviewIds: t }, - }; - window.__uniapp_x_postMessage - ? window.__uniapp_x_postMessageToService(d) - : window.__uniapp_x_.postMessageToService(JSON.stringify(d)); - } else if (o()) { - if ("postMessage" === e) { - var s = { data: [n] }; - return window.__dcloud_weex_postMessage - ? window.__dcloud_weex_postMessage(s) - : window.__dcloud_weex_.postMessage(JSON.stringify(s)); - } - var w = { - type: "WEB_INVOKE_APPSERVICE", - args: { data: i, webviewIds: t }, - }; - window.__dcloud_weex_postMessage - ? window.__dcloud_weex_postMessageToService(w) - : window.__dcloud_weex_.postMessageToService(JSON.stringify(w)); - } else { - if (!window.plus) - return window.parent.postMessage( - { type: "WEB_INVOKE_APPSERVICE", data: i, pageId: "" }, - "*", - ); - if (0 === t.length) { - var u = plus.webview.currentWebview(); - if (!u) throw new Error("plus.webview.currentWebview() is undefined"); - var g = u.parent(), - v = ""; - ((v = g ? g.id : u.id), t.push(v)); - } - if (plus.webview.getWebviewById("__uniapp__service")) - plus.webview.postMessageToUniNView( - { type: "WEB_INVOKE_APPSERVICE", args: { data: i, webviewIds: t } }, - "__uniapp__service", - ); - else { - var c = JSON.stringify(i); - plus.webview - .getLaunchWebview() - .evalJS( - 'UniPlusBridge.subscribeHandler("' - .concat("WEB_INVOKE_APPSERVICE", '",') - .concat(c, ",") - .concat(JSON.stringify(t), ");"), - ); - } - } - }, - d = { - navigateTo: function () { - var e = - arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, - n = e.url; - r("navigateTo", { url: encodeURI(n) }); - }, - navigateBack: function () { - var e = - arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, - n = e.delta; - r("navigateBack", { delta: parseInt(n) || 1 }); - }, - switchTab: function () { - var e = - arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, - n = e.url; - r("switchTab", { url: encodeURI(n) }); - }, - reLaunch: function () { - var e = - arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, - n = e.url; - r("reLaunch", { url: encodeURI(n) }); - }, - redirectTo: function () { - var e = - arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, - n = e.url; - r("redirectTo", { url: encodeURI(n) }); - }, - getEnv: function (e) { - a() - ? e({ uvue: !0 }) - : o() - ? e({ nvue: !0 }) - : window.plus - ? e({ plus: !0 }) - : e({ h5: !0 }); - }, - postMessage: function () { - var e = - arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}; - r("postMessage", e.data || {}); - }, - }, - s = /uni-app/i.test(navigator.userAgent), - w = /Html5Plus/i.test(navigator.userAgent), - u = /complete|loaded|interactive/; - var g = - window.my && - navigator.userAgent.indexOf( - ["t", "n", "e", "i", "l", "C", "y", "a", "p", "i", "l", "A"] - .reverse() - .join(""), - ) > -1; - var v = - window.swan && window.swan.webView && /swan/i.test(navigator.userAgent); - var c = - window.qq && - window.qq.miniProgram && - /QQ/i.test(navigator.userAgent) && - /miniProgram/i.test(navigator.userAgent); - var p = - window.tt && - window.tt.miniProgram && - /toutiaomicroapp/i.test(navigator.userAgent); - var _ = - window.wx && - window.wx.miniProgram && - /micromessenger/i.test(navigator.userAgent) && - /miniProgram/i.test(navigator.userAgent); - var m = window.qa && /quickapp/i.test(navigator.userAgent); - var f = - window.ks && - window.ks.miniProgram && - /micromessenger/i.test(navigator.userAgent) && - /miniProgram/i.test(navigator.userAgent); - var l = - window.tt && - window.tt.miniProgram && - /Lark|Feishu/i.test(navigator.userAgent); - var E = - window.jd && window.jd.miniProgram && /jdmp/i.test(navigator.userAgent); - var x = - window.xhs && - window.xhs.miniProgram && - /xhsminiapp/i.test(navigator.userAgent); - for ( - var S, - h = function () { - ((window.UniAppJSBridge = !0), - document.dispatchEvent( - new CustomEvent("UniAppJSBridgeReady", { - bubbles: !0, - cancelable: !0, - }), - )); - }, - y = [ - function (e) { - if (s || w) - return ( - window.__uniapp_x_postMessage || - window.__uniapp_x_ || - window.__dcloud_weex_postMessage || - window.__dcloud_weex_ - ? document.addEventListener("DOMContentLoaded", e) - : window.plus && u.test(document.readyState) - ? setTimeout(e, 0) - : document.addEventListener("plusready", e), - d - ); - }, - function (e) { - if (_) - return ( - window.WeixinJSBridge && window.WeixinJSBridge.invoke - ? setTimeout(e, 0) - : document.addEventListener("WeixinJSBridgeReady", e), - window.wx.miniProgram - ); - }, - function (e) { - if (c) - return ( - window.QQJSBridge && window.QQJSBridge.invoke - ? setTimeout(e, 0) - : document.addEventListener("QQJSBridgeReady", e), - window.qq.miniProgram - ); - }, - function (e) { - if (g) { - document.addEventListener("DOMContentLoaded", e); - var n = window.my; - return { - navigateTo: n.navigateTo, - navigateBack: n.navigateBack, - switchTab: n.switchTab, - reLaunch: n.reLaunch, - redirectTo: n.redirectTo, - postMessage: n.postMessage, - getEnv: n.getEnv, - }; - } - }, - function (e) { - if (v) - return ( - document.addEventListener("DOMContentLoaded", e), - window.swan.webView - ); - }, - function (e) { - if (p) - return ( - document.addEventListener("DOMContentLoaded", e), - window.tt.miniProgram - ); - }, - function (e) { - if (m) { - window.QaJSBridge && window.QaJSBridge.invoke - ? setTimeout(e, 0) - : document.addEventListener("QaJSBridgeReady", e); - var n = window.qa; - return { - navigateTo: n.navigateTo, - navigateBack: n.navigateBack, - switchTab: n.switchTab, - reLaunch: n.reLaunch, - redirectTo: n.redirectTo, - postMessage: n.postMessage, - getEnv: n.getEnv, - }; - } - }, - function (e) { - if (f) - return ( - window.WeixinJSBridge && window.WeixinJSBridge.invoke - ? setTimeout(e, 0) - : document.addEventListener("WeixinJSBridgeReady", e), - window.ks.miniProgram - ); - }, - function (e) { - if (l) - return ( - document.addEventListener("DOMContentLoaded", e), - window.tt.miniProgram - ); - }, - function (e) { - if (E) - return ( - window.JDJSBridgeReady && window.JDJSBridgeReady.invoke - ? setTimeout(e, 0) - : document.addEventListener("JDJSBridgeReady", e), - window.jd.miniProgram - ); - }, - function (e) { - if (x) return window.xhs.miniProgram; - }, - function (e) { - return (document.addEventListener("DOMContentLoaded", e), d); - }, - ], - M = 0; - M < y.length && !(S = y[M](h)); - M++ - ); - S || (S = {}); - var P = "undefined" != typeof uni ? uni : {}; - if (!P.navigateTo) for (var b in S) i(S, b) && (P[b] = S[b]); - return ((P.webView = S), P); -}); diff --git a/Cunkebao/public/assets/face/666.png b/Cunkebao/public/assets/face/666.png deleted file mode 100644 index f947dc66..00000000 Binary files a/Cunkebao/public/assets/face/666.png and /dev/null differ diff --git a/Cunkebao/public/assets/face/Emm.png b/Cunkebao/public/assets/face/Emm.png deleted file mode 100644 index 8fb9370d..00000000 Binary files a/Cunkebao/public/assets/face/Emm.png and /dev/null differ diff --git a/Cunkebao/public/assets/gesture/OK.png b/Cunkebao/public/assets/gesture/OK.png deleted file mode 100644 index 2d0f6e5f..00000000 Binary files a/Cunkebao/public/assets/gesture/OK.png and /dev/null differ diff --git a/Cunkebao/src/components/EmojiSeclection/wechatEmoji.ts b/Cunkebao/src/components/EmojiSeclection/wechatEmoji.ts index 5e2f3807..7cb53be3 100644 --- a/Cunkebao/src/components/EmojiSeclection/wechatEmoji.ts +++ b/Cunkebao/src/components/EmojiSeclection/wechatEmoji.ts @@ -161,273 +161,313 @@ const EMOJI_DATA: Record = { 微笑: { name: "微笑", category: EmojiCategory.FACE, - path: "/assets/face/微笑.png", + path: "/assets/face/smile.png", }, 撇嘴: { name: "撇嘴", category: EmojiCategory.FACE, - path: "/assets/face/撇嘴.png", + path: "/assets/face/pout.png", + }, + 色: { + name: "色", + category: EmojiCategory.FACE, + path: "/assets/face/lustful.png", }, - 色: { name: "色", category: EmojiCategory.FACE, path: "/assets/face/色.png" }, 发呆: { name: "发呆", category: EmojiCategory.FACE, - path: "/assets/face/发呆.png", + path: "/assets/face/daze.png", }, 得意: { name: "得意", category: EmojiCategory.FACE, - path: "/assets/face/得意.png", + path: "/assets/face/smug.png", }, 流泪: { name: "流泪", category: EmojiCategory.FACE, - path: "/assets/face/流泪.png", + path: "/assets/face/crying.png", }, 害羞: { name: "害羞", category: EmojiCategory.FACE, - path: "/assets/face/害羞.png", + path: "/assets/face/shy.png", }, 闭嘴: { name: "闭嘴", category: EmojiCategory.FACE, - path: "/assets/face/闭嘴.png", + path: "/assets/face/shut-up.png", + }, + 睡: { + name: "睡", + category: EmojiCategory.FACE, + path: "/assets/face/sleep.png", }, - 睡: { name: "睡", category: EmojiCategory.FACE, path: "/assets/face/睡.png" }, 大哭: { name: "大哭", category: EmojiCategory.FACE, - path: "/assets/face/大哭.png", + path: "/assets/face/wail.png", }, 尴尬: { name: "尴尬", category: EmojiCategory.FACE, - path: "/assets/face/尴尬.png", + path: "/assets/face/awkward.png", }, 发怒: { name: "发怒", category: EmojiCategory.FACE, - path: "/assets/face/发怒.png", + path: "/assets/face/angry.png", }, 调皮: { name: "调皮", category: EmojiCategory.FACE, - path: "/assets/face/调皮.png", + path: "/assets/face/naughty.png", }, 呲牙: { name: "呲牙", category: EmojiCategory.FACE, - path: "/assets/face/呲牙.png", + path: "/assets/face/grin.png", }, 惊讶: { name: "惊讶", category: EmojiCategory.FACE, - path: "/assets/face/惊讶.png", + path: "/assets/face/surprised.png", }, 难过: { name: "难过", category: EmojiCategory.FACE, - path: "/assets/face/难过.png", + path: "/assets/face/sad.png", + }, + 囧: { + name: "囧", + category: EmojiCategory.FACE, + path: "/assets/face/embarrassed.png", }, - 囧: { name: "囧", category: EmojiCategory.FACE, path: "/assets/face/囧.png" }, 抓狂: { name: "抓狂", category: EmojiCategory.FACE, - path: "/assets/face/抓狂.png", + path: "/assets/face/crazy.png", + }, + 吐: { + name: "吐", + category: EmojiCategory.FACE, + path: "/assets/face/vomit.png", }, - 吐: { name: "吐", category: EmojiCategory.FACE, path: "/assets/face/吐.png" }, 偷笑: { name: "偷笑", category: EmojiCategory.FACE, - path: "/assets/face/偷笑.png", + path: "/assets/face/snicker.png", }, 愉快: { name: "愉快", category: EmojiCategory.FACE, - path: "/assets/face/愉快.png", + path: "/assets/face/happy.png", }, 白眼: { name: "白眼", category: EmojiCategory.FACE, - path: "/assets/face/白眼.png", + path: "/assets/face/roll-eyes.png", }, 傲慢: { name: "傲慢", category: EmojiCategory.FACE, - path: "/assets/face/傲慢.png", + path: "/assets/face/arrogant.png", + }, + 困: { + name: "困", + category: EmojiCategory.FACE, + path: "/assets/face/sleepy.png", }, - 困: { name: "困", category: EmojiCategory.FACE, path: "/assets/face/困.png" }, 惊恐: { name: "惊恐", category: EmojiCategory.FACE, - path: "/assets/face/惊恐.png", + path: "/assets/face/panic.png", }, 憨笑: { name: "憨笑", category: EmojiCategory.FACE, - path: "/assets/face/憨笑.png", + path: "/assets/face/silly-smile.png", }, 悠闲: { name: "悠闲", category: EmojiCategory.FACE, - path: "/assets/face/悠闲.png", + path: "/assets/face/leisurely.png", }, 咒骂: { name: "咒骂", category: EmojiCategory.FACE, - path: "/assets/face/咒骂.png", + path: "/assets/face/curse.png", }, 疑问: { name: "疑问", category: EmojiCategory.FACE, - path: "/assets/face/疑问.png", + path: "/assets/face/question.png", + }, + 嘘: { + name: "嘘", + category: EmojiCategory.FACE, + path: "/assets/face/shush.png", + }, + 晕: { + name: "晕", + category: EmojiCategory.FACE, + path: "/assets/face/dizzy.png", + }, + 衰: { + name: "衰", + category: EmojiCategory.FACE, + path: "/assets/face/unlucky.png", }, - 嘘: { name: "嘘", category: EmojiCategory.FACE, path: "/assets/face/嘘.png" }, - 晕: { name: "晕", category: EmojiCategory.FACE, path: "/assets/face/晕.png" }, - 衰: { name: "衰", category: EmojiCategory.FACE, path: "/assets/face/衰.png" }, 骷髅: { name: "骷髅", category: EmojiCategory.FACE, - path: "/assets/face/骷髅.png", + path: "/assets/face/skull.png", }, 敲打: { name: "敲打", category: EmojiCategory.FACE, - path: "/assets/face/敲打.png", + path: "/assets/face/knock.png", }, 再见: { name: "再见", category: EmojiCategory.FACE, - path: "/assets/face/再见.png", + path: "/assets/face/goodbye.png", }, 擦汗: { name: "擦汗", category: EmojiCategory.FACE, - path: "/assets/face/擦汗.png", + path: "/assets/face/wipe-sweat.png", }, 抠鼻: { name: "抠鼻", category: EmojiCategory.FACE, - path: "/assets/face/抠鼻.png", + path: "/assets/face/pick-nose.png", }, 鼓掌: { name: "鼓掌", category: EmojiCategory.FACE, - path: "/assets/face/鼓掌.png", + path: "/assets/face/clap.png", }, 坏笑: { name: "坏笑", category: EmojiCategory.FACE, - path: "/assets/face/坏笑.png", + path: "/assets/face/evil-smile.png", }, 右哼哼: { name: "右哼哼", category: EmojiCategory.FACE, - path: "/assets/face/右哼哼.png", + path: "/assets/face/right-hum.png", }, 鄙视: { name: "鄙视", category: EmojiCategory.FACE, - path: "/assets/face/鄙视.png", + path: "/assets/face/despise.png", }, 委屈: { name: "委屈", category: EmojiCategory.FACE, - path: "/assets/face/委屈.png", + path: "/assets/face/wronged.png", }, 快哭了: { name: "快哭了", category: EmojiCategory.FACE, - path: "/assets/face/快哭了.png", + path: "/assets/face/about-to-cry.png", }, 阴险: { name: "阴险", category: EmojiCategory.FACE, - path: "/assets/face/阴险.png", + path: "/assets/face/sinister.png", }, 亲亲: { name: "亲亲", category: EmojiCategory.FACE, - path: "/assets/face/亲亲.png", + path: "/assets/face/kiss.png", }, 可怜: { name: "可怜", category: EmojiCategory.FACE, - path: "/assets/face/可怜.png", + path: "/assets/face/pitiful.png", }, 笑脸: { name: "笑脸", category: EmojiCategory.FACE, - path: "/assets/face/笑脸.png", + path: "/assets/face/smiley.png", }, 生病: { name: "生病", category: EmojiCategory.FACE, - path: "/assets/face/生病.png", + path: "/assets/face/sick.png", }, 脸红: { name: "脸红", category: EmojiCategory.FACE, - path: "/assets/face/脸红.png", + path: "/assets/face/blush.png", }, 破涕为笑: { name: "破涕为笑", category: EmojiCategory.FACE, - path: "/assets/face/破涕为笑.png", + path: "/assets/face/tears-to-smile.png", }, 恐惧: { name: "恐惧", category: EmojiCategory.FACE, - path: "/assets/face/恐惧.png", + path: "/assets/face/fear.png", }, 失望: { name: "失望", category: EmojiCategory.FACE, - path: "/assets/face/失望.png", + path: "/assets/face/disappointed.png", }, 无语: { name: "无语", category: EmojiCategory.FACE, - path: "/assets/face/无语.png", + path: "/assets/face/speechless.png", }, 嘿哈: { name: "嘿哈", category: EmojiCategory.FACE, - path: "/assets/face/嘿哈.png", + path: "/assets/face/hey-ha.png", }, 捂脸: { name: "捂脸", category: EmojiCategory.FACE, - path: "/assets/face/捂脸.png", + path: "/assets/face/facepalm.png", }, 机智: { name: "机智", category: EmojiCategory.FACE, - path: "/assets/face/机智.png", + path: "/assets/face/smart.png", }, 皱眉: { name: "皱眉", category: EmojiCategory.FACE, - path: "/assets/face/皱眉.png", + path: "/assets/face/frown.png", + }, + 耶: { + name: "耶", + category: EmojiCategory.FACE, + path: "/assets/face/yeah.png", }, - 耶: { name: "耶", category: EmojiCategory.FACE, path: "/assets/face/耶.png" }, 吃瓜: { name: "吃瓜", category: EmojiCategory.FACE, - path: "/assets/face/吃瓜.png", + path: "/assets/face/eat-melon.png", }, 加油: { name: "加油", category: EmojiCategory.FACE, - path: "/assets/face/加油.png", + path: "/assets/face/cheer-up.png", }, - 汗: { name: "汗", category: EmojiCategory.FACE, path: "/assets/face/汗.png" }, + 汗: { + name: "汗", + category: EmojiCategory.FACE, + path: "/assets/face/sweat.png", + }, 天啊: { name: "天啊", category: EmojiCategory.FACE, - path: "/assets/face/天啊.png", + path: "/assets/face/oh-my.png", }, Emm: { name: "Emm", @@ -437,28 +477,32 @@ const EMOJI_DATA: Record = { 社会社会: { name: "社会社会", category: EmojiCategory.FACE, - path: "/assets/face/社会社会.png", + path: "/assets/face/social.png", }, 旺柴: { name: "旺柴", category: EmojiCategory.FACE, - path: "/assets/face/旺柴.png", + path: "/assets/face/doge.png", }, 好的: { name: "好的", category: EmojiCategory.FACE, - path: "/assets/face/好的.png", + path: "/assets/face/good.png", }, 打脸: { name: "打脸", category: EmojiCategory.FACE, - path: "/assets/face/打脸.png", + path: "/assets/face/slap-face.png", + }, + 哇: { + name: "哇", + category: EmojiCategory.FACE, + path: "/assets/face/wow.png", }, - 哇: { name: "哇", category: EmojiCategory.FACE, path: "/assets/face/哇.png" }, 翻白眼: { name: "翻白眼", category: EmojiCategory.FACE, - path: "/assets/face/翻白眼.png", + path: "/assets/face/eye-roll.png", }, "666": { name: "666", @@ -468,54 +512,54 @@ const EMOJI_DATA: Record = { 让我看看: { name: "让我看看", category: EmojiCategory.FACE, - path: "/assets/face/让我看看.png", + path: "/assets/face/let-me-see.png", }, 叹气: { name: "叹气", category: EmojiCategory.FACE, - path: "/assets/face/叹气.png", + path: "/assets/face/sigh.png", }, 苦涩: { name: "苦涩", category: EmojiCategory.FACE, - path: "/assets/face/苦涩.png", + path: "/assets/face/bitter.png", }, 裂开: { name: "裂开", category: EmojiCategory.FACE, - path: "/assets/face/裂开.png", + path: "/assets/face/crack.png", }, 奸笑: { name: "奸笑", category: EmojiCategory.FACE, - path: "/assets/face/奸笑.png", + path: "/assets/face/sly-smile.png", }, // 手势表情 握手: { name: "握手", category: EmojiCategory.GESTURE, - path: "/assets/gesture/握手.png", + path: "/assets/gesture/handshake.png", }, 胜利: { name: "胜利", category: EmojiCategory.GESTURE, - path: "/assets/gesture/胜利.png", + path: "/assets/gesture/victory.png", }, 抱拳: { name: "抱拳", category: EmojiCategory.GESTURE, - path: "/assets/gesture/抱拳.png", + path: "/assets/gesture/fist-salute.png", }, 勾引: { name: "勾引", category: EmojiCategory.GESTURE, - path: "/assets/gesture/勾引.png", + path: "/assets/gesture/beckon.png", }, 拳头: { name: "拳头", category: EmojiCategory.GESTURE, - path: "/assets/gesture/拳头.png", + path: "/assets/gesture/fist.png", }, OK: { name: "OK", @@ -525,148 +569,148 @@ const EMOJI_DATA: Record = { 合十: { name: "合十", category: EmojiCategory.GESTURE, - path: "/assets/gesture/合十.png", + path: "/assets/gesture/pray.png", }, 强: { name: "强", category: EmojiCategory.GESTURE, - path: "/assets/gesture/强.png", + path: "/assets/gesture/strong.png", }, 拥抱: { name: "拥抱", category: EmojiCategory.GESTURE, - path: "/assets/gesture/拥抱.png", + path: "/assets/gesture/hug.png", }, 弱: { name: "弱", category: EmojiCategory.GESTURE, - path: "/assets/gesture/弱.png", + path: "/assets/gesture/weak.png", }, // 动物表情 猪头: { name: "猪头", category: EmojiCategory.ANIMAL, - path: "/assets/animal/猪头.png", + path: "/assets/animal/pig.png", }, 跳跳: { name: "跳跳", category: EmojiCategory.ANIMAL, - path: "/assets/animal/跳跳.png", + path: "/assets/animal/jump.png", }, 发抖: { name: "发抖", category: EmojiCategory.ANIMAL, - path: "/assets/animal/发抖.png", + path: "/assets/animal/tremble.png", }, 转圈: { name: "转圈", category: EmojiCategory.ANIMAL, - path: "/assets/animal/转圈.png", + path: "/assets/animal/circle.png", }, // 祝福表情 庆祝: { name: "庆祝", category: EmojiCategory.BLESSING, - path: "/assets/blessing/庆祝.png", + path: "/assets/blessing/celebrate.png", }, 礼物: { name: "礼物", category: EmojiCategory.BLESSING, - path: "/assets/blessing/礼物.png", + path: "/assets/blessing/gift.png", }, 红包: { name: "红包", category: EmojiCategory.BLESSING, - path: "/assets/blessing/红包.png", + path: "/assets/blessing/red-envelope.png", }, 發: { name: "發", category: EmojiCategory.BLESSING, - path: "/assets/blessing/發.png", + path: "/assets/blessing/get-rich.png", }, 福: { name: "福", category: EmojiCategory.BLESSING, - path: "/assets/blessing/福.png", + path: "/assets/blessing/fortune.png", }, 烟花: { name: "烟花", category: EmojiCategory.BLESSING, - path: "/assets/blessing/烟花.png", + path: "/assets/blessing/fireworks.png", }, 爆竹: { name: "爆竹", category: EmojiCategory.BLESSING, - path: "/assets/blessing/爆竹.png", + path: "/assets/blessing/firecrackers.png", }, // 其他表情 嘴唇: { name: "嘴唇", category: EmojiCategory.OTHER, - path: "/assets/other/嘴唇.png", + path: "/assets/other/lips.png", }, 爱心: { name: "爱心", category: EmojiCategory.OTHER, - path: "/assets/other/爱心.png", + path: "/assets/other/heart.png", }, 心碎: { name: "心碎", category: EmojiCategory.OTHER, - path: "/assets/other/心碎.png", + path: "/assets/other/broken-heart.png", }, 啤酒: { name: "啤酒", category: EmojiCategory.OTHER, - path: "/assets/other/啤酒.png", + path: "/assets/other/beer.png", }, 咖啡: { name: "咖啡", category: EmojiCategory.OTHER, - path: "/assets/other/咖啡.png", + path: "/assets/other/coffee.png", }, 蛋糕: { name: "蛋糕", category: EmojiCategory.OTHER, - path: "/assets/other/蛋糕.png", + path: "/assets/other/cake.png", }, 凋谢: { name: "凋谢", category: EmojiCategory.OTHER, - path: "/assets/other/凋谢.png", + path: "/assets/other/wither.png", }, 菜刀: { name: "菜刀", category: EmojiCategory.OTHER, - path: "/assets/other/菜刀.png", + path: "/assets/other/knife.png", }, 炸弹: { name: "炸弹", category: EmojiCategory.OTHER, - path: "/assets/other/炸弹.png", + path: "/assets/other/bomb.png", }, 便便: { name: "便便", category: EmojiCategory.OTHER, - path: "/assets/other/便便.png", + path: "/assets/other/poop.png", }, 太阳: { name: "太阳", category: EmojiCategory.OTHER, - path: "/assets/other/太阳.png", + path: "/assets/other/sun.png", }, 月亮: { name: "月亮", category: EmojiCategory.OTHER, - path: "/assets/other/月亮.png", + path: "/assets/other/moon.png", }, 玫瑰: { name: "玫瑰", category: EmojiCategory.OTHER, - path: "/assets/other/玫瑰.png", + path: "/assets/other/rose.png", }, }; diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/detail/index.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/detail/index.tsx index 786669ed..ca0242b4 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/detail/index.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/detail/index.tsx @@ -784,12 +784,6 @@ const TrafficPoolDetail: React.FC = () => { )} - - {/* 添加新标签按钮 */} - )} diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx index 86dda202..5feee159 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx @@ -1,57 +1,94 @@ -import React from "react"; -import { Popup, Selector } from "antd-mobile"; +import React, { useState, useEffect } from "react"; +import { Popup, Selector, Button } from "antd-mobile"; +import { fetchPackageOptions } from "./api"; import type { PackageOption } from "./data"; interface BatchAddModalProps { visible: boolean; onClose: () => void; - packageOptions: PackageOption[]; - batchTarget: string; - setBatchTarget: (v: string) => void; selectedCount: number; - onConfirm: () => void; + onConfirm: (data: { + packageOptions: PackageOption[]; + selectedPackageId: string; + }) => void; } const BatchAddModal: React.FC = ({ visible, onClose, - packageOptions = [], - batchTarget, - setBatchTarget, selectedCount, onConfirm, -}) => ( - // - //
- //
选择目标分组
- // ({ label: p.name, value: p.id }))} - // value={[batchTarget]} - // onChange={v => setBatchTarget(v[0])} - // /> - //
- //
- // 将选中的{selectedCount}个用户加入所选分组 - //
- //
- onClose()} - position="bottom" - bodyStyle={{ height: "80vh" }} - > -
-
选择目标分组
- ({ label: p.name, value: p.id }))} - value={[batchTarget]} - onChange={v => setBatchTarget(v[0])} - /> -
-
- 将选中的{selectedCount}个用户加入所选分组 -
-
-); +}) => { + const [packageOptions, setPackageOptions] = useState([]); + const [selectedPackageId, setSelectedPackageId] = useState(""); + const [loading, setLoading] = useState(false); + + // 获取分组选项 + useEffect(() => { + if (visible) { + setLoading(true); + fetchPackageOptions() + .then(res => { + setPackageOptions(res.list || []); + }) + .catch(error => { + console.error("获取分组选项失败:", error); + }) + .finally(() => { + setLoading(false); + }); + } + }, [visible]); + + const handleSubmit = () => { + if (!selectedPackageId) { + // 可以添加提示 + return; + } + onConfirm({ + packageOptions, + selectedPackageId, + }); + }; + return ( + onClose()} + position="bottom" + bodyStyle={{ height: "80vh" }} + > +
+
选择目标分组
+ {loading ? ( +
加载中...
+ ) : ( + ({ label: p.name, value: p.id }))} + value={[selectedPackageId]} + onChange={v => setSelectedPackageId(v[0])} + /> + )} +
+ 将选中的{selectedCount}个用户加入所选分组 +
+ +
+
+ ); +}; export default BatchAddModal; diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/DataAnalysisPanel.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/DataAnalysisPanel.tsx index 395d7b51..5256de31 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/DataAnalysisPanel.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/DataAnalysisPanel.tsx @@ -1,24 +1,77 @@ -import React from "react"; +import React, { useState, useEffect, useMemo } from "react"; import { Card, Button } from "antd-mobile"; +import { fetchTrafficPoolList } from "./api"; +import type { TrafficPoolUser } from "./data"; interface DataAnalysisPanelProps { - stats: { + showStats: boolean; + setShowStats: (v: boolean) => void; + onConfirm: (stats: { total: number; highValue: number; added: number; pending: number; failed: number; addSuccessRate: number; - }; - showStats: boolean; - setShowStats: (v: boolean) => void; + }) => void; } const DataAnalysisPanel: React.FC = ({ - stats, showStats, setShowStats, + onConfirm, }) => { + const [list, setList] = useState([]); + const [loading, setLoading] = useState(false); + + // 计算统计数据 + const stats = useMemo(() => { + const total = list.length; + const highValue = list.filter( + u => u.tags && u.tags.includes("高价值客户池"), + ).length; + const added = list.filter(u => u.status === 1).length; + const pending = list.filter(u => u.status === 0).length; + const failed = list.filter(u => u.status === -1).length; + const addSuccessRate = total ? Math.round((added / total) * 100) : 0; + return { total, highValue, added, pending, failed, addSuccessRate }; + }, [list]); + + // 获取数据 + useEffect(() => { + if (showStats) { + setLoading(true); + fetchTrafficPoolList({ page: 1, pageSize: 1000 }) // 获取所有数据进行统计 + .then(res => { + setList(res.list || []); + // 通过 onConfirm 抛出统计数据 + const total = res.list?.length || 0; + const highValue = + res.list?.filter(u => u.tags && u.tags.includes("高价值客户池")) + .length || 0; + const added = res.list?.filter(u => u.status === 1).length || 0; + const pending = res.list?.filter(u => u.status === 0).length || 0; + const failed = res.list?.filter(u => u.status === -1).length || 0; + const addSuccessRate = total ? Math.round((added / total) * 100) : 0; + + onConfirm({ + total, + highValue, + added, + pending, + failed, + addSuccessRate, + }); + }) + .catch(error => { + console.error("获取统计数据失败:", error); + }) + .finally(() => { + setLoading(false); + }); + } + }, [showStats, onConfirm]); + if (!showStats) return null; return (
= ({ boxShadow: "0 2px 8px rgba(0,0,0,0.04)", }} > -
- -
- {stats.total} + {loading ? ( +
+ 加载统计数据中... +
+ ) : ( + <> +
+ +
+ {stats.total} +
+
总用户数
+
+ +
+ {stats.highValue} +
+
高价值用户
+
-
总用户数
- - -
- {stats.highValue} +
+ +
+ {stats.addSuccessRate}% +
+
添加成功率
+
+ +
+ {stats.added} +
+
已添加
+
+ +
+ {stats.pending} +
+
待添加
+
+ +
+ {stats.failed} +
+
添加失败
+
-
高价值用户
- -
-
- -
- {stats.addSuccessRate}% -
-
添加成功率
-
- -
- {stats.added} -
-
已添加
-
- -
- {stats.pending} -
-
待添加
-
- -
- {stats.failed} -
-
添加失败
-
-
+ + )}
{/* 数据分析面板 */} { + // 可以在这里处理统计数据,比如更新本地状态或发送到父组件 + console.log("收到统计数据:", statsData); + }} /> {/* 批量操作栏 */} @@ -114,7 +230,7 @@ const TrafficPoolList: React.FC = () => { style={{ display: "flex", alignItems: "center", - padding: "8px 12px", + padding: "8px 12px 8px 26px", background: "#fff", borderBottom: "1px solid #f0f0f0", }} @@ -140,6 +256,18 @@ const TrafficPoolList: React.FC = () => { )} + {searchInput.length > 0 && ( + <> + + + )}
} @@ -167,35 +298,40 @@ const TrafficPoolList: React.FC = () => { setBatchModal(false)} - packageOptions={packageOptions} - batchTarget={batchTarget} - setBatchTarget={setBatchTarget} selectedCount={selectedIds.length} - onConfirm={handleBatchAdd} + onConfirm={data => { + // 处理批量加入逻辑 + handleBatchAdd(data); + }} /> {/* 筛选弹窗 */} setShowFilter(false)} onConfirm={filters => { - // 更新筛选条件 - setSelectedDevices( - filters.deviceIds.map(id => ({ - id: parseInt(id), - memo: "", - imei: "", - wechatId: "", - status: "offline" as const, - })), - ); - setPackageId(filters.packageId ? parseInt(filters.packageId) : 0); - setScenarioId(filters.scenarioId ? parseInt(filters.scenarioId) : 0); - setUserValue(filters.userValue); - setUserStatus(filters.userStatus); - // 重新获取列表 - getList(); + // 更新公共筛选条件状态 + const newFilterParams = { + selectedDevices: filters.selectedDevices, + packageId: filters.packageld, + scenarioId: filters.sceneId, + userValue: filters.userValue, + userStatus: filters.addStatus, + }; + + setFilterParams(newFilterParams); + // 重置到第一页并请求列表 + setPage(1); + getList({ + page: 1, + packageld: newFilterParams.packageId, + sceneId: newFilterParams.scenarioId, + userValue: newFilterParams.userValue, + addStatus: newFilterParams.userStatus, + deviceld: newFilterParams.selectedDevices.map(d => d.id).join(), + }); }} scenarioOptions={scenarioOptions} + initialFilters={filterParams} />
{list.length === 0 && !loading ? ( diff --git a/Cunkebao/src/pages/mobile/workspace/contact-import/form/data.ts b/Cunkebao/src/pages/mobile/workspace/contact-import/form/data.ts index 4847665e..64767d09 100644 --- a/Cunkebao/src/pages/mobile/workspace/contact-import/form/data.ts +++ b/Cunkebao/src/pages/mobile/workspace/contact-import/form/data.ts @@ -14,7 +14,7 @@ export interface Allocation { /** 设备id */ deviceGroups: number[]; /** 流量池 */ - pools?: JSON | null; + poolGroups?: number[]; /** 分配数量 */ num?: number | null; @@ -72,7 +72,7 @@ export interface ContactImportTaskConfig { id: number; workbenchId: number; devices: number[]; - pools: number[]; + poolGroups: number[]; num: number; clearContact: number; remarkType: number; @@ -114,7 +114,7 @@ export interface CreateContactImportTaskData { type: number; config: { devices: number[]; - pools: number[]; + poolGroups: number[]; num: number; clearContact: number; remarkType: number; diff --git a/Cunkebao/src/pages/mobile/workspace/contact-import/form/index.tsx b/Cunkebao/src/pages/mobile/workspace/contact-import/form/index.tsx index a7606240..001ad6ba 100644 --- a/Cunkebao/src/pages/mobile/workspace/contact-import/form/index.tsx +++ b/Cunkebao/src/pages/mobile/workspace/contact-import/form/index.tsx @@ -1,17 +1,19 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useCallback } from "react"; import { useNavigate, useParams } from "react-router-dom"; import { PlusOutlined, MinusOutlined } from "@ant-design/icons"; import { Button, Input, message, TimePicker, Select, Switch } from "antd"; import NavCommon from "@/components/NavCommon"; import Layout from "@/components/Layout/Layout"; import DeviceSelection from "@/components/DeviceSelection"; +import PoolSelection from "@/components/PoolSelection"; import { createContactImportTask, updateContactImportTask, fetchContactImportTaskDetail, } from "./api"; import { Allocation } from "./data"; - +import { PoolSelectionItem } from "@/components/PoolSelection/data"; +import { DeviceSelectionItem } from "@/components/DeviceSelection/data"; import style from "./index.module.scss"; import dayjs from "dayjs"; @@ -27,7 +29,7 @@ const ContactImportForm: React.FC = () => { type: 6, // 任务类型,固定为6 workbenchId: 1, // 默认工作台ID deviceGroups: [] as number[], - pools: [] as any[], + poolGroups: [] as number[], num: 50, clearContact: 0, remarkType: 0, @@ -35,7 +37,8 @@ const ContactImportForm: React.FC = () => { startTime: dayjs("09:00", "HH:mm"), endTime: dayjs("21:00", "HH:mm"), // 保留原有字段用于UI显示 - deviceGroupsOptions: [] as any[], + deviceGroupsOptions: [] as DeviceSelectionItem[], + poolGroupsOptions: [] as PoolSelectionItem[], // 流量池选择项 }); // 处理设备选择 @@ -47,8 +50,17 @@ const ContactImportForm: React.FC = () => { })); }; + // 处理流量池选择 + const handlePoolSelect = (selectedpoolGroups: PoolSelectionItem[]) => { + setFormData(prev => ({ + ...prev, + poolGroupsOptions: selectedpoolGroups, + poolGroups: selectedpoolGroups.map(pool => Number(pool.id)), // 提取流量池信息存储到pools数组 + })); + }; + // 获取任务详情(编辑模式) - const loadTaskDetail = async () => { + const loadTaskDetail = useCallback(async () => { if (!id) return; try { @@ -59,6 +71,7 @@ const ContactImportForm: React.FC = () => { // 构造设备选择组件需要的数据格式 const deviceGroupsOptions = config.deviceGroupsOptions || []; + const poolGroupsOptions = config.poolGroupsOptions || []; setFormData({ name: data.name || "", @@ -67,7 +80,7 @@ const ContactImportForm: React.FC = () => { workbenchId: config.workbenchId || 1, deviceGroups: deviceGroupsOptions.map((device: any) => device.id) || [], - pools: config.pools ? JSON.parse(JSON.stringify(config.pools)) : [], + poolGroups: config.poolGroups || [], num: config.num || 50, clearContact: config.clearContact || 0, remarkType: config.remarkType || 0, @@ -75,6 +88,7 @@ const ContactImportForm: React.FC = () => { startTime: config.startTime ? dayjs(config.startTime, "HH:mm") : null, endTime: config.endTime ? dayjs(config.endTime, "HH:mm") : null, deviceGroupsOptions, + poolGroupsOptions, }); } } catch (error) { @@ -84,7 +98,7 @@ const ContactImportForm: React.FC = () => { } finally { setLoading(false); } - }; + }, [id, navigate]); // 更新表单数据 const handleUpdateFormData = (data: Partial) => { @@ -125,7 +139,7 @@ const ContactImportForm: React.FC = () => { type: formData.type, workbenchId: formData.workbenchId, deviceGroups: formData.deviceGroups, - pools: JSON.parse(JSON.stringify(formData.pools)), + poolGroups: formData.poolGroups, num: formData.num, clearContact: formData.clearContact, remarkType: formData.remarkType, @@ -161,7 +175,7 @@ const ContactImportForm: React.FC = () => { type: 6, workbenchId: 1, deviceGroups: [], - pools: [], + poolGroups: [], num: 50, clearContact: 0, remarkType: 0, @@ -169,6 +183,7 @@ const ContactImportForm: React.FC = () => { startTime: dayjs("09:00", "HH:mm"), endTime: dayjs("21:00", "HH:mm"), deviceGroupsOptions: [], + poolGroupsOptions: [], }); }; @@ -176,7 +191,7 @@ const ContactImportForm: React.FC = () => { if (isEdit) { loadTaskDetail(); } - }, [id, isEdit]); + }, [id, isEdit, loadTaskDetail]); return ( {
选择要分配联系人的设备
+
+
流量池选择
+ +
选择要导入的流量池
+
+
分配数量
diff --git a/Cunkebao/src/pages/mobile/workspace/contact-import/list/data.ts b/Cunkebao/src/pages/mobile/workspace/contact-import/list/data.ts index 33986379..a813afd2 100644 --- a/Cunkebao/src/pages/mobile/workspace/contact-import/list/data.ts +++ b/Cunkebao/src/pages/mobile/workspace/contact-import/list/data.ts @@ -35,7 +35,7 @@ export interface ContactImportTaskConfig { id: number; workbenchId: number; devices: number[]; - pools: number[]; + poolGroups: number[]; num: number; clearContact: number; remarkType: number; @@ -77,7 +77,7 @@ export interface CreateContactImportTaskData { type: number; config: { devices: number[]; - pools: number[]; + poolGroups: number[]; num: number; clearContact: number; remarkType: number; diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/data.ts b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/data.ts index 20b45fe6..ab82999f 100644 --- a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/data.ts +++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/data.ts @@ -27,7 +27,7 @@ export interface TrafficDistributionConfig { accountGroupsOptions: any[]; deviceGroups: any[]; deviceGroupsOptions: any[]; - pools: any[]; + poolGroups: any[]; exp: number; createTime: string; updateTime: string; @@ -58,7 +58,7 @@ export interface TrafficDistributionFormData { deviceGroupsOptions: any[]; accountGroups: any[]; accountGroupsOptions: any[]; - pools: any[]; + poolGroups: any[]; enabled: boolean; } diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/index.tsx b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/index.tsx index 7d6f21b1..b18da0a7 100644 --- a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/index.tsx +++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/index.tsx @@ -1,15 +1,5 @@ -import React, { useState, useEffect } from "react"; -import { - Form, - Input, - Button, - Radio, - Slider, - TimePicker, - message, - Checkbox, -} from "antd"; -import { SearchOutlined } from "@ant-design/icons"; +import React, { useState, useEffect, useCallback } from "react"; +import { Form, Input, Button, Radio, Slider, TimePicker, message } from "antd"; import { useNavigate, useParams } from "react-router-dom"; import style from "./index.module.scss"; import StepIndicator from "@/components/StepIndicator"; @@ -19,38 +9,16 @@ import AccountSelection from "@/components/AccountSelection"; import { AccountItem } from "@/components/AccountSelection/data"; import DeviceSelection from "@/components/DeviceSelection"; import { DeviceSelectionItem } from "@/components/DeviceSelection/data"; +import PoolSelection from "@/components/PoolSelection"; +import { PoolSelectionItem } from "@/components/PoolSelection/data"; import { getTrafficDistributionDetail, updateTrafficDistribution, createTrafficDistribution, } from "./api"; -import type { - TrafficDistributionDetail, - TrafficDistributionFormData, -} from "./data"; +import type { TrafficDistributionFormData } from "./data"; import dayjs from "dayjs"; -const scenarioList = [ - { label: "海报获客", value: "poster" }, - { label: "电话获客", value: "phone" }, - { label: "抖音获客", value: "douyin" }, - { label: "小红书获客", value: "xiaohongshu" }, - { label: "微信群获客", value: "weixinqun" }, - { label: "API获客", value: "api" }, - { label: "订单获客", value: "order" }, - { label: "付款码获客", value: "payment" }, -]; -const poolList = [ - { - id: "pool-1", - name: "高价值客户池", - userCount: 156, - tags: ["高价值", "优先添加"], - }, - { id: "pool-2", name: "潜在客户池", userCount: 289, tags: ["潜在客户"] }, - { id: "pool-3", name: "新用户池", userCount: 432, tags: ["新用户"] }, -]; - const stepList = [ { id: 1, title: "基本信息", subtitle: "基本信息" }, { id: 2, title: "目标设置", subtitle: "目标设置" }, @@ -73,22 +41,20 @@ const TrafficDistributionForm: React.FC = () => { const [deviceGroupsOptions, setDeviceGroupsOptions] = useState([]); const [accountGroups, setAccountGroups] = useState([]); const [accountGroupsOptions, setAccountGroupsOptions] = useState([]); - const [distributeType, setDistributeType] = useState(1); - const [maxPerDay, setMaxPerDay] = useState(50); - const [timeType, setTimeType] = useState(1); - const [timeRange, setTimeRange] = useState(null); + // 使用 Form 管理字段,配合 useWatch 读取值 const [loading, setLoading] = useState(false); const [detailLoading, setDetailLoading] = useState(false); - const [selectedPools, setSelectedPools] = useState([]); - const [poolSearch, setPoolSearch] = useState(""); - const [targetSelectionTab, setTargetSelectionTab] = useState< - "device" | "account" - >("device"); + const [poolGroupsOptions, setPoolGroupsOptions] = useState< + PoolSelectionItem[] + >([]); - // 编辑时的详情数据 - const [detailData, setDetailData] = - useState(null); + // 编辑时的详情数据(不需要保存整份数据,仅回填表单与本地状态) + + // 监听表单字段变化(antd v5 推荐) + const maxPerDay = Form.useWatch("maxPerDay", form); + const timeType = Form.useWatch("timeType", form); + // const timeRange = Form.useWatch("timeRange", form); // 生成默认名称 const generateDefaultName = () => { @@ -98,20 +64,12 @@ const TrafficDistributionForm: React.FC = () => { return `流量分发 ${dateStr} ${timeStr}`; }; - // 获取详情数据 - useEffect(() => { - if (isEdit && id) { - fetchDetail(); - } - }, [isEdit, id]); - - const fetchDetail = async () => { + const fetchDetail = useCallback(async () => { if (!id) return; setDetailLoading(true); try { const detail = await getTrafficDistributionDetail(id); - setDetailData(detail); // 回填表单数据 const config = detail.config; @@ -122,11 +80,6 @@ const TrafficDistributionForm: React.FC = () => { timeType: config.timeType, }); - // 设置状态 - setDistributeType(config.distributeType); - setMaxPerDay(config.maxPerDay); - setTimeType(config.timeType); - // 设置账号组数据 setAccountGroups(config.accountGroups || []); setAccountGroupsOptions(config.accountGroupsOptions || []); @@ -136,6 +89,8 @@ const TrafficDistributionForm: React.FC = () => { setDeviceGroups(config.deviceGroups || []); setDeviceGroupsOptions(config.deviceGroupsOptions || []); setSelectedDevices(config.deviceGroupsOptions || []); + //设置流量池 + setPoolGroupsOptions(config.poolGroupsOptions || []); // 设置时间范围 - 使用dayjs格式 if (config.timeType === 2 && config.startTime && config.endTime) { @@ -147,22 +102,37 @@ const TrafficDistributionForm: React.FC = () => { // 使用dayjs创建时间对象 const startTime = dayjs().hour(startHour).minute(startMinute).second(0); const endTime = dayjs().hour(endHour).minute(endMinute).second(0); - setTimeRange([startTime, endTime]); + form.setFieldsValue({ timeRange: [startTime, endTime] }); } - // 设置流量池 - setSelectedPools(config.pools.map((pool: any) => pool.id || pool)); + // 设置流量池 - 交由 PoolSelection 控件受控 } catch (error) { console.error("获取详情失败:", error); message.error("获取详情失败"); } finally { setDetailLoading(false); } + }, [id, form]); + + // 获取详情数据 + useEffect(() => { + if (isEdit && id) { + fetchDetail(); + } + }, [isEdit, id, fetchDetail]); + const handleFinish = async () => { + form.submit(); }; - const handleFinish = async (values?: any) => { + const handleFinish2 = async (values?: any) => { setLoading(true); try { + // 校验流量池至少选择一个 + if (!poolGroupsOptions || poolGroupsOptions.length === 0) { + message.error("请至少选择一个流量池"); + setLoading(false); + return; + } // 如果没有传递values参数,从表单中获取 const formValues = values || form.getFieldsValue(); @@ -173,18 +143,22 @@ const TrafficDistributionForm: React.FC = () => { source: "", sourceIcon: "", description: "", - distributeType: distributeType, - maxPerDay: maxPerDay, - timeType: timeType, + distributeType: formValues.distributeType, + maxPerDay: formValues.maxPerDay, + timeType: formValues.timeType, startTime: - timeType === 2 && timeRange?.[0] ? timeRange[0].format("HH:mm") : "", + formValues.timeType === 2 && formValues.timeRange?.[0] + ? formValues.timeRange[0].format("HH:mm") + : "", endTime: - timeType === 2 && timeRange?.[1] ? timeRange[1].format("HH:mm") : "", - deviceGroups: deviceGroups, + formValues.timeType === 2 && formValues.timeRange?.[1] + ? formValues.timeRange[1].format("HH:mm") + : "", + deviceGroups: deviceGroupsOptions.map(v => v.id), deviceGroupsOptions: deviceGroupsOptions, - accountGroups: accountGroups, + accountGroups: accountGroupsOptions.map(v => v.id), accountGroupsOptions: accountGroupsOptions, - pools: selectedPools, + poolGroups: poolGroupsOptions.map(v => v.id), enabled: true, }; @@ -216,15 +190,26 @@ const TrafficDistributionForm: React.FC = () => { .catch(() => { // 验证失败,不进行下一步 }); + } else if (current === 1) { + // 第二步:目标设置至少需要选择设备或客服之一 + const hasDevice = + Array.isArray(selectedDevices) && selectedDevices.length > 0; + if (!hasDevice) { + message.error("请至少选择一个设备"); + return; + } + setCurrent(cur => cur + 1); } else { setCurrent(cur => cur + 1); } }; const prev = () => setCurrent(cur => cur - 1); - // 过滤流量池 - const filteredPools = poolList.filter(pool => pool.name.includes(poolSearch)); + const handPoolAction = params => { + setPoolGroupsOptions(params); + }; + // 移除未使用的输入同步函数 return ( { >
- {current === 0 && ( -
+
基本信息
+ -
基本信息
+ +
+ + + + 均分配 + + (流量将均分分配给所有客服) + + + + 优先级分配 + + (按客服优先级顺序分配) + + + + 比例分配 + (按设置比例分配流量) + + + + +
+ 每日最大分配量 + + {maxPerDay || 0} 人/天 + +
- + - - setDistributeType(e.target.value)} - className={style.radioGroup} - > - - 均分配 - - (流量将均分分配给所有客服) - - - - 优先级分配 - - (按客服优先级顺序分配) - - - - 比例分配 - - (按设置比例分配流量) - - - - - -
- 每日最大分配量 - {maxPerDay} 人/天 -
- 限制每天最多分配的流量数量
+ + + + 全天分配 + 自定义时间段 + + + {timeType === 2 && ( + ({ + validator(_, value) { + if (getFieldValue("timeType") === 1) { + return Promise.resolve(); + } + if (value && value.length === 2) { + return Promise.resolve(); + } + return Promise.reject(new Error("请选择开始和结束时间")); + }, + }), + ]} + > + -
- 限制每天最多分配的流量数量 -
- - setTimeType(e.target.value)} - className={style.radioGroup} - > - 全天分配 - 自定义时间段 - - - {timeType === 2 && ( - -
-
- 开始时间 - setTimeRange([v, timeRange?.[1]])} - /> -
-
- 结束时间 - setTimeRange([timeRange?.[0], v])} - /> -
-
-
- )} - - )} + )} + +
客服选择
+
+ { + setAccountGroupsOptions(accounts); + }} + placeholder="请选择客服" + showSelectedList={true} + selectedListMaxHeight={300} + accountGroups={accountGroups} + /> +
+ {current === 1 && (
目标设置
- - {/* Tab 切换 */} -
-
-
setTargetSelectionTab("device")} - > - 设备选择 -
-
setTargetSelectionTab("account")} - > - 客服选择 -
-
-
- - {/* Tab 内容 */} -
- {targetSelectionTab === "device" && ( -
- { - setSelectedDevices(devices); - setDeviceGroupsOptions(devices); - }} - placeholder="请选择设备" - showSelectedList={true} - selectedListMaxHeight={300} - deviceGroups={deviceGroups} - /> -
- )} - {targetSelectionTab === "account" && ( -
- { - setSelectedAccounts(accounts); - setAccountGroupsOptions(accounts); - }} - placeholder="请选择客服" - showSelectedList={true} - selectedListMaxHeight={300} - accountGroups={accountGroups} - /> -
- )} +
+ { + setSelectedDevices(devices); + setDeviceGroupsOptions(devices); + }} + placeholder="请选择设备" + showSelectedList={true} + selectedListMaxHeight={300} + deviceGroups={deviceGroups} + />
)} {current === 2 && ( -
-
流量池选择
-
- setPoolSearch(e.target.value)} - style={{ marginBottom: 12 }} - /> -
- {filteredPools.map(pool => ( - - ))} -
-
- 已选流量池:{selectedPools.length} 个 -
-
-
+ )}
diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/api.ts b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/api.ts index 67d4ba32..fddb19bc 100644 --- a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/api.ts +++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/api.ts @@ -24,7 +24,7 @@ export function toggleDistributionRuleStatus( // 删除计划 export function deleteDistributionRule(id: number): Promise { - return request("/v1/workbench/delete", { id }, "POST"); + return request("/v1/workbench/delete", { id }, "DELETE"); } // 获取流量分发规则详情 diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/data.ts b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/data.ts index f9c7a478..d7826493 100644 --- a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/data.ts +++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/data.ts @@ -113,7 +113,7 @@ export interface DistributionRule { endTime: string; account: (string | number)[]; devices: string[]; - pools: string[]; + poolGroups: string[]; exp: number; createTime: string; updateTime: string; diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.tsx b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.tsx index f94f54ba..1a220b6f 100644 --- a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.tsx +++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.tsx @@ -272,7 +272,7 @@ const TrafficDistributionList: React.FC = () => { onClick={() => showPoolList(item)} >
- {item.config?.pools?.length || 0} + {item.config?.poolGroups?.length || 0}
流量池
diff --git a/Server/application/ai/controller/DouBaoAI.php b/Server/application/ai/controller/DouBaoAI.php index 18012dbb..e7a50646 100644 --- a/Server/application/ai/controller/DouBaoAI.php +++ b/Server/application/ai/controller/DouBaoAI.php @@ -28,32 +28,25 @@ class DouBaoAI } - public function text() + + public function text($params = []) { $this->__init(); - - $content = input('content',''); - if (empty($content)){ + if (empty($params)){ return json_encode(['code' => 500, 'msg' => '提示词缺失']); } - - // 发送请求 - $params = [ - 'model' => 'doubao-1-5-pro-32k-250115', - 'messages' => [ - ['role' => 'system', 'content' => '你是人工智能助手.'], - ['role' => 'user', 'content' => $content], - ], - /*'extra_headers' => [ - 'x-is-encrypted' => true - ], - 'temperature' => 1, - 'top_p' => 0.7, - 'max_tokens' => 4096, - 'frequency_penalty' => 0,*/ - ]; $result = requestCurl($this->apiUrl, $params, 'POST', $this->headers, 'json'); $result = json_decode($result, true); - return successJson($result); + if(isset($result['error'])){ + $error = $result['error']; + return json_encode(['code' => 500, 'msg' => $error['message']]); + }else{ + $content = $result['choices'][0]['message']['content']; + $token = intval($result['usage']['total_tokens']) * 20; + return json_encode(['code' => 200, 'msg' => '成功','data' => ['token' => $token,'content' => $content]]); + } + } + + } \ No newline at end of file diff --git a/Server/application/chukebao/config/route.php b/Server/application/chukebao/config/route.php index 1384ac63..090ddec1 100644 --- a/Server/application/chukebao/config/route.php +++ b/Server/application/chukebao/config/route.php @@ -16,6 +16,7 @@ Route::group('v1/', function () { //群相关 Route::group('wechatChatroom/', function () { Route::get('list', 'app\chukebao\controller\WechatChatroomController@getList'); // 获取好友列表 + Route::post('aiAnnouncement', 'app\chukebao\controller\WechatChatroomController@aiAnnouncement'); // AI群公告 }); //客服相关 @@ -26,8 +27,62 @@ Route::group('v1/', function () { //客服相关 Route::group('message/', function () { Route::get('list', 'app\chukebao\controller\MessageController@getList'); // 获取好友列表 + Route::get('readMessage', 'app\chukebao\controller\MessageController@readMessage'); // 读取消息 + Route::get('details', 'app\chukebao\controller\MessageController@details'); // 消息详情 }); + //AI相关 + Route::group('ai/', function () { + //问答 + Route::group('questions/', function () { + Route::get('list', 'app\chukebao\controller\QuestionsController@getList'); // 问答列表 + Route::post('add', 'app\chukebao\controller\QuestionsController@create'); // 问答添加 + Route::post('update', 'app\chukebao\controller\QuestionsController@update'); // 问答更新 + Route::get('delete', 'app\chukebao\controller\QuestionsController@delete'); // 问答删除 + Route::get('detail', 'app\chukebao\controller\QuestionsController@detail'); // 问答详情 + }); + + //全局配置 + Route::group('settings/', function () { + Route::get('get', 'app\chukebao\controller\AiSettingsController@getSetting'); + Route::post('set', 'app\chukebao\controller\AiSettingsController@setSetting'); + }); + + //好友配置 + Route::group('friend/', function () { + Route::post('set', 'app\chukebao\controller\AiSettingsController@setFriend'); + Route::get('get', 'app\chukebao\controller\AiSettingsController@getFriend'); + Route::post('setAll', 'app\chukebao\controller\AiSettingsController@setAllFriend'); + }); + + + //ai对话 + Route::get('getUserTokens', 'app\chukebao\controller\AiSettingsController@getUserTokens'); + Route::post('chat', 'app\chukebao\controller\AiChatController@index'); + + }); + + + //代办事项 + Route::group('todo/', function () { + Route::get('list', 'app\chukebao\controller\ToDoController@getList'); + Route::post('add', 'app\chukebao\controller\ToDoController@create'); + Route::get('process', 'app\chukebao\controller\ToDoController@process'); + }); + + + //跟进提醒 + Route::group('followUp/', function () { + Route::get('list', 'app\chukebao\controller\FollowUpController@getList'); + Route::post('add', 'app\chukebao\controller\FollowUpController@create'); + Route::get('process', 'app\chukebao\controller\FollowUpController@process'); + }); + + + //算力相关 + Route::group('tokensRecord/', function () { + Route::get('list', 'app\chukebao\controller\TokensRecordController@getList'); + }); }); diff --git a/Server/application/chukebao/controller/AiChatController.php b/Server/application/chukebao/controller/AiChatController.php new file mode 100644 index 00000000..c488a1ad --- /dev/null +++ b/Server/application/chukebao/controller/AiChatController.php @@ -0,0 +1,106 @@ +getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + $friendId = $this->request->param('friendId', ''); + $wechatAccountId = $this->request->param('wechatAccountId', ''); + $content = $this->request->param('content', ''); + + if (empty($wechatAccountId) || empty($friendId)){ + return ResponseHelper::error('参数缺失'); + } + + $tokens = Db::name('users') + ->where('id', $userId) + ->where('companyId', $companyId) + ->value('tokens'); + if ($tokens <= 0){ + return ResponseHelper::error('用户Tokens余额不足'); + } + + + //读取AI配置 + $setting = Db::name('ai_settings')->where(['companyId' => $companyId,'userId' => $userId])->find(); + if(empty($setting)){ + return ResponseHelper::error('未找到配置信息,请先配置AI策略'); + } + $config = json_decode($setting['config'],true); + $modelSetting = $config['modelSetting']; + $round = isset($config['round']) ? $config['round'] : 10; + + + // 导出聊天 + $messages = Db::table('s2_wechat_message') + ->where('wechatFriendId', $friendId) + ->order('wechatTime desc') + ->field('id,content,msgType,isSend,wechatTime') + ->limit($round) + ->select(); + + usort($messages, function($a, $b) { + return $a['wechatTime'] <=> $b['wechatTime']; + }); + + //处理聊天数据 + $msg = []; + foreach ($messages as $val){ + if (empty($val['content'])){ + continue; + } + if (!empty($val['isSend'])){ + $msg[] = '客服:' . $val['content']; + }else{ + $msg[] = '用户:' . $val['content']; + } + } + $content = implode("\n", $msg); + + + $params = [ + 'model' => 'doubao-1-5-pro-32k-250115', + 'messages' => [ + // ['role' => 'system', 'content' => '请完成跟客户的对话'], + ['role' => 'system', 'content' => '角色设定:' . $modelSetting['role']], + ['role' => 'system', 'content' => '公司背景:' . $modelSetting['businessBackground']], + ['role' => 'system', 'content' => '对话风格:' . $modelSetting['dialogueStyle']], + ['role' => 'user', 'content' => $content], + ], + ]; + + //AI处理 + $ai = new DouBaoAI(); + $res = $ai->text($params); + $res = json_decode($res,true); + + if ($res['code'] == 200) { + //扣除Tokens + $tokensRecord = new tokensRecord(); + $nickname = Db::table('s2_wechat_friend')->where(['id' => $friendId])->value('nickname'); + $remarks = !empty($nickname) ? '与好友【'.$nickname.'】聊天' : '与好友聊天'; + $data = [ + 'tokens' => $res['data']['token'], + 'type' => 0, + 'form' => 1, + 'wechatAccountId' => $wechatAccountId, + 'friendIdOrGroupId' => $friendId, + 'remarks' => $remarks, + ]; + $tokensRecord->consumeTokens($data); + return ResponseHelper::success($res['data']['content']); + }else{ + return ResponseHelper::error($res['msg']); + } + + + } +} \ No newline at end of file diff --git a/Server/application/chukebao/controller/AiSettingsController.php b/Server/application/chukebao/controller/AiSettingsController.php new file mode 100644 index 00000000..e9c9b1ae --- /dev/null +++ b/Server/application/chukebao/controller/AiSettingsController.php @@ -0,0 +1,270 @@ + false, + 'round' => 10, + 'aiStopSetting' => [ + 'status' => true, + 'key' => ['好', '不错', '好的', '下次', '可以'] + ], + 'fileSetting' => [ + 'type' => 1, + 'content' => '' + ], + 'modelSetting' => [ + 'model' => 'GPT-4', + 'role' => '你是一名销售的AI助理,同时也是一个工智能技术专家,你的名字叫小灵,你是单身女性,出生于2003年10月10日,喜欢听音乐和看电影有着丰富的人生阅历,前成熟大方,分享用幽默风趣的语言和客户交流,顾客问起你的感情,回复内容中不要使用号,特别注意不要跟客户问题,不要更多选择发送的信息。', + 'businessBackground' => '灵销智能公司开发了多款AI营销智能技术产品,以提升销售GPT AI大模型为核心,接入打造的销售/营销/客服等AI智能应用,为企业AI办公,AI助理,AI销售,AI营销,AI直播等大AI应用产品。', + 'dialogueStyle' => '客户:你们的AI解决方案具体是怎么收费的?销售:嗯,朋友,我们的AI解决方案是根据项目需求来定的,这样吧,你能跟我说说你们的具体情况吗,不过这样一分钱,您看怎么样?我们可以给您做个详细的方案对比。', + ] + ]; + + const TYPE_DATA = ['audioSetting', 'round', 'aiStopSetting', 'fileSetting', 'modelSetting']; + + /** + * 获取配置信息 + * @return \think\response\Json + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ + public function getSetting() + { + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + $data = Db::name('ai_settings')->where(['userId' => $userId, 'companyId' => $companyId])->find(); + if (empty($data)) { + $setting = self::SETTING_DEFAULT; + $data = [ + 'companyId' => $companyId, + 'userId' => $userId, + 'config' => json_encode($setting, 256), + 'createTime' => time(), + 'updateTime' => time() + ]; + Db::name('ai_settings')->insert($data); + + } else { + $setting = json_decode($data['config'], true); + } + + return ResponseHelper::success($setting, '获取成功'); + } + + + /** + * 配置 + * @return \think\response\Json + * @throws \Exception + */ + public function setSetting() + { + $key = $this->request->param('key', ''); + $value = $this->request->param('value', ''); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($key) || empty($value)) { + return ResponseHelper::error('参数缺失'); + } + + + if (!in_array($key, self::TYPE_DATA)) { + return ResponseHelper::error('该类型不在配置项'); + } + + Db::startTrans(); + try { + $data = Db::name('ai_settings')->where(['userId' => $userId, 'companyId' => $companyId])->find(); + if (empty($data)) { + $setting = self::SETTING_DEFAULT; + } else { + $setting = json_decode($data['config'], true); + } + $setting[$key] = $value; + $setting = json_encode($setting, 256); + Db::name('ai_settings')->where(['id' => $data['id']])->update(['config' => $setting, 'updateTime' => time()]); + Db::commit(); + return ResponseHelper::success(' ', '配置成功'); + } catch (\Exception $e) { + Db::rollback(); + return ResponseHelper::error('配置失败:' . $e->getMessage()); + } + } + + + public function getUserTokens() + { + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + $tokens = Db::name('users') + ->where('id', $userId) + ->where('companyId', $companyId) + ->value('tokens'); + + return ResponseHelper::success($tokens, '获取成功'); + } + + + + public function getFriend() + { + $friendId = $this->request->param('friendId', ''); + $wechatAccountId = $this->request->param('wechatAccountId', ''); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + $aiType = AiFriendSettings::where(['userId' => $userId, 'companyId' => $companyId,'friendId' => $friendId,'wechatAccountId' => $wechatAccountId])->value('type'); + if (empty($aiType)) { + $aiType = 0; + } + return ResponseHelper::success($aiType, '获取成功'); + } + + + + + + public function setFriend() + { + $friendId = $this->request->param('friendId', ''); + $wechatAccountId = $this->request->param('wechatAccountId', ''); + $type = $this->request->param('type', 0); + + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($friendId) || empty($wechatAccountId)) { + return ResponseHelper::error('参数缺失'); + } + $friend = Db::table('s2_wechat_friend')->where(['id' => $friendId,'wechatAccountId' => $wechatAccountId])->find(); + + if (empty($friend)) { + return ResponseHelper::error('该好友不存在'); + } + + $aiFriendSettings = AiFriendSettings::where(['userId' => $userId, 'companyId' => $companyId,'friendId' => $friendId,'wechatAccountId' => $wechatAccountId])->find(); + Db::startTrans(); + try { + if (empty($aiFriendSettings)) { + $aiFriendSettings = new AiFriendSettings(); + $aiFriendSettings->companyId = $companyId; + $aiFriendSettings->userId = $userId; + $aiFriendSettings->type = $type; + $aiFriendSettings->wechatAccountId = $wechatAccountId; + $aiFriendSettings->friendId = $friendId; + $aiFriendSettings->createTime = time(); + $aiFriendSettings->updateTime = time(); + }else{ + $aiFriendSettings->type = $type; + $aiFriendSettings->updateTime = time(); + } + $aiFriendSettings->save(); + Db::commit(); + return ResponseHelper::success(' ', '配置成功'); + } catch (\Exception $e) { + Db::rollback(); + return ResponseHelper::error('配置失败:' . $e->getMessage()); + } + + } + + + + + public function setAllFriend() + { + $packageId = $this->request->param('packageId', []); + $type = $this->request->param('type', 0); + $isUpdata = $this->request->param('isUpdata', 0); + + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($packageId)) { + return ResponseHelper::error('参数缺失'); + } + //列出所有好友 + $row = Db::name('traffic_source_package_item')->alias('a') + ->join('wechat_friendship f','a.identifier = f.wechatId and f.companyId = '.$companyId) + ->join(['s2_wechat_account' => 'wa'],'f.ownerWechatId = wa.wechatId') + ->whereIn('a.packageId' , $packageId) + ->field('f.id as friendId,wa.id as wechatAccountId') + ->group('f.id') + ->select(); + + if (empty($row)) { + return ResponseHelper::error('`好友不存在'); + } + + + + + + + // 1000条为一组进行批量处理 + $batchSize = 1000; + $totalRows = count($row); + + for ($i = 0; $i < $totalRows; $i += $batchSize) { + $batchRows = array_slice($row, $i, $batchSize); + if (!empty($batchRows)) { + // 1. 提取当前批次的phone + $friendIds = array_column($batchRows, 'friendId'); + // 2. 批量查询已存在的phone + $existingPhones = []; + if (!empty($friendIds)) { + //强制更新 + if(!empty($isUpdata)){ + Db::name('ai_friend_settings')->whereIn('friendId',$friendIds)->update(['type' => $type,'updateTime' => time()]); + } + + $existing = Db::name('ai_friend_settings') + ->where('companyId', $companyId) + ->where('friendId', 'in', $friendIds) + ->field('friendId') + ->select(); + $existingPhones = array_column($existing, 'friendId'); + } + + // 3. 过滤出新数据,批量插入 + $newData = []; + foreach ($batchRows as $row) { + if (!empty($friendIds) && !in_array($row['friendId'], $existingPhones)) { + $newData[] = [ + 'companyId' => $companyId, + 'userId' => $userId, + 'type' => $type, + 'wechatAccountId' => $row['wechatAccountId'], + 'friendId' => $row['friendId'], + 'createTime' => time(), + 'updateTime' => time(), + ]; + } + } + // 4. 批量插入新数据 + if (!empty($newData)) { + Db::name('ai_friend_settings')->insertAll($newData); + } + } + } + try { + return ResponseHelper::success(' ', '配置成功'); + } catch (\Exception $e) { + return ResponseHelper::error('配置失败:' . $e->getMessage()); + } + + } + +} \ No newline at end of file diff --git a/Server/application/chukebao/controller/FollowUpController.php b/Server/application/chukebao/controller/FollowUpController.php new file mode 100644 index 00000000..dbefba17 --- /dev/null +++ b/Server/application/chukebao/controller/FollowUpController.php @@ -0,0 +1,143 @@ +request->param('page', 1); + $limit = $this->request->param('limit', 10); + $keyword = $this->request->param('keyword', ''); + $isRemind = $this->request->param('isRemind', ''); + $isProcess = $this->request->param('isProcess', ''); + $type = $this->request->param('type', ''); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + + $where = [ + ['companyId','=',$companyId], + ['userId' ,'=', $userId] + ]; + + if ($isRemind != '') { + $where[] = ['isRemind','=',$isRemind]; + } + if ($type != '') { + $where[] = ['type','=',$type]; + } + if ($isProcess != '') { + $where[] = ['isProcess','=',$isProcess]; + } + + if(!empty($keyword)){ + $where[] = ['title|description','like','%'.$keyword.'%']; + } + + $query = FollowUp::where($where); + + $list = $query->where($where)->page($page,$limit)->order('id desc')->select(); + $total = $query->count(); + + foreach ($list as &$item) { + $nickname = Db::table('s2_wechat_friend')->where(['id' => $item['friendId']])->value('nickname'); + $item['nickname'] = !empty($nickname) ? $nickname : '-'; + $item['reminderTime'] = date('Y-m-d H:i:s',$item['reminderTime']); + } + unset($item); + + return ResponseHelper::success(['list'=>$list,'total'=>$total]); + } + + + /** + * 添加 + * @return \think\response\Json + * @throws \Exception + */ + public function create(){ + $type = $this->request->param('type', 0); + $title = $this->request->param('title', ''); + $reminderTime = $this->request->param('reminderTime', ''); + $description = $this->request->param('description', ''); + $friendId = $this->request->param('friendId', ''); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($title) || empty($reminderTime) || empty($description) || empty($friendId)){ + return ResponseHelper::error('参数缺失'); + } + $friend = Db::name('wechat_friendship')->where(['id' => $friendId,'companyId' => $companyId])->find(); + if (empty($friend)) { + return ResponseHelper::error('好友不存在'); + } + + + Db::startTrans(); + try { + $FollowUp = new FollowUp(); + $FollowUp->type = $type; + $FollowUp->title = $title; + $FollowUp->friendId = $friendId; + $FollowUp->reminderTime = !empty($reminderTime) ? strtotime($reminderTime) : time(); + $FollowUp->description = $description; + $FollowUp->userId = $userId; + $FollowUp->companyId = $companyId; + $FollowUp->updateTime = time(); + $FollowUp->createTime = time(); + $FollowUp->save(); + Db::commit(); + return ResponseHelper::success(' ','创建成功'); + } catch (\Exception $e) { + Db::rollback(); + return ResponseHelper::error('创建失败:'.$e->getMessage()); + } + } + + + /** + * 处理代办事项 + * @return \think\response\Json + * @throws \Exception + */ + public function process(){ + $ids = $this->request->param('ids',''); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($ids)){ + return ResponseHelper::error('参数缺失'); + } + $ids = explode(',',$ids); + + if (!is_array($ids)){ + return ResponseHelper::error('格式错误'); + } + + $FollowUpIds = FollowUp::where(['userId' => $userId,'companyId' => $companyId,'isProcess' => 0])->whereIn('id',$ids)->column('id'); + if (empty($FollowUpIds)){ + return ResponseHelper::error('代办事项不存在'); + } + + Db::startTrans(); + try { + FollowUp::whereIn('id',$FollowUpIds)->update(['isProcess' => 1,'isRemind' => 1,'updateTime' => time()]); + Db::commit(); + return ResponseHelper::success(' ','已处理'); + } catch (\Exception $e) { + Db::rollback(); + return ResponseHelper::error('处理失败:'.$e->getMessage()); + } + + + + + + } + +} \ No newline at end of file diff --git a/Server/application/chukebao/controller/LoginController.php b/Server/application/chukebao/controller/LoginController.php index 44a03338..832d055f 100644 --- a/Server/application/chukebao/controller/LoginController.php +++ b/Server/application/chukebao/controller/LoginController.php @@ -45,7 +45,9 @@ class LoginController extends Controller ->where(function ($query) use ($username) { $query->where('account', $username)->whereOr('phone', $username); }) - ->where('passwordMd5', md5($password)) + ->where(function ($query2) use ($password) { + $query2->where('passwordMd5', md5($password))->whereOr('passwordLocal', localEncrypt($password)); + }) ->find(); }else{ $user = $payload; @@ -84,9 +86,41 @@ class LoginController extends Controller $kefuData['self'] = $self; Db::name('users')->where('id', $user['id'])->update(['passwordLocal' => localEncrypt($params['password']),'updateTime' => time()]); }else{ - return ResponseHelper::error($result['error_description']); + $kefuData = [ + 'token' => [ + "access_token"=> "27gINKZqGux6V4j9QLawOcTKlWXg-j4zxQjKvScvDTq-YlLcwIrDP2AFaNZKnOo9zLzepOBC8qrdXh4z9GxxkwE9TKGRQI1FjITRlMZzrim13IbSEbJUoywGs_BhDmIZnnPhfjqxDB1vjZgVtT2Kp4bxbUCV3i2uO_FTv_DT2G7NUFFLjq8oIuUrd_c1YXeYkH8m8Fw1AM4yPZJZyfdaHSSMOpJ2Bk2LAghnB6OaZCYWNFQcwWARsmh1BSAANUOAoadjkztZC7Fme-GGOm2sLo0WL6Mf26NfeLmnkluewTiPMyacD7RYclAR2LZ_8Mhwr3pwRg", + "token_type"=> "bearer", + "expires_in"=> 195519999, + "refresh_token"=> "a9545daa-d1c4-4c87-8c4c-b713631d4f0d" + ], + 'self' => [ + 'account' => [ + "id"=> 5538, + "realName"=> "测试", + "nickname"=> "", + "memo"=> "", + "avatar"=> "", + "userName"=> "wz_02", + "secret"=> "8f6f743395ad4198b6a4c0e6ca0e452f", + "accountType"=> 10, + "departmentId"=> 2130, + "useGoogleSecretKey"=> false, + "hasVerifyGoogleSecret"=> true + ], + 'tenant' => [ + "id" => 242, + "name"=> "泉州市卡若网络技术有限公司", + "guid"=> "5E2C38F5A275450D935F3ECEC076124E", + "thirdParty"=> null, + "tenantType"=> 0, + "deployName"=> "deploy-s2" + ] + ] + ]; + //return ResponseHelper::error($result['error_description']); } + unset($user['passwordMd5'],$user['deleteTime']); $userData['member'] = $user; diff --git a/Server/application/chukebao/controller/MessageController.php b/Server/application/chukebao/controller/MessageController.php index c213b7e8..beffd1ed 100644 --- a/Server/application/chukebao/controller/MessageController.php +++ b/Server/application/chukebao/controller/MessageController.php @@ -53,6 +53,9 @@ class MessageController extends BaseController ->field('id,nickname,avatar') ->find(); $v['msgInfo'] = $friend; + $v['unreadCount'] = Db::table('s2_wechat_message') + ->where(['wechatFriendId' => $v['wechatFriendId'],'isRead' => 0]) + ->count(); } if (!empty($v['wechatChatroomId'])){ @@ -61,12 +64,87 @@ class MessageController extends BaseController ->field('id,nickname,chatroomAvatar as avatar') ->find(); $v['msgInfo'] = $chatroom; + $v['unreadCount'] = Db::table('s2_wechat_message') + ->where(['wechatChatroomId' => $v['wechatChatroomId'],'isRead' => 0]) + ->count(); } - } unset($v); return ResponseHelper::success($list); } + + + public function readMessage(){ + $wechatFriendId = $this->request->param('wechatFriendId', ''); + $wechatChatroomId = $this->request->param('wechatChatroomId', ''); + $accountId = $this->getUserInfo('s2_accountId'); + if (empty($accountId)){ + return ResponseHelper::error('请先登录'); + } + if (empty($wechatChatroomId) && empty($wechatFriendId)){ + return ResponseHelper::error('参数缺失'); + } + + $where = []; + if (!empty($wechatChatroomId)){ + $where[] = ['wechatChatroomId','=',$wechatChatroomId]; + } + + if (!empty($wechatFriendId)){ + $where[] = ['wechatFriendId','=',$wechatFriendId]; + } + + Db::table('s2_wechat_message')->where($where)->update(['isRead' => 1]); + return ResponseHelper::success([]); + } + + + + + public function details(){ + $wechatFriendId = $this->request->param('wechatFriendId', ''); + $wechatChatroomId = $this->request->param('wechatChatroomId', ''); + $wechatAccountId = $this->request->param('wechatAccountId', ''); + $page = $this->request->param('page', 1); + $limit = $this->request->param('limit', 10); + $from = $this->request->param('From', ''); + $to = $this->request->param('To', ''); + $olderData = $this->request->param('olderData', false); + $accountId = $this->getUserInfo('s2_accountId'); + if (empty($accountId)){ + return ResponseHelper::error('请先登录'); + } + if (empty($wechatChatroomId) && empty($wechatFriendId)){ + return ResponseHelper::error('参数缺失'); + } + + $where = []; + if (!empty($wechatChatroomId)){ + $where[] = ['wechatChatroomId','=',$wechatChatroomId]; + } + + if (!empty($wechatFriendId)){ + $where[] = ['wechatFriendId','=',$wechatFriendId]; + } + + if (!empty($From) && !empty($To)){ + $where[] = ['wechatTime','between',[$from,$to]]; + } + + + $list = Db::table('s2_wechat_message')->where($where)->page($page,$limit)->order('id DESC')->select(); + $total = Db::table('s2_wechat_message')->where($where)->count(); + + + foreach ($list as $k=>&$v){ + $v['wechatTime'] = !empty($v['wechatTime']) ? date('Y-m-d H:i:s',$v['wechatTime']) : ''; + } + + + return ResponseHelper::success(['total'=>$total,'list'=>$list]); + } + + } \ No newline at end of file diff --git a/Server/application/chukebao/controller/QuestionsController.php b/Server/application/chukebao/controller/QuestionsController.php new file mode 100644 index 00000000..9ee8799e --- /dev/null +++ b/Server/application/chukebao/controller/QuestionsController.php @@ -0,0 +1,232 @@ +request->param('page', 1); + $limit = $this->request->param('limit', 10); + $keyword = $this->request->param('keyword', ''); + $accountId = $this->getUserInfo('s2_accountId'); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($accountId)){ + return ResponseHelper::error('请先登录'); + } + $query = Questions::where(['userId' => $userId,'companyId' => $companyId,'isDel' => 0]) + ->order('id desc'); + if (!empty($keyword)){ + $query->where('questions|answers', 'like', '%'.$keyword.'%'); + } + $list = $query->page($page, $limit)->select()->toArray(); + $total = $query->count(); + + foreach ($list as $k => &$v){ + $user = Db::name('users')->where(['id' => $v['userId']])->field('username,account')->find(); + if (!empty($user)){ + $v['userName'] = !empty($user['username']) ? $user['username'] : $user['account']; + }else{ + $v['userName'] = ''; + } + $v['answers'] = json_decode($v['answers'],true); + } + unset($v); + return ResponseHelper::success(['list'=>$list,'total'=>$total]); + } + + + /** + * 新增 + * @return \think\response\Json + * @throws \Exception + */ + public function create(){ + + $type = $this->request->param('type', 0); + $questions = $this->request->param('questions', ''); + $answers = $this->request->param('answers', []); + $status = $this->request->param('status', 0); + $accountId = $this->getUserInfo('s2_accountId'); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($accountId)){ + return ResponseHelper::error('请先登录'); + } + + if (empty($questions) || empty($answers)){ + return ResponseHelper::error('问题和答案不能为空'); + } + + Db::startTrans(); + try { + $questionsModel = new Questions(); + $questionsModel->type = $type; + $questionsModel->questions = $questions; + $questionsModel->answers = !empty($answers) ? json_encode($answers,256) : json_encode([],256); + $questionsModel->status = $status; + $questionsModel->accountId = $accountId; + $questionsModel->userId = $userId; + $questionsModel->companyId = $companyId; + $questionsModel->createTime = time(); + $questionsModel->updateTime = time(); + $questionsModel->save(); + Db::commit(); + return ResponseHelper::success(' ','创建成功'); + } catch (\Exception $e) { + Db::rollback(); + return ResponseHelper::error('创建失败:'.$e->getMessage()); + } + } + + + /** + * 更新 + * @return \think\response\Json + * @throws \Exception + */ + public function update(){ + + $id = $this->request->param('id', 0); + $accountId = $this->getUserInfo('s2_accountId'); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + $type = $this->request->param('type', 0); + $questions = $this->request->param('questions', ''); + $answers = $this->request->param('answers', []); + $status = $this->request->param('status', 0); + $accountId = $this->getUserInfo('s2_accountId'); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($accountId)){ + return ResponseHelper::error('请先登录'); + } + + if (empty($id)){ + return ResponseHelper::error('参数缺失'); + } + + if (empty($questions) || empty($answers)){ + return ResponseHelper::error('问题和答案不能为空'); + } + Db::startTrans(); + try { + $questionsData = Questions::where(['id' => $id,'userId' => $userId,'companyId' => $companyId,'isDel' => 0])->find(); + $questionsData->type = $type; + $questionsData->questions = $questions; + $questionsData->answers = !empty($answers) ? json_encode($answers,256) : json_encode([],256); + $questionsData->status = $status; + $questionsData->accountId = $accountId; + $questionsData->userId = $userId; + $questionsData->companyId = $companyId; + $questionsData->updateTime = time(); + $questionsData->save(); + Db::commit(); + return ResponseHelper::success(' ','更新成功'); + } catch (\Exception $e) { + Db::rollback(); + return ResponseHelper::error('更新失败:'.$e->getMessage()); + } + } + + + + + + /** + * 删除 + * @return \think\response\Json + * @throws \Exception + */ + public function delete(){ + + $id = $this->request->param('id', 0); + $accountId = $this->getUserInfo('s2_accountId'); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($accountId)){ + return ResponseHelper::error('请先登录'); + } + + if (empty($id)){ + return ResponseHelper::error('参数缺失'); + } + $questions = Questions::where(['id' => $id,'userId' => $userId,'companyId' => $companyId,'isDel' => 0])->find(); + + if (empty($questions)){ + return ResponseHelper::error('该问题不存在或者已删除'); + } + $res = Questions::where(['id' => $id])->update(['isDel' => 1,'deleteTime' => time()]); + + if (!empty($res)){ + return ResponseHelper::success('','已删除'); + }else{ + return ResponseHelper::error('删除失败'); + } + + } + + + /** + * 详情 + * @return \think\response\Json + * @throws \Exception + */ + public function detail(){ + + $id = $this->request->param('id', 0); + $accountId = $this->getUserInfo('s2_accountId'); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($accountId)){ + return ResponseHelper::error('请先登录'); + } + + if (empty($id)){ + return ResponseHelper::error('参数缺失'); + } + $questions = Questions::where(['id' => $id,'userId' => $userId,'companyId' => $companyId,'isDel' => 0])->find(); + + if (empty($questions)){ + return ResponseHelper::error('该问题不存在或者已删除'); + } + + $questions['answers'] = json_decode($questions['answers'],true); + $user = Db::name('users')->where(['id' => $questions['userId']])->field('username,account')->find(); + if (!empty($user)){ + $questions['userName'] = !empty($user['username']) ? $user['username'] : $user['account']; + }else{ + $questions['userName'] = ''; + } + + unset( + $questions['isDel'], + $questions['deleteTime'], + $questions['createTime'], + $questions['updateTime'] + ); + + return ResponseHelper::success($questions,'获取成功'); + + + } + + + + +} \ No newline at end of file diff --git a/Server/application/chukebao/controller/ToDoController.php b/Server/application/chukebao/controller/ToDoController.php new file mode 100644 index 00000000..c71ab30b --- /dev/null +++ b/Server/application/chukebao/controller/ToDoController.php @@ -0,0 +1,143 @@ +request->param('page', 1); + $limit = $this->request->param('limit', 10); + $keyword = $this->request->param('keyword', ''); + $isRemind = $this->request->param('isRemind', ''); + $isProcess = $this->request->param('isProcess', ''); + $level = $this->request->param('level', ''); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + + $where = [ + ['companyId','=',$companyId], + ['userId' ,'=', $userId] + ]; + + if ($isRemind != '') { + $where[] = ['isRemind','=',$isRemind]; + } + if ($level != '') { + $where[] = ['level','=',$level]; + } + if ($isProcess != '') { + $where[] = ['isProcess','=',$isProcess]; + } + + if(!empty($keyword)){ + $where[] = ['title|description','like','%'.$keyword.'%']; + } + + $query = ToDo::where($where); + + $list = $query->where($where)->page($page,$limit)->order('id desc')->select(); + $total = $query->count(); + + foreach ($list as &$item) { + $nickname = Db::table('s2_wechat_friend')->where(['id' => $item['friendId']])->value('nickname'); + $item['nickname'] = !empty($nickname) ? $nickname : '-'; + $item['reminderTime'] = date('Y-m-d H:i:s',$item['reminderTime']); + } + unset($item); + + return ResponseHelper::success(['list'=>$list,'total'=>$total]); + } + + + /** + * 添加 + * @return \think\response\Json + * @throws \Exception + */ + public function create(){ + $level = $this->request->param('level', 0); + $title = $this->request->param('title', ''); + $reminderTime = $this->request->param('reminderTime', ''); + $description = $this->request->param('description', ''); + $friendId = $this->request->param('friendId', ''); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($title) || empty($reminderTime) || empty($description) || empty($friendId)){ + return ResponseHelper::error('参数缺失'); + } + $friend = Db::name('wechat_friendship')->where(['id' => $friendId,'companyId' => $companyId])->find(); + if (empty($friend)) { + return ResponseHelper::error('好友不存在'); + } + + + Db::startTrans(); + try { + $todo = new ToDo(); + $todo->level = $level; + $todo->title = $title; + $todo->friendId = $friendId; + $todo->reminderTime = !empty($reminderTime) ? strtotime($reminderTime) : time(); + $todo->description = $description; + $todo->userId = $userId; + $todo->companyId = $companyId; + $todo->updateTime = time(); + $todo->createTime = time(); + $todo->save(); + Db::commit(); + return ResponseHelper::success(' ','创建成功'); + } catch (\Exception $e) { + Db::rollback(); + return ResponseHelper::error('创建失败:'.$e->getMessage()); + } + } + + + /** + * 处理代办事项 + * @return \think\response\Json + * @throws \Exception + */ + public function process(){ + $ids = $this->request->param('ids',''); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + if (empty($ids)){ + return ResponseHelper::error('参数缺失'); + } + $ids = explode(',',$ids); + + if (!is_array($ids)){ + return ResponseHelper::error('格式错误'); + } + + $todoIds = ToDo::where(['userId' => $userId,'companyId' => $companyId,'isProcess' => 0])->whereIn('id',$ids)->column('id'); + if (empty($todoIds)){ + return ResponseHelper::error('代办事项不存在'); + } + + Db::startTrans(); + try { + ToDo::whereIn('id',$todoIds)->update(['isProcess' => 1,'isRemind' => 1,'updateTime' => time()]); + Db::commit(); + return ResponseHelper::success(' ','已处理'); + } catch (\Exception $e) { + Db::rollback(); + return ResponseHelper::error('处理失败:'.$e->getMessage()); + } + + + + + + } + +} \ No newline at end of file diff --git a/Server/application/chukebao/controller/TokensRecordController.php b/Server/application/chukebao/controller/TokensRecordController.php new file mode 100644 index 00000000..deb8882d --- /dev/null +++ b/Server/application/chukebao/controller/TokensRecordController.php @@ -0,0 +1,179 @@ +request->param('page', 1); + $limit = $this->request->param('limit', 10); + $type = $this->request->param('type', ''); + $form = $this->request->param('form', ''); + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + + + $where = [ + ['companyId','=',$companyId], + ['userId' ,'=', $userId] + ]; + + if ($type != '') { + $where[] = ['type','=',$type]; + } + if ($form != '') { + $where[] = ['form','=',$form]; + } + + + $query = TokensRecord::where($where); + + $list = $query->where($where)->page($page,$limit)->order('id desc')->select(); + $total = $query->count(); + + foreach ($list as &$item) { + if (in_array($item['type'],[1])){ + $nickname = Db::table('s2_wechat_friend')->where(['id' => $item['friendIdOrGroupId']])->value('nickname'); + $item['nickname'] = !empty($nickname) ? $nickname : '-'; + } + if (in_array($item['type'],[2,3])){ + $nickname = Db::table('s2_wechat_chatroom')->where(['id' => $item['friendIdOrGroupId']])->value('nickname'); + $item['nickname'] = !empty($nickname) ? $nickname : '-'; + } + } + unset($item); + + return ResponseHelper::success(['list'=>$list,'total'=>$total]); + } + + + public function consumeTokens($data = []) + { + if (empty($data)){ + return ResponseHelper::error('数据缺失'); + } + + $tokens = isset($data['tokens']) ? intval($data['tokens']) : 0; + $type = isset($data['type']) ? intval($data['type']) : 0; + $form = isset($data['form']) ? intval($data['form']) : 0; + $wechatAccountId = isset($data['wechatAccountId']) ? intval($data['wechatAccountId']) : 0; + $friendIdOrGroupId = isset($data['friendIdOrGroupId']) ? intval($data['friendIdOrGroupId']) : 0; + $remarks = isset($data['remarks']) ? $data['remarks'] : ''; + $companyId = isset($data['companyId']) ? intval($data['companyId']) : $this->getUserInfo('companyId'); + $userId = isset($data['userId']) ? intval($data['userId']) : $this->getUserInfo('id'); + + // 验证必要参数 + if ($tokens <= 0) { + return ResponseHelper::error('tokens数量必须大于0'); + } + + if (!in_array($type, [0, 1])) { + return ResponseHelper::error('类型参数错误,0为减少,1为增加'); + } + + if (!in_array($form, [0, 1, 2, 3, 4, 5])) { + return ResponseHelper::error('来源参数错误'); + } + + // 重试机制,最多重试3次 + $maxRetries = 3; + $retryCount = 0; + while ($retryCount < $maxRetries) { + try { + return $this->doConsumeTokens($userId, $companyId, $tokens, $type, $form, $wechatAccountId, $friendIdOrGroupId, $remarks); + } catch (\Exception $e) { + $retryCount++; + if ($retryCount >= $maxRetries) { + return ResponseHelper::error('操作失败,请稍后重试:' . $e->getMessage()); + } + // 短暂延迟后重试 + usleep(100000); // 100ms + } + } + } + + /** + * 执行tokens消费的核心方法 + */ + private function doConsumeTokens($userId, $companyId, $tokens, $type, $form, $wechatAccountId, $friendIdOrGroupId, $remarks) + { + // 开启数据库事务 + Db::startTrans(); + try { + // 使用悲观锁获取用户当前tokens余额,确保并发安全 + $userInfo = Db::name('users') + ->where('id', $userId) + ->where('companyId', $companyId) + ->lock(true) // 悲观锁,防止并发问题 + ->find(); + + if (!$userInfo) { + throw new \Exception('用户不存在'); + } + + $currentTokens = intval($userInfo['tokens']); + + // 计算新的余额 + $newBalance = $type == 1 ? ($currentTokens + $tokens) : ($currentTokens - $tokens); + + // 使用原子更新操作,基于当前值进行更新,防止并发覆盖 + $updateResult = Db::name('users') + ->where('id', $userId) + ->where('companyId', $companyId) + ->where('tokens', $currentTokens) // 确保基于当前值更新 + ->update([ + 'tokens' => $newBalance, + 'updateTime' => time() + ]); + + if (!$updateResult) { + // 如果更新失败,说明tokens值已被其他事务修改,需要重新获取 + throw new \Exception('tokens余额已被其他操作修改,请重试'); + } + + // 记录tokens变动 + $recordData = [ + 'companyId' => $companyId, + 'userId' => $userId, + 'wechatAccountId' => $wechatAccountId, + 'friendIdOrGroupId' => $friendIdOrGroupId, + 'form' => $form, + 'type' => $type, + 'tokens' => $tokens, + 'balanceTokens' => $newBalance, + 'remarks' => $remarks, + 'createTime' => time() + ]; + + $recordId = Db::name('tokens_record')->insertGetId($recordData); + + if (!$recordId) { + throw new \Exception('记录tokens变动失败'); + } + + // 提交事务 + Db::commit(); + + return ResponseHelper::success([ + 'recordId' => $recordId, + 'oldBalance' => $currentTokens, + 'newBalance' => $newBalance, + 'changeAmount' => $type == 1 ? $tokens : -$tokens + ], 'tokens变动记录成功'); + + } catch (\Exception $e) { + // 回滚事务 + Db::rollback(); + throw $e; // 重新抛出异常,让重试机制处理 + } + } + + + +} \ No newline at end of file diff --git a/Server/application/chukebao/controller/WechatChatroomController.php b/Server/application/chukebao/controller/WechatChatroomController.php index e6c64f5c..8753da88 100644 --- a/Server/application/chukebao/controller/WechatChatroomController.php +++ b/Server/application/chukebao/controller/WechatChatroomController.php @@ -2,6 +2,8 @@ namespace app\chukebao\controller; +use app\ai\controller\DouBaoAI; +use app\chukebao\controller\TokensRecordController as tokensRecord; use library\ResponseHelper; use think\Db; @@ -22,12 +24,121 @@ class WechatChatroomController extends BaseController $total = $query->count(); - foreach ($list as $k=>&$v){ - $v['createTime'] = !empty($v['createTime']) ? date('Y-m-d H:i:s',$v['createTime']) : ''; - $v['updateTime'] = !empty($v['updateTime']) ? date('Y-m-d H:i:s',$v['updateTime']) : ''; + // 提取所有聊天室ID,用于批量查询 + $chatroomIds = array_column($list, 'id'); + + + // 一次性查询所有聊天室的未读消息数量 + $unreadCounts = []; + if (!empty($chatroomIds)) { + $unreadResults = Db::table('s2_wechat_message') + ->field('wechatChatroomId, COUNT(*) as count') + ->where('wechatChatroomId', 'in', $chatroomIds) + ->where('isRead', 0) + ->group('wechatChatroomId') + ->select(); + + foreach ($unreadResults as $result) { + $unreadCounts[$result['wechatChatroomId']] = $result['count']; + } + } + // 一次性查询所有聊天室的最新消息 + $latestMessages = []; + if (!empty($chatroomIds)) { + // 使用子查询获取每个聊天室的最新消息ID + $subQuery = Db::table('s2_wechat_message') + ->field('MAX(id) as max_id, wechatChatroomId') + ->where('wechatChatroomId', 'in', $chatroomIds) + ->group('wechatChatroomId') + ->buildSql(); + + // 查询最新消息的详细信息 + $messageResults = Db::table('s2_wechat_message') + ->alias('m') + ->join([$subQuery => 'sub'], 'm.id = sub.max_id') + ->field('m.*, sub.wechatChatroomId') + ->select(); + + foreach ($messageResults as $message) { + $latestMessages[$message['wechatChatroomId']] = $message; + } + } + + // 处理每个聊天室的数据 + foreach ($list as $k => &$v) { + $v['createTime'] = !empty($v['createTime']) ? date('Y-m-d H:i:s', $v['createTime']) : ''; + $v['updateTime'] = !empty($v['updateTime']) ? date('Y-m-d H:i:s', $v['updateTime']) : ''; + + $config = [ + 'unreadCount' => isset($unreadCounts[$v['id']]) ? $unreadCounts[$v['id']] : 0, + 'chat' => isset($latestMessages[$v['id']]), + 'msgTime' => isset($latestMessages[$v['id']]) ? $latestMessages[$v['id']]['wechatTime'] : 0 + ]; + $v['config'] = $config; } unset($v); return ResponseHelper::success(['list'=>$list,'total'=>$total]); } + + + + public function aiAnnouncement() + { + $userId = $this->getUserInfo('id'); + $companyId = $this->getUserInfo('companyId'); + $wechatAccountId = $this->request->param('wechatAccountId', ''); + $groupId = $this->request->param('groupId', ''); + $content = $this->request->param('content', ''); + + if (empty($groupId) || empty($content)|| empty($wechatAccountId)){ + return ResponseHelper::error('参数缺失'); + } + + $tokens = Db::name('users') + ->where('id', $userId) + ->where('companyId', $companyId) + ->value('tokens'); + if ($tokens <= 0){ + return ResponseHelper::error('用户Tokens余额不足'); + } + + $params = [ + 'model' => 'doubao-1-5-pro-32k-250115', + 'messages' => [ + ['role' => 'system', 'content' => '你现在是存客宝的AI助理,你精通中国大陆的法律'], + ['role' => 'user', 'content' => $content], + ], + ]; + + //AI处理 + $ai = new DouBaoAI(); + $res = $ai->text($params); + $res = json_decode($res,true); + + + if ($res['code'] == 200) { + //扣除Tokens + $tokensRecord = new tokensRecord(); + $nickname = Db::table('s2_wechat_chatroom')->where(['id' => $groupId])->value('nickname'); + $remarks = !empty($nickname) ? '生成【'.$nickname.'】群公告' : '生成群公告'; + $data = [ + 'tokens' => $res['data']['token'], + 'type' => 0, + 'form' => 3, + 'wechatAccountId' => $wechatAccountId, + 'friendIdOrGroupId' => $groupId, + 'remarks' => $remarks, + ]; + $tokensRecord->consumeTokens($data); + return ResponseHelper::success($res['data']['content']); + }else{ + return ResponseHelper::error($res['msg']); + } + + + exit_data($res); + + } + } \ No newline at end of file diff --git a/Server/application/chukebao/controller/WechatFriendController.php b/Server/application/chukebao/controller/WechatFriendController.php index bd8f0095..f73a6ab8 100644 --- a/Server/application/chukebao/controller/WechatFriendController.php +++ b/Server/application/chukebao/controller/WechatFriendController.php @@ -22,10 +22,71 @@ class WechatFriendController extends BaseController $total = $query->count(); - foreach ($list as $k=>&$v){ - $v['createTime'] = !empty($v['createTime']) ? date('Y-m-d H:i:s',$v['createTime']) : ''; - $v['updateTime'] = !empty($v['updateTime']) ? date('Y-m-d H:i:s',$v['updateTime']) : ''; - $v['passTime'] = !empty($v['passTime']) ? date('Y-m-d H:i:s',$v['passTime']) : ''; + // 提取所有好友ID + $friendIds = array_column($list, 'id'); + + // 一次性查询所有好友的未读消息数量 + $unreadCounts = []; + if (!empty($friendIds)) { + $unreadResults = Db::table('s2_wechat_message') + ->field('wechatFriendId, COUNT(*) as count') + ->where('wechatFriendId', 'in', $friendIds) + ->where('isRead', 0) + ->group('wechatFriendId') + ->select(); + + foreach ($unreadResults as $result) { + $unreadCounts[$result['wechatFriendId']] = $result['count']; + } + } + + // 一次性查询所有好友的最新消息 + $latestMessages = []; + if (!empty($friendIds)) { + // 使用子查询获取每个好友的最新消息ID + $subQuery = Db::table('s2_wechat_message') + ->field('MAX(id) as max_id, wechatFriendId') + ->where('wechatFriendId', 'in', $friendIds) + ->group('wechatFriendId') + ->buildSql(); + + // 查询最新消息的详细信息 + $messageResults = Db::table('s2_wechat_message') + ->alias('m') + ->join([$subQuery => 'sub'], 'm.id = sub.max_id') + ->field('m.*, sub.wechatFriendId') + ->select(); + + foreach ($messageResults as $message) { + $latestMessages[$message['wechatFriendId']] = $message; + } + } + + + $aiTypeData = []; + if (!empty($friendIds)) { + $aiTypeData = Db::name('ai_friend_settings') + ->where('friendId', 'in', $friendIds) + ->column('friendId,type'); + } + + + // 处理每个好友的数据 + foreach ($list as $k => &$v) { + $v['createTime'] = !empty($v['createTime']) ? date('Y-m-d H:i:s', $v['createTime']) : ''; + $v['updateTime'] = !empty($v['updateTime']) ? date('Y-m-d H:i:s', $v['updateTime']) : ''; + $v['passTime'] = !empty($v['passTime']) ? date('Y-m-d H:i:s', $v['passTime']) : ''; + + + $config = [ + 'unreadCount' => isset($unreadCounts[$v['id']]) ? $unreadCounts[$v['id']] : 0, + 'chat' => isset($latestMessages[$v['id']]), + 'msgTime' => isset($latestMessages[$v['id']]) ? $latestMessages[$v['id']]['wechatTime'] : 0 + ]; + + // 将消息配置添加到好友数据中 + $v['config'] = $config; + $v['aiType'] = isset($aiTypeData[$v['id']]) ? $aiTypeData[$v['id']] : 0; } unset($v); diff --git a/Server/application/chukebao/model/AiFriendSettings.php b/Server/application/chukebao/model/AiFriendSettings.php new file mode 100644 index 00000000..de99b4a9 --- /dev/null +++ b/Server/application/chukebao/model/AiFriendSettings.php @@ -0,0 +1,17 @@ +setName('clean:expired_group_messages') + ->setDescription('Clean expired group messages from the database') + ->addOption('days', 'd', Option::VALUE_OPTIONAL, 'Number of days to keep messages (default: 90)', 90) + ->addOption('dry-run', null, Option::VALUE_NONE, 'Perform a dry run without deleting any data') + ->addOption('batch-size', 'b', Option::VALUE_OPTIONAL, 'Batch size for deletion (default: 1000)', 1000); + } + + protected function execute(Input $input, Output $output) + { + $days = (int)$input->getOption('days'); + $dryRun = $input->getOption('dry-run'); + $batchSize = (int)$input->getOption('batch-size'); + + if ($dryRun) { + $output->writeln("Running in dry-run mode. No data will be deleted."); + } + + $cutoffDate = date('Y-m-d H:i:s', strtotime("-{$days} days")); + $output->writeln("Cleaning group messages older than {$cutoffDate} (keeping last {$days} days)"); + + // 清理微信群组消息 + $this->cleanWechatGroupMessages($cutoffDate, $dryRun, $batchSize, $output); + + $output->writeln("Group message cleanup completed successfully."); + } + + protected function cleanWechatGroupMessages($cutoffDate, $dryRun, $batchSize, Output $output) + { + $output->writeln("\nCleaning s2_wechat_group_message table..."); + + // 获取符合条件的消息总数 + $totalCount = Db::table('s2_wechat_group_message') + ->where('createTime', '<', $cutoffDate) + ->count(); + + if ($totalCount === 0) { + $output->writeln(" No expired group messages found."); + return; + } + + $output->writeln(" Found {$totalCount} group messages to clean up."); + + if ($dryRun) { + $output->writeln(" Dry run mode: would delete {$totalCount} group messages."); + return; + } + + // 计算需要执行的批次数 + $batches = ceil($totalCount / $batchSize); + $deletedCount = 0; + + $output->writeln(" Deleting in {$batches} batches of {$batchSize} records..."); + + // 分批删除数据 + for ($i = 0; $i < $batches; $i++) { + // 获取一批要删除的ID + $ids = Db::table('s2_wechat_group_message') + ->where('createTime', '<', $cutoffDate) + ->limit($batchSize) + ->column('id'); + + if (empty($ids)) { + break; + } + + // 删除这批数据 + $count = Db::table('s2_wechat_group_message') + ->whereIn('id', $ids) + ->delete(); + + $deletedCount += $count; + $progress = round(($deletedCount / $totalCount) * 100, 2); + $output->write(" Progress: {$progress}% ({$deletedCount}/{$totalCount})\r"); + + // 短暂暂停,减轻数据库负担 + usleep(500000); // 暂停0.5秒 + } + + $output->writeln(""); + $output->writeln(" Successfully deleted {$deletedCount} expired group messages."); + + // 优化表 + $output->writeln(" Optimizing table..."); + Db::execute("OPTIMIZE TABLE s2_wechat_group_message"); + $output->writeln(" Table optimization completed."); + } +} \ No newline at end of file diff --git a/Server/application/command/CleanExpiredMessages.php b/Server/application/command/CleanExpiredMessages.php new file mode 100644 index 00000000..d499f653 --- /dev/null +++ b/Server/application/command/CleanExpiredMessages.php @@ -0,0 +1,100 @@ +setName('clean:expired_messages') + ->setDescription('Clean expired messages from the database') + ->addOption('days', 'd', Option::VALUE_OPTIONAL, 'Number of days to keep messages (default: 90)', 90) + ->addOption('dry-run', null, Option::VALUE_NONE, 'Perform a dry run without deleting any data') + ->addOption('batch-size', 'b', Option::VALUE_OPTIONAL, 'Batch size for deletion (default: 1000)', 1000); + } + + protected function execute(Input $input, Output $output) + { + $days = (int)$input->getOption('days'); + $dryRun = $input->getOption('dry-run'); + $batchSize = (int)$input->getOption('batch-size'); + + if ($dryRun) { + $output->writeln("Running in dry-run mode. No data will be deleted."); + } + + $cutoffDate = date('Y-m-d H:i:s', strtotime("-{$days} days")); + $output->writeln("Cleaning messages older than {$cutoffDate} (keeping last {$days} days)"); + + // 清理微信消息 + $this->cleanWechatMessages($cutoffDate, $dryRun, $batchSize, $output); + + $output->writeln("Message cleanup completed successfully."); + } + + protected function cleanWechatMessages($cutoffDate, $dryRun, $batchSize, Output $output) + { + $output->writeln("\nCleaning s2_wechat_message table..."); + + // 获取符合条件的消息总数 + $totalCount = Db::table('s2_wechat_message') + ->where('createTime', '<', $cutoffDate) + ->count(); + + if ($totalCount === 0) { + $output->writeln(" No expired messages found."); + return; + } + + $output->writeln(" Found {$totalCount} messages to clean up."); + + if ($dryRun) { + $output->writeln(" Dry run mode: would delete {$totalCount} messages."); + return; + } + + // 计算需要执行的批次数 + $batches = ceil($totalCount / $batchSize); + $deletedCount = 0; + + $output->writeln(" Deleting in {$batches} batches of {$batchSize} records..."); + + // 分批删除数据 + for ($i = 0; $i < $batches; $i++) { + // 获取一批要删除的ID + $ids = Db::table('s2_wechat_message') + ->where('createTime', '<', $cutoffDate) + ->limit($batchSize) + ->column('id'); + + if (empty($ids)) { + break; + } + + // 删除这批数据 + $count = Db::table('s2_wechat_message') + ->whereIn('id', $ids) + ->delete(); + + $deletedCount += $count; + $progress = round(($deletedCount / $totalCount) * 100, 2); + $output->write(" Progress: {$progress}% ({$deletedCount}/{$totalCount})\r"); + + // 短暂暂停,减轻数据库负担 + usleep(500000); // 暂停0.5秒 + } + + $output->writeln(""); + $output->writeln(" Successfully deleted {$deletedCount} expired messages."); + + // 优化表 + $output->writeln(" Optimizing table..."); + Db::execute("OPTIMIZE TABLE s2_wechat_message"); + $output->writeln(" Table optimization completed."); + } +} \ No newline at end of file diff --git a/Server/application/command/OptimizeMessageIndexes.php b/Server/application/command/OptimizeMessageIndexes.php new file mode 100644 index 00000000..a604191e --- /dev/null +++ b/Server/application/command/OptimizeMessageIndexes.php @@ -0,0 +1,112 @@ +setName('optimize:message_indexes') + ->setDescription('Optimize database indexes for message-related tables'); + } + + protected function execute(Input $input, Output $output) + { + $output->writeln("Starting index optimization for message-related tables..."); + + // 优化 s2_wechat_message 表索引 + $this->optimizeWechatMessageIndexes($output); + + // 优化 s2_wechat_chatroom 表索引 + $this->optimizeWechatChatroomIndexes($output); + + // 优化 s2_wechat_friend 表索引 + $this->optimizeWechatFriendIndexes($output); + + $output->writeln("Index optimization completed successfully."); + } + + protected function optimizeWechatMessageIndexes(Output $output) + { + $output->writeln("Optimizing s2_wechat_message table indexes..."); + + // 检查并添加 wechatChatroomId 索引 + $this->addIndexIfNotExists('s2_wechat_message', 'idx_chatroom_id', 'wechatChatroomId', $output); + + // 检查并添加 wechatFriendId 索引 + $this->addIndexIfNotExists('s2_wechat_message', 'idx_friend_id', 'wechatFriendId', $output); + + // 检查并添加 isRead 索引 + $this->addIndexIfNotExists('s2_wechat_message', 'idx_is_read', 'isRead', $output); + + // 检查并添加 type 索引 + $this->addIndexIfNotExists('s2_wechat_message', 'idx_type', 'type', $output); + + // 检查并添加 createTime 索引 + $this->addIndexIfNotExists('s2_wechat_message', 'idx_create_time', 'createTime', $output); + + // 检查并添加组合索引 (wechatChatroomId, isRead) + $this->addIndexIfNotExists('s2_wechat_message', 'idx_chatroom_read', 'wechatChatroomId,isRead', $output); + + // 检查并添加组合索引 (wechatFriendId, isRead) + $this->addIndexIfNotExists('s2_wechat_message', 'idx_friend_read', 'wechatFriendId,isRead', $output); + } + + protected function optimizeWechatChatroomIndexes(Output $output) + { + $output->writeln("Optimizing s2_wechat_chatroom table indexes..."); + + // 检查并添加 accountId 索引 + $this->addIndexIfNotExists('s2_wechat_chatroom', 'idx_account_id', 'accountId', $output); + + // 检查并添加 isDeleted 索引 + $this->addIndexIfNotExists('s2_wechat_chatroom', 'idx_is_deleted', 'isDeleted', $output); + + // 检查并添加组合索引 (accountId, isDeleted) + $this->addIndexIfNotExists('s2_wechat_chatroom', 'idx_account_deleted', 'accountId,isDeleted', $output); + } + + protected function optimizeWechatFriendIndexes(Output $output) + { + $output->writeln("Optimizing s2_wechat_friend table indexes..."); + + // 检查并添加 accountId 索引 + $this->addIndexIfNotExists('s2_wechat_friend', 'idx_account_id', 'accountId', $output); + + // 检查并添加 isDeleted 索引 + $this->addIndexIfNotExists('s2_wechat_friend', 'idx_is_deleted', 'isDeleted', $output); + + // 检查并添加组合索引 (accountId, isDeleted) + $this->addIndexIfNotExists('s2_wechat_friend', 'idx_account_deleted', 'accountId,isDeleted', $output); + } + + protected function addIndexIfNotExists($table, $indexName, $columns, Output $output) + { + try { + // 检查索引是否已存在 + $indexExists = false; + $indexes = Db::query("SHOW INDEX FROM {$table}"); + + foreach ($indexes as $index) { + if ($index['Key_name'] === $indexName) { + $indexExists = true; + break; + } + } + + if (!$indexExists) { + // 添加索引 + Db::execute("ALTER TABLE {$table} ADD INDEX {$indexName} ({$columns})"); + $output->writeln(" - Added index {$indexName} on {$table}({$columns})"); + } else { + $output->writeln(" - Index {$indexName} already exists on {$table}"); + } + } catch (\Exception $e) { + $output->writeln(" - Error adding index {$indexName} to {$table}: " . $e->getMessage()); + } + } +} \ No newline at end of file diff --git a/Server/application/command/ScheduleMessageMaintenance.php b/Server/application/command/ScheduleMessageMaintenance.php new file mode 100644 index 00000000..359faf93 --- /dev/null +++ b/Server/application/command/ScheduleMessageMaintenance.php @@ -0,0 +1,121 @@ +setName('schedule:message_maintenance') + ->setDescription('Schedule and run message maintenance tasks') + ->addOption('optimize-indexes', null, Option::VALUE_NONE, 'Run index optimization') + ->addOption('clean-messages', null, Option::VALUE_NONE, 'Clean expired messages') + ->addOption('days', 'd', Option::VALUE_OPTIONAL, 'Number of days to keep messages (default: 90)', 90) + ->addOption('batch-size', 'b', Option::VALUE_OPTIONAL, 'Batch size for deletion (default: 1000)', 1000) + ->addOption('dry-run', null, Option::VALUE_NONE, 'Perform a dry run without deleting any data'); + } + + protected function execute(Input $input, Output $output) + { + $optimizeIndexes = $input->getOption('optimize-indexes'); + $cleanMessages = $input->getOption('clean-messages'); + $days = (int)$input->getOption('days'); + $batchSize = (int)$input->getOption('batch-size'); + $dryRun = $input->getOption('dry-run'); + + // 如果没有指定任何选项,则运行所有维护任务 + if (!$optimizeIndexes && !$cleanMessages) { + $optimizeIndexes = true; + $cleanMessages = true; + } + + $output->writeln("Starting scheduled message maintenance tasks..."); + $startTime = microtime(true); + + // 运行索引优化 + if ($optimizeIndexes) { + $this->runCommand($output, 'optimize:message_indexes'); + } + + // 清理过期消息 + if ($cleanMessages) { + $options = []; + + if ($days !== 90) { + $options[] = "--days={$days}"; + } + + if ($batchSize !== 1000) { + $options[] = "--batch-size={$batchSize}"; + } + + if ($dryRun) { + $options[] = "--dry-run"; + } + + $this->runCommand($output, 'clean:expired_messages', $options); + $this->runCommand($output, 'clean:expired_group_messages', $options); + } + + $endTime = microtime(true); + $executionTime = round($endTime - $startTime, 2); + $output->writeln("All maintenance tasks completed in {$executionTime} seconds."); + } + + protected function runCommand(Output $output, $command, array $options = []) + { + $output->writeln("\nRunning command: {$command}"); + + $optionsStr = implode(' ', $options); + $fullCommand = "php think {$command} {$optionsStr}"; + + $output->writeln("Executing: {$fullCommand}"); + $output->writeln("\nCommand output:"); + + // 执行命令并实时输出结果 + $descriptorSpec = [ + 0 => ["pipe", "r"], // stdin + 1 => ["pipe", "w"], // stdout + 2 => ["pipe", "w"] // stderr + ]; + + $process = proc_open($fullCommand, $descriptorSpec, $pipes); + + if (is_resource($process)) { + // 关闭标准输入 + fclose($pipes[0]); + + // 读取标准输出 + while (!feof($pipes[1])) { + $line = fgets($pipes[1]); + if ($line !== false) { + $output->write($line); + } + } + fclose($pipes[1]); + + // 读取标准错误 + $errorOutput = stream_get_contents($pipes[2]); + fclose($pipes[2]); + + // 获取命令执行结果 + $exitCode = proc_close($process); + + if ($exitCode !== 0) { + $output->writeln("\nCommand failed with exit code {$exitCode}"); + if (!empty($errorOutput)) { + $output->writeln("Error output:"); + $output->writeln($errorOutput); + } + } else { + $output->writeln("\nCommand completed successfully."); + } + } else { + $output->writeln("Failed to execute command."); + } + } +} \ No newline at end of file diff --git a/Server/application/common/config/route.php b/Server/application/common/config/route.php index 8c6ccc6b..fc94c79b 100644 --- a/Server/application/common/config/route.php +++ b/Server/application/common/config/route.php @@ -9,7 +9,6 @@ Route::group('v1/auth', function () { Route::post('login', 'app\common\controller\PasswordLoginController@index'); // 账号密码登录 Route::post('mobile-login', 'app\common\controller\Auth@mobileLogin'); // 手机号验证码登录 Route::post('code', 'app\common\controller\Auth@SendCodeController'); // 发送验证码 - // 需要JWT认证的接口 Route::get('info', 'app\common\controller\Auth@info')->middleware(['jwt']); // 获取用户信息 Route::post('refresh', 'app\common\controller\Auth@refresh')->middleware(['jwt']); // 刷新令牌 @@ -22,4 +21,13 @@ Route::group('v1/', function () { })->middleware(['jwt']); -Route::get('app/update', 'app\common\controller\Api@uploadApp'); \ No newline at end of file + +Route::group('v1/pay', function () { + Route::post('', 'app\cunkebao\controller\Pay@createOrder')->middleware(['jwt']); + Route::any('notify', 'app\common\controller\PaymentService@notify'); +}); + + + + +Route::get('app/update', 'app\common\controller\PaymentService@createOrder'); \ No newline at end of file diff --git a/Server/application/common/controller/PaymentService.php b/Server/application/common/controller/PaymentService.php new file mode 100644 index 00000000..3e7e6a25 --- /dev/null +++ b/Server/application/common/controller/PaymentService.php @@ -0,0 +1,366 @@ + 'unified.trade.native', + 'sign_type' => PaymentUtil::SIGN_TYPE_MD5, + 'mch_id' => Env::get('payment.mchId'), + 'out_trade_no' => $order['orderNo'], + 'body' => $order['goodsName'] ?? '', + 'total_fee' => $order['money'] ?? 0, + 'mch_create_ip' => Request::ip(), + 'notify_url' => Env::get('payment.notify_url', '127.0.0.1'), + 'nonce_str' => PaymentUtil::generateNonceStr(), + ]; + + Db::startTrans(); + try { + // 过滤空值签名 + $secret = Env::get('payment.key'); + $params['sign_type'] = 'MD5'; + $params['sign'] = PaymentUtil::generateSign($params, $secret, 'MD5'); + + $url = Env::get('payment.url'); + if (empty($url)) { + throw new \Exception('支付网关地址未配置'); + } + + //创建订单 + Order::create([ + 'mchId' => $params['mch_id'], + 'companyId' => $order['companyId'], + 'userId' => $order['userId'], + 'orderType' => $order['orderType'] ?? 1, + 'status' => 0, + 'goodsId' => $order['goodsId'], + 'goodsName' => $order['goodsName'], + 'money' => $order['money'], + 'orderNo' => $order['orderNo'], + 'ip' => Request::ip(), + 'nonceStr' => $params['nonce_str'], + 'createTime' => time(), + ]); + + + // XML POST 请求 + $xmlBody = $this->arrayToXml($params); + $response = $this->postXml($url, $xmlBody); + $parsed = $this->parseXmlOrRaw($response); + + if ($parsed['status'] == 0 && $parsed['result_code'] == 0) { + Db::commit(); + return json(['code' => 200, 'msg' => '订单创建成功', 'data' => $parsed['code_url']]); + } else { + Db::rollback(); + return json(['code' => 500, 'msg' => '订单创建失败:' . $parsed['err_msg']]); + } + + } catch (\Exception $e) { + Db::rollback(); + return json(['code' => 500, 'msg' => '订单创建失败:' . $e->getMessage()]); + } + } + + + /** + * POST 请求(x-www-form-urlencoded) + */ + protected function httpPost(string $url, array $params, array $headers = []) + { + if (!function_exists('requestCurl')) { + throw new \RuntimeException('requestCurl 未定义'); + } + return requestCurl($url, $params, 'POST', $headers, 'dataBuild'); + } + + /** + * 解析响应 + */ + protected function parseResponse($response) + { + if ($response === '' || $response === null) { + return ''; + } + $decoded = json_decode($response, true); + if (json_last_error() === JSON_ERROR_NONE) { + return $decoded; + } + if (strpos($response, '=') !== false && strpos($response, '&') !== false) { + $arr = []; + foreach (explode('&', $response) as $pair) { + if ($pair === '') continue; + $kv = explode('=', $pair, 2); + $arr[$kv[0]] = $kv[1] ?? ''; + } + return $arr; + } + return $response; + } + + /** + * 以 XML 方式 POST(text/xml) + */ + protected function postXml(string $url, string $xml) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: text/xml; charset=UTF-8' + ]); + curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + $res = curl_exec($ch); + curl_close($ch); + return $res; + } + + /** + * 数组转 XML(按 ASCII 升序,字符串走 CDATA) + */ + protected function arrayToXml(array $data): string + { + // 过滤空值 + $filtered = []; + foreach ($data as $k => $v) { + if ($v === '' || $v === null) continue; + $filtered[$k] = $v; + } + ksort($filtered, SORT_STRING); + + $xml = ''; + foreach ($filtered as $key => $value) { + if (is_numeric($value)) { + $xml .= "<{$key}>{$value}"; + } else { + $xml .= "<{$key}>"; + } + } + $xml .= ''; + return $xml; + } + + /** + * 解析 XML 响应 + */ + protected function parseXmlOrRaw($response) + { + if (!is_string($response) || $response === '') { + return $response; + } + libxml_use_internal_errors(true); + $xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA); + if ($xml !== false) { + $json = json_encode($xml, JSON_UNESCAPED_UNICODE); + return json_decode($json, true); + } + return $response; + } + + /** + * 支付结果异步通知 + * - 威富通回调为 XML;需校验签名与业务字段并更新订单 + * - 回应:成功回"success",失败回"fail" + * @return void + */ + public function notify() + { + $rawBody = file_get_contents('php://input'); + $payload = $this->parseXmlOrRaw($rawBody); + if (!is_array($payload) || empty($payload)) { + return json_encode(['code' => 500, 'msg' => 'XML解析错误']); + } + + + if ($payload['status'] != 0 || $payload['result_code'] != 0) { + $errMsg = (isset($payload['err_msg']) ? $payload['err_msg'] : isset($payload['err_msg'])) ? $payload['err_msg'] : '未知错误'; + return json_encode(['code' => 500, 'msg' => $errMsg]); + } + + + // 业务处理:更新订单 + Db::startTrans(); + try { + $outTradeNo = $payload['out_trade_no']; + $pay_result = $payload['pay_result']; + $time_end = $payload['time_end']; + $order = Order::where('orderNo', $outTradeNo)->find(); + if (!$order) { + Db::rollback(); + return json_encode(['code' => 500, 'msg' => '该订单不存在']); + } + + if ($pay_result != 0) { + $order->payInfo = $payload['pay_info']; + $order->payType = $payload['trade_type'] == 'pay.wechat.jspay' ? 1 : 2; + $order->status = 3; + $order->save(); + Db::commit(); + return json_encode(['code' => 500, 'msg' => $payload['pay_info']]); + } + $order->status = 1; + $order->payTime = $this->parsePayTime($time_end); + $order->save(); + Db::commit(); + return json_encode(['code' => 200, 'msg' => '付款成功']); + } catch (\Exception $e) { + Db::rollback(); + return json_encode(['code' => 500, 'msg' => '付款失败' . $e->getMessage()]); + } + } + + /** + * 解析威富通时间(yyyyMMddHHmmss)为时间戳 + */ + protected function parsePayTime(string $timeEnd) + { + if ($timeEnd === '') { + return 0; + } + // 期望格式:20250102153045 + if (preg_match('/^\\d{14}$/', $timeEnd) !== 1) { + return 0; + } + $dt = \DateTime::createFromFormat('YmdHis', $timeEnd, new \DateTimeZone('Asia/Shanghai')); + return $dt ? $dt->getTimestamp() : 0; + } + + /** + * 查询订单(威富通 unified.trade.query) + * - 入参:商户订单号或平台交易号 + * - 出参:统一 JSON 格式,包含交易状态与关键信息 + * @param array $query + * - out_trade_no: string 商户订单号(与 transaction_id 二选一) + * - transaction_id: string 平台交易号(与 out_trade_no 二选一) + * @return \think\response\Json + */ + public function queryOrder(array $query) + { + $outTradeNo = $query['out_trade_no'] ?? ($query['orderNo'] ?? ''); + $transactionId = $query['transaction_id'] ?? ''; + + if ($outTradeNo === '' && $transactionId === '') { + return json(['code' => 422, 'msg' => '缺少查询参数:out_trade_no 或 transaction_id']); + } + + $params = [ + 'service' => 'unified.trade.query', + 'mch_id' => Env::get('payment.mchId'), + 'out_trade_no' => $outTradeNo ?: null, + 'nonce_str' => PaymentUtil::generateNonceStr(), + 'sign_type' => 'MD5', + ]; + + // 过滤空值后签名 + $secret = Env::get('payment.key'); + if (empty($secret)) { + return json(['code' => 500, 'msg' => '支付密钥未配置']); + } + + $filtered = []; + foreach ($params as $k => $v) { + if ($v === '' || $v === null) continue; + $filtered[$k] = $v; + } + $filtered['sign'] = PaymentUtil::generateSign($filtered, $secret, $filtered['sign_type']); + + $url = Env::get('payment.url'); + if (empty($url)) { + return json(['code' => 500, 'msg' => '支付网关地址未配置']); + } + + // 请求网关 + $xmlBody = $this->arrayToXml($filtered); + $response = $this->postXml($url, $xmlBody); + $parsed = $this->parseXmlOrRaw($response); + + if (!is_array($parsed)) { + return json(['code' => 500, 'msg' => '响应解析失败', 'data' => $response]); + } + + if (($parsed['status'] ?? '') !== '0') { + return json(['code' => 500, 'msg' => '通信失败:' . ($parsed['message'] ?? 'unknown')]); + } + + if (($parsed['result_code'] ?? '') !== '0') { + return json(['code' => 200, 'msg' => '业务失败', 'data' => [ + 'err_code' => $parsed['err_code'] ?? '', + 'err_msg' => $parsed['err_msg'] ?? '', + ]]); + } + + $tradeState = $parsed['trade_state'] ?? ''; + $resp = [ + 'trade_state' => $tradeState, + 'trade_state_desc' => $parsed['trade_state_desc'] ?? '', + 'transaction_id' => $parsed['transaction_id'] ?? '', + 'out_trade_no' => $parsed['out_trade_no'] ?? $outTradeNo, + 'total_fee' => isset($parsed['total_fee']) ? (int)$parsed['total_fee'] : null, + 'time_end' => $parsed['time_end'] ?? '', + 'buyer_logon_id' => $parsed['buyer_logon_id'] ?? '', + 'bank_type' => $parsed['bank_type'] ?? '', + ]; + + // 若已支付,同步本地订单 + if ($tradeState === 'SUCCESS' && ($resp['out_trade_no'] ?? '') !== '') { + Db::startTrans(); + try { + /** @var Order|null $order */ + $order = Order::where('orderNo', $resp['out_trade_no'])->lock(true)->find(); + if ($order) { + $paidAt = $this->parsePayTime($resp['time_end'] ?? '') ?: time(); + if ((int)$order['status'] !== 1) { + $order->save([ + 'status' => 1, + 'transactionId' => $resp['transaction_id'] ?? '', + 'payTime' => $paidAt, + 'updateTime' => time(), + ]); + } + } + Db::commit(); + } catch (\Throwable $e) { + Db::rollback(); + Log::error('[SwiftPass][query] update order exception: ' . $e->getMessage()); + } + } + + return json(['code' => 200, 'msg' => '查询成功', 'data' => $resp]); + } +} + diff --git a/Server/application/common/model/Order.php b/Server/application/common/model/Order.php new file mode 100644 index 00000000..82b6b5b8 --- /dev/null +++ b/Server/application/common/model/Order.php @@ -0,0 +1,14 @@ + $value) { + $pairs[] = $key . '=' . $value; + } + return implode('&', $pairs); + } + + /** + * 生成MD5签名 + * + * @param string $queryString 待签名字符串 + * @param string $secretKey 密钥 + * @return string MD5签名 + */ + private static function generateMd5Sign(string $queryString, string $secretKey): string + { + $signString = $queryString . '&key=' . $secretKey; + return strtoupper(md5($signString)); + } + + /** + * 生成RSA256签名 + * + * @param string $queryString 待签名字符串 + * @param string $privateKey 私钥 + * @return string RSA256签名 + */ + private static function generateRsa256Sign(string $queryString, string $privateKey): string + { + $privateKey = self::formatPrivateKey($privateKey); + $key = openssl_pkey_get_private($privateKey); + if (!$key) { + throw new \Exception('RSA私钥格式错误'); + } + + $signature = ''; + $result = openssl_sign($queryString, $signature, $key, OPENSSL_ALGO_SHA256); + openssl_pkey_free($key); + + if (!$result) { + throw new \Exception('RSA256签名失败'); + } + + return base64_encode($signature); + } + + /** + * 生成RSA1签名 + * + * @param string $queryString 待签名字符串 + * @param string $privateKey 私钥 + * @return string RSA1签名 + */ + private static function generateRsa1Sign(string $queryString, string $privateKey): string + { + $privateKey = self::formatPrivateKey($privateKey); + $key = openssl_pkey_get_private($privateKey); + if (!$key) { + throw new \Exception('RSA私钥格式错误'); + } + + $signature = ''; + $result = openssl_sign($queryString, $signature, $key, OPENSSL_ALGO_SHA1); + openssl_pkey_free($key); + + if (!$result) { + throw new \Exception('RSA1签名失败'); + } + + return base64_encode($signature); + } + + /** + * 格式化私钥 + * + * @param string $privateKey 原始私钥 + * @return string 格式化后的私钥 + */ + private static function formatPrivateKey(string $privateKey): string + { + $privateKey = str_replace(['-----BEGIN PRIVATE KEY-----', '-----END PRIVATE KEY-----', "\n", "\r"], '', $privateKey); + $privateKey = chunk_split($privateKey, 64, "\n"); + return "-----BEGIN PRIVATE KEY-----\n" . $privateKey . "-----END PRIVATE KEY-----"; + } + + /** + * 格式化公钥 + * + * @param string $publicKey 原始公钥 + * @return string 格式化后的公钥 + */ + private static function formatPublicKey(string $publicKey): string + { + $publicKey = str_replace(['-----BEGIN PUBLIC KEY-----', '-----END PUBLIC KEY-----', "\n", "\r"], '', $publicKey); + $publicKey = chunk_split($publicKey, 64, "\n"); + return "-----BEGIN PUBLIC KEY-----\n" . $publicKey . "-----END PUBLIC KEY-----"; + } + + /** + * 验证RSA签名 + * + * @param string $queryString 原始字符串 + * @param string $signature 签名 + * @param string $publicKey 公钥 + * @param string $signType 签名类型 + * @return bool 验证结果 + */ + public static function verifyRsaSign(string $queryString, string $signature, string $publicKey, string $signType = self::SIGN_TYPE_RSA_1_256): bool + { + $publicKey = self::formatPublicKey($publicKey); + $key = openssl_pkey_get_public($publicKey); + if (!$key) { + return false; + } + + $algorithm = $signType === self::SIGN_TYPE_RSA_1_1 ? OPENSSL_ALGO_SHA1 : OPENSSL_ALGO_SHA256; + $result = openssl_verify($queryString, base64_decode($signature), $key, $algorithm); + openssl_pkey_free($key); + + return $result === 1; + } + + /** + * 生成随机字符串 + * + * @param int $length 长度 + * @return string 随机字符串 + */ + public static function generateNonceStr(int $length = 32): string + { + $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + $str = ''; + for ($i = 0; $i < $length; $i++) { + $str .= $chars[mt_rand(0, strlen($chars) - 1)]; + } + return $str; + } + + /** + * 生成时间戳 + * + * @return int 时间戳 + */ + public static function generateTimestamp(): int + { + return time(); + } + + /** + * 格式化金额(分转元) + * + * @param int $amount 金额(分) + * @return string 格式化后的金额(元) + */ + public static function formatAmount(int $amount): string + { + return number_format($amount / 100, 2, '.', ''); + } + + /** + * 解析金额(元转分) + * + * @param string $amount 金额(元) + * @return int 金额(分) + */ + public static function parseAmount(string $amount): int + { + return (int) round(floatval($amount) * 100); + } +} diff --git a/Server/application/common/util/Signer.php b/Server/application/common/util/Signer.php new file mode 100644 index 00000000..9b68840d --- /dev/null +++ b/Server/application/common/util/Signer.php @@ -0,0 +1,135 @@ + $value) { + if ($key === 'sign') { + continue; + } + if ($value === '' || $value === null) { + continue; + } + $filtered[$key] = $value; + } + + ksort($filtered, SORT_STRING); + + $pairs = []; + foreach ($filtered as $key => $value) { + // 原始值拼接,不做 urlencode + $pairs[] = $key . '=' . (is_bool($value) ? ($value ? '1' : '0') : (string)$value); + } + + return implode('&', $pairs); + } + + /** + * MD5 签名 + * - 若提供 secret,则原串末尾追加 &key=SECRET + * - 返回 32 位小写 + * + * @param string $signString + * @param string|null $secret + * @return string + */ + protected static function signMd5($signString, $secret = null) + { + if ($secret !== null && $secret !== '') { + $signString .= '&key=' . $secret; + } + return strtolower(md5($signString)); + } + + /** + * RSA 签名 + * + * @param string $signString + * @param array $options 必填:private_key,可选:passphrase + * @param string $hashAlgo sha256|sha1 + * @return string base64 签名 + * @throws \InvalidArgumentException + */ + protected static function signRsa($signString, array $options, $hashAlgo = 'sha256') + { + if (empty($options['private_key'])) { + throw new \InvalidArgumentException('RSA signing requires private_key.'); + } + + $privateKey = $options['private_key']; + $passphrase = isset($options['passphrase']) ? (string)$options['passphrase'] : ''; + + // 兼容无头尾私钥,自动包裹为 PEM + if (strpos($privateKey, 'BEGIN') === false) { + $privateKey = "-----BEGIN PRIVATE KEY-----\n" . trim(chunk_split(str_replace(["\r", "\n"], '', $privateKey), 64, "\n")) . "\n-----END PRIVATE KEY-----"; + } + + $pkeyId = openssl_pkey_get_private($privateKey, $passphrase); + if ($pkeyId === false) { + throw new \InvalidArgumentException('Invalid RSA private key or passphrase.'); + } + + $signature = ''; + $algoConst = $hashAlgo === 'sha1' ? OPENSSL_ALGO_SHA1 : OPENSSL_ALGO_SHA256; + $ok = openssl_sign($signString, $signature, $pkeyId, $algoConst); + openssl_free_key($pkeyId); + + if (!$ok) { + throw new \InvalidArgumentException('OpenSSL sign failed.'); + } + + return base64_encode($signature); + } +} + + diff --git a/Server/application/cunkebao/controller/Pay.php b/Server/application/cunkebao/controller/Pay.php new file mode 100644 index 00000000..99553f0c --- /dev/null +++ b/Server/application/cunkebao/controller/Pay.php @@ -0,0 +1,27 @@ + 111, + 'userId' => 111, + 'orderNo' => date('YmdHis') . rand(100000, 999999), + 'goodsId' => 34, + 'goodsName' => '测试测试', + 'orderType' => 1, + 'money' => 1 + ]; + + $paymentService = new PaymentService(); + $res = $paymentService->createOrder($order); + return $res; + } +} \ No newline at end of file diff --git a/Server/application/cunkebao/controller/WorkbenchController.php b/Server/application/cunkebao/controller/WorkbenchController.php index e273675b..9499c40f 100644 --- a/Server/application/cunkebao/controller/WorkbenchController.php +++ b/Server/application/cunkebao/controller/WorkbenchController.php @@ -149,7 +149,7 @@ class WorkbenchController extends Controller $config->startTime = $param['startTime']; $config->endTime = $param['endTime']; $config->devices = json_encode($param['deviceGroups'], JSON_UNESCAPED_UNICODE); - $config->pools = json_encode($param['pools'], JSON_UNESCAPED_UNICODE); + $config->pools = json_encode($param['poolGroups'], JSON_UNESCAPED_UNICODE); $config->account = json_encode($param['accountGroups'], JSON_UNESCAPED_UNICODE); $config->createTime = time(); $config->updateTime = time(); @@ -159,7 +159,7 @@ class WorkbenchController extends Controller $config = new WorkbenchImportContact; $config->workbenchId = $workbench->id; $config->devices = json_encode($param['deviceGroups'], JSON_UNESCAPED_UNICODE); - $config->pools = json_encode($param['pools'], JSON_UNESCAPED_UNICODE); + $config->pools = json_encode($param['poolGroups'], JSON_UNESCAPED_UNICODE); $config->num = $param['num']; $config->clearContact = $param['clearContact']; $config->remark = $param['remark']; @@ -314,13 +314,13 @@ class WorkbenchController extends Controller if (!empty($item->trafficConfig)) { $item->config = $item->trafficConfig; $item->config->devices = json_decode($item->config->devices, true); - $item->config->pools = json_decode($item->config->pools, true); + $item->config->poolGroups = json_decode($item->config->pools, true); $item->config->account = json_decode($item->config->account, true); $config_item = Db::name('workbench_traffic_config_item')->where(['workbenchId' => $item->id])->order('id DESC')->find(); $item->config->lastUpdated = !empty($config_item) ? date('Y-m-d H:i', $config_item['createTime']) : '--'; //统计 - $labels = $item->config->pools; + $labels = $item->config->poolGroups; $totalUsers = Db::table('s2_wechat_friend')->alias('wf') ->join(['s2_company_account' => 'sa'], 'sa.id = wf.accountId', 'left') ->join(['s2_wechat_account' => 'wa'], 'wa.id = wf.wechatAccountId', 'left') @@ -352,7 +352,7 @@ class WorkbenchController extends Controller 'dailyAverage' => intval($dailyAverage), 'totalAccounts' => $totalAccounts, 'deviceCount' => count($item->config->devices), - 'poolCount' => !empty($item->config->pools) ? count($item->config->pools) : 'ALL', + 'poolCount' => !empty($item->config->poolGroups) ? count($item->config->poolGroups) : 'ALL', 'totalUsers' => $totalUsers >> 0 ]; } @@ -363,7 +363,7 @@ class WorkbenchController extends Controller if (!empty($item->importContact)) { $item->config = $item->importContact; $item->config->devices = json_decode($item->config->devices, true); - $item->config->pools = json_decode($item->config->pools, true); + $item->config->poolGroups = json_decode($item->config->pools, true); } unset($item->importContact, $item->import_contact); break; @@ -505,12 +505,12 @@ class WorkbenchController extends Controller $workbench->config = $workbench->trafficConfig; $workbench->config->deviceGroups = json_decode($workbench->config->devices, true); $workbench->config->accountGroups = json_decode($workbench->config->account, true); - $workbench->config->pools = json_decode($workbench->config->pools, true); + $workbench->config->poolGroups = json_decode($workbench->config->pools, true); $config_item = Db::name('workbench_traffic_config_item')->where(['workbenchId' => $workbench->id])->order('id DESC')->find(); $workbench->config->lastUpdated = !empty($config_item) ? date('Y-m-d H:i', $config_item['createTime']) : '--'; //统计 - $labels = $workbench->config->pools; + $labels = $workbench->config->poolGroups; $totalUsers = Db::table('s2_wechat_friend')->alias('wf') ->join(['s2_company_account' => 'sa'], 'sa.id = wf.accountId', 'left') ->join(['s2_wechat_account' => 'wa'], 'wa.id = wf.wechatAccountId', 'left') @@ -549,7 +549,7 @@ class WorkbenchController extends Controller 'dailyAverage' => intval($dailyAverage), 'totalAccounts' => $totalAccounts, 'deviceCount' => count($workbench->config->deviceGroups), - 'poolCount' => count($workbench->config->pools), + 'poolCount' => count($workbench->config->poolGroups), 'totalUsers' => $totalUsers >> 0 ]; unset($workbench->trafficConfig, $workbench->traffic_config); @@ -559,7 +559,7 @@ class WorkbenchController extends Controller if (!empty($workbench->importContact)) { $workbench->config = $workbench->importContact; $workbench->config->deviceGroups = json_decode($workbench->config->devices, true); - $workbench->config->pools = json_decode($workbench->config->pools, true); + $workbench->config->poolGroups = json_decode($workbench->config->pools, true); } unset($workbench->importContact, $workbench->import_contact); break; @@ -789,7 +789,7 @@ class WorkbenchController extends Controller $config->startTime = $param['startTime']; $config->endTime = $param['endTime']; $config->devices = json_encode($param['deviceGroups']); - $config->pools = json_encode($param['pools']); + $config->pools = json_encode($param['poolGroups']); $config->account = json_encode($param['accountGroups']); $config->updateTime = time(); $config->save(); @@ -799,7 +799,7 @@ class WorkbenchController extends Controller $config = WorkbenchImportContact::where('workbenchId', $param['id'])->find();; if ($config) { $config->devices = json_encode($param['deviceGroups']); - $config->pools = json_encode($param['pools']); + $config->pools = json_encode($param['poolGroups']); $config->num = $param['num']; $config->clearContact = $param['clearContact']; $config->remark = $param['remark']; @@ -1450,7 +1450,7 @@ class WorkbenchController extends Controller 'startTime' => $param['startTime'], 'endTime' => $param['endTime'], 'targets' => json_encode($param['targets'], JSON_UNESCAPED_UNICODE), - 'pools' => json_encode($param['pools'], JSON_UNESCAPED_UNICODE), + 'pools' => json_encode($param['poolGroups'], JSON_UNESCAPED_UNICODE), 'createTime' => time(), 'updateTime' => time() ]); diff --git a/Server/application/cunkebao/controller/plan/GetAddFriendPlanDetailV1Controller.php b/Server/application/cunkebao/controller/plan/GetAddFriendPlanDetailV1Controller.php index 7ec88c07..55dfaae4 100644 --- a/Server/application/cunkebao/controller/plan/GetAddFriendPlanDetailV1Controller.php +++ b/Server/application/cunkebao/controller/plan/GetAddFriendPlanDetailV1Controller.php @@ -120,7 +120,7 @@ class GetAddFriendPlanDetailV1Controller extends Controller // 解析JSON字段 $sceneConf = json_decode($plan['sceneConf'], true) ?: []; $reqConf = json_decode($plan['reqConf'], true) ?: []; - $reqConf['deveiceGroups'] = $reqConf['device']; + $reqConf['deviceGroups'] = $reqConf['device']; $msgConf = json_decode($plan['msgConf'], true) ?: []; $tagConf = json_decode($plan['tagConf'], true) ?: []; @@ -139,8 +139,8 @@ class GetAddFriendPlanDetailV1Controller extends Controller } - if (!empty($reqConf['deveiceGroups'])){ - $deveiceGroupsOptions = DeviceModel::alias('d') + if (!empty($reqConf['deviceGroups'])){ + $deviceGroupsOptions = DeviceModel::alias('d') ->field([ 'd.id', 'd.imei', 'd.memo', 'd.alive', 'l.wechatId', @@ -149,16 +149,16 @@ class GetAddFriendPlanDetailV1Controller extends Controller ->leftJoin('device_wechat_login l', 'd.id = l.deviceId and l.alive =' . DeviceWechatLoginModel::ALIVE_WECHAT_ACTIVE . ' and l.companyId = d.companyId') ->leftJoin('wechat_account a', 'l.wechatId = a.wechatId') ->order('d.id desc') - ->whereIn('d.id',$reqConf['deveiceGroups']) + ->whereIn('d.id',$reqConf['deviceGroups']) ->select(); - foreach ($deveiceGroupsOptions as &$device) { + foreach ($deviceGroupsOptions as &$device) { $curstomer = WechatCustomerModel::field('friendShip')->where(['wechatId' => $device['wechatId']])->find(); $device['totalFriend'] = $curstomer->friendShip->totalFriend ?? 0; } unset($device); - $reqConf['deveiceGroupsOptions'] = $deveiceGroupsOptions; + $reqConf['deviceGroupsOptions'] = $deviceGroupsOptions; }else{ - $reqConf['deveiceGroupsOptions'] = []; + $reqConf['deviceGroupsOptions'] = []; } diff --git a/Server/application/cunkebao/controller/traffic/GetPotentialListWithInCompanyV1Controller.php b/Server/application/cunkebao/controller/traffic/GetPotentialListWithInCompanyV1Controller.php index a6252698..84137be8 100644 --- a/Server/application/cunkebao/controller/traffic/GetPotentialListWithInCompanyV1Controller.php +++ b/Server/application/cunkebao/controller/traffic/GetPotentialListWithInCompanyV1Controller.php @@ -56,11 +56,11 @@ class GetPotentialListWithInCompanyV1Controller extends BaseController } if (!empty($device)) { - $where[] = ['d.deviceId', '=', $device]; +// $where[] = ['d.deviceId', '=', $device]; } if (!empty($taskId)) { - $where[] = ['t.sceneId', '=', $taskId]; + //$where[] = ['t.sceneId', '=', $taskId]; } $where[] = ['s.companyId', '=', $this->getUserInfo('companyId')]; diff --git a/Server/application/cunkebao/validate/Workbench.php b/Server/application/cunkebao/validate/Workbench.php index c382cfe8..ba9cb462 100644 --- a/Server/application/cunkebao/validate/Workbench.php +++ b/Server/application/cunkebao/validate/Workbench.php @@ -55,11 +55,9 @@ class Workbench extends Validate 'distributeType' => 'requireIf:type,5|in:1,2', 'maxPerDay' => 'requireIf:type,5|number|min:1', 'timeType' => 'requireIf:type,5|in:1,2', - 'startTime' => 'requireIf:type,5|dateFormat:H:i', - 'endTime' => 'requireIf:type,5|dateFormat:H:i', 'accountGroups' => 'requireIf:type,5|array|min:1', // 通用参数 - 'deveiceGroups' => 'requireIf:type,1,2,5|array', + 'deviceGroups' => 'requireIf:type,1,2,5|array', ]; /** @@ -142,8 +140,8 @@ class Workbench extends Validate 'timeType.requireIf' => '请选择时间类型', // 通用提示 - 'deveiceGroups.require' => '请选择设备', - 'deveiceGroups.array' => '设备格式错误', + 'deviceGroups.require' => '请选择设备', + 'deviceGroups.array' => '设备格式错误', 'targetGroups.require' => '请选择目标用户组', 'targetGroups.array' => '目标用户组格式错误', 'accountGroups.requireIf' => '流量分发时必须选择分发账号', @@ -155,7 +153,7 @@ class Workbench extends Validate * 验证场景 */ protected $scene = [ - 'create' => ['name', 'type', 'autoStart', 'deveiceGroups', 'targetGroups', + 'create' => ['name', 'type', 'autoStart', 'deviceGroups', 'targetGroups', 'interval', 'maxLikes', 'startTime', 'endTime', 'contentTypes', 'syncInterval', 'syncCount', 'syncType', 'pushType', 'startTime', 'endTime', 'maxPerDay', 'pushOrder', 'isLoop', 'status', 'wechatGroups', 'contentGroups', @@ -163,7 +161,7 @@ class Workbench extends Validate 'groupNameTemplate', 'maxGroupsPerDay', 'groupSizeMin', 'groupSizeMax', ], 'update_status' => ['id', 'status'], - 'edit' => ['name', 'type', 'autoStart', 'deveiceGroups', 'targetGroups', + 'edit' => ['name', 'type', 'autoStart', 'deviceGroups', 'targetGroups', 'interval', 'maxLikes', 'startTime', 'endTime', 'contentTypes', 'syncInterval', 'syncCount', 'syncType', 'pushType', 'startTime', 'endTime', 'maxPerDay', 'pushOrder', 'isLoop', 'status', 'wechatGroups', 'contentGroups', diff --git a/Touchkebao/emoji-mapping.json b/Touchkebao/emoji-mapping.json new file mode 100644 index 00000000..deb3111d --- /dev/null +++ b/Touchkebao/emoji-mapping.json @@ -0,0 +1,121 @@ +{ + "face": { + "微笑": "smile", + "撇嘴": "pout", + "色": "lust", + "发呆": "daze", + "得意": "proud", + "流泪": "cry", + "害羞": "shy", + "闭嘴": "shut-up", + "睡": "sleep", + "大哭": "sob", + "尴尬": "awkward", + "发怒": "angry", + "调皮": "naughty", + "呲牙": "grin", + "惊讶": "surprised", + "难过": "sad", + "囧": "embarrassed", + "抓狂": "crazy", + "吐": "vomit", + "偷笑": "snicker", + "愉快": "happy", + "白眼": "roll-eyes", + "傲慢": "arrogant", + "困": "sleepy", + "惊恐": "panic", + "憨笑": "silly-smile", + "悠闲": "relaxed", + "咒骂": "curse", + "疑问": "question", + "嘘": "shush", + "晕": "dizzy", + "衰": "unlucky", + "骷髅": "skull", + "敲打": "knock", + "再见": "goodbye", + "擦汗": "wipe-sweat", + "抠鼻": "pick-nose", + "鼓掌": "clap", + "坏笑": "evil-smile", + "右哼哼": "right-hum", + "鄙视": "despise", + "委屈": "wronged", + "快哭了": "about-to-cry", + "阴险": "sinister", + "亲亲": "kiss", + "可怜": "pitiful", + "笑脸": "smiley", + "生病": "sick", + "脸红": "blush", + "破涕为笑": "smile-through-tears", + "恐惧": "fear", + "失望": "disappointed", + "无语": "speechless", + "嘿哈": "hey-ha", + "捂脸": "facepalm", + "机智": "smart", + "皱眉": "frown", + "耶": "yeah", + "吃瓜": "eat-melon", + "加油": "cheer-up", + "汗": "sweat", + "天啊": "oh-my-god", + "Emm": "emm", + "社会社会": "social", + "旺柴": "doge", + "好的": "ok", + "打脸": "slap-face", + "哇": "wow", + "翻白眼": "eye-roll", + "666": "666", + "让我看看": "let-me-see", + "叹气": "sigh", + "苦涩": "bitter", + "裂开": "crack", + "奸笑": "wicked-smile" + }, + "gesture": { + "握手": "handshake", + "胜利": "victory", + "抱拳": "fist-salute", + "勾引": "beckon", + "拳头": "fist", + "OK": "ok", + "合十": "pray", + "强": "strong", + "拥抱": "hug", + "弱": "weak" + }, + "animal": { + "猪头": "pig-head", + "跳跳": "jump", + "发抖": "shiver", + "转圈": "spin" + }, + "blessing": { + "庆祝": "celebrate", + "礼物": "gift", + "红包": "red-envelope", + "發": "fortune", + "福": "blessing", + "烟花": "fireworks", + "爆竹": "firecrackers" + }, + "other": { + "嘴唇": "lips", + "爱心": "heart", + "心碎": "broken-heart", + "啤酒": "beer", + "咖啡": "coffee", + "蛋糕": "cake", + "凋谢": "wither", + "菜刀": "knife", + "炸弹": "bomb", + "便便": "poop", + "太阳": "sun", + "月亮": "moon", + "玫瑰": "rose" + } +} diff --git a/Touchkebao/index.html b/Touchkebao/index.html index 16de6c67..92656ef9 100644 --- a/Touchkebao/index.html +++ b/Touchkebao/index.html @@ -3,7 +3,7 @@ - 存客宝 + 触客宝