@nhdropshipping/y-components 1.0.66 → 1.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/QueryEncapsulation.vue.d.ts +7 -1
- package/dist/components/QueryEncapsulation.vue.d.ts.map +1 -1
- package/dist/components/ytable.vue.d.ts +4 -0
- package/dist/components/ytable.vue.d.ts.map +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +2303 -2253
- package/dist/index.esm.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/components/ybutton.vue","../src/components/yinput.vue","../src/components/ytable.vue","../src/components/yselect.vue","../src/components/ypagination.vue","../src/components/ybadge.vue","../src/components/ydialog.vue","../src/components/ypopover.vue","../src/components/ytime.vue","../src/components/yswitch.vue","../src/components/yimage.vue","../src/components/ydropdown.vue","../src/components/ydrawer.vue","../src/components/ytree.vue","../src/components/QueryEncapsulation.vue","../src/components/ymessage/ymessageToast.vue","../src/components/ymessage/ymessage.ts","../src/components/hintTag.vue","../src/index.ts"],"sourcesContent":["<template>\n <template v-if=\"!isGroup\">\n <button\n class=\"y-btn\"\n :class=\"[\n `y-btn--${variant}`,\n `y-btn--${size}`,\n { 'is-block': block, 'is-loading': loading },\n groupPosition !== 'single' ? 'is-grouped' : '',\n groupPositionClass\n ]\"\n :type=\"htmlType\"\n :disabled=\"disabled || loading\"\n :aria-busy=\"loading ? 'true' : 'false'\"\n :aria-disabled=\"(disabled || loading) ? 'true' : 'false'\"\n @click=\"onClick\"\n >\n <span class=\"content\"><slot /></span>\n </button>\n </template>\n <template v-else>\n <div class=\"y-btn-group\" role=\"group\">\n <button\n v-for=\"(item, index) in groupItems\"\n :key=\"item.value ?? index\"\n class=\"y-btn\"\n :class=\"[\n `y-btn--${item.variant ?? variant}`,\n `y-btn--${item.size ?? size}`,\n 'is-grouped',\n index === 0 ? 'group-pos-start' : (index === (groupItems?.length || 0) - 1 ? 'group-pos-end' : 'group-pos-middle'),\n { 'is-loading': item.loading || loading }\n ]\"\n :type=\"htmlType\"\n :disabled=\"(item.disabled ?? false) || disabled || loading || item.loading\"\n :aria-busy=\"(item.loading || loading) ? 'true' : 'false'\"\n :aria-disabled=\"((item.disabled ?? false) || disabled || loading || item.loading) ? 'true' : 'false'\"\n :aria-label=\"item.ariaLabel || item.label\"\n @click=\"onGroupItemClick(item, $event)\"\n >\n <span class=\"content\">\n <svg v-if=\"item.icon === 'chevron-left'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M12.78 15.22a.75.75 0 01-1.06 0l-5-5a.75.75 0 010-1.06l5-5a.75.75 0 111.06 1.06L8.81 10l3.97 3.97a.75.75 0 010 1.06z\" clip-rule=\"evenodd\" />\n </svg>\n <svg v-else-if=\"item.icon === 'chevron-right'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M7.22 4.78a.75.75 0 011.06 0l5 5a.75.75 0 010 1.06l-5 5a.75.75 0 11-1.06-1.06L11.19 10 7.22 6.03a.75.75 0 010-1.06z\" clip-rule=\"evenodd\" />\n </svg>\n <span v-if=\"item.label && !item.onlyIcon\">{{ item.label }}</span>\n </span>\n </button>\n </div>\n </template>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nconst props = withDefaults(defineProps<{\n htmlType?: 'button' | 'submit' | 'reset'\n variant?: 'primary' | 'secondary' | 'danger' | 'success' | 'info'\n size?: 'tiny' | 'mini' | 'small' | 'medium' | 'large'\n disabled?: boolean\n loading?: boolean\n block?: boolean\n /**\n * 组合按钮位置:\n * - single: 非组合(默认)\n * - start: 组合按钮的第一个\n * - middle: 组合按钮中间\n * - end: 组合按钮最后一个\n */\n groupPosition?: 'single' | 'start' | 'middle' | 'end'\n /**\n * 若提供,则此组件内部渲染为按钮组\n */\n groupItems?: Array<{\n label: string\n value?: string | number\n disabled?: boolean\n loading?: boolean\n variant?: 'primary' | 'secondary' | 'danger' | 'success' | 'info'\n size?: 'tiny' | 'mini' | 'small' | 'medium' | 'large'\n icon?: 'chevron-left' | 'chevron-right'\n onlyIcon?: boolean\n ariaLabel?: string\n }>\n}>(), {\n htmlType: 'button',\n variant: 'primary',\n size: 'medium',\n disabled: false,\n loading: false,\n block: false,\n groupPosition: 'single',\n groupItems: undefined,\n})\n\nconst emit = defineEmits<{\n (e: 'click', ev: MouseEvent): void\n (e: 'group-click', value: string | number | undefined, ev: MouseEvent): void\n}>()\n\nfunction onClick(ev: MouseEvent) {\n if (props.disabled || props.loading) {\n ev.preventDefault()\n ev.stopPropagation()\n return\n }\n emit('click', ev)\n}\n\nconst groupPositionClass = computed(() => {\n switch (props.groupPosition) {\n case 'start':\n return 'group-pos-start'\n case 'middle':\n return 'group-pos-middle'\n case 'end':\n return 'group-pos-end'\n default:\n return 'group-pos-single'\n }\n})\n\nconst isGroup = computed(() => Array.isArray(props.groupItems) && props.groupItems.length > 0)\n\nfunction onGroupItemClick(item: { value?: string | number; disabled?: boolean; loading?: boolean }, ev: MouseEvent) {\n if (props.disabled || props.loading || item.disabled || item.loading) {\n ev.preventDefault()\n ev.stopPropagation()\n return\n }\n emit('group-click', item.value, ev)\n}\n</script>\n\n<style scoped>\n.y-btn {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n border: none;\n border-radius: 10px;\n font-weight: 600;\n cursor: pointer;\n transition: transform 0.05s ease, opacity 0.2s ease;\n outline: none;\n}\n\n/* 尺寸变体 */\n.y-btn--tiny {\n height: 20px;\n padding: 0 6px;\n font-size: 10px;\n border-radius: 3px;\n}\n\n.y-btn--mini {\n height: 24px;\n padding: 0 8px;\n font-size: 11px;\n border-radius: 4px;\n}\n\n.y-btn--small {\n height: 32px;\n padding: 0 12px;\n font-size: 12px;\n border-radius: 5px;\n}\n\n.y-btn--medium {\n height: 44px;\n padding: 0 16px;\n font-size: 14px;\n border-radius: 7px;\n}\n\n.y-btn--large {\n height: 52px;\n padding: 0 20px;\n font-size: 16px;\n border-radius: 8px;\n}\n\n/* 变体样式 */\n.y-btn--primary {\n background: linear-gradient(90deg, #111827, #1f2937);\n color: #fff;\n}\n\n.y-btn--primary:hover { \n background: linear-gradient(90deg, #1f2937, #374151);\n}\n\n.y-btn--secondary {\n background: #f7f7f7;\n color: #374151;\n border: 1px solid #E2E8F0;\n}\n\n.y-btn--secondary:hover {\n background: #ebecee;\n border-color: #9ca3af;\n}\n\n.y-btn--danger {\n background: #c41e3a;\n color: #fff;\n border: 1px solid #c41e3a;\n}\n\n.y-btn--danger:hover {\n background: #ad152e;\n border-color: #ad152e;\n}\n\n.y-btn--success {\n background: #008060;\n color: #fff;\n border: 1px solid #008060;\n}\n\n.y-btn--success:hover {\n background: #006b4f;\n border-color: #006b4f;\n}\n\n.y-btn--info {\n background: #34b4fa;\n color: #fff;\n border: 1px solid #34b4fa;\n}\n\n.y-btn--info:hover {\n background: #1e9bdc;\n border-color: #1e9bdc;\n}\n\n.y-btn:active { \n transform: translateY(1px); \n}\n\n.y-btn.is-block { \n width: 100%; \n}\n\n.y-btn.is-loading { \n cursor: wait; \n opacity: 0.92; \n}\n\n/* 禁用态样式(单按钮与组按钮通用) */\n.y-btn:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.y-btn.is-loading .content { \n opacity: 0; \n}\n\n.y-btn.is-loading::after {\n content: '';\n position: absolute;\n left: 50%;\n top: 50%;\n width: 16px;\n height: 16px;\n transform: translate(-50%, -50%);\n border-radius: 50%;\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: rgba(255,255,255,1);\n animation: spin 0.8s linear infinite;\n}\n\n.y-btn--tiny.is-loading::after {\n width: 10px;\n height: 10px;\n border-width: 1.5px;\n}\n\n.y-btn--mini.is-loading::after {\n width: 12px;\n height: 12px;\n border-width: 1.5px;\n}\n\n.y-btn--small.is-loading::after {\n width: 14px;\n height: 14px;\n border-width: 1.8px;\n}\n\n.y-btn--secondary.is-loading::after {\n border: 2px solid rgba(55, 65, 81, 0.3);\n border-top-color: rgba(55, 65, 81, 1);\n}\n\n.y-btn--danger.is-loading::after {\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: rgba(255,255,255,1);\n}\n\n.y-btn--success.is-loading::after {\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: rgba(255,255,255,1);\n}\n\n.y-btn--info.is-loading::after {\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: rgba(255,255,255,1);\n}\n\n/* 组合按钮样式(连体) */\n.y-btn-group { display: inline-flex; }\n.y-btn.is-grouped {\n border-radius: 0;\n}\n\n.y-btn.group-pos-start {\n border-top-left-radius: 7px;\n border-bottom-left-radius: 7px;\n}\n\n.y-btn.group-pos-middle {\n margin-left: -1px; /* 抵消边框以无缝连接 */\n}\n\n.y-btn.group-pos-end {\n margin-left: -1px; /* 抵消边框以无缝连接 */\n border-top-right-radius: 7px;\n border-bottom-right-radius: 7px;\n}\n\n/* 针对不同尺寸的圆角适配 */\n.y-btn--tiny.group-pos-start { border-top-left-radius: 3px; border-bottom-left-radius: 3px; }\n.y-btn--tiny.group-pos-end { border-top-right-radius: 3px; border-bottom-right-radius: 3px; }\n\n.y-btn--mini.group-pos-start { border-top-left-radius: 4px; border-bottom-left-radius: 4px; }\n.y-btn--mini.group-pos-end { border-top-right-radius: 4px; border-bottom-right-radius: 4px; }\n\n.y-btn--small.group-pos-start { border-top-left-radius: 5px; border-bottom-left-radius: 5px; }\n.y-btn--small.group-pos-end { border-top-right-radius: 5px; border-bottom-right-radius: 5px; }\n\n.y-btn--large.group-pos-start { border-top-left-radius: 8px; border-bottom-left-radius: 8px; }\n.y-btn--large.group-pos-end { border-top-right-radius: 8px; border-bottom-right-radius: 8px; }\n\n/* 提升 hover 时的层级,避免边框覆盖问题 */\n.y-btn.is-grouped { position: relative; z-index: 1; }\n.y-btn.is-grouped:hover { z-index: 2; }\n\n@keyframes spin {\n to { transform: translate(-50%, -50%) rotate(360deg); }\n}\n\n/* 图标尺寸与对齐 */\n.y-btn .icon {\n width: 16px;\n height: 16px;\n}\n\n@media (prefers-color-scheme: dark) {\n .y-btn--primary { \n background: linear-gradient(90deg, #0b1220, #111827); \n }\n \n .y-btn--secondary {\n background: rgba(2, 6, 23, 0.4);\n border-color: rgba(148, 163, 184, 0.18);\n color: #e5eef7;\n }\n \n .y-btn--secondary:hover {\n background: rgba(2, 6, 23, 0.6);\n border-color: rgba(148, 163, 184, 0.3);\n }\n}\n</style>","<template>\n <div class=\"y-input-wrap\" :class=\"{ 'is-block': block }\" :style=\"{ width: width }\">\n <input\n ref=\"inputRef\"\n class=\"y-input\"\n :class=\"`y-input--${size}`\"\n :id=\"id\"\n :name=\"name\"\n :type=\"type\"\n :placeholder=\"inputPlaceholder\"\n :autocomplete=\"autocomplete\"\n :inputmode=\"inputmode\"\n :min=\"min\"\n :max=\"max\"\n :disabled=\"disabled\"\n :required=\"required\"\n :value=\"modelValue\"\n @input=\"onInput\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n @keyup.enter=\"onEnter\"\n @paste=\"onPaste\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\n\nconst props = withDefaults(defineProps<{\n modelValue?: string\n type?: 'text' | 'email' | 'password' | 'search' | 'tel' | 'url' | 'number'\n placeholder?: string\n autocomplete?: string\n inputmode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url'\n id?: string\n name?: string\n disabled?: boolean\n required?: boolean\n block?: boolean\n size?: 'tiny' | 'mini' | 'small' | 'medium' | 'large'\n width?: string\n min?: string | number\n max?: string | number\n clearOnFocus?: boolean\n}>(), {\n modelValue: '',\n type: 'text',\n placeholder: '',\n autocomplete: 'off',\n inputmode: undefined,\n id: undefined,\n name: undefined,\n disabled: false,\n required: false,\n block: false,\n size: 'medium',\n width: '200px',\n min: undefined,\n max: undefined,\n clearOnFocus: false,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n (e: 'enter', value: string): void\n (e: 'paste', value: string): void\n}>()\n\nconst inputRef = ref<HTMLInputElement | null>(null)\nconst previousValue = ref<string>('')\nconst hasChanged = ref<boolean>(false) // 标记用户是否修改了输入值\nconst isFocused = ref<boolean>(false) // 标记是否正在聚焦\nconst inputPlaceholder = ref<string>(props.placeholder || '')\n\nwatch(() => props.placeholder, (val) => {\n if (!isFocused.value) {\n inputPlaceholder.value = val || ''\n }\n})\n\nfunction onInput(ev: Event) {\n const target = ev.target as HTMLInputElement\n hasChanged.value = true // 标记用户已修改值\n emit('update:modelValue', target.value)\n}\n\nfunction onFocus() {\n isFocused.value = true\n if (props.clearOnFocus) {\n // 保存聚焦前的值\n previousValue.value = props.modelValue || ''\n // 重置修改标志\n hasChanged.value = false\n // 使用原值展示提示\n inputPlaceholder.value = previousValue.value || props.placeholder || ''\n // 清空输入框\n emit('update:modelValue', '')\n }\n}\n\nfunction onBlur() {\n isFocused.value = false\n if (props.clearOnFocus) {\n // 只有当用户没有修改值且失去焦点时值为空,才恢复之前的值\n if (!hasChanged.value && (!props.modelValue || props.modelValue === '')) {\n emit('update:modelValue', previousValue.value)\n }\n }\n\n // 如果传入了 min,并且当前值小于 min,则自动校正为最小值\n if (props.min !== undefined && props.modelValue !== undefined && props.modelValue !== '') {\n const current = Number(props.modelValue)\n const minVal = Number(props.min)\n if (!Number.isNaN(current) && !Number.isNaN(minVal) && current < minVal) {\n emit('update:modelValue', String(minVal))\n }\n }\n\n inputPlaceholder.value = props.placeholder || ''\n}\n\nfunction onEnter(ev: KeyboardEvent) {\n const target = ev.target as HTMLInputElement\n emit('enter', target.value)\n}\n\nfunction onPaste(ev: ClipboardEvent) {\n const target = ev.target as HTMLInputElement\n requestAnimationFrame(() => {\n emit('paste', target.value)\n })\n}\n</script>\n\n<style scoped>\n.y-input-wrap { width: 100%; }\n.y-input-wrap.is-block { display: block; width: 100%; }\n\n/* 继承登录页 .input 的视觉规范 */\n.y-input {\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n border: 1px solid #e2e8f0;\n border-radius: 10px;\n padding: 0 12px;\n font-size: 14px;\n outline: none;\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n background: #ffffff;\n color: #0b1a29;\n}\n\n/* 尺寸变体 */\n.y-input--tiny {\n height: 19px;\n padding: 0 6px;\n font-size: 10px;\n border-radius: 4px;\n}\n\n.y-input--mini {\n height: 24px;\n padding: 0 8px;\n font-size: 11px;\n border-radius: 6px;\n}\n\n.y-input--small {\n height: 32px;\n padding: 0 10px;\n font-size: 12px;\n border-radius: 8px;\n}\n\n.y-input--medium {\n height: 44px;\n padding: 0 12px;\n font-size: 14px;\n border-radius: 10px;\n}\n\n.y-input--large {\n height: 52px;\n padding: 0 16px;\n font-size: 16px;\n border-radius: 12px;\n}\n\n.y-input:focus {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59,130,246,0.15);\n}\n\n@media (prefers-color-scheme: dark) {\n .y-input {\n background: rgba(2,6,23,0.4);\n border-color: rgba(148,163,184,0.18);\n color: #e5eef7;\n }\n}\n</style>\n\n\n","<template>\n <div class=\"ytable-container\" ref=\"tableContainer\">\n <!-- 批量操作栏 -->\n <transition name=\"bulk-slide\">\n <div class=\"bulk-bar\" v-if=\"selectedItems.length && showBulkActions\">\n <div class=\"bulk-left\">已选择 {{ selectedItems.length }} 项</div>\n <div class=\"bulk-actions\">\n <slot name=\"bulk-actions\" :selectedItems=\"selectedItems\" :clearSelection=\"clearSelection\">\n <YButton size=\"small\" class=\"btn\" @click=\"clearSelection\">清除选择</YButton>\n </slot>\n </div>\n </div>\n </transition>\n\n <!-- 表格容器 -->\n <div class=\"card\">\n <!-- 表头右上角收起/展开所有提示标签按钮 -->\n <div class=\"table-header-actions\" v-if=\"hasHintTags\">\n <button \n class=\"toggle-all-hints-btn\" \n :class=\"{ 'is-expanded': allHintsExpanded }\"\n @click=\"toggleAllHints\"\n :title=\"allHintsExpanded ? '收起所有提示标签' : '展开所有提示标签'\"\n >\n <svg \n v-if=\"allHintsExpanded\"\n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"toggle-icon\"\n >\n <path \n d=\"M15 18L9 12L15 6\" \n stroke=\"currentColor\" \n stroke-width=\"2\" \n stroke-linecap=\"round\" \n stroke-linejoin=\"round\"\n />\n </svg>\n <svg \n v-else\n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"toggle-icon\"\n >\n <path \n d=\"M9 18L15 12L9 6\" \n stroke=\"currentColor\" \n stroke-width=\"2\" \n stroke-linecap=\"round\" \n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n <!-- 表头固定区域 -->\n <div class=\"table-header\" ref=\"headerRef\">\n <table class=\"table\">\n <colgroup>\n <col v-if=\"props.expandable\" style=\"width: 34px; min-width: 34px;\" />\n <col v-if=\"selectable\" style=\"width: 60px; min-width: 60px;\" />\n <col v-for=\"(col, i) in columns\" :key=\"col.key\"\n :style=\"{ width: headerColWidths[i] || undefined, minWidth: headerColWidths[i] || '80px' }\" />\n </colgroup>\n <thead>\n <tr>\n <th v-if=\"props.expandable\" class=\"col-expand\"></th>\n <!-- 选择列 -->\n <th v-if=\"selectable\" class=\"col-select\">\n <div class=\"select-header\">\n <input \n type=\"checkbox\" \n :checked=\"isAllVisibleSelected\" \n :disabled=\"isAllVisibleDisabled\"\n @change=\"toggleSelectAllVisible\" \n />\n <span v-if=\"selectedItems.length > 0\" class=\"select-count\">{{ selectedItems.length }}</span>\n </div>\n </th>\n <!-- 动态列头 -->\n <th \n v-for=\"(column, colIndex) in columns\" \n :key=\"column.key\" \n :class=\"getColumnClass(column, true)\"\n :style=\"getColumnStyle(column, colIndex, true)\"\n >\n {{ column.title }}\n </th>\n </tr>\n </thead>\n </table>\n </div>\n \n <!-- 表格内容滚动区域 -->\n <div class=\"table-body-wrap\" ref=\"bodyWrapRef\" :class=\"{ 'is-loading': loading, 'is-empty': !pagedData.length && !loading }\" :style=\"{ maxHeight: tableMaxHeight }\">\n <!-- Loading 状态 -->\n <div v-if=\"loading\" class=\"loading-overlay\">\n <div class=\"loading-spinner\"></div>\n <div class=\"loading-text\">加载中...</div>\n </div>\n\n <!-- 空数据覆盖层 -->\n <div v-if=\"!pagedData.length && !loading\" class=\"empty-overlay\">\n <slot name=\"empty\">\n {{ emptyText }}\n </slot>\n </div>\n \n <table class=\"table\" :class=\"{ 'loading-table': loading }\" ref=\"bodyTableRef\">\n <colgroup>\n <col v-if=\"props.expandable\" style=\"width: 34px; min-width: 34px;\" />\n <col v-if=\"selectable\" style=\"width: 60px; min-width: 60px;\" />\n <col v-for=\"(col, i) in columns\" :key=\"col.key\"\n :style=\"{ width: headerColWidths[i] || undefined, minWidth: headerColWidths[i] || '80px' }\" />\n </colgroup>\n <tbody>\n <template v-for=\"(item, index) in pagedData\" :key=\"getRowKey(item, index)\">\n <tr\n :class=\"{ 'row-selected': isRowSelected(item, index) }\"\n @click=\"handleRowClick(item, index)\"\n >\n <td v-if=\"props.expandable\" class=\"col-expand\">\n <button class=\"expand-btn\" type=\"button\" @click.stop=\"toggleRowExpand(getRowKey(item, index))\">\n <span :class=\"['expand-icon', { 'is-open': isRowExpanded(getRowKey(item, index)) }]\"></span>\n </button>\n </td>\n <!-- 选择列 -->\n <td v-if=\"selectable\" class=\"col-select\" @click.stop>\n <input \n type=\"checkbox\" \n :value=\"getRowKey(item, index)\"\n :checked=\"selectedItems.includes(getRowKey(item, index))\" \n :disabled=\"isRowDisabled(item, index)\"\n @change.stop=\"toggleSelect(getRowKey(item, index))\" \n />\n </td>\n <!-- 动态数据列 -->\n <td \n v-for=\"(column, colIndex) in columns\" \n :key=\"column.key\"\n :class=\"getColumnClass(column)\"\n :style=\"getColumnStyle(column, colIndex, false)\"\n >\n <slot \n :name=\"`cell-${column.key}`\" \n :item=\"item\" \n :value=\"getNestedValue(item, column.key)\"\n :index=\"index\"\n >\n {{ formatCellValue(item, column) }}\n </slot>\n </td>\n </tr>\n <tr\n v-if=\"props.expandable && isRowExpanded(getRowKey(item, index))\"\n :key=\"`${getRowKey(item, index)}-expand`\"\n class=\"expand-row\"\n >\n <td :colspan=\"totalTableColumns\" class=\"expand-cell\">\n <slot name=\"expand\" :item=\"item\" :index=\"index\" />\n </td>\n </tr>\n </template>\n </tbody>\n </table>\n </div>\n\n <!-- 分页 -->\n <YPagination\n class=\"align-right\"\n v-if=\"pagination\"\n v-model:current-page=\"currentPage\"\n v-model:page-size=\"pageSize\"\n :loading=\"props.loading\"\n :disable-next=\"shouldDisableNext\"\n :page-size-options=\"pageSizeOptions\"\n @page-change=\"handlePageChange\"\n @page-size-change=\"handlePageSizeChange\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch, onMounted, onUnmounted, nextTick, provide } from 'vue'\n\nexport interface TableColumn {\n key: string\n title: string\n width?: string | number\n align?: 'left' | 'center' | 'right'\n formatter?: (value: any, item: any) => string\n sortable?: boolean\n fixed?: 'left' | 'right'\n}\n\nexport interface TableProps {\n data: any[]\n columns: TableColumn[]\n selectable?: boolean\n showBulkActions?: boolean\n pagination?: boolean\n pageSize?: number\n currentPage?: number\n total?: number\n loading?: boolean\n pageSizeOptions?: Array<{ label: string; value: number }>\n rowKey?: string | ((item: any) => string | number)\n emptyText?: string\n searchKeyword?: string\n searchFields?: string[]\n stickyHeader?: boolean\n expandable?: boolean\n rowDisabled?: (item: any, index: number) => boolean\n selectedItems?: (string | number)[]\n rowSelectable?: boolean\n requireDeselectBeforeSelect?: boolean\n}\n\nconst props = withDefaults(defineProps<TableProps & {\n expandable?: boolean\n rowDisabled?: (item: any, index: number) => boolean\n selectedItems?: (string | number)[]\n rowSelectable?: boolean\n requireDeselectBeforeSelect?: boolean\n}>(), {\n selectable: false,\n showBulkActions: false,\n pagination: true,\n pageSize: 10,\n loading: false,\n pageSizeOptions: () => [\n { label: '1/页', value: 1 },\n { label: '20/页', value: 20 },\n { label: '50/页', value: 50 },\n { label: '100/页', value: 100 }\n ],\n rowKey: 'id',\n emptyText: '无数据',\n searchKeyword: '',\n searchFields: () => [],\n stickyHeader: false,\n rowDisabled: undefined,\n selectedItems: undefined,\n rowSelectable: false,\n requireDeselectBeforeSelect: true\n})\n\nconst emit = defineEmits<{\n edit: [item: any]\n select: [selectedItems: (string | number)[]]\n 'update:selectedItems': [selectedItems: (string | number)[]]\n 'page-change': [page: number]\n 'page-size-change': [size: number]\n 'row-click': [item: any, key: string | number | null]\n}>()\n\n// 响应式数据\nconst currentPage = ref(props.currentPage || 1)\nconst pageSize = ref(props.pageSize)\nconst selectedItems = ref<(string | number)[]>(props.selectedItems || [])\nconst selectedRowKey = ref<(string | number)[]>([])\nconst expandedKeys = ref<Set<string | number>>(new Set())\nconst tableMaxHeight = ref('none')\nconst tableContainer = ref<HTMLElement>()\nconst headerRef = ref<HTMLElement>()\nconst bodyWrapRef = ref<HTMLElement>()\nconst bodyTableRef = ref<HTMLTableElement>()\n// 头部列宽数组:优先使用外部列宽;未传则根据首行内容测量\nconst headerColWidths = ref<string[]>([])\nconst headerWidthMap = ref<Record<string, string>>({})\n\n// 管理所有 hintTag 实例\nconst hintTagInstances = ref<Set<any>>(new Set())\n\n// 计算是否有 hintTag 实例(用于控制按钮显示)\nconst hasHintTags = computed(() => hintTagInstances.value.size > 0)\n\n// 计算当前所有 hintTag 的展开状态\n// 使用 hintTagStateUpdateTrigger 确保响应式更新\nconst allHintsExpanded = computed(() => {\n // 引用 hintTagStateUpdateTrigger 以建立响应式依赖\n void hintTagStateUpdateTrigger.value\n \n if (hintTagInstances.value.size === 0) return false\n let expandedCount = 0\n hintTagInstances.value.forEach((instance) => {\n if (instance && instance.isExpanded) {\n expandedCount++\n }\n })\n return expandedCount === hintTagInstances.value.size\n})\n\n// 计算是否所有 hintTag 都已收起\nconst allHintsCollapsed = computed(() => {\n // 引用 hintTagStateUpdateTrigger 以建立响应式依赖\n void hintTagStateUpdateTrigger.value\n \n if (hintTagInstances.value.size === 0) return true\n let collapsedCount = 0\n hintTagInstances.value.forEach((instance) => {\n if (instance && !instance.isExpanded) {\n collapsedCount++\n }\n })\n return collapsedCount === hintTagInstances.value.size\n})\n\n// 注册 hintTag 实例\nfunction registerHintTag(instance: any) {\n hintTagInstances.value.add(instance)\n}\n\n// 注销 hintTag 实例\nfunction unregisterHintTag(instance: any) {\n hintTagInstances.value.delete(instance)\n}\n\n// 收起所有 hintTag\nfunction collapseAllHints() {\n hintTagInstances.value.forEach((instance) => {\n if (instance && typeof instance.collapse === 'function') {\n instance.collapse()\n }\n })\n}\n\n// 展开所有 hintTag\nfunction expandAllHints() {\n hintTagInstances.value.forEach((instance) => {\n if (instance && typeof instance.expand === 'function') {\n instance.expand()\n }\n })\n}\n\n// 切换所有 hintTag 的展开/收起状态\nfunction toggleAllHints() {\n if (allHintsExpanded.value) {\n // 如果全部展开,则全部收起\n collapseAllHints()\n } else {\n // 否则全部展开\n expandAllHints()\n }\n}\n\n// 用于触发计算属性重新计算的响应式变量\nconst hintTagStateUpdateTrigger = ref(0)\n\n// 通知 hintTag 状态变化的函数\nfunction notifyHintTagStateChange() {\n hintTagStateUpdateTrigger.value++\n}\n\n// 通过 provide 向子组件提供注册方法\nprovide('registerHintTag', registerHintTag)\nprovide('unregisterHintTag', unregisterHintTag)\nprovide('notifyHintTagStateChange', notifyHintTagStateChange)\n\nconst autoColumnKeys = computed(() =>\n props.columns\n .filter((col) => !normalizeWidth(col.width))\n .map((col) => col.key)\n)\n\nfunction getAutoColumnWidth(): string {\n const count = autoColumnKeys.value.length || 1\n const per = 100 / count\n return `${per.toFixed(6)}%`\n}\n\n// 自定义竖向滚动条状态\nconst vTrackRef = ref<HTMLElement>()\nconst vScroll = ref({\n show: false,\n thumbHeight: 40,\n thumbTop: 0\n})\nlet isDragging = false\nlet dragStartY = 0\nlet dragStartScrollTop = 0\n\n// 滚动条宽度(用于表头右侧固定列对齐)\nconst scrollbarWidth = ref(0)\n\nfunction normalizeWidth(width?: string | number): string | undefined {\n if (width === undefined || width === null) return undefined\n if (typeof width === 'number') {\n if (Number.isFinite(width)) {\n return `${width}px`\n }\n return undefined\n }\n const trimmed = String(width).trim()\n if (!trimmed) return undefined\n if (/^\\d+(\\.\\d+)?$/.test(trimmed)) {\n return `${trimmed}px`\n }\n return trimmed\n}\n\nfunction parseWidthNumber(width?: string | number): number | null {\n const normalized = normalizeWidth(width)\n if (!normalized) return null\n const parsed = parseFloat(normalized)\n return Number.isFinite(parsed) ? parsed : null\n}\n\n// 计算属性\n// const totalColumns = computed(() => {\n// let count = props.columns.length\n// if (props.selectable) count++\n// return count\n// })\n\nconst totalTableColumns = computed(() => {\n let count = props.columns.length\n if (props.selectable) count += 1\n if (props.expandable) count += 1\n return count\n})\n\nconst filteredData = computed(() => {\n if (!props.searchKeyword || !props.searchFields.length) {\n return props.data\n }\n \n const keyword = props.searchKeyword.toLowerCase()\n return props.data.filter((item) => {\n return props.searchFields!.some(field => {\n const value = getNestedValue(item, field)\n return String(value).toLowerCase().includes(keyword)\n })\n })\n})\n\n// 移除对 total 的依赖,不再计算总页数\n\nconst pagedData = computed(() => {\n if (!props.pagination) return filteredData.value\n // 服务端分页:不再依赖 total 和 totalPages,直接渲染传入数据\n return filteredData.value\n})\n\nconst isAllVisibleSelected = computed(() => {\n if (!props.selectable) return false\n const visibleKeys = pagedData.value\n .map((item, index) => ({ key: getRowKey(item, index), item, index }))\n .filter(({ item, index }) => !isRowDisabled(item, index))\n .map(({ key }) => key)\n return visibleKeys.length > 0 && visibleKeys.every(key => selectedItems.value.includes(key))\n})\n\nconst isAllVisibleDisabled = computed(() => {\n if (!props.selectable) return false\n // 如果所有可见行都被禁用,则全选按钮也禁用\n const visibleKeys = pagedData.value.map((item, index) => ({ item, index }))\n return visibleKeys.length > 0 && visibleKeys.every(({ item, index }) => isRowDisabled(item, index))\n})\n\n// 判断是否应该禁用下一页按钮\n// 当返回的数据量小于 pageSize 时,说明已经到最后一页了\nconst shouldDisableNext = computed(() => {\n if (!props.pagination) return false\n // 如果当前页数据量小于每页显示条数,说明已经是最后一页\n return pagedData.value.length < pageSize.value\n})\n\n// 计算固定列的累计宽度\nconst fixedLeftWidths = computed(() => {\n const widths: number[] = []\n let cumulativeWidth = props.selectable ? 60 : 0 // 选择列宽度\n \n for (let i = 0; i < props.columns.length; i++) {\n const col = props.columns[i]\n if (col.fixed === 'left') {\n let width = 80 // 默认宽度\n const parsedWidth = parseWidthNumber(col.width)\n if (parsedWidth !== null) {\n width = parsedWidth\n } else if (headerColWidths.value[i]) {\n const parsedHeaderWidth = parseWidthNumber(headerColWidths.value[i])\n width = parsedHeaderWidth ?? width\n }\n widths.push(cumulativeWidth)\n cumulativeWidth += width\n }\n }\n return widths\n})\n\nconst fixedRightWidths = computed(() => {\n const widths: number[] = []\n let cumulativeWidth = 0\n \n // 从右往左计算,但需要保证索引顺序正确\n // 先收集所有右侧固定列的宽度和索引\n const rightFixedColumns: Array<{ index: number; width: number }> = []\n for (let i = props.columns.length - 1; i >= 0; i--) {\n const col = props.columns[i]\n if (col.fixed === 'right') {\n let width = 80 // 默认宽度\n const parsedWidth = parseWidthNumber(col.width)\n if (parsedWidth !== null) {\n width = parsedWidth\n } else if (headerColWidths.value[i]) {\n const parsedHeaderWidth = parseWidthNumber(headerColWidths.value[i])\n width = parsedHeaderWidth ?? width\n }\n rightFixedColumns.push({ index: i, width })\n }\n }\n \n // 从右到左计算累计宽度(数组顺序:最右边的列索引最小)\n // widths[i] 对应第 i 个右侧固定列(从右往左数)的 right 偏移量\n for (let i = 0; i < rightFixedColumns.length; i++) {\n widths.push(cumulativeWidth)\n cumulativeWidth += rightFixedColumns[i].width\n }\n \n return widths\n})\n\n// 获取固定列的索引位置(用于查找对应的累计宽度)\nfunction getFixedColumnIndex(columnIndex: number, fixed: 'left' | 'right'): number {\n if (fixed === 'left') {\n let count = 0\n for (let i = 0; i < columnIndex; i++) {\n if (props.columns[i].fixed === 'left') {\n count++\n }\n }\n return count\n } else {\n // 对于右侧固定列,计算从右往左是第几个(索引0是最右边的)\n let count = 0\n for (let i = props.columns.length - 1; i > columnIndex; i--) {\n if (props.columns[i].fixed === 'right') {\n count++\n }\n }\n return count\n }\n}\n\n// 方法\nfunction getRowKey(item: any, index: number): string | number {\n if (typeof props.rowKey === 'function') {\n return props.rowKey(item)\n }\n return item[props.rowKey] || index\n}\n\n// 检查行是否被禁用\nfunction isRowDisabled(item: any, index: number): boolean {\n if (props.rowDisabled && typeof props.rowDisabled === 'function') {\n return props.rowDisabled(item, index)\n }\n return false\n}\n\nfunction isRowExpanded(key: string | number) {\n return expandedKeys.value.has(key)\n}\n\nfunction toggleRowExpand(key: string | number) {\n if (expandedKeys.value.has(key)) {\n expandedKeys.value.delete(key)\n } else {\n expandedKeys.value.add(key)\n }\n}\n\nfunction getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj)\n}\n\nfunction getColumnClass(column: TableColumn, isHeader = false): string {\n const classes = [] as string[]\n if (column.align) {\n classes.push(`text-${column.align}`)\n }\n if (column.fixed === 'right') {\n classes.push('col-fixed-right')\n if (isHeader) classes.push('col-fixed-right-header')\n }\n if (column.fixed === 'left') {\n classes.push('col-fixed-left')\n if (isHeader) classes.push('col-fixed-left-header')\n }\n return classes.join(' ')\n}\n\nfunction getColumnStyle(column: TableColumn, columnIndex: number, isHeader: boolean): Record<string, string> {\n const style: Record<string, string> = {}\n \n const normalizedWidth = normalizeWidth(column.width)\n if (normalizedWidth) {\n // 如果设置了固定宽度,使用固定宽度\n style.width = normalizedWidth\n style.minWidth = normalizedWidth\n style.maxWidth = normalizedWidth\n } else {\n // 如果没有设置宽度,使用均等分配的宽度,确保列宽稳定\n const autoWidth = getAutoColumnWidth()\n style.width = autoWidth\n style.minWidth = autoWidth\n style.maxWidth = autoWidth\n }\n \n // 处理固定列的位置\n if (column.fixed === 'left') {\n const fixedIndex = getFixedColumnIndex(columnIndex, 'left')\n const leftOffset = fixedLeftWidths.value[fixedIndex] || 0\n style.left = `${leftOffset}px`\n style.zIndex = isHeader ? `${10 + fixedIndex}` : `${5 + fixedIndex}`\n } else if (column.fixed === 'right') {\n const fixedIndex = getFixedColumnIndex(columnIndex, 'right')\n const rightOffset = fixedRightWidths.value[fixedIndex] || 0\n \n // 对于表头的右侧固定列,减去2px以精确对齐\n // 这可能是因为边框或间距导致的细微差异\n if (isHeader) {\n style.right = `${rightOffset - 3}px`\n } else {\n style.right = `${rightOffset}px`\n }\n \n style.zIndex = isHeader ? `${10 + fixedIndex}` : `${5 + fixedIndex}`\n }\n \n return style\n}\n\nfunction formatCellValue(item: any, column: TableColumn): string {\n const value = getNestedValue(item, column.key)\n if (column.formatter) {\n return column.formatter(value, item)\n }\n return value || ''\n}\n\nfunction toggleSelect(key: string | number) {\n // 找到对应的行数据\n const rowData = pagedData.value.find((item, index) => getRowKey(item, index) === key)\n const rowIndex = pagedData.value.findIndex((item, index) => getRowKey(item, index) === key)\n \n // 如果行被禁用,不允许选择\n if (rowData && rowIndex >= 0 && isRowDisabled(rowData, rowIndex)) {\n return\n }\n \n if (selectedItems.value.includes(key)) {\n selectedItems.value = selectedItems.value.filter(x => x !== key)\n } else {\n selectedItems.value = [...selectedItems.value, key]\n }\n emit('select', selectedItems.value)\n emit('update:selectedItems', selectedItems.value)\n}\n\nfunction toggleSelectAllVisible() {\n // 只处理未禁用的行\n const visibleKeys = pagedData.value\n .map((item, index) => ({ key: getRowKey(item, index), item, index }))\n .filter(({ item, index }) => !isRowDisabled(item, index))\n .map(({ key }) => key)\n \n if (visibleKeys.length === 0) return\n \n if (visibleKeys.every(key => selectedItems.value.includes(key))) {\n selectedItems.value = selectedItems.value.filter(key => !visibleKeys.includes(key))\n } else {\n const union = new Set([...selectedItems.value, ...visibleKeys])\n selectedItems.value = Array.from(union)\n }\n emit('select', selectedItems.value)\n emit('update:selectedItems', selectedItems.value)\n}\n\nfunction clearSelection() {\n selectedItems.value = []\n emit('select', selectedItems.value)\n emit('update:selectedItems', selectedItems.value)\n}\n\n// 行点击选中处理\nfunction handleRowClick(item: any, index: number) {\n if (!props.rowSelectable) return\n \n const key = getRowKey(item, index)\n \n // 如果行被禁用,不允许选择\n if (isRowDisabled(item, index)) {\n return\n }\n \n // 根据 requireDeselectBeforeSelect 决定行为\n if (props.requireDeselectBeforeSelect) {\n // 模式1:可以多选,再次点击为取消\n if (selectedRowKey.value.includes(key)) {\n // 如果已选中,则取消选中\n selectedRowKey.value = selectedRowKey.value.filter(k => k !== key)\n emit('row-click', item, null)\n } else {\n // 如果未选中,则添加到选中列表\n selectedRowKey.value = [...selectedRowKey.value, key]\n emit('row-click', item, key)\n }\n } else {\n // 模式2:点击其他行时,自动切换选中状态(单选模式)\n if (selectedRowKey.value.includes(key)) {\n selectedRowKey.value = []\n emit('row-click', item, null)\n } else {\n selectedRowKey.value = [key]\n emit('row-click', item, key)\n }\n }\n}\n\n// 判断行是否被选中\nfunction isRowSelected(item: any, index: number): boolean {\n if (!props.rowSelectable) return false\n const key = getRowKey(item, index)\n return selectedRowKey.value.includes(key)\n}\n\n// 监听外部传入的 selectedItems prop,同步到内部状态\nwatch(() => props.selectedItems, (newVal) => {\n if (newVal !== undefined && Array.isArray(newVal)) {\n // 只有当外部传入的值与内部值不同时才更新,避免循环更新\n const currentSet = new Set(selectedItems.value)\n const newSet = new Set(newVal)\n if (currentSet.size !== newSet.size || \n ![...currentSet].every(key => newSet.has(key))) {\n selectedItems.value = [...newVal]\n }\n } else if (newVal === undefined && selectedItems.value.length > 0) {\n // 如果外部传入 undefined 且内部有选中项,清空内部选中状态\n selectedItems.value = []\n }\n}, { deep: true, immediate: true })\n\n// 监听搜索关键词变化,重置页码\nwatch(() => props.searchKeyword, () => {\n currentPage.value = 1\n})\n\n// 监听数据变化,重置页码(仅在客户端分页时)并清空选中行\nwatch(() => props.data, () => {\n // 只有在没有外部 total 的情况下(客户端分页)才重置页码\n if (!props.total) {\n currentPage.value = 1\n }\n // 数据变化时清空选中行状态\n if (props.rowSelectable) {\n selectedRowKey.value = []\n }\n}, { deep: true })\n\n// 分页事件处理\nfunction handlePageChange(page: number) {\n currentPage.value = page\n // 分页变化时清空选中行状态\n if (props.rowSelectable) {\n selectedRowKey.value = []\n }\n emit('page-change', page)\n}\n\nfunction handlePageSizeChange(size: number) {\n pageSize.value = size\n currentPage.value = 1 // 切换每页条数后重置到第一页\n // 分页大小变化时清空选中行状态\n if (props.rowSelectable) {\n selectedRowKey.value = []\n }\n emit('page-size-change', size)\n}\n\n// 父组件重置分页时,同步内部选中状态\nwatch(() => props.currentPage, (val) => {\n const next = typeof val === 'number' && val > 0 ? val : 1\n if (currentPage.value !== next) currentPage.value = next\n})\n\nwatch(() => props.pageSize, (val) => {\n const next = typeof val === 'number' && val > 0 ? val : 10\n if (pageSize.value !== next) pageSize.value = next\n})\n\n// 计算表格最大高度\nfunction calculateTableMaxHeight() {\n if (!tableContainer.value) return\n \n nextTick(() => {\n const containerRect = tableContainer.value!.getBoundingClientRect()\n const viewportHeight = window.innerHeight\n const containerTop = containerRect.top\n \n // 获取表头高度\n const headerElement = tableContainer.value!.querySelector('.table-header') as HTMLElement\n const headerHeight = headerElement ? headerElement.offsetHeight : 40\n \n // 获取分页组件高度\n let paginationHeight = 0\n if (props.pagination) {\n const paginationElement = tableContainer.value!.querySelector('.ypagination') as HTMLElement\n paginationHeight = paginationElement ? paginationElement.offsetHeight : 60\n }\n \n // 获取批量操作栏高度\n const bulkBarElement = tableContainer.value!.querySelector('.bulk-bar') as HTMLElement\n const bulkBarHeight = bulkBarElement ? bulkBarElement.offsetHeight : 0\n \n // 计算可用空间\n // 有分页时:减去表头高度、分页组件高度、批量操作栏高度、安全边距(20px)\n // 无分页时:减去表头高度、批量操作栏高度、安全边距(40px,离底部更远)\n const safeMargin = 20\n const reservedHeight = headerHeight + paginationHeight + bulkBarHeight + safeMargin\n const availableHeight = viewportHeight - containerTop - reservedHeight\n \n // 设置最小高度为200px,最大高度为可用空间\n const minHeight = 200\n const maxHeight = Math.max(minHeight, availableHeight)\n \n // 获取表格内容高度\n const tableContent = tableContainer.value!.querySelector('.table-body-wrap .table') as HTMLElement\n if (tableContent) {\n const contentHeight = tableContent.offsetHeight\n \n // 如果内容高度超过可用空间,则限制高度并显示滚动条\n if (contentHeight > availableHeight) {\n tableMaxHeight.value = `${maxHeight}px`\n } else {\n // 如果内容高度小于可用空间,则不限制高度\n tableMaxHeight.value = 'none'\n }\n }\n })\n}\n\n// 同步表头与内容的横向滚动\nlet isSyncingScroll = false // 防止循环同步\nfunction syncHeaderScroll() {\n if (!headerRef.value || !bodyWrapRef.value || isSyncingScroll) return\n if (headerRef.value.scrollLeft !== bodyWrapRef.value.scrollLeft) {\n isSyncingScroll = true\n headerRef.value.scrollLeft = bodyWrapRef.value.scrollLeft\n requestAnimationFrame(() => {\n isSyncingScroll = false\n })\n }\n}\n\n// 同步表头滚动到内容区域\nfunction syncBodyScroll() {\n if (!headerRef.value || !bodyWrapRef.value || isSyncingScroll) return\n if (bodyWrapRef.value.scrollLeft !== headerRef.value.scrollLeft) {\n isSyncingScroll = true\n bodyWrapRef.value.scrollLeft = headerRef.value.scrollLeft\n requestAnimationFrame(() => {\n isSyncingScroll = false\n })\n }\n}\n\n// 计算虚拟竖向滚动条尺寸与位置\nfunction updateVirtualScrollbar() {\n nextTick(() => {\n if (!bodyWrapRef.value) return\n const wrap = bodyWrapRef.value\n const contentHeight = wrap.scrollHeight\n const viewport = wrap.clientHeight\n const scrollTop = wrap.scrollTop\n const needVBar = contentHeight > viewport + 1\n vScroll.value.show = needVBar\n if (!needVBar) return\n\n const minThumb = 24\n const ratio = viewport / contentHeight\n const trackHeight = vTrackRef.value ? vTrackRef.value.clientHeight : viewport\n const thumbHeight = Math.max(minThumb, Math.floor(trackHeight * ratio))\n vScroll.value.thumbHeight = thumbHeight\n\n const maxThumbTop = Math.max(0, trackHeight - thumbHeight)\n const maxScrollTop = Math.max(1, contentHeight - viewport)\n vScroll.value.thumbTop = Math.min(maxThumbTop, Math.floor((scrollTop / maxScrollTop) * maxThumbTop))\n })\n}\n\nfunction onThumbMousemove(e: MouseEvent) {\n if (!isDragging || !bodyWrapRef.value || !vTrackRef.value) return\n e.preventDefault()\n const trackHeight = vTrackRef.value.clientHeight\n const maxThumbTop = Math.max(0, trackHeight - vScroll.value.thumbHeight)\n const wrap = bodyWrapRef.value\n const contentHeight = wrap.scrollHeight\n const viewport = wrap.clientHeight\n const maxScrollTop = Math.max(1, contentHeight - viewport)\n const deltaY = e.clientY - dragStartY\n const scrollDelta = (deltaY / Math.max(1, maxThumbTop)) * maxScrollTop\n wrap.scrollTop = Math.min(maxScrollTop, Math.max(0, dragStartScrollTop + scrollDelta))\n updateVirtualScrollbar()\n}\n\nfunction onThumbMouseup() {\n isDragging = false\n window.removeEventListener('mousemove', onThumbMousemove)\n window.removeEventListener('mouseup', onThumbMouseup)\n}\n\n// function onTrackMousedown(e: MouseEvent) {\n// if (!bodyWrapRef.value || !vTrackRef.value) return\n// // 点击轨道跳转:将滑块中心移动到点击处\n// const rect = vTrackRef.value.getBoundingClientRect()\n// const y = e.clientY - rect.top\n// const trackHeight = vTrackRef.value.clientHeight\n// const thumbHeight = vScroll.value.thumbHeight\n// const targetTop = Math.min(Math.max(0, y - thumbHeight / 2), Math.max(0, trackHeight - thumbHeight))\n//\n// const wrap = bodyWrapRef.value\n// const contentHeight = wrap.scrollHeight\n// const viewport = wrap.clientHeight\n// const maxScrollTop = Math.max(1, contentHeight - viewport)\n// const maxThumbTop = Math.max(1, trackHeight - thumbHeight)\n// const targetScrollTop = (targetTop / maxThumbTop) * maxScrollTop\n// wrap.scrollTop = targetScrollTop\n// updateVirtualScrollbar()\n// }\n\n// 计算/测量列宽:对未设置 width 的列,使用首行单元格的内容宽度\nfunction measureAutoColumnWidths() {\n nextTick(() => {\n // 如果已完整测量过列宽,则不再重复测量,避免分页切换时轻微跳动\n if (headerColWidths.value.length === props.columns.length && headerColWidths.value.every(w => !!w)) {\n return\n }\n const widths: string[] = []\n // 先用 props.columns 中显式宽度填充\n props.columns.forEach((col, index) => {\n const normalizedWidth = normalizeWidth(col.width)\n if (normalizedWidth) {\n widths.push(normalizedWidth)\n headerWidthMap.value[col.key] = normalizedWidth\n } else if (headerWidthMap.value[col.key]) {\n widths.push(headerWidthMap.value[col.key])\n } else {\n const fallback = headerColWidths.value[index]\n if (fallback) {\n widths.push(fallback)\n headerWidthMap.value[col.key] = fallback\n } else {\n const autoWidth = getAutoColumnWidth()\n widths.push(autoWidth)\n headerWidthMap.value[col.key] = autoWidth\n }\n }\n })\n\n const firstRow = bodyTableRef.value?.querySelector('tbody tr') as HTMLTableRowElement | null\n if (firstRow) {\n // 计算 data 列在 tbody 中的起始索引\n const startIndex = props.selectable ? 1 : 0\n const tds = Array.from(firstRow.children) as HTMLElement[]\n for (let i = 0; i < props.columns.length; i++) {\n if (!widths[i]) {\n const td = tds[startIndex + i] as HTMLElement | undefined\n if (td && td.clientWidth > 0) {\n const measured = `${td.clientWidth}px`\n widths[i] = measured\n headerWidthMap.value[props.columns[i].key] = measured\n } else {\n const autoWidth = getAutoColumnWidth()\n widths[i] = autoWidth\n headerWidthMap.value[props.columns[i].key] = autoWidth\n }\n }\n }\n } else {\n // 没有数据时,尽量沿用上一次测量结果,避免列宽跳动\n for (let i = 0; i < widths.length; i++) {\n if (!widths[i]) {\n const stored = headerWidthMap.value[props.columns[i]?.key || '']\n widths[i] = stored || headerColWidths.value[i] || '80px'\n if (props.columns[i]) {\n headerWidthMap.value[props.columns[i].key] = widths[i]\n }\n }\n }\n }\n headerColWidths.value = widths\n })\n}\n\n// 窗口大小变化和滚动时重新计算\nfunction handleResize() {\n calculateTableMaxHeight()\n updateHeaderScrollbarGutter()\n}\n\n// 监听数据变化,重新计算高度\nwatch(() => props.data, () => {\n nextTick(() => {\n calculateTableMaxHeight()\n // 不在数据变化时重新测量列宽,避免分页切换引起的列宽抖动\n syncHeaderScroll()\n updateHeaderScrollbarGutter()\n expandedKeys.value.clear()\n })\n}, { deep: true })\n\n// 监听分页变化,重新计算高度\nwatch([currentPage, pageSize], () => {\n nextTick(() => {\n calculateTableMaxHeight()\n // 分页切换不再重新测量列宽\n syncHeaderScroll()\n updateHeaderScrollbarGutter()\n })\n})\n\n// 列配置变化时,重置并测量列宽\nwatch(() => props.columns, () => {\n const nextWidths: string[] = []\n const nextMap: Record<string, string> = { ...headerWidthMap.value }\n\n props.columns.forEach((col, idx) => {\n const normalizedWidth = normalizeWidth(col.width)\n if (normalizedWidth) {\n nextWidths.push(normalizedWidth)\n nextMap[col.key] = normalizedWidth\n } else if (nextMap[col.key]) {\n nextWidths.push(nextMap[col.key])\n } else if (headerColWidths.value[idx]) {\n nextWidths.push(headerColWidths.value[idx])\n nextMap[col.key] = headerColWidths.value[idx]\n } else {\n nextWidths.push('')\n }\n })\n\n // 移除已经不存在的列的缓存\n const currentKeys = new Set(props.columns.map(col => col.key))\n Object.keys(nextMap).forEach((key) => {\n if (!currentKeys.has(key)) {\n delete nextMap[key]\n }\n })\n\n headerWidthMap.value = nextMap\n headerColWidths.value = nextWidths\n\n nextTick(() => {\n measureAutoColumnWidths()\n syncHeaderScroll()\n updateHeaderScrollbarGutter()\n })\n}, { deep: true })\n\n// 监听选中项变化,重新计算高度(批量操作栏显示/隐藏)\nwatch(() => selectedItems.value, () => {\n nextTick(() => {\n calculateTableMaxHeight()\n updateHeaderScrollbarGutter()\n })\n}, { deep: true })\n\n// 监听 loading 状态变化,更新滚动条补偿\nwatch(() => props.loading, () => {\n nextTick(() => {\n updateHeaderScrollbarGutter()\n })\n})\n\n// 生命周期\nonMounted(() => {\n nextTick(() => {\n calculateTableMaxHeight()\n measureAutoColumnWidths()\n updateHeaderScrollbarGutter()\n updateVirtualScrollbar()\n })\n window.addEventListener('resize', handleResize)\n window.addEventListener('scroll', handleResize, true)\n // 监听内容滚动以同步表头\n bodyWrapRef.value?.addEventListener('scroll', () => {\n syncHeaderScroll()\n updateVirtualScrollbar()\n // 滚动时也更新滚动条补偿(因为滚动可能导致内容高度变化)\n updateHeaderScrollbarGutter()\n }, { passive: true })\n // 监听表头滚动以同步内容区域\n headerRef.value?.addEventListener('scroll', () => {\n syncBodyScroll()\n }, { passive: true })\n // 初始同步一次\n nextTick(() => syncHeaderScroll())\n \n // 使用 ResizeObserver 监听内容区域大小变化,实时更新滚动条补偿\n if (bodyWrapRef.value && typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(() => {\n updateHeaderScrollbarGutter()\n })\n resizeObserver.observe(bodyWrapRef.value)\n }\n})\n\nonUnmounted(() => {\n window.removeEventListener('resize', handleResize)\n window.removeEventListener('scroll', handleResize, true)\n bodyWrapRef.value?.removeEventListener('scroll', syncHeaderScroll)\n headerRef.value?.removeEventListener('scroll', syncBodyScroll)\n window.removeEventListener('mousemove', onThumbMousemove)\n window.removeEventListener('mouseup', onThumbMouseup)\n // 清理 ResizeObserver\n if (resizeObserver) {\n resizeObserver.disconnect()\n resizeObserver = null\n }\n})\n\n// 为表头添加与内容滚动条同宽的内边距,避免列错位\nlet lastScrollbarWidth = -1 // 缓存上次的滚动条宽度,避免不必要的 DOM 操作\nfunction updateHeaderScrollbarGutter() {\n if (!headerRef.value || !bodyWrapRef.value) return\n \n // 使用 requestAnimationFrame 确保在浏览器重绘后计算\n requestAnimationFrame(() => {\n if (!headerRef.value || !bodyWrapRef.value) return\n \n const wrap = bodyWrapRef.value\n // 计算滚动条宽度(容器总宽度 - 内容可见宽度)\n // 注意:这里需要考虑竖向滚动条(占用右侧空间)\n const currentScrollbarWidth = Math.ceil(wrap.offsetWidth - wrap.clientWidth)\n \n // 更新响应式变量\n scrollbarWidth.value = currentScrollbarWidth\n \n // 只有当滚动条宽度发生变化时才更新 DOM,避免不必要的操作\n if (currentScrollbarWidth !== lastScrollbarWidth) {\n lastScrollbarWidth = currentScrollbarWidth\n const headerTable = headerRef.value.querySelector('.table') as HTMLElement\n const bodyTable = bodyTableRef.value\n \n if (headerTable && bodyTable) {\n // 先移除之前的样式,确保测量准确\n headerRef.value.style.paddingRight = '0px'\n headerTable.style.width = ''\n headerTable.style.marginRight = ''\n \n // 测量表头和内容区域的 table 实际宽度\n // const headerTableWidth = headerTable.offsetWidth\n // const bodyTableWidth = bodyTable.offsetWidth\n \n // 计算宽度差异\n // const widthDiff = bodyTableWidth - headerTableWidth\n \n if (currentScrollbarWidth > 0) {\n // 如果有滚动条,需要补偿\n // 表头容器的 padding-right 用于补偿滚动条宽度\n headerRef.value.style.paddingRight = `${currentScrollbarWidth}px`\n // table 的宽度设置为 100%(相对于容器内容区域,不包括 padding)\n // 这样表头 table 的宽度就会和内容区域 table 的实际宽度一致\n headerTable.style.width = '100%'\n // 使用负 margin 让 table 向右偏移,填充 padding 区域\n // 这样表头 table 的右边缘就会和内容区域 table 的右边缘对齐\n headerTable.style.marginRight = `-${currentScrollbarWidth}px`\n } else {\n headerRef.value.style.paddingRight = '0px'\n headerTable.style.width = '100%'\n headerTable.style.marginRight = '0px'\n }\n }\n }\n })\n}\n\n// 使用 ResizeObserver 监听内容区域大小变化,自动更新滚动条补偿\nlet resizeObserver: ResizeObserver | null = null\n\n// 清理 hintTag 实例(组件卸载时)\nonUnmounted(() => {\n hintTagInstances.value.clear()\n})\n</script>\n\n<style scoped lang=\"less\">\n.ytable-container {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.bulk-bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 10px;\n background: #FFFFFF;\n border: 1px solid #dfe3e8;\n border-radius: 6px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.bulk-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* 批量操作栏出现/消失动画 */\n.bulk-slide-enter-active,\n.bulk-slide-leave-active {\n transition: all 0.2s ease;\n}\n\n.bulk-slide-enter-from,\n.bulk-slide-leave-to {\n transform: translateY(-8px);\n opacity: 0;\n}\n\n.card {\n border-radius: 6px;\n background: #fff;\n padding: 4px 5px;\n box-shadow: 0rem 0.3125rem 0.3125rem -0.15625rem rgba(0, 0, 0, 0.03),\n 0rem 0.1875rem 0.1875rem -0.09375rem rgba(0, 0, 0, 0.02),\n 0rem 0.125rem 0.125rem -0.0625rem rgba(0, 0, 0, 0.02),\n 0rem 0.0625rem 0.0625rem -0.03125rem rgba(0, 0, 0, 0.03),\n 0rem 0.03125rem 0.03125rem 0rem rgba(0, 0, 0, 0.04),\n 0rem 0rem 0rem 0.0625rem rgba(0, 0, 0, 0.06);\n position: relative;\n}\n\n/* 表头右上角操作按钮区域 */\n.table-header-actions {\n position: absolute;\n top: 8px;\n right: 12px;\n z-index: 10;\n pointer-events: auto;\n}\n\n.toggle-all-hints-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n background: #ffffff;\n color: #666666;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n cursor: pointer;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);\n transition: all 0.2s ease;\n padding: 0;\n}\n\n.toggle-all-hints-btn:hover {\n color: #333333;\n background: #f5f5f5;\n border-color: #d1d5db;\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);\n}\n\n.toggle-all-hints-btn:active {\n transform: scale(0.95);\n}\n\n.toggle-all-hints-btn.is-expanded {\n color: #008060;\n border-color: #008060;\n}\n\n.toggle-all-hints-btn.is-expanded:hover {\n background: #f0f9f7;\n border-color: #006b52;\n}\n\n.toggle-icon {\n width: 16px;\n height: 16px;\n transition: transform 0.2s ease;\n}\n\n/* 表头固定区域 */\n.table-header {\n width: 100%;\n overflow-x: auto; /* 允许水平滚动 */\n overflow-y: hidden; /* 禁止垂直滚动 */\n /* 隐藏滚动条,但保持滚动功能 */\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE/Edge */\n /* 通过 JavaScript 动态设置 table 的 margin-right 来补偿滚动条宽度 */\n box-sizing: border-box;\n}\n\n/* 隐藏表头区域的滚动条 */\n.table-header::-webkit-scrollbar {\n display: none;\n}\n\n/* 表格内容滚动区域 */\n.table-body-wrap {\n width: 100%;\n overflow: auto;\n position: relative;\n padding-right: 0; // 右侧不留 padding\n /* 滚动条会占用空间,通过动态补偿表头来保持对齐 */\n}\n\n// 加载中时,确保最小高度存在,避免高度被收缩\n.table-body-wrap.is-loading {\n min-height: 200px;\n}\n\n// 空数据时保证最小高度,用于承载覆盖层\n.table-body-wrap.is-empty {\n min-height: 200px;\n}\n\n// 空数据覆盖层(不改变表格布局,避免副作用)\n.empty-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n pointer-events: none; // 允许滚动容器继续滚动(若需要)\n}\n\n// 仅在卡片内的滚动区域做“贴边”处理\n.card > .table-body-wrap {\n width: calc(100% + 4px);\n margin-right: -4px; // 抵消 .card 的 5px 右内边距\n}\n\n// 移除已废弃的 overflow: overlay,使用动态计算滚动条宽度来保持对齐\n\n/* 滚动条样式 - 只在内容区域 */\n.table-body-wrap::-webkit-scrollbar {\n width: 4px;\n height: 6px;\n}\n// 隐藏原生竖向滚动条(保留横向)\n.table-body-wrap::-webkit-scrollbar:vertical {\n width: 0;\n}\n\n// 明确指定水平滚动条厚度与侧边一致\n.table-body-wrap::-webkit-scrollbar:horizontal {\n height: 6px;\n}\n\n.table-body-wrap::-webkit-scrollbar-track {\n background: transparent;\n position: relative;\n \n // 添加顶部箭头\n &::before {\n content: '';\n position: absolute;\n top: 1px;\n left: 50%;\n transform: translateX(-50%);\n width: 0;\n height: 0;\n border-left: 2px solid transparent;\n border-right: 2px solid transparent;\n border-bottom: 3px solid #9ca3af;\n z-index: 1;\n transition: all 0.2s ease;\n }\n \n // 添加底部箭头\n &::after {\n content: '';\n position: absolute;\n bottom: 1px;\n left: 50%;\n transform: translateX(-50%);\n width: 0;\n height: 0;\n border-left: 2px solid transparent;\n border-right: 2px solid transparent;\n border-top: 3px solid #9ca3af;\n z-index: 1;\n transition: all 0.2s ease;\n }\n}\n\n// 水平滚动条轨道与左右箭头\n.table-body-wrap::-webkit-scrollbar-track:horizontal {\n background: transparent;\n position: relative;\n}\n\n.table-body-wrap::-webkit-scrollbar-track:horizontal::before {\n content: '';\n position: absolute;\n left: 1px;\n top: 50%;\n transform: translateY(-50%);\n width: 0;\n height: 0;\n border-top: 2px solid transparent;\n border-bottom: 2px solid transparent;\n border-right: 3px solid #9ca3af; // 左侧指向右的三角\n z-index: 1;\n transition: all 0.2s ease;\n}\n\n.table-body-wrap::-webkit-scrollbar-track:horizontal::after {\n content: '';\n position: absolute;\n right: 1px;\n top: 50%;\n transform: translateY(-50%);\n width: 0;\n height: 0;\n border-top: 2px solid transparent;\n border-bottom: 2px solid transparent;\n border-left: 3px solid #9ca3af; // 右侧指向左的三角\n z-index: 1;\n transition: all 0.2s ease;\n}\n\n.table-body-wrap::-webkit-scrollbar-thumb {\n background: #bac0ca;\n border-radius: 2px;\n transition: all 0.2s ease;\n margin: 4px 0; // 为箭头留出空间\n \n &:hover {\n background: #6b7280;\n }\n \n &:active {\n background: #4b5563;\n }\n}\n\n// 水平 thumb 预留左右边距,避免遮挡左右箭头\n.table-body-wrap::-webkit-scrollbar-thumb:horizontal {\n margin: 0 4px;\n}\n\n.table-body-wrap::-webkit-scrollbar-corner {\n background: transparent;\n}\n\n// Firefox 滚动条厚度与颜色(与侧边一致)\n.table-body-wrap {\n scrollbar-width: thin;\n scrollbar-color: #bac0ca transparent;\n}\n\n// 滚动条按钮样式(兼容性)\n.table-body-wrap::-webkit-scrollbar-button {\n display: block;\n height: 4px;\n background: transparent;\n \n // 顶部按钮\n &:vertical:start:decrement {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 3'%3E%3Cpath fill='%239ca3af' d='M2 0L0 3h4z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: center;\n background-size: 4px 3px;\n }\n \n // 底部按钮\n &:vertical:end:increment {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 3'%3E%3Cpath fill='%239ca3af' d='M2 3L0 0h4z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: center;\n background-size: 4px 3px;\n }\n \n &:hover {\n // 悬停时箭头颜色变深\n &:vertical:start:decrement {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 3'%3E%3Cpath fill='%236b7280' d='M2 0L0 3h4z'/%3E%3C/svg%3E\");\n }\n \n &:vertical:end:increment {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 3'%3E%3Cpath fill='%236b7280' d='M2 3L0 0h4z'/%3E%3C/svg%3E\");\n }\n }\n}\n\n.table {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n table-layout: fixed;\n}\n\n.table thead th {\n text-align: left;\n // font-weight: 600;\n font-size: 12px;\n color: #7c7c7c;\n background: #f8f9fa;\n border-bottom: 1px solid #dfe3e8;\n padding: 8px 8px;\n white-space: nowrap;\n}\n\n\n.table tbody td {\n padding: 4px 8px;\n border-bottom: 1px solid #f1f3f4;\n vertical-align: middle;\n text-align: left;\n font-size: 12px;\n // font-weight: 550;\n color: #535353;\n transition: background-color 0.3s ease;\n}\n\n/* 行选中样式 */\n.table tbody tr {\n transition: background-color 0.3s ease;\n}\n\n.table tbody tr.row-selected {\n background-color: #e6f4ff;\n}\n\n.table tbody tr.row-selected td {\n background-color: #e6f4ff;\n}\n\n.table tbody tr:hover:not(.row-selected) {\n background-color: #f5f5f5;\n}\n\n.col-select {\n width: auto;\n min-width: 60px;\n}\n\n.select-header {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n}\n\n.select-count {\n font-size: 11px;\n color: #1A1A1A;\n font-weight: 600;\n background: #f0f0f0;\n padding: 0 4px;\n border-radius: 3px;\n line-height: 1.4;\n white-space: nowrap;\n}\n\n.col-expand {\n width: 28px;\n text-align: center;\n}\n\n.expand-btn {\n width: 20px;\n height: 20px;\n border: none;\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s ease;\n}\n\n.expand-btn:hover {\n background: rgba(0, 0, 0, 0.05);\n}\n\n.expand-icon {\n display: inline-block;\n width: 0;\n height: 0;\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n border-top: 7px solid #6b7280;\n transition: transform 0.2s ease;\n}\n\n.expand-icon.is-open {\n transform: rotate(180deg);\n}\n\n.expand-row .expand-cell {\n background: #f9fafb;\n}\n\n/* 通用固定列样式(右侧) */\n.table thead th.col-fixed-right,\n.table tbody td.col-fixed-right {\n position: sticky;\n /* right 值通过 JavaScript 动态设置 */\n background: #fff;\n /* z-index 通过 JavaScript 动态设置 */\n transition: background-color 0.3s ease;\n}\n.table tbody td.col-fixed-right {\n box-shadow: -6px 0 6px -6px rgba(0,0,0,0.08);\n}\n\n/* 通用固定列样式(左侧) */\n.table thead th.col-fixed-left,\n.table tbody td.col-fixed-left {\n position: sticky;\n /* left 值通过 JavaScript 动态设置 */\n background: #fff;\n /* z-index 通过 JavaScript 动态设置 */\n transition: background-color 0.3s ease;\n}\n.table tbody td.col-fixed-left {\n box-shadow: 6px 0 6px -6px rgba(0,0,0,0.08);\n}\n\n/* 选中行时固定列的背景色 */\n.table tbody tr.row-selected td.col-fixed-right,\n.table tbody tr.row-selected td.col-fixed-left {\n background-color: #e6f4ff;\n}\n\n.text-left { text-align: left; }\n.text-center { text-align: center; }\n.text-right { text-align: right; }\n\n\n.link {\n background: transparent;\n border: none;\n color: #2563eb;\n cursor: pointer;\n}\n\n.empty {\n text-align: center;\n color: #888;\n padding: 0;\n height: 200px; // 保底高度\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* 复选框主题色为 #1A1A1A */\n.table input[type=\"checkbox\"],\n.bulk-bar input[type=\"checkbox\"] {\n accent-color: #1A1A1A;\n}\n\n/* 聚焦时轻微外发光,保持无侵入 */\n.table input[type=\"checkbox\"]:focus-visible,\n.bulk-bar input[type=\"checkbox\"]:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px rgba(26, 26, 26, 0.2);\n border-radius: 3px;\n}\n\n/* Loading 状态样式 */\n.loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.8);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n z-index: 10;\n}\n\n.loading-spinner {\n width: 32px;\n height: 32px;\n border: 3px solid #f3f3f3;\n border-top: 3px solid #1A1A1A;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n margin-bottom: 8px;\n}\n\n.loading-text {\n font-size: 14px;\n color: #666;\n}\n\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.loading-table {\n opacity: 0.6;\n pointer-events: none;\n}\n\n/* 右对齐分页(覆盖子组件内部的 space-between) */\n:deep(.ypagination.align-right) {\n justify-content: flex-end !important;\n}\n\n/* 自定义悬浮竖向滚动条 */\n.v-scrollbar {\n position: absolute;\n top: 0;\n right: 2px;\n bottom: 0;\n width: 8px;\n display: flex;\n align-items: stretch;\n z-index: 5;\n pointer-events: none; // 仅轨道与滑块可交互\n}\n\n.v-scrollbar-track {\n position: relative;\n width: 100%;\n margin: 4px 0;\n border-radius: 4px;\n background: rgba(0,0,0,0.03);\n transition: background 0.2s ease;\n pointer-events: auto;\n}\n\n.v-scrollbar:hover .v-scrollbar-track {\n background: rgba(0,0,0,0.06);\n}\n\n.v-scrollbar-thumb {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n border-radius: 4px;\n background: rgba(0,0,0,0.24);\n cursor: grab;\n pointer-events: auto;\n transition: background 0.2s ease, opacity 0.2s ease;\n}\n\n.v-scrollbar-thumb:hover {\n background: rgba(0,0,0,0.34);\n}\n\n.v-scrollbar-thumb:active {\n cursor: grabbing;\n background: rgba(0,0,0,0.42);\n}\n</style>\n","<template>\n <div class=\"yselect\" :class=\"{ 'yselect--disabled': disabled, [`yselect--${size}`]: true }\" :style=\"{ width: width }\" ref=\"selectContainer\">\n <div \n ref=\"triggerElement\"\n class=\"yselect__trigger\"\n :class=\"{ \n 'yselect__trigger--open': isOpen,\n 'yselect__trigger--disabled': disabled,\n 'yselect__trigger--error': error\n }\"\n @mousedown.prevent.stop=\"toggleDropdown\"\n @keydown.enter.prevent=\"toggleDropdown\"\n @keydown.space.prevent=\"toggleDropdown\"\n @keydown.escape=\"closeDropdown\"\n @keydown.arrow-down.prevent=\"openDropdown\"\n @keydown.arrow-up.prevent=\"openDropdown\"\n tabindex=\"0\"\n role=\"combobox\"\n :aria-expanded=\"isOpen\"\n :aria-haspopup=\"true\"\n >\n <span class=\"yselect__value\" :class=\"{ 'yselect__placeholder': !selectedLabel }\" v-if=\"!filterable || !isOpen\">\n <slot name=\"value\" :value=\"props.multiple ? selectedOptions : selectedOption\" :label=\"selectedLabel\" :multiple=\"props.multiple\">\n <template v-if=\"props.multiple\">\n <div class=\"yselect__tags\" v-if=\"selectedOptions.length > 0\">\n <span \n v-for=\"(option, idx) in selectedOptions\" \n :key=\"getOptionKey(option, idx)\"\n class=\"yselect__tag\"\n >\n <img \n v-if=\"(option as any)?.flagImg\"\n class=\"yselect__flag\"\n :src=\"(option as any).flagImg\"\n alt=\"flag\"\n />\n <span class=\"yselect__tag-text\">{{ getOptionLabel(option) }}</span>\n <span \n v-if=\"clearable && !disabled\"\n class=\"yselect__tag-close\"\n @click.stop=\"removeTag(option, $event)\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M2.5 2.5l5 5M7.5 2.5l-5 5\" stroke=\"currentColor\" stroke-width=\"1.2\" stroke-linecap=\"round\"/>\n </svg>\n </span>\n </span>\n </div>\n <span v-else class=\"yselect__placeholder-text\">{{ placeholder }}</span>\n </template>\n <template v-else>\n <template v-if=\"selectedOption\">\n <img \n v-if=\"(selectedOption as any)?.flagImg\"\n class=\"yselect__flag\"\n :src=\"(selectedOption as any).flagImg\"\n alt=\"flag\"\n />\n {{ selectedLabel }}\n </template>\n <template v-else>\n {{ placeholder }}\n </template>\n </template>\n </slot>\n </span>\n <input\n v-else\n ref=\"inputElement\"\n class=\"yselect__input\"\n type=\"text\"\n :placeholder=\"props.multiple ? (selectedOptions.length > 0 ? `已选择 ${selectedOptions.length} 项` : placeholder) : (selectedLabel || placeholder)\"\n v-model=\"searchQuery\"\n @keydown.stop\n @keydown.arrow-down.prevent=\"moveHover(1)\"\n @keydown.arrow-up.prevent=\"moveHover(-1)\"\n @keydown.enter.prevent=\"selectHovered()\"\n @keydown.esc.prevent=\"closeDropdown\"\n @keydown.delete.prevent=\"handleClear\"\n />\n <span \n v-if=\"clearable && !disabled && (props.multiple ? selectedOptions.length > 0 : selectedOption)\"\n class=\"yselect__clear\"\n title=\"清空\"\n @click.stop=\"handleClear\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path d=\"M3 3l6 6M9 3L3 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n </span>\n <span class=\"yselect__arrow\" :class=\"{ 'yselect__arrow--open': isOpen }\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path d=\"M3 4.5L6 7.5L9 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n </div>\n\n <transition name=\"yselect-dropdown\">\n <teleport to=\"body\">\n <div \n v-if=\"isOpen\" \n class=\"yselect__dropdown yselect__dropdown--portal\"\n :class=\"{ 'yselect__dropdown--top': shouldOpenUpward }\"\n :style=\"portalDropdownStyle\"\n @mousedown.stop\n @click.stop\n >\n <div class=\"yselect__options\" ref=\"optionsContainer\">\n <div\n v-for=\"(option, index) in displayedOptions\"\n :key=\"getOptionKey(option, index)\"\n class=\"yselect__option\"\n :class=\"{\n 'yselect__option--selected': isSelected(option),\n 'yselect__option--disabled': isOptionDisabled(option),\n 'yselect__option--hover': hoveredIndex === index\n }\"\n @click=\"selectOption(option, index)\"\n @mouseenter=\"hoveredIndex = index\"\n @mouseleave=\"hoveredIndex = -1\"\n >\n <slot name=\"option\" :option=\"option\" :index=\"index\" :selected=\"isSelected(option)\">\n <span v-if=\"props.multiple\" class=\"yselect__option-check\">\n <svg \n v-if=\"isSelected(option)\"\n width=\"14\" \n height=\"14\" \n viewBox=\"0 0 14 14\" \n fill=\"none\"\n >\n <path d=\"M2 7l3 3 7-7\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <img \n v-if=\"(option as any)?.flagImg\"\n class=\"yselect__flag\"\n :src=\"(option as any).flagImg\"\n alt=\"flag\"\n />\n {{ getOptionLabel(option) }}\n </slot>\n </div>\n </div>\n </div>\n </teleport>\n </transition>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch, nextTick, onMounted, onUnmounted } from 'vue'\n\nexport interface SelectOption {\n label: string\n value: any\n disabled?: boolean\n [key: string]: any\n}\n\nexport interface SelectProps {\n modelValue?: any | any[]\n options: SelectOption[] | any[]\n placeholder?: string\n disabled?: boolean\n error?: boolean\n clearable?: boolean\n clearTo?: any\n filterable?: boolean\n multiple?: boolean\n valueKey?: string\n labelKey?: string\n disabledKey?: string\n size?: 'small' | 'medium' | 'large'\n width?: string\n}\n\nconst props = withDefaults(defineProps<SelectProps>(), {\n placeholder: '请选择',\n disabled: false,\n error: false,\n clearable: true,\n clearTo: undefined,\n filterable: false,\n multiple: false,\n valueKey: 'value',\n labelKey: 'label',\n disabledKey: 'disabled',\n size: 'medium',\n width: '200px'\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: any | any[]]\n 'change': [value: any | any[], option: SelectOption | SelectOption[] | null]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n 'clear': []\n}>()\n\n// 响应式数据\nconst isOpen = ref(false)\nconst hoveredIndex = ref(-1)\nconst optionsContainer = ref<HTMLElement>()\nconst triggerElement = ref<HTMLElement>()\nconst selectContainer = ref<HTMLElement>()\nconst shouldOpenUpward = ref(false)\nconst inputElement = ref<HTMLInputElement>()\nconst searchQuery = ref('')\n\n// 计算属性\nconst selectedOption = computed(() => {\n if (props.multiple) return null\n return props.options.find(option => getOptionValue(option) === props.modelValue) || null\n})\n\nconst selectedOptions = computed(() => {\n if (!props.multiple) return []\n const values = Array.isArray(props.modelValue) ? props.modelValue : []\n return props.options.filter(option => values.includes(getOptionValue(option)))\n})\n\nconst selectedLabel = computed(() => {\n if (props.multiple) {\n const count = selectedOptions.value.length\n if (count === 0) return ''\n return `已选择 ${count} 项`\n }\n return selectedOption.value ? getOptionLabel(selectedOption.value) : ''\n})\n\nconst displayedOptions = computed(() => {\n if (!props.filterable) return props.options\n const query = searchQuery.value.trim().toLowerCase()\n if (!query) return props.options\n return props.options.filter((opt: any) => {\n const label = getOptionLabel(opt)\n return String(label).toLowerCase().includes(query)\n })\n})\n\n// const dropdownStyle = computed(() => {\n// const style: Record<string, string> = {}\n// \n// if (props.width === 'auto') {\n// style.width = '100%'\n// style.minWidth = 'auto'\n// } else {\n// style.width = props.width\n// style.minWidth = props.width\n// }\n// \n// return style\n// })\n\nconst portalDropdownStyle = computed(() => {\n const style: Record<string, string> = { position: 'fixed', zIndex: '4000' }\n const trigger = triggerElement.value\n if (!trigger) return style\n const rect = trigger.getBoundingClientRect()\n const width = (selectContainer.value?.getBoundingClientRect().width || rect.width)\n style.left = `${rect.left}px`\n style.width = `${width}px`\n if (shouldOpenUpward.value) {\n // 向上展开时,使用 bottom 定位而不是 top,这样更准确\n style.bottom = `${window.innerHeight - rect.top + 4}px`\n style.top = 'auto'\n } else {\n style.top = `${rect.bottom + 4}px`\n }\n return style\n})\n\n// 计算是否应该向上展开\nfunction calculateDropdownPosition() {\n if (!isOpen.value || !triggerElement.value) return\n \n nextTick(() => {\n const trigger = triggerElement.value\n if (!trigger) return\n \n const triggerRect = trigger.getBoundingClientRect()\n const viewportHeight = window.innerHeight\n const dropdownHeight = 200 // 预估下拉菜单高度\n \n // 计算下拉菜单底部位置\n const dropdownBottom = triggerRect.bottom + dropdownHeight + 4 // 4px 是 margin-top\n \n // 计算向上展开时下拉菜单顶部位置\n const dropdownTop = triggerRect.top - dropdownHeight - 4 // 4px 是 margin-bottom\n \n // 如果下拉菜单会超出视口底部,且向上展开不会超出视口顶部,则向上展开\n const shouldOpenDown = dropdownBottom <= viewportHeight - 20 // 20px 安全边距\n const canOpenUp = dropdownTop >= 20 // 20px 安全边距\n \n shouldOpenUpward.value = !shouldOpenDown && canOpenUp\n })\n}\n\n// 方法\nfunction getOptionValue(option: any): any {\n if (typeof option === 'object' && option !== null) {\n return option[props.valueKey]\n }\n return option\n}\n\nfunction getOptionLabel(option: any): string {\n if (typeof option === 'object' && option !== null) {\n return option[props.labelKey] || String(option[props.valueKey])\n }\n return String(option)\n}\n\nfunction getOptionKey(option: any, index: number): string | number {\n if (typeof option === 'object' && option !== null && option.id !== undefined) {\n return option.id\n }\n return getOptionValue(option) || index\n}\n\nfunction isSelected(option: any): boolean {\n if (props.multiple) {\n const values = Array.isArray(props.modelValue) ? props.modelValue : []\n return values.includes(getOptionValue(option))\n }\n return getOptionValue(option) === props.modelValue\n}\n\nfunction isOptionDisabled(option: any): boolean {\n if (typeof option === 'object' && option !== null) {\n return option[props.disabledKey] === true\n }\n return false\n}\n\nfunction toggleDropdown() {\n if (props.disabled) return\n isOpen.value ? closeDropdown() : openDropdown()\n}\n\nfunction openDropdown() {\n if (props.disabled) return\n isOpen.value = true\n nextTick(() => {\n calculateDropdownPosition()\n scrollToSelected()\n if (props.filterable && inputElement.value) {\n inputElement.value.focus()\n // 打开时默认清空,便于直接输入筛选\n searchQuery.value = ''\n }\n })\n}\n\nfunction closeDropdown() {\n isOpen.value = false\n hoveredIndex.value = -1\n shouldOpenUpward.value = false\n if (props.filterable) {\n searchQuery.value = ''\n }\n}\n\nfunction selectOption(option: any, _index: number) {\n if (isOptionDisabled(option)) return\n \n const value = getOptionValue(option)\n \n if (props.multiple) {\n const currentValues = Array.isArray(props.modelValue) ? [...props.modelValue] : []\n const optionValue = getOptionValue(option)\n const valueIndex = currentValues.indexOf(optionValue)\n \n if (valueIndex > -1) {\n // 取消选择\n currentValues.splice(valueIndex, 1)\n } else {\n // 添加选择\n currentValues.push(optionValue)\n }\n \n emit('update:modelValue', currentValues)\n emit('change', currentValues, selectedOptions.value)\n // 多选模式下不关闭下拉框\n } else {\n emit('update:modelValue', value)\n emit('change', value, option)\n closeDropdown()\n }\n}\n\nfunction handleClear() {\n if (!props.clearable || props.disabled) return\n const cleared = props.multiple ? (props.clearTo !== undefined ? props.clearTo : []) : props.clearTo\n emit('update:modelValue', cleared)\n emit('change', cleared, props.multiple ? [] : null)\n emit('clear')\n // 清空后关闭下拉并重置搜索\n if (!props.multiple) {\n closeDropdown()\n }\n}\n\nfunction removeTag(option: any, event: Event) {\n event.stopPropagation()\n if (props.disabled || !props.multiple) return\n \n const currentValues = Array.isArray(props.modelValue) ? [...props.modelValue] : []\n const optionValue = getOptionValue(option)\n const index = currentValues.indexOf(optionValue)\n \n if (index > -1) {\n currentValues.splice(index, 1)\n emit('update:modelValue', currentValues)\n emit('change', currentValues, selectedOptions.value)\n }\n}\n\nfunction moveHover(delta: number) {\n if (!displayedOptions.value || displayedOptions.value.length === 0) {\n hoveredIndex.value = -1\n return\n }\n let next = hoveredIndex.value\n const total = displayedOptions.value.length\n // 初次移动时从 -1 开始\n if (next === -1) {\n next = delta > 0 ? 0 : total - 1\n } else {\n next = (next + delta + total) % total\n }\n // 跳过禁用项,最多循环 total 次避免死循环\n let attempts = 0\n while (attempts < total && isOptionDisabled(displayedOptions.value[next])) {\n next = (next + delta + total) % total\n attempts++\n }\n hoveredIndex.value = attempts >= total ? -1 : next\n scrollHoverIntoView()\n}\n\nfunction selectHovered() {\n if (hoveredIndex.value < 0) return\n const option = displayedOptions.value[hoveredIndex.value]\n if (!option || isOptionDisabled(option)) return\n selectOption(option, hoveredIndex.value)\n}\n\nfunction scrollToSelected() {\n if (!optionsContainer.value) return\n \n const selectedElement = optionsContainer.value.querySelector('.yselect__option--selected') as HTMLElement | null\n if (selectedElement) {\n selectedElement.scrollIntoView({ block: 'nearest' })\n }\n}\n\nfunction scrollHoverIntoView() {\n if (!optionsContainer.value) return\n if (hoveredIndex.value < 0) return\n const optionNodes = optionsContainer.value.querySelectorAll('.yselect__option')\n const el = optionNodes[hoveredIndex.value] as HTMLElement | undefined\n if (el) el.scrollIntoView({ block: 'nearest' })\n}\n\nfunction handleClickOutside(event: Event) {\n const target = event.target as HTMLElement\n if (!selectContainer.value || !selectContainer.value.contains(target)) {\n closeDropdown()\n }\n}\n\n// 监听器\nwatch(() => props.modelValue, () => {\n hoveredIndex.value = -1\n})\n\n// 窗口大小变化和滚动时重新计算位置\nfunction handleResize() {\n if (isOpen.value) {\n calculateDropdownPosition()\n }\n}\n\n// 生命周期\nonMounted(() => {\n document.addEventListener('click', handleClickOutside)\n window.addEventListener('resize', handleResize)\n window.addEventListener('scroll', handleResize, true)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', handleClickOutside)\n window.removeEventListener('resize', handleResize)\n window.removeEventListener('scroll', handleResize, true)\n})\n</script>\n\n<style scoped lang=\"less\">\n.yselect {\n position: relative;\n display: inline-block;\n width: 100%;\n min-width: 0;\n flex-shrink: 0;\n}\n\n.yselect--disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.yselect__trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n min-width: 0;\n flex-shrink: 0;\n border: 1px solid #e2e8f0;\n background: #ffffff;\n cursor: pointer;\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n outline: none;\n line-height: 1.5;\n color: #0b1a29;\n box-sizing: border-box;\n}\n\n.yselect__trigger:hover:not(.yselect__trigger--disabled) {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15);\n}\n\n.yselect__trigger:focus {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15);\n}\n\n.yselect__trigger--open {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15);\n}\n\n.yselect__trigger--disabled {\n background: #f9fafb;\n cursor: not-allowed;\n color: #9ca3af;\n}\n\n.yselect__trigger--error {\n border-color: #ef4444;\n}\n\n.yselect__trigger--error:focus {\n border-color: #ef4444;\n box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.15);\n}\n\n.yselect__value {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: #0b1a29;\n display: flex;\n align-items: center;\n min-width: 0;\n}\n\n.yselect__tags {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n align-items: center;\n flex: 1;\n min-width: 0;\n}\n\n.yselect__tag {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background: #eff6ff;\n color: #1d4ed8;\n border-radius: 4px;\n font-size: 12px;\n line-height: 1.4;\n max-width: 150px;\n flex-shrink: 0;\n}\n\n.yselect__tag-text {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin-right: 4px;\n}\n\n.yselect__tag-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n cursor: pointer;\n color: #1d4ed8;\n flex-shrink: 0;\n margin-left: 2px;\n}\n\n.yselect__tag-close:hover {\n color: #1e40af;\n}\n\n.yselect__placeholder-text {\n color: #9ca3af;\n}\n\n.yselect__flag {\n width: 14px;\n height: 14px;\n object-fit: cover;\n border-radius: 2px;\n margin-right: 6px;\n}\n\n.yselect__placeholder {\n color: #9ca3af;\n}\n\n.yselect__input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n color: #0b1a29;\n font-size: inherit;\n line-height: 1.5;\n min-width: 0;\n}\n\n.yselect__input::placeholder {\n color: #9ca3af;\n}\n\n.yselect__trigger--disabled .yselect__value {\n color: #9ca3af;\n}\n\n.yselect__arrow {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n color: #6b7280;\n transition: transform 0.2s ease;\n flex-shrink: 0;\n}\n\n.yselect__clear {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n color: #9ca3af;\n margin-left: 6px;\n cursor: pointer;\n}\n\n.yselect__clear:hover {\n color: #6b7280;\n}\n\n.yselect__arrow--open {\n transform: rotate(180deg);\n}\n\n.yselect__dropdown {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n z-index: 1000;\n margin-top: 4px;\n background: #ffffff;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n box-shadow: 0 8px 20px rgba(2, 6, 23, 0.15);\n overflow: hidden;\n}\n\n.yselect__dropdown--top {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 4px;\n}\n\n.yselect__options {\n max-height: 200px;\n overflow-y: auto;\n padding: 4px 0;\n}\n\n.yselect__option {\n display: flex;\n align-items: center;\n height: 36px;\n padding: 0 12px;\n cursor: pointer;\n transition: background-color 0.2s ease, color 0.2s ease;\n font-size: 13px;\n line-height: 1.5;\n color: #0b1a29;\n}\n\n.yselect__option-check {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-right: 8px;\n flex-shrink: 0;\n color: #1d4ed8;\n}\n\n.yselect__option:hover:not(.yselect__option--disabled) {\n background-color: #F6F6F7;\n color: #303061;\n}\n\n.yselect__option--selected {\n background: #eff6ff;\n color: #1d4ed8;\n font-weight: 500;\n}\n\n.yselect__option--selected:hover {\n background: #dbeafe;\n}\n\n.yselect__option--disabled {\n color: #9ca3af;\n cursor: not-allowed;\n background: transparent;\n}\n\n.yselect__option--hover {\n background-color: #F6F6F7;\n color: #303061;\n}\n\n/* 尺寸变体 */\n.yselect--small .yselect__trigger {\n height: 32px;\n padding: 0 10px;\n font-size: 12px;\n border-radius: 6px;\n min-width: 80px;\n}\n\n.yselect--medium .yselect__trigger {\n height: 44px;\n padding: 0 12px;\n font-size: 14px;\n border-radius: 8px;\n min-width: 100px;\n}\n\n.yselect--multiple .yselect__trigger {\n min-height: 44px;\n height: auto;\n padding-top: 4px;\n padding-bottom: 4px;\n}\n\n.yselect--multiple.yselect--small .yselect__trigger {\n min-height: 32px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n\n.yselect--multiple.yselect--large .yselect__trigger {\n min-height: 52px;\n padding-top: 6px;\n padding-bottom: 6px;\n}\n\n.yselect--large .yselect__trigger {\n height: 52px;\n padding: 0 16px;\n font-size: 16px;\n border-radius: 10px;\n min-width: 120px;\n}\n\n/* 过渡动画 */\n.yselect-dropdown-enter-active,\n.yselect-dropdown-leave-active {\n transition: all 0.2s ease;\n transform-origin: top;\n}\n\n.yselect-dropdown-enter-from {\n opacity: 0;\n transform: scaleY(0.8) translateY(-8px);\n}\n\n.yselect-dropdown-leave-to {\n opacity: 0;\n transform: scaleY(0.8) translateY(-8px);\n}\n\n/* 滚动条样式 */\n.yselect__options::-webkit-scrollbar {\n width: 6px;\n}\n\n.yselect__options::-webkit-scrollbar-track {\n background: #f1f5f9;\n}\n\n.yselect__options::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 3px;\n}\n\n.yselect__options::-webkit-scrollbar-thumb:hover {\n background: #94a3b8;\n}\n\n/* 暗色主题支持 */\n@media (prefers-color-scheme: dark) {\n .yselect__trigger {\n background: rgba(2, 6, 23, 0.4);\n border-color: rgba(148, 163, 184, 0.18);\n color: #e5eef7;\n }\n \n .yselect__placeholder {\n color: #9aa6b2;\n }\n \n .yselect__input::placeholder {\n color: #9aa6b2;\n }\n \n .yselect__trigger--disabled {\n background: rgba(2, 6, 23, 0.2);\n color: #9ca3af;\n }\n \n .yselect__value {\n color: #e5eef7;\n }\n \n .yselect__dropdown {\n background: rgba(2, 6, 23, 0.9);\n border-color: rgba(148, 163, 184, 0.18);\n }\n \n .yselect__option {\n color: #e5eef7;\n }\n \n .yselect__option:hover:not(.yselect__option--disabled) {\n background-color: #F6F6F7;\n color: #303061;\n }\n \n .yselect__option--hover {\n background-color: #F6F6F7;\n color: #303061;\n }\n}\n</style>\n","<template>\n <div class=\"ypagination\">\n <div class=\"page-actions\">\n <!-- 上一页按钮 -->\n <YButton\n size=\"small\"\n variant=\"secondary\"\n :disabled=\"currentPage === 1 || loading\"\n @click=\"goToPage(1)\"\n >首页</YButton\n >\n <!-- 在一个 YButton 中生成上一页/下一页组合按钮 -->\n <YButton\n class=\"ml-1\"\n variant=\"secondary\"\n size=\"small\"\n :groupItems=\"[\n { label: '上一页', value: 'prev', disabled: currentPage === 1 || loading, icon: 'chevron-left', onlyIcon: true, ariaLabel: '上一页' },\n { label: '下一页', value: 'next', disabled: loading || disableNext, icon: 'chevron-right', onlyIcon: true, ariaLabel: '下一页' }\n ]\"\n @group-click=\"onPagerGroupClick\"\n />\n\n <!-- 每页条数选择 -->\n <div class=\"page-size-select\">\n <YSelect\n v-model=\"pageSize\"\n :options=\"pageSizeOptions\"\n size=\"small\"\n width=\"105px\"\n :clearable=\"false\"\n :disabled=\"loading\"\n @change=\"handlePageSizeChange\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from \"vue\"\n// import type { SelectOption } from \"./YSelect.vue\";\n\nexport interface PaginationProps {\n currentPage: number;\n pageSize: number;\n loading?: boolean;\n pageSizeOptions?: Array<{ label: string; value: number }>;\n disableNext?: boolean; // 是否禁用下一页按钮\n}\n\nconst props = withDefaults(defineProps<PaginationProps>(), {\n loading: false,\n disableNext: false,\n pageSizeOptions: () => [\n { label: \"10/页\", value: 10 },\n { label: \"20/页\", value: 20 },\n { label: \"50/页\", value: 50 },\n { label: \"100/页\", value: 100 },\n ],\n});\n\nconst emit = defineEmits<{\n \"update:currentPage\": [page: number];\n \"update:pageSize\": [size: number];\n \"page-change\": [page: number];\n \"page-size-change\": [size: number];\n}>();\n\n// 响应式数据\nconst pageSize = ref(props.pageSize);\n\n// 每页条数选项\nconst pageSizeOptions = computed(() => props.pageSizeOptions);\n\n// 计算属性\n// 简化:不再计算总页数与页码列表\n\n// 使用计算属性来获取当前页,支持双向绑定\nconst currentPage = computed({\n get: () => props.currentPage,\n set: (value) => {\n emit(\"update:currentPage\", value);\n emit(\"page-change\", value);\n },\n});\n\n// 方法\nfunction goToPage(page: number) {\n if (props.loading) return;\n if (page >= 1 && page !== props.currentPage) {\n currentPage.value = page;\n }\n}\n\nfunction handlePageSizeChange(value: number) {\n if (props.loading) return; // loading 时不允许切换每页条数\n pageSize.value = value;\n emit(\"update:pageSize\", value);\n emit(\"page-size-change\", value);\n // 切换每页条数后,重置到第一页\n currentPage.value = 1;\n}\n\nfunction onPagerGroupClick(action?: string | number) {\n if (props.loading) return;\n if (action === 'prev') {\n goToPage(currentPage.value - 1);\n } else if (action === 'next') {\n goToPage(currentPage.value + 1);\n }\n}\n\n// 同步外部 pageSize\n// (不再根据 totalPages 回调修正 currentPage)\n// 外部如需限制页码由父组件控制\npageSize.value = props.pageSize;\n\n// 监听父组件变更以同步内部状态(确保选中项更新)\nwatch(\n () => props.pageSize,\n (val) => {\n if (typeof val === 'number' && pageSize.value !== val) {\n pageSize.value = val;\n }\n }\n);\n</script>\n\n<style scoped lang=\"less\">\n.ypagination {\n border-top: 1px solid #E6ECF2;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 10px 2px;\n gap: 12px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.page-info {\n font-size: 14px;\n color: #666;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.page-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n min-width: 0;\n}\n\n.btn-group {\n display: inline-flex;\n}\n\n.page-numbers {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n min-width: 0;\n}\n\n.btn {\n height: 28px;\n padding: 0 6px;\n border-radius: 8px;\n border: 1px solid #ddd;\n background: #fff;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.2s ease;\n white-space: nowrap;\n flex-shrink: 0;\n min-width: auto;\n}\n\n.btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.btn:hover:not(:disabled) {\n border-color: #999;\n background: #f8f8f8;\n}\n\n.page-btn {\n min-width: 28px;\n height: 28px;\n padding: 0 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n font-size: 12px;\n}\n\n.page-btn.active {\n background: #474747;\n color: #fff;\n border-color: #474747;\n}\n\n.page-btn.active:hover {\n background: #121820;\n border-color: #121820;\n}\n\n.ellipsis {\n padding: 0 2px;\n color: #999;\n font-size: 12px;\n user-select: none;\n min-width: 12px;\n text-align: center;\n flex-shrink: 0;\n}\n\n.page-size-select {\n flex-shrink: 0;\n min-width: 75px;\n margin-left: 25px;\n}\n\n/* 响应式设计 */\n@media (max-width: 768px) {\n .ypagination {\n flex-direction: column;\n gap: 8px;\n align-items: stretch;\n }\n\n .page-info {\n text-align: center;\n }\n\n .page-actions {\n justify-content: center;\n flex-wrap: wrap;\n }\n\n .page-numbers {\n order: 1;\n justify-content: center;\n }\n\n .btn:first-child,\n .btn:last-child {\n order: 2;\n }\n\n .select {\n order: 3;\n }\n}\n\n@media (max-width: 480px) {\n .page-numbers {\n gap: 2px;\n }\n\n .page-btn {\n min-width: 28px;\n height: 26px;\n padding: 0 6px;\n font-size: 12px;\n }\n\n .btn {\n height: 26px;\n padding: 0 8px;\n font-size: 12px;\n }\n\n .select {\n height: 26px;\n font-size: 12px;\n }\n}\n</style>\n","<template>\r\n <span\r\n class=\"y-badge\"\r\n :class=\"[\r\n `y-badge--${toneClass}`,\r\n `y-badge--${size}`,\r\n { 'is-outline': outline, 'is-pill': pill },\r\n progress ? `y-badge--progress-${progress}` : ''\r\n ]\"\r\n role=\"status\"\r\n :aria-label=\"ariaLabel\"\r\n >\r\n <span class=\"y-badge__inner\">\r\n <!-- 进度/图标优先渲染 -->\r\n <span v-if=\"progress\" class=\"y-badge__progress\" aria-hidden=\"true\">\r\n <svg v-if=\"progress === 'incomplete'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <circle cx=\"10\" cy=\"10\" r=\"5\" />\r\n </svg>\r\n <svg v-else-if=\"progress === 'partiallyComplete'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path d=\"M10 5a5 5 0 100 10V5z\" />\r\n <circle cx=\"10\" cy=\"10\" r=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" />\r\n </svg>\r\n <svg v-else-if=\"progress === 'complete'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path fill-rule=\"evenodd\" d=\"M16.707 5.293a1 1 0 010 1.414l-7.25 7.25a1 1 0 01-1.414 0l-4-4a1 1 0 111.414-1.414L8.75 11.086l6.543-6.543a1 1 0 011.414 0z\" clip-rule=\"evenodd\" />\r\n </svg>\r\n </span>\r\n\r\n <span v-else-if=\"icon\" class=\"y-badge__icon\" aria-hidden=\"true\">\r\n <svg v-if=\"icon === 'dot'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><circle cx=\"10\" cy=\"10\" r=\"4\"/></svg>\r\n <svg v-else-if=\"icon === 'check'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path fill-rule=\"evenodd\" d=\"M16.707 5.293a1 1 0 010 1.414l-7.25 7.25a1 1 0 01-1.414 0l-4-4a1 1 0 111.414-1.414L8.75 11.086l6.543-6.543a1 1 0 011.414 0z\" clip-rule=\"evenodd\" /></svg>\r\n <svg v-else-if=\"icon === 'alert'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path fill-rule=\"evenodd\" d=\"M8.257 3.099c.765-1.36 2.721-1.36 3.486 0l6.518 11.59c.75 1.334-.214 3.011-1.743 3.011H3.482c-1.53 0-2.493-1.677-1.743-3.01L8.257 3.1zM11 14a1 1 0 10-2 0 1 1 0 002 0zm-1-2a1 1 0 01-1-1V8a1 1 0 112 0v3a1 1 0 01-1 1z\" clip-rule=\"evenodd\"/></svg>\r\n <svg v-else class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><circle cx=\"10\" cy=\"10\" r=\"4\"/></svg>\r\n </span>\r\n\r\n <span class=\"y-badge__label\"><slot>{{ label }}</slot></span>\r\n </span>\r\n </span>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from 'vue'\r\n\r\nconst props = withDefaults(defineProps<{\r\n /** 视觉语气 */\r\n tone?: 'default' | 'informational' | 'success' | 'attention' | 'warning' | 'critical'\r\n /** 尺寸 */\r\n size?: 'small' | 'medium'\r\n /** 进度状态(与 icon 互斥,优先级更高) */\r\n progress?: 'incomplete' | 'partiallyComplete' | 'complete'\r\n /** 内置图标:dot | check | alert | placeholder(string 亦以 dot 代替) */\r\n icon?: 'dot' | 'check' | 'alert' | 'placeholder' | string | undefined\r\n /** 是否圆角胶囊 */\r\n pill?: boolean\r\n /** 描边样式(浅背景 + 边框) */\r\n outline?: boolean\r\n /** 文本标签(未提供 slot 时兜底) */\r\n label?: string\r\n}>(), {\r\n tone: 'default',\r\n size: 'medium',\r\n progress: undefined,\r\n icon: undefined,\r\n pill: true,\r\n outline: false,\r\n label: ''\r\n})\r\n\r\nconst toneClass = computed(() => props.tone || 'default')\r\n\r\nconst ariaLabel = computed(() => {\r\n const text = (props.label || '').trim()\r\n const tone = props.tone\r\n const prog = props.progress\r\n if (prog) {\r\n const progMap: Record<string, string> = {\r\n incomplete: '未完成',\r\n partiallyComplete: '部分完成',\r\n complete: '已完成',\r\n }\r\n return text ? `${text},进度:${progMap[prog] || prog}` : `进度:${progMap[prog] || prog}`\r\n }\r\n if (tone && tone !== 'default') {\r\n const toneMap: Record<string, string> = {\r\n informational: '信息',\r\n success: '成功',\r\n attention: '注意',\r\n warning: '警告',\r\n critical: '严重',\r\n default: '默认'\r\n }\r\n return text ? `${text},语气:${toneMap[tone] || tone}` : `语气:${toneMap[tone] || tone}`\r\n }\r\n return text || '标记'\r\n})\r\n</script>\r\n\r\n<style scoped>\r\n.y-badge {\r\n display: inline-flex;\r\n vertical-align: middle;\r\n line-height: 1;\r\n}\r\n\r\n.y-badge__inner {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 6px;\r\n border: 1px solid transparent;\r\n border-radius: 6px;\r\n padding: 2px 8px;\r\n font-weight: 600;\r\n font-size: 12px;\r\n color: #111827;\r\n background-color: #f3f4f6;\r\n}\r\n\r\n/* 尺寸 */\r\n.y-badge--small .y-badge__inner { padding: 1px 6px; font-size: 11px; border-radius: 6px; }\r\n.y-badge--medium .y-badge__inner { padding: 3px 10px; font-size: 12px; border-radius: 8px; }\r\n\r\n/* 胶囊圆角 */\r\n.is-pill .y-badge__inner { border-radius: 9999px; }\r\n\r\n/* 图标与进度图标统一尺寸 */\r\n.y-badge .icon { width: 12px; height: 12px; }\r\n\r\n/* 语气色板(尽量贴近 Polaris 感觉) */\r\n/* default */\r\n.y-badge--default .y-badge__inner { color: #374151; background-color: #F3F4F6; border-color: transparent; }\r\n.is-outline.y-badge--default .y-badge__inner { background-color: #fff; color: #374151; border-color: #E5E7EB; }\r\n\r\n/* informational */\r\n.y-badge--informational .y-badge__inner { color: #0b5394; background-color: #eaf3ff; }\r\n.is-outline.y-badge--informational .y-badge__inner { background-color: #fff; color: #0b5394; border-color: #b3d4ff; }\r\n\r\n/* success */\r\n.y-badge--success .y-badge__inner { color: #006c4f; background-color: #e7f5f0; }\r\n.is-outline.y-badge--success .y-badge__inner { background-color: #fff; color: #006c4f; border-color: #a8e0cf; }\r\n\r\n/* attention(信息但强调) */\r\n.y-badge--attention .y-badge__inner { color: #5b3a00; background-color: #fff3cd; }\r\n.is-outline.y-badge--attention .y-badge__inner { background-color: #fff; color: #5b3a00; border-color: #ffe69c; }\r\n\r\n/* warning */\r\n.y-badge--warning .y-badge__inner { color: #7a4400; background-color: #fdecc8; }\r\n.is-outline.y-badge--warning .y-badge__inner { background-color: #fff; color: #7a4400; border-color: #fbd38d; }\r\n\r\n/* critical */\r\n.y-badge--critical .y-badge__inner { color: #9b1c1c; background-color: #fde8e8; }\r\n.is-outline.y-badge--critical .y-badge__inner { background-color: #fff; color: #9b1c1c; border-color: #f5b5b5; }\r\n\r\n/* 进度类修饰,主要影响图标颜色与对比度(背景跟随 tone) */\r\n.y-badge__progress .icon { opacity: 0.9; }\r\n\r\n/* 深色模式粗略处理 */\r\n@media (prefers-color-scheme: dark) {\r\n .y-badge__inner { color: #e5eef7; background-color: rgba(2, 6, 23, 0.4); border-color: rgba(148, 163, 184, 0.18); }\r\n .y-badge--default .y-badge__inner { color: #e5eef7; background-color: rgba(2, 6, 23, 0.4); }\r\n .is-outline .y-badge__inner { background-color: transparent; }\r\n\r\n .y-badge--informational .y-badge__inner { color: #b7d4ff; background-color: rgba(30, 64, 175, 0.3); border-color: rgba(96, 165, 250, 0.35); }\r\n .y-badge--success .y-badge__inner { color: #b7f0da; background-color: rgba(2, 44, 34, 0.4); border-color: rgba(45, 212, 191, 0.35); }\r\n .y-badge--attention .y-badge__inner { color: #ffe3a3; background-color: rgba(120, 53, 15, 0.35); border-color: rgba(251, 191, 36, 0.35); }\r\n .y-badge--warning .y-badge__inner { color: #ffd9a3; background-color: rgba(120, 53, 15, 0.35); border-color: rgba(251, 191, 36, 0.35); }\r\n .y-badge--critical .y-badge__inner { color: #ffc3c3; background-color: rgba(127, 29, 29, 0.35); border-color: rgba(248, 113, 113, 0.35); }\r\n}\r\n</style>\r\n","<template>\n <teleport to=\"body\">\n <div\n v-show=\"visible\"\n class=\"y-dialog-root\"\n role=\"dialog\"\n :aria-modal=\"true\"\n :aria-hidden=\"!visible\"\n :style=\"{ zIndex: String(zIndex) }\"\n >\n <div\n class=\"y-dialog-mask\"\n @click=\"onMaskClick\"\n ></div>\n\n <transition name=\"dialog-zoom-fade\">\n <div\n v-show=\"visible\"\n ref=\"panelRef\"\n class=\"y-dialog-panel\"\n :class=\"[ center ? 'is-center' : '' ]\"\n :style=\"panelStyle\"\n @keydown.esc.prevent.stop=\"onEsc\"\n tabindex=\"-1\"\n >\n <div v-if=\"showHeader\" class=\"y-dialog-header\">\n <slot name=\"header\">\n <div class=\"y-dialog-title\">{{ title }}</div>\n </slot>\n <button\n v-if=\"closable\"\n type=\"button\"\n class=\"y-dialog-close\"\n aria-label=\"Close\"\n @click=\"close\"\n >\n ✕\n </button>\n </div>\n\n <div class=\"y-dialog-body\">\n <slot />\n </div>\n\n <div v-if=\"$slots.footer\" class=\"y-dialog-footer\">\n <slot name=\"footer\" />\n </div>\n </div>\n </transition>\n </div>\n </teleport>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue'\n\nconst props = withDefaults(defineProps<{\n modelValue?: boolean\n title?: string\n width?: string | number\n top?: string\n closable?: boolean\n maskClosable?: boolean\n zIndex?: number\n showHeader?: boolean\n center?: boolean\n}>(), {\n modelValue: false,\n title: '',\n width: '520px',\n top: '15vh',\n closable: true,\n maskClosable: true,\n zIndex: 3000,\n showHeader: true,\n center: false,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'open'): void\n (e: 'close'): void\n}>()\n\nconst visible = computed({\n get: () => props.modelValue,\n set: (v: boolean) => emit('update:modelValue', v),\n})\n\nconst panelRef = ref<HTMLElement | null>(null)\n\nconst panelStyle = computed(() => {\n const style: Record<string, string> = {}\n style.width = typeof props.width === 'number' ? `${props.width}px` : String(props.width)\n style.margin = '0 auto'\n style.top = props.top\n return style\n})\n\nfunction onMaskClick() {\n if (!props.maskClosable) return\n close()\n}\n\nfunction close() {\n if (!visible.value) return\n visible.value = false\n emit('close')\n}\n\nfunction onEsc() {\n if (props.closable) close()\n}\n\nfunction onKeydown(e: KeyboardEvent) {\n if (e.key === 'Escape') onEsc()\n}\n\nwatch(() => props.modelValue, (v) => {\n if (v) {\n emit('open')\n requestAnimationFrame(() => panelRef.value?.focus())\n document.addEventListener('keydown', onKeydown)\n document.body.style.overflow = 'hidden'\n } else {\n document.removeEventListener('keydown', onKeydown)\n document.body.style.overflow = ''\n }\n})\n\nonMounted(() => {\n if (props.modelValue) {\n document.addEventListener('keydown', onKeydown)\n document.body.style.overflow = 'hidden'\n }\n})\n\nonUnmounted(() => {\n document.removeEventListener('keydown', onKeydown)\n document.body.style.overflow = ''\n})\n</script>\n\n<style scoped lang=\"less\">\n.y-dialog-root {\n position: fixed;\n inset: 0;\n}\n\n.y-dialog-mask {\n position: absolute;\n inset: 0;\n background: rgba(2, 6, 23, 0.55);\n backdrop-filter: blur(2px);\n}\n\n.y-dialog-panel {\n position: relative;\n background: #ffffff;\n border-radius: 12px;\n border: 1px solid rgba(15, 23, 42, 0.06);\n box-shadow: 0 12px 40px rgba(2, 6, 23, 0.18);\n}\n\n.y-dialog-panel.is-center .y-dialog-title { text-align: center; width: 100%; }\n\n.y-dialog-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid rgba(15, 23, 42, 0.06);\n}\n\n.y-dialog-title {\n font-size: 16px;\n font-weight: 600;\n color: #0b1a29;\n}\n\n.y-dialog-close {\n appearance: none;\n border: none;\n background: transparent;\n color: #334155;\n font-size: 16px;\n line-height: 1;\n cursor: pointer;\n padding: 6px;\n border-radius: 8px;\n}\n.y-dialog-close:hover { background: rgba(15,23,42,0.05); }\n\n.y-dialog-body {\n padding: 16px;\n max-height: calc(85vh - 110px);\n overflow: auto;\n}\n\n.y-dialog-footer {\n padding: 12px 16px;\n border-top: 1px solid rgba(15, 23, 42, 0.06);\n}\n\n/* 进入/离场动画:缩放淡入 */\n.dialog-zoom-fade-enter-from,\n.dialog-zoom-fade-leave-to { transform: scale(0.96); opacity: 0; }\n.dialog-zoom-fade-enter-active,\n.dialog-zoom-fade-leave-active { transition: transform 200ms cubic-bezier(0.2, 0.6, 0.4, 1), opacity 200ms cubic-bezier(0.2, 0.6, 0.4, 1); }\n.dialog-zoom-fade-enter-to,\n.dialog-zoom-fade-leave-from { transform: scale(1); opacity: 1; }\n\n@media (prefers-color-scheme: dark) {\n .y-dialog-panel {\n background: rgba(15, 23, 42, 0.7);\n border-color: rgba(148, 163, 184, 0.12);\n box-shadow: 0 12px 40px rgba(2, 6, 23, 0.5);\n }\n .y-dialog-title { color: #e5eef7; }\n .y-dialog-close { color: #cbd5e1; }\n .y-dialog-close:hover { background: rgba(148,163,184,0.12); }\n}\n</style>\n\n\n","<template>\n <div class=\"ypopover\" ref=\"popoverRef\">\n <!-- 触发器 -->\n <div \n ref=\"triggerRef\"\n @click=\"handleTriggerClick\"\n @mouseenter=\"handleMouseEnter\"\n @mouseleave=\"handleMouseLeave\"\n >\n <slot name=\"reference\"></slot>\n </div>\n \n <!-- 弹出内容 -->\n <Teleport to=\"body\">\n <Transition name=\"ypopover-fade\">\n <div\n v-if=\"visible\"\n ref=\"contentRef\"\n class=\"ypopover__content\"\n :class=\"[\n `ypopover__content--${placement}`,\n {\n 'ypopover__content--dark': dark,\n 'ypopover__content--no-padding': !showPadding\n }\n ]\"\n :style=\"contentStyle\"\n @click.stop\n @mouseenter=\"handleContentMouseEnter\"\n @mouseleave=\"handleContentMouseLeave\"\n >\n <!-- 箭头 -->\n <div \n v-if=\"showArrow\"\n class=\"ypopover__arrow\"\n :class=\"`ypopover__arrow--${placement}`\"\n :style=\"arrowStyle\"\n ></div>\n \n <!-- 内容 -->\n <div class=\"ypopover__inner\">\n <slot></slot>\n </div>\n </div>\n </Transition>\n </Teleport>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'\n\ninterface Props {\n // 触发方式\n trigger?: 'click' | 'hover' | 'focus' | 'manual'\n // 弹出位置\n placement?: 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end'\n // 是否显示箭头\n showArrow?: boolean\n // 是否显示内边距\n showPadding?: boolean\n // 是否深色主题\n dark?: boolean\n // 是否禁用\n disabled?: boolean\n // 延迟显示时间(hover模式)\n openDelay?: number\n // 延迟隐藏时间(hover模式)\n closeDelay?: number\n // 是否点击外部关闭\n closeOnClickOutside?: boolean\n // 是否点击内容关闭\n closeOnClickContent?: boolean\n // 弹出框宽度\n width?: string | number\n // 弹出框最大宽度\n maxWidth?: string | number\n // 弹出框偏移量\n offset?: number\n // 手动控制显示状态\n modelValue?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n trigger: 'click',\n placement: 'bottom',\n showArrow: true,\n showPadding: true,\n dark: false,\n disabled: false,\n openDelay: 0,\n closeDelay: 200,\n closeOnClickOutside: true,\n closeOnClickContent: false,\n width: 'auto',\n maxWidth: '300px',\n offset: 8,\n modelValue: false\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n 'show': []\n 'hide': []\n 'before-show': []\n 'before-hide': []\n}>()\n\n// 响应式数据\nconst popoverRef = ref<HTMLElement>()\nconst triggerRef = ref<HTMLElement>()\nconst contentRef = ref<HTMLElement>()\nconst visible = ref(false)\nconst triggerRect = ref<DOMRect>()\nconst contentRect = ref<DOMRect>()\nconst arrowPosition = ref<Record<string, string>>({})\n\n// 定时器\nlet openTimer: number | null = null\nlet closeTimer: number | null = null\n\n// 计算属性\nconst contentStyle = computed(() => {\n if (!visible.value || !triggerRect.value) return {}\n \n const style: Record<string, string> = {}\n \n // 设置宽度\n if (props.width !== 'auto') {\n style.width = typeof props.width === 'number' ? `${props.width}px` : props.width\n }\n \n // 设置最大宽度\n if (props.maxWidth) {\n style.maxWidth = typeof props.maxWidth === 'number' ? `${props.maxWidth}px` : props.maxWidth\n }\n \n // 计算位置\n const { top, left } = calculatePosition()\n style.top = `${top}px`\n style.left = `${left}px`\n \n return style\n})\n\nconst arrowStyle = computed(() => {\n if (!props.showArrow) return {}\n \n // 返回计算好的箭头位置,如果没有则使用默认居中\n if (Object.keys(arrowPosition.value).length > 0) {\n return arrowPosition.value\n }\n \n // 默认居中位置\n const style: Record<string, string> = {}\n if (props.placement.startsWith('top') || props.placement.startsWith('bottom')) {\n style.left = '50%'\n } else {\n style.top = '50%'\n }\n return style\n})\n\n// 计算弹出框位置\nfunction calculatePosition() {\n if (!triggerRect.value) return { top: 0, left: 0 }\n \n const { width: triggerWidth, height: triggerHeight, top: triggerTop, left: triggerLeft } = triggerRect.value\n const contentWidth = contentRef.value?.offsetWidth || 200\n const contentHeight = contentRef.value?.offsetHeight || 100\n \n let top = 0\n let left = 0\n \n switch (props.placement) {\n case 'top':\n top = triggerTop - contentHeight - props.offset\n left = triggerLeft + (triggerWidth - contentWidth) / 2\n break\n case 'top-start':\n top = triggerTop - contentHeight - props.offset\n left = triggerLeft\n break\n case 'top-end':\n top = triggerTop - contentHeight - props.offset\n left = triggerLeft + triggerWidth - contentWidth\n break\n case 'bottom':\n top = triggerTop + triggerHeight + props.offset\n left = triggerLeft + (triggerWidth - contentWidth) / 2\n break\n case 'bottom-start':\n top = triggerTop + triggerHeight + props.offset\n left = triggerLeft\n break\n case 'bottom-end':\n top = triggerTop + triggerHeight + props.offset\n left = triggerLeft + triggerWidth - contentWidth\n break\n case 'left':\n top = triggerTop + (triggerHeight - contentHeight) / 2\n left = triggerLeft - contentWidth - props.offset\n break\n case 'left-start':\n top = triggerTop\n left = triggerLeft - contentWidth - props.offset\n break\n case 'left-end':\n top = triggerTop + triggerHeight - contentHeight\n left = triggerLeft - contentWidth - props.offset\n break\n case 'right':\n top = triggerTop + (triggerHeight - contentHeight) / 2\n left = triggerLeft + triggerWidth + props.offset\n break\n case 'right-start':\n top = triggerTop\n left = triggerLeft + triggerWidth + props.offset\n break\n case 'right-end':\n top = triggerTop + triggerHeight - contentHeight\n left = triggerLeft + triggerWidth + props.offset\n break\n }\n \n // 边界检测\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n \n // 水平边界检测\n if (left < 8) left = 8\n if (left + contentWidth > viewportWidth - 8) {\n left = viewportWidth - contentWidth - 8\n }\n \n // 垂直边界检测\n if (top < 8) top = 8\n if (top + contentHeight > viewportHeight - 8) {\n top = viewportHeight - contentHeight - 8\n }\n \n return { top, left }\n}\n\n// 显示弹出框\nfunction show() {\n if (props.disabled || visible.value) return\n \n clearTimers()\n \n if (props.openDelay > 0) {\n openTimer = setTimeout(() => {\n doShow()\n }, props.openDelay)\n } else {\n doShow()\n }\n}\n\nfunction doShow() {\n emit('before-show')\n visible.value = true\n emit('update:modelValue', true)\n emit('show')\n \n // 使用双重 nextTick 确保 DOM 完全更新\n nextTick(() => {\n nextTick(() => {\n updatePosition()\n })\n })\n}\n\n// 隐藏弹出框\nfunction hide() {\n if (!visible.value) return\n \n clearTimers()\n \n if (props.closeDelay > 0) {\n closeTimer = setTimeout(() => {\n doHide()\n }, props.closeDelay)\n } else {\n doHide()\n }\n}\n\nfunction doHide() {\n emit('before-hide')\n visible.value = false\n emit('update:modelValue', false)\n emit('hide')\n}\n\n// 清除定时器\nfunction clearTimers() {\n if (openTimer) {\n clearTimeout(openTimer)\n openTimer = null\n }\n if (closeTimer) {\n clearTimeout(closeTimer)\n closeTimer = null\n }\n}\n\n// 计算箭头位置\nfunction calculateArrowPosition() {\n if (!props.showArrow || !triggerRect.value || !contentRef.value) {\n arrowPosition.value = {}\n return\n }\n \n const trigger = triggerRect.value\n const contentRect = contentRef.value.getBoundingClientRect()\n \n // 如果弹出框还没有正确的尺寸,使用默认居中\n if (contentRect.width === 0 || contentRect.height === 0) {\n const style: Record<string, string> = {}\n if (props.placement.startsWith('top') || props.placement.startsWith('bottom')) {\n style.left = '50%'\n } else {\n style.top = '50%'\n }\n arrowPosition.value = style\n return\n }\n \n const style: Record<string, string> = {}\n \n // 根据位置计算箭头位置\n if (props.placement.startsWith('top')) {\n style.bottom = '-6px'\n // 水平居中\n const triggerCenterX = trigger.left + trigger.width / 2\n const contentLeft = contentRect.left\n const arrowOffset = triggerCenterX - contentLeft\n style.left = `${Math.max(12, Math.min(arrowOffset, contentRect.width - 12))}px`\n } else if (props.placement.startsWith('bottom')) {\n style.top = '-6px'\n // 水平居中\n const triggerCenterX = trigger.left + trigger.width / 2\n const contentLeft = contentRect.left\n const arrowOffset = triggerCenterX - contentLeft\n style.left = `${Math.max(12, Math.min(arrowOffset, contentRect.width - 12))}px`\n } else if (props.placement.startsWith('left')) {\n style.right = '-6px'\n // 垂直居中\n const triggerCenterY = trigger.top + trigger.height / 2\n const contentTop = contentRect.top\n const arrowOffset = triggerCenterY - contentTop\n style.top = `${Math.max(12, Math.min(arrowOffset, contentRect.height - 12))}px`\n } else if (props.placement.startsWith('right')) {\n style.left = '-6px'\n // 垂直居中\n const triggerCenterY = trigger.top + trigger.height / 2\n const contentTop = contentRect.top\n const arrowOffset = triggerCenterY - contentTop\n style.top = `${Math.max(12, Math.min(arrowOffset, contentRect.height - 12))}px`\n }\n \n arrowPosition.value = style\n}\n\n// 更新位置\nfunction updatePosition() {\n if (!triggerRef.value) return\n \n triggerRect.value = triggerRef.value.getBoundingClientRect()\n \n if (contentRef.value) {\n contentRect.value = contentRef.value.getBoundingClientRect()\n \n // 计算箭头位置\n calculateArrowPosition()\n \n // 如果弹出框刚显示,使用 requestAnimationFrame 确保位置正确\n if (visible.value) {\n requestAnimationFrame(() => {\n if (contentRef.value) {\n contentRect.value = contentRef.value.getBoundingClientRect()\n calculateArrowPosition()\n }\n })\n }\n }\n}\n\n// 事件处理\nfunction handleTriggerClick() {\n if (props.disabled) return\n \n if (props.trigger === 'click') {\n if (visible.value) {\n hide()\n } else {\n show()\n }\n }\n}\n\nfunction handleMouseEnter() {\n if (props.disabled || props.trigger !== 'hover') return\n \n clearTimers()\n show()\n}\n\nfunction handleMouseLeave() {\n if (props.disabled || props.trigger !== 'hover') return\n \n hide()\n}\n\n// 鼠标进入弹出框内容\nfunction handleContentMouseEnter() {\n if (props.disabled || props.trigger !== 'hover') return\n \n clearTimers()\n}\n\n// 鼠标离开弹出框内容\nfunction handleContentMouseLeave() {\n if (props.disabled || props.trigger !== 'hover') return\n \n hide()\n}\n\n// 点击外部关闭\nfunction handleClickOutside(event: MouseEvent) {\n if (!props.closeOnClickOutside || !visible.value) return\n \n const target = event.target as HTMLElement\n if (\n popoverRef.value &&\n !popoverRef.value.contains(target) &&\n contentRef.value &&\n !contentRef.value.contains(target)\n ) {\n hide()\n }\n}\n\n// 点击内容关闭\n// function handleContentClick() {\n// if (props.closeOnClickContent) {\n// hide()\n// }\n// }\n\n// 监听 modelValue 变化\nwatch(() => props.modelValue, (newVal) => {\n if (newVal !== visible.value) {\n if (newVal) {\n show()\n } else {\n hide()\n }\n }\n})\n\n// 监听 visible 变化\nwatch(visible, (newVal) => {\n if (newVal) {\n document.addEventListener('click', handleClickOutside)\n window.addEventListener('resize', updatePosition)\n window.addEventListener('scroll', updatePosition, true)\n\n // 初次显示时可能由于 Teleport 尚未完成渲染导致定位不准确,这里增加多次异步更新保证贴边自适应\n nextTick(() => {\n updatePosition()\n requestAnimationFrame(() => {\n updatePosition()\n })\n setTimeout(() => {\n updatePosition()\n }, 0)\n })\n } else {\n document.removeEventListener('click', handleClickOutside)\n window.removeEventListener('resize', updatePosition)\n window.removeEventListener('scroll', updatePosition, true)\n }\n})\n\n// 生命周期\nonMounted(() => {\n if (props.modelValue) {\n show()\n }\n})\n\nonUnmounted(() => {\n clearTimers()\n document.removeEventListener('click', handleClickOutside)\n window.removeEventListener('resize', updatePosition)\n window.removeEventListener('scroll', updatePosition, true)\n})\n\n// 暴露方法\ndefineExpose({\n show,\n hide,\n updatePosition\n})\n</script>\n\n<style scoped lang=\"less\">\n.ypopover {\n display: inline-block;\n}\n\n.ypopover__content {\n position: fixed;\n z-index: 2000;\n background: #ffffff;\n border: 1px solid #e4e7ed;\n border-radius: 4px;\n box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);\n word-wrap: break-word;\n max-width: 300px;\n}\n\n.ypopover__content--dark {\n background: #303133;\n border-color: #303133;\n color: #ffffff;\n}\n\n.ypopover__content--no-padding .ypopover__inner {\n padding: 0;\n}\n\n.ypopover__inner {\n padding: 8px 12px;\n font-size: 14px;\n line-height: 1.4;\n color: #606266;\n}\n\n.ypopover__content--dark .ypopover__inner {\n color: #ffffff;\n}\n\n// 滚动条样式优化\n.ypopover__content,\n.ypopover__inner {\n &::-webkit-scrollbar {\n width: 4px;\n height: 4px;\n }\n\n &::-webkit-scrollbar-track {\n background: transparent;\n border-radius: 2px;\n }\n\n &::-webkit-scrollbar-thumb {\n background: #E7E7E7;\n border-radius: 2px;\n transition: background 0.2s;\n\n &:hover {\n background: #D0D0D0;\n }\n }\n}\n\n.ypopover__content--dark {\n &::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n\n &:hover {\n background: rgba(255, 255, 255, 0.4);\n }\n }\n}\n\n// 穿透样式,应用到 slot 内容中的滚动元素\n:deep(*) {\n &::-webkit-scrollbar {\n width: 4px;\n height: 4px;\n }\n\n &::-webkit-scrollbar-track {\n background: transparent;\n border-radius: 2px;\n }\n\n &::-webkit-scrollbar-thumb {\n background: #E7E7E7;\n border-radius: 2px;\n transition: background 0.2s;\n\n &:hover {\n background: #D0D0D0;\n }\n }\n}\n\n.ypopover__content--dark :deep(*) {\n &::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n\n &:hover {\n background: rgba(255, 255, 255, 0.4);\n }\n }\n}\n\n.ypopover__arrow {\n position: absolute;\n width: 0;\n height: 0;\n border: 6px solid transparent;\n}\n\n.ypopover__arrow--top {\n border-top-color: #e4e7ed;\n border-bottom: none;\n transform: translateX(-50%);\n}\n\n.ypopover__arrow--top::after {\n content: '';\n position: absolute;\n top: -5px;\n left: -6px;\n border: 6px solid transparent;\n border-top-color: #ffffff;\n border-bottom: none;\n}\n\n.ypopover__arrow--bottom {\n border-bottom-color: #e4e7ed;\n border-top: none;\n transform: translateX(-50%);\n}\n\n.ypopover__arrow--bottom::after {\n content: '';\n position: absolute;\n bottom: -5px;\n left: -6px;\n border: 6px solid transparent;\n border-bottom-color: #ffffff;\n border-top: none;\n}\n\n.ypopover__arrow--left {\n border-left-color: #e4e7ed;\n border-right: none;\n transform: translateY(-50%);\n}\n\n.ypopover__arrow--left::after {\n content: '';\n position: absolute;\n left: -5px;\n top: -6px;\n border: 6px solid transparent;\n border-left-color: #ffffff;\n border-right: none;\n}\n\n.ypopover__arrow--right {\n border-right-color: #e4e7ed;\n border-left: none;\n transform: translateY(-50%);\n}\n\n.ypopover__arrow--right::after {\n content: '';\n position: absolute;\n right: -5px;\n top: -6px;\n border: 6px solid transparent;\n border-right-color: #ffffff;\n border-left: none;\n}\n\n// 深色主题箭头\n.ypopover__content--dark .ypopover__arrow--top {\n border-top-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--top::after {\n border-top-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--bottom {\n border-bottom-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--bottom::after {\n border-bottom-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--left {\n border-left-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--left::after {\n border-left-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--right {\n border-right-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--right::after {\n border-right-color: #303133;\n}\n\n// 过渡动画\n.ypopover-fade-enter-active,\n.ypopover-fade-leave-active {\n transition: opacity 0.2s ease;\n}\n\n.ypopover-fade-enter-from,\n.ypopover-fade-leave-to {\n opacity: 0;\n}\n</style>\n","<template>\n <div class=\"nh-time-search\" :class=\"[`nh-time--${size}`]\">\n <!-- 主要输入区域 -->\n <div class=\"relative\">\n <div\n ref=\"trigger\"\n @click=\"toggleDropdown\"\n @keydown=\"handleTriggerKeydown\"\n :class=\"['nh-time-trigger', { 'is-focus': isOpen, 'has-value': hasValue }]\"\n tabindex=\"0\"\n >\n <input\n readonly\n :value=\"displayText\"\n :placeholder=\"placeholder\"\n class=\"nh-time-input\"\n />\n <span class=\"nh-time-suffix\">\n <i \n v-if=\"clearable && hasValue\" \n @click.stop=\"handleClearClick\"\n class=\"nh-time-clear\"\n >\n <svg viewBox=\"0 0 1024 1024\" width=\"14\" height=\"14\">\n <path d=\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1 1.9-11.2c1.5-1.2 3.3-1.9 5.2-1.9l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130.1 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z\" fill=\"currentColor\"/>\n </svg>\n </i>\n \n <i class=\"nh-time-icon\">\n <svg viewBox=\"0 0 1024 1024\" width=\"14\" height=\"14\">\n <path d=\"M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zM648 248v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h112v120H152V248h112v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h312zm184 584H192V424h640v408z\" fill=\"currentColor\"/>\n </svg>\n </i>\n \n <i class=\"nh-time-arrow\" :class=\"{ 'is-reverse': isOpen }\">\n <svg viewBox=\"0 0 1024 1024\" width=\"12\" height=\"12\">\n <path d=\"M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3 0.1-12.7-6.4-12.7z\" fill=\"currentColor\"/>\n </svg>\n </i>\n </span>\n </div>\n\n <!-- 下拉面板 -->\n <transition name=\"el-zoom-in-top\">\n <div\n v-if=\"isOpen\"\n ref=\"dropdown\"\n :class=\"dropdownClasses\"\n @keydown=\"handleDropdownKeydown\"\n >\n <!-- 快捷选项 -->\n <div class=\"nh-time-shortcuts\">\n <div class=\"nh-time-shortcuts-title\">快捷选项</div>\n <ul class=\"nh-time-shortcuts-list\">\n <li\n v-for=\"(shortcut, index) in shortcuts\"\n :key=\"shortcut.label\"\n @click=\"selectShortcut(shortcut)\"\n @keydown=\"handleShortcutKeydown($event, index)\"\n @mouseenter=\"handleShortcutMouseEnter(index)\"\n @mouseleave=\"handleShortcutMouseLeave\"\n :class=\"[\n 'nh-time-shortcut', \n { \n 'is-active': activeShortcutIndex === index,\n 'is-selected': selectedShortcutIndex === index\n }\n ]\"\n tabindex=\"0\"\n >\n {{ shortcut.label }}\n </li>\n </ul>\n </div>\n\n <!-- 自定义时间选择 -->\n <div class=\"nh-time-custom\">\n <div class=\"nh-time-custom-header\">\n <span>自定义时间</span>\n <!-- 新增:选择状态提示 -->\n <div class=\"nh-time-selection-status\">\n <span v-if=\"!tempStartDate && !tempEndDate\" class=\"status-text\">\n 请选择开始日期\n </span>\n <span v-else-if=\"tempStartDate && !tempEndDate\" class=\"status-text\">\n 请选择结束日期\n </span>\n <span v-else-if=\"tempStartDate && tempEndDate\" class=\"status-text status-complete\">\n 已选择完整范围\n </span>\n </div>\n </div>\n \n <!-- 日期选择器容器 -->\n <div class=\"nh-time-pickers\">\n <!-- 开始日期选择器 - 修改为通用日历 -->\n <div class=\"nh-time-picker\">\n <div class=\"nh-date-picker\">\n <!-- 年月选择器 -->\n <div class=\"nh-date-picker-header\">\n <button \n @click=\"changeMonth('start', -1)\"\n class=\"nh-date-picker-btn nh-date-picker-prev-btn\"\n type=\"button\"\n >\n <svg viewBox=\"0 0 1024 1024\" width=\"12\" height=\"12\">\n <path d=\"M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 0 0 0 50.3l450.8 352.1c5.2 4.1 12.9 0.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z\" fill=\"currentColor\"/>\n </svg>\n </button>\n <span class=\"nh-date-picker-header-label\">\n {{ formatYearMonth(startCalendar.year, startCalendar.month) }}\n </span>\n <button \n @click=\"changeMonth('start', 1)\"\n class=\"nh-date-picker-btn nh-date-picker-next-btn\"\n type=\"button\"\n >\n <svg viewBox=\"0 0 1024 1024\" width=\"12\" height=\"12\">\n <path d=\"M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.8 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z\" fill=\"currentColor\"/>\n </svg>\n </button>\n </div>\n \n <!-- 星期标题 -->\n <div class=\"nh-date-picker-content\">\n <table class=\"nh-date-table\">\n <thead>\n <tr>\n <th v-for=\"day in weekDays\" :key=\"day\" class=\"nh-date-table-th\">{{ day }}</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(week, weekIndex) in startCalendarDays\" :key=\"`start-week-${weekIndex}`\">\n <td \n v-for=\"(day, dayIndex) in week\" \n :key=\"`start-day-${weekIndex}-${dayIndex}`\"\n :class=\"getDateCellClass(day, 'start')\"\n @click=\"selectDate(day, 'start')\"\n >\n <div class=\"nh-date-table-cell\">\n <span v-if=\"day\">{{ day.day }}</span>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n \n <!-- 结束日期选择器 - 修改为通用日历 -->\n <div class=\"nh-time-picker\">\n <div class=\"nh-date-picker\">\n <!-- 年月选择器 -->\n <div class=\"nh-date-picker-header\">\n <button \n @click=\"changeMonth('end', -1)\"\n class=\"nh-date-picker-btn nh-date-picker-prev-btn\"\n type=\"button\"\n >\n <svg viewBox=\"0 0 1024 1024\" width=\"12\" height=\"12\">\n <path d=\"M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 0 0 0 50.3l450.8 352.1c5.2 4.1 12.9 0.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z\" fill=\"currentColor\"/>\n </svg>\n </button>\n <span class=\"nh-date-picker-header-label\">\n {{ formatYearMonth(endCalendar.year, endCalendar.month) }}\n </span>\n <button \n @click=\"changeMonth('end', 1)\"\n class=\"nh-date-picker-btn nh-date-picker-next-btn\"\n type=\"button\"\n >\n <svg viewBox=\"0 0 1024 1024\" width=\"12\" height=\"12\">\n <path d=\"M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.8 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z\" fill=\"currentColor\"/>\n </svg>\n </button>\n </div>\n \n <!-- 日期表格 -->\n <div class=\"nh-date-picker-content\">\n <table class=\"nh-date-table\">\n <thead>\n <tr>\n <th v-for=\"day in weekDays\" :key=\"day\" class=\"nh-date-table-th\">{{ day }}</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(week, weekIndex) in endCalendarDays\" :key=\"`end-week-${weekIndex}`\">\n <td \n v-for=\"(day, dayIndex) in week\" \n :key=\"`end-day-${weekIndex}-${dayIndex}`\"\n :class=\"getDateCellClass(day, 'end')\"\n @click=\"selectDate(day, 'end')\"\n >\n <div class=\"nh-date-table-cell\">\n <span v-if=\"day\">{{ day.day }}</span>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"nh-time-actions\">\n <YButton\n v-if=\"clearable\"\n @click=\"clearSelection\"\n :variant=\"'secondary'\"\n :size=\"size\"\n >\n 清空\n </YButton>\n <!-- 修改:优化确定按钮的状态提示 -->\n <YButton\n @click=\"confirmSelection\"\n :disabled=\"!canConfirm\"\n :variant=\"'primary'\"\n :size=\"size\"\n >\n {{ tempStartDate && !tempEndDate ? '继续选择结束日期' : '确认' }}\n </YButton>\n </div>\n </div>\n </div>\n </transition>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'\n\n// 定义类型\ninterface TimeRange {\n startDate: Date | null\n endDate: Date | null\n}\n\ninterface Shortcut {\n label: string\n getValue: () => TimeRange\n}\n\ninterface Props {\n modelValue?: TimeRange | { startDate: string | Date | number | null, endDate: string | Date | number | null }\n placeholder?: string\n shortcuts?: Shortcut[]\n clearable?: boolean\n format?: 'timestamp' | 'string' | 'date'\n includeTime?: boolean\n size?: 'mini' | 'small' | 'medium' | 'large'\n}\n\ninterface CalendarDay {\n date: Date\n day: number\n isCurrentMonth: boolean\n isToday: boolean\n isSelected: boolean\n isInRange: boolean\n isDisabled: boolean\n}\n\n// 定义 props,添加 includeTime 属性并提供默认值\nconst props = withDefaults(defineProps<Props>(), {\n modelValue: () => ({ startDate: null, endDate: null }),\n placeholder: '请选择日期范围',\n clearable: true,\n format: 'timestamp',\n includeTime: false,\n size: 'small',\n shortcuts: () => [\n {\n label: '今天',\n getValue: () => {\n const today = new Date()\n const start = new Date(today.getFullYear(), today.getMonth(), today.getDate())\n const end = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59)\n return { startDate: start, endDate: end }\n }\n },\n {\n label: '昨天',\n getValue: () => {\n const yesterday = new Date()\n yesterday.setDate(yesterday.getDate() - 1)\n const start = new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate())\n const end = new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate(), 23, 59, 59)\n return { startDate: start, endDate: end }\n }\n },\n {\n label: '近7天',\n getValue: () => {\n const end = new Date()\n const start = new Date()\n start.setDate(start.getDate() - 6)\n start.setHours(0, 0, 0, 0)\n end.setHours(23, 59, 59, 999)\n return { startDate: start, endDate: end }\n }\n },\n {\n label: '近30天',\n getValue: () => {\n const end = new Date()\n const start = new Date()\n start.setDate(start.getDate() - 29)\n start.setHours(0, 0, 0, 0)\n end.setHours(23, 59, 59, 999)\n return { startDate: start, endDate: end }\n }\n },\n {\n label: '近3个月',\n getValue: () => {\n const end = new Date()\n const start = new Date()\n start.setMonth(start.getMonth() - 3)\n start.setHours(0, 0, 0, 0)\n end.setHours(23, 59, 59, 999)\n return { startDate: start, endDate: end }\n }\n }\n ]\n})\n\n// 定义 emits\nconst emit = defineEmits<{\n 'update:modelValue': [value: TimeRange | { startDate: string | number | null, endDate: string | number | null }]\n 'change': [value: TimeRange | { startDate: string | number | null, endDate: string | number | null }]\n}>()\n\n// 响应式数据\nconst isOpen = ref(false)\nconst activeShortcutIndex = ref(-1)\nconst selectedShortcutIndex = ref(-1)\nconst pendingValue = ref<TimeRange | null>(null)\nconst trigger = ref<HTMLElement>()\nconst dropdown = ref<HTMLElement>()\nconst dropdownPosition = ref({\n top: true,\n left: true\n})\n\n// 修改:日历相关的响应式数据\nconst startCalendar = ref({\n year: new Date().getFullYear(),\n month: new Date().getMonth()\n})\n\nconst endCalendar = ref({\n year: new Date().getFullYear(),\n month: new Date().getMonth() + 1\n})\n\n// 新增:确保结束日历月份不会与开始日历相同的函数\nconst ensureDifferentMonths = () => {\n const startTime = new Date(startCalendar.value.year, startCalendar.value.month).getTime()\n const endTime = new Date(endCalendar.value.year, endCalendar.value.month).getTime()\n \n if (startTime >= endTime) {\n // 如果开始月份大于等于结束月份,将结束月份设为开始月份的下一个月\n const nextMonth = new Date(startCalendar.value.year, startCalendar.value.month + 1)\n endCalendar.value.year = nextMonth.getFullYear()\n endCalendar.value.month = nextMonth.getMonth()\n }\n}\n\n// 新增:确保开始日历月份不会与结束日历相同的函数\nconst ensureDifferentMonthsReverse = () => {\n const startTime = new Date(startCalendar.value.year, startCalendar.value.month).getTime()\n const endTime = new Date(endCalendar.value.year, endCalendar.value.month).getTime()\n \n if (endTime <= startTime) {\n // 如果结束月份小于等于开始月份,将开始月份设为结束月份的上一个月\n const prevMonth = new Date(endCalendar.value.year, endCalendar.value.month - 1)\n startCalendar.value.year = prevMonth.getFullYear()\n startCalendar.value.month = prevMonth.getMonth()\n }\n}\n\nconst weekDays = ['一', '二', '三', '四', '五', '六', '日']\n\nconst tempStartDate = ref<Date | null>(null)\nconst tempEndDate = ref<Date | null>(null)\n\n// 修改:日期转换工具函数 - 支持时间戳\nconst parseDate = (date: string | Date | number | null): Date | null => {\n if (!date) return null\n if (date instanceof Date) return date\n if (typeof date === 'number') {\n // 时间戳格式\n return new Date(date)\n }\n if (typeof date === 'string') {\n const parsed = new Date(date)\n return isNaN(parsed.getTime()) ? null : parsed\n }\n return null\n}\n\n// 修改:格式化为字符串 - 根据 includeTime 决定返回格式\nconst formatDateToString = (date: Date | null): string | null => {\n if (!date) return null\n \n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n \n if (props.includeTime) {\n // 年月日时分秒格式: YYYY-MM-DD HH:mm:ss\n const hours = String(date.getHours()).padStart(2, '0')\n const minutes = String(date.getMinutes()).padStart(2, '0')\n const seconds = String(date.getSeconds()).padStart(2, '0')\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`\n } else {\n // 年月日格式: YYYY-MM-DD\n return `${year}-${month}-${day}`\n }\n}\n\n// 格式化为时间戳\nconst formatDateToTimestamp = (date: Date | null): number | null => {\n if (!date) return null\n return date.getTime()\n}\n\n// 修改:标准化输入值\nconst normalizeValue = (value: any): TimeRange => {\n if (!value) return { startDate: null, endDate: null }\n \n return {\n startDate: parseDate(value.startDate),\n endDate: parseDate(value.endDate)\n }\n}\n\n// 修改:格式化输出值 - 确保根据 includeTime 属性决定时间戳的精度\nconst formatOutputValue = (value: TimeRange) => {\n if (props.format === 'string') {\n // 返回根据 includeTime 决定的字符串格式\n return {\n startDate: formatDateToString(value.startDate),\n endDate: formatDateToString(value.endDate)\n }\n } else if (props.format === 'timestamp') {\n // 返回时间戳\n return {\n startDate: formatDateToTimestamp(value.startDate),\n endDate: formatDateToTimestamp(value.endDate)\n }\n } else {\n // format === 'date',返回Date对象\n return value\n }\n}\n\n// 工具函数\nconst formatYearMonth = (year: number, month: number) => {\n return `${String(month + 1).padStart(2, '0')}/${year}`\n}\n\nconst isSameDay = (date1: Date, date2: Date) => {\n return date1.getFullYear() === date2.getFullYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate()\n}\n\nconst isDateInRange = (date: Date, start: Date | null, end: Date | null) => {\n if (!start || !end) return false\n return date >= start && date <= end\n}\n\n// 修改:检查当前值是否匹配某个快捷选项\nconst findMatchingShortcutIndex = (currentValue: any): number => {\n const normalizedValue = normalizeValue(currentValue)\n \n if (!normalizedValue?.startDate || !normalizedValue?.endDate) {\n return -1\n }\n\n for (let i = 0; i < props.shortcuts.length; i++) {\n const shortcutValue = props.shortcuts[i].getValue()\n \n if (shortcutValue.startDate && shortcutValue.endDate &&\n normalizedValue.startDate && normalizedValue.endDate) {\n \n // 比较日期时忽略时间部分\n const currentStart = new Date(normalizedValue.startDate.getFullYear(), \n normalizedValue.startDate.getMonth(), \n normalizedValue.startDate.getDate())\n const currentEnd = new Date(normalizedValue.endDate.getFullYear(), \n normalizedValue.endDate.getMonth(), \n normalizedValue.endDate.getDate())\n \n const shortcutStart = new Date(shortcutValue.startDate.getFullYear(), \n shortcutValue.startDate.getMonth(), \n shortcutValue.startDate.getDate())\n const shortcutEnd = new Date(shortcutValue.endDate.getFullYear(), \n shortcutValue.endDate.getMonth(), \n shortcutValue.endDate.getDate())\n \n if (currentStart.getTime() === shortcutStart.getTime() && \n currentEnd.getTime() === shortcutEnd.getTime()) {\n return i\n }\n }\n }\n \n return -1\n}\n\n// 修改:生成日历天数数据,调整日历布局\nconst generateCalendarDays = (year: number, month: number): CalendarDay[][] => {\n const firstDay = new Date(year, month, 1)\n const lastDay = new Date(year, month + 1, 0)\n const firstDayWeek = firstDay.getDay()\n const daysInMonth = lastDay.getDate()\n \n const days: CalendarDay[] = []\n const today = new Date()\n \n // 修改:确保每个月的第一天不在第一个位置\n // 如果当月第一天是周日(0),则显示上个月的6天\n // 否则显示上个月的(firstDayWeek-1)天\n const prevDaysCount = firstDayWeek === 0 ? 6 : firstDayWeek - 1\n \n // 添加上个月的日期 - 设为禁用\n // 修复:应基于当前月份计算上个月的最后一天,避免出现溢出到当月的日期(如 09/31 -> 10/01)\n const prevMonth = new Date(year, month, 0)\n for (let i = prevDaysCount - 1; i >= 0; i--) {\n const date = new Date(year, month - 1, prevMonth.getDate() - i)\n days.push({\n date,\n day: date.getDate(),\n isCurrentMonth: false,\n isToday: isSameDay(date, today),\n isSelected: false,\n isInRange: false,\n isDisabled: true // 禁用非当前月的日期\n })\n }\n \n // 添加当前月的日期\n for (let i = 1; i <= daysInMonth; i++) {\n const date = new Date(year, month, i)\n days.push({\n date,\n day: i,\n isCurrentMonth: true,\n isToday: isSameDay(date, today),\n isSelected: false,\n isInRange: false,\n isDisabled: false\n })\n }\n \n // 添加下个月的日期 - 设为禁用\n const remainingDays = 42 - days.length\n for (let i = 1; i <= remainingDays; i++) {\n const date = new Date(year, month + 1, i)\n days.push({\n date,\n day: i,\n isCurrentMonth: false,\n isToday: isSameDay(date, today),\n isSelected: false,\n isInRange: false,\n isDisabled: true // 禁用非当前月的日期\n })\n }\n \n // 将天数数组分组为周\n const weeks: CalendarDay[][] = []\n for (let i = 0; i < days.length; i += 7) {\n weeks.push(days.slice(i, i + 7))\n }\n \n return weeks\n}\n\n// 方法\nconst updateValue = (value: TimeRange) => {\n const formattedValue = formatOutputValue(value)\n emit('update:modelValue', formattedValue)\n emit('change', formattedValue)\n}\n\n// 新增:计算下拉面板最佳位置的函数\nconst calculateDropdownPosition = () => {\n if (!trigger.value || !dropdown.value) return\n\n const triggerRect = trigger.value.getBoundingClientRect()\n const dropdownRect = dropdown.value.getBoundingClientRect()\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n\n const spaceBelow = viewportHeight - triggerRect.bottom\n const spaceAbove = triggerRect.top\n const dropdownHeight = dropdownRect.height || 400\n \n if (spaceBelow < dropdownHeight && spaceAbove > dropdownHeight) {\n dropdownPosition.value.top = false\n } else {\n dropdownPosition.value.top = true\n }\n\n const spaceRight = viewportWidth - triggerRect.left\n const dropdownWidth = dropdownRect.width || 640\n \n if (spaceRight < dropdownWidth) {\n dropdownPosition.value.left = false\n } else {\n dropdownPosition.value.left = true\n }\n}\n\nconst toggleDropdown = () => {\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n // 初始化临时日期 - 使用标准化的值\n const normalizedValue = normalizeValue(props.modelValue)\n tempStartDate.value = normalizedValue?.startDate || null\n tempEndDate.value = normalizedValue?.endDate || null\n \n // 更新选中的快捷选项索引\n selectedShortcutIndex.value = findMatchingShortcutIndex(props.modelValue)\n \n // 重置键盘导航索引\n activeShortcutIndex.value = -1\n \n // 初始化日历显示月份\n if (normalizedValue?.startDate) {\n startCalendar.value.year = normalizedValue.startDate.getFullYear()\n startCalendar.value.month = normalizedValue.startDate.getMonth()\n }\n \n if (normalizedValue?.endDate) {\n endCalendar.value.year = normalizedValue.endDate.getFullYear()\n endCalendar.value.month = normalizedValue.endDate.getMonth()\n } else {\n // 如果没有结束日期,默认显示开始日期的下一个月\n const nextMonth = new Date(startCalendar.value.year, startCalendar.value.month + 1)\n endCalendar.value.year = nextMonth.getFullYear()\n endCalendar.value.month = nextMonth.getMonth()\n }\n \n // 确保两个日历显示不同的月份\n ensureDifferentMonths()\n \n nextTick(() => {\n calculateDropdownPosition()\n })\n }\n}\n\nconst handleClickOutside = (event: Event) => {\n const target = event.target as HTMLElement\n const triggerEl = trigger.value\n const dropdownEl = dropdown.value\n \n if (triggerEl && dropdownEl && \n !triggerEl.contains(target) && \n !dropdownEl.contains(target)) {\n isOpen.value = false\n activeShortcutIndex.value = -1\n }\n}\n\nconst handleTriggerKeydown = (event: KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n toggleDropdown()\n } else if (event.key === 'ArrowDown') {\n event.preventDefault()\n isOpen.value = true\n nextTick(() => {\n calculateDropdownPosition()\n focusFirstShortcut()\n })\n }\n}\n\nconst handleDropdownKeydown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n isOpen.value = false\n activeShortcutIndex.value = -1\n trigger.value?.focus()\n }\n}\n \nconst handleShortcutKeydown = (event: KeyboardEvent, index: number) => {\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n activeShortcutIndex.value = Math.min(index + 1, props.shortcuts.length - 1)\n focusShortcut(activeShortcutIndex.value)\n } else if (event.key === 'ArrowUp') {\n event.preventDefault()\n activeShortcutIndex.value = Math.max(index - 1, 0)\n focusShortcut(activeShortcutIndex.value)\n } else if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n selectShortcut(props.shortcuts[index])\n }\n}\n\nconst handleShortcutMouseEnter = (index: number) => {\n activeShortcutIndex.value = index\n}\n\nconst handleShortcutMouseLeave = () => {\n activeShortcutIndex.value = -1\n}\n\nconst focusFirstShortcut = () => {\n activeShortcutIndex.value = 0\n focusShortcut(0)\n}\n\nconst focusShortcut = (index: number) => {\n if (dropdown.value) {\n const shortcuts = dropdown.value.querySelectorAll('.nh-time-shortcut')\n const shortcutElement = shortcuts[index] as HTMLElement\n if (shortcutElement) {\n shortcutElement.focus()\n }\n }\n}\n\nconst selectShortcut = (shortcut: Shortcut) => {\n const value = shortcut.getValue()\n \n // 如果需要包含时间,确保时间部分正确设置\n if (props.includeTime && value.startDate && value.endDate) {\n value.startDate.setHours(0, 0, 0, 0)\n value.endDate.setHours(23, 59, 59, 999)\n }\n \n updateValue(value)\n \n // 更新选中的快捷选项索引\n selectedShortcutIndex.value = props.shortcuts.findIndex(s => s.label === shortcut.label)\n \n // 重置键盘导航索引\n activeShortcutIndex.value = -1\n \n isOpen.value = false\n}\n\n// 修改:选择日期时设置时间部分\nconst selectDate = (day: CalendarDay | null, type: 'start' | 'end') => {\n if (!day || day.isDisabled) return\n \n // 创建日期对象,根据是否需要保留时间部分设置时间\n let selectedDate: Date\n \n if (props.includeTime) {\n // 如果需要保留时分秒,则根据开始/结束位置设置不同的时间值\n selectedDate = new Date(day.date)\n if (type === 'start' || !tempStartDate.value) {\n // 开始日期设置为当天 00:00:00\n selectedDate.setHours(0, 0, 0, 0)\n } else {\n // 结束日期设置为当天 23:59:59\n selectedDate.setHours(23, 59, 59, 999)\n }\n } else {\n // 如果不需要保留时分秒,只保留年月日\n selectedDate = new Date(day.date.getFullYear(), day.date.getMonth(), day.date.getDate())\n }\n \n // 智能选择逻辑:\n // 1. 如果没有选择任何日期,当前选择的日期作为开始日期\n // 2. 如果已有开始日期但没有结束日期:\n // - 如果新选择的日期 >= 开始日期,设为结束日期\n // - 如果新选择的日期 < 开始日期,将新日期设为开始日期,原开始日期设为结束日期\n // 3. 如果已有开始和结束日期,重新开始选择:设为新的开始日期,清空结束日期\n \n if (!tempStartDate.value && !tempEndDate.value) {\n // 情况1:没有选择任何日期\n tempStartDate.value = selectedDate\n tempEndDate.value = null\n } else if (tempStartDate.value && !tempEndDate.value) {\n // 情况2:已有开始日期,没有结束日期\n if (selectedDate >= tempStartDate.value) {\n // 选择的日期大于等于开始日期,设为结束日期\n // 确保结束日期总是设置为 23:59:59\n if (props.includeTime) {\n selectedDate.setHours(23, 59, 59, 999)\n }\n tempEndDate.value = selectedDate\n } else {\n // 选择的日期小于开始日期,自动交换:新日期作为开始日期,原开始日期作为结束日期\n const endDate = tempStartDate.value\n // 确保结束日期总是设置为 23:59:59\n if (props.includeTime) {\n endDate.setHours(23, 59, 59, 999)\n }\n tempEndDate.value = endDate\n tempStartDate.value = selectedDate\n }\n } else {\n // 情况3:已有开始和结束日期,重新开始选择\n tempStartDate.value = selectedDate\n tempEndDate.value = null\n }\n \n // 清除快捷选项的选中状态,因为用户选择了自定义日期\n selectedShortcutIndex.value = -1\n \n // 更新待确认的值\n if (tempStartDate.value && tempEndDate.value) {\n // 确保结束日期总是设置为 23:59:59(如果启用了时间)\n const endDate = new Date(tempEndDate.value)\n if (props.includeTime) {\n endDate.setHours(23, 59, 59, 999)\n }\n pendingValue.value = { \n startDate: tempStartDate.value, \n endDate: endDate \n }\n } else {\n pendingValue.value = null\n }\n}\n\nconst getDateCellClass = (day: CalendarDay | null, type: 'start' | 'end') => {\n if (!day) return ['nh-date-table-td']\n \n const classes = ['nh-date-table-td']\n \n if (!day.isCurrentMonth) {\n classes.push('is-prev-month')\n }\n \n if (day.isToday) {\n classes.push('is-today')\n }\n \n if (day.isDisabled) {\n classes.push('is-disabled')\n }\n \n // 检查是否是选中的日期\n if (tempStartDate.value && isSameDay(day.date, tempStartDate.value)) {\n classes.push('is-selected', 'is-start')\n }\n \n if (tempEndDate.value && isSameDay(day.date, tempEndDate.value)) {\n classes.push('is-selected', 'is-end')\n }\n \n // 检查是否在选中范围内\n if (tempStartDate.value && tempEndDate.value && \n isDateInRange(day.date, tempStartDate.value, tempEndDate.value)) {\n classes.push('is-in-range')\n }\n \n return classes\n}\n\nconst confirmSelection = () => {\n if (pendingValue.value) {\n // 再次确保结束日期设置为 23:59:59(如果启用了时间)\n if (props.includeTime && pendingValue.value.endDate) {\n pendingValue.value.endDate.setHours(23, 59, 59, 999)\n }\n \n updateValue(pendingValue.value)\n // 检查新的值是否匹配某个快捷选项\n selectedShortcutIndex.value = findMatchingShortcutIndex(pendingValue.value)\n isOpen.value = false\n }\n}\n\nconst clearSelection = () => {\n updateValue({ startDate: null, endDate: null })\n resetSelection()\n activeShortcutIndex.value = -1\n isOpen.value = false\n}\n\n// 新增:监听窗口大小变化,重新计算位置\nconst handleResize = () => {\n if (isOpen.value) {\n nextTick(() => {\n calculateDropdownPosition()\n })\n }\n}\n\n// 计算属性\nconst startCalendarDays = computed(() => {\n return generateCalendarDays(startCalendar.value.year, startCalendar.value.month)\n})\n\nconst endCalendarDays = computed(() => {\n return generateCalendarDays(endCalendar.value.year, endCalendar.value.month)\n})\n\nconst displayText = computed(() => {\n const normalizedValue = normalizeValue(props.modelValue)\n \n if (!normalizedValue || !normalizedValue.startDate || !normalizedValue.endDate) {\n return ''\n }\n \n const formatDate = (date: Date) => {\n const year = String(date.getFullYear())\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n return `${year}/${month}/${day}`\n }\n \n const startStr = formatDate(normalizedValue.startDate)\n const endStr = formatDate(normalizedValue.endDate)\n \n // 如果是同一天且不包含时间,只显示一个日期\n if (!props.includeTime && startStr === endStr) {\n return startStr\n }\n \n return `${startStr} - ${endStr}`\n})\n\nconst dropdownClasses = computed(() => {\n return [\n 'nh-time-dropdown',\n {\n 'nh-time-dropdown-top': !dropdownPosition.value.top,\n 'nh-time-dropdown-right': !dropdownPosition.value.left\n }\n ]\n})\n\n// 新增计算属性:检查是否有值\nconst hasValue = computed(() => {\n const normalizedValue = normalizeValue(props.modelValue)\n return !!(normalizedValue?.startDate && normalizedValue?.endDate)\n})\n\n// 新增计算属性:检查是否可以确认 - 修改逻辑\nconst canConfirm = computed(() => {\n return !!(tempStartDate.value && tempEndDate.value)\n})\n\n// 修改:格式化显示日期(用于选择器标题)- 增强显示格式\n// const formatDisplayDate = (date: Date) => {\n// return new Intl.DateTimeFormat('zh-CN', {\n// month: '2-digit',\n// day: '2-digit'\n// }).format(date)\n// }\n\n// 新增:重置选择状态的方法\nconst resetSelection = () => {\n tempStartDate.value = null\n tempEndDate.value = null\n pendingValue.value = null\n selectedShortcutIndex.value = -1\n}\n\n// 监听器 - 修改以确保日历月份正确初始化\nwatch(() => props.modelValue, (newValue) => {\n const normalizedValue = normalizeValue(newValue)\n \n if (normalizedValue?.startDate) {\n const startDate = normalizedValue.startDate\n startCalendar.value.year = startDate.getFullYear()\n startCalendar.value.month = startDate.getMonth()\n }\n \n if (normalizedValue?.endDate) {\n const endDate = normalizedValue.endDate\n endCalendar.value.year = endDate.getFullYear()\n endCalendar.value.month = endDate.getMonth()\n } else if (normalizedValue?.startDate) {\n // 如果只有开始日期,结束日历显示下一个月\n const nextMonth = new Date(startCalendar.value.year, startCalendar.value.month + 1)\n endCalendar.value.year = nextMonth.getFullYear()\n endCalendar.value.month = nextMonth.getMonth()\n }\n \n // 确保两个日历显示不同的月份\n if (normalizedValue?.startDate || normalizedValue?.endDate) {\n ensureDifferentMonths()\n }\n \n // 当外部值改变时,更新选中的快捷选项\n if (!isOpen.value) {\n selectedShortcutIndex.value = findMatchingShortcutIndex(newValue)\n }\n}, { immediate: true, deep: true })\n\n// 新增:监听日历月份变化,确保不会显示相同月份\nwatch([startCalendar, endCalendar], () => {\n const startTime = new Date(startCalendar.value.year, startCalendar.value.month).getTime()\n const endTime = new Date(endCalendar.value.year, endCalendar.value.month).getTime()\n \n // 如果两个日历显示相同月份,自动调整\n if (startTime === endTime) {\n const nextMonth = new Date(startCalendar.value.year, startCalendar.value.month + 1)\n endCalendar.value.year = nextMonth.getFullYear()\n endCalendar.value.month = nextMonth.getMonth()\n }\n}, { deep: true })\n\n// 生命周期\nonMounted(() => {\n document.addEventListener('click', handleClickOutside)\n window.addEventListener('resize', handleResize)\n window.addEventListener('scroll', handleResize)\n \n // 初始化时设置选中的快捷选项和日历月份\n selectedShortcutIndex.value = findMatchingShortcutIndex(props.modelValue)\n \n // 修复:初始化日历月份时使用标准化的值\n const normalizedValue = normalizeValue(props.modelValue)\n \n if (normalizedValue?.startDate) {\n startCalendar.value.year = normalizedValue.startDate.getFullYear()\n startCalendar.value.month = normalizedValue.startDate.getMonth()\n }\n \n if (normalizedValue?.endDate) {\n endCalendar.value.year = normalizedValue.endDate.getFullYear()\n endCalendar.value.month = normalizedValue.endDate.getMonth()\n } else {\n // 默认显示当前月和下个月\n const nextMonth = new Date(startCalendar.value.year, startCalendar.value.month + 1)\n endCalendar.value.year = nextMonth.getFullYear()\n endCalendar.value.month = nextMonth.getMonth()\n }\n \n ensureDifferentMonths()\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', handleClickOutside)\n window.removeEventListener('resize', handleResize)\n window.removeEventListener('scroll', handleResize)\n})\n\n// 新增:处理输入框清空按钮点击\nconst handleClearClick = () => {\n if (!props.clearable) return\n \n updateValue({ startDate: null, endDate: null })\n resetSelection()\n activeShortcutIndex.value = -1\n}\n\n// 修改:日期选择相关方法\nconst changeMonth = (type: 'start' | 'end', direction: number) => {\n if (type === 'start') {\n const newDate = new Date(startCalendar.value.year, startCalendar.value.month + direction, 1)\n startCalendar.value.year = newDate.getFullYear()\n startCalendar.value.month = newDate.getMonth()\n \n // 确保结束月份不会与开始月份相同\n ensureDifferentMonths()\n } else {\n const newDate = new Date(endCalendar.value.year, endCalendar.value.month + direction, 1)\n endCalendar.value.year = newDate.getFullYear()\n endCalendar.value.month = newDate.getMonth()\n \n // 确保开始月份不会与结束月份相同\n ensureDifferentMonthsReverse()\n }\n}\n</script>\n\n<style scoped>\n/* 基础样式,与 YInput/YSelect 风格统一 */\n.nh-time-search {\n position: relative;\n display: inline-block;\n width: 250px;\n font-size: 14px;\n color: #0b1a29;\n}\n\n.nh-time-trigger {\n position: relative;\n display: inline-block;\n width: 100%;\n cursor: pointer;\n}\n\n.nh-time-trigger.is-focus .nh-time-input {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59,130,246,0.15);\n}\n\n.nh-time-input {\n background-color: #ffffff;\n border: 1px solid #e2e8f0;\n border-radius: 10px;\n box-sizing: border-box;\n color: #0b1a29;\n display: inline-block;\n font-size: inherit;\n outline: none;\n padding: 0 40px 0 12px;\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n width: 100%;\n cursor: pointer;\n font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif;\n}\n\n.nh-time-input:hover { border-color: #60a5fa; }\n\n.nh-time-input:focus {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59,130,246,0.15);\n outline: none;\n}\n\n.nh-time-input::placeholder {\n color: #9ca3af;\n}\n\n.nh-time-suffix {\n position: absolute;\n height: 100%;\n right: 8px;\n top: 0;\n display: flex;\n align-items: center;\n color: #6b7280;\n font-size: 14px;\n pointer-events: none;\n gap: 4px;\n}\n\n.nh-time-icon { display: flex; align-items: center; }\n\n.nh-time-arrow {\n display: flex;\n align-items: center;\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n}\n\n.nh-time-clear {\n display: flex;\n align-items: center;\n cursor: pointer;\n color: #9ca3af;\n transition: all 0.2s ease;\n pointer-events: auto;\n}\n\n.nh-time-clear:hover {\n color: #6b7280;\n}\n\n.nh-time-clear:active {\n transform: scale(0.9);\n}\n\n/* 下拉面板样式 */\n.nh-time-dropdown {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n z-index: 50;\n background: #ffffff;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n box-shadow: 0 8px 20px rgba(2,6,23,0.15);\n display: flex;\n min-width: 640px;\n max-width: calc(100vw - 20px);\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.nh-time-dropdown-top {\n top: auto;\n bottom: calc(100% + 4px);\n}\n\n.nh-time-dropdown-right {\n left: auto;\n right: 0;\n}\n\n/* 快捷选项样式 */\n.nh-time-shortcuts {\n width: 140px;\n border-right: 1px solid #e5e7eb;\n background-color: #f9fafb;\n}\n\n.nh-time-shortcuts-title {\n padding: 12px 16px 8px;\n color: #374151;\n font-size: 12px;\n font-weight: 500;\n border-bottom: 1px solid #e5e7eb;\n background-color: #f9fafb;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.nh-time-shortcuts-list {\n margin: 0;\n padding: 4px 0;\n list-style: none;\n}\n\n.nh-time-shortcut {\n display: block;\n width: 100%;\n padding: 8px 16px;\n margin: 0;\n font-size: 13px;\n color: #374151;\n cursor: pointer;\n border: none;\n background: none;\n text-align: left;\n outline: none;\n transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out;\n font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif;\n}\n\n.nh-time-shortcut:hover,\n.nh-time-shortcut.is-active {\n background-color: #f3f4f6;\n color: #1f2937;\n}\n\n.nh-time-shortcut:focus {\n background-color: #f3f4f6;\n outline: none;\n}\n\n.nh-time-shortcut.is-selected {\n background-color: #313B4A !important;\n color: #ffffff !important;\n}\n\n.nh-time-shortcut.is-selected:hover {\n background-color: #354051 !important;\n color: #ffffff !important;\n}\n\n.nh-time-shortcut:active {\n background-color: #e5e7eb;\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n transform: translateY(1px);\n}\n\n/* 自定义时间选择样式 */\n.nh-time-custom {\n flex: 1;\n padding: 8px 16px;\n background-color: #ffffff;\n}\n\n.nh-time-custom-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.nh-time-custom-header span {\n font-size: 14px;\n font-weight: 500;\n color: #374151;\n}\n\n/* 选择状态提示样式 */\n.nh-time-selection-status {\n display: flex;\n align-items: center;\n}\n\n.status-text {\n font-size: 12px;\n color: #6b7280;\n padding: 4px 8px;\n border-radius: 4px;\n background-color: #f3f4f6;\n font-weight: 500;\n}\n\n.status-text.status-complete {\n color: #059669;\n background-color: #d1fae5;\n}\n\n.nh-time-pickers {\n display: flex;\n gap: 24px;\n margin-bottom: 8px;\n}\n\n.nh-time-picker {\n flex: 1;\n}\n\n.nh-time-picker-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid #f3f4f6;\n min-height: 40px;\n}\n\n.nh-time-picker-title {\n font-size: 13px;\n color: #6b7280;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.nh-time-picker-dates {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 2px;\n}\n\n.nh-time-picker-date {\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 3px;\n font-weight: 500;\n}\n\n.nh-time-picker-date.start-date {\n color: #313B4A;\n background-color: #e4f0fd;\n}\n\n.nh-time-picker-date.end-date {\n color: #059669;\n background-color: #d1fae5;\n}\n\n.nh-time-picker-hint {\n display: flex;\n align-items: center;\n}\n\n.hint-text {\n font-size: 11px;\n color: #9ca3af;\n text-align: right;\n line-height: 1.3;\n max-width: 120px;\n}\n\n/* 日期选择器样式 */\n.nh-date-picker {\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: #ffffff;\n overflow: hidden;\n}\n\n.nh-date-picker:before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: 8px;\n padding: 1px;\n background: linear-gradient(to bottom, rgba(255, 255, 255, 0.8), rgba(229, 231, 235, 0.5));\n mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask-composite: xor;\n mask-composite: exclude;\n pointer-events: none;\n}\n\n.nh-date-picker-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background-color: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n}\n\n.nh-date-picker-header-label {\n font-size: 14px;\n font-weight: 600;\n color: #374151;\n}\n\n.nh-date-picker-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 6px;\n color: #6b7280;\n transition: all 0.15s ease-in-out;\n}\n\n.nh-date-picker-btn:hover {\n background-color: #f3f4f6;\n color: #374151;\n}\n\n.nh-date-picker-btn:focus {\n outline: none;\n background-color: #f3f4f6;\n}\n\n.nh-date-picker-btn:active {\n transform: translateY(0);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.05);\n background: linear-gradient(to bottom, #f3f4f6, #e5e7eb);\n}\n\n.nh-date-picker-content {\n padding: 12px;\n background: linear-gradient(135deg, #ffffff, #fafafa);\n}\n\n/* 日期表格样式 */\n.nh-date-table {\n width: 100%;\n border-collapse: collapse;\n table-layout: fixed;\n}\n\n.nh-date-table-th {\n padding: 8px 4px;\n text-align: center;\n font-size: 11px;\n color: #6b7280;\n font-weight: 500;\n border-bottom: 1px solid #f3f4f6;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.nh-date-table-td {\n width: 32px;\n height: 32px;\n padding: 3px;\n box-sizing: border-box;\n}\n\n.nh-date-table-cell {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 26px;\n width: 26px;\n margin: 0 auto;\n border-radius: 6px;\n font-size: 13px;\n color: #374151;\n transition: all 0.15s ease-in-out;\n position: relative;\n font-weight: 400;\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.02);\n}\n\n.nh-date-table-td:hover .nh-date-table-cell {\n background-color: #f3f4f6;\n color: #1f2937;\n}\n\n/* 日期状态样式 - 修改禁用状态但保留选中样式 */\n.nh-date-table-td.is-prev-month .nh-date-table-cell {\n color: #d1d5db;\n background-color: #f9fafb;\n cursor: not-allowed;\n}\n\n.nh-date-table-td.is-prev-month:hover .nh-date-table-cell {\n background-color: #f9fafb;\n color: #d1d5db;\n}\n\n/* 禁用状态的通用样式 */\n.nh-date-table-td.is-disabled .nh-date-table-cell {\n background-color: #f9fafb;\n color: #d1d5db;\n cursor: not-allowed;\n}\n\n.nh-date-table-td.is-disabled:hover .nh-date-table-cell {\n background-color: #f9fafb;\n color: #d1d5db;\n}\n\n/* 保留正常的选中状态样式 */\n.nh-date-table-td.is-selected .nh-date-table-cell {\n background-color: #313B4A;\n color: #ffffff;\n font-weight: 500;\n}\n\n.nh-date-table-td.is-in-range .nh-date-table-cell {\n background-color: #e4f0fd;\n color: #313B4A;\n}\n\n.nh-date-table-td.is-start .nh-date-table-cell,\n.nh-date-table-td.is-end .nh-date-table-cell {\n background-color: #313B4A;\n color: #ffffff;\n font-weight: 500;\n}\n\n/* 今天标记 */\n.nh-date-table-td.is-today .nh-date-table-cell {\n color: #c23616;\n font-weight: 600;\n}\n\n/* 修改:禁用且在选中范围内的日期显示为灰色背景 */\n.nh-date-table-td.is-disabled.is-in-range .nh-date-table-cell {\n background-color: #f3f4f6 !important;\n color: #9ca3af !important;\n cursor: not-allowed;\n}\n\n/* 修改:禁用且是开始/结束日期的样式 */\n.nh-date-table-td.is-disabled.is-start .nh-date-table-cell,\n.nh-date-table-td.is-disabled.is-end .nh-date-table-cell {\n background-color: #9ca3af !important;\n color: #ffffff !important;\n cursor: not-allowed;\n}\n\n.nh-date-table-td.is-disabled.is-selected .nh-date-table-cell {\n background-color: #9ca3af !important;\n color: #ffffff !important;\n cursor: not-allowed;\n}\n\n/* 修改:只有禁用且未选中的日期才显示完全禁用样式 */\n.nh-date-table-td.is-disabled:not(.is-selected):not(.is-start):not(.is-end):not(.is-in-range) .nh-date-table-cell {\n background-color: #f9fafb;\n color: #d1d5db;\n cursor: not-allowed;\n}\n\n.nh-date-table-td.is-disabled:not(.is-selected):not(.is-start):not(.is-end):not(.is-in-range):hover .nh-date-table-cell {\n background-color: #f9fafb;\n color: #d1d5db;\n}\n\n/* 今天标记 - 非当前月的禁用状态 */\n.nh-date-table-td.is-disabled.is-today:not(.is-selected):not(.is-start):not(.is-end):not(.is-in-range) .nh-date-table-cell {\n color: #d1d5db;\n font-weight: 600;\n background-color: #f9fafb;\n}\n\n/* 修改:禁用范围内日期的连接线样式 */\n.nh-date-table-td.is-disabled.is-in-range::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 0;\n right: 0;\n height: 26px;\n background-color: rgba(156, 163, 175, 0.2);\n transform: translateY(-50%);\n z-index: -1;\n border: 1px solid rgba(156, 163, 175, 0.3);\n}\n\n/* 保留选中范围的连续效果 - 正常状态 */\n.nh-date-table-td.is-in-range:not(.is-disabled)::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 0;\n right: 0;\n height: 26px;\n background-color: rgba(49, 59, 74, 0.1);\n transform: translateY(-50%);\n z-index: -1;\n border: 1px solid rgba(49, 59, 74, 0.2);\n}\n\n.nh-date-table-td.is-start.is-in-range::before {\n left: 50%;\n}\n\n.nh-date-table-td.is-end.is-in-range::before {\n right: 50%;\n}\n\n.nh-date-table-td.is-start.is-end.is-in-range::before {\n display: none;\n}\n\n/* 修改:禁用日期的视觉标记为灰色 */\n.nh-date-table-td.is-disabled.is-start .nh-date-table-cell::before {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 6px;\n height: 6px;\n background-color: #d1d5db;\n border-radius: 50%;\n z-index: 1;\n}\n\n.nh-date-table-td.is-disabled.is-end .nh-date-table-cell::after {\n content: '';\n position: absolute;\n bottom: 2px;\n right: 2px;\n width: 6px;\n height: 6px;\n background-color: #d1d5db;\n border-radius: 50%;\n z-index: 1;\n}\n\n/* 保留正常日期范围视觉标记 */\n.nh-date-table-td.is-start:not(.is-disabled) .nh-date-table-cell::before {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 6px;\n height: 6px;\n background-color: #ffffff;\n border-radius: 50%;\n z-index: 1;\n}\n\n.nh-date-table-td.is-end:not(.is-disabled) .nh-date-table-cell::after {\n content: '';\n position: absolute;\n bottom: 2px;\n right: 2px;\n width: 6px;\n height: 6px;\n background-color: #ffffff;\n border-radius: 50%;\n z-index: 1;\n}\n\n/* 只有完全禁用且未选中的日期才隐藏范围连接线和标记 */\n.nh-date-table-td.is-disabled:not(.is-selected):not(.is-start):not(.is-end):not(.is-in-range) .nh-date-table-cell::before,\n.nh-date-table-td.is-disabled:not(.is-selected):not(.is-start):not(.is-end):not(.is-in-range) .nh-date-table-cell::after {\n display: none;\n}\n\n.nh-time-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding-top: 2px;\n}\n\n/* 尺寸适配,与 YInput/YButton 保持一致 */\n.nh-time--mini .nh-time-input { height: 24px; border-radius: 6px; font-size: 11px; }\n.nh-time--small .nh-time-input { height: 32px; border-radius: 8px; font-size: 12px; }\n.nh-time--medium .nh-time-input { height: 44px; border-radius: 10px; font-size: 14px; }\n.nh-time--large .nh-time-input { height: 52px; border-radius: 12px; font-size: 16px; }\n\n/* 过渡动画 */\n.el-zoom-in-top-enter-active,\n.el-zoom-in-top-leave-active {\n opacity: 1;\n transform: scale(1);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n transform-origin: top;\n}\n\n.el-zoom-in-top-enter-from,\n.el-zoom-in-top-leave-to {\n opacity: 0;\n transform: scale(0.95);\n}\n\n/* 输入框状态优化 */\n.nh-time-trigger.has-value .nh-time-input {\n color: #1f2937;\n font-weight: 500;\n background-image: linear-gradient(to bottom, #ffffff, #f9fafb);\n}\n\n.nh-time-trigger:not(.has-value) .nh-time-input {\n color: #9ca3af;\n}\n\n/* 箭头旋转动画 */\n.nh-time-arrow {\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n}\n\n.nh-time-arrow.is-reverse {\n transform: rotate(180deg);\n}\n\n/* 日历图标优化 */\n.nh-time-icon {\n display: flex;\n align-items: center;\n color: #6b7280;\n filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.1));\n}\n\n.nh-time-trigger.is-focus .nh-time-icon {\n color: #313B4A;\n filter: drop-shadow(0 1px 2px rgba(49, 59, 74, 0.2));\n}\n\n/* 输入框聚焦状态优化 */\n.nh-time-trigger.is-focus {\n box-shadow: 0 0 0 2px rgba(49, 59, 74, 0.2), 0 2px 5px rgba(0, 0, 0, 0.1);\n border-radius: 6px;\n}\n\n/* 清空按钮优化 */\n.nh-time-clear {\n opacity: 0;\n transition: all 0.2s ease;\n transform-origin: center;\n}\n\n.nh-time-trigger:hover .nh-time-clear,\n.nh-time-trigger.is-focus .nh-time-clear {\n opacity: 1;\n}\n\n/* 响应式设计 */\n@media (max-width: 768px) {\n .nh-time-search {\n width: 200px;\n }\n \n .nh-time-dropdown {\n min-width: 320px;\n max-width: calc(100vw - 20px);\n flex-direction: column;\n }\n \n .nh-time-shortcuts {\n width: 100%;\n border-right: none;\n border-bottom: 1px solid #e5e7eb;\n box-shadow: 0 2px 4px -2px rgba(0, 0, 0, 0.05);\n }\n \n .nh-time-shortcuts-list {\n display: flex;\n flex-wrap: wrap;\n padding: 8px;\n gap: 4px;\n }\n \n .nh-time-shortcut {\n flex: 1;\n min-width: 80px;\n text-align: center;\n padding: 6px 8px;\n border-radius: 4px;\n }\n \n .nh-time-pickers {\n flex-direction: column;\n gap: 12px;\n }\n \n .nh-date-picker-header-label {\n font-size: 13px;\n }\n \n .nh-date-table-cell {\n height: 24px;\n width: 24px;\n font-size: 12px;\n }\n \n .nh-date-table-td {\n height: 24px;\n width: 24px;\n }\n \n .nh-time-picker-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n min-height: auto;\n }\n \n .nh-time-picker-dates {\n align-items: flex-start;\n width: 100%;\n }\n \n .hint-text {\n max-width: 100%;\n text-align: left;\n }\n \n .nh-time-actions {\n flex-direction: row;\n gap: 8px;\n }\n}\n\n/* 增强立体感的额外效果 */\n/* 悬停时的提升效果 */\n.nh-date-table-td:not(.is-disabled):hover {\n z-index: 1;\n}\n\n.nh-date-table-td:not(.is-disabled):active .nh-date-table-cell {\n transform: translateY(0);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n transition: all 0.1s ease;\n}\n\n/* 选中日期的脉冲动画效果 */\n@keyframes pulse {\n 0% {\n box-shadow: 0 0 0 0 rgba(49, 59, 74, 0.4);\n }\n 70% {\n box-shadow: 0 0 0 6px rgba(49, 59, 74, 0);\n }\n 100% {\n box-shadow: 0 0 0 0 rgba(49, 59, 74, 0);\n }\n}\n\n.nh-date-table-td.is-selected:not(.is-disabled) .nh-date-table-cell {\n animation: pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) 1;\n}\n\n/* 日期选择器边框渐变效果 */\n.nh-date-picker {\n position: relative;\n}\n\n.nh-date-picker:before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: 8px;\n padding: 1px;\n background: linear-gradient(to bottom, rgba(255, 255, 255, 0.8), rgba(229, 231, 235, 0.5));\n mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask-composite: xor;\n mask-composite: exclude;\n pointer-events: none;\n}\n\n/* 月份切换按钮的点击效果 */\n.nh-date-picker-btn:active {\n transform: translateY(0);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.05);\n background: linear-gradient(to bottom, #f3f4f6, #e5e7eb);\n}\n\n/* 快捷选项的点击效果 */\n.nh-time-shortcut:active {\n background-color: #e5e7eb;\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n transform: translateY(1px);\n}\n\n/* 下拉面板的内阴影效果 */\n.nh-time-dropdown:before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: 10px;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5);\n pointer-events: none;\n}\n\n/* 日期选择器内容区域的微妙渐变 */\n.nh-date-picker-content {\n background: linear-gradient(135deg, #ffffff, #fafafa);\n}\n\n/* 日期单元格的微妙阴影 */\n.nh-date-table-cell {\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.02);\n}\n\n/* 当前日期的特殊标记 */\n.nh-date-table-td.is-today .nh-date-table-cell:after {\n content: '';\n position: absolute;\n bottom: 3px;\n left: 50%;\n transform: translateX(-50%);\n width: 4px;\n height: 4px;\n background-color: #313B4A;\n border-radius: 50%;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n/* 选择状态完成的微妙动画 */\n@keyframes completeStatus {\n 0% {\n transform: scale(0.9);\n opacity: 0.7;\n }\n 50% {\n transform: scale(1.05);\n opacity: 1;\n }\n 100% {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.status-text.status-complete {\n animation: completeStatus 0.3s ease-out;\n}\n\n/* 日历标题的微妙阴影 */\n.nh-date-picker-header-label {\n position: relative;\n z-index: 1;\n}\n\n.nh-date-picker-header-label:after {\n content: '';\n position: absolute;\n bottom: -2px;\n left: 0;\n width: 100%;\n height: 4px;\n background: linear-gradient(to right, rgba(49, 59, 74, 0), rgba(49, 59, 74, 0.1), rgba(49, 59, 74, 0));\n border-radius: 2px;\n z-index: -1;\n}\n\n/* 日期范围选择的过渡效果 */\n.nh-date-table-td.is-in-range .nh-date-table-cell {\n transition: background 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;\n}\n\n/* 日期选择器的整体边框效果 */\n.nh-time-picker {\n position: relative;\n overflow: visible;\n}\n\n.nh-time-picker:after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: 10px;\n box-shadow: 0 0 0 1px rgba(229, 231, 235, 0.8);\n pointer-events: none;\n}\n</style>","<template>\n <button\n ref=\"rootEl\"\n class=\"yswitch\"\n :class=\"[\n `yswitch--${size}`,\n { 'yswitch--checked': isChecked, 'yswitch--disabled': disabled, 'yswitch--loading': loading }\n ]\"\n :style=\"switchStyle\"\n role=\"switch\"\n :aria-checked=\"isChecked\"\n :aria-disabled=\"disabled\"\n :disabled=\"disabled || loading\"\n @click=\"onToggle\"\n @keydown.enter.prevent=\"onToggle\"\n @keydown.space.prevent=\"onToggle\"\n >\n <span class=\"yswitch__track\"></span>\n <span class=\"yswitch__thumb\">\n <span v-if=\"loading\" class=\"yswitch__spinner\" aria-hidden=\"true\"></span>\n </span>\n <span v-if=\"showText\" class=\"yswitch__label\" :class=\"{ 'yswitch__label--left': !isChecked, 'yswitch__label--right': isChecked }\">\n {{ isChecked ? activeText : inactiveText }}\n </span>\n </button>\n \n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, onMounted } from 'vue'\n\nexport interface SwitchProps<T = boolean> {\n modelValue?: T\n trueValue?: T\n falseValue?: T\n disabled?: boolean\n loading?: boolean\n size?: 'small' | 'medium' | 'large'\n activeColor?: string\n inactiveColor?: string\n activeText?: string\n inactiveText?: string\n showText?: boolean\n}\n\nconst props = withDefaults(defineProps<SwitchProps>(), {\n modelValue: false,\n trueValue: true,\n falseValue: false,\n disabled: false,\n loading: false,\n size: 'medium',\n activeColor: '#10b981',\n inactiveColor: '#e5e7eb',\n activeText: '开',\n inactiveText: '关',\n showText: false,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: any]\n 'change': [value: any]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\nconst rootEl = ref<HTMLButtonElement>()\n\nconst isChecked = computed(() => props.modelValue === props.trueValue)\n\nconst switchStyle = computed(() => {\n const style: Record<string, string> = {}\n // 轨道背景色\n style.background = isChecked.value ? props.activeColor : props.inactiveColor\n return style\n})\n\nfunction onToggle() {\n if (props.disabled || props.loading) return\n const next = isChecked.value ? props.falseValue : props.trueValue\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nonMounted(() => {\n const el = rootEl.value\n if (!el) return\n el.addEventListener('focus', (e) => emit('focus', e as FocusEvent))\n el.addEventListener('blur', (e) => emit('blur', e as FocusEvent))\n})\n\n</script>\n\n<style scoped lang=\"less\">\n.yswitch {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: flex-start;\n border: none;\n cursor: pointer;\n outline: none;\n user-select: none;\n background: #e5e7eb;\n border-radius: 999px;\n transition: background-color 0.2s ease, box-shadow 0.2s ease;\n padding: 0;\n}\n\n.yswitch:focus-visible {\n box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.2);\n}\n\n.yswitch--disabled {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.yswitch__track {\n position: absolute;\n inset: 0;\n border-radius: 999px;\n}\n\n.yswitch__thumb {\n position: relative;\n background: #ffffff;\n border-radius: 50%;\n transition: transform 0.2s ease;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.yswitch--small {\n width: 36px;\n height: 20px;\n}\n.yswitch--small .yswitch__thumb {\n width: 16px;\n height: 16px;\n transform: translateX(2px);\n}\n.yswitch--small.yswitch--checked .yswitch__thumb {\n transform: translateX(18px);\n}\n\n.yswitch--medium {\n width: 44px;\n height: 24px;\n}\n.yswitch--medium .yswitch__thumb {\n width: 20px;\n height: 20px;\n transform: translateX(2px);\n}\n.yswitch--medium.yswitch--checked .yswitch__thumb {\n transform: translateX(22px);\n}\n\n.yswitch--large {\n width: 45px;\n height: 32px;\n}\n.yswitch--large .yswitch__thumb {\n width: 28px;\n height: 28px;\n transform: translateX(2px);\n}\n.yswitch--large.yswitch--checked .yswitch__thumb {\n transform: translateX(26px);\n}\n\n.yswitch__label {\n margin-left: 8px;\n font-size: 12px;\n color: #4b5563;\n white-space: nowrap;\n}\n\n.yswitch__spinner {\n width: 12px;\n height: 12px;\n border: 2px solid rgba(0,0,0,0.15);\n border-top-color: rgba(0,0,0,0.45);\n border-radius: 50%;\n animation: yswitch-spin 0.8s linear infinite;\n}\n\n@keyframes yswitch-spin {\n to { transform: rotate(360deg); }\n}\n\n/* 暗色主题适配 */\n@media (prefers-color-scheme: dark) {\n .yswitch__label { color: #cbd5e1; }\n}\n\n</style>\n\n\n","<template>\n <div \n ref=\"containerRef\"\n class=\"yimage-container\"\n :class=\"containerClass\"\n >\n <!-- 懒加载占位符 -->\n <div \n v-if=\"!isLoaded && !hasError && !isInView\"\n class=\"yimage-placeholder\"\n :style=\"radiusStyle\"\n >\n <div class=\"yimage-placeholder-content\">\n <svg class=\"yimage-placeholder-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"></path>\n </svg>\n </div>\n </div>\n\n <!-- 加载动画 -->\n <div \n v-if=\"isLoading && !hasError\"\n class=\"yimage-loading\"\n :style=\"radiusStyle\"\n >\n <div class=\"yimage-loading-content\">\n <div class=\"yimage-spinner\"></div>\n </div>\n </div>\n\n <!-- 错误占位图 -->\n <div \n v-if=\"hasError\"\n class=\"yimage-error\"\n :style=\"radiusStyle\"\n @click=\"handleErrorClick\"\n >\n <img \n src=\"https://img.nihaojewelry.com/media/2025/6/27/1938511770352222208.png\" \n alt=\"Error Image\" \n class=\"yimage-error-image\"\n :style=\"radiusStyle\"\n />\n </div>\n\n <!-- 实际图片 -->\n <img\n v-show=\"isLoaded && !hasError\"\n ref=\"imageRef\"\n :src=\"imgSrc\"\n :alt=\"alt\"\n :class=\"imageClass\"\n @load=\"handleLoad\"\n @error=\"handleError\"\n @click.stop=\"handlePreview\"\n :style=\"imageStyle\"\n />\n \n <!-- 点击区域覆盖层,确保即使图片未完全加载也能点击 -->\n <div\n v-if=\"props.preview && (!isLoaded || isLoading || hasError || !isInView)\"\n class=\"yimage-preview-trigger\"\n @click.stop=\"handlePreview\"\n ></div>\n\n <!-- 大图预览遮罩 -->\n <Teleport to=\"body\" v-if=\"isMounted\">\n <transition name=\"fade\">\n <div \n v-if=\"showPreview\"\n class=\"yimage-preview-mask\"\n @click.self=\"closePreview\"\n @wheel.prevent=\"handleWheel\"\n >\n <div class=\"yimage-preview-content\" \n :class=\"{'is-active': showPreview}\">\n <!-- 预览图片 -->\n <img\n ref=\"previewImageRef\"\n :src=\"resolvedPreviewSrc\"\n :alt=\"alt\"\n class=\"yimage-preview-image\"\n :style=\"{ transform: `scale(${zoomLevel})` }\"\n @click.stop\n />\n </div>\n \n <!-- 图片信息 - 右下角,完整展示链接 -->\n <!-- <div class=\"fixed bottom-4 right-4 bg-black/50 text-white p-3 rounded max-w-md\">\n <p class=\"text-sm\">{{ alt || '图片预览' }}</p>\n <p class=\"text-xs text-gray-300 mt-1 break-all\">{{ previewSrc || props.src }}</p>\n <p class=\"text-xs text-gray-300 mt-1\">缩放: {{ Math.round(zoomLevel * 100) }}%</p>\n </div> -->\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'\nimport { Teleport } from 'vue'\nimport type { CSSProperties } from 'vue'\n\ninterface Props {\n src: string\n alt?: string\n width?: string | number\n height?: string | number\n lazy?: boolean\n preview?: boolean\n fit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\n radius?: string | number\n className?: string\n previewSrcList?: string | string[]\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n alt: '',\n lazy: true,\n preview: true,\n fit: 'cover',\n radius: '0',\n className: ''\n})\n\nconst emit = defineEmits<{\n load: [event: Event]\n error: [event: Event]\n preview: [src: string]\n}>()\n\n// 响应式状态\nconst containerRef = ref<HTMLElement>()\nconst imageRef = ref<HTMLImageElement>()\nconst previewImageRef = ref<HTMLImageElement>()\nconst isLoaded = ref(false)\nconst isLoading = ref(false)\nconst hasError = ref(false)\nconst isInView = ref(false)\nconst showPreview = ref(false)\nconst imgSrc = ref('data:image/svg+xml;charset=utf-8;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgdmlld0JveD0iMCAwIDIwMCAyMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPCEtLSDog4zmma8gLS0+CiAgPHJlY3Qgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiIGZpbGw9IiNGM0Y0RjYiLz4KICAKICA8IS0tIOWbvueJh+WbvuaghyAtLT4KICA8cmVjdCB4PSI1MCIgeT0iNDAiIHdpZHRoPSIxMDAiIGhlaWdodD0iODAiIHJ4PSI0IiBmaWxsPSIjRDFENURCIiBzdHJva2U9IiM5Q0EzQUYiIHN0cm9rZS13aWR0aD0iMiIvPgogIAogIDwhLS0g5Zu+54mH5YaF6YOo6KOF6aWwIC0tPgogIDxjaXJjbGUgY3g9IjgwIiBjeT0iNzAiIHI9IjgiIGZpbGw9IiM5Q0EzQUYiLz4KICA8cGF0aCBkPSJNNjAgMTAwIEw5MCA4NSBMMTIwIDk1IEwxNDAgODAiIHN0cm9rZT0iIzlDQTNBRiIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KICAKICA8IS0tIOaWh+WtlyAtLT4KICA8dGV4dCB4PSIxMDAiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZCNzI4MCIgZm9udC1mYW1pbHk9IkFyaWFsLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEyIiBmb250LXdlaWdodD0iNTAwIj4KICAgIEltYWdlIG5vdCBhdmFpbGFibGUKICA8L3RleHQ+Cjwvc3ZnPiA=')\nconst previewSrc = ref('')\nconst zoomLevel = ref(1)\nconst isMounted = ref(false)\n\n// 新增:保存原始滚动条状态\nconst originalBodyStyle = ref<{\n overflow: string\n paddingRight: string\n}>({\n overflow: '',\n paddingRight: ''\n})\n\n// 计算属性\nconst RADIUS_TOKEN_MAP: Record<string, string> = {\n none: '0px',\n sm: '0.125rem',\n md: '0.375rem',\n lg: '0.5rem',\n xl: '0.75rem',\n '2xl': '1rem',\n full: '9999px'\n}\n\nconst containerClass = computed(() => props.className || '')\n\nconst radiusValue = computed(() => {\n if (typeof props.radius === 'number') {\n return `${props.radius}px`\n }\n if (typeof props.radius === 'string') {\n if (/(px|%|rem|em)$/.test(props.radius)) {\n return props.radius\n }\n if (RADIUS_TOKEN_MAP[props.radius]) {\n return RADIUS_TOKEN_MAP[props.radius]\n }\n }\n return ''\n})\n\nconst radiusStyle = computed<CSSProperties>(() => {\n if (!radiusValue.value) {\n return {}\n }\n return {\n borderRadius: radiusValue.value\n }\n})\n\nconst imageClass = computed(() => {\n return [\n 'yimage-image',\n props.preview ? 'is-previewable' : ''\n ].filter(Boolean).join(' ')\n})\n\nconst imageStyle = computed(() => {\n const style: CSSProperties = {\n objectFit: props.fit || 'cover',\n backgroundColor: '#fff'\n }\n \n if (props.width) {\n style.width = typeof props.width === 'number' ? `${props.width}px` : props.width\n }\n \n if (props.height) {\n style.height = typeof props.height === 'number' ? `${props.height}px` : props.height\n }\n \n if (radiusValue.value) {\n style.borderRadius = radiusValue.value\n }\n \n return style\n})\n\nconst resolvedPreviewSrc = computed(() => {\n if (previewSrc.value) {\n return previewSrc.value\n }\n if (Array.isArray(props.previewSrcList)) {\n return props.previewSrcList.find(Boolean) || props.src\n }\n return props.previewSrcList || props.src\n})\n\n// 工具函数\n// 新增:获取滚动条宽度\nconst getScrollbarWidth = () => {\n const scrollDiv = document.createElement('div')\n scrollDiv.style.cssText = 'width: 100px; height: 100px; overflow: scroll; position: absolute; top: -9999px;'\n document.body.appendChild(scrollDiv)\n const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth\n document.body.removeChild(scrollDiv)\n return scrollbarWidth\n}\n\n// 新增:锁定页面滚动\nconst lockBodyScroll = () => {\n // 保存原始样式\n originalBodyStyle.value = {\n overflow: document.body.style.overflow || '',\n paddingRight: document.body.style.paddingRight || ''\n }\n \n // 检查是否有滚动条\n const hasScrollbar = document.body.scrollHeight > window.innerHeight\n \n if (hasScrollbar) {\n const scrollbarWidth = getScrollbarWidth()\n // 设置右边距来防止页面跳动\n document.body.style.paddingRight = `${scrollbarWidth}px`\n }\n \n // 隐藏滚动条\n document.body.style.overflow = 'hidden'\n}\n\n// 新增:解锁页面滚动\nconst unlockBodyScroll = () => {\n // 恢复原始样式\n document.body.style.overflow = originalBodyStyle.value.overflow\n document.body.style.paddingRight = originalBodyStyle.value.paddingRight\n}\n\n// 懒加载逻辑\nlet observer: IntersectionObserver | null = null\n\nconst setupIntersectionObserver = () => {\n if (!props.lazy || !containerRef.value) return\n \n observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n isInView.value = true\n imgSrc.value = props.src\n observer?.unobserve(entry.target)\n }\n })\n },\n {\n rootMargin: '50px'\n }\n )\n \n observer.observe(containerRef.value)\n}\n\n// 事件处理\nconst handleLoad = (event: Event) => {\n isLoaded.value = true\n isLoading.value = false\n hasError.value = false\n emit('load', event)\n}\n\nconst handleError = (event: Event) => {\n hasError.value = true\n isLoading.value = false\n isLoaded.value = false\n emit('error', event)\n}\n\nconst retryLoad = () => {\n hasError.value = false\n isLoading.value = true\n isLoaded.value = false\n \n nextTick(() => {\n if (imageRef.value) {\n imageRef.value.src = props.src\n }\n })\n}\n\nconst getPreviewUrl = () => {\n if (Array.isArray(props.previewSrcList)) {\n return props.previewSrcList.find(Boolean) || props.src\n }\n return props.previewSrcList || props.src\n}\n\nconst handleErrorClick = () => {\n // 如果有预览源,即使加载失败也允许预览\n if (props.preview && (props.previewSrcList || props.src)) {\n handlePreview()\n } else {\n retryLoad()\n }\n}\n\nconst handlePreview = () => {\n if (!props.preview) return\n \n // 重置缩放级别\n zoomLevel.value = 1;\n \n // 使用预览源或原始源\n const previewUrl = getPreviewUrl();\n\n // 如果图片已经在当前 img 元素中加载完成,直接显示预览\n if (imageRef.value && imageRef.value.complete && imageRef.value.naturalWidth > 0) {\n previewSrc.value = previewUrl;\n nextTick(() => {\n showPreview.value = true;\n lockBodyScroll();\n emit('preview', previewUrl);\n });\n return;\n }\n \n // 预加载图片以避免闪烁\n const img = new Image();\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let isHandled = false;\n \n const showPreviewModal = () => {\n if (isHandled) return;\n isHandled = true;\n \n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n \n previewSrc.value = previewUrl;\n nextTick(() => {\n showPreview.value = true;\n lockBodyScroll();\n emit('preview', previewUrl);\n });\n };\n \n // 设置超时,防止预加载卡住\n timeoutId = setTimeout(() => {\n showPreviewModal();\n }, 500);\n \n img.onload = () => {\n showPreviewModal();\n };\n \n img.onerror = () => {\n // 如果预加载失败,仍然尝试显示\n showPreviewModal();\n };\n \n // 如果图片已经在缓存中,complete 会立即为 true\n img.src = previewUrl;\n \n // 检查图片是否已经在缓存中\n if (img.complete) {\n showPreviewModal();\n }\n}\n\nconst closePreview = () => {\n showPreview.value = false;\n \n // 等待过渡动画完成后恢复滚动\n setTimeout(() => {\n unlockBodyScroll();\n }, 300); // 与CSS过渡时间一致\n}\n\nconst handleWheel = (event: WheelEvent) => {\n // 确定缩放方向 (向上滚动放大,向下滚动缩小)\n const zoomDirection = event.deltaY < 0 ? 1 : -1;\n \n // 计算新的缩放级别 (每次缩放10%)\n const zoomStep = 0.1;\n let newZoom = zoomLevel.value + (zoomDirection * zoomStep);\n \n // 限制缩放范围在50%到200%之间\n newZoom = Math.max(0.5, Math.min(2.0, newZoom));\n \n // 更新缩放级别\n zoomLevel.value = newZoom;\n}\n\n// 生命周期\nonMounted(() => {\n if (!props.lazy) {\n isInView.value = true\n } else {\n setupIntersectionObserver()\n }\n \n if (isInView.value) {\n isLoading.value = true\n }\n\n // 设置客户端渲染标志\n isMounted.value = true\n})\n\nonUnmounted(() => {\n if (observer) {\n observer.disconnect()\n }\n \n // 确保组件销毁时恢复滚动状态\n if (showPreview.value) {\n unlockBodyScroll()\n }\n})\n\n// 监听src变化\nconst watchSrc = () => {\n if (props.src && isInView.value) {\n isLoading.value = true\n hasError.value = false\n isLoaded.value = false\n }\n}\n\nwatch(() => imgSrc.value, watchSrc)\nwatch(() => props.src, (nv) => {\n imgSrc.value = nv || ''\n})\n// 暴露方法\ndefineExpose({\n retryLoad,\n closePreview\n})\n</script>\n\n<style scoped>\n.yimage-container {\n position: relative;\n display: inline-block;\n overflow: hidden;\n}\n\n.yimage-placeholder,\n.yimage-loading,\n.yimage-error {\n width: 100%;\n height: 100%;\n}\n\n.yimage-placeholder {\n background-color: #e5e7eb;\n animation: yimage-pulse 2s ease-in-out infinite;\n}\n\n.yimage-placeholder-content {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n\n.yimage-placeholder-icon {\n width: 24px;\n height: 24px;\n color: #9ca3af;\n}\n\n.yimage-loading {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(249, 250, 251, 0.9);\n pointer-events: none;\n}\n\n.yimage-loading-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n}\n\n.yimage-spinner {\n width: 32px;\n height: 32px;\n border: 4px solid rgba(26, 26, 26, 0.2);\n border-top-color: #1A1A1A;\n border-radius: 999px;\n animation: yimage-spin 1s linear infinite;\n}\n\n.yimage-error {\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: #f3f4f6;\n cursor: pointer;\n}\n\n.yimage-error-image {\n width: 70%;\n height: 70%;\n object-fit: contain;\n cursor: pointer;\n}\n\n.yimage-image {\n width: 100%;\n height: 100%;\n display: block;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.yimage-image.is-previewable {\n cursor: pointer;\n}\n\n.yimage-image.is-previewable:hover {\n opacity: 0.9;\n}\n\n.yimage-preview-trigger {\n position: absolute;\n inset: 0;\n cursor: pointer;\n z-index: 10;\n}\n\n.yimage-preview-mask {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.75);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 99999;\n}\n\n.yimage-preview-content {\n position: relative;\n max-width: 64rem;\n max-height: 100%;\n padding: 1rem;\n transform: scale(0.95);\n transition: transform 0.3s ease;\n}\n\n.yimage-preview-content.is-active {\n transform: scale(1);\n}\n\n.yimage-preview-image {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n border-radius: 0.5rem;\n box-shadow: 0 20px 45px rgba(0, 0, 0, 0.35);\n transition: transform 0.2s ease;\n}\n\n/* 过渡动画 */\n.fade-enter-active,\n.fade-leave-active {\n transition: opacity 0.3s ease;\n}\n\n.fade-enter-from,\n.fade-leave-to {\n opacity: 0;\n}\n\n/* 基础图片设置 */\nimg {\n display: block;\n -webkit-user-drag: none;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n -ms-user-select: none;\n}\n\n@keyframes yimage-pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n\n@keyframes yimage-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n</style> ","<template>\n <div class=\"y-dropdown\" ref=\"dropdownRef\">\n <!-- 触发器 -->\n <div \n class=\"y-dropdown__trigger\" \n @mouseenter=\"showDropdown\"\n @mouseleave=\"hideDropdown\"\n >\n <slot name=\"trigger\">\n <button class=\"y-dropdown__button\">\n 下拉菜单\n </button>\n </slot>\n </div>\n\n <!-- 下拉菜单 -->\n <transition name=\"dropdown-fade\" appear>\n <div \n v-show=\"visible\"\n class=\"y-dropdown__menu\"\n :class=\"menuClass\"\n :style=\"menuStyle\"\n @mouseenter=\"showDropdown\"\n @mouseleave=\"hideDropdown\"\n >\n <slot>\n <div class=\"y-dropdown__item\">选项 1</div>\n <div class=\"y-dropdown__item\">选项 2</div>\n <div class=\"y-dropdown__item\">选项 3</div>\n </slot>\n </div>\n </transition>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'\n\ninterface Props {\n trigger?: 'hover' | 'click'\n placement?: 'bottom' | 'top' | 'left' | 'right'\n disabled?: boolean\n menuWidth?: number | string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n trigger: 'hover',\n placement: 'bottom',\n disabled: false,\n menuWidth: undefined\n})\n\nconst visible = ref(false)\nconst dropdownRef = ref<HTMLElement>()\nlet hideTimer: number | null = null\n\n// 计算菜单类名\nconst menuClass = computed(() => {\n return `y-dropdown__menu--${props.placement}`\n})\n\nconst menuStyle = computed(() => {\n if (!props.menuWidth) return {}\n const width =\n typeof props.menuWidth === 'number'\n ? `${props.menuWidth}px`\n : props.menuWidth\n return {\n width,\n minWidth: width,\n maxWidth: width\n }\n})\n\n// 显示下拉菜单\nconst showDropdown = () => {\n console.log('显示下拉菜单', visible.value)\n if (props.disabled) return\n \n // 清除隐藏定时器\n if (hideTimer) {\n clearTimeout(hideTimer)\n hideTimer = null\n }\n \n visible.value = true\n console.log('设置 visible 为 true', visible.value)\n \n // 立即计算位置,确保菜单在显示时就在正确位置\n nextTick(() => {\n updatePosition()\n })\n}\n\n// 隐藏下拉菜单\nconst hideDropdown = () => {\n console.log('隐藏下拉菜单')\n // 添加延迟,给用户时间移入菜单\n hideTimer = setTimeout(() => {\n visible.value = false\n console.log('设置 visible 为 false', visible.value)\n }, 150)\n}\n\n// 更新菜单位置\nconst updatePosition = () => {\n if (!dropdownRef.value) return\n \n const trigger = dropdownRef.value.querySelector('.y-dropdown__trigger') as HTMLElement\n const menu = dropdownRef.value.querySelector('.y-dropdown__menu') as HTMLElement\n \n if (!trigger || !menu) return\n \n // 获取触发器和菜单的尺寸信息\n const triggerRect = trigger.getBoundingClientRect()\n const menuRect = menu.getBoundingClientRect()\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n \n // 重置位置样式\n menu.style.top = ''\n menu.style.left = ''\n menu.style.right = ''\n menu.style.bottom = ''\n menu.style.transform = ''\n \n let top = 0\n let left = 0\n \n // 根据 placement 设置基本位置\n switch (props.placement) {\n case 'bottom':\n top = triggerRect.height + 4\n left = 0\n break\n \n case 'top':\n top = -(menuRect.height + 4)\n left = 0\n break\n \n case 'right':\n top = 0\n left = triggerRect.width + 4\n break\n \n case 'left':\n top = 0\n left = -(menuRect.width + 4)\n break\n }\n \n // 计算相对于视口的绝对位置\n let absoluteTop = triggerRect.top + top\n let absoluteLeft = triggerRect.left + left\n \n // 水平边界检测和调整\n if (props.placement === 'bottom' || props.placement === 'top') {\n const menuWidth = menuRect.width || 260 // 使用实际菜单宽度\n \n // 如果菜单会超出右边界,向左偏移保持10px边距\n if (absoluteLeft + menuWidth > viewportWidth - 10) {\n absoluteLeft = viewportWidth - menuWidth - 10\n }\n \n // 如果菜单会超出左边界,向右偏移保持10px边距\n if (absoluteLeft < 10) {\n absoluteLeft = 10\n }\n }\n \n // 垂直边界检测和调整\n if (props.placement === 'left' || props.placement === 'right') {\n const menuHeight = menuRect.height || 200 // 使用实际菜单高度\n \n // 如果菜单会超出下边界,向上偏移保持10px边距\n if (absoluteTop + menuHeight > viewportHeight - 10) {\n absoluteTop = viewportHeight - menuHeight - 10\n }\n \n // 如果菜单会超出上边界,向下偏移保持10px边距\n if (absoluteTop < 10) {\n absoluteTop = 10\n }\n }\n \n // 应用位置(使用固定定位的绝对坐标)\n menu.style.top = `${absoluteTop}px`\n menu.style.left = `${absoluteLeft}px`\n}\n\n// 点击外部关闭\nconst handleClickOutside = (event: MouseEvent) => {\n if (props.trigger === 'click' && dropdownRef.value && !dropdownRef.value.contains(event.target as Node)) {\n visible.value = false\n }\n}\n\n// 窗口大小变化时重新计算位置\nconst handleResize = () => {\n if (visible.value) {\n updatePosition()\n }\n}\n\nonMounted(() => {\n if (props.trigger === 'click') {\n document.addEventListener('click', handleClickOutside)\n }\n // 监听窗口大小变化\n window.addEventListener('resize', handleResize)\n // 监听滚动事件\n window.addEventListener('scroll', handleResize)\n})\n\nonUnmounted(() => {\n if (props.trigger === 'click') {\n document.removeEventListener('click', handleClickOutside)\n }\n // 清理定时器\n if (hideTimer) {\n clearTimeout(hideTimer)\n }\n // 清理事件监听器\n window.removeEventListener('resize', handleResize)\n window.removeEventListener('scroll', handleResize)\n})\n\nwatch(\n () => props.menuWidth,\n () => {\n if (visible.value) {\n nextTick(() => {\n updatePosition()\n })\n }\n }\n)\n</script>\n\n<style scoped lang=\"less\">\n.y-dropdown {\n position: relative;\n display: inline-block;\n\n &__trigger {\n cursor: pointer;\n }\n\n &__button {\n height: 44px;\n padding: 0 16px;\n border: 1px solid #e2e8f0;\n border-radius: 10px;\n background: #fff;\n color: #0b1a29;\n cursor: pointer;\n font-size: 14px;\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n\n &:hover {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59,130,246,0.15);\n }\n }\n\n &__menu {\n position: fixed;\n z-index: 9999;\n min-width: 100px;\n max-width: 300px;\n background: #fff;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n box-shadow: 0 8px 20px rgba(2,6,23,0.15);\n white-space: nowrap;\n\n &--bottom {\n top: calc(100% + 4px);\n left: 0;\n }\n\n &--top {\n bottom: calc(100% + 4px);\n left: 0;\n }\n\n &--left {\n top: 0;\n right: calc(100% + 4px);\n }\n\n &--right {\n top: 0;\n left: calc(100% + 4px);\n }\n }\n\n &__item {\n height: 36px;\n padding: 0 12px;\n color: #0b1a29;\n cursor: pointer;\n display: flex;\n align-items: center;\n font-size: 13px;\n transition: background-color 0.2s ease, color 0.2s ease;\n\n &:hover {\n background-color: #F6F6F7;\n color: #303061;\n }\n\n &:not(:last-child) {\n border-bottom: 1px solid #f1f5f9;\n }\n }\n}\n\n// 动画效果 - 只使用透明度变化,不改变位置\n.dropdown-fade-enter-active {\n transition: opacity 0.15s ease-out;\n}\n\n.dropdown-fade-leave-active {\n transition: opacity 0.1s ease-in;\n}\n\n.dropdown-fade-enter-from,\n.dropdown-fade-leave-to {\n opacity: 0;\n}\n\n.dropdown-fade-enter-to,\n.dropdown-fade-leave-from {\n opacity: 1;\n}\n\n// 暗色主题支持\n@media (prefers-color-scheme: dark) {\n .y-dropdown__button {\n background: rgba(2,6,23,0.4);\n border-color: rgba(148,163,184,0.18);\n color: #e5eef7;\n }\n \n .y-dropdown__menu {\n background: rgba(2,6,23,0.9);\n border-color: rgba(148,163,184,0.18);\n }\n \n .y-dropdown__item {\n color: #e5eef7;\n \n &:hover {\n background-color: #F6F6F7;\n color: #303061;\n }\n \n &:not(:last-child) {\n border-bottom-color: rgba(148,163,184,0.1);\n }\n }\n}\n</style>\n","<template>\r\n <teleport to=\"body\">\r\n <div\r\n v-show=\"visible\"\r\n class=\"y-drawer-root\"\r\n role=\"dialog\"\r\n :aria-modal=\"true\"\r\n :aria-hidden=\"!visible\"\r\n :style=\"{ zIndex: String(zIndex) }\"\r\n >\r\n <div\r\n class=\"y-drawer-mask\"\r\n @click=\"onMaskClick\"\r\n ></div>\r\n\r\n <transition :name=\"transitionName\">\r\n <div\r\n v-show=\"visible\"\r\n ref=\"panelRef\"\r\n class=\"y-drawer-panel\"\r\n :class=\"[\r\n `is-${placement}`,\r\n roundedClass,\r\n ]\"\r\n :style=\"panelStyle\"\r\n @keydown.esc.prevent.stop=\"onEsc\"\r\n tabindex=\"-1\"\r\n >\r\n <div v-if=\"showHeader\" class=\"y-drawer-header\">\r\n <div class=\"y-drawer-title\">{{ title }}</div>\r\n <button\r\n v-if=\"closable\"\r\n type=\"button\"\r\n class=\"y-drawer-close\"\r\n aria-label=\"Close\"\r\n @click=\"close\"\r\n >\r\n ✕\r\n </button>\r\n </div>\r\n\r\n <div class=\"y-drawer-body\">\r\n <slot />\r\n </div>\r\n\r\n <div v-if=\"$slots.footer\" class=\"y-drawer-footer\">\r\n <slot name=\"footer\" />\r\n </div>\r\n </div>\r\n </transition>\r\n </div>\r\n </teleport>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue'\r\n\r\nconst props = withDefaults(defineProps<{\r\n modelValue?: boolean\r\n placement?: 'right' | 'bottom'\r\n width?: string | number\r\n height?: string | number\r\n title?: string\r\n closable?: boolean\r\n maskClosable?: boolean\r\n zIndex?: number\r\n showHeader?: boolean\r\n}>(), {\r\n modelValue: false,\r\n placement: 'right',\r\n width: '420px',\r\n height: '60vh',\r\n title: '',\r\n closable: true,\r\n maskClosable: true,\r\n zIndex: 3000,\r\n showHeader: true,\r\n})\r\n\r\nconst emit = defineEmits<{\r\n (e: 'update:modelValue', value: boolean): void\r\n (e: 'open'): void\r\n (e: 'close'): void\r\n}>()\r\n\r\nconst visible = computed({\r\n get: () => props.modelValue,\r\n set: (v: boolean) => emit('update:modelValue', v),\r\n})\r\n\r\nconst panelRef = ref<HTMLElement | null>(null)\r\n\r\nconst transitionName = computed(() => props.placement === 'right' ? 'drawer-slide-right' : 'drawer-slide-bottom')\r\n\r\nconst roundedClass = computed(() => props.placement === 'right' ? 'rounded-left' : 'rounded-top')\r\n\r\nconst panelStyle = computed(() => {\r\n const style: Record<string, string> = {}\r\n if (props.placement === 'right') {\r\n style.width = typeof props.width === 'number' ? `${props.width}px` : String(props.width)\r\n style.height = '100%'\r\n style.right = '0'\r\n style.top = '0'\r\n } else {\r\n style.height = typeof props.height === 'number' ? `${props.height}px` : String(props.height)\r\n style.width = '100%'\r\n style.bottom = '0'\r\n style.left = '0'\r\n }\r\n return style\r\n})\r\n\r\nfunction onMaskClick() {\r\n if (!props.maskClosable) return\r\n close()\r\n}\r\n\r\nfunction close() {\r\n if (!visible.value) return\r\n visible.value = false\r\n emit('close')\r\n}\r\n\r\nfunction onEsc() {\r\n if (props.closable) close()\r\n}\r\n\r\nfunction onKeydown(e: KeyboardEvent) {\r\n if (e.key === 'Escape') onEsc()\r\n}\r\n\r\nwatch(() => props.modelValue, (v) => {\r\n if (v) {\r\n emit('open')\r\n // 聚焦,便于 Esc 关闭\r\n requestAnimationFrame(() => panelRef.value?.focus())\r\n document.addEventListener('keydown', onKeydown)\r\n document.body.style.overflow = 'hidden'\r\n } else {\r\n document.removeEventListener('keydown', onKeydown)\r\n document.body.style.overflow = ''\r\n }\r\n})\r\n\r\nonMounted(() => {\r\n if (props.modelValue) {\r\n document.addEventListener('keydown', onKeydown)\r\n document.body.style.overflow = 'hidden'\r\n }\r\n})\r\n\r\nonUnmounted(() => {\r\n document.removeEventListener('keydown', onKeydown)\r\n document.body.style.overflow = ''\r\n})\r\n</script>\r\n\r\n<style scoped>\r\n.y-drawer-root {\r\n position: fixed;\r\n inset: 0;\r\n}\r\n\r\n.y-drawer-mask {\r\n position: absolute;\r\n inset: 0;\r\n background: rgba(2, 6, 23, 0.55);\r\n backdrop-filter: blur(2px);\r\n}\r\n\r\n.y-drawer-panel {\r\n position: absolute;\r\n display: flex;\r\n flex-direction: column;\r\n background: #ffffff;\r\n border: 1px solid rgba(15, 23, 42, 0.06);\r\n box-shadow: 0 12px 40px rgba(2, 6, 23, 0.18);\r\n}\r\n\r\n/* 圆角根据拉出方向,仅对露出的边做圆角 */\r\n.rounded-left { border-radius: 12px 0 0 12px; }\r\n.rounded-top { border-radius: 12px 12px 0 0; }\r\n\r\n.y-drawer-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 14px 16px;\r\n border-bottom: 1px solid rgba(15, 23, 42, 0.06);\r\n}\r\n\r\n.y-drawer-title {\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #0b1a29;\r\n}\r\n\r\n.y-drawer-close {\r\n appearance: none;\r\n border: none;\r\n background: transparent;\r\n color: #334155;\r\n font-size: 16px;\r\n line-height: 1;\r\n cursor: pointer;\r\n padding: 6px;\r\n border-radius: 8px;\r\n}\r\n.y-drawer-close:hover { background: rgba(15,23,42,0.05); }\r\n\r\n.y-drawer-body {\r\n padding: 16px;\r\n overflow: auto;\r\n}\r\n\r\n.y-drawer-footer {\r\n padding: 12px 16px;\r\n border-top: 1px solid rgba(15, 23, 42, 0.06);\r\n}\r\n\r\n/* 进入/离场动画:右侧 */\r\n.drawer-slide-right-enter-from,\r\n.drawer-slide-right-leave-to { transform: translateX(100%); opacity: 0.98; }\r\n.drawer-slide-right-enter-active,\r\n.drawer-slide-right-leave-active { transition: transform 220ms ease, opacity 220ms ease; }\r\n.drawer-slide-right-enter-to,\r\n.drawer-slide-right-leave-from { transform: translateX(0%); opacity: 1; }\r\n\r\n/* 进入/离场动画:底部 */\r\n.drawer-slide-bottom-enter-from,\r\n.drawer-slide-bottom-leave-to { transform: translateY(100%); opacity: 0.98; }\r\n.drawer-slide-bottom-enter-active,\r\n.drawer-slide-bottom-leave-active { transition: transform 220ms ease, opacity 220ms ease; }\r\n.drawer-slide-bottom-enter-to,\r\n.drawer-slide-bottom-leave-from { transform: translateY(0%); opacity: 1; }\r\n\r\n/* 位置占位 */\r\n.y-drawer-panel.is-right { right: 0; top: 0; bottom: 0; }\r\n.y-drawer-panel.is-bottom { left: 0; right: 0; bottom: 0; }\r\n\r\n@media (prefers-color-scheme: dark) {\r\n .y-drawer-panel {\r\n background: rgba(15, 23, 42, 0.7);\r\n border-color: rgba(148, 163, 184, 0.12);\r\n box-shadow: 0 12px 40px rgba(2, 6, 23, 0.5);\r\n }\r\n .y-drawer-title { color: #e5eef7; }\r\n .y-drawer-close { color: #cbd5e1; }\r\n .y-drawer-close:hover { background: rgba(148,163,184,0.12); }\r\n}\r\n</style>\r\n\r\n\r\n","<template>\n <div\n class=\"ytree\"\n :class=\"[`ytree--${size}`, { 'ytree--disabled': disabled }]\"\n >\n <div class=\"ytree__container\">\n <div\n v-for=\"node in treeData\"\n :key=\"getNodeKey(node)\"\n class=\"ytree-node\"\n :class=\"{ 'ytree-node--current': isNodeCurrent(node), 'ytree-node--highlight': isNodeHighlighted(node) }\"\n >\n <div\n class=\"ytree-node__content\"\n :class=\"{ 'is-child-style': isChildStyleNode(node, node) }\"\n :style=\"{ paddingLeft: '8px' }\"\n :data-level=\"getNodeDepth(node, node)\"\n @click=\"handleNodeClick(node, node, null, node)\"\n @contextmenu=\"handleNodeContextMenu($event, node, node, null)\"\n >\n <!-- 展开/收起图标 -->\n <span\n v-if=\"hasChildren(node)\"\n class=\"ytree-node__expand-icon\"\n :class=\"{ 'is-expanded': isNodeExpanded(node) }\"\n @click.stop=\"handleExpandClick(node)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path\n d=\"M4.5 3L7.5 6L4.5 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n\n <span v-else class=\"w-[16px]\"></span>\n\n <!-- 复选框 -->\n <span\n v-if=\"showCheckbox\"\n class=\"ytree-node__checkbox\"\n :class=\"{\n 'is-checked': isNodeChecked(node),\n 'is-indeterminate': isNodeIndeterminate(node),\n }\"\n @click.stop=\"handleCheckClick(node)\"\n >\n <svg\n v-if=\"isNodeChecked(node)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L4.5 8.5L10 3\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <svg\n v-else-if=\"isNodeIndeterminate(node)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L10 6\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </span>\n\n <!-- 节点图标 -->\n <span\n v-if=\"iconClass\"\n class=\"ytree-node__icon\"\n :class=\"iconClass\"\n ></span>\n\n <!-- 节点头像/图标 -->\n <img\n class=\"ytree-node__avatar\"\n :src=\"getNodeIcon(node, node)\"\n :alt=\"isEmployeeNode(node) ? 'person' : 'dept'\"\n />\n\n <!-- 节点标签 -->\n <span\n class=\"ytree-node__label\"\n :class=\"{ 'is-employee': isEmployeeNode(node) }\"\n >\n {{ getNodeLabel(node) }}\n </span>\n\n <!-- 自定义节点内容插槽 -->\n <div class=\"ytree-node__custom-content\">\n <slot\n name=\"node-content\"\n :node=\"node\"\n :is-current=\"isNodeCurrent(node)\"\n :is-expanded=\"isNodeExpanded(node)\"\n :has-children=\"hasChildren(node)\"\n />\n </div>\n </div>\n\n <!-- 子节点 - 递归渲染 -->\n <transition name=\"ytree-node\">\n <div\n v-if=\"hasChildren(node) && isNodeExpanded(node)\"\n class=\"ytree-node__children\"\n >\n <div\n v-for=\"child in getNodeChildren(node)\"\n :key=\"getNodeKey(child)\"\n class=\"ytree-node\"\n :class=\"{ 'ytree-node--current': isNodeCurrent(child), 'ytree-node--highlight': isNodeHighlighted(child) }\"\n >\n <div\n class=\"ytree-node__content\"\n :class=\"{ 'is-child-style': isChildStyleNode(child, node) }\"\n :style=\"{ paddingLeft: `${6 + 14 + 2}px` }\"\n :data-level=\"getNodeDepth(node, child)\"\n @click=\"handleNodeClick(child, child, null, node)\"\n @contextmenu=\"handleNodeContextMenu($event, child, child, null)\"\n >\n <!-- 展开/收起图标 -->\n <span\n v-if=\"hasChildren(child)\"\n class=\"ytree-node__expand-icon\"\n :class=\"{ 'is-expanded': isNodeExpanded(child) }\"\n @click.stop=\"handleExpandClick(child)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path\n d=\"M4.5 3L7.5 6L4.5 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n <span v-else class=\"w-[16px]\"></span>\n\n <!-- 复选框 -->\n <span\n v-if=\"showCheckbox\"\n class=\"ytree-node__checkbox\"\n :class=\"{\n 'is-checked': isNodeChecked(child),\n 'is-indeterminate': isNodeIndeterminate(child),\n }\"\n @click.stop=\"handleCheckClick(child)\"\n >\n <svg\n v-if=\"isNodeChecked(child)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L4.5 8.5L10 3\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <svg\n v-else-if=\"isNodeIndeterminate(child)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L10 6\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </span>\n\n <!-- 节点图标 -->\n <span\n v-if=\"iconClass\"\n class=\"ytree-node__icon\"\n :class=\"iconClass\"\n ></span>\n\n <!-- 节点头像/图标 -->\n <img\n class=\"ytree-node__avatar\"\n :src=\"getNodeIcon(child, node)\"\n :alt=\"isEmployeeNode(child) ? 'person' : 'dept'\"\n />\n\n <!-- 节点标签 -->\n <span\n class=\"ytree-node__label\"\n :class=\"{ 'is-employee': isEmployeeNode(child) }\"\n >\n {{ getNodeLabel(child) }}\n </span>\n\n <!-- 自定义节点内容插槽 -->\n <div class=\"ytree-node__custom-content\">\n <slot\n name=\"node-content\"\n :node=\"child\"\n :is-current=\"isNodeCurrent(child)\"\n :is-expanded=\"isNodeExpanded(child)\"\n :has-children=\"hasChildren(child)\"\n />\n </div>\n </div>\n\n <!-- 第三级子节点 -->\n <transition name=\"ytree-node\">\n <div\n v-if=\"hasChildren(child) && isNodeExpanded(child)\"\n class=\"ytree-node__children\"\n >\n <div\n v-for=\"grandChild in getNodeChildren(child)\"\n :key=\"getNodeKey(grandChild)\"\n class=\"ytree-node\"\n :class=\"{\n 'ytree-node--current': isNodeCurrent(grandChild),\n 'ytree-node--highlight': isNodeHighlighted(grandChild),\n }\"\n >\n <div\n class=\"ytree-node__content\"\n :class=\"{ 'is-child-style': isChildStyleNode(grandChild, node) }\"\n :style=\"{ paddingLeft: `${6 + 14 + 2 + 14 + 2}px` }\"\n :data-level=\"getNodeDepth(node, grandChild)\"\n @click=\"handleNodeClick(grandChild, grandChild, null, node)\"\n @contextmenu=\"\n handleNodeContextMenu(\n $event,\n grandChild,\n grandChild,\n null\n )\n \"\n >\n <!-- 展开/收起图标 -->\n <span\n v-if=\"hasChildren(grandChild)\"\n class=\"ytree-node__expand-icon\"\n :class=\"{ 'is-expanded': isNodeExpanded(grandChild) }\"\n @click.stop=\"handleExpandClick(grandChild)\"\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M4.5 3L7.5 6L4.5 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n <span v-else class=\"w-[16px]\"></span>\n\n <!-- 复选框 -->\n <span\n v-if=\"showCheckbox\"\n class=\"ytree-node__checkbox\"\n :class=\"{\n 'is-checked': isNodeChecked(grandChild),\n 'is-indeterminate': isNodeIndeterminate(grandChild),\n }\"\n @click.stop=\"handleCheckClick(grandChild)\"\n >\n <svg\n v-if=\"isNodeChecked(grandChild)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L4.5 8.5L10 3\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <svg\n v-else-if=\"isNodeIndeterminate(grandChild)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L10 6\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </span>\n\n <!-- 节点图标 -->\n <span\n v-if=\"iconClass\"\n class=\"ytree-node__icon\"\n :class=\"iconClass\"\n ></span>\n\n <!-- 节点头像/图标 -->\n <img\n class=\"ytree-node__avatar\"\n :src=\"getNodeIcon(grandChild, node)\"\n :alt=\"isEmployeeNode(grandChild) ? 'person' : 'dept'\"\n />\n\n <!-- 节点标签 -->\n <span\n class=\"ytree-node__label\"\n :class=\"{ 'is-employee': isEmployeeNode(grandChild) }\"\n >\n {{ getNodeLabel(grandChild) }}\n </span>\n\n <!-- 自定义节点内容插槽 -->\n <div class=\"ytree-node__custom-content\">\n <slot\n name=\"node-content\"\n :node=\"grandChild\"\n :is-current=\"isNodeCurrent(grandChild)\"\n :is-expanded=\"isNodeExpanded(grandChild)\"\n :has-children=\"hasChildren(grandChild)\"\n />\n </div>\n </div>\n\n <!-- 第四级子节点 -->\n <transition name=\"ytree-node\">\n <div\n v-if=\"\n hasChildren(grandChild) && isNodeExpanded(grandChild)\n \"\n class=\"ytree-node__children\"\n >\n <div\n v-for=\"greatGrandChild in getNodeChildren(grandChild)\"\n :key=\"getNodeKey(greatGrandChild)\"\n class=\"ytree-node\"\n :class=\"{\n 'ytree-node--current':\n isNodeCurrent(greatGrandChild),\n 'ytree-node--highlight': isNodeHighlighted(greatGrandChild),\n }\"\n >\n <div\n class=\"ytree-node__content\"\n :class=\"{ 'is-child-style': isChildStyleNode(greatGrandChild, node) }\"\n :style=\"{\n paddingLeft: `${6 + 14 + 2 + 14 + 2 + 14 + 2}px`,\n }\"\n :data-level=\"getNodeDepth(node, greatGrandChild)\"\n @click=\"\n handleNodeClick(\n greatGrandChild,\n greatGrandChild,\n null,\n node\n )\n \"\n @contextmenu=\"\n handleNodeContextMenu(\n $event,\n greatGrandChild,\n greatGrandChild,\n null\n )\n \"\n >\n <!-- 展开/收起图标 -->\n <span\n v-if=\"hasChildren(greatGrandChild)\"\n class=\"ytree-node__expand-icon\"\n :class=\"{\n 'is-expanded': isNodeExpanded(greatGrandChild),\n }\"\n @click.stop=\"handleExpandClick(greatGrandChild)\"\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M4.5 3L7.5 6L4.5 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n <span v-else class=\"w-[16px]\"></span>\n\n <!-- 复选框 -->\n <span\n v-if=\"showCheckbox\"\n class=\"ytree-node__checkbox\"\n :class=\"{\n 'is-checked': isNodeChecked(greatGrandChild),\n 'is-indeterminate':\n isNodeIndeterminate(greatGrandChild),\n }\"\n @click.stop=\"handleCheckClick(greatGrandChild)\"\n >\n <svg\n v-if=\"isNodeChecked(greatGrandChild)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L4.5 8.5L10 3\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <svg\n v-else-if=\"isNodeIndeterminate(greatGrandChild)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L10 6\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </span>\n\n <!-- 节点图标 -->\n <span\n v-if=\"iconClass\"\n class=\"ytree-node__icon\"\n :class=\"iconClass\"\n ></span>\n\n <!-- 节点头像/图标 -->\n <img\n class=\"ytree-node__avatar\"\n :src=\"getNodeIcon(greatGrandChild, node)\"\n :alt=\"\n isEmployeeNode(greatGrandChild)\n ? 'person'\n : 'dept'\n \"\n />\n\n <!-- 节点标签 -->\n <span\n class=\"ytree-node__label\"\n :class=\"{\n 'is-employee': isEmployeeNode(greatGrandChild),\n }\"\n >\n {{ getNodeLabel(greatGrandChild) }}\n </span>\n\n <!-- 自定义节点内容插槽 -->\n <div class=\"ytree-node__custom-content\">\n <slot\n name=\"node-content\"\n :node=\"greatGrandChild\"\n :is-current=\"isNodeCurrent(greatGrandChild)\"\n :is-expanded=\"isNodeExpanded(greatGrandChild)\"\n :has-children=\"hasChildren(greatGrandChild)\"\n />\n </div>\n </div>\n\n <!-- 第五级子节点 -->\n <transition name=\"ytree-node\">\n <div\n v-if=\"\n hasChildren(greatGrandChild) &&\n isNodeExpanded(greatGrandChild)\n \"\n class=\"ytree-node__children\"\n >\n <div\n v-for=\"greatGreatGrandChild in getNodeChildren(\n greatGrandChild\n )\"\n :key=\"getNodeKey(greatGreatGrandChild)\"\n class=\"ytree-node\"\n :class=\"{\n 'ytree-node--current':\n isNodeCurrent(greatGreatGrandChild),\n }\"\n >\n <div\n class=\"ytree-node__content\"\n :class=\"{ 'is-child-style': isChildStyleNode(greatGreatGrandChild, node) }\"\n :style=\"{\n paddingLeft: `${\n 6 + 14 + 2 + 14 + 2 + 14 + 2 + 14 + 2\n }px`,\n }\"\n :data-level=\"\n getNodeDepth(node, greatGreatGrandChild)\n \"\n @click=\"\n handleNodeClick(\n greatGreatGrandChild,\n greatGreatGrandChild,\n null,\n node\n )\n \"\n @contextmenu=\"\n handleNodeContextMenu(\n $event,\n greatGreatGrandChild,\n greatGreatGrandChild,\n null\n )\n \"\n >\n <!-- 展开/收起图标 -->\n <span\n v-if=\"hasChildren(greatGreatGrandChild)\"\n class=\"ytree-node__expand-icon\"\n :class=\"{\n 'is-expanded':\n isNodeExpanded(greatGreatGrandChild),\n }\"\n @click.stop=\"\n handleExpandClick(greatGreatGrandChild)\n \"\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M4.5 3L7.5 6L4.5 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n <span v-else class=\"w-[16px]\"></span>\n\n <!-- 复选框 -->\n <span\n v-if=\"showCheckbox\"\n class=\"ytree-node__checkbox\"\n :class=\"{\n 'is-checked':\n isNodeChecked(greatGreatGrandChild),\n 'is-indeterminate':\n isNodeIndeterminate(\n greatGreatGrandChild\n ),\n }\"\n @click.stop=\"\n handleCheckClick(greatGreatGrandChild)\n \"\n >\n <svg\n v-if=\"isNodeChecked(greatGreatGrandChild)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L4.5 8.5L10 3\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <svg\n v-else-if=\"\n isNodeIndeterminate(\n greatGreatGrandChild\n )\n \"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L10 6\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </span>\n\n <!-- 节点图标 -->\n <span\n v-if=\"iconClass\"\n class=\"ytree-node__icon\"\n :class=\"iconClass\"\n ></span>\n\n <!-- 节点头像/图标 -->\n <img\n class=\"ytree-node__avatar\"\n :src=\"getNodeIcon(greatGreatGrandChild, node)\"\n :alt=\"\n isEmployeeNode(greatGreatGrandChild)\n ? 'person'\n : 'dept'\n \"\n />\n\n <!-- 节点标签 -->\n <span\n class=\"ytree-node__label\"\n :class=\"{\n 'is-employee':\n isEmployeeNode(greatGreatGrandChild),\n }\"\n >\n {{ getNodeLabel(greatGreatGrandChild) }}\n </span>\n\n <!-- 自定义节点内容插槽 -->\n <div class=\"ytree-node__custom-content\">\n <slot\n name=\"node-content\"\n :node=\"greatGreatGrandChild\"\n :is-current=\"\n isNodeCurrent(greatGreatGrandChild)\n \"\n :is-expanded=\"\n isNodeExpanded(greatGreatGrandChild)\n \"\n :has-children=\"\n hasChildren(greatGreatGrandChild)\n \"\n />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </div>\n </div>\n </transition>\n </div>\n </div>\n </transition>\n </div>\n </div>\n </transition>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, provide, watch } from \"vue\";\n// import YTreeNode from './ytree-node.vue'\n\n// 节点图标地址(部门/人员)\nconst DEPT_ICON_URL =\n \"https://image.nhdropshipping.com/fit-in/500x500/filters:format(webp)/media/2025/10/17/1979094146203385856/32.png\";\nconst PERSON_ICON_URL =\n \"https://image.nhdropshipping.com/fit-in/500x500/filters:format(webp)/media/2025/10/17/1979095296159907840/32.png\";\n\nexport interface TreeNode {\n id?: string | number;\n label: string;\n children?: TreeNode[];\n disabled?: boolean;\n isLeaf?: boolean;\n expanded?: boolean;\n checked?: boolean;\n indeterminate?: boolean;\n data?: any;\n [key: string]: any;\n}\n\nexport interface TreeProps {\n data?: TreeNode[];\n emptyText?: string;\n nodeKey?: string;\n props?: {\n children?: string;\n label?: string;\n disabled?: string;\n isLeaf?: string;\n };\n renderAfterExpand?: boolean;\n defaultExpandAll?: boolean;\n defaultExpandedKeys?: (string | number)[];\n defaultCheckedKeys?: (string | number)[];\n defaultSelectedKeys?: (string | number)[];\n checkStrictly?: boolean;\n checkOnClickNode?: boolean;\n checkDescendants?: boolean;\n autoExpandParent?: boolean;\n defaultChecked?: boolean;\n filterNodeMethod?: (value: any, data: TreeNode, node: any) => boolean;\n lazy?: boolean;\n load?: (node: TreeNode, resolve: (data: TreeNode[]) => void) => void;\n renderContent?: (h: any, node: TreeNode, data: any, store: any) => any;\n highlightCurrent?: boolean;\n expandOnClickNode?: boolean;\n currentNodeKey?: string | number;\n accordion?: boolean;\n indent?: number;\n iconClass?: string;\n showCheckbox?: boolean;\n draggable?: boolean;\n allowDrag?: (node: TreeNode) => boolean;\n allowDrop?: (\n draggingNode: TreeNode,\n dropNode: TreeNode,\n type: \"prev\" | \"inner\" | \"next\"\n ) => boolean;\n size?: \"small\" | \"medium\" | \"large\";\n disabled?: boolean;\n deptIconUrl?: string;\n personIconUrl?: string;\n buttonIconUrl?: string;\n // 是否启用第四级节点特殊处理(已废弃)\n enableFourthLevelSpecialHandling?: boolean;\n // 从第几级开始不进行任何\"默认/自动展开\"的级别阈值(如传 4 表示第4级及其以下不自动展开)\n restrictAutoExpandFromLevel?: number | undefined;\n // 子样式节点配置:定义第几级节点为子样式节点及其图标\n childStyleLevel?: number | undefined;\n childStyleIconUrl?: string;\n // 是否启用子样式节点自定义点击事件(如果启用,子样式节点点击会触发 child-node-click 事件而不是 node-click)\n enableChildStyleCustomClick?: boolean;\n}\n\nconst props = withDefaults(defineProps<TreeProps>(), {\n data: () => [],\n emptyText: \"暂无数据\",\n nodeKey: \"id\",\n props: () => ({\n children: \"children\",\n label: \"label\",\n disabled: \"disabled\",\n isLeaf: \"isLeaf\",\n }),\n renderAfterExpand: true,\n defaultExpandAll: false,\n defaultExpandedKeys: () => [],\n defaultCheckedKeys: () => [],\n defaultSelectedKeys: () => [],\n checkStrictly: false,\n checkOnClickNode: false,\n checkDescendants: true,\n autoExpandParent: true,\n defaultChecked: false,\n lazy: false,\n highlightCurrent: false,\n expandOnClickNode: true,\n accordion: false,\n indent: 18,\n iconClass: \"\",\n showCheckbox: false,\n draggable: false,\n size: \"medium\",\n disabled: false,\n deptIconUrl: \"\",\n personIconUrl: \"\",\n buttonIconUrl: \"\",\n enableFourthLevelSpecialHandling: false,\n restrictAutoExpandFromLevel: undefined,\n childStyleLevel: undefined,\n childStyleIconUrl: \"\",\n enableChildStyleCustomClick: false,\n});\n\nconst emit = defineEmits<{\n \"node-click\": [data: TreeNode, node: any, nodeComponent: any];\n \"node-contextmenu\": [\n event: Event,\n data: TreeNode,\n node: any,\n nodeComponent: any\n ];\n \"check-change\": [data: TreeNode, checked: boolean, indeterminate: boolean];\n check: [data: TreeNode, checked: any, indeterminate: any];\n \"current-change\": [data: TreeNode, node: any];\n \"node-expand\": [data: TreeNode, node: any, nodeComponent: any];\n \"node-collapse\": [data: TreeNode, node: any, nodeComponent: any];\n \"node-drag-start\": [node: TreeNode, event: DragEvent];\n \"node-drag-enter\": [\n draggingNode: TreeNode,\n dropNode: TreeNode,\n event: DragEvent\n ];\n \"node-drag-leave\": [\n draggingNode: TreeNode,\n dropNode: TreeNode,\n event: DragEvent\n ];\n \"node-drag-over\": [\n draggingNode: TreeNode,\n dropNode: TreeNode,\n event: DragEvent\n ];\n \"node-drag-end\": [\n draggingNode: TreeNode,\n dropNode: TreeNode,\n event: DragEvent\n ];\n \"node-drop\": [\n draggingNode: TreeNode,\n dropNode: TreeNode,\n dropType: \"before\" | \"after\" | \"inner\",\n event: DragEvent\n ];\n \"checked-keys-change\": [keys: Array<string | number>];\n \"child-node-click\": [data: TreeNode, node: any, nodeComponent: any];\n}>();\n\n// 计算属性\nconst treeData = computed(() => {\n console.log(\"ytree 组件接收到的数据:\", props.data);\n return props.data || [];\n});\n// const nodeProps = computed(() => props.props || {});\n\n// 提供全局状态\nconst store = ref({\n currentNode: null as TreeNode | null,\n currentKey: null as string | number | null,\n checkedKeys: new Set<string | number>(),\n expandedKeys: new Set<string | number>(),\n selectedKeys: new Set<string | number>(),\n highlightedKeys: new Set<string | number>(),\n});\n\nprovide(\"treeStore\", store);\n\n// 方法\nconst effectiveRestrictLevel = computed<number | undefined>(() => {\n // 仅以新属性为准(组件化配置)。传入有效正数才启用限制\n return props.restrictAutoExpandFromLevel && props.restrictAutoExpandFromLevel > 0\n ? props.restrictAutoExpandFromLevel\n : undefined;\n});\n\nfunction getNodeKey(node: TreeNode): string | number {\n return node[props.nodeKey] || node.id || Math.random();\n}\n\nfunction getNodeLabel(node: TreeNode): string {\n return (props.props?.label ? node[props.props.label] : undefined) || node.label || \"\";\n}\n\nfunction isEmployeeNode(node: any): boolean {\n return Boolean(node?.data?.isEmployee);\n}\n\nfunction getNodeIcon(node: any, rootNode?: TreeNode): string {\n const dept = props.deptIconUrl || DEPT_ICON_URL;\n const person = props.personIconUrl || PERSON_ICON_URL;\n const button = props.buttonIconUrl || \"\";\n const childStyleIcon = props.childStyleIconUrl || \"\";\n \n // 优先检查是否是子样式节点\n if (rootNode && childStyleIcon && isChildStyleNode(node, rootNode)) {\n return childStyleIcon;\n }\n \n // 兼容旧的按钮节点判断逻辑\n if (node?.data?.isButton && button) return button;\n \n return isEmployeeNode(node) ? person : dept;\n}\n\nfunction hasChildren(node: TreeNode): boolean {\n const children = (props.props?.children ? node[props.props.children] : undefined) || node.children;\n return children && children.length > 0;\n}\n\nfunction getNodeChildren(node: TreeNode): TreeNode[] {\n return (props.props?.children ? node[props.props.children] : undefined) || node.children || [];\n}\n\n// 计算节点在树中的深度\nfunction getNodeDepth(\n node: TreeNode,\n targetNode: TreeNode,\n currentDepth: number = 1\n): number {\n if (node === targetNode) {\n return currentDepth;\n }\n\n const children = getNodeChildren(node);\n for (const child of children) {\n const depth = getNodeDepth(child, targetNode, currentDepth + 1);\n if (depth > 0) {\n return depth;\n }\n }\n\n return 0;\n}\n\n// 判断节点是否是子样式节点\nfunction isChildStyleNode(node: TreeNode, rootNode: TreeNode): boolean {\n if (!props.childStyleLevel || props.childStyleLevel < 1) {\n return false;\n }\n const depth = getNodeDepth(rootNode, node);\n return depth === props.childStyleLevel;\n}\n\n// 检查节点是否为第四级节点(按钮权限)\n// function isFourthLevelNode(node: TreeNode): boolean {\n// return Boolean(node.data?.isButton);\n// }\n\nfunction isNodeExpanded(node: TreeNode): boolean {\n const nodeKey = getNodeKey(node);\n return store.value.expandedKeys.has(nodeKey);\n}\n\nfunction isNodeChecked(node: TreeNode): boolean {\n const nodeKey = getNodeKey(node);\n const directlyChecked = store.value.checkedKeys.has(nodeKey);\n\n // 如果直接选中,检查是否真的是全选状态\n if (directlyChecked) {\n if (hasChildren(node)) {\n const children = getNodeChildren(node);\n const checkedChildren = children.filter((child) => isNodeChecked(child));\n const indeterminateChildren = children.filter((child) =>\n isNodeIndeterminate(child)\n );\n\n // 只有当所有子节点都被选中且没有中间状态时,才显示为选中状态\n return (\n checkedChildren.length === children.length &&\n indeterminateChildren.length === 0\n );\n }\n return true;\n }\n\n // 如果有子节点且子节点全部选中,也返回true\n if (hasChildren(node)) {\n const children = getNodeChildren(node);\n // 检查是否有子节点处于中间状态\n const hasIndeterminateChild = children.some((child) =>\n isNodeIndeterminate(child)\n );\n if (hasIndeterminateChild) return false;\n\n return (\n children.length > 0 && children.every((child) => isNodeChecked(child))\n );\n }\n\n return false;\n}\n\nfunction isNodeIndeterminate(node: TreeNode): boolean {\n if (!hasChildren(node)) return false;\n\n const children = getNodeChildren(node);\n const checkedChildren = children.filter((child) => isNodeChecked(child));\n const indeterminateChildren = children.filter((child) =>\n isNodeIndeterminate(child)\n );\n\n // 如果子节点全部选中,则当前节点应该显示为选中状态(不是中间状态)\n if (checkedChildren.length === children.length) return false;\n\n // 如果子节点部分选中或有中间状态,则显示中间状态\n return checkedChildren.length > 0 || indeterminateChildren.length > 0;\n}\n\nfunction isNodeCurrent(node: TreeNode): boolean {\n const key = getNodeKey(node);\n return store.value.currentKey === key;\n}\n\nfunction isNodeHighlighted(node: TreeNode): boolean {\n const key = getNodeKey(node);\n return store.value.highlightedKeys.has(key);\n}\n\nfunction handleCheckClick(node: TreeNode) {\n // 如果组件被禁用,不允许勾选操作\n if (props.disabled) return;\n\n const nodeKey = getNodeKey(node);\n const isChecked = store.value.checkedKeys.has(nodeKey);\n const newCheckedState = !isChecked;\n\n // 保存当前的展开状态,避免被勾选操作影响\n const currentExpandedKeys = new Set(store.value.expandedKeys);\n\n // Update current node\n if (newCheckedState) {\n store.value.checkedKeys.add(nodeKey);\n } else {\n store.value.checkedKeys.delete(nodeKey);\n }\n\n // Cascade to children - 选中功能保持正常,但展开逻辑特殊处理\n function cascadeChildren(children: TreeNode[], check: boolean) {\n children.forEach((child) => {\n const childKey = getNodeKey(child);\n if (check) {\n store.value.checkedKeys.add(childKey);\n } else {\n store.value.checkedKeys.delete(childKey);\n }\n\n // 递归处理所有子节点,确保选中功能正常\n if (hasChildren(child)) {\n cascadeChildren(getNodeChildren(child), check);\n }\n });\n }\n\n // 正常递归选中所有子节点\n cascadeChildren(getNodeChildren(node), newCheckedState);\n\n // 特殊处理:如果选中了包含第四级子节点的节点,不自动展开第四级节点\n if (newCheckedState) {\n preventAutoExpandFourthLevel(node);\n }\n\n // Update all parent nodes recursively from bottom to top\n updateAllParentNodes();\n\n // 恢复展开状态,确保勾选操作不影响节点的展开收缩\n store.value.expandedKeys = currentExpandedKeys;\n\n // Emit change\n emit(\"check-change\", node, newCheckedState, false);\n emit(\"check\", node, newCheckedState, false);\n emit(\"checked-keys-change\", Array.from(store.value.checkedKeys));\n}\n\n// 防止自动展开第四级节点的函数\nfunction preventAutoExpandFourthLevel(_node: TreeNode) {\n // 兼容旧日志,统一到可配置级别\n if (effectiveRestrictLevel.value) {\n console.log(\n `已启用从第${effectiveRestrictLevel.value}级开始不默认展开的限制(不主动收起已展开节点)`\n );\n }\n}\n\n// 重写 handleExpandClick 函数,确保第四级节点只能手动展开\nfunction handleExpandClick(node: TreeNode) {\n const nodeKey = getNodeKey(node);\n const isExpanded = store.value.expandedKeys.has(nodeKey);\n\n if (isExpanded) {\n // 收起节点\n store.value.expandedKeys.delete(nodeKey);\n emit(\"node-collapse\", node, node, null);\n } else {\n // 展开节点 - 第四级节点只能手动展开\n store.value.expandedKeys.add(nodeKey);\n emit(\"node-expand\", node, node, null);\n }\n}\n\n// 递归更新所有父节点,从叶子节点向上更新\nfunction updateAllParentNodes() {\n // 收集所有节点\n const allNodes: TreeNode[] = [];\n\n function collectAllNodes(nodes: TreeNode[]) {\n nodes.forEach((node) => {\n allNodes.push(node);\n if (hasChildren(node)) {\n collectAllNodes(getNodeChildren(node));\n }\n });\n }\n\n collectAllNodes(treeData.value);\n\n // 从叶子节点开始,向上更新父节点状态\n function updateNodeParents(node: TreeNode) {\n if (hasChildren(node)) {\n const children = getNodeChildren(node);\n const nodeKey = getNodeKey(node);\n\n // 检查子节点状态\n const checkedChildren = children.filter((child) => isNodeChecked(child));\n const indeterminateChildren = children.filter((child) =>\n isNodeIndeterminate(child)\n );\n\n // 如果所有子节点都被选中且没有中间状态,添加父节点到checkedKeys\n if (\n checkedChildren.length === children.length &&\n indeterminateChildren.length === 0\n ) {\n store.value.checkedKeys.add(nodeKey);\n } else if (\n checkedChildren.length > 0 ||\n indeterminateChildren.length > 0\n ) {\n // 如果有子节点被选中或有中间状态,也添加父节点到checkedKeys(用于中间状态传值)\n store.value.checkedKeys.add(nodeKey);\n } else {\n // 否则从checkedKeys中移除父节点\n store.value.checkedKeys.delete(nodeKey);\n }\n }\n }\n\n // 从叶子节点开始更新(倒序遍历)\n for (let i = allNodes.length - 1; i >= 0; i--) {\n updateNodeParents(allNodes[i]);\n }\n}\n\nfunction handleNodeClick(data: TreeNode, node: any, nodeComponent: any, rootNode?: TreeNode) {\n if (props.disabled) return;\n \n // 判断是否是子样式节点\n const isChildStyle = rootNode ? isChildStyleNode(data, rootNode) : false;\n \n // 如果启用了子样式节点自定义点击事件且是子样式节点,触发 child-node-click 事件\n if (props.enableChildStyleCustomClick && isChildStyle) {\n emit(\"child-node-click\", data, node, nodeComponent);\n return;\n }\n // 需求:当 expandOnClickNode=true 且为父节点时,优先展开/收起且不触发事件\n if (props.expandOnClickNode && hasChildren(data)) {\n handleExpandClick(data);\n return;\n }\n\n store.value.currentNode = data;\n store.value.currentKey = getNodeKey(data);\n\n // 权限树可用性:若展示复选框,点击整行也进行勾选切换\n if (props.showCheckbox) {\n handleCheckClick(data);\n }\n\n // 有无监听器都 emit,Vue 会按需处理\n emit(\"node-click\", data, node, nodeComponent);\n}\n\nfunction handleNodeContextMenu(\n event: Event,\n data: TreeNode,\n node: any,\n nodeComponent: any\n) {\n if (props.disabled) return;\n emit(\"node-contextmenu\", event, data, node, nodeComponent);\n}\n\n// 初始化默认状态\nwatch(\n () => props.defaultExpandedKeys,\n (keys) => {\n if (keys) {\n const restrictLevel = effectiveRestrictLevel.value;\n if (restrictLevel) {\n // 允许外部传入默认展开 keys,但需过滤:从 restrictLevel 起不自动展开\n // 同时保留“已手动展开”的受限级别节点\n\n // 计算节点深度工具\n function getDepthByKey(targetKey: string | number, nodes: TreeNode[], level = 1): number {\n for (const n of nodes) {\n if (getNodeKey(n) === targetKey) return level;\n if (hasChildren(n)) {\n const d = getDepthByKey(targetKey, getNodeChildren(n), level + 1);\n if (d > 0) return d;\n }\n }\n return 0;\n }\n\n // 仅保留小于限制级别的默认展开 keys\n const filtered = (keys || []).filter((k) => {\n const depth = getDepthByKey(k as any, treeData.value, 1);\n return depth > 0 && depth < restrictLevel;\n });\n const newExpandedKeys = new Set(filtered);\n\n // 自动补齐:将第 1 至 restrictLevel-1 级的所有可展开节点加入(确保 3/4 层也会展开)\n function collectKeysToDepth(nodes: TreeNode[], level: number, maxDepth: number) {\n nodes.forEach((node) => {\n if (level < maxDepth && hasChildren(node)) {\n newExpandedKeys.add(getNodeKey(node));\n collectKeysToDepth(getNodeChildren(node), level + 1, maxDepth);\n } else if (level < maxDepth && !hasChildren(node)) {\n // 叶子节点无需加入,但继续一致的遍历结构\n } else if (level >= maxDepth) {\n // 达到限制深度,停止自动补齐\n }\n });\n }\n collectKeysToDepth(treeData.value, 1, restrictLevel);\n\n // 保留当前“已展开”的受限级别节点(通常由用户手动展开)\n store.value.expandedKeys.forEach((key) => {\n const depth = getDepthByKey(key, treeData.value, 1);\n if (depth >= restrictLevel) {\n newExpandedKeys.add(key);\n }\n });\n\n store.value.expandedKeys = newExpandedKeys;\n } else {\n store.value.expandedKeys = new Set(keys);\n }\n }\n },\n { immediate: true }\n);\n\n// 处理 defaultExpandAll\nfunction expandAllNodes() {\n if (props.defaultExpandAll) {\n // 收集所有有子节点的节点ID\n const allExpandableKeys = new Set<string | number>();\n\n const restrictLevel = effectiveRestrictLevel.value;\n\n function collectExpandableKeys(nodes: TreeNode[], level: number = 1) {\n nodes.forEach((node) => {\n if (!hasChildren(node)) return;\n\n const children = getNodeChildren(node);\n\n if (restrictLevel) {\n // 达到或超过限制级别,则不再自动展开\n if (level >= restrictLevel) return;\n\n // 若下一层就是限制级别,则当前父节点也不自动展开,但递归子节点以便后续逻辑使用\n const hasChildAtRestrictLevel = level + 1 === restrictLevel;\n if (!hasChildAtRestrictLevel) {\n allExpandableKeys.add(getNodeKey(node));\n }\n collectExpandableKeys(children, level + 1);\n } else {\n // 普通模式:所有有子节点的层级默认展开\n allExpandableKeys.add(getNodeKey(node));\n collectExpandableKeys(children, level + 1);\n }\n });\n }\n\n collectExpandableKeys(treeData.value, 1);\n\n store.value.expandedKeys = allExpandableKeys;\n }\n}\n\n// 展开包含选中权限的节点路径\nfunction expandNodesWithCheckedPermissions() {\n if (props.defaultCheckedKeys && props.defaultCheckedKeys.length > 0) {\n const checkedKeys = new Set(props.defaultCheckedKeys);\n const expandableKeys = new Set<string | number>();\n\n function findPathsToCheckedNodes(\n nodes: TreeNode[],\n parentPath: (string | number)[] = []\n ) {\n nodes.forEach((node) => {\n const nodeKey = getNodeKey(node);\n const currentPath = [...parentPath, nodeKey];\n\n // 如果当前节点被选中,展开到它的所有父节点\n if (checkedKeys.has(nodeKey)) {\n parentPath.forEach((key) => expandableKeys.add(key));\n }\n\n // 递归处理子节点\n if (hasChildren(node)) {\n findPathsToCheckedNodes(getNodeChildren(node), currentPath);\n }\n });\n }\n\n findPathsToCheckedNodes(treeData.value);\n\n const restrictLevel = effectiveRestrictLevel.value;\n if (restrictLevel) {\n // 启用限制:保持当前展开状态,不进行自动展开\n console.log(\n `已启用从第${restrictLevel}级开始不默认展开:保持当前展开状态不变`\n );\n return;\n }\n // 普通模式:自动展开到包含选中权限的路径\n store.value.expandedKeys = expandableKeys;\n }\n}\n\n// 根据key查找节点\n// function findNodeByKey(key: string | number): TreeNode | null {\n// function searchNodes(nodes: TreeNode[]): TreeNode | null {\n// for (const node of nodes) {\n// if (getNodeKey(node) === key) {\n// return node;\n// }\n// if (hasChildren(node)) {\n// const found = searchNodes(getNodeChildren(node));\n// if (found) return found;\n// }\n// }\n// return null;\n// }\n// return searchNodes(treeData.value);\n// }\n\nwatch(() => props.defaultExpandAll, expandAllNodes, { immediate: true });\n\n// 当树数据变化时,如果设置了 defaultExpandAll,重新展开所有节点\nwatch(() => treeData.value, expandAllNodes, { deep: true });\n\nwatch(\n () => props.defaultCheckedKeys,\n (keys) => {\n if (keys) {\n store.value.checkedKeys = new Set(keys);\n\n // 在权限树模式下,完全跳过自动展开逻辑,保持当前展开状态不变\n if (!props.enableFourthLevelSpecialHandling) {\n // 当选中权限变化时,展开包含这些权限的节点路径\n expandNodesWithCheckedPermissions();\n } else {\n console.log(\"权限树模式:跳过自动展开逻辑,保持当前展开状态\");\n }\n } else {\n store.value.checkedKeys.clear();\n }\n },\n { immediate: true }\n);\n\n// 根据传入的一组 id,展开到对应节点并高亮这些节点\nfunction highlightAndExpandByIds(ids: Array<string | number>) {\n try {\n const targetIds = Array.isArray(ids) ? ids : [];\n if (targetIds.length === 0) return;\n\n // 工具:查找到目标 key 的路径(返回 key 数组路径)\n function findPathToKey(\n nodes: TreeNode[],\n targetKey: string | number,\n path: (string | number)[] = []\n ): (string | number)[] | null {\n for (const n of nodes) {\n const nk = getNodeKey(n);\n const newPath = [...path, nk];\n if (nk === targetKey) return newPath;\n if (hasChildren(n)) {\n const p = findPathToKey(getNodeChildren(n), targetKey, newPath);\n if (p) return p;\n }\n }\n return null;\n }\n\n // 清除旧的高亮\n store.value.highlightedKeys.clear();\n\n // 累积需要展开的父级 key\n const keysToExpand = new Set<string | number>(store.value.expandedKeys);\n\n targetIds.forEach((targetId) => {\n const path = findPathToKey(treeData.value, targetId);\n if (path && path.length > 0) {\n // 父级全部加入展开集合(除最后一个自身)\n path.slice(0, -1).forEach((k) => keysToExpand.add(k));\n // 目标节点加入高亮集合\n store.value.highlightedKeys.add(path[path.length - 1]);\n }\n });\n\n // 应用展开\n store.value.expandedKeys = keysToExpand;\n } catch (e) {\n console.warn('highlightAndExpandByIds 执行失败', e);\n }\n}\n\n// 清除高亮\nfunction clearHighlights() {\n store.value.highlightedKeys.clear();\n}\n\n// 清除当前选中节点\nfunction clearCurrentNode() {\n store.value.currentNode = null;\n store.value.currentKey = null;\n}\n\ndefineExpose({ highlightAndExpandByIds, clearHighlights, clearCurrentNode });\n\nwatch(\n () => props.defaultSelectedKeys,\n (keys) => {\n if (keys) {\n store.value.selectedKeys = new Set(keys);\n }\n },\n { immediate: true }\n);\n</script>\n\n<style scoped>\n.ytree {\n position: relative;\n font-size: 14px;\n line-height: 1.5;\n color: #0b1a29;\n}\n\n.ytree--disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.ytree__container {\n position: relative;\n overflow: auto;\n}\n\n/* 尺寸变体 */\n.ytree--small {\n font-size: 12px;\n}\n\n.ytree--small .ytree__container {\n padding: 2px 0;\n}\n\n.ytree--medium {\n font-size: 13px;\n}\n\n.ytree--medium .ytree__container {\n padding: 4px 0;\n}\n\n.ytree--large {\n font-size: 14px;\n}\n\n.ytree--large .ytree__container {\n padding: 6px 0;\n}\n\n/* 树节点样式 */\n.ytree-node {\n position: relative;\n}\n\n.ytree-node__content {\n display: flex;\n align-items: center;\n height: 24px;\n padding: 0 6px;\n cursor: pointer;\n transition: background-color 0.2s ease, color 0.2s ease;\n border-radius: 4px;\n margin: 0.5px 0;\n}\n\n.ytree-node__content:hover:not(.ytree-node--disabled .ytree-node__content) {\n background-color: #f6f6f7;\n color: #303061;\n}\n\n.ytree-node--current > .ytree-node__content {\n background-color: #f0f0f0;\n font-weight: bold;\n}\n\n/* 高亮节点样式(仅文本变绿,无背景) */\n.ytree-node--highlight > .ytree-node__content .ytree-node__label {\n color: #10b981 !important;\n font-weight: 600;\n}\n\n.ytree-node--disabled .ytree-node__content {\n color: #9ca3af;\n cursor: not-allowed;\n}\n\n.ytree-node__expand-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n margin-right: 2px;\n color: #6b7280;\n transition: transform 0.2s ease, color 0.2s ease;\n cursor: pointer;\n border-radius: 2px;\n}\n\n.ytree-node__expand-icon:hover {\n color: #374151;\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n.ytree-node__expand-icon.is-expanded {\n transform: rotate(90deg);\n}\n\n.ytree-node__expand-icon--empty {\n width: 14px;\n height: 14px;\n margin-right: 4px;\n}\n\n.ytree-node__checkbox {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 10px;\n height: 10px;\n margin-right: 4px;\n border: 1px solid #d1d5db;\n border-radius: 2px;\n background: #ffffff;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n/* .ytree-node__checkbox:hover:not(.is-disabled) {\n border-color: #60a5fa;\n background-color: #f0f9ff;\n} */\n\n.ytree-node__checkbox.is-checked {\n background-color: #3f8682;\n color: #ffffff;\n}\n\n.ytree-node__checkbox.is-indeterminate {\n background-color: #3f8682;\n border-color: #3f8682;\n color: #ffffff;\n}\n\n.ytree-node__checkbox.is-disabled {\n background-color: #f9fafb;\n border-color: #e5e7eb;\n color: #9ca3af;\n cursor: not-allowed;\n}\n\n.ytree-node__icon {\n margin-right: 4px;\n font-size: 12px;\n color: #6b7280;\n}\n\n.ytree-node__label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 13px;\n line-height: 1.4;\n font-weight:500;\n}\n\n/* 子样式节点特殊样式 - 通过配置的级别动态应用 */\n.ytree-node__content.is-child-style .ytree-node__label {\n font-weight: 500 !important;\n color: #636363 !important;\n font-size: 12px !important;\n}\n\n/* 兼容旧的第四级节点样式(已废弃,保留以兼容旧代码) */\n.ytree--permission-tree .ytree-node__content[data-level=\"4\"] .ytree-node__label,\n.ytree--permission-tree .ytree-node[data-level=\"4\"] .ytree-node__label,\n.permission-tree .ytree-node__content[data-level=\"4\"] .ytree-node__label,\n.permission-tree .ytree-node[data-level=\"4\"] .ytree-node__label {\n font-weight: 500 !important;\n color: #636363 !important;\n font-size: 12px !important;\n}\n\n/* 员工节点颜色样式 */\n.ytree-node__label.is-employee {\n font-weight: 500;\n color: #777777;\n font-size: 12px;\n}\n\n/* 高亮覆盖(优先级更高,放在子样式规则之后) */\n.ytree-node.ytree-node--highlight > .ytree-node__content .ytree-node__label,\n.ytree-node.ytree-node--highlight > .ytree-node__content.is-child-style .ytree-node__label {\n color: #00a761 !important;\n font-weight: bold !important;\n}\n\n.ytree-node__custom-content {\n display: flex;\n align-items: center;\n margin-left: auto;\n flex-shrink: 0;\n}\n\n.ytree-node__avatar {\n width: 14px;\n height: 14px;\n margin-right: 4px;\n border-radius: 2px;\n object-fit: cover;\n}\n\n.ytree-node__label.is-current {\n font-weight: 500;\n}\n\n/* 暗色主题支持 */\n@media (prefers-color-scheme: dark) {\n .ytree {\n color: #e5eef7;\n }\n\n .ytree-node__content {\n color: #e5eef7;\n }\n\n .ytree-node__content:hover:not(.ytree-node--disabled .ytree-node__content) {\n background-color: rgba(2, 6, 23, 0.4);\n color: #e5eef7;\n }\n\n .ytree-node--current .ytree-node__content {\n background-color: rgba(59, 130, 246, 0.2);\n color: #60a5fa;\n }\n\n .ytree-node--disabled .ytree-node__content {\n color: #9ca3af;\n }\n\n .ytree-node__expand-icon {\n color: #9ca3af;\n }\n\n .ytree-node__expand-icon:hover {\n color: #cbd5e1;\n background-color: rgba(148, 163, 184, 0.1);\n }\n\n .ytree-node__checkbox {\n background: rgba(2, 6, 23, 0.4);\n border-color: rgba(148, 163, 184, 0.3);\n }\n\n .ytree-node__checkbox:hover:not(.is-disabled) {\n border-color: #60a5fa;\n background-color: rgba(59, 130, 246, 0.1);\n }\n\n .ytree-node__icon {\n color: #9ca3af;\n }\n\n /* 子样式节点暗色主题样式 */\n .ytree-node__content.is-child-style .ytree-node__label {\n color: #9ca3af !important;\n }\n\n /* 兼容旧的第四级节点暗色主题样式(已废弃,保留以兼容旧代码) */\n .ytree--permission-tree\n .ytree-node__content[data-level=\"4\"]\n .ytree-node__label,\n .ytree--permission-tree .ytree-node[data-level=\"4\"] .ytree-node__label,\n .permission-tree .ytree-node__content[data-level=\"4\"] .ytree-node__label,\n .permission-tree .ytree-node[data-level=\"4\"] .ytree-node__label {\n color: #9ca3af !important;\n }\n}\n</style>\n","<template>\n <div class=\"query-encapsulation\">\n <div class=\"query-encapsulation__container\">\n <div class=\"query-encapsulation__content\">\n <!-- 查询字段和操作按钮 -->\n <div class=\"query-encapsulation__fields\">\n <!-- 所有查询字段(带过渡动画,且不影响原有布局) -->\n <transition-group name=\"qf\" tag=\"div\" class=\"query-encapsulation__fields-group\">\n <div\n v-for=\"field in displayedFields\"\n :key=\"field.key\"\n class=\"query-encapsulation__field-item\"\n >\n <!-- 优先使用插槽自定义字段 -->\n <slot \n :name=\"`field-${field.key}`\" \n :field=\"field\" \n :value=\"searchForm[field.key]\"\n :update-value=\"(val: any) => updateFieldValue(field.key, val)\"\n >\n <!-- 默认渲染 -->\n <div class=\"query-encapsulation__field-wrapper\">\n <label v-if=\"Iflabel || field.type === 'switch'\" class=\"query-encapsulation__field-label\">{{ field.label }}</label>\n <component\n :is=\"getFieldComponent(field.type)\"\n v-model=\"searchForm[field.key]\"\n :placeholder=\"field.placeholder || `请输入${field.label}`\"\n :options=\"field.options\"\n :clearable=\"field.clearable !== false\"\n :size=\"field.size || 'small'\"\n :width=\"field.width || '180px'\"\n :format=\"field.format || 'timestamp'\"\n :include-time=\"field.includeTime || false\"\n :filterable=\"field.filterable === true\"\n :true-value=\"field.trueValue\"\n :false-value=\"field.falseValue\"\n :active-text=\"field.activeText\"\n :inactive-text=\"field.inactiveText\"\n :show-text=\"field.showText\"\n :active-color=\"field.activeColor || (field.type === 'switch' ? '#1B2433' : undefined)\"\n :inactive-color=\"field.inactiveColor\"\n v-on=\"getFieldListeners(field)\"\n @input=\"field.type !== 'switch' ? handleFieldChange(field) : undefined\"\n @change=\"field.type === 'switch' ? handleSwitchChange(field, $event) : handleFieldChange(field)\"\n />\n </div>\n </slot>\n </div>\n </transition-group>\n\n <!-- 展开/收起按钮 -->\n <div class=\"query-encapsulation__toggle\" v-if=\"hasHiddenFields\">\n <YButton variant=\"secondary\" size=\"small\" @click=\"toggleExpanded\">\n {{ isExpanded ? \"收起\" : \"展开\" }}\n <span\n class=\"query-encapsulation__toggle-icon\"\n :class=\"{ 'is-expanded': isExpanded }\"\n >▼</span\n >\n </YButton>\n </div>\n\n <!-- 操作按钮 -->\n <div class=\"query-encapsulation__actions\">\n <div class=\"query-encapsulation__actions-group\">\n <YButton\n variant=\"primary\"\n size=\"small\"\n @click=\"handleSearch\"\n :loading=\"loading\"\n >\n 搜索\n </YButton>\n <YButton\n variant=\"secondary\"\n size=\"small\"\n @click=\"handleReset\"\n :loading=\"loading\"\n >\n 重置\n </YButton>\n <slot name=\"extra-actions\"></slot>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n ref,\n reactive,\n computed,\n watch,\n onMounted,\n onBeforeUnmount,\n nextTick,\n} from \"vue\";\nimport YInput from \"./yinput.vue\";\nimport YSelect from \"./yselect.vue\";\nimport YButton from \"./ybutton.vue\";\nimport YTime from \"./ytime.vue\";\nimport YSwitch from \"./yswitch.vue\";\nimport type { SelectOption } from \"./yselect.vue\";\n\nexport interface QueryField {\n key: string;\n label: string;\n type: \"input\" | \"select\" | \"date\" | \"daterange\" | \"switch\";\n placeholder?: string;\n options?: SelectOption[];\n clearable?: boolean;\n size?: \"mini\" | \"small\" | \"medium\" | \"large\";\n width?: string;\n required?: boolean;\n hidden?: boolean; // 是否默认隐藏\n format?: \"timestamp\" | \"string\" | \"date\"; // 时间格式\n includeTime?: boolean; // 是否包含时间\n startKey?: string; // 开始时间的 key\n endKey?: string; // 结束时间的 key\n filterable?: boolean; // 可输入搜索(仅 select 支持)\n // switch 相关配置\n trueValue?: any; // switch 开启时的值\n falseValue?: any; // switch 关闭时的值\n activeText?: string; // switch 开启时的文本\n inactiveText?: string; // switch 关闭时的文本\n showText?: boolean; // switch 是否显示文本\n activeColor?: string; // switch 开启时的颜色\n inactiveColor?: string; // switch 关闭时的颜色\n onSwitchChange?: (value: any, field: QueryField) => void; // switch 切换时的自定义处理函数\n}\n\nexport interface QueryEncapsulationProps {\n Iflabel?: boolean;\n fields: QueryField[];\n maxVisibleFields?: number;\n loading?: boolean;\n modelValue?: Record<string, any>;\n}\n\nconst props = withDefaults(defineProps<QueryEncapsulationProps>(), {\n Iflabel: true,\n maxVisibleFields: 5,\n loading: false,\n modelValue: () => ({}),\n});\n\nconst emit = defineEmits<{\n \"update:modelValue\": [value: Record<string, any>];\n search: [payload: { data: Record<string, any>; raw: Record<string, any> }];\n reset: [];\n \"field-change\": [field: QueryField, value: any];\n}>();\n\n// 响应式数据\nconst isExpanded = ref(false);\nconst searchForm = reactive<Record<string, any>>({});\nconst autoTriggerTypes: QueryField[\"type\"][] = [\"select\", \"date\", \"daterange\", \"switch\"];\nlet autoSearchTimer: ReturnType<typeof setTimeout> | undefined;\n\n// 计算属性\nconst visibleFields = computed(() => {\n return props.fields.filter((field) => !field.hidden);\n});\n\n// 展示的字段(受展开/收起控制)\nconst displayedFields = computed(() => {\n if (isExpanded.value) return visibleFields.value;\n return visibleFields.value.slice(0, props.maxVisibleFields);\n});\n\n// const hiddenFields = computed(() => {\n// return visibleFields.value.slice(props.maxVisibleFields);\n// });\n\nconst hasHiddenFields = computed(() => {\n return visibleFields.value.length > props.maxVisibleFields;\n});\n\n// 方法\nfunction getFieldComponent(type: string) {\n switch (type) {\n case \"select\":\n return YSelect;\n case \"date\":\n case \"daterange\":\n return YTime;\n case \"switch\":\n return YSwitch;\n case \"input\":\n default:\n return YInput;\n }\n}\n\nfunction updateFieldValue(key: string, value: any) {\n searchForm[key] = value;\n const field = props.fields.find((f) => f.key === key);\n if (field) {\n handleFieldChange(field);\n }\n}\n\nfunction handleFieldChange(field: QueryField) {\n emit(\"field-change\", field, searchForm[field.key]);\n emit(\"update:modelValue\", { ...searchForm });\n if (autoTriggerTypes.includes(field.type)) {\n scheduleAutoSearch();\n }\n}\n\nfunction handleSwitchChange(field: QueryField, value: any) {\n // 如果配置了自定义处理函数,则调用它\n if (field.onSwitchChange && typeof field.onSwitchChange === 'function') {\n field.onSwitchChange(value, field);\n }\n // 仍然触发默认的字段变化处理(会自动触发搜索,因为 switch 已添加到 autoTriggerTypes)\n handleFieldChange(field);\n}\n\nfunction handleSearch() {\n // 过滤空值参数\n const searchParams = filterEmptyParams(searchForm);\n\n // 格式化参数(处理日期范围等特殊字段)\n const formattedParams = formatSearchParams(searchParams);\n\n const rawParams = { ...searchForm };\n\n // 将参数包裹在data对象中\n emit(\"search\", { data: formattedParams, raw: rawParams });\n}\n\nfunction handleReset() {\n // 重置所有字段\n Object.keys(searchForm).forEach((key) => {\n const field = props.fields.find((f) => f.key === key);\n if (field?.type === \"daterange\") {\n searchForm[key] = { startDate: null, endDate: null };\n } else if (field?.type === \"date\") {\n searchForm[key] = null;\n } else if (field?.type === \"switch\") {\n // switch 类型重置为 falseValue 或 false\n searchForm[key] = field.falseValue !== undefined ? field.falseValue : false;\n } else {\n searchForm[key] = \"\";\n }\n });\n emit(\"reset\");\n emit(\"update:modelValue\", { ...searchForm });\n}\n\nfunction toggleExpanded() {\n isExpanded.value = !isExpanded.value;\n}\n\nfunction getFieldListeners(field: QueryField) {\n // 只有 input 类型需要特殊的事件监听\n if (field.type !== \"input\") {\n return {};\n }\n return {\n enter: () => handleInputQuickSearch(),\n paste: () => handleInputQuickSearch(),\n };\n}\n\nasync function handleInputQuickSearch() {\n await nextTick();\n handleSearch();\n}\n\nfunction scheduleAutoSearch() {\n if (autoSearchTimer) {\n clearTimeout(autoSearchTimer);\n }\n autoSearchTimer = setTimeout(() => {\n autoSearchTimer = undefined;\n nextTick().then(() => handleSearch());\n }, 0);\n}\n\n// 过滤空值参数\nfunction filterEmptyParams(params: Record<string, any>) {\n const filtered: Record<string, any> = {};\n\n Object.keys(params).forEach((key) => {\n const field = props.fields.find((f) => f.key === key);\n const rawValue = params[key];\n const value =\n typeof rawValue === \"string\" ? rawValue.trim() : rawValue;\n\n if (value === null || value === undefined || value === \"\") {\n return;\n }\n\n if (\n typeof value === \"object\" &&\n value.startDate &&\n value.endDate\n ) {\n if (value.startDate && value.endDate) {\n filtered[key] = value;\n }\n return;\n }\n\n if (field && (field.type === \"date\" || field.type === \"daterange\")) {\n if (value !== 0) {\n filtered[key] = value;\n }\n return;\n }\n\n filtered[key] = value;\n });\n\n return filtered;\n}\n\n// 格式化搜索参数\nfunction formatSearchParams(params: Record<string, any>) {\n const formatted: Record<string, any> = {};\n\n Object.keys(params).forEach((key) => {\n const value = params[key];\n const field = props.fields.find((f) => f.key === key);\n\n if (field) {\n // 根据字段类型格式化参数\n if (field.type === \"daterange\" && typeof value === \"object\") {\n // 日期范围字段:使用自定义的 key 或默认 key\n const startKey = field.startKey || `${key}Start`;\n const endKey = field.endKey || `${key}End`;\n\n // 只有当开始和结束日期都存在且不为0时才添加\n if (value.startDate && value.endDate && value.startDate !== 0 && value.endDate !== 0) {\n if (field.format === \"timestamp\") {\n formatted[startKey] = new Date(value.startDate).getTime();\n formatted[endKey] = new Date(value.endDate).getTime();\n } else {\n formatted[startKey] = value.startDate;\n formatted[endKey] = value.endDate;\n }\n }\n } else if (field.type === \"date\" && value && value !== 0) {\n // 单个日期字段\n if (field.format === \"timestamp\") {\n formatted[key] = new Date(value).getTime();\n } else {\n formatted[key] = value;\n }\n } else {\n // 普通字段直接传递\n formatted[key] = value;\n }\n } else {\n // 没有找到字段定义,直接传递\n formatted[key] = value;\n }\n });\n\n return formatted;\n}\n\n// 初始化表单数据\nfunction initFormData() {\n props.fields.forEach((field) => {\n if (searchForm[field.key] === undefined) {\n // 根据字段类型设置默认值\n if (field.type === \"daterange\") {\n searchForm[field.key] = props.modelValue?.[field.key] || {\n startDate: null,\n endDate: null,\n };\n } else if (field.type === \"date\") {\n searchForm[field.key] = props.modelValue?.[field.key] || null;\n } else if (field.type === \"switch\") {\n // switch 类型使用 falseValue 或 false 作为默认值\n searchForm[field.key] = props.modelValue?.[field.key] !== undefined \n ? props.modelValue[field.key] \n : (field.falseValue !== undefined ? field.falseValue : false);\n } else {\n searchForm[field.key] = props.modelValue?.[field.key] || \"\";\n }\n }\n });\n}\n\n// 监听外部数据变化\nwatch(\n () => props.modelValue,\n (newValue) => {\n if (newValue) {\n Object.assign(searchForm, newValue);\n }\n },\n { deep: true, immediate: true }\n);\n\n// 生命周期\nonMounted(() => {\n initFormData();\n});\n\nonBeforeUnmount(() => {\n if (autoSearchTimer) {\n clearTimeout(autoSearchTimer);\n autoSearchTimer = undefined;\n }\n});\n</script>\n\n<style scoped>\n/* 主容器 */\n.query-encapsulation {\n width: 100%;\n}\n\n.query-encapsulation__container {\n background: #ffffff;\n border-radius: 10px;\n padding: 16px;\n margin-bottom: 8px;\n box-shadow: \n 0rem 0.3125rem 0.3125rem -0.15625rem rgba(0, 0, 0, 0.03),\n 0rem 0.1875rem 0.1875rem -0.09375rem rgba(0, 0, 0, 0.02),\n 0rem 0.125rem 0.125rem -0.0625rem rgba(0, 0, 0, 0.02),\n 0rem 0.0625rem 0.0625rem -0.03125rem rgba(0, 0, 0, 0.03),\n 0rem 0.03125rem 0.03125rem 0rem rgba(0, 0, 0, 0.04),\n 0rem 0rem 0rem 0.0625rem rgba(0, 0, 0, 0.06);\n}\n\n.query-encapsulation__content {\n width: 100%;\n}\n\n/* 查询字段容器 */\n.query-encapsulation__fields {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.query-encapsulation__fields:last-child {\n margin-bottom: 0;\n}\n\n/* 字段组容器 - 修复 transition-group 布局问题 */\n.query-encapsulation__fields-group {\n display: contents;\n}\n\n/* 单个字段项 */\n.query-encapsulation__field-item {\n display: flex;\n align-items: center;\n transition: all 0.3s ease;\n}\n\n.query-encapsulation__field-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* 字段标签 */\n.query-encapsulation__field-label {\n font-size: 13px;\n font-weight: 500;\n color: #374151;\n white-space: nowrap;\n min-width: fit-content;\n flex-shrink: 0;\n margin-right: 8px;\n}\n\n/* 展开/收起按钮 */\n.query-encapsulation__toggle {\n display: flex;\n align-items: center;\n margin-left: 0;\n}\n\n/* 展开/收起图标 */\n.query-encapsulation__toggle-icon {\n display: inline-block;\n margin-left: 4px;\n transition: transform 0.3s ease;\n font-size: 10px;\n}\n\n.query-encapsulation__toggle-icon.is-expanded {\n transform: rotate(180deg);\n}\n\n/* 操作按钮容器 */\n.query-encapsulation__actions {\n display: flex;\n align-items: center;\n}\n\n.query-encapsulation__actions-group {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n/* 查询字段进出场与移动动画 */\n.qf-enter-active,\n.qf-leave-active {\n transition: all 0.2s ease;\n}\n\n.qf-enter-from,\n.qf-leave-to {\n opacity: 0;\n transform: translateY(-6px);\n}\n\n.qf-move {\n transition: transform 0.2s ease;\n}\n\n/* 响应式设计 - 移动优先 */\n/* 超大屏幕(1024px 及以下) */\n@media (max-width: 1024px) {\n .query-encapsulation__fields {\n gap: 10px;\n }\n}\n\n/* 中等屏幕(768px 及以下) */\n@media (max-width: 768px) {\n .query-encapsulation__container {\n padding: 10px;\n }\n}\n\n/* 小屏幕(640px 及以下) */\n@media (max-width: 640px) {\n .query-encapsulation__container {\n padding: 10px;\n }\n \n .query-encapsulation__fields {\n gap: 8px;\n }\n}\n\n/* 兼容性处理:如果浏览器不支持 contents,使用 flex 布局 */\n@supports not (display: contents) {\n .query-encapsulation__fields-group {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 12px;\n }\n \n @media (max-width: 1024px) {\n .query-encapsulation__fields-group {\n gap: 10px;\n }\n }\n \n @media (max-width: 640px) {\n .query-encapsulation__fields-group {\n gap: 8px;\n }\n }\n}\n</style>\n","<template>\n <transition name=\"y-msg-fade\" @after-leave=\"onAfterLeave\">\n <div\n v-show=\"visible\"\n class=\"y-msg\"\n :class=\"[`y-msg--${type}`]\"\n :style=\"{ zIndex: zIndex }\"\n role=\"status\"\n aria-live=\"polite\"\n @mouseenter=\"handleMouseEnter\"\n @mouseleave=\"handleMouseLeave\"\n >\n <span class=\"y-msg__icon\" :class=\"`y-msg__icon--${type}`\" aria-hidden=\"true\">\n <svg v-if=\"type==='success'\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M20 6L9 17l-5-5\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <svg v-else-if=\"type==='warning'\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M12 9v4m0 4h.01M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <svg v-else width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M12 9v4m0 4h.01M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </span>\n <div class=\"y-msg__content\" v-text=\"message\"></div>\n <button v-if=\"closable\" class=\"y-msg__close\" type=\"button\" @click=\"close\">✕</button>\n </div>\n </transition>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted, onBeforeUnmount, ref } from 'vue'\n\nconst props = withDefaults(defineProps<{\n id: number\n type?: 'success' | 'warning' | 'error'\n message: string\n duration?: number\n offset: number\n zIndex: number\n closable?: boolean\n onClose?: (id: number) => void\n}>(), {\n type: 'success',\n duration: 3000,\n closable: false,\n})\n\nconst visible = ref(false)\nlet timer: number | undefined\nlet remainingTime: number = 0\nlet startTime: number = 0\n\nonMounted(() => {\n // 先隐藏,下一帧再显示以触发过渡\n requestAnimationFrame(() => {\n visible.value = true\n if (props.duration && props.duration > 0) {\n startTimer(props.duration)\n }\n })\n})\n\nonBeforeUnmount(() => { \n clearTimer()\n})\n\nfunction startTimer(duration: number) {\n remainingTime = duration\n startTime = Date.now()\n timer = window.setTimeout(() => close(), duration)\n}\n\nfunction clearTimer() {\n if (timer) {\n window.clearTimeout(timer)\n timer = undefined\n }\n}\n\nfunction handleMouseEnter() {\n if (timer && props.duration && props.duration > 0) {\n clearTimer()\n // 计算剩余时间\n const elapsed = Date.now() - startTime\n remainingTime = Math.max(0, remainingTime - elapsed)\n }\n}\n\nfunction handleMouseLeave() {\n if (props.duration && props.duration > 0 && remainingTime > 0) {\n // 使用剩余时间重新启动计时器\n startTimer(remainingTime)\n }\n}\n\nfunction close() {\n visible.value = false\n}\n\nfunction onAfterLeave() {\n props.onClose?.(props.id)\n}\n</script>\n\n<style scoped>\n.y-msg {\n position: fixed;\n left: 50%;\n top: 0;\n transform: translate(-50%, 0);\n min-width: 260px;\n max-width: 86vw;\n box-sizing: border-box;\n padding: 10px 14px;\n border-radius: 12px;\n background: #ffffff;\n color: #0b1a29;\n display: flex;\n align-items: center;\n gap: 10px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n border: 1px solid rgba(15, 23, 42, 0.08);\n border-left-width: 3px;\n will-change: opacity, transform;\n transition:\n transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1),\n opacity 200ms ease;\n}\n\n.y-msg__icon { \n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n border-radius: 6px;\n padding: 4px;\n box-sizing: border-box;\n}\n.y-msg__icon--success { \n background-color: #047B5D; \n color: #ffffff; \n}\n.y-msg__icon--warning { \n background-color: #FFB800; \n color: #ffffff; \n}\n.y-msg__icon--error { \n background-color: #C41E3A; \n color: #ffffff; \n}\n.y-msg__content { \n margin-top: 2px;\n white-space: pre-wrap; \n word-break: break-word; \n line-height: 1.4;\n display: flex;\n align-items: center;\n /* font-weight: bold; */\n}\n.y-msg__close {\n margin-left: 8px;\n height: 22px; width: 22px;\n border: none; border-radius: 6px; background: transparent; color: inherit; cursor: pointer;\n}\n.y-msg__close:hover { background: rgba(2,6,23,0.06); }\n\n/* 状态色 - 背景统一为白色,通过图标和边框区分 */\n.y-msg--success { \n background: #ffffff; \n color: #0b1a29;\n}\n.y-msg--warning { \n background: #ffffff; \n color: #0b1a29;\n}\n.y-msg--error { \n background: #ffffff; \n color: #0b1a29;\n}\n\n@media (prefers-color-scheme: dark) {\n .y-msg { \n background: #1f2937; \n color: #ffffff;\n border-color: rgba(148, 163, 184, 0.2);\n border-left-width: 3px;\n }\n .y-msg--success { \n background: #1f2937; \n color: #ffffff;\n border-left-color: #047B5D;\n }\n .y-msg--warning { \n background: #1f2937; \n color: #ffffff;\n border-left-color: #FFB800;\n }\n .y-msg--error { \n background: #1f2937; \n color: #ffffff;\n border-left-color: #C41E3A;\n }\n}\n\n/* 进入/离开动效(自然惯性:更慢进入,稍快离开) */\n.y-msg-fade-enter-from { opacity: 0; transform: translate(-50%, -18px) scale(0.972); }\n.y-msg-fade-enter-active { transition: opacity 360ms cubic-bezier(0.22, 1, 0.36, 1), transform 360ms cubic-bezier(0.22, 1, 0.36, 1); }\n.y-msg-fade-leave-active { transition: opacity 200ms cubic-bezier(0.4, 0, 0.2, 1), transform 220ms cubic-bezier(0.4, 0, 0.2, 1); }\n.y-msg-fade-leave-to { opacity: 0; transform: translate(-50%, -10px) scale(0.982); }\n\n/* 离场节点固定 top,不参与 top 过渡,仅做自身淡出/轻微位移,避免与重排叠加 */\n.y-msg.is-leaving { transition-property: opacity, transform; pointer-events: none; }\n\n@media (prefers-reduced-motion: reduce) {\n .y-msg, .y-msg-fade-enter-active, .y-msg-fade-leave-active { transition: none; }\n}\n</style>\n\n\n","import { createVNode, render } from 'vue'\nimport YMessageToast from './ymessageToast.vue'\n\nlet seed = 1\nconst GAP = 12\ntype InstanceItem = { id: number; el: HTMLElement; vm: any; height: number; leaving?: boolean }\nconst instances: Array<InstanceItem> = []\n\ntype YMessageType = 'success' | 'warning' | 'error'\n\ninterface MessageOptions {\n type?: YMessageType\n message: string\n duration?: number\n closable?: boolean\n}\n\nfunction calcOffset(): number {\n let offset = 20\n instances.forEach(inst => { offset += inst.height + GAP })\n return offset\n}\n\nfunction close(id: number) {\n const index = instances.findIndex(i => i.id === id)\n if (index === -1) return\n const { el } = instances[index]\n const node = el.firstElementChild as HTMLElement | null\n // 标记离场,锁定自身 top,避免与重排上移动画叠加造成闪烁\n if (node) {\n const computedTop = window.getComputedStyle(node).top\n node.style.top = computedTop\n node.classList.add('is-leaving')\n // 同步触发离场过渡(添加离场类后,不再参与 top 过渡)\n node.style.willChange = 'opacity, transform'\n }\n instances[index].leaving = true\n // 先让其他实例平滑上移,跳过离场中的实例\n updatePositions()\n // 等待过渡完成再卸载(避免闪断)\n const LEAVE_MS = 260\n setTimeout(() => {\n render(null, el)\n el.parentNode && el.parentNode.removeChild(el)\n const rmIndex = instances.findIndex(i => i.id === id)\n if (rmIndex !== -1) instances.splice(rmIndex, 1)\n updatePositions()\n }, LEAVE_MS)\n}\n\nfunction show(options: MessageOptions) {\n const id = seed++\n const el = document.createElement('div')\n document.body.appendChild(el)\n\n const vm = createVNode(YMessageToast, {\n id,\n type: options.type || 'success',\n message: options.message,\n duration: options.duration ?? 2500,\n offset: calcOffset(),\n zIndex: 3000 + id,\n closable: options.closable ?? false,\n onClose: (cid: number) => close(cid),\n })\n\n render(vm, el)\n\n const initialHeight = (el.firstElementChild as HTMLElement)?.offsetHeight || 0\n instances.push({ id, el, vm, height: initialHeight, leaving: false })\n updatePositions()\n\n // 等待一帧让过渡进入可见后,重新测量实际高度,避免初始为 0 导致重叠\n requestAnimationFrame(() => {\n const node = el.firstElementChild as HTMLElement | null\n if (!node) return\n const realHeight = node.offsetHeight || initialHeight || 0\n const inst = instances.find(i => i.id === id)\n if (inst) {\n inst.height = realHeight\n updatePositions()\n }\n })\n\n return { close: () => close(id) }\n}\n\nexport const YMessage = {\n success(message: string, durationOrOpts?: number | Omit<MessageOptions,'type'|'message'>) {\n const opts = typeof durationOrOpts === 'number' ? { duration: durationOrOpts } : (durationOrOpts || {})\n return show({ ...opts, type: 'success', message })\n },\n warning(message: string, durationOrOpts?: number | Omit<MessageOptions,'type'|'message'>) {\n const opts = typeof durationOrOpts === 'number' ? { duration: durationOrOpts } : (durationOrOpts || {})\n return show({ ...opts, type: 'warning', message })\n },\n error(message: string, durationOrOpts?: number | Omit<MessageOptions,'type'|'message'>) {\n const opts = typeof durationOrOpts === 'number' ? { duration: durationOrOpts } : (durationOrOpts || {})\n return show({ ...opts, type: 'error', message })\n },\n}\n\nexport type { YMessageType, MessageOptions }\n\n// 自动挂载到全局,无需 import 即可使用\nif (typeof window !== 'undefined') {\n ;(window as any).YMessage = YMessage\n // 同时挂载为全局变量(在非严格模式下可用)\n if (typeof (globalThis as any).YMessage === 'undefined') {\n ;(globalThis as any).YMessage = YMessage\n }\n}\n\nfunction updatePositions() {\n let offset = 20\n instances.forEach(inst => {\n const node = inst.el.firstElementChild as HTMLElement | null\n if (!node) return\n // const currentTop = parseFloat(node.style.top || '20') || 20\n const targetTop = offset\n // const dy = targetTop - currentTop\n // 用 transform 做平滑上移,避免频繁 top 导致回流\n node.style.transform = `translate(-50%, ${targetTop}px)`\n // 仅在首次定位时写入 top 以保证初始位置\n if (!node.style.top) node.style.top = '0px'\n if (!inst.leaving) {\n offset += (node.offsetHeight || inst.height) + GAP\n } else {\n const currentHeight = node.offsetHeight || inst.height\n offset += currentHeight + GAP\n }\n })\n}\n\n\n","<template>\n <div :class=\"['hint-tag-wrapper', `hint-tag-wrapper-${position}`]\">\n <transition name=\"hint-slide\">\n <div \n v-show=\"isExpanded\" \n :class=\"['hint-tag', `hint-tag-${position}`]\"\n :style=\"{ \n width: position === 'top' || position === 'bottom' ? 'auto' : width,\n borderColor: borderColor\n }\"\n >\n <div class=\"hint-tag-content\">\n <slot>{{ content }}</slot>\n </div>\n <div class=\"hint-tag-toggle\" @click=\"toggle\">\n <svg \n class=\"hint-tag-icon\"\n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path \n d=\"M15 18L9 12L15 6\" \n stroke=\"currentColor\" \n stroke-width=\"2\" \n stroke-linecap=\"round\" \n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n </div>\n </transition>\n \n <!-- 收起后的小按钮 -->\n <transition name=\"hint-button-fade\">\n <div \n v-show=\"!isExpanded\" \n :class=\"['hint-tag-button', `hint-tag-button-${position}`]\"\n @click=\"toggle\"\n :title=\"tooltip || content\"\n >\n <svg \n class=\"hint-tag-button-icon\" \n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path \n d=\"M9 18L15 12L9 6\" \n stroke=\"currentColor\" \n stroke-width=\"2\" \n stroke-linecap=\"round\" \n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n </transition>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { ref, inject, onMounted, onUnmounted, watch } from 'vue'\n\ninterface Props {\n content?: string\n position?: 'top' | 'right' | 'bottom' | 'left'\n defaultExpanded?: boolean\n width?: string\n tooltip?: string\n borderColor?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n content: '',\n position: 'right',\n defaultExpanded: true,\n width: '280px',\n tooltip: '',\n borderColor: '#00a8e8'\n})\n\nconst isExpanded = ref(props.defaultExpanded)\n\nconst toggle = () => {\n isExpanded.value = !isExpanded.value\n}\n\n// 收起方法(用于批量收起)\nconst collapse = () => {\n if (isExpanded.value) {\n isExpanded.value = false\n }\n}\n\n// 展开方法(用于批量展开)\nconst expand = () => {\n if (!isExpanded.value) {\n isExpanded.value = true\n }\n}\n\n// 暴露方法供外部调用\ndefineExpose({\n toggle,\n isExpanded,\n collapse,\n expand\n})\n\n// 尝试注册到父级 ytable 组件\nconst registerHintTag = inject<(instance: any) => void>('registerHintTag', null)\nconst unregisterHintTag = inject<(instance: any) => void>('unregisterHintTag', null)\nconst notifyHintTagStateChange = inject<() => void>('notifyHintTagStateChange', null)\n\n// 创建实例对象用于注册\nconst instance = {\n collapse,\n expand,\n toggle,\n get isExpanded() {\n return isExpanded.value\n }\n}\n\n// 监听状态变化,通知父组件更新\nwatch(() => isExpanded.value, () => {\n if (notifyHintTagStateChange) {\n notifyHintTagStateChange()\n }\n})\n\nonMounted(() => {\n if (registerHintTag) {\n registerHintTag(instance)\n }\n})\n\nonUnmounted(() => {\n if (unregisterHintTag) {\n unregisterHintTag(instance)\n }\n})\n</script>\n\n<style scoped lang=\"less\">\n.hint-tag-wrapper {\n display: inline-block;\n position: relative;\n vertical-align: middle;\n margin-left: 4px;\n z-index: 1000;\n pointer-events: none;\n}\n\n.hint-tag {\n position: absolute;\n background: #ffffff;\n color: #333333;\n border-radius: 6px;\n border: 1px solid;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n display: flex;\n align-items: stretch;\n font-size: 12px;\n white-space: nowrap;\n pointer-events: auto;\n \n &.hint-tag-right {\n left: 0;\n top: 50%;\n transform: translateY(-50%);\n flex-direction: row;\n }\n \n &.hint-tag-left {\n right: 0;\n top: 50%;\n transform: translateY(-50%);\n flex-direction: row-reverse;\n }\n \n &.hint-tag-top {\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n flex-direction: column-reverse;\n margin-bottom: 4px;\n }\n \n &.hint-tag-bottom {\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n flex-direction: column;\n margin-top: 4px;\n }\n}\n\n.hint-tag-content {\n flex: 1;\n padding: 6px 10px;\n line-height: 1.5;\n max-height: 150px;\n overflow-y: auto;\n white-space: normal;\n word-break: break-word;\n \n &::-webkit-scrollbar {\n width: 4px;\n }\n \n &::-webkit-scrollbar-track {\n background: #f3f4f6;\n border-radius: 4px;\n }\n \n &::-webkit-scrollbar-thumb {\n background: #d1d5db;\n border-radius: 4px;\n \n &:hover {\n background: #9ca3af;\n }\n }\n}\n\n.hint-tag-toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px;\n cursor: pointer;\n background: #f3f4f6;\n transition: background 0.2s ease;\n flex-shrink: 0;\n color: #666666;\n \n &:hover {\n background: #e5e7eb;\n }\n \n .hint-tag-right & {\n border-radius: 0 6px 6px 0;\n }\n \n .hint-tag-left & {\n border-radius: 6px 0 0 6px;\n }\n \n .hint-tag-top & {\n border-radius: 6px 6px 0 0;\n }\n \n .hint-tag-bottom & {\n border-radius: 0 0 6px 6px;\n }\n}\n\n.hint-tag-icon {\n width: 16px;\n height: 16px;\n transition: transform 0.2s ease;\n \n .hint-tag-right & {\n transform: rotate(0deg); // 向左箭头(展开状态,点击后收起)\n }\n \n .hint-tag-left & {\n transform: rotate(180deg); // 向右箭头(展开状态,点击后收起)\n }\n \n .hint-tag-top & {\n transform: rotate(-90deg); // 向上箭头(展开状态,点击后收起)\n }\n \n .hint-tag-bottom & {\n transform: rotate(90deg); // 向下箭头(展开状态,点击后收起)\n }\n}\n\n.hint-tag-button {\n width: 20px;\n height: 20px;\n background: #ffffff;\n color: #666666;\n border: 1px solid #e5e7eb;\n border-radius: 50%;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);\n transition: transform 0.2s ease, box-shadow 0.2s ease, color 0.2s ease;\n pointer-events: auto;\n vertical-align: middle;\n \n &:hover {\n color: #333333;\n transform: scale(1.1);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n}\n\n.hint-tag-button-icon {\n width: 12px;\n height: 12px;\n transition: transform 0.2s ease;\n \n .hint-tag-button-right & {\n transform: rotate(0deg); // 收起状态,点击后展开,显示→\n }\n \n .hint-tag-button-left & {\n transform: rotate(180deg); // 收起状态,点击后展开,显示←\n }\n \n .hint-tag-button-top & {\n transform: rotate(-90deg); // 收起状态,点击后展开,显示↑\n }\n \n .hint-tag-button-bottom & {\n transform: rotate(90deg); // 收起状态,点击后展开,显示↓\n }\n}\n\n// 动画效果\n.hint-slide-enter-active,\n.hint-slide-leave-active {\n transition: all 0.3s ease;\n}\n\n.hint-tag-right {\n &.hint-slide-enter-from,\n &.hint-slide-leave-to {\n transform: translateY(-50%) translateX(-20px);\n opacity: 0;\n }\n}\n\n.hint-tag-left {\n &.hint-slide-enter-from,\n &.hint-slide-leave-to {\n transform: translateY(-50%) translateX(20px);\n opacity: 0;\n }\n}\n\n.hint-tag-top {\n &.hint-slide-enter-from,\n &.hint-slide-leave-to {\n transform: translateX(-50%) translateY(20px);\n opacity: 0;\n }\n}\n\n.hint-tag-bottom {\n &.hint-slide-enter-from,\n &.hint-slide-leave-to {\n transform: translateX(-50%) translateY(-20px);\n opacity: 0;\n }\n}\n\n.hint-button-fade-enter-active,\n.hint-button-fade-leave-active {\n transition: all 0.2s ease;\n}\n\n.hint-button-fade-enter-from,\n.hint-button-fade-leave-to {\n opacity: 0;\n transform: scale(0.5);\n}\n</style>\n","// 全局类型声明(确保 YMessage 全局类型可用)\ndeclare global {\n interface Window {\n YMessage: {\n success(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n warning(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n error(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n }\n }\n \n // 允许在全局作用域直接使用 YMessage(非严格模式)\n var YMessage: {\n success(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n warning(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n error(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n }\n}\n\n// 导出所有组件\nexport { default as YButton } from './components/ybutton.vue'\nexport { default as YInput } from './components/yinput.vue'\nexport { default as YTable } from './components/ytable.vue'\nexport { default as YSelect } from './components/yselect.vue'\nexport { default as YPagination } from './components/ypagination.vue'\nexport { default as YBadge } from './components/ybadge.vue'\nexport { default as YDialog } from './components/ydialog.vue'\nexport { default as YPopover } from './components/ypopover.vue'\nexport { default as YTime } from './components/ytime.vue'\nexport { default as YSwitch } from './components/yswitch.vue'\nexport { default as YImage } from './components/yimage.vue'\nexport { default as YDropdown } from './components/ydropdown.vue'\nexport { default as YDrawer } from './components/ydrawer.vue'\nexport { default as YTree } from './components/ytree.vue'\nexport { default as QueryEncapsulation } from './components/QueryEncapsulation.vue'\n\n// 导出 YMessage\nexport { YMessage } from './components/ymessage/ymessage'\nexport type { YMessageType, MessageOptions } from './components/ymessage/ymessage'\n\n// 导出类型\nexport type { SwitchProps } from './components/yswitch.vue'\nexport type { SelectOption } from './components/yselect.vue'\nexport type { PaginationProps } from './components/ypagination.vue'\n\n// 安装函数(用于 Vue.use())\nimport type { App } from 'vue'\nimport YButton from './components/ybutton.vue'\nimport YInput from './components/yinput.vue'\nimport YTable from './components/ytable.vue'\nimport YSelect from './components/yselect.vue'\nimport YPagination from './components/ypagination.vue'\nimport YBadge from './components/ybadge.vue'\nimport YDialog from './components/ydialog.vue'\nimport YPopover from './components/ypopover.vue'\nimport YTime from './components/ytime.vue'\nimport YSwitch from './components/yswitch.vue'\nimport YImage from './components/yimage.vue'\nimport YDropdown from './components/ydropdown.vue'\nimport YDrawer from './components/ydrawer.vue'\nimport YTree from './components/ytree.vue'\nimport HintTag from './components/hintTag.vue'\nimport QueryEncapsulation from './components/QueryEncapsulation.vue'\nimport { YMessage } from './components/ymessage/ymessage'\n\nconst components = {\n YButton,\n YInput,\n YTable,\n YSelect,\n YPagination,\n YBadge,\n YDialog,\n YPopover,\n YTime,\n YSwitch,\n YImage,\n YDropdown,\n YDrawer,\n YTree,\n QueryEncapsulation,\n HintTag,\n}\n\nexport default {\n install(app: App) {\n // 注册所有组件\n Object.keys(components).forEach((key) => {\n app.component(key, components[key as keyof typeof components])\n })\n \n // 将 YMessage 挂载到 Vue 全局属性,方便在模板中使用 this.$message\n app.config.globalProperties.$message = YMessage\n \n // 确保挂载到 window 对象,实现全局直接使用(无需 import)\n if (typeof window !== 'undefined') {\n ;(window as any).YMessage = YMessage\n }\n },\n}\n\n"],"names":["props","__props","emit","__emit","onClick","ev","groupPositionClass","computed","isGroup","onGroupItemClick","item","_openBlock","_createElementBlock","_hoisted_3","_Fragment","_renderList","index","_a","$event","_createElementVNode","_hoisted_5","_hoisted_6","_cache","_hoisted_7","_hoisted_8","_toDisplayString","_hoisted_2","_renderSlot","_ctx","inputRef","ref","previousValue","hasChanged","isFocused","inputPlaceholder","watch","val","onInput","target","onFocus","onBlur","current","minVal","onEnter","onPaste","_normalizeClass","currentPage","pageSize","selectedItems","selectedRowKey","expandedKeys","tableMaxHeight","tableContainer","headerRef","bodyWrapRef","bodyTableRef","headerColWidths","headerWidthMap","hintTagInstances","hasHintTags","allHintsExpanded","hintTagStateUpdateTrigger","expandedCount","instance","collapsedCount","registerHintTag","unregisterHintTag","collapseAllHints","expandAllHints","toggleAllHints","notifyHintTagStateChange","provide","autoColumnKeys","col","normalizeWidth","getAutoColumnWidth","vTrackRef","vScroll","isDragging","dragStartY","dragStartScrollTop","scrollbarWidth","width","trimmed","parseWidthNumber","normalized","parsed","totalTableColumns","count","filteredData","keyword","field","value","getNestedValue","pagedData","isAllVisibleSelected","visibleKeys","getRowKey","isRowDisabled","key","isAllVisibleDisabled","shouldDisableNext","fixedLeftWidths","widths","cumulativeWidth","i","parsedWidth","fixedRightWidths","rightFixedColumns","getFixedColumnIndex","columnIndex","fixed","isRowExpanded","toggleRowExpand","obj","path","getColumnClass","column","isHeader","classes","getColumnStyle","style","normalizedWidth","autoWidth","fixedIndex","leftOffset","rightOffset","formatCellValue","toggleSelect","rowData","rowIndex","x","toggleSelectAllVisible","union","clearSelection","handleRowClick","k","isRowSelected","newVal","currentSet","newSet","handlePageChange","page","handlePageSizeChange","size","next","calculateTableMaxHeight","nextTick","containerRect","viewportHeight","containerTop","headerElement","headerHeight","paginationHeight","paginationElement","bulkBarElement","bulkBarHeight","reservedHeight","availableHeight","maxHeight","tableContent","isSyncingScroll","syncHeaderScroll","syncBodyScroll","updateVirtualScrollbar","wrap","contentHeight","viewport","scrollTop","needVBar","minThumb","ratio","trackHeight","thumbHeight","maxThumbTop","maxScrollTop","onThumbMousemove","e","scrollDelta","onThumbMouseup","measureAutoColumnWidths","w","fallback","firstRow","startIndex","tds","td","measured","stored","_b","handleResize","updateHeaderScrollbarGutter","nextWidths","nextMap","idx","currentKeys","onMounted","resizeObserver","onUnmounted","lastScrollbarWidth","currentScrollbarWidth","headerTable","bodyTable","_createVNode","_Transition","_hoisted_1","_component_YButton","_hoisted_4","_hoisted_9","_hoisted_10","_hoisted_11","_normalizeStyle","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_16","colIndex","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_22","_createBlock","_component_YPagination","isOpen","hoveredIndex","optionsContainer","triggerElement","selectContainer","shouldOpenUpward","inputElement","searchQuery","selectedOption","option","getOptionValue","selectedOptions","values","selectedLabel","getOptionLabel","displayedOptions","query","opt","label","portalDropdownStyle","trigger","rect","calculateDropdownPosition","triggerRect","dropdownHeight","dropdownBottom","dropdownTop","shouldOpenDown","canOpenUp","getOptionKey","isSelected","isOptionDisabled","toggleDropdown","closeDropdown","openDropdown","scrollToSelected","selectOption","_index","currentValues","optionValue","valueIndex","handleClear","cleared","removeTag","event","moveHover","delta","total","attempts","scrollHoverIntoView","selectHovered","selectedElement","el","handleClickOutside","_withModifiers","_createTextVNode","_Teleport","pageSizeOptions","goToPage","onPagerGroupClick","action","_component_YSelect","toneClass","ariaLabel","text","tone","prog","progMap","toneMap","visible","v","panelRef","panelStyle","onMaskClick","close","onEsc","onKeydown","$slots","popoverRef","triggerRef","contentRef","contentRect","arrowPosition","openTimer","closeTimer","contentStyle","top","left","calculatePosition","arrowStyle","triggerWidth","triggerHeight","triggerTop","triggerLeft","contentWidth","viewportWidth","show","clearTimers","doShow","updatePosition","hide","doHide","calculateArrowPosition","triggerCenterX","contentLeft","arrowOffset","triggerCenterY","contentTop","handleTriggerClick","handleMouseEnter","handleMouseLeave","handleContentMouseEnter","handleContentMouseLeave","__expose","activeShortcutIndex","selectedShortcutIndex","pendingValue","dropdown","dropdownPosition","startCalendar","endCalendar","ensureDifferentMonths","startTime","endTime","nextMonth","ensureDifferentMonthsReverse","prevMonth","weekDays","tempStartDate","tempEndDate","parseDate","date","formatDateToString","year","month","day","hours","minutes","seconds","formatDateToTimestamp","normalizeValue","formatOutputValue","formatYearMonth","isSameDay","date1","date2","isDateInRange","start","end","findMatchingShortcutIndex","currentValue","normalizedValue","shortcutValue","currentStart","currentEnd","shortcutStart","shortcutEnd","generateCalendarDays","firstDay","lastDay","firstDayWeek","daysInMonth","days","today","prevDaysCount","remainingDays","weeks","updateValue","formattedValue","dropdownRect","spaceBelow","spaceAbove","spaceRight","dropdownWidth","triggerEl","dropdownEl","handleTriggerKeydown","focusFirstShortcut","handleDropdownKeydown","handleShortcutKeydown","focusShortcut","selectShortcut","handleShortcutMouseEnter","handleShortcutMouseLeave","shortcutElement","shortcut","s","selectDate","type","selectedDate","endDate","getDateCellClass","confirmSelection","resetSelection","startCalendarDays","endCalendarDays","displayText","formatDate","startStr","endStr","dropdownClasses","hasValue","canConfirm","newValue","startDate","handleClearClick","changeMonth","direction","newDate","_hoisted_15","week","weekIndex","dayIndex","_hoisted_21","_hoisted_23","_hoisted_24","_hoisted_25","_hoisted_26","_hoisted_27","_hoisted_28","_hoisted_30","_hoisted_31","_hoisted_32","rootEl","isChecked","switchStyle","onToggle","containerRef","imageRef","previewImageRef","isLoaded","isLoading","hasError","isInView","showPreview","imgSrc","previewSrc","zoomLevel","isMounted","originalBodyStyle","RADIUS_TOKEN_MAP","containerClass","radiusValue","radiusStyle","imageClass","imageStyle","resolvedPreviewSrc","getScrollbarWidth","scrollDiv","lockBodyScroll","unlockBodyScroll","observer","setupIntersectionObserver","entries","entry","handleLoad","handleError","retryLoad","getPreviewUrl","handleErrorClick","handlePreview","previewUrl","img","timeoutId","isHandled","showPreviewModal","closePreview","handleWheel","zoomDirection","newZoom","nv","_vShow","dropdownRef","hideTimer","menuClass","menuStyle","showDropdown","hideDropdown","menu","menuRect","absoluteTop","absoluteLeft","menuWidth","menuHeight","transitionName","roundedClass","DEPT_ICON_URL","PERSON_ICON_URL","treeData","store","effectiveRestrictLevel","getNodeKey","node","getNodeLabel","isEmployeeNode","getNodeIcon","rootNode","dept","person","button","childStyleIcon","isChildStyleNode","hasChildren","children","getNodeChildren","getNodeDepth","targetNode","currentDepth","child","depth","isNodeExpanded","nodeKey","isNodeChecked","checkedChildren","indeterminateChildren","isNodeIndeterminate","isNodeCurrent","isNodeHighlighted","handleCheckClick","newCheckedState","currentExpandedKeys","cascadeChildren","check","childKey","preventAutoExpandFourthLevel","updateAllParentNodes","_node","handleExpandClick","allNodes","collectAllNodes","nodes","updateNodeParents","handleNodeClick","data","nodeComponent","isChildStyle","handleNodeContextMenu","keys","restrictLevel","getDepthByKey","targetKey","level","n","d","collectKeysToDepth","maxDepth","newExpandedKeys","filtered","expandAllNodes","collectExpandableKeys","allExpandableKeys","expandNodesWithCheckedPermissions","findPathsToCheckedNodes","parentPath","currentPath","checkedKeys","expandableKeys","highlightAndExpandByIds","ids","findPathToKey","nk","newPath","p","targetIds","keysToExpand","targetId","clearHighlights","clearCurrentNode","grandChild","greatGrandChild","_hoisted_33","_hoisted_34","_hoisted_36","_hoisted_37","greatGreatGrandChild","_hoisted_40","_hoisted_42","_hoisted_43","_hoisted_45","isExpanded","searchForm","reactive","autoTriggerTypes","autoSearchTimer","visibleFields","displayedFields","hasHiddenFields","getFieldComponent","YSelect","YTime","YSwitch","YInput","updateFieldValue","f","handleFieldChange","scheduleAutoSearch","handleSwitchChange","handleSearch","searchParams","filterEmptyParams","formattedParams","formatSearchParams","rawParams","handleReset","toggleExpanded","getFieldListeners","handleInputQuickSearch","params","rawValue","formatted","startKey","endKey","initFormData","_c","_d","onBeforeUnmount","_TransitionGroup","_resolveDynamicComponent","_mergeProps","_toHandlers","YButton","timer","remainingTime","startTimer","clearTimer","duration","elapsed","onAfterLeave","seed","GAP","instances","calcOffset","offset","inst","id","computedTop","updatePositions","render","rmIndex","options","vm","createVNode","YMessageToast","cid","initialHeight","realHeight","YMessage","message","durationOrOpts","targetTop","currentHeight","toggle","collapse","expand","inject","components","YTable","YPagination","YBadge","YDialog","YPopover","YImage","YDropdown","YDrawer","YTree","QueryEncapsulation","HintTag","app"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDA,UAAMA,IAAQC,GAwCRC,IAAOC;AAKb,aAASC,EAAQC,GAAgB;AAC/B,UAAIL,EAAM,YAAYA,EAAM,SAAS;AACnC,QAAAK,EAAG,eAAA,GACHA,EAAG,gBAAA;AACH;AAAA,MACF;AACA,MAAAH,EAAK,SAASG,CAAE;AAAA,IAClB;AAEA,UAAMC,IAAqBC,EAAS,MAAM;AACxC,cAAQP,EAAM,eAAA;AAAA,QACZ,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT,KAAK;AACH,iBAAO;AAAA,QACT;AACE,iBAAO;AAAA,MAAA;AAAA,IAEb,CAAC,GAEKQ,IAAUD,EAAS,MAAM,MAAM,QAAQP,EAAM,UAAU,KAAKA,EAAM,WAAW,SAAS,CAAC;AAE7F,aAASS,EAAiBC,GAA0EL,GAAgB;AAClH,UAAIL,EAAM,YAAYA,EAAM,WAAWU,EAAK,YAAYA,EAAK,SAAS;AACpE,QAAAL,EAAG,eAAA,GACHA,EAAG,gBAAA;AACH;AAAA,MACF;AACA,MAAAH,EAAK,eAAeQ,EAAK,OAAOL,CAAE;AAAA,IACpC;qBAnImBG,EAAA,SAoBfG,KAAAC,EA6BM,OA7BNC,IA6BM;AAAA,OA5BJF,EAAA,EAAA,GAAAC,EA2BSE,IAAA,MAAAC,GA1BiBd,EAAA,YAAU,CAA1BS,GAAMM,MAAK;;oBADrBJ,EA2BS,UAAA;AAAA,UAzBN,KAAKF,EAAK,SAASM;AAAA,UACpB,UAAM,SAAO;AAAA,sBACiBN,EAAK,WAAWT,EAAA,OAAO;AAAA,sBAAwBS,EAAK,QAAQT,EAAA,IAAI;AAAA;YAAsCe,MAAK,IAAA,oBAA8BA,SAAWC,IAAAhB,EAAA,eAAA,gBAAAgB,EAAY,WAAM,KAAA,IAAA,kBAAA;AAAA,4BAA8EP,EAAK,WAAWT,EAAA,QAAA;AAAA,UAAO;UAOxS,MAAMA,EAAA;AAAA,UACN,WAAWS,EAAK,YAAQ,OAAcT,EAAA,YAAYA,EAAA,WAAWS,EAAK;AAAA,UAClE,aAAYA,EAAK,WAAWT,EAAA,UAAO,SAAA;AAAA,UACnC,kBAAiBS,EAAK,YAAQ,OAAcT,EAAA,YAAYA,EAAA,WAAWS,EAAK,UAAO,SAAA;AAAA,UAC/E,cAAYA,EAAK,aAAaA,EAAK;AAAA,UACnC,SAAK,CAAAQ,MAAET,EAAiBC,GAAMQ,CAAM;AAAA,QAAA;UAErCC,EAQO,QARPC,IAQO;AAAA,YAPMV,EAAK,SAAI,kBAApBC,EAAA,GAAAC,EAEM,OAFNS,IAEM,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cADJH,EAAyK,QAAA;AAAA,gBAAnK,aAAU;AAAA,gBAAU,GAAE;AAAA,gBAAuH,aAAU;AAAA,cAAA;oBAE/IT,EAAK,SAAI,mBAAzBC,KAAAC,EAEM,OAFNW,IAEM,CAAA,GAAAD,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cADJH,EAAwK,QAAA;AAAA,gBAAlK,aAAU;AAAA,gBAAU,GAAE;AAAA,gBAAsH,aAAU;AAAA,cAAA;;YAElJT,EAAK,SAAK,CAAKA,EAAK,iBAAhCE,EAAiE,QAAAY,IAAAC,GAApBf,EAAK,KAAK,GAAA,CAAA;;;;gBA7C7DE,EAgBS,UAAA;AAAA;MAfP,UAAM,SAAO;AAAA,kBACeX,EAAA,OAAO;AAAA,kBAAsBA,EAAA,IAAI;AAAA,QAA0B,EAAA,YAAAA,EAAA,qBAAqBA,EAAA,QAAA;AAAA,QAAmBA,EAAA,kBAAa,WAAA,eAAA;AAAA,QAA2CK,EAAA;AAAA,MAAA;MAOtL,MAAML,EAAA;AAAA,MACN,UAAUA,EAAA,YAAYA,EAAA;AAAA,MACtB,aAAWA,EAAA,UAAO,SAAA;AAAA,MAClB,iBAAgBA,EAAA,YAAYA,EAAA,UAAO,SAAA;AAAA,MACnC,SAAAG;AAAA,IAAA;MAEDe,EAAqC,QAArCO,IAAqC;AAAA,QAAfC,GAAQC,EAAA,QAAA,WAAA,CAAA,GAAA,QAAA,EAAA;AAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACYpC,UAAM5B,IAAQC,GAkCRC,IAAOC,GAMP0B,IAAWC,EAA6B,IAAI,GAC5CC,IAAgBD,EAAY,EAAE,GAC9BE,IAAaF,EAAa,EAAK,GAC/BG,IAAYH,EAAa,EAAK,GAC9BI,IAAmBJ,EAAY9B,EAAM,eAAe,EAAE;AAE5D,IAAAmC,GAAM,MAAMnC,EAAM,aAAa,CAACoC,MAAQ;AACtC,MAAKH,EAAU,UACbC,EAAiB,QAAQE,KAAO;AAAA,IAEpC,CAAC;AAED,aAASC,EAAQhC,GAAW;AAC1B,YAAMiC,IAASjC,EAAG;AAClB,MAAA2B,EAAW,QAAQ,IACnB9B,EAAK,qBAAqBoC,EAAO,KAAK;AAAA,IACxC;AAEA,aAASC,IAAU;AACjB,MAAAN,EAAU,QAAQ,IACdjC,EAAM,iBAER+B,EAAc,QAAQ/B,EAAM,cAAc,IAE1CgC,EAAW,QAAQ,IAEnBE,EAAiB,QAAQH,EAAc,SAAS/B,EAAM,eAAe,IAErEE,EAAK,qBAAqB,EAAE;AAAA,IAEhC;AAEA,aAASsC,IAAS;AAUhB,UATAP,EAAU,QAAQ,IACdjC,EAAM,gBAEJ,CAACgC,EAAW,UAAU,CAAChC,EAAM,cAAcA,EAAM,eAAe,OAClEE,EAAK,qBAAqB6B,EAAc,KAAK,GAK7C/B,EAAM,QAAQ,UAAaA,EAAM,eAAe,UAAaA,EAAM,eAAe,IAAI;AACxF,cAAMyC,IAAU,OAAOzC,EAAM,UAAU,GACjC0C,IAAS,OAAO1C,EAAM,GAAG;AAC/B,QAAI,CAAC,OAAO,MAAMyC,CAAO,KAAK,CAAC,OAAO,MAAMC,CAAM,KAAKD,IAAUC,KAC/DxC,EAAK,qBAAqB,OAAOwC,CAAM,CAAC;AAAA,MAE5C;AAEA,MAAAR,EAAiB,QAAQlC,EAAM,eAAe;AAAA,IAChD;AAEA,aAAS2C,EAAQtC,GAAmB;AAClC,YAAMiC,IAASjC,EAAG;AAClB,MAAAH,EAAK,SAASoC,EAAO,KAAK;AAAA,IAC5B;AAEA,aAASM,EAAQvC,GAAoB;AACnC,YAAMiC,IAASjC,EAAG;AAClB,4BAAsB,MAAM;AAC1B,QAAAH,EAAK,SAASoC,EAAO,KAAK;AAAA,MAC5B,CAAC;AAAA,IACH;2BAnIE1B,EAsBM,OAAA;AAAA,MAtBD,OAAKiC,EAAA,CAAC,gBAAc,EAAA,YAAuB5C,EAAA,MAAA,CAAK,CAAA;AAAA,MAAK,mBAAgBA,EAAA,OAAK;AAAA,IAAA;MAC7EkB,EAoBE,SAAA;AAAA,iBAnBI;AAAA,QAAJ,KAAIU;AAAA,QACJ,OAAKgB,EAAA,CAAC,WAAS,YACK5C,EAAA,IAAI,EAAA,CAAA;AAAA,QACvB,IAAIA,EAAA;AAAA,QACJ,MAAMA,EAAA;AAAA,QACN,MAAMA,EAAA;AAAA,QACN,aAAaiC,EAAA;AAAA,QACb,cAAcjC,EAAA;AAAA,QACd,WAAWA,EAAA;AAAA,QACX,KAAKA,EAAA;AAAA,QACL,KAAKA,EAAA;AAAA,QACL,UAAUA,EAAA;AAAA,QACV,UAAUA,EAAA;AAAA,QACV,OAAOA,EAAA;AAAA,QACP,SAAAoC;AAAA,QACA,SAAAE;AAAA,QACA,QAAAC;AAAA,QACA,YAAaG,GAAO,CAAA,OAAA,CAAA;AAAA,QACpB,SAAAC;AAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACuMP,UAAM5C,IAAQC,GA6BRC,IAAOC,GAUP2C,IAAchB,EAAI9B,EAAM,eAAe,CAAC,GACxC+C,IAAWjB,EAAI9B,EAAM,QAAQ,GAC7BgD,IAAgBlB,EAAyB9B,EAAM,iBAAiB,CAAA,CAAE,GAClEiD,IAAiBnB,EAAyB,EAAE,GAC5CoB,IAAepB,EAA0B,oBAAI,KAAK,GAClDqB,IAAiBrB,EAAI,MAAM,GAC3BsB,IAAiBtB,EAAA,GACjBuB,IAAYvB,EAAA,GACZwB,IAAcxB,EAAA,GACdyB,IAAezB,EAAA,GAEf0B,IAAkB1B,EAAc,EAAE,GAClC2B,IAAiB3B,EAA4B,EAAE,GAG/C4B,IAAmB5B,EAAc,oBAAI,KAAK,GAG1C6B,IAAcpD,EAAS,MAAMmD,EAAiB,MAAM,OAAO,CAAC,GAI5DE,IAAmBrD,EAAS,MAAM;AAItC,UAFKsD,EAA0B,OAE3BH,EAAiB,MAAM,SAAS,EAAG,QAAO;AAC9C,UAAII,IAAgB;AACpB,aAAAJ,EAAiB,MAAM,QAAQ,CAACK,MAAa;AAC3C,QAAIA,KAAYA,EAAS,cACvBD;AAAA,MAEJ,CAAC,GACMA,MAAkBJ,EAAiB,MAAM;AAAA,IAClD,CAAC;AAGyB,IAAAnD,EAAS,MAAM;AAIvC,UAFKsD,EAA0B,OAE3BH,EAAiB,MAAM,SAAS,EAAG,QAAO;AAC9C,UAAIM,IAAiB;AACrB,aAAAN,EAAiB,MAAM,QAAQ,CAACK,MAAa;AAC3C,QAAIA,KAAY,CAACA,EAAS,cACxBC;AAAA,MAEJ,CAAC,GACMA,MAAmBN,EAAiB,MAAM;AAAA,IACnD,CAAC;AAGD,aAASO,EAAgBF,GAAe;AACtC,MAAAL,EAAiB,MAAM,IAAIK,CAAQ;AAAA,IACrC;AAGA,aAASG,GAAkBH,GAAe;AACxC,MAAAL,EAAiB,MAAM,OAAOK,CAAQ;AAAA,IACxC;AAGA,aAASI,IAAmB;AAC1B,MAAAT,EAAiB,MAAM,QAAQ,CAACK,MAAa;AAC3C,QAAIA,KAAY,OAAOA,EAAS,YAAa,cAC3CA,EAAS,SAAA;AAAA,MAEb,CAAC;AAAA,IACH;AAGA,aAASK,KAAiB;AACxB,MAAAV,EAAiB,MAAM,QAAQ,CAACK,MAAa;AAC3C,QAAIA,KAAY,OAAOA,EAAS,UAAW,cACzCA,EAAS,OAAA;AAAA,MAEb,CAAC;AAAA,IACH;AAGA,aAASM,KAAiB;AACxB,MAAIT,EAAiB,QAEnBO,EAAA,IAGAC,GAAA;AAAA,IAEJ;AAGA,UAAMP,IAA4B/B,EAAI,CAAC;AAGvC,aAASwC,IAA2B;AAClC,MAAAT,EAA0B;AAAA,IAC5B;AAGA,IAAAU,GAAQ,mBAAmBN,CAAe,GAC1CM,GAAQ,qBAAqBL,EAAiB,GAC9CK,GAAQ,4BAA4BD,CAAwB;AAE5D,UAAME,IAAiBjE;AAAA,MAAS,MAC9BP,EAAM,QACH,OAAO,CAACyE,MAAQ,CAACC,EAAeD,EAAI,KAAK,CAAC,EAC1C,IAAI,CAACA,MAAQA,EAAI,GAAG;AAAA,IAAA;AAGzB,aAASE,IAA6B;AAGpC,aAAO,IADK,OADEH,EAAe,MAAM,UAAU,IAE/B,QAAQ,CAAC,CAAC;AAAA,IAC1B;AAGA,UAAMI,KAAY9C,EAAA,GACZ+C,KAAU/C,EAAI;AAAA,MAClB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IAAA,CACX;AACD,QAAIgD,IAAa,IACbC,KAAa,GACbC,IAAqB;AAGzB,UAAMC,IAAiBnD,EAAI,CAAC;AAE5B,aAAS4C,EAAeQ,GAA6C;AACnE,UAA2BA,KAAU,KAAM;AAC3C,UAAI,OAAOA,KAAU;AACnB,eAAI,OAAO,SAASA,CAAK,IAChB,GAAGA,CAAK,OAEjB;AAEF,YAAMC,IAAU,OAAOD,CAAK,EAAE,KAAA;AAC9B,UAAKC;AACL,eAAI,gBAAgB,KAAKA,CAAO,IACvB,GAAGA,CAAO,OAEZA;AAAA,IACT;AAEA,aAASC,EAAiBF,GAAwC;AAChE,YAAMG,IAAaX,EAAeQ,CAAK;AACvC,UAAI,CAACG,EAAY,QAAO;AACxB,YAAMC,IAAS,WAAWD,CAAU;AACpC,aAAO,OAAO,SAASC,CAAM,IAAIA,IAAS;AAAA,IAC5C;AASA,UAAMC,IAAoBhF,EAAS,MAAM;AACvC,UAAIiF,IAAQxF,EAAM,QAAQ;AAC1B,aAAIA,EAAM,eAAYwF,KAAS,IAC3BxF,EAAM,eAAYwF,KAAS,IACxBA;AAAA,IACT,CAAC,GAEKC,IAAelF,EAAS,MAAM;AAClC,UAAI,CAACP,EAAM,iBAAiB,CAACA,EAAM,aAAa;AAC9C,eAAOA,EAAM;AAGf,YAAM0F,IAAU1F,EAAM,cAAc,YAAA;AACpC,aAAOA,EAAM,KAAK,OAAO,CAACU,MACjBV,EAAM,aAAc,KAAK,CAAA2F,MAAS;AACvC,cAAMC,IAAQC,GAAenF,GAAMiF,CAAK;AACxC,eAAO,OAAOC,CAAK,EAAE,YAAA,EAAc,SAASF,CAAO;AAAA,MACrD,CAAC,CACF;AAAA,IACH,CAAC,GAIKI,IAAYvF,EAAS,OACpBP,EAAM,YAEJyF,EAAa,MACrB,GAEKM,IAAuBxF,EAAS,MAAM;AAC1C,UAAI,CAACP,EAAM,WAAY,QAAO;AAC9B,YAAMgG,IAAcF,EAAU,MAC3B,IAAI,CAACpF,GAAMM,OAAW,EAAE,KAAKiF,GAAUvF,GAAMM,CAAK,GAAG,MAAAN,GAAM,OAAAM,IAAQ,EACnE,OAAO,CAAC,EAAE,MAAAN,GAAM,OAAAM,EAAA,MAAY,CAACkF,GAAcxF,GAAMM,CAAK,CAAC,EACvD,IAAI,CAAC,EAAE,KAAAmF,EAAA,MAAUA,CAAG;AACvB,aAAOH,EAAY,SAAS,KAAKA,EAAY,MAAM,OAAOhD,EAAc,MAAM,SAASmD,CAAG,CAAC;AAAA,IAC7F,CAAC,GAEKC,IAAuB7F,EAAS,MAAM;AAC1C,UAAI,CAACP,EAAM,WAAY,QAAO;AAE9B,YAAMgG,IAAcF,EAAU,MAAM,IAAI,CAACpF,GAAMM,OAAW,EAAE,MAAAN,GAAM,OAAAM,EAAA,EAAQ;AAC1E,aAAOgF,EAAY,SAAS,KAAKA,EAAY,MAAM,CAAC,EAAE,MAAAtF,GAAM,OAAAM,EAAA,MAAYkF,GAAcxF,GAAMM,CAAK,CAAC;AAAA,IACpG,CAAC,GAIKqF,KAAoB9F,EAAS,MAC5BP,EAAM,aAEJ8F,EAAU,MAAM,SAAS/C,EAAS,QAFX,EAG/B,GAGKuD,KAAkB/F,EAAS,MAAM;AACrC,YAAMgG,IAAmB,CAAA;AACzB,UAAIC,IAAkBxG,EAAM,aAAa,KAAK;AAE9C,eAASyG,IAAI,GAAGA,IAAIzG,EAAM,QAAQ,QAAQyG,KAAK;AAC7C,cAAMhC,IAAMzE,EAAM,QAAQyG,CAAC;AAC3B,YAAIhC,EAAI,UAAU,QAAQ;AACxB,cAAIS,IAAQ;AACZ,gBAAMwB,IAActB,EAAiBX,EAAI,KAAK;AAC9C,UAAIiC,MAAgB,OAClBxB,IAAQwB,IACClD,EAAgB,MAAMiD,CAAC,MAEhCvB,IAD0BE,EAAiB5B,EAAgB,MAAMiD,CAAC,CAAC,KACtCvB,IAE/BqB,EAAO,KAAKC,CAAe,GAC3BA,KAAmBtB;AAAA,QACrB;AAAA,MACF;AACA,aAAOqB;AAAA,IACT,CAAC,GAEKI,KAAmBpG,EAAS,MAAM;AACtC,YAAMgG,IAAmB,CAAA;AACzB,UAAIC,IAAkB;AAItB,YAAMI,IAA6D,CAAA;AACnE,eAASH,IAAIzG,EAAM,QAAQ,SAAS,GAAGyG,KAAK,GAAGA,KAAK;AAClD,cAAMhC,IAAMzE,EAAM,QAAQyG,CAAC;AAC3B,YAAIhC,EAAI,UAAU,SAAS;AACzB,cAAIS,IAAQ;AACZ,gBAAMwB,IAActB,EAAiBX,EAAI,KAAK;AAC9C,UAAIiC,MAAgB,OAClBxB,IAAQwB,IACClD,EAAgB,MAAMiD,CAAC,MAEhCvB,IAD0BE,EAAiB5B,EAAgB,MAAMiD,CAAC,CAAC,KACtCvB,IAE/B0B,EAAkB,KAAK,EAAE,OAAOH,GAAG,OAAAvB,GAAO;AAAA,QAC5C;AAAA,MACF;AAIA,eAASuB,IAAI,GAAGA,IAAIG,EAAkB,QAAQH;AAC5C,QAAAF,EAAO,KAAKC,CAAe,GAC3BA,KAAmBI,EAAkBH,CAAC,EAAE;AAG1C,aAAOF;AAAA,IACT,CAAC;AAGD,aAASM,GAAoBC,GAAqBC,GAAiC;AACjF,UAAIA,MAAU,QAAQ;AACpB,YAAIvB,IAAQ;AACZ,iBAASiB,IAAI,GAAGA,IAAIK,GAAaL;AAC/B,UAAIzG,EAAM,QAAQyG,CAAC,EAAE,UAAU,UAC7BjB;AAGJ,eAAOA;AAAA,MACT,OAAO;AAEL,YAAIA,IAAQ;AACZ,iBAASiB,IAAIzG,EAAM,QAAQ,SAAS,GAAGyG,IAAIK,GAAaL;AACtD,UAAIzG,EAAM,QAAQyG,CAAC,EAAE,UAAU,WAC7BjB;AAGJ,eAAOA;AAAA,MACT;AAAA,IACF;AAGA,aAASS,GAAUvF,GAAWM,GAAgC;AAC5D,aAAI,OAAOhB,EAAM,UAAW,aACnBA,EAAM,OAAOU,CAAI,IAEnBA,EAAKV,EAAM,MAAM,KAAKgB;AAAA,IAC/B;AAGA,aAASkF,GAAcxF,GAAWM,GAAwB;AACxD,aAAIhB,EAAM,eAAe,OAAOA,EAAM,eAAgB,aAC7CA,EAAM,YAAYU,GAAMM,CAAK,IAE/B;AAAA,IACT;AAEA,aAASgG,GAAcb,GAAsB;AAC3C,aAAOjD,EAAa,MAAM,IAAIiD,CAAG;AAAA,IACnC;AAEA,aAASc,GAAgBd,GAAsB;AAC7C,MAAIjD,EAAa,MAAM,IAAIiD,CAAG,IAC5BjD,EAAa,MAAM,OAAOiD,CAAG,IAE7BjD,EAAa,MAAM,IAAIiD,CAAG;AAAA,IAE9B;AAEA,aAASN,GAAeqB,GAAUC,GAAmB;AACnD,aAAOA,EAAK,MAAM,GAAG,EAAE,OAAO,CAAC1E,GAAS0D,MAAQ1D,KAAA,gBAAAA,EAAU0D,IAAMe,CAAG;AAAA,IACrE;AAEA,aAASE,GAAeC,GAAqBC,IAAW,IAAe;AACrE,YAAMC,IAAU,CAAA;AAChB,aAAIF,EAAO,SACTE,EAAQ,KAAK,QAAQF,EAAO,KAAK,EAAE,GAEjCA,EAAO,UAAU,YACnBE,EAAQ,KAAK,iBAAiB,GAC1BD,KAAUC,EAAQ,KAAK,wBAAwB,IAEjDF,EAAO,UAAU,WACnBE,EAAQ,KAAK,gBAAgB,GACzBD,KAAUC,EAAQ,KAAK,uBAAuB,IAE7CA,EAAQ,KAAK,GAAG;AAAA,IACzB;AAEA,aAASC,GAAeH,GAAqBP,GAAqBQ,GAA2C;AAC3G,YAAMG,IAAgC,CAAA,GAEhCC,IAAkBhD,EAAe2C,EAAO,KAAK;AACnD,UAAIK;AAEF,QAAAD,EAAM,QAAQC,GACdD,EAAM,WAAWC,GACjBD,EAAM,WAAWC;AAAA,WACZ;AAEL,cAAMC,IAAYhD,EAAA;AAClB,QAAA8C,EAAM,QAAQE,GACdF,EAAM,WAAWE,GACjBF,EAAM,WAAWE;AAAA,MACnB;AAGA,UAAIN,EAAO,UAAU,QAAQ;AAC3B,cAAMO,IAAaf,GAAoBC,GAAa,MAAM,GACpDe,IAAavB,GAAgB,MAAMsB,CAAU,KAAK;AACxD,QAAAH,EAAM,OAAO,GAAGI,CAAU,MAC1BJ,EAAM,SAASH,IAAW,GAAG,KAAKM,CAAU,KAAK,GAAG,IAAIA,CAAU;AAAA,MACpE,WAAWP,EAAO,UAAU,SAAS;AACnC,cAAMO,IAAaf,GAAoBC,GAAa,OAAO,GACrDgB,IAAcnB,GAAiB,MAAMiB,CAAU,KAAK;AAI1D,QAAIN,IACFG,EAAM,QAAQ,GAAGK,IAAc,CAAC,OAEhCL,EAAM,QAAQ,GAAGK,CAAW,MAG9BL,EAAM,SAASH,IAAW,GAAG,KAAKM,CAAU,KAAK,GAAG,IAAIA,CAAU;AAAA,MACpE;AAEA,aAAOH;AAAA,IACT;AAEA,aAASM,GAAgBrH,GAAW2G,GAA6B;AAC/D,YAAMzB,IAAQC,GAAenF,GAAM2G,EAAO,GAAG;AAC7C,aAAIA,EAAO,YACFA,EAAO,UAAUzB,GAAOlF,CAAI,IAE9BkF,KAAS;AAAA,IAClB;AAEA,aAASoC,GAAa7B,GAAsB;AAE1C,YAAM8B,IAAUnC,EAAU,MAAM,KAAK,CAACpF,GAAMM,MAAUiF,GAAUvF,GAAMM,CAAK,MAAMmF,CAAG,GAC9E+B,IAAWpC,EAAU,MAAM,UAAU,CAACpF,GAAMM,MAAUiF,GAAUvF,GAAMM,CAAK,MAAMmF,CAAG;AAG1F,MAAI8B,KAAWC,KAAY,KAAKhC,GAAc+B,GAASC,CAAQ,MAI3DlF,EAAc,MAAM,SAASmD,CAAG,IAClCnD,EAAc,QAAQA,EAAc,MAAM,OAAO,CAAAmF,MAAKA,MAAMhC,CAAG,IAE/DnD,EAAc,QAAQ,CAAC,GAAGA,EAAc,OAAOmD,CAAG,GAEpDjG,EAAK,UAAU8C,EAAc,KAAK,GAClC9C,EAAK,wBAAwB8C,EAAc,KAAK;AAAA,IAClD;AAEA,aAASoF,IAAyB;AAEhC,YAAMpC,IAAcF,EAAU,MAC3B,IAAI,CAACpF,GAAMM,OAAW,EAAE,KAAKiF,GAAUvF,GAAMM,CAAK,GAAG,MAAAN,GAAM,OAAAM,IAAQ,EACnE,OAAO,CAAC,EAAE,MAAAN,GAAM,OAAAM,EAAA,MAAY,CAACkF,GAAcxF,GAAMM,CAAK,CAAC,EACvD,IAAI,CAAC,EAAE,KAAAmF,EAAA,MAAUA,CAAG;AAEvB,UAAIH,EAAY,WAAW,GAE3B;AAAA,YAAIA,EAAY,MAAM,CAAAG,MAAOnD,EAAc,MAAM,SAASmD,CAAG,CAAC;AAC5D,UAAAnD,EAAc,QAAQA,EAAc,MAAM,OAAO,OAAO,CAACgD,EAAY,SAASG,CAAG,CAAC;AAAA,aAC7E;AACL,gBAAMkC,wBAAY,IAAI,CAAC,GAAGrF,EAAc,OAAO,GAAGgD,CAAW,CAAC;AAC9D,UAAAhD,EAAc,QAAQ,MAAM,KAAKqF,CAAK;AAAA,QACxC;AACA,QAAAnI,EAAK,UAAU8C,EAAc,KAAK,GAClC9C,EAAK,wBAAwB8C,EAAc,KAAK;AAAA;AAAA,IAClD;AAEA,aAASsF,IAAiB;AACxB,MAAAtF,EAAc,QAAQ,CAAA,GACtB9C,EAAK,UAAU8C,EAAc,KAAK,GAClC9C,EAAK,wBAAwB8C,EAAc,KAAK;AAAA,IAClD;AAGA,aAASuF,EAAe7H,GAAWM,GAAe;AAChD,UAAI,CAAChB,EAAM,cAAe;AAE1B,YAAMmG,IAAMF,GAAUvF,GAAMM,CAAK;AAGjC,MAAIkF,GAAcxF,GAAMM,CAAK,MAKzBhB,EAAM,8BAEJiD,EAAe,MAAM,SAASkD,CAAG,KAEnClD,EAAe,QAAQA,EAAe,MAAM,OAAO,CAAAuF,MAAKA,MAAMrC,CAAG,GACjEjG,EAAK,aAAaQ,GAAM,IAAI,MAG5BuC,EAAe,QAAQ,CAAC,GAAGA,EAAe,OAAOkD,CAAG,GACpDjG,EAAK,aAAaQ,GAAMyF,CAAG,KAIzBlD,EAAe,MAAM,SAASkD,CAAG,KACnClD,EAAe,QAAQ,CAAA,GACvB/C,EAAK,aAAaQ,GAAM,IAAI,MAE5BuC,EAAe,QAAQ,CAACkD,CAAG,GAC3BjG,EAAK,aAAaQ,GAAMyF,CAAG;AAAA,IAGjC;AAGA,aAASsC,EAAc/H,GAAWM,GAAwB;AACxD,UAAI,CAAChB,EAAM,cAAe,QAAO;AACjC,YAAMmG,IAAMF,GAAUvF,GAAMM,CAAK;AACjC,aAAOiC,EAAe,MAAM,SAASkD,CAAG;AAAA,IAC1C;AAGA,IAAAhE,GAAM,MAAMnC,EAAM,eAAe,CAAC0I,MAAW;AAC3C,UAAIA,MAAW,UAAa,MAAM,QAAQA,CAAM,GAAG;AAEjD,cAAMC,IAAa,IAAI,IAAI3F,EAAc,KAAK,GACxC4F,IAAS,IAAI,IAAIF,CAAM;AAC7B,SAAIC,EAAW,SAASC,EAAO,QAC3B,CAAC,CAAC,GAAGD,CAAU,EAAE,MAAM,CAAAxC,MAAOyC,EAAO,IAAIzC,CAAG,CAAC,OAC/CnD,EAAc,QAAQ,CAAC,GAAG0F,CAAM;AAAA,MAEpC,OAAWA,MAAW,UAAa1F,EAAc,MAAM,SAAS,MAE9DA,EAAc,QAAQ,CAAA;AAAA,IAE1B,GAAG,EAAE,MAAM,IAAM,WAAW,IAAM,GAGlCb,GAAM,MAAMnC,EAAM,eAAe,MAAM;AACrC,MAAA8C,EAAY,QAAQ;AAAA,IACtB,CAAC,GAGDX,GAAM,MAAMnC,EAAM,MAAM,MAAM;AAE5B,MAAKA,EAAM,UACT8C,EAAY,QAAQ,IAGlB9C,EAAM,kBACRiD,EAAe,QAAQ,CAAA;AAAA,IAE3B,GAAG,EAAE,MAAM,IAAM;AAGjB,aAAS4F,GAAiBC,GAAc;AACtC,MAAAhG,EAAY,QAAQgG,GAEhB9I,EAAM,kBACRiD,EAAe,QAAQ,CAAA,IAEzB/C,EAAK,eAAe4I,CAAI;AAAA,IAC1B;AAEA,aAASC,GAAqBC,GAAc;AAC1C,MAAAjG,EAAS,QAAQiG,GACjBlG,EAAY,QAAQ,GAEhB9C,EAAM,kBACRiD,EAAe,QAAQ,CAAA,IAEzB/C,EAAK,oBAAoB8I,CAAI;AAAA,IAC/B;AAGA,IAAA7G,GAAM,MAAMnC,EAAM,aAAa,CAACoC,MAAQ;AACtC,YAAM6G,IAAO,OAAO7G,KAAQ,YAAYA,IAAM,IAAIA,IAAM;AACxD,MAAIU,EAAY,UAAUmG,MAAMnG,EAAY,QAAQmG;AAAA,IACtD,CAAC,GAED9G,GAAM,MAAMnC,EAAM,UAAU,CAACoC,MAAQ;AACnC,YAAM6G,IAAO,OAAO7G,KAAQ,YAAYA,IAAM,IAAIA,IAAM;AACxD,MAAIW,EAAS,UAAUkG,MAAMlG,EAAS,QAAQkG;AAAA,IAChD,CAAC;AAGD,aAASC,KAA0B;AACjC,MAAK9F,EAAe,SAEpB+F,GAAS,MAAM;AACb,cAAMC,IAAgBhG,EAAe,MAAO,sBAAA,GACtCiG,IAAiB,OAAO,aACxBC,IAAeF,EAAc,KAG7BG,IAAgBnG,EAAe,MAAO,cAAc,eAAe,GACnEoG,IAAeD,IAAgBA,EAAc,eAAe;AAGlE,YAAIE,IAAmB;AACvB,YAAIzJ,EAAM,YAAY;AACpB,gBAAM0J,KAAoBtG,EAAe,MAAO,cAAc,cAAc;AAC5E,UAAAqG,IAAmBC,KAAoBA,GAAkB,eAAe;AAAA,QAC1E;AAGA,cAAMC,IAAiBvG,EAAe,MAAO,cAAc,WAAW,GAChEwG,KAAgBD,IAAiBA,EAAe,eAAe,GAM/DE,KAAiBL,IAAeC,IAAmBG,KADtC,IAEbE,KAAkBT,IAAiBC,IAAeO,IAIlDE,KAAY,KAAK,IADL,KACoBD,EAAe,GAG/CE,KAAe5G,EAAe,MAAO,cAAc,yBAAyB;AAClF,QAAI4G,OACoBA,GAAa,eAGfF,KAClB3G,EAAe,QAAQ,GAAG4G,EAAS,OAGnC5G,EAAe,QAAQ;AAAA,MAG7B,CAAC;AAAA,IACH;AAGA,QAAI8G,KAAkB;AACtB,aAASC,KAAmB;AAC1B,MAAI,CAAC7G,EAAU,SAAS,CAACC,EAAY,SAAS2G,MAC1C5G,EAAU,MAAM,eAAeC,EAAY,MAAM,eACnD2G,KAAkB,IAClB5G,EAAU,MAAM,aAAaC,EAAY,MAAM,YAC/C,sBAAsB,MAAM;AAC1B,QAAA2G,KAAkB;AAAA,MACpB,CAAC;AAAA,IAEL;AAGA,aAASE,KAAiB;AACxB,MAAI,CAAC9G,EAAU,SAAS,CAACC,EAAY,SAAS2G,MAC1C3G,EAAY,MAAM,eAAeD,EAAU,MAAM,eACnD4G,KAAkB,IAClB3G,EAAY,MAAM,aAAaD,EAAU,MAAM,YAC/C,sBAAsB,MAAM;AAC1B,QAAA4G,KAAkB;AAAA,MACpB,CAAC;AAAA,IAEL;AAGA,aAASG,KAAyB;AAChC,MAAAjB,GAAS,MAAM;AACb,YAAI,CAAC7F,EAAY,MAAO;AACxB,cAAM+G,IAAO/G,EAAY,OACnBgH,IAAgBD,EAAK,cACrBE,IAAWF,EAAK,cAChBG,IAAYH,EAAK,WACjBI,IAAWH,IAAgBC,IAAW;AAE5C,YADA1F,GAAQ,MAAM,OAAO4F,GACjB,CAACA,EAAU;AAEf,cAAMC,IAAW,IACXC,IAAQJ,IAAWD,GACnBM,KAAchG,GAAU,QAAQA,GAAU,MAAM,eAAe2F,GAC/DM,KAAc,KAAK,IAAIH,GAAU,KAAK,MAAME,KAAcD,CAAK,CAAC;AACtE,QAAA9F,GAAQ,MAAM,cAAcgG;AAE5B,cAAMC,KAAc,KAAK,IAAI,GAAGF,KAAcC,EAAW,GACnDE,KAAe,KAAK,IAAI,GAAGT,IAAgBC,CAAQ;AACzD,QAAA1F,GAAQ,MAAM,WAAW,KAAK,IAAIiG,IAAa,KAAK,MAAON,IAAYO,KAAgBD,EAAW,CAAC;AAAA,MACrG,CAAC;AAAA,IACH;AAEA,aAASE,GAAiBC,GAAe;AACvC,UAAI,CAACnG,KAAc,CAACxB,EAAY,SAAS,CAACsB,GAAU,MAAO;AAC3D,MAAAqG,EAAE,eAAA;AACF,YAAML,IAAchG,GAAU,MAAM,cAC9BkG,IAAc,KAAK,IAAI,GAAGF,IAAc/F,GAAQ,MAAM,WAAW,GACjEwF,IAAO/G,EAAY,OACnBgH,IAAgBD,EAAK,cACrBE,IAAWF,EAAK,cAChBU,IAAe,KAAK,IAAI,GAAGT,IAAgBC,CAAQ,GAEnDW,MADSD,EAAE,UAAUlG,MACG,KAAK,IAAI,GAAG+F,CAAW,IAAKC;AAC1D,MAAAV,EAAK,YAAY,KAAK,IAAIU,GAAc,KAAK,IAAI,GAAG/F,IAAqBkG,EAAW,CAAC,GACrFd,GAAA;AAAA,IACF;AAEA,aAASe,KAAiB;AACxB,MAAArG,IAAa,IACb,OAAO,oBAAoB,aAAakG,EAAgB,GACxD,OAAO,oBAAoB,WAAWG,EAAc;AAAA,IACtD;AAsBA,aAASC,KAA0B;AACjC,MAAAjC,GAAS,MAAM;;AAEb,YAAI3F,EAAgB,MAAM,WAAWxD,EAAM,QAAQ,UAAUwD,EAAgB,MAAM,MAAM,CAAA6H,MAAK,CAAC,CAACA,CAAC;AAC/F;AAEF,cAAM9E,IAAmB,CAAA;AAEzB,QAAAvG,EAAM,QAAQ,QAAQ,CAACyE,GAAKzD,MAAU;AACpC,gBAAM0G,IAAkBhD,EAAeD,EAAI,KAAK;AAChD,cAAIiD;AACF,YAAAnB,EAAO,KAAKmB,CAAe,GAC3BjE,EAAe,MAAMgB,EAAI,GAAG,IAAIiD;AAAA,mBACvBjE,EAAe,MAAMgB,EAAI,GAAG;AACrC,YAAA8B,EAAO,KAAK9C,EAAe,MAAMgB,EAAI,GAAG,CAAC;AAAA,eACpC;AACL,kBAAM6G,KAAW9H,EAAgB,MAAMxC,CAAK;AAC5C,gBAAIsK;AACF,cAAA/E,EAAO,KAAK+E,EAAQ,GACpB7H,EAAe,MAAMgB,EAAI,GAAG,IAAI6G;AAAA,iBAC3B;AACL,oBAAM3D,KAAYhD,EAAA;AAClB,cAAA4B,EAAO,KAAKoB,EAAS,GACrBlE,EAAe,MAAMgB,EAAI,GAAG,IAAIkD;AAAA,YAClC;AAAA,UACF;AAAA,QACF,CAAC;AAED,cAAM4D,KAAWtK,IAAAsC,EAAa,UAAb,gBAAAtC,EAAoB,cAAc;AACnD,YAAIsK,GAAU;AAEZ,gBAAMC,IAAaxL,EAAM,aAAa,IAAI,GACpCyL,IAAM,MAAM,KAAKF,EAAS,QAAQ;AACxC,mBAAS9E,IAAI,GAAGA,IAAIzG,EAAM,QAAQ,QAAQyG;AACxC,gBAAI,CAACF,EAAOE,CAAC,GAAG;AACd,oBAAMiF,KAAKD,EAAID,IAAa/E,CAAC;AAC7B,kBAAIiF,MAAMA,GAAG,cAAc,GAAG;AAC5B,sBAAMC,KAAW,GAAGD,GAAG,WAAW;AAClC,gBAAAnF,EAAOE,CAAC,IAAIkF,IACZlI,EAAe,MAAMzD,EAAM,QAAQyG,CAAC,EAAE,GAAG,IAAIkF;AAAA,cAC/C,OAAO;AACL,sBAAMhE,KAAYhD,EAAA;AAClB,gBAAA4B,EAAOE,CAAC,IAAIkB,IACZlE,EAAe,MAAMzD,EAAM,QAAQyG,CAAC,EAAE,GAAG,IAAIkB;AAAA,cAC/C;AAAA,YACF;AAAA,QAEJ;AAEE,mBAASlB,IAAI,GAAGA,IAAIF,EAAO,QAAQE;AACjC,gBAAI,CAACF,EAAOE,CAAC,GAAG;AACd,oBAAMmF,IAASnI,EAAe,QAAMoI,IAAA7L,EAAM,QAAQyG,CAAC,MAAf,gBAAAoF,EAAkB,QAAO,EAAE;AAC/D,cAAAtF,EAAOE,CAAC,IAAImF,KAAUpI,EAAgB,MAAMiD,CAAC,KAAK,QAC9CzG,EAAM,QAAQyG,CAAC,MACjBhD,EAAe,MAAMzD,EAAM,QAAQyG,CAAC,EAAE,GAAG,IAAIF,EAAOE,CAAC;AAAA,YAEzD;AAGJ,QAAAjD,EAAgB,QAAQ+C;AAAA,MAC1B,CAAC;AAAA,IACH;AAGA,aAASuF,KAAe;AACtB,MAAA5C,GAAA,GACA6C,GAAA;AAAA,IACF;AAGA,IAAA5J,GAAM,MAAMnC,EAAM,MAAM,MAAM;AAC5B,MAAAmJ,GAAS,MAAM;AACb,QAAAD,GAAA,GAEAgB,GAAA,GACA6B,GAAA,GACA7I,EAAa,MAAM,MAAA;AAAA,MACrB,CAAC;AAAA,IACH,GAAG,EAAE,MAAM,IAAM,GAGjBf,GAAM,CAACW,GAAaC,CAAQ,GAAG,MAAM;AACnC,MAAAoG,GAAS,MAAM;AACb,QAAAD,GAAA,GAEAgB,GAAA,GACA6B,GAAA;AAAA,MACF,CAAC;AAAA,IACH,CAAC,GAGD5J,GAAM,MAAMnC,EAAM,SAAS,MAAM;AAC/B,YAAMgM,IAAuB,CAAA,GACvBC,IAAkC,EAAE,GAAGxI,EAAe,MAAA;AAE5D,MAAAzD,EAAM,QAAQ,QAAQ,CAACyE,GAAKyH,MAAQ;AAClC,cAAMxE,IAAkBhD,EAAeD,EAAI,KAAK;AAChD,QAAIiD,KACFsE,EAAW,KAAKtE,CAAe,GAC/BuE,EAAQxH,EAAI,GAAG,IAAIiD,KACVuE,EAAQxH,EAAI,GAAG,IACxBuH,EAAW,KAAKC,EAAQxH,EAAI,GAAG,CAAC,IACvBjB,EAAgB,MAAM0I,CAAG,KAClCF,EAAW,KAAKxI,EAAgB,MAAM0I,CAAG,CAAC,GAC1CD,EAAQxH,EAAI,GAAG,IAAIjB,EAAgB,MAAM0I,CAAG,KAE5CF,EAAW,KAAK,EAAE;AAAA,MAEtB,CAAC;AAGD,YAAMG,IAAc,IAAI,IAAInM,EAAM,QAAQ,IAAI,CAAAyE,MAAOA,EAAI,GAAG,CAAC;AAC7D,aAAO,KAAKwH,CAAO,EAAE,QAAQ,CAAC9F,MAAQ;AACpC,QAAKgG,EAAY,IAAIhG,CAAG,KACtB,OAAO8F,EAAQ9F,CAAG;AAAA,MAEtB,CAAC,GAED1C,EAAe,QAAQwI,GACvBzI,EAAgB,QAAQwI,GAExB7C,GAAS,MAAM;AACb,QAAAiC,GAAA,GACAlB,GAAA,GACA6B,GAAA;AAAA,MACF,CAAC;AAAA,IACH,GAAG,EAAE,MAAM,IAAM,GAGjB5J,GAAM,MAAMa,EAAc,OAAO,MAAM;AACrC,MAAAmG,GAAS,MAAM;AACb,QAAAD,GAAA,GACA6C,GAAA;AAAA,MACF,CAAC;AAAA,IACH,GAAG,EAAE,MAAM,IAAM,GAGjB5J,GAAM,MAAMnC,EAAM,SAAS,MAAM;AAC/B,MAAAmJ,GAAS,MAAM;AACb,QAAA4C,GAAA;AAAA,MACF,CAAC;AAAA,IACH,CAAC,GAGDK,GAAU,MAAM;;AACd,MAAAjD,GAAS,MAAM;AACb,QAAAD,GAAA,GACAkC,GAAA,GACAW,GAAA,GACA3B,GAAA;AAAA,MACF,CAAC,GACD,OAAO,iBAAiB,UAAU0B,EAAY,GAC9C,OAAO,iBAAiB,UAAUA,IAAc,EAAI,IAEpD7K,IAAAqC,EAAY,UAAZ,QAAArC,EAAmB,iBAAiB,UAAU,MAAM;AAClD,QAAAiJ,GAAA,GACAE,GAAA,GAEA2B,GAAA;AAAA,MACF,GAAG,EAAE,SAAS,QAEdF,IAAAxI,EAAU,UAAV,QAAAwI,EAAiB,iBAAiB,UAAU,MAAM;AAChD,QAAA1B,GAAA;AAAA,MACF,GAAG,EAAE,SAAS,OAEdhB,GAAS,MAAMe,IAAkB,GAG7B5G,EAAY,SAAS,OAAO,iBAAmB,QACjD+I,KAAiB,IAAI,eAAe,MAAM;AACxC,QAAAN,GAAA;AAAA,MACF,CAAC,GACDM,GAAe,QAAQ/I,EAAY,KAAK;AAAA,IAE5C,CAAC,GAEDgJ,GAAY,MAAM;;AAChB,aAAO,oBAAoB,UAAUR,EAAY,GACjD,OAAO,oBAAoB,UAAUA,IAAc,EAAI,IACvD7K,IAAAqC,EAAY,UAAZ,QAAArC,EAAmB,oBAAoB,UAAUiJ,MACjD2B,IAAAxI,EAAU,UAAV,QAAAwI,EAAiB,oBAAoB,UAAU1B,KAC/C,OAAO,oBAAoB,aAAaa,EAAgB,GACxD,OAAO,oBAAoB,WAAWG,EAAc,GAEhDkB,OACFA,GAAe,WAAA,GACfA,KAAiB;AAAA,IAErB,CAAC;AAGD,QAAIE,KAAqB;AACzB,aAASR,KAA8B;AACrC,MAAI,CAAC1I,EAAU,SAAS,CAACC,EAAY,SAGrC,sBAAsB,MAAM;AAC1B,YAAI,CAACD,EAAU,SAAS,CAACC,EAAY,MAAO;AAE5C,cAAM+G,IAAO/G,EAAY,OAGnBkJ,IAAwB,KAAK,KAAKnC,EAAK,cAAcA,EAAK,WAAW;AAM3E,YAHApF,EAAe,QAAQuH,GAGnBA,MAA0BD,IAAoB;AAChD,UAAAA,KAAqBC;AACrB,gBAAMC,IAAcpJ,EAAU,MAAM,cAAc,QAAQ,GACpDqJ,IAAYnJ,EAAa;AAE/B,UAAIkJ,KAAeC,MAEjBrJ,EAAU,MAAM,MAAM,eAAe,OACrCoJ,EAAY,MAAM,QAAQ,IAC1BA,EAAY,MAAM,cAAc,IAS5BD,IAAwB,KAG1BnJ,EAAU,MAAM,MAAM,eAAe,GAAGmJ,CAAqB,MAG7DC,EAAY,MAAM,QAAQ,QAG1BA,EAAY,MAAM,cAAc,IAAID,CAAqB,SAEzDnJ,EAAU,MAAM,MAAM,eAAe,OACrCoJ,EAAY,MAAM,QAAQ,QAC1BA,EAAY,MAAM,cAAc;AAAA,QAGtC;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAIJ,KAAwC;AAG5C,WAAAC,GAAY,MAAM;AAChB,MAAA5I,EAAiB,MAAM,MAAA;AAAA,IACzB,CAAC;;kBAnqCC9C,EAoLM,OAAA;AAAA,QApLD,OAAM;AAAA,iBAAuB;AAAA,QAAJ,KAAIwC;AAAA,MAAA;QAEhCuJ,GASaC,IAAA,EATD,MAAK,gBAAY;AAAA,sBAC3B,MAOM;AAAA,YAPsB5J,EAAA,MAAc,UAAU/C,EAAA,mBAApDU,KAAAC,EAOM,OAPNiM,IAOM;AAAA,cANJ1L,EAA6D,OAA7DO,IAAuB,YAAOsB,EAAA,MAAc,MAAM,IAAG,MAAE,CAAA;AAAA,cACvD7B,EAIM,OAJNN,IAIM;AAAA,gBAHJc,GAEOC,EAAA,QAAA,gBAAA;AAAA,kBAFoB,eAAeoB,EAAA;AAAA,kBAAgB,gBAAAsF;AAAA,gBAAA,GAA1D,MAEO;AAAA,kBADLqE,GAAwEG,GAAA;AAAA,oBAA/D,MAAK;AAAA,oBAAQ,OAAM;AAAA,oBAAO,SAAOxE;AAAA,kBAAA;gCAAgB,MAAI,CAAA,GAAAhH,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,yBAAJ,QAAI,EAAA;AAAA,oBAAA;;;;;;;;;QAOtEH,EAqKM,OArKN4L,IAqKM;AAAA,UAnKoCpJ,EAAA,SAAxChD,EAAA,GAAAC,EAsCM,OAtCNQ,IAsCM;AAAA,YArCJD,EAoCS,UAAA;AAAA,cAnCP,OAAK0B,EAAA,CAAC,wBAAsB,EAAA,eACHe,EAAA,MAAA,CAAgB,CAAA;AAAA,cACxC,SAAOS;AAAA,cACP,OAAOT,EAAA,QAAgB,aAAA;AAAA,YAAA;cAGhBA,EAAA,SADRjD,KAAAC,EAcM,OAdNW,IAcM,CAAA,GAAAD,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAPJH,EAME,QAAA;AAAA,kBALA,GAAE;AAAA,kBACF,QAAO;AAAA,kBACP,gBAAa;AAAA,kBACb,kBAAe;AAAA,kBACf,mBAAgB;AAAA,gBAAA;uBAGpBR,KAAAC,EAcM,OAdNY,IAcM,CAAA,GAAAF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAPJH,EAME,QAAA;AAAA,kBALA,GAAE;AAAA,kBACF,QAAO;AAAA,kBACP,gBAAa;AAAA,kBACb,kBAAe;AAAA,kBACf,mBAAgB;AAAA,gBAAA;;;;UAMxBA,EAmCM,OAAA;AAAA,YAnCD,OAAM;AAAA,qBAAmB;AAAA,YAAJ,KAAIkC;AAAA,UAAA;YAC5BlC,EAiCQ,SAjCR6L,IAiCQ;AAAA,cAhCN7L,EAKW,YAAA,MAAA;AAAA,gBAJEnB,EAAM,cAAjBW,EAAA,GAAAC,EAAqE,OAArEqM,EAAqE;gBAC1DhN,EAAA,cAAXU,EAAA,GAAAC,EAA+D,OAA/DsM,EAA+D;iBAC/DvM,EAAA,EAAA,GAAAC,EACmGE,IAAA,MAAAC,GAD3Ed,EAAA,SAAO,CAAlBwE,GAAKgC,YAAlB7F,EACmG,OAAA;AAAA,kBADjE,KAAK6D,EAAI;AAAA,kBACrC,OAAK0I,GAAA,EAAA,OAAW3J,QAAgBiD,CAAC,KAAK,QAAS,UAAYjD,EAAA,MAAgBiD,CAAC,KAAA,QAAA;AAAA,gBAAA;;cAEpFtF,EAyBQ,SAAA,MAAA;AAAA,gBAxBNA,EAuBK,MAAA,MAAA;AAAA,kBAtBOnB,EAAM,cAAhBW,EAAA,GAAAC,EAAoD,MAApDwM,EAAoD;kBAE1CnN,EAAA,cAAVU,EAAA,GAAAC,EAUK,MAVLyM,IAUK;AAAA,oBATHlM,EAQM,OARNmM,IAQM;AAAA,sBAPJnM,EAKE,SAAA;AAAA,wBAJA,MAAK;AAAA,wBACJ,SAAS4E,EAAA;AAAA,wBACT,UAAUK,EAAA;AAAA,wBACV,UAAQgC;AAAA,sBAAA;sBAECpF,EAAA,MAAc,SAAM,KAAhCrC,EAAA,GAAAC,EAA4F,QAA5F2M,IAA4F9L,GAA9BuB,EAAA,MAAc,MAAM,GAAA,CAAA;;;mBAItFrC,EAAA,EAAA,GAAAC,EAOKE,IAAA,MAAAC,GAN0Bd,EAAA,SAAO,CAA5BoH,GAAQmG,YADlB5M,EAOK,MAAA;AAAA,oBALF,KAAKyG,EAAO;AAAA,oBACZ,OAAKxE,EAAEuE,GAAeC,GAAM,EAAA,CAAA;AAAA,oBAC5B,OAAK8F,GAAE3F,GAAeH,GAAQmG,GAAQ,EAAA,CAAA;AAAA,kBAAA,GAEpC/L,GAAA4F,EAAO,KAAK,GAAA,CAAA;;;;;UAQzBlG,EAuEM,OAAA;AAAA,YAvED,OAAK0B,EAAA,CAAC,mBAAiB,EAAA,cAA2C5C,EAAA,sBAAsB6F,EAAA,MAAU,UAAM,CAAK7F,EAAA,QAAA,CAAO,CAAA;AAAA,qBAAxF;AAAA,YAAJ,KAAIqD;AAAA,YAA6F,uBAAoBH,EAAA,OAAc;AAAA,UAAA;YAEnJlD,EAAA,WAAXU,KAAAC,EAGM,OAHN6M,IAGM,CAAA,GAAAnM,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAFJH,EAAmC,OAAA,EAA9B,OAAM,kBAAA,GAAiB,MAAA,EAAA;AAAA,cAC5BA,EAAsC,OAAA,EAAjC,OAAM,eAAA,GAAe,UAAM,EAAA;AAAA,YAAA;aAItB2E,EAAA,MAAU,UAAM,CAAK7F,EAAA,WAAjCU,KAAAC,EAIM,OAJN8M,IAIM;AAAA,cAHJ/L,GAEOC,uBAFP,MAEO;AAAA,sBADF3B,EAAA,SAAS,GAAA,CAAA;AAAA,cAAA;;YAIhBkB,EAwDQ,SAAA;AAAA,cAxDD,OAAK0B,EAAA,CAAC,SAAO,EAAA,iBAA4B5C,EAAA,QAAA,CAAO,CAAA;AAAA,uBAAQ;AAAA,cAAJ,KAAIsD;AAAA,YAAA;cAC7DpC,EAKW,YAAA,MAAA;AAAA,gBAJEnB,EAAM,cAAjBW,EAAA,GAAAC,EAAqE,OAArE+M,EAAqE;gBAC1D1N,EAAA,cAAXU,EAAA,GAAAC,EAA+D,OAA/DgN,EAA+D;iBAC/DjN,EAAA,EAAA,GAAAC,EACmGE,IAAA,MAAAC,GAD3Ed,EAAA,SAAO,CAAlBwE,GAAKgC,YAAlB7F,EACmG,OAAA;AAAA,kBADjE,KAAK6D,EAAI;AAAA,kBACrC,OAAK0I,GAAA,EAAA,OAAW3J,QAAgBiD,CAAC,KAAK,QAAS,UAAYjD,EAAA,MAAgBiD,CAAC,KAAA,QAAA;AAAA,gBAAA;;cAEpFtF,EAgDQ,SAAA,MAAA;AAAA,iBA/CNR,EAAA,EAAA,GAAAC,EA8CWE,IAAA,MAAAC,GA9CuB+E,EAAA,OAAS,CAAzBpF,GAAMM;uBAA2BiF,GAAUvF,GAAMM,CAAK;AAAA,gBAAA;kBACtEG,EAmCK,MAAA;AAAA,oBAlCF,OAAK0B,EAAA,EAAA,gBAAoB4F,EAAc/H,GAAMM,CAAK,GAAA;AAAA,oBAClD,SAAK,CAAAE,MAAEqH,EAAe7H,GAAMM,CAAK;AAAA,kBAAA;oBAExBhB,EAAM,cAAhBW,EAAA,GAAAC,EAIK,MAJLiN,IAIK;AAAA,sBAHH1M,EAES,UAAA;AAAA,wBAFD,OAAM;AAAA,wBAAa,MAAK;AAAA,wBAAU,kBAAY8F,GAAgBhB,GAAUvF,GAAMM,CAAK,CAAA,GAAA,CAAA,MAAA,CAAA;AAAA,sBAAA;wBACzFG,EAA4F,QAAA;AAAA,0BAArF,sCAAoC6F,GAAcf,GAAUvF,GAAMM,CAAK,CAAA,GAAA,CAAA;AAAA,wBAAA;;;oBAIxEf,EAAA,mBAAVW,EAQK,MAAA;AAAA;sBARiB,OAAM;AAAA,sBAAc,2BAAD,MAAA;AAAA,sBAAA,GAAW,CAAA,MAAA,CAAA;AAAA,oBAAA;sBAClDO,EAME,SAAA;AAAA,wBALA,MAAK;AAAA,wBACJ,OAAO8E,GAAUvF,GAAMM,CAAK;AAAA,wBAC5B,SAASgC,QAAc,SAASiD,GAAUvF,GAAMM,CAAK,CAAA;AAAA,wBACrD,UAAUkF,GAAcxF,GAAMM,CAAK;AAAA,wBACnC,mBAAagH,GAAa/B,GAAUvF,GAAMM,CAAK,CAAA,GAAA,CAAA,MAAA,CAAA;AAAA,sBAAA;;qBAIpDL,EAAA,EAAA,GAAAC,EAcKE,IAAA,MAAAC,GAb0Bd,EAAA,SAAO,CAA5BoH,GAAQmG,aADlB5M,EAcK,MAAA;AAAA,sBAZF,KAAKyG,EAAO;AAAA,sBACZ,OAAKxE,EAAEuE,GAAeC,CAAM,CAAA;AAAA,sBAC5B,OAAK8F,GAAE3F,GAAeH,GAAQmG,IAAQ,EAAA,CAAA;AAAA,oBAAA;sBAEvC7L,GAOOC,EAAA,QAAA,QANUyF,EAAO,GAAG,IAAA;AAAA,wBACxB,MAAA3G;AAAA,wBACA,OAAOmF,GAAenF,GAAM2G,EAAO,GAAG;AAAA,wBACtC,OAAArG;AAAA,sBAAA,GAJH,MAOO;AAAA,8BADF+G,GAAgBrH,GAAM2G,CAAM,CAAA,GAAA,CAAA;AAAA,sBAAA;;;kBAK7BrH,EAAM,cAAcgH,GAAcf,GAAUvF,GAAMM,CAAK,CAAA,UAD/DJ,EAQK,MAAA;AAAA,oBANF,KAAG,GAAKqF,GAAUvF,GAAMM,CAAK,CAAA;AAAA,oBAC9B,OAAM;AAAA,kBAAA;oBAENG,EAEK,MAAA;AAAA,sBAFA,SAASoE,EAAA;AAAA,sBAAmB,OAAM;AAAA,oBAAA;sBACrC5D,GAAkDC,EAAA,QAAA,UAAA;AAAA,wBAA7B,MAAAlB;AAAA,wBAAa,OAAAM;AAAA,sBAAA;;;;;;;UAWtCf,EAAA,mBAFR6N,GAUEC,GAAA;AAAA;YATA,OAAM;AAAA,YAEE,gBAAcjL,EAAA;AAAA,2DAAAA,EAAW,QAAA5B;AAAA,YACzB,aAAW6B,EAAA;AAAA,wDAAAA,EAAQ,QAAA7B;AAAA,YAC1B,SAASlB,EAAM;AAAA,YACf,gBAAcqG,GAAA;AAAA,YACd,qBAAmBpG,EAAA;AAAA,YACnB,cAAa4I;AAAA,YACb,kBAAkBE;AAAA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACF3B,UAAM/I,IAAQC,GAeRC,IAAOC,GASP6N,IAASlM,EAAI,EAAK,GAClBmM,IAAenM,EAAI,EAAE,GACrBoM,IAAmBpM,EAAA,GACnBqM,IAAiBrM,EAAA,GACjBsM,IAAkBtM,EAAA,GAClBuM,IAAmBvM,EAAI,EAAK,GAC5BwM,IAAexM,EAAA,GACfyM,IAAczM,EAAI,EAAE,GAGpB0M,IAAiBjO,EAAS,MAC1BP,EAAM,WAAiB,OACpBA,EAAM,QAAQ,KAAK,CAAAyO,MAAUC,EAAeD,CAAM,MAAMzO,EAAM,UAAU,KAAK,IACrF,GAEK2O,IAAkBpO,EAAS,MAAM;AACrC,UAAI,CAACP,EAAM,SAAU,QAAO,CAAA;AAC5B,YAAM4O,IAAS,MAAM,QAAQ5O,EAAM,UAAU,IAAIA,EAAM,aAAa,CAAA;AACpE,aAAOA,EAAM,QAAQ,OAAO,CAAAyO,MAAUG,EAAO,SAASF,EAAeD,CAAM,CAAC,CAAC;AAAA,IAC/E,CAAC,GAEKI,IAAgBtO,EAAS,MAAM;AACnC,UAAIP,EAAM,UAAU;AAClB,cAAMwF,IAAQmJ,EAAgB,MAAM;AACpC,eAAInJ,MAAU,IAAU,KACjB,OAAOA,CAAK;AAAA,MACrB;AACA,aAAOgJ,EAAe,QAAQM,EAAeN,EAAe,KAAK,IAAI;AAAA,IACvE,CAAC,GAEKO,IAAmBxO,EAAS,MAAM;AACtC,UAAI,CAACP,EAAM,WAAY,QAAOA,EAAM;AACpC,YAAMgP,IAAQT,EAAY,MAAM,KAAA,EAAO,YAAA;AACvC,aAAKS,IACEhP,EAAM,QAAQ,OAAO,CAACiP,MAAa;AACxC,cAAMC,IAAQJ,EAAeG,CAAG;AAChC,eAAO,OAAOC,CAAK,EAAE,YAAA,EAAc,SAASF,CAAK;AAAA,MACnD,CAAC,IAJkBhP,EAAM;AAAA,IAK3B,CAAC,GAgBKmP,IAAsB5O,EAAS,MAAM;;AACzC,YAAMkH,IAAgC,EAAE,UAAU,SAAS,QAAQ,OAAA,GAC7D2H,IAAUjB,EAAe;AAC/B,UAAI,CAACiB,EAAS,QAAO3H;AACrB,YAAM4H,IAAOD,EAAQ,sBAAA,GACflK,MAASjE,IAAAmN,EAAgB,UAAhB,gBAAAnN,EAAuB,wBAAwB,UAASoO,EAAK;AAC5E,aAAA5H,EAAM,OAAO,GAAG4H,EAAK,IAAI,MACzB5H,EAAM,QAAQ,GAAGvC,CAAK,MAClBmJ,EAAiB,SAEnB5G,EAAM,SAAS,GAAG,OAAO,cAAc4H,EAAK,MAAM,CAAC,MACnD5H,EAAM,MAAM,UAEZA,EAAM,MAAM,GAAG4H,EAAK,SAAS,CAAC,MAEzB5H;AAAA,IACT,CAAC;AAGD,aAAS6H,IAA4B;AACnC,MAAI,CAACtB,EAAO,SAAS,CAACG,EAAe,SAErChF,GAAS,MAAM;AACb,cAAMiG,IAAUjB,EAAe;AAC/B,YAAI,CAACiB,EAAS;AAEd,cAAMG,IAAcH,EAAQ,sBAAA,GACtB/F,IAAiB,OAAO,aACxBmG,IAAiB,KAGjBC,IAAiBF,EAAY,SAASC,IAAiB,GAGvDE,IAAcH,EAAY,MAAMC,IAAiB,GAGjDG,KAAiBF,KAAkBpG,IAAiB,IACpDuG,KAAYF,KAAe;AAEjC,QAAArB,EAAiB,QAAQ,CAACsB,MAAkBC;AAAA,MAC9C,CAAC;AAAA,IACH;AAGA,aAASlB,EAAeD,GAAkB;AACxC,aAAI,OAAOA,KAAW,YAAYA,MAAW,OACpCA,EAAOzO,EAAM,QAAQ,IAEvByO;AAAA,IACT;AAEA,aAASK,EAAeL,GAAqB;AAC3C,aAAI,OAAOA,KAAW,YAAYA,MAAW,OACpCA,EAAOzO,EAAM,QAAQ,KAAK,OAAOyO,EAAOzO,EAAM,QAAQ,CAAC,IAEzD,OAAOyO,CAAM;AAAA,IACtB;AAEA,aAASoB,GAAapB,GAAazN,GAAgC;AACjE,aAAI,OAAOyN,KAAW,YAAYA,MAAW,QAAQA,EAAO,OAAO,SAC1DA,EAAO,KAETC,EAAeD,CAAM,KAAKzN;AAAA,IACnC;AAEA,aAAS8O,EAAWrB,GAAsB;AACxC,aAAIzO,EAAM,YACO,MAAM,QAAQA,EAAM,UAAU,IAAIA,EAAM,aAAa,CAAA,GACtD,SAAS0O,EAAeD,CAAM,CAAC,IAExCC,EAAeD,CAAM,MAAMzO,EAAM;AAAA,IAC1C;AAEA,aAAS+P,GAAiBtB,GAAsB;AAC9C,aAAI,OAAOA,KAAW,YAAYA,MAAW,OACpCA,EAAOzO,EAAM,WAAW,MAAM,KAEhC;AAAA,IACT;AAEA,aAASgQ,KAAiB;AACxB,MAAIhQ,EAAM,aACVgO,EAAO,QAAQiC,EAAA,IAAkBC,EAAA;AAAA,IACnC;AAEA,aAASA,IAAe;AACtB,MAAIlQ,EAAM,aACVgO,EAAO,QAAQ,IACf7E,GAAS,MAAM;AACb,QAAAmG,EAAA,GACAa,GAAA,GACInQ,EAAM,cAAcsO,EAAa,UACnCA,EAAa,MAAM,MAAA,GAEnBC,EAAY,QAAQ;AAAA,MAExB,CAAC;AAAA,IACH;AAEA,aAAS0B,IAAgB;AACvB,MAAAjC,EAAO,QAAQ,IACfC,EAAa,QAAQ,IACrBI,EAAiB,QAAQ,IACrBrO,EAAM,eACRuO,EAAY,QAAQ;AAAA,IAExB;AAEA,aAAS6B,EAAa3B,GAAa4B,GAAgB;AACjD,UAAIN,GAAiBtB,CAAM,EAAG;AAE9B,YAAM7I,IAAQ8I,EAAeD,CAAM;AAEnC,UAAIzO,EAAM,UAAU;AAClB,cAAMsQ,IAAgB,MAAM,QAAQtQ,EAAM,UAAU,IAAI,CAAC,GAAGA,EAAM,UAAU,IAAI,CAAA,GAC1EuQ,IAAc7B,EAAeD,CAAM,GACnC+B,IAAaF,EAAc,QAAQC,CAAW;AAEpD,QAAIC,IAAa,KAEfF,EAAc,OAAOE,GAAY,CAAC,IAGlCF,EAAc,KAAKC,CAAW,GAGhCrQ,EAAK,qBAAqBoQ,CAAa,GACvCpQ,EAAK,UAAUoQ,GAAe3B,EAAgB,KAAK;AAAA,MAErD;AACE,QAAAzO,EAAK,qBAAqB0F,CAAK,GAC/B1F,EAAK,UAAU0F,GAAO6I,CAAM,GAC5BwB,EAAA;AAAA,IAEJ;AAEA,aAASQ,IAAc;AACrB,UAAI,CAACzQ,EAAM,aAAaA,EAAM,SAAU;AACxC,YAAM0Q,IAAU1Q,EAAM,WAAYA,EAAM,YAAY,SAAYA,EAAM,UAAU,CAAA,IAAMA,EAAM;AAC5F,MAAAE,EAAK,qBAAqBwQ,CAAO,GACjCxQ,EAAK,UAAUwQ,GAAS1Q,EAAM,WAAW,CAAA,IAAK,IAAI,GAClDE,EAAK,OAAO,GAEPF,EAAM,YACTiQ,EAAA;AAAA,IAEJ;AAEA,aAASU,GAAUlC,GAAamC,GAAc;AAE5C,UADAA,EAAM,gBAAA,GACF5Q,EAAM,YAAY,CAACA,EAAM,SAAU;AAEvC,YAAMsQ,IAAgB,MAAM,QAAQtQ,EAAM,UAAU,IAAI,CAAC,GAAGA,EAAM,UAAU,IAAI,CAAA,GAC1EuQ,IAAc7B,EAAeD,CAAM,GACnCzN,IAAQsP,EAAc,QAAQC,CAAW;AAE/C,MAAIvP,IAAQ,OACVsP,EAAc,OAAOtP,GAAO,CAAC,GAC7Bd,EAAK,qBAAqBoQ,CAAa,GACvCpQ,EAAK,UAAUoQ,GAAe3B,EAAgB,KAAK;AAAA,IAEvD;AAEA,aAASkC,GAAUC,GAAe;AAChC,UAAI,CAAC/B,EAAiB,SAASA,EAAiB,MAAM,WAAW,GAAG;AAClE,QAAAd,EAAa,QAAQ;AACrB;AAAA,MACF;AACA,UAAIhF,IAAOgF,EAAa;AACxB,YAAM8C,IAAQhC,EAAiB,MAAM;AAErC,MAAI9F,MAAS,KACXA,IAAO6H,IAAQ,IAAI,IAAIC,IAAQ,IAE/B9H,KAAQA,IAAO6H,IAAQC,KAASA;AAGlC,UAAIC,IAAW;AACf,aAAOA,IAAWD,KAAShB,GAAiBhB,EAAiB,MAAM9F,CAAI,CAAC;AACtE,QAAAA,KAAQA,IAAO6H,IAAQC,KAASA,GAChCC;AAEF,MAAA/C,EAAa,QAAQ+C,KAAYD,IAAQ,KAAK9H,GAC9CgI,EAAA;AAAA,IACF;AAEA,aAASC,IAAgB;AACvB,UAAIjD,EAAa,QAAQ,EAAG;AAC5B,YAAMQ,IAASM,EAAiB,MAAMd,EAAa,KAAK;AACxD,MAAI,CAACQ,KAAUsB,GAAiBtB,CAAM,KACtC2B,EAAa3B,GAAQR,EAAa,KAAK;AAAA,IACzC;AAEA,aAASkC,KAAmB;AAC1B,UAAI,CAACjC,EAAiB,MAAO;AAE7B,YAAMiD,IAAkBjD,EAAiB,MAAM,cAAc,4BAA4B;AACzF,MAAIiD,KACFA,EAAgB,eAAe,EAAE,OAAO,UAAA,CAAW;AAAA,IAEvD;AAEA,aAASF,IAAsB;AAE7B,UADI,CAAC/C,EAAiB,SAClBD,EAAa,QAAQ,EAAG;AAE5B,YAAMmD,IADclD,EAAiB,MAAM,iBAAiB,kBAAkB,EACvDD,EAAa,KAAK;AACzC,MAAImD,KAAIA,EAAG,eAAe,EAAE,OAAO,WAAW;AAAA,IAChD;AAEA,aAASC,EAAmBT,GAAc;AACxC,YAAMtO,IAASsO,EAAM;AACrB,OAAI,CAACxC,EAAgB,SAAS,CAACA,EAAgB,MAAM,SAAS9L,CAAM,MAClE2N,EAAA;AAAA,IAEJ;AAGA,IAAA9N,GAAM,MAAMnC,EAAM,YAAY,MAAM;AAClC,MAAAiO,EAAa,QAAQ;AAAA,IACvB,CAAC;AAGD,aAASnC,IAAe;AACtB,MAAIkC,EAAO,SACTsB,EAAA;AAAA,IAEJ;AAGA,WAAAlD,GAAU,MAAM;AACd,eAAS,iBAAiB,SAASiF,CAAkB,GACrD,OAAO,iBAAiB,UAAUvF,CAAY,GAC9C,OAAO,iBAAiB,UAAUA,GAAc,EAAI;AAAA,IACtD,CAAC,GAEDQ,GAAY,MAAM;AAChB,eAAS,oBAAoB,SAAS+E,CAAkB,GACxD,OAAO,oBAAoB,UAAUvF,CAAY,GACjD,OAAO,oBAAoB,UAAUA,GAAc,EAAI;AAAA,IACzD,CAAC,mBA9eClL,EAiJM,OAAA;AAAA,MAjJD,OAAKiC,EAAA,CAAC,WAAS,EAAA,qBAAgC5C,EAAA,uBAAuBA,EAAA,IAAI,EAAA,GAAA,GAAA,CAAA,CAAA;AAAA,MAAc,mBAAgBA,EAAA,OAAK;AAAA,eAAQ;AAAA,MAAJ,KAAImO;AAAA,IAAA;MACxHjN,EA6FM,OAAA;AAAA,iBA5FA;AAAA,QAAJ,KAAIgN;AAAA,QACJ,UAAM,oBAAkB;AAAA,oCACqBH,EAAA;AAAA,wCAA8C/N,EAAA;AAAA,qCAA6CA,EAAA;AAAA,QAAA;QAKvI,eAAwB+P,IAAc,CAAA,WAAA,MAAA,CAAA;AAAA,QACtC,WAAO;AAAA,eAAgBA,IAAc,CAAA,SAAA,CAAA,GAAA,CAAA,OAAA,CAAA;AAAA,eACdA,IAAc,CAAA,SAAA,CAAA,GAAA,CAAA,OAAA,CAAA;AAAA,aACrBC,GAAa,CAAA,QAAA,CAAA;AAAA,eACDC,GAAY,CAAA,SAAA,CAAA,GAAA,CAAA,YAAA,CAAA;AAAA,eACdA,GAAY,CAAA,SAAA,CAAA,GAAA,CAAA,UAAA,CAAA;AAAA,QAAA;AAAA,QACvC,UAAS;AAAA,QACT,MAAK;AAAA,QACJ,iBAAelC,EAAA;AAAA,QACf,iBAAe;AAAA,MAAA;QAEwE,CAAA/N,EAAA,eAAe+N,EAAA,cAAvGpN,EA4CO,QAAA;AAAA;UA5CD,OAAKiC,EAAA,CAAC,kBAAgB,EAAA,sBAAA,CAAoCgM,EAAA,OAAa,CAAA;AAAA,QAAA;UAC3ElN,GA0COC,EAAA,QAAA,SAAA;AAAA,YA1Ca,OAAO5B,EAAM,WAAW2O,EAAA,QAAkBH,EAAA;AAAA,YAAiB,OAAOK,EAAA;AAAA,YAAgB,UAAU7O,EAAM;AAAA,UAAA,GAAtH,MAAA;;AA0CO;AAAA,cAzCWA,EAAM,iBAAtBY,EA0BWE,IAAA,EAAA,KAAA,KAAA;AAAA,gBAzBwB6N,EAAA,MAAgB,SAAM,KAAvDhO,KAAAC,EAuBM,OAvBNc,IAuBM;AAAA,mBAtBJf,EAAA,EAAA,GAAAC,EAqBOE,IAAA,MAAAC,GApBmB4N,EAAA,OAAe,CAA/BF,GAAQvC,YADlBtL,EAqBO,QAAA;AAAA,oBAnBJ,KAAKiP,GAAapB,GAAQvC,CAAG;AAAA,oBAC9B,OAAM;AAAA,kBAAA;oBAGGuC,KAAA,QAAAA,EAAgB,gBADzB7N,EAKE,OAAA;AAAA;sBAHA,OAAM;AAAA,sBACL,KAAM6N,EAAe;AAAA,sBACtB,KAAI;AAAA,oBAAA;oBAENtN,EAAmE,QAAnE4L,IAAmEtL,GAAhCqN,EAAeL,CAAM,CAAA,GAAA,CAAA;AAAA,oBAEhDxO,EAAA,cAAcA,EAAA,iBADtBW,EAQO,QAAA;AAAA;sBANL,OAAM;AAAA,sBACL,SAAK0Q,EAAA,CAAApQ,MAAOyP,GAAUlC,GAAQvN,CAAM,GAAA,CAAA,MAAA,CAAA;AAAA,oBAAA;sBAErCC,EAEM,OAAA;AAAA,wBAFD,OAAM;AAAA,wBAAK,QAAO;AAAA,wBAAK,SAAQ;AAAA,wBAAY,MAAK;AAAA,sBAAA;wBACnDA,EAAqG,QAAA;AAAA,0BAA/F,GAAE;AAAA,0BAA4B,QAAO;AAAA,0BAAe,gBAAa;AAAA,0BAAM,kBAAe;AAAA,wBAAA;;;;4BAKpGP,EAAuE,QAAvES,IAAuEI,GAArBxB,EAAA,WAAW,GAAA,CAAA;AAAA,cAAA,gBAE/DW,EAaWE,IAAA,EAAA,KAAA,KAAA;AAAA,gBAZO0N,EAAA,cAAhB5N,EAQWE,IAAA,EAAA,KAAA,KAAA;AAAA,mBANAG,IAAAuN,EAAA,UAAA,QAAAvN,EAAwB,gBADjCL,EAKE,OAAA;AAAA;oBAHA,OAAM;AAAA,oBACL,KAAM4N,EAAA,MAAuB;AAAA,oBAC9B,KAAI;AAAA,kBAAA;kBACJ+C,GAAA,SACC1C,EAAA,KAAa,GAAA,CAAA;AAAA,gBAAA,gBAElBjO,EAEWE,IAAA,EAAA,KAAA,KAAA;AAAA,wBADNb,EAAA,WAAW,GAAA,CAAA;AAAA,gBAAA;;;;0BAKtBW,EAaE,SAAA;AAAA;mBAXI;AAAA,UAAJ,KAAI0N;AAAA,UACJ,OAAM;AAAA,UACN,MAAK;AAAA,UACJ,aAAatO,EAAM,WAAY2O,QAAgB,SAAM,IAAA,OAAcA,EAAA,MAAgB,MAAM,OAAO1O,gBAAgB4O,EAAA,SAAiB5O,EAAA;AAAA,wDACzHsO,EAAW,QAAArN;AAAA,UACnB,WAAO;AAAA,8BAAR,MAAA;AAAA,YAAA,GAAa,CAAA,MAAA,CAAA;AAAA,wCACgB2P,GAAS,CAAA,GAAA,CAAA,SAAA,CAAA,GAAA,CAAA,YAAA,CAAA;AAAA,wCACXA,GAAS,EAAA,GAAA,CAAA,SAAA,CAAA,GAAA,CAAA,UAAA,CAAA;AAAA,wCACZK,EAAA,GAAa,CAAA,SAAA,CAAA,GAAA,CAAA,OAAA,CAAA;AAAA,iBACfjB,GAAa,CAAA,SAAA,CAAA,GAAA,CAAA,KAAA,CAAA;AAAA,iBACVQ,GAAW,CAAA,SAAA,CAAA,GAAA,CAAA,QAAA,CAAA;AAAA,UAAA;AAAA;eAN3BlC,EAAA,KAAW;AAAA,QAAA;QASdtO,EAAA,aAAS,CAAKA,EAAA,aAAaD,EAAM,WAAW2O,EAAA,MAAgB,SAAM,IAAOH,EAAA,eADjF5N,EASO,QAAA;AAAA;UAPL,OAAM;AAAA,UACN,OAAM;AAAA,UACL,WAAY6P,GAAW,CAAA,MAAA,CAAA;AAAA,QAAA;UAExBtP,EAEM,OAAA;AAAA,YAFD,OAAM;AAAA,YAAK,QAAO;AAAA,YAAK,SAAQ;AAAA,YAAY,MAAK;AAAA,UAAA;YACnDA,EAA4F,QAAA;AAAA,cAAtF,GAAE;AAAA,cAAmB,QAAO;AAAA,cAAe,gBAAa;AAAA,cAAM,kBAAe;AAAA,YAAA;;;QAGvFA,EAIO,QAAA;AAAA,UAJD,OAAK0B,EAAA,CAAC,kBAAgB,EAAA,wBAAmCmL,EAAA,OAAM,CAAA;AAAA,QAAA;UACnE7M,EAEM,OAAA;AAAA,YAFD,OAAM;AAAA,YAAK,QAAO;AAAA,YAAK,SAAQ;AAAA,YAAY,MAAK;AAAA,UAAA;YACnDA,EAAsH,QAAA;AAAA,cAAhH,GAAE;AAAA,cAAqB,QAAO;AAAA,cAAe,gBAAa;AAAA,cAAM,kBAAe;AAAA,cAAQ,mBAAgB;AAAA,YAAA;;;;MAKnHwL,GAgDaC,IAAA,EAhDD,MAAK,sBAAkB;AAAA,oBACjC,MA8CW;AAAA,gBA9CXkB,GA8CW0D,IAAA,EA9CD,IAAG,UAAM;AAAA,YAETxD,EAAA,cADRpN,EA4CM,OAAA;AAAA;cA1CJ,OAAKiC,EAAA,CAAC,+CAA6C,EAAA,0BACfwL,EAAA,MAAA,CAAgB,CAAA;AAAA,cACnD,UAAOc,EAAA,KAAmB;AAAA,cAC1B,+BAAD,MAAA;AAAA,cAAA,GAAe,CAAA,MAAA,CAAA;AAAA,cACd,2BAAD,MAAA;AAAA,cAAA,GAAW,CAAA,MAAA,CAAA;AAAA,YAAA;cAEXhO,EAmCM,OAAA;AAAA,gBAnCD,OAAM;AAAA,yBAAuB;AAAA,gBAAJ,KAAI+M;AAAA,cAAA;iBAChCvN,EAAA,EAAA,GAAAC,EAiCME,IAAA,MAAAC,GAhCsBgO,EAAA,OAAgB,CAAlCN,GAAQzN,YADlBJ,EAiCM,OAAA;AAAA,kBA/BH,KAAKiP,GAAapB,GAAQzN,CAAK;AAAA,kBAChC,UAAM,mBAAiB;AAAA,oBACgC,6BAAA8O,EAAWrB,CAAM;AAAA,oBAAgD,6BAAAsB,GAAiBtB,CAAM;AAAA,oBAA6C,0BAAAR,EAAA,UAAiBjN;AAAA,kBAAA;kBAK5M,SAAK,CAAAE,MAAEkP,EAAa3B,CAAa;AAAA,kBACjC,cAAU,CAAAvN,MAAE+M,EAAA,QAAejN;AAAA,kBAC3B,qCAAYiN,EAAA,QAAY;AAAA,gBAAA;kBAEzBtM,GAmBOC,EAAA,QAAA,UAAA;AAAA,oBAnBc,QAAA6M;AAAA,oBAAiB,OAAAzN;AAAA,oBAAe,UAAU8O,EAAWrB,CAAM;AAAA,kBAAA,GAAhF,MAmBO;AAAA,oBAlBOzO,EAAM,YAAlBW,EAAA,GAAAC,EAUO,QAVPqM,IAUO;AAAA,sBARG6C,EAAWrB,CAAM,KADzB9N,EAAA,GAAAC,EAQM,OARNsM,IAQM,CAAA,GAAA5L,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,wBADJH,EAA8G,QAAA;AAAA,0BAAxG,GAAE;AAAA,0BAAe,QAAO;AAAA,0BAAe,gBAAa;AAAA,0BAAI,kBAAe;AAAA,0BAAQ,mBAAgB;AAAA,wBAAA;;;oBAIhGsN,KAAA,QAAAA,EAAgB,gBADzB7N,EAKE,OAAA;AAAA;sBAHA,OAAM;AAAA,sBACL,KAAM6N,EAAe;AAAA,sBACtB,KAAI;AAAA,oBAAA;uBACJ,MACFhN,GAAGqN,EAAeL,CAAM,CAAA,GAAA,CAAA;AAAA,kBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;ACxFxC,UAAMzO,IAAQC,GAWRC,IAAOC,GAQP4C,IAAWjB,EAAI9B,EAAM,QAAQ,GAG7ByR,IAAkBlR,EAAS,MAAMP,EAAM,eAAe,GAMtD8C,IAAcvC,EAAS;AAAA,MAC3B,KAAK,MAAMP,EAAM;AAAA,MACjB,KAAK,CAAC4F,MAAU;AACd,QAAA1F,EAAK,sBAAsB0F,CAAK,GAChC1F,EAAK,eAAe0F,CAAK;AAAA,MAC3B;AAAA,IAAA,CACD;AAGD,aAAS8L,EAAS5I,GAAc;AAC9B,MAAI9I,EAAM,WACN8I,KAAQ,KAAKA,MAAS9I,EAAM,gBAC9B8C,EAAY,QAAQgG;AAAA,IAExB;AAEA,aAASC,EAAqBnD,GAAe;AAC3C,MAAI5F,EAAM,YACV+C,EAAS,QAAQ6C,GACjB1F,EAAK,mBAAmB0F,CAAK,GAC7B1F,EAAK,oBAAoB0F,CAAK,GAE9B9C,EAAY,QAAQ;AAAA,IACtB;AAEA,aAAS6O,EAAkBC,GAA0B;AACnD,MAAI5R,EAAM,YACN4R,MAAW,SACbF,EAAS5O,EAAY,QAAQ,CAAC,IACrB8O,MAAW,UACpBF,EAAS5O,EAAY,QAAQ,CAAC;AAAA,IAElC;AAKA,WAAAC,EAAS,QAAQ/C,EAAM,UAGvBmC;AAAA,MACE,MAAMnC,EAAM;AAAA,MACZ,CAACoC,MAAQ;AACP,QAAI,OAAOA,KAAQ,YAAYW,EAAS,UAAUX,MAChDW,EAAS,QAAQX;AAAA,MAErB;AAAA,IAAA;;AA5HA,aAAAzB,EAAA,GAAAC,EAmCM,OAnCNiM,IAmCM;AAAA,QAlCJ1L,EAiCM,OAjCNO,IAiCM;AAAA,UA/BJiL,GAMCG,GAAA;AAAA,YALC,MAAK;AAAA,YACL,SAAQ;AAAA,YACP,UAAUhK,EAAA,UAAW,KAAU7C,EAAA;AAAA,YAC/B,gCAAOyR,EAAQ,CAAA;AAAA,UAAA;wBACf,MAAE,CAAA,GAAApQ,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,iBAAF,MAAE,EAAA;AAAA,YAAA;;;UAGLqL,GASEG,GAAA;AAAA,YARD,OAAM;AAAA,YACL,SAAQ;AAAA,YACR,MAAK;AAAA,YACJ,YAAU;AAAA,cAAuD,EAAA,OAAA,OAAA,OAAA,QAAA,UAAAhK,EAAA,eAAqB7C,EAAA,SAAO,MAAA,gBAAA,UAAA,IAAA,WAAA,MAAA;AAAA,cAA+G,EAAA,OAAA,OAAA,OAAA,QAAA,UAAAA,EAAA,WAAWA,EAAA,aAAW,MAAA,iBAAA,UAAA,IAAA,WAAA,MAAA;AAAA,YAAA;AAAA,YAIlO,cAAa0R;AAAA,UAAA;UAIhBxQ,EAUM,OAVNN,IAUM;AAAA,YATJ8L,GAQEkF,GAAA;AAAA,0BAPS9O,EAAA;AAAA,4DAAAA,EAAQ,QAAA7B;AAAA,cAChB,SAASuQ,EAAA;AAAA,cACV,MAAK;AAAA,cACL,OAAM;AAAA,cACL,WAAW;AAAA,cACX,UAAUxR,EAAA;AAAA,cACV,UAAQ8I;AAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACUnB,UAAM/I,IAAQC,GAyBR6R,IAAYvR,EAAS,MAAMP,EAAM,QAAQ,SAAS,GAElD+R,IAAYxR,EAAS,MAAM;AAC/B,YAAMyR,KAAQhS,EAAM,SAAS,IAAI,KAAA,GAC3BiS,IAAOjS,EAAM,MACbkS,IAAOlS,EAAM;AACnB,UAAIkS,GAAM;AACR,cAAMC,IAAkC;AAAA,UACtC,YAAY;AAAA,UACZ,mBAAmB;AAAA,UACnB,UAAU;AAAA,QAAA;AAEZ,eAAOH,IAAO,GAAGA,CAAI,OAAOG,EAAQD,CAAI,KAAKA,CAAI,KAAK,MAAMC,EAAQD,CAAI,KAAKA,CAAI;AAAA,MACnF;AACA,UAAID,KAAQA,MAAS,WAAW;AAC9B,cAAMG,IAAkC;AAAA,UACtC,eAAe;AAAA,UACf,SAAS;AAAA,UACT,WAAW;AAAA,UACX,SAAS;AAAA,UACT,UAAU;AAAA,UACV,SAAS;AAAA,QAAA;AAEX,eAAOJ,IAAO,GAAGA,CAAI,OAAOI,EAAQH,CAAI,KAAKA,CAAI,KAAK,MAAMG,EAAQH,CAAI,KAAKA,CAAI;AAAA,MACnF;AACA,aAAOD,KAAQ;AAAA,IACjB,CAAC;2BA5FCpR,EAmCO,QAAA;AAAA,MAlCL,UAAM,WAAS;AAAA,oBACckR,EAAA,KAAS;AAAA,oBAAuB7R,EAAA,IAAI;AAAA,QAA2B,EAAA,cAAAA,EAAA,oBAAoBA,EAAA,KAAA;AAAA,QAAeA,EAAA,gCAAgCA,EAAA,QAAQ,KAAA;AAAA,MAAA;MAMvK,MAAK;AAAA,MACJ,cAAY8R,EAAA;AAAA,IAAA;MAEb5Q,EAuBO,QAvBPO,IAuBO;AAAA,QArBOzB,EAAA,YAAZU,EAAA,GAAAC,EAWO,QAXPC,IAWO;AAAA,UAVMZ,EAAA,aAAQ,gBAAnBU,EAAA,GAAAC,EAEM,OAFNmM,IAEM,CAAA,GAAAzL,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,YADJH,EAAgC,UAAA;AAAA,cAAxB,IAAG;AAAA,cAAK,IAAG;AAAA,cAAK,GAAE;AAAA,YAAA;kBAEZlB,EAAA,aAAQ,uBAAxBU,KAAAC,EAGM,OAHNQ,IAGM,CAAA,GAAAE,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,YAFJH,EAAkC,QAAA,EAA5B,GAAE,wBAAA,GAAuB,MAAA,EAAA;AAAA,YAC/BA,EAAmF,UAAA;AAAA,cAA3E,IAAG;AAAA,cAAK,IAAG;AAAA,cAAK,GAAE;AAAA,cAAI,MAAK;AAAA,cAAO,QAAO;AAAA,cAAe,gBAAa;AAAA,YAAA;kBAE/DlB,EAAA,aAAQ,cAAxBU,KAAAC,EAEM,OAFNS,IAEM,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,YADJH,EAAgL,QAAA;AAAA,cAA1K,aAAU;AAAA,cAAU,GAAE;AAAA,cAA8H,aAAU;AAAA,YAAA;;cAIvJlB,EAAA,QAAjBU,KAAAC,EAKO,QALPW,IAKO;AAAA,UAJMtB,EAAA,SAAI,SAAfU,EAAA,GAAAC,EAAqH,OAArHY,IAAqH,CAAA,GAAAF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,YAArCH,EAA+B,UAAA;AAAA,cAAvB,IAAG;AAAA,cAAK,IAAG;AAAA,cAAK,GAAE;AAAA,YAAA;kBAC1FlB,EAAA,SAAI,WAApBU,KAAAC,EAA6Q,OAA7QoM,IAA6Q,CAAA,GAAA1L,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,YAAtLH,EAAgL,QAAA;AAAA,cAA1K,aAAU;AAAA,cAAU,GAAE;AAAA,cAA8H,aAAU;AAAA,YAAA;kBAC3OlB,EAAA,SAAI,WAApBU,KAAAC,EAAuW,OAAvWqM,IAAuW,CAAA,GAAA3L,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,YAAhRH,EAA0Q,QAAA;AAAA,cAApQ,aAAU;AAAA,cAAU,GAAE;AAAA,cAAyN,aAAU;AAAA,YAAA;mBACtVR,KAAAC,EAAsG,OAAtGsM,IAAsG,CAAA,GAAA5L,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,YAArCH,EAA+B,UAAA;AAAA,cAAvB,IAAG;AAAA,cAAK,IAAG;AAAA,cAAK,GAAE;AAAA,YAAA;;;QAG7FA,EAA4D,QAA5DiM,IAA4D;AAAA,UAA/BzL,GAAwBC,yBAAxB,MAAwB;AAAA,kBAAf3B,EAAA,KAAK,GAAA,CAAA;AAAA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;ACsBjD,UAAMD,IAAQC,GAsBRC,IAAOC,GAMPkS,IAAU9R,EAAS;AAAA,MACvB,KAAK,MAAMP,EAAM;AAAA,MACjB,KAAK,CAACsS,MAAepS,EAAK,qBAAqBoS,CAAC;AAAA,IAAA,CACjD,GAEKC,IAAWzQ,EAAwB,IAAI,GAEvC0Q,IAAajS,EAAS,MAAM;AAChC,YAAMkH,IAAgC,CAAA;AACtC,aAAAA,EAAM,QAAQ,OAAOzH,EAAM,SAAU,WAAW,GAAGA,EAAM,KAAK,OAAO,OAAOA,EAAM,KAAK,GACvFyH,EAAM,SAAS,UACfA,EAAM,MAAMzH,EAAM,KACXyH;AAAA,IACT,CAAC;AAED,aAASgL,IAAc;AACrB,MAAKzS,EAAM,gBACX0S,EAAA;AAAA,IACF;AAEA,aAASA,IAAQ;AACf,MAAKL,EAAQ,UACbA,EAAQ,QAAQ,IAChBnS,EAAK,OAAO;AAAA,IACd;AAEA,aAASyS,IAAQ;AACf,MAAI3S,EAAM,YAAU0S,EAAA;AAAA,IACtB;AAEA,aAASE,EAAU3H,GAAkB;AACnC,MAAIA,EAAE,QAAQ,YAAU0H,EAAA;AAAA,IAC1B;AAEA,WAAAxQ,GAAM,MAAMnC,EAAM,YAAY,CAACsS,MAAM;AACnC,MAAIA,KACFpS,EAAK,MAAM,GACX,sBAAsB,MAAA;;AAAM,gBAAAe,IAAAsR,EAAS,UAAT,gBAAAtR,EAAgB;AAAA,OAAO,GACnD,SAAS,iBAAiB,WAAW2R,CAAS,GAC9C,SAAS,KAAK,MAAM,WAAW,aAE/B,SAAS,oBAAoB,WAAWA,CAAS,GACjD,SAAS,KAAK,MAAM,WAAW;AAAA,IAEnC,CAAC,GAEDxG,GAAU,MAAM;AACd,MAAIpM,EAAM,eACR,SAAS,iBAAiB,WAAW4S,CAAS,GAC9C,SAAS,KAAK,MAAM,WAAW;AAAA,IAEnC,CAAC,GAEDtG,GAAY,MAAM;AAChB,eAAS,oBAAoB,WAAWsG,CAAS,GACjD,SAAS,KAAK,MAAM,WAAW;AAAA,IACjC,CAAC,mBA3IC9E,GAiDW0D,IAAA,EAjDD,IAAG,UAAM;AAAA,SACjBrQ,EA+CM,OAAA;AAAA,QA7CJ,OAAM;AAAA,QACN,MAAK;AAAA,QACJ,cAAY;AAAA,QACZ,gBAAckR,EAAA;AAAA,QACd,OAAKlF,GAAA,EAAA,QAAY,OAAOlN,EAAA,MAAM,GAAA;AAAA,MAAA;QAE/BkB,EAGO,OAAA;AAAA,UAFL,OAAM;AAAA,UACL,SAAOsR;AAAA,QAAA;QAGV9F,GAiCaC,IAAA,EAjCD,MAAK,sBAAkB;AAAA,sBACjC,MA+BM;AAAA,eA/BNzL,EA+BM,OAAA;AAAA,uBA7BA;AAAA,cAAJ,KAAIoR;AAAA,cACJ,OAAK1P,EAAA,CAAC,kBAAgB,CACZ5C,EAAA,SAAM,cAAA,EAAA,CAAA,CAAA;AAAA,cACf,UAAOuS,EAAA,KAAU;AAAA,cACjB,gBAA0BG,GAAK,CAAA,WAAA,MAAA,CAAA,GAAA,CAAA,KAAA,CAAA;AAAA,cAChC,UAAS;AAAA,YAAA;cAEE1S,EAAA,cAAXU,EAAA,GAAAC,EAaM,OAbNC,IAaM;AAAA,gBAZJc,GAEOC,wBAFP,MAEO;AAAA,kBADLT,EAA6C,OAA7C4L,IAA6CtL,GAAdxB,EAAA,KAAK,GAAA,CAAA;AAAA,gBAAA;gBAG9BA,EAAA,iBADRW,EAQS,UAAA;AAAA;kBANP,MAAK;AAAA,kBACL,OAAM;AAAA,kBACN,cAAW;AAAA,kBACV,SAAO8R;AAAA,gBAAA,GACT,KAED;;cAGFvR,EAEM,OAFNC,IAEM;AAAA,gBADJO,GAAQC,EAAA,QAAA,WAAA,CAAA,GAAA,QAAA,EAAA;AAAA,cAAA;cAGCiR,EAAAA,OAAO,UAAlBlS,KAAAC,EAEM,OAFNS,IAEM;AAAA,gBADJM,GAAsBC,EAAA,QAAA,UAAA,CAAA,GAAA,QAAA,EAAA;AAAA,cAAA;;mBA5BhByQ,EAAA,KAAO;AAAA,YAAA;;;;;aAdXA,EAAA,KAAO;AAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;ACgFrB,UAAMrS,IAAQC,GAiBRC,IAAOC,GASP2S,IAAahR,EAAA,GACbiR,IAAajR,EAAA,GACbkR,IAAalR,EAAA,GACbuQ,IAAUvQ,EAAI,EAAK,GACnByN,IAAczN,EAAA,GACdmR,IAAcnR,EAAA,GACdoR,IAAgBpR,EAA4B,EAAE;AAGpD,QAAIqR,IAA2B,MAC3BC,IAA4B;AAGhC,UAAMC,IAAe9S,EAAS,MAAM;AAClC,UAAI,CAAC8R,EAAQ,SAAS,CAAC9C,EAAY,cAAc,CAAA;AAEjD,YAAM9H,IAAgC,CAAA;AAGtC,MAAIzH,EAAM,UAAU,WAClByH,EAAM,QAAQ,OAAOzH,EAAM,SAAU,WAAW,GAAGA,EAAM,KAAK,OAAOA,EAAM,QAIzEA,EAAM,aACRyH,EAAM,WAAW,OAAOzH,EAAM,YAAa,WAAW,GAAGA,EAAM,QAAQ,OAAOA,EAAM;AAItF,YAAM,EAAE,KAAAsT,IAAK,MAAAC,EAAA,IAASC,EAAA;AACtB,aAAA/L,EAAM,MAAM,GAAG6L,EAAG,MAClB7L,EAAM,OAAO,GAAG8L,CAAI,MAEb9L;AAAA,IACT,CAAC,GAEKgM,IAAalT,EAAS,MAAM;AAChC,UAAI,CAACP,EAAM,UAAW,QAAO,CAAA;AAG7B,UAAI,OAAO,KAAKkT,EAAc,KAAK,EAAE,SAAS;AAC5C,eAAOA,EAAc;AAIvB,YAAMzL,IAAgC,CAAA;AACtC,aAAIzH,EAAM,UAAU,WAAW,KAAK,KAAKA,EAAM,UAAU,WAAW,QAAQ,IAC1EyH,EAAM,OAAO,QAEbA,EAAM,MAAM,OAEPA;AAAA,IACT,CAAC;AAGD,aAAS+L,IAAoB;;AAC3B,UAAI,CAACjE,EAAY,MAAO,QAAO,EAAE,KAAK,GAAG,MAAM,EAAA;AAE/C,YAAM,EAAE,OAAOmE,GAAc,QAAQC,IAAe,KAAKC,GAAY,MAAMC,EAAA,IAAgBtE,EAAY,OACjGuE,MAAe7S,IAAA+R,EAAW,UAAX,gBAAA/R,EAAkB,gBAAe,KAChDqJ,MAAgBuB,KAAAmH,EAAW,UAAX,gBAAAnH,GAAkB,iBAAgB;AAExD,UAAIyH,IAAM,GACNC,IAAO;AAEX,cAAQvT,EAAM,WAAA;AAAA,QACZ,KAAK;AACH,UAAAsT,IAAMM,IAAatJ,IAAgBtK,EAAM,QACzCuT,IAAOM,KAAeH,IAAeI,KAAgB;AACrD;AAAA,QACF,KAAK;AACH,UAAAR,IAAMM,IAAatJ,IAAgBtK,EAAM,QACzCuT,IAAOM;AACP;AAAA,QACF,KAAK;AACH,UAAAP,IAAMM,IAAatJ,IAAgBtK,EAAM,QACzCuT,IAAOM,IAAcH,IAAeI;AACpC;AAAA,QACF,KAAK;AACH,UAAAR,IAAMM,IAAaD,KAAgB3T,EAAM,QACzCuT,IAAOM,KAAeH,IAAeI,KAAgB;AACrD;AAAA,QACF,KAAK;AACH,UAAAR,IAAMM,IAAaD,KAAgB3T,EAAM,QACzCuT,IAAOM;AACP;AAAA,QACF,KAAK;AACH,UAAAP,IAAMM,IAAaD,KAAgB3T,EAAM,QACzCuT,IAAOM,IAAcH,IAAeI;AACpC;AAAA,QACF,KAAK;AACH,UAAAR,IAAMM,KAAcD,KAAgBrJ,KAAiB,GACrDiJ,IAAOM,IAAcC,IAAe9T,EAAM;AAC1C;AAAA,QACF,KAAK;AACH,UAAAsT,IAAMM,GACNL,IAAOM,IAAcC,IAAe9T,EAAM;AAC1C;AAAA,QACF,KAAK;AACH,UAAAsT,IAAMM,IAAaD,KAAgBrJ,GACnCiJ,IAAOM,IAAcC,IAAe9T,EAAM;AAC1C;AAAA,QACF,KAAK;AACH,UAAAsT,IAAMM,KAAcD,KAAgBrJ,KAAiB,GACrDiJ,IAAOM,IAAcH,IAAe1T,EAAM;AAC1C;AAAA,QACF,KAAK;AACH,UAAAsT,IAAMM,GACNL,IAAOM,IAAcH,IAAe1T,EAAM;AAC1C;AAAA,QACF,KAAK;AACH,UAAAsT,IAAMM,IAAaD,KAAgBrJ,GACnCiJ,IAAOM,IAAcH,IAAe1T,EAAM;AAC1C;AAAA,MAAA;AAIJ,YAAM+T,IAAgB,OAAO,YACvB1K,IAAiB,OAAO;AAG9B,aAAIkK,IAAO,MAAGA,IAAO,IACjBA,IAAOO,IAAeC,IAAgB,MACxCR,IAAOQ,IAAgBD,IAAe,IAIpCR,IAAM,MAAGA,IAAM,IACfA,IAAMhJ,IAAgBjB,IAAiB,MACzCiK,IAAMjK,IAAiBiB,IAAgB,IAGlC,EAAE,KAAAgJ,GAAK,MAAAC,EAAA;AAAA,IAChB;AAGA,aAASS,IAAO;AACd,MAAIhU,EAAM,YAAYqS,EAAQ,UAE9B4B,EAAA,GAEIjU,EAAM,YAAY,IACpBmT,IAAY,WAAW,MAAM;AAC3B,QAAAe,EAAA;AAAA,MACF,GAAGlU,EAAM,SAAS,IAElBkU,EAAA;AAAA,IAEJ;AAEA,aAASA,IAAS;AAChB,MAAAhU,EAAK,aAAa,GAClBmS,EAAQ,QAAQ,IAChBnS,EAAK,qBAAqB,EAAI,GAC9BA,EAAK,MAAM,GAGXiJ,GAAS,MAAM;AACb,QAAAA,GAAS,MAAM;AACb,UAAAgL,GAAA;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAGA,aAASC,IAAO;AACd,MAAK/B,EAAQ,UAEb4B,EAAA,GAEIjU,EAAM,aAAa,IACrBoT,IAAa,WAAW,MAAM;AAC5B,QAAAiB,GAAA;AAAA,MACF,GAAGrU,EAAM,UAAU,IAEnBqU,GAAA;AAAA,IAEJ;AAEA,aAASA,KAAS;AAChB,MAAAnU,EAAK,aAAa,GAClBmS,EAAQ,QAAQ,IAChBnS,EAAK,qBAAqB,EAAK,GAC/BA,EAAK,MAAM;AAAA,IACb;AAGA,aAAS+T,IAAc;AACrB,MAAId,MACF,aAAaA,CAAS,GACtBA,IAAY,OAEVC,MACF,aAAaA,CAAU,GACvBA,IAAa;AAAA,IAEjB;AAGA,aAASkB,KAAyB;AAChC,UAAI,CAACtU,EAAM,aAAa,CAACuP,EAAY,SAAS,CAACyD,EAAW,OAAO;AAC/D,QAAAE,EAAc,QAAQ,CAAA;AACtB;AAAA,MACF;AAEA,YAAM9D,IAAUG,EAAY,OACtB0D,KAAcD,EAAW,MAAM,sBAAA;AAGrC,UAAIC,GAAY,UAAU,KAAKA,GAAY,WAAW,GAAG;AACvD,cAAMxL,IAAgC,CAAA;AACtC,QAAIzH,EAAM,UAAU,WAAW,KAAK,KAAKA,EAAM,UAAU,WAAW,QAAQ,IAC1EyH,EAAM,OAAO,QAEbA,EAAM,MAAM,OAEdyL,EAAc,QAAQzL;AACtB;AAAA,MACF;AAEA,YAAMA,IAAgC,CAAA;AAGtC,UAAIzH,EAAM,UAAU,WAAW,KAAK,GAAG;AACrC,QAAAyH,EAAM,SAAS;AAEf,cAAM8M,IAAiBnF,EAAQ,OAAOA,EAAQ,QAAQ,GAChDoF,IAAcvB,GAAY,MAC1BwB,IAAcF,IAAiBC;AACrC,QAAA/M,EAAM,OAAO,GAAG,KAAK,IAAI,IAAI,KAAK,IAAIgN,GAAaxB,GAAY,QAAQ,EAAE,CAAC,CAAC;AAAA,MAC7E,WAAWjT,EAAM,UAAU,WAAW,QAAQ,GAAG;AAC/C,QAAAyH,EAAM,MAAM;AAEZ,cAAM8M,IAAiBnF,EAAQ,OAAOA,EAAQ,QAAQ,GAChDoF,IAAcvB,GAAY,MAC1BwB,IAAcF,IAAiBC;AACrC,QAAA/M,EAAM,OAAO,GAAG,KAAK,IAAI,IAAI,KAAK,IAAIgN,GAAaxB,GAAY,QAAQ,EAAE,CAAC,CAAC;AAAA,MAC7E,WAAWjT,EAAM,UAAU,WAAW,MAAM,GAAG;AAC7C,QAAAyH,EAAM,QAAQ;AAEd,cAAMiN,IAAiBtF,EAAQ,MAAMA,EAAQ,SAAS,GAChDuF,IAAa1B,GAAY,KACzBwB,IAAcC,IAAiBC;AACrC,QAAAlN,EAAM,MAAM,GAAG,KAAK,IAAI,IAAI,KAAK,IAAIgN,GAAaxB,GAAY,SAAS,EAAE,CAAC,CAAC;AAAA,MAC7E,WAAWjT,EAAM,UAAU,WAAW,OAAO,GAAG;AAC9C,QAAAyH,EAAM,OAAO;AAEb,cAAMiN,IAAiBtF,EAAQ,MAAMA,EAAQ,SAAS,GAChDuF,IAAa1B,GAAY,KACzBwB,IAAcC,IAAiBC;AACrC,QAAAlN,EAAM,MAAM,GAAG,KAAK,IAAI,IAAI,KAAK,IAAIgN,GAAaxB,GAAY,SAAS,EAAE,CAAC,CAAC;AAAA,MAC7E;AAEA,MAAAC,EAAc,QAAQzL;AAAA,IACxB;AAGA,aAAS0M,KAAiB;AACxB,MAAKpB,EAAW,UAEhBxD,EAAY,QAAQwD,EAAW,MAAM,sBAAA,GAEjCC,EAAW,UACbC,EAAY,QAAQD,EAAW,MAAM,sBAAA,GAGrCsB,GAAA,GAGIjC,EAAQ,SACV,sBAAsB,MAAM;AAC1B,QAAIW,EAAW,UACbC,EAAY,QAAQD,EAAW,MAAM,sBAAA,GACrCsB,GAAA;AAAA,MAEJ,CAAC;AAAA,IAGP;AAGA,aAASM,IAAqB;AAC5B,MAAI5U,EAAM,YAENA,EAAM,YAAY,YAChBqS,EAAQ,QACV+B,EAAA,IAEAJ,EAAA;AAAA,IAGN;AAEA,aAASa,IAAmB;AAC1B,MAAI7U,EAAM,YAAYA,EAAM,YAAY,YAExCiU,EAAA,GACAD,EAAA;AAAA,IACF;AAEA,aAASc,IAAmB;AAC1B,MAAI9U,EAAM,YAAYA,EAAM,YAAY,WAExCoU,EAAA;AAAA,IACF;AAGA,aAASW,IAA0B;AACjC,MAAI/U,EAAM,YAAYA,EAAM,YAAY,WAExCiU,EAAA;AAAA,IACF;AAGA,aAASe,KAA0B;AACjC,MAAIhV,EAAM,YAAYA,EAAM,YAAY,WAExCoU,EAAA;AAAA,IACF;AAGA,aAAS/C,GAAmBT,GAAmB;AAC7C,UAAI,CAAC5Q,EAAM,uBAAuB,CAACqS,EAAQ,MAAO;AAElD,YAAM/P,KAASsO,EAAM;AACrB,MACEkC,EAAW,SACX,CAACA,EAAW,MAAM,SAASxQ,EAAM,KACjC0Q,EAAW,SACX,CAACA,EAAW,MAAM,SAAS1Q,EAAM,KAEjC8R,EAAA;AAAA,IAEJ;AAUA,WAAAjS,GAAM,MAAMnC,EAAM,YAAY,CAAC0I,MAAW;AACxC,MAAIA,MAAW2J,EAAQ,UACjB3J,IACFsL,EAAA,IAEAI,EAAA;AAAA,IAGN,CAAC,GAGDjS,GAAMkQ,GAAS,CAAC3J,MAAW;AACzB,MAAIA,KACF,SAAS,iBAAiB,SAAS2I,EAAkB,GACrD,OAAO,iBAAiB,UAAU8C,EAAc,GAChD,OAAO,iBAAiB,UAAUA,IAAgB,EAAI,GAGtDhL,GAAS,MAAM;AACb,QAAAgL,GAAA,GACA,sBAAsB,MAAM;AAC1B,UAAAA,GAAA;AAAA,QACF,CAAC,GACD,WAAW,MAAM;AACf,UAAAA,GAAA;AAAA,QACF,GAAG,CAAC;AAAA,MACN,CAAC,MAED,SAAS,oBAAoB,SAAS9C,EAAkB,GACxD,OAAO,oBAAoB,UAAU8C,EAAc,GACnD,OAAO,oBAAoB,UAAUA,IAAgB,EAAI;AAAA,IAE7D,CAAC,GAGD/H,GAAU,MAAM;AACd,MAAIpM,EAAM,cACRgU,EAAA;AAAA,IAEJ,CAAC,GAED1H,GAAY,MAAM;AAChB,MAAA2H,EAAA,GACA,SAAS,oBAAoB,SAAS5C,EAAkB,GACxD,OAAO,oBAAoB,UAAU8C,EAAc,GACnD,OAAO,oBAAoB,UAAUA,IAAgB,EAAI;AAAA,IAC3D,CAAC,GAGDc,EAAa;AAAA,MACX,MAAAjB;AAAA,MACA,MAAAI;AAAA,MACA,gBAAAD;AAAA,IAAA,CACD,oBAxfCvT,EA6CM,OAAA;AAAA,MA7CD,OAAM;AAAA,eAAe;AAAA,MAAJ,KAAIkS;AAAA,IAAA;MAExB3R,EAOM,OAAA;AAAA,iBANA;AAAA,QAAJ,KAAI4R;AAAA,QACH,SAAO6B;AAAA,QACP,cAAYC;AAAA,QACZ,cAAYC;AAAA,MAAA;QAEbnT,GAA8BC,EAAA,QAAA,aAAA,CAAA,GAAA,QAAA,EAAA;AAAA,MAAA;YAIhCkM,GAgCW0D,IAAA,EAhCD,IAAG,UAAM;AAAA,QACjB7E,GA8BaC,IAAA,EA9BD,MAAK,mBAAe;AAAA,sBAC9B,MA4BM;AAAA,YA3BEyF,EAAA,cADRzR,EA4BM,OAAA;AAAA;uBA1BA;AAAA,cAAJ,KAAIoS;AAAA,cACJ,UAAM,qBAAmB;AAAA,sCACmB/S,EAAA,SAAS;AAAA;6CAA2DA,EAAA;AAAA,oDAAsDA,EAAA;AAAA,gBAAA;AAAA;cAOrK,UAAOoT,EAAA,KAAY;AAAA,cACnB,6BAAD,MAAA;AAAA,cAAA,GAAW,CAAA,MAAA,CAAA;AAAA,cACV,cAAY0B;AAAA,cACZ,cAAYC;AAAA,YAAA;cAIL/U,EAAA,kBADRW,EAKO,OAAA;AAAA;gBAHL,OAAKiC,EAAA,CAAC,mBAAiB,oBACK5C,EAAA,SAAS,EAAA,CAAA;AAAA,gBACpC,UAAOwT,EAAA,KAAU;AAAA,cAAA;cAIpBtS,EAEM,OAFN0L,IAEM;AAAA,gBADJlL,GAAaC,EAAA,QAAA,WAAA,CAAA,GAAA,QAAA,EAAA;AAAA,cAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACkOzB,UAAM5B,IAAQC,GAgERC,IAAOC,GAMP6N,IAASlM,EAAI,EAAK,GAClBoT,IAAsBpT,EAAI,EAAE,GAC5BqT,IAAwBrT,EAAI,EAAE,GAC9BsT,IAAetT,EAAsB,IAAI,GACzCsN,IAAUtN,EAAA,GACVuT,IAAWvT,EAAA,GACXwT,IAAmBxT,EAAI;AAAA,MAC3B,KAAK;AAAA,MACL,MAAM;AAAA,IAAA,CACP,GAGKyT,IAAgBzT,EAAI;AAAA,MACxB,OAAM,oBAAI,KAAA,GAAO,YAAA;AAAA,MACjB,QAAO,oBAAI,KAAA,GAAO,SAAA;AAAA,IAAS,CAC5B,GAEK0T,IAAc1T,EAAI;AAAA,MACtB,OAAM,oBAAI,KAAA,GAAO,YAAA;AAAA,MACjB,QAAO,oBAAI,KAAA,GAAO,aAAa;AAAA,IAAA,CAChC,GAGK2T,IAAwB,MAAM;AAClC,YAAMC,IAAY,IAAI,KAAKH,EAAc,MAAM,MAAMA,EAAc,MAAM,KAAK,EAAE,QAAA,GAC1EI,IAAU,IAAI,KAAKH,EAAY,MAAM,MAAMA,EAAY,MAAM,KAAK,EAAE,QAAA;AAE1E,UAAIE,KAAaC,GAAS;AAExB,cAAMC,IAAY,IAAI,KAAKL,EAAc,MAAM,MAAMA,EAAc,MAAM,QAAQ,CAAC;AAClF,QAAAC,EAAY,MAAM,OAAOI,EAAU,YAAA,GACnCJ,EAAY,MAAM,QAAQI,EAAU,SAAA;AAAA,MACtC;AAAA,IACF,GAGMC,IAA+B,MAAM;AACzC,YAAMH,IAAY,IAAI,KAAKH,EAAc,MAAM,MAAMA,EAAc,MAAM,KAAK,EAAE,QAAA;AAGhF,UAFgB,IAAI,KAAKC,EAAY,MAAM,MAAMA,EAAY,MAAM,KAAK,EAAE,QAAA,KAE3DE,GAAW;AAExB,cAAMI,IAAY,IAAI,KAAKN,EAAY,MAAM,MAAMA,EAAY,MAAM,QAAQ,CAAC;AAC9E,QAAAD,EAAc,MAAM,OAAOO,EAAU,YAAA,GACrCP,EAAc,MAAM,QAAQO,EAAU,SAAA;AAAA,MACxC;AAAA,IACF,GAEMC,IAAW,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG,GAE7CC,IAAgBlU,EAAiB,IAAI,GACrCmU,IAAcnU,EAAiB,IAAI,GAGnCoU,IAAY,CAACC,MAAqD;AACtE,UAAI,CAACA,EAAM,QAAO;AAClB,UAAIA,aAAgB,KAAM,QAAOA;AACjC,UAAI,OAAOA,KAAS;AAElB,eAAO,IAAI,KAAKA,CAAI;AAEtB,UAAI,OAAOA,KAAS,UAAU;AAC5B,cAAM7Q,IAAS,IAAI,KAAK6Q,CAAI;AAC5B,eAAO,MAAM7Q,EAAO,QAAA,CAAS,IAAI,OAAOA;AAAA,MAC1C;AACA,aAAO;AAAA,IACT,GAGM8Q,IAAqB,CAACD,MAAqC;AAC/D,UAAI,CAACA,EAAM,QAAO;AAElB,YAAME,IAAOF,EAAK,YAAA,GACZG,IAAQ,OAAOH,EAAK,SAAA,IAAa,CAAC,EAAE,SAAS,GAAG,GAAG,GACnDI,IAAM,OAAOJ,EAAK,QAAA,CAAS,EAAE,SAAS,GAAG,GAAG;AAElD,UAAInW,EAAM,aAAa;AAErB,cAAMwW,KAAQ,OAAOL,EAAK,SAAA,CAAU,EAAE,SAAS,GAAG,GAAG,GAC/CM,KAAU,OAAON,EAAK,WAAA,CAAY,EAAE,SAAS,GAAG,GAAG,GACnDO,KAAU,OAAOP,EAAK,WAAA,CAAY,EAAE,SAAS,GAAG,GAAG;AACzD,eAAO,GAAGE,CAAI,IAAIC,CAAK,IAAIC,CAAG,IAAIC,EAAK,IAAIC,EAAO,IAAIC,EAAO;AAAA,MAC/D;AAEE,eAAO,GAAGL,CAAI,IAAIC,CAAK,IAAIC,CAAG;AAAA,IAElC,GAGMI,KAAwB,CAACR,MACxBA,IACEA,EAAK,QAAA,IADM,MAKdS,IAAiB,CAAChR,MACjBA,IAEE;AAAA,MACL,WAAWsQ,EAAUtQ,EAAM,SAAS;AAAA,MACpC,SAASsQ,EAAUtQ,EAAM,OAAO;AAAA,IAAA,IAJf,EAAE,WAAW,MAAM,SAAS,KAAA,GAS3CiR,KAAoB,CAACjR,MACrB5F,EAAM,WAAW,WAEZ;AAAA,MACL,WAAWoW,EAAmBxQ,EAAM,SAAS;AAAA,MAC7C,SAASwQ,EAAmBxQ,EAAM,OAAO;AAAA,IAAA,IAElC5F,EAAM,WAAW,cAEnB;AAAA,MACL,WAAW2W,GAAsB/Q,EAAM,SAAS;AAAA,MAChD,SAAS+Q,GAAsB/Q,EAAM,OAAO;AAAA,IAAA,IAIvCA,GAKLkR,KAAkB,CAACT,GAAcC,MAC9B,GAAG,OAAOA,IAAQ,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC,IAAID,CAAI,IAGhDU,IAAY,CAACC,GAAaC,MACvBD,EAAM,YAAA,MAAkBC,EAAM,YAAA,KAC9BD,EAAM,SAAA,MAAeC,EAAM,cAC3BD,EAAM,QAAA,MAAcC,EAAM,QAAA,GAG7BC,IAAgB,CAACf,GAAYgB,GAAoBC,MACjD,CAACD,KAAS,CAACC,IAAY,KACpBjB,KAAQgB,KAAShB,KAAQiB,GAI5BC,IAA4B,CAACC,MAA8B;AAC/D,YAAMC,IAAkBX,EAAeU,CAAY;AAEnD,UAAI,EAACC,KAAA,QAAAA,EAAiB,cAAa,EAACA,KAAA,QAAAA,EAAiB;AACnD,eAAO;AAGT,eAAS9Q,IAAI,GAAGA,IAAIzG,EAAM,UAAU,QAAQyG,KAAK;AAC/C,cAAM+Q,IAAgBxX,EAAM,UAAUyG,CAAC,EAAE,SAAA;AAEzC,YAAI+Q,EAAc,aAAaA,EAAc,WACzCD,EAAgB,aAAaA,EAAgB,SAAS;AAGxD,gBAAME,KAAe,IAAI;AAAA,YAAKF,EAAgB,UAAU,YAAA;AAAA,YAC3BA,EAAgB,UAAU,SAAA;AAAA,YAC1BA,EAAgB,UAAU,QAAA;AAAA,UAAQ,GACzDG,KAAa,IAAI;AAAA,YAAKH,EAAgB,QAAQ,YAAA;AAAA,YACzBA,EAAgB,QAAQ,SAAA;AAAA,YACxBA,EAAgB,QAAQ,QAAA;AAAA,UAAQ,GAErDI,KAAgB,IAAI;AAAA,YAAKH,EAAc,UAAU,YAAA;AAAA,YACzBA,EAAc,UAAU,SAAA;AAAA,YACxBA,EAAc,UAAU,QAAA;AAAA,UAAQ,GACxDI,KAAc,IAAI;AAAA,YAAKJ,EAAc,QAAQ,YAAA;AAAA,YACvBA,EAAc,QAAQ,SAAA;AAAA,YACtBA,EAAc,QAAQ,QAAA;AAAA,UAAQ;AAE1D,cAAIC,GAAa,cAAcE,GAAc,QAAA,KACzCD,GAAW,QAAA,MAAcE,GAAY;AACvC,mBAAOnR;AAAA,QAEX;AAAA,MACF;AAEA,aAAO;AAAA,IACT,GAGMoR,IAAuB,CAACxB,GAAcC,MAAmC;AAC7E,YAAMwB,IAAW,IAAI,KAAKzB,GAAMC,GAAO,CAAC,GAClCyB,IAAU,IAAI,KAAK1B,GAAMC,IAAQ,GAAG,CAAC,GACrC0B,KAAeF,EAAS,OAAA,GACxBG,KAAcF,EAAQ,QAAA,GAEtBG,KAAsB,CAAA,GACtBC,yBAAY,KAAA,GAKZC,KAAgBJ,OAAiB,IAAI,IAAIA,KAAe,GAIxDlC,KAAY,IAAI,KAAKO,GAAMC,GAAO,CAAC;AACzC,eAAS7P,KAAI2R,KAAgB,GAAG3R,MAAK,GAAGA,MAAK;AAC3C,cAAM0P,KAAO,IAAI,KAAKE,GAAMC,IAAQ,GAAGR,GAAU,QAAA,IAAYrP,EAAC;AAC9D,QAAAyR,GAAK,KAAK;AAAA,UACR,MAAA/B;AAAA,UACA,KAAKA,GAAK,QAAA;AAAA,UACV,gBAAgB;AAAA,UAChB,SAASY,EAAUZ,IAAMgC,EAAK;AAAA,UAC9B,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,YAAY;AAAA;AAAA,QAAA,CACb;AAAA,MACH;AAGA,eAAS1R,KAAI,GAAGA,MAAKwR,IAAaxR,MAAK;AACrC,cAAM0P,KAAO,IAAI,KAAKE,GAAMC,GAAO7P,EAAC;AACpC,QAAAyR,GAAK,KAAK;AAAA,UACR,MAAA/B;AAAA,UACA,KAAK1P;AAAA,UACL,gBAAgB;AAAA,UAChB,SAASsQ,EAAUZ,IAAMgC,EAAK;AAAA,UAC9B,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,YAAY;AAAA,QAAA,CACb;AAAA,MACH;AAGA,YAAME,KAAgB,KAAKH,GAAK;AAChC,eAASzR,KAAI,GAAGA,MAAK4R,IAAe5R,MAAK;AACvC,cAAM0P,KAAO,IAAI,KAAKE,GAAMC,IAAQ,GAAG7P,EAAC;AACxC,QAAAyR,GAAK,KAAK;AAAA,UACR,MAAA/B;AAAA,UACA,KAAK1P;AAAA,UACL,gBAAgB;AAAA,UAChB,SAASsQ,EAAUZ,IAAMgC,EAAK;AAAA,UAC9B,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,YAAY;AAAA;AAAA,QAAA,CACb;AAAA,MACH;AAGA,YAAMG,KAAyB,CAAA;AAC/B,eAAS7R,KAAI,GAAGA,KAAIyR,GAAK,QAAQzR,MAAK;AACpC,QAAA6R,GAAM,KAAKJ,GAAK,MAAMzR,IAAGA,KAAI,CAAC,CAAC;AAGjC,aAAO6R;AAAA,IACT,GAGMC,KAAc,CAAC3S,MAAqB;AACxC,YAAM4S,IAAiB3B,GAAkBjR,CAAK;AAC9C,MAAA1F,EAAK,qBAAqBsY,CAAc,GACxCtY,EAAK,UAAUsY,CAAc;AAAA,IAC/B,GAGMlJ,KAA4B,MAAM;AACtC,UAAI,CAACF,EAAQ,SAAS,CAACiG,EAAS,MAAO;AAEvC,YAAM9F,IAAcH,EAAQ,MAAM,sBAAA,GAC5BqJ,IAAepD,EAAS,MAAM,sBAAA,GAC9BtB,IAAgB,OAAO,YAGvB2E,KAFiB,OAAO,cAEMnJ,EAAY,QAC1CoJ,KAAapJ,EAAY,KACzBC,KAAiBiJ,EAAa,UAAU;AAE9C,MAAIC,KAAalJ,MAAkBmJ,KAAanJ,KAC9C8F,EAAiB,MAAM,MAAM,KAE7BA,EAAiB,MAAM,MAAM;AAG/B,YAAMsD,KAAa7E,IAAgBxE,EAAY,MACzCsJ,KAAgBJ,EAAa,SAAS;AAE5C,MAAIG,KAAaC,KACfvD,EAAiB,MAAM,OAAO,KAE9BA,EAAiB,MAAM,OAAO;AAAA,IAElC,GAEMtF,IAAiB,MAAM;AAE3B,UADAhC,EAAO,QAAQ,CAACA,EAAO,OACnBA,EAAO,OAAO;AAEhB,cAAMuJ,IAAkBX,EAAe5W,EAAM,UAAU;AAgBvD,YAfAgW,EAAc,SAAQuB,KAAA,gBAAAA,EAAiB,cAAa,MACpDtB,EAAY,SAAQsB,KAAA,gBAAAA,EAAiB,YAAW,MAGhDpC,EAAsB,QAAQkC,EAA0BrX,EAAM,UAAU,GAGxEkV,EAAoB,QAAQ,IAGxBqC,KAAA,QAAAA,EAAiB,cACnBhC,EAAc,MAAM,OAAOgC,EAAgB,UAAU,YAAA,GACrDhC,EAAc,MAAM,QAAQgC,EAAgB,UAAU,SAAA,IAGpDA,KAAA,QAAAA,EAAiB;AACnB,UAAA/B,EAAY,MAAM,OAAO+B,EAAgB,QAAQ,YAAA,GACjD/B,EAAY,MAAM,QAAQ+B,EAAgB,QAAQ,SAAA;AAAA,aAC7C;AAEL,gBAAM3B,IAAY,IAAI,KAAKL,EAAc,MAAM,MAAMA,EAAc,MAAM,QAAQ,CAAC;AAClF,UAAAC,EAAY,MAAM,OAAOI,EAAU,YAAA,GACnCJ,EAAY,MAAM,QAAQI,EAAU,SAAA;AAAA,QACtC;AAGA,QAAAH,EAAA,GAEAtM,GAAS,MAAM;AACb,UAAAmG,GAAA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,GAEM+B,KAAqB,CAACT,MAAiB;AAC3C,YAAMtO,IAASsO,EAAM,QACfkI,IAAY1J,EAAQ,OACpB2J,IAAa1D,EAAS;AAE5B,MAAIyD,KAAaC,KACb,CAACD,EAAU,SAASxW,CAAM,KAC1B,CAACyW,EAAW,SAASzW,CAAM,MAC7B0L,EAAO,QAAQ,IACfkH,EAAoB,QAAQ;AAAA,IAEhC,GAEM8D,IAAuB,CAACpI,MAAyB;AACjD,MAAIA,EAAM,QAAQ,WAAWA,EAAM,QAAQ,OACzCA,EAAM,eAAA,GACVZ,EAAA,KACaY,EAAM,QAAQ,gBACvBA,EAAM,eAAA,GACV5C,EAAO,QAAQ,IACf7E,GAAS,MAAM;AACb,QAAAmG,GAAA,GACA2J,EAAA;AAAA,MACF,CAAC;AAAA,IAEL,GAEMC,IAAwB,CAACtI,MAAyB;;AAClD,MAAIA,EAAM,QAAQ,aACpB5C,EAAO,QAAQ,IACfkH,EAAoB,QAAQ,KAC5BjU,IAAAmO,EAAQ,UAAR,QAAAnO,EAAe;AAAA,IAEnB,GAEMkY,IAAwB,CAACvI,GAAsB5P,MAAkB;AACjE,MAAI4P,EAAM,QAAQ,eAChBA,EAAM,eAAA,GACVsE,EAAoB,QAAQ,KAAK,IAAIlU,IAAQ,GAAGhB,EAAM,UAAU,SAAS,CAAC,GAC1EoZ,EAAclE,EAAoB,KAAK,KAC1BtE,EAAM,QAAQ,aACvBA,EAAM,eAAA,GACVsE,EAAoB,QAAQ,KAAK,IAAIlU,IAAQ,GAAG,CAAC,GACjDoY,EAAclE,EAAoB,KAAK,MAC1BtE,EAAM,QAAQ,WAAWA,EAAM,QAAQ,SAChDA,EAAM,eAAA,GACVyI,EAAerZ,EAAM,UAAUgB,CAAK,CAAC;AAAA,IAEzC,GAEMsY,IAA2B,CAACtY,MAAkB;AAClD,MAAAkU,EAAoB,QAAQlU;AAAA,IAC9B,GAEMuY,IAA2B,MAAM;AACrC,MAAArE,EAAoB,QAAQ;AAAA,IAC9B,GAEM+D,IAAqB,MAAM;AAC/B,MAAA/D,EAAoB,QAAQ,GAC5BkE,EAAc,CAAC;AAAA,IACjB,GAEMA,IAAgB,CAACpY,MAAkB;AACvC,UAAIqU,EAAS,OAAO;AAElB,cAAMmE,IADYnE,EAAS,MAAM,iBAAiB,mBAAmB,EACnCrU,CAAK;AACvC,QAAIwY,KACFA,EAAgB,MAAA;AAAA,MAEpB;AAAA,IACF,GAEMH,IAAiB,CAACI,MAAuB;AAC7C,YAAM7T,IAAQ6T,EAAS,SAAA;AAGvB,MAAIzZ,EAAM,eAAe4F,EAAM,aAAaA,EAAM,YAChDA,EAAM,UAAU,SAAS,GAAG,GAAG,GAAG,CAAC,GACnCA,EAAM,QAAQ,SAAS,IAAI,IAAI,IAAI,GAAG,IAGxC2S,GAAY3S,CAAK,GAGjBuP,EAAsB,QAAQnV,EAAM,UAAU,UAAU,OAAK0Z,EAAE,UAAUD,EAAS,KAAK,GAGvFvE,EAAoB,QAAQ,IAE5BlH,EAAO,QAAQ;AAAA,IACjB,GAGM2L,IAAa,CAACpD,GAAyBqD,MAA0B;AACrE,UAAI,CAACrD,KAAOA,EAAI,WAAY;AAG5B,UAAIsD;AAwBJ,UAtBI7Z,EAAM,eAER6Z,IAAe,IAAI,KAAKtD,EAAI,IAAI,GAC5BqD,MAAS,WAAW,CAAC5D,EAAc,QAErC6D,EAAa,SAAS,GAAG,GAAG,GAAG,CAAC,IAGhCA,EAAa,SAAS,IAAI,IAAI,IAAI,GAAG,KAIvCA,IAAe,IAAI,KAAKtD,EAAI,KAAK,YAAA,GAAeA,EAAI,KAAK,SAAA,GAAYA,EAAI,KAAK,SAAS,GAUrF,CAACP,EAAc,SAAS,CAACC,EAAY;AAEvC,QAAAD,EAAc,QAAQ6D,GACtB5D,EAAY,QAAQ;AAAA,eACXD,EAAc,SAAS,CAACC,EAAY;AAE7C,YAAI4D,KAAgB7D,EAAc;AAGhC,UAAIhW,EAAM,eACR6Z,EAAa,SAAS,IAAI,IAAI,IAAI,GAAG,GAEvC5D,EAAY,QAAQ4D;AAAA,aACf;AAEL,gBAAMC,IAAU9D,EAAc;AAE9B,UAAIhW,EAAM,eACR8Z,EAAQ,SAAS,IAAI,IAAI,IAAI,GAAG,GAElC7D,EAAY,QAAQ6D,GACpB9D,EAAc,QAAQ6D;AAAA,QACxB;AAAA;AAGA,QAAA7D,EAAc,QAAQ6D,GACtB5D,EAAY,QAAQ;AAOtB,UAHAd,EAAsB,QAAQ,IAG1Ba,EAAc,SAASC,EAAY,OAAO;AAE5C,cAAM6D,IAAU,IAAI,KAAK7D,EAAY,KAAK;AAC1C,QAAIjW,EAAM,eACR8Z,EAAQ,SAAS,IAAI,IAAI,IAAI,GAAG,GAElC1E,EAAa,QAAQ;AAAA,UACnB,WAAWY,EAAc;AAAA,UACzB,SAAA8D;AAAA,QAAA;AAAA,MAEJ;AACE,QAAA1E,EAAa,QAAQ;AAAA,IAEzB,GAEM2E,KAAmB,CAACxD,GAAyBqD,MAA0B;AAC3E,UAAI,CAACrD,EAAK,QAAO,CAAC,kBAAkB;AAEpC,YAAMhP,IAAU,CAAC,kBAAkB;AAEnC,aAAKgP,EAAI,kBACPhP,EAAQ,KAAK,eAAe,GAG1BgP,EAAI,WACNhP,EAAQ,KAAK,UAAU,GAGrBgP,EAAI,cACNhP,EAAQ,KAAK,aAAa,GAIxByO,EAAc,SAASe,EAAUR,EAAI,MAAMP,EAAc,KAAK,KAChEzO,EAAQ,KAAK,eAAe,UAAU,GAGpC0O,EAAY,SAASc,EAAUR,EAAI,MAAMN,EAAY,KAAK,KAC5D1O,EAAQ,KAAK,eAAe,QAAQ,GAIlCyO,EAAc,SAASC,EAAY,SACnCiB,EAAcX,EAAI,MAAMP,EAAc,OAAOC,EAAY,KAAK,KAChE1O,EAAQ,KAAK,aAAa,GAGrBA;AAAA,IACT,GAEMyS,KAAmB,MAAM;AAC7B,MAAI5E,EAAa,UAEXpV,EAAM,eAAeoV,EAAa,MAAM,WAC1CA,EAAa,MAAM,QAAQ,SAAS,IAAI,IAAI,IAAI,GAAG,GAGrDmD,GAAYnD,EAAa,KAAK,GAE9BD,EAAsB,QAAQkC,EAA0BjC,EAAa,KAAK,GAC1EpH,EAAO,QAAQ;AAAA,IAEnB,GAEM1F,KAAiB,MAAM;AAC3B,MAAAiQ,GAAY,EAAE,WAAW,MAAM,SAAS,MAAM,GAC9C0B,GAAA,GACA/E,EAAoB,QAAQ,IAC5BlH,EAAO,QAAQ;AAAA,IACjB,GAGMlC,KAAe,MAAM;AACzB,MAAIkC,EAAO,SACT7E,GAAS,MAAM;AACb,QAAAmG,GAAA;AAAA,MACF,CAAC;AAAA,IAEL,GAGM4K,KAAoB3Z,EAAS,MAC1BsX,EAAqBtC,EAAc,MAAM,MAAMA,EAAc,MAAM,KAAK,CAChF,GAEK4E,KAAkB5Z,EAAS,MACxBsX,EAAqBrC,EAAY,MAAM,MAAMA,EAAY,MAAM,KAAK,CAC5E,GAEK4E,KAAc7Z,EAAS,MAAM;AACjC,YAAMgX,IAAkBX,EAAe5W,EAAM,UAAU;AAEvD,UAAI,CAACuX,KAAmB,CAACA,EAAgB,aAAa,CAACA,EAAgB;AACrE,eAAO;AAGT,YAAM8C,IAAa,CAAClE,OAAe;AACjC,cAAME,KAAO,OAAOF,GAAK,YAAA,CAAa,GAChCG,KAAQ,OAAOH,GAAK,SAAA,IAAa,CAAC,EAAE,SAAS,GAAG,GAAG,GACnDI,KAAM,OAAOJ,GAAK,QAAA,CAAS,EAAE,SAAS,GAAG,GAAG;AAClD,eAAO,GAAGE,EAAI,IAAIC,EAAK,IAAIC,EAAG;AAAA,MAChC,GAEM+D,IAAWD,EAAW9C,EAAgB,SAAS,GAC/CgD,IAASF,EAAW9C,EAAgB,OAAO;AAGjD,aAAI,CAACvX,EAAM,eAAesa,MAAaC,IAC9BD,IAGF,GAAGA,CAAQ,MAAMC,CAAM;AAAA,IAChC,CAAC,GAEKC,KAAkBja,EAAS,MACxB;AAAA,MACL;AAAA,MACA;AAAA,QACE,wBAAwB,CAAC+U,EAAiB,MAAM;AAAA,QAChD,0BAA0B,CAACA,EAAiB,MAAM;AAAA,MAAA;AAAA,IACpD,CAEH,GAGKmF,KAAWla,EAAS,MAAM;AAC9B,YAAMgX,IAAkBX,EAAe5W,EAAM,UAAU;AACvD,aAAO,CAAC,EAAEuX,KAAA,QAAAA,EAAiB,cAAaA,KAAA,QAAAA,EAAiB;AAAA,IAC3D,CAAC,GAGKmD,KAAana,EAAS,MACnB,CAAC,EAAEyV,EAAc,SAASC,EAAY,MAC9C,GAWKgE,KAAiB,MAAM;AAC3B,MAAAjE,EAAc,QAAQ,MACtBC,EAAY,QAAQ,MACpBb,EAAa,QAAQ,MACrBD,EAAsB,QAAQ;AAAA,IAChC;AAGA,IAAAhT,GAAM,MAAMnC,EAAM,YAAY,CAAC2a,MAAa;AAC1C,YAAMpD,IAAkBX,EAAe+D,CAAQ;AAE/C,UAAIpD,KAAA,QAAAA,EAAiB,WAAW;AAC9B,cAAMqD,IAAYrD,EAAgB;AAClC,QAAAhC,EAAc,MAAM,OAAOqF,EAAU,YAAA,GACrCrF,EAAc,MAAM,QAAQqF,EAAU,SAAA;AAAA,MACxC;AAEA,UAAIrD,KAAA,QAAAA,EAAiB,SAAS;AAC5B,cAAMuC,IAAUvC,EAAgB;AAChC,QAAA/B,EAAY,MAAM,OAAOsE,EAAQ,YAAA,GACjCtE,EAAY,MAAM,QAAQsE,EAAQ,SAAA;AAAA,MACpC,WAAWvC,KAAA,QAAAA,EAAiB,WAAW;AAErC,cAAM3B,IAAY,IAAI,KAAKL,EAAc,MAAM,MAAMA,EAAc,MAAM,QAAQ,CAAC;AAClF,QAAAC,EAAY,MAAM,OAAOI,EAAU,YAAA,GACnCJ,EAAY,MAAM,QAAQI,EAAU,SAAA;AAAA,MACtC;AAGA,OAAI2B,KAAA,QAAAA,EAAiB,aAAaA,KAAA,QAAAA,EAAiB,YACjD9B,EAAA,GAIGzH,EAAO,UACVmH,EAAsB,QAAQkC,EAA0BsD,CAAQ;AAAA,IAEpE,GAAG,EAAE,WAAW,IAAM,MAAM,IAAM,GAGlCxY,GAAM,CAACoT,GAAeC,CAAW,GAAG,MAAM;AACxC,YAAME,IAAY,IAAI,KAAKH,EAAc,MAAM,MAAMA,EAAc,MAAM,KAAK,EAAE,QAAA,GAC1EI,IAAU,IAAI,KAAKH,EAAY,MAAM,MAAMA,EAAY,MAAM,KAAK,EAAE,QAAA;AAG1E,UAAIE,MAAcC,GAAS;AACzB,cAAMC,IAAY,IAAI,KAAKL,EAAc,MAAM,MAAMA,EAAc,MAAM,QAAQ,CAAC;AAClF,QAAAC,EAAY,MAAM,OAAOI,EAAU,YAAA,GACnCJ,EAAY,MAAM,QAAQI,EAAU,SAAA;AAAA,MACtC;AAAA,IACF,GAAG,EAAE,MAAM,IAAM,GAGjBxJ,GAAU,MAAM;AACd,eAAS,iBAAiB,SAASiF,EAAkB,GACrD,OAAO,iBAAiB,UAAUvF,EAAY,GAC9C,OAAO,iBAAiB,UAAUA,EAAY,GAG9CqJ,EAAsB,QAAQkC,EAA0BrX,EAAM,UAAU;AAGxE,YAAMuX,IAAkBX,EAAe5W,EAAM,UAAU;AAOvD,UALIuX,KAAA,QAAAA,EAAiB,cACnBhC,EAAc,MAAM,OAAOgC,EAAgB,UAAU,YAAA,GACrDhC,EAAc,MAAM,QAAQgC,EAAgB,UAAU,SAAA,IAGpDA,KAAA,QAAAA,EAAiB;AACnB,QAAA/B,EAAY,MAAM,OAAO+B,EAAgB,QAAQ,YAAA,GACjD/B,EAAY,MAAM,QAAQ+B,EAAgB,QAAQ,SAAA;AAAA,WAC7C;AAEL,cAAM3B,IAAY,IAAI,KAAKL,EAAc,MAAM,MAAMA,EAAc,MAAM,QAAQ,CAAC;AAClF,QAAAC,EAAY,MAAM,OAAOI,EAAU,YAAA,GACnCJ,EAAY,MAAM,QAAQI,EAAU,SAAA;AAAA,MACtC;AAEA,MAAAH,EAAA;AAAA,IACF,CAAC,GAEDnJ,GAAY,MAAM;AAChB,eAAS,oBAAoB,SAAS+E,EAAkB,GACxD,OAAO,oBAAoB,UAAUvF,EAAY,GACjD,OAAO,oBAAoB,UAAUA,EAAY;AAAA,IACnD,CAAC;AAGD,UAAM+O,KAAmB,MAAM;AAC7B,MAAK7a,EAAM,cAEXuY,GAAY,EAAE,WAAW,MAAM,SAAS,MAAM,GAC9C0B,GAAA,GACA/E,EAAoB,QAAQ;AAAA,IAC9B,GAGM4F,KAAc,CAAClB,GAAuBmB,MAAsB;AAChE,UAAInB,MAAS,SAAS;AACpB,cAAMoB,IAAU,IAAI,KAAKzF,EAAc,MAAM,MAAMA,EAAc,MAAM,QAAQwF,GAAW,CAAC;AAC3F,QAAAxF,EAAc,MAAM,OAAOyF,EAAQ,YAAA,GACnCzF,EAAc,MAAM,QAAQyF,EAAQ,SAAA,GAGpCvF,EAAA;AAAA,MACF,OAAO;AACL,cAAMuF,IAAU,IAAI,KAAKxF,EAAY,MAAM,MAAMA,EAAY,MAAM,QAAQuF,GAAW,CAAC;AACvF,QAAAvF,EAAY,MAAM,OAAOwF,EAAQ,YAAA,GACjCxF,EAAY,MAAM,QAAQwF,EAAQ,SAAA,GAGlCnF,EAAA;AAAA,MACF;AAAA,IACF;;;kBAhjCEjV,EAoOM,OAAA;AAAA,QApOD,OAAKiC,EAAA,CAAC,kBAAgB,CAAA,YAAsB5C,EAAA,IAAI,EAAA,CAAA,CAAA;AAAA,MAAA;QAEnDkB,EAiOM,OAjON0L,IAiOM;AAAA,UAhOJ1L,EAoCM,OAAA;AAAA,qBAnCA;AAAA,YAAJ,KAAIiO;AAAA,YACH,SAAOY;AAAA,YACP,WAASgJ;AAAA,YACT,OAAKnW,EAAA,CAAA,mBAAA,EAAA,YAAoCmL,EAAA,OAAM,aAAeyM,GAAA,MAAA,CAAQ,CAAA;AAAA,YACvE,UAAS;AAAA,UAAA;YAETtZ,EAKE,SAAA;AAAA,cAJA,UAAA;AAAA,cACC,OAAOiZ,GAAA;AAAA,cACP,aAAana,EAAA;AAAA,cACd,OAAM;AAAA,YAAA;YAERkB,EAsBO,QAtBPN,IAsBO;AAAA,cApBGZ,EAAA,aAAawa,GAAA,cADrB7Z,EAQI,KAAA;AAAA;gBAND,WAAYia,IAAgB,CAAA,MAAA,CAAA;AAAA,gBAC7B,OAAM;AAAA,cAAA;gBAEN1Z,EAEM,OAAA;AAAA,kBAFD,SAAQ;AAAA,kBAAgB,OAAM;AAAA,kBAAK,QAAO;AAAA,gBAAA;kBAC7CA,EAAmZ,QAAA;AAAA,oBAA7Y,GAAE;AAAA,oBAAsX,MAAK;AAAA,kBAAA;;;8BAIvYA,EAII,KAAA,EAJD,OAAM,kBAAc;AAAA,gBACrBA,EAEM,OAAA;AAAA,kBAFD,SAAQ;AAAA,kBAAgB,OAAM;AAAA,kBAAK,QAAO;AAAA,gBAAA;kBAC7CA,EAA4X,QAAA;AAAA,oBAAtX,GAAE;AAAA,oBAA+V,MAAK;AAAA,kBAAA;;;cAIhXA,EAII,KAAA;AAAA,gBAJD,OAAK0B,EAAA,CAAC,iBAAe,EAAA,cAAyBmL,EAAA,OAAM,CAAA;AAAA,cAAA;gBACrD7M,EAEM,OAAA;AAAA,kBAFD,SAAQ;AAAA,kBAAgB,OAAM;AAAA,kBAAK,QAAO;AAAA,gBAAA;kBAC7CA,EAA2N,QAAA;AAAA,oBAArN,GAAE;AAAA,oBAA8L,MAAK;AAAA,kBAAA;;;;;UAOnNwL,GAwLaC,IAAA,EAxLD,MAAK,oBAAgB;AAAA,wBAC/B,MAsLM;AAAA,cArLEoB,EAAA,cADRpN,EAsLM,OAAA;AAAA;yBApLA;AAAA,gBAAJ,KAAIyU;AAAA,gBACH,SAAOmF,GAAA,KAAe;AAAA,gBACtB,WAAStB;AAAA,cAAA;gBAGV/X,EAsBM,OAtBN4L,IAsBM;AAAA,kBArBJzL,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAH,EAA+C,OAAA,EAA1C,OAAM,0BAAA,GAA0B,QAAI,EAAA;AAAA,kBACzCA,EAmBK,MAnBLC,IAmBK;AAAA,qBAlBHT,EAAA,EAAA,GAAAC,EAiBKE,IAAA,MAAAC,GAhByBd,EAAA,WAAS,CAA7BwZ,GAAUzY,aADpBJ,EAiBK,MAAA;AAAA,sBAfF,KAAK6Y,EAAS;AAAA,sBACd,SAAK,CAAAvY,OAAEmY,EAAeI,CAAQ;AAAA,sBAC9B,WAAO,CAAAvY,OAAEiY,EAAsBjY,IAAQF,EAAK;AAAA,sBAC5C,cAAU,CAAAE,OAAEoY,EAAyBtY,EAAK;AAAA,sBAC1C,cAAYuY;AAAA,sBACZ,OAAK1W,EAAA;AAAA;;0BAAiG,aAAAqS,EAAA,UAAwBlU;AAAA,0BAA0C,eAAAmU,EAAA,UAA0BnU;AAAA,wBAAA;AAAA;sBAOnM,UAAS;AAAA,oBAAA,GAENS,GAAAgY,EAAS,KAAK,GAAA,IAAApY,EAAA;;;gBAMvBF,EAqJM,OArJNI,IAqJM;AAAA,kBApJJJ,EAcM,OAdNK,IAcM;AAAA,oBAbJF,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAH,EAAkB,cAAZ,SAAK,EAAA;AAAA,oBAEXA,EAUM,OAVN6L,IAUM;AAAA,sBATS,CAAAgJ,EAAA,UAAkBC,EAAA,cAA/BrV,EAEO,QAFPqM,IAAgE,WAEhE,KACiB+I,EAAA,UAAkBC,EAAA,cAAnCrV,EAEO,QAFPsM,IAAoE,WAEpE,KACiB8I,EAAA,SAAiBC,EAAA,cAAlCrV,EAEO,QAFPwM,IAAmF,WAEnF;;;kBAKJjM,EA8GM,OA9GNkM,IA8GM;AAAA,oBA5GJlM,EAoDM,OApDNmM,IAoDM;AAAA,sBAnDJnM,EAkDM,OAlDN8Z,IAkDM;AAAA,wBAhDJ9Z,EAsBM,OAtBNoM,IAsBM;AAAA,0BArBJpM,EAQS,UAAA;AAAA,4BAPN,gCAAO2Z,GAAW,SAAA,EAAA;AAAA,4BACnB,OAAM;AAAA,4BACN,MAAK;AAAA,0BAAA;4BAEL3Z,EAEM,OAAA;AAAA,8BAFD,SAAQ;AAAA,8BAAgB,OAAM;AAAA,8BAAK,QAAO;AAAA,4BAAA;8BAC7CA,EAAyN,QAAA;AAAA,gCAAnN,GAAE;AAAA,gCAA4L,MAAK;AAAA,8BAAA;;;0BAG7MA,EAEO,QAFPsM,IAEOhM,GADFqV,GAAgBvB,EAAA,MAAc,MAAMA,EAAA,MAAc,KAAK,CAAA,GAAA,CAAA;AAAA,0BAE5DpU,EAQS,UAAA;AAAA,4BAPN,gCAAO2Z,GAAW,SAAA,CAAA;AAAA,4BACnB,OAAM;AAAA,4BACN,MAAK;AAAA,0BAAA;4BAEL3Z,EAEM,OAAA;AAAA,8BAFD,SAAQ;AAAA,8BAAgB,OAAM;AAAA,8BAAK,QAAO;AAAA,4BAAA;8BAC7CA,EAA0N,QAAA;AAAA,gCAApN,GAAE;AAAA,gCAA6L,MAAK;AAAA,8BAAA;;;;wBAMhNA,EAsBM,OAtBNuM,IAsBM;AAAA,0BArBJvM,EAoBQ,SApBRwM,IAoBQ;AAAA,4BAnBNxM,EAIQ,SAAA,MAAA;AAAA,8BAHNA,EAEK,MAAA,MAAA;AAAA,sCADHP,EAA8EE,IAAA,MAAAC,GAA5DgV,GAAQ,CAAfQ,MAAXpV,EAA8E,MAAA;AAAA,kCAAjD,KAAKoV;AAAA,kCAAK,OAAM;AAAA,gCAAA,MAAsBA,CAAG,GAAA,CAAA;;;4BAG1EpV,EAaQ,SAAA,MAAA;AAAA,+BAZNR,EAAA,EAAA,GAAAC,EAWKE,IAAA,MAAAC,GAX2BmZ,GAAA,OAAiB,CAArCgB,GAAMC,aAAlBva,EAWK,MAAA;AAAA,gCAX+C,mBAAmBua,EAAS;AAAA,8BAAA;iCAC9Exa,EAAA,EAAA,GAAAC,EASKE,IAAA,MAAAC,GARuBma,GAAI,CAAtB3E,IAAK6E,aADfxa,EASK,MAAA;AAAA,kCAPF,KAAG,aAAeua,EAAS,IAAIC,EAAQ;AAAA,kCACvC,OAAKvY,EAAEkX,GAAiBxD,EAAG,CAAA;AAAA,kCAC3B,SAAK,CAAArV,OAAEyY,EAAWpD,IAAG,OAAA;AAAA,gCAAA;kCAEtBpV,EAEM,OAFNka,IAEM;AAAA,oCADQ9E,WAAZ3V,EAAqC,QAAAiN,IAAApM,GAAjB8U,GAAI,GAAG,GAAA,CAAA;;;;;;;;;oBAW3CpV,EAoDM,OApDNma,IAoDM;AAAA,sBAnDJna,EAkDM,OAlDNoa,IAkDM;AAAA,wBAhDJpa,EAsBM,OAtBNqa,IAsBM;AAAA,0BArBJra,EAQS,UAAA;AAAA,4BAPN,gCAAO2Z,GAAW,OAAA,EAAA;AAAA,4BACnB,OAAM;AAAA,4BACN,MAAK;AAAA,0BAAA;4BAEL3Z,EAEM,OAAA;AAAA,8BAFD,SAAQ;AAAA,8BAAgB,OAAM;AAAA,8BAAK,QAAO;AAAA,4BAAA;8BAC7CA,EAAyN,QAAA;AAAA,gCAAnN,GAAE;AAAA,gCAA4L,MAAK;AAAA,8BAAA;;;0BAG7MA,EAEO,QAFPsa,IAEOha,GADFqV,GAAgBtB,EAAA,MAAY,MAAMA,EAAA,MAAY,KAAK,CAAA,GAAA,CAAA;AAAA,0BAExDrU,EAQS,UAAA;AAAA,4BAPN,gCAAO2Z,GAAW,OAAA,CAAA;AAAA,4BACnB,OAAM;AAAA,4BACN,MAAK;AAAA,0BAAA;4BAEL3Z,EAEM,OAAA;AAAA,8BAFD,SAAQ;AAAA,8BAAgB,OAAM;AAAA,8BAAK,QAAO;AAAA,4BAAA;8BAC7CA,EAA0N,QAAA;AAAA,gCAApN,GAAE;AAAA,gCAA6L,MAAK;AAAA,8BAAA;;;;wBAMhNA,EAsBM,OAtBNua,IAsBM;AAAA,0BArBJva,EAoBQ,SApBRwa,IAoBQ;AAAA,4BAnBNxa,EAIQ,SAAA,MAAA;AAAA,8BAHNA,EAEK,MAAA,MAAA;AAAA,sCADHP,EAA8EE,IAAA,MAAAC,GAA5DgV,GAAQ,CAAfQ,MAAXpV,EAA8E,MAAA;AAAA,kCAAjD,KAAKoV;AAAA,kCAAK,OAAM;AAAA,gCAAA,MAAsBA,CAAG,GAAA,CAAA;;;4BAG1EpV,EAaQ,SAAA,MAAA;AAAA,+BAZNR,EAAA,EAAA,GAAAC,EAWKE,IAAA,MAAAC,GAX2BoZ,GAAA,OAAe,CAAnCe,GAAMC,aAAlBva,EAWK,MAAA;AAAA,gCAX6C,iBAAiBua,EAAS;AAAA,8BAAA;iCAC1Exa,EAAA,EAAA,GAAAC,EASKE,IAAA,MAAAC,GARuBma,GAAI,CAAtB3E,IAAK6E,aADfxa,EASK,MAAA;AAAA,kCAPF,KAAG,WAAaua,EAAS,IAAIC,EAAQ;AAAA,kCACrC,OAAKvY,EAAEkX,GAAiBxD,EAAG,CAAA;AAAA,kCAC3B,SAAK,CAAArV,OAAEyY,EAAWpD,IAAG,KAAA;AAAA,gCAAA;kCAEtBpV,EAEM,OAFNya,IAEM;AAAA,oCADQrF,WAAZ3V,EAAqC,QAAAib,IAAApa,GAAjB8U,GAAI,GAAG,GAAA,CAAA;;;;;;;;;;kBAW7CpV,EAkBM,OAlBN2a,IAkBM;AAAA,oBAhBI7b,EAAA,kBADR6N,GAOUhB,GAAA;AAAA;sBALP,SAAOxE;AAAA,sBACP,SAAS;AAAA,sBACT,MAAMrI,EAAA;AAAA,oBAAA;kCACR,MAED,CAAA,GAAAqB,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,2BAFC,QAED,EAAA;AAAA,sBAAA;;;oBAEAqL,GAOUG,GAAA;AAAA,sBANP,SAAOkN;AAAA,sBACP,WAAWU,GAAA;AAAA,sBACX,SAAS;AAAA,sBACT,MAAMza,EAAA;AAAA,oBAAA;kCAEP,MAAuD;AAAA,wBAApDsR,GAAA9P,GAAAuU,EAAA,UAAkBC,EAAA,QAAW,aAAA,IAAA,GAAA,CAAA;AAAA,sBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACjLhD,UAAMjW,IAAQC,GAcRC,IAAOC,GAOP4b,IAASja,EAAA,GAETka,IAAYzb,EAAS,MAAMP,EAAM,eAAeA,EAAM,SAAS,GAE/Dic,IAAc1b,EAAS,MAAM;AACjC,YAAMkH,IAAgC,CAAA;AAEtC,aAAAA,EAAM,aAAauU,EAAU,QAAQhc,EAAM,cAAcA,EAAM,eACxDyH;AAAA,IACT,CAAC;AAED,aAASyU,IAAW;AAClB,UAAIlc,EAAM,YAAYA,EAAM,QAAS;AACrC,YAAMiJ,IAAO+S,EAAU,QAAQhc,EAAM,aAAaA,EAAM;AACxD,MAAAE,EAAK,qBAAqB+I,CAAI,GAC9B/I,EAAK,UAAU+I,CAAI;AAAA,IACrB;AAEA,WAAAmD,GAAU,MAAM;AACd,YAAMgF,IAAK2K,EAAO;AAClB,MAAK3K,MACLA,EAAG,iBAAiB,SAAS,CAACnG,MAAM/K,EAAK,SAAS+K,CAAe,CAAC,GAClEmG,EAAG,iBAAiB,QAAQ,CAACnG,MAAM/K,EAAK,QAAQ+K,CAAe,CAAC;AAAA,IAClE,CAAC,mBAxFCrK,EAuBS,UAAA;AAAA,eAtBH;AAAA,MAAJ,KAAImb;AAAA,MACJ,UAAM,WAAS;AAAA,oBACa9b,EAAA,IAAI;AAAA,8BAAgC+b,EAAA,OAAS,qBAAuB/b,EAAA,UAAQ,oBAAsBA,EAAA,QAAA;AAAA,MAAO;MAIpI,UAAOgc,EAAA,KAAW;AAAA,MACnB,MAAK;AAAA,MACJ,gBAAcD,EAAA;AAAA,MACd,iBAAe/b,EAAA;AAAA,MACf,UAAUA,EAAA,YAAYA,EAAA;AAAA,MACtB,SAAOic;AAAA,MACP,WAAO;AAAA,aAAgBA,GAAQ,CAAA,SAAA,CAAA,GAAA,CAAA,OAAA,CAAA;AAAA,aACRA,GAAQ,CAAA,SAAA,CAAA,GAAA,CAAA,OAAA,CAAA;AAAA,MAAA;AAAA;sBAEhC/a,EAAoC,QAAA,EAA9B,OAAM,iBAAA,GAAgB,MAAA,EAAA;AAAA,MAC5BA,EAEO,QAFPO,IAEO;AAAA,QADOzB,EAAA,WAAZU,EAAA,GAAAC,EAAwE,QAAxEC,EAAwE;;MAE9DZ,EAAA,iBAAZW,EAEO,QAAA;AAAA;QAFe,OAAKiC,EAAA,CAAC,kBAAgB,EAAA,wBAAA,CAAoCmZ,EAAA,gCAAoCA,EAAA,MAAA,CAAS,CAAA;AAAA,MAAA,MACxHA,EAAA,QAAY/b,EAAA,aAAaA,EAAA,YAAY,GAAA,CAAA;;;;;;;;;;;;;;;;;;;AC+F9C,UAAMD,IAAQC,GASRC,IAAOC,GAOPgc,IAAera,EAAA,GACfsa,IAAWta,EAAA,GACXua,IAAkBva,EAAA,GAClBwa,IAAWxa,EAAI,EAAK,GACpBya,IAAYza,EAAI,EAAK,GACrB0a,IAAW1a,EAAI,EAAK,GACpB2a,IAAW3a,EAAI,EAAK,GACpB4a,IAAc5a,EAAI,EAAK,GACvB6a,IAAS7a,EAAI,07BAA07B,GACv8B8a,IAAa9a,EAAI,EAAE,GACnB+a,IAAY/a,EAAI,CAAC,GACjBgb,IAAYhb,EAAI,EAAK,GAGrBib,IAAoBjb,EAGvB;AAAA,MACD,UAAU;AAAA,MACV,cAAc;AAAA,IAAA,CACf,GAGKkb,IAA2C;AAAA,MAC/C,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,IAAA,GAGFC,IAAiB1c,EAAS,MAAMP,EAAM,aAAa,EAAE,GAErDkd,KAAc3c,EAAS,MAAM;AACjC,UAAI,OAAOP,EAAM,UAAW;AAC1B,eAAO,GAAGA,EAAM,MAAM;AAExB,UAAI,OAAOA,EAAM,UAAW,UAAU;AACpC,YAAI,iBAAiB,KAAKA,EAAM,MAAM;AACpC,iBAAOA,EAAM;AAEf,YAAIgd,EAAiBhd,EAAM,MAAM;AAC/B,iBAAOgd,EAAiBhd,EAAM,MAAM;AAAA,MAExC;AACA,aAAO;AAAA,IACT,CAAC,GAEKmd,IAAc5c,EAAwB,MACrC2c,GAAY,QAGV;AAAA,MACL,cAAcA,GAAY;AAAA,IAAA,IAHnB,CAAA,CAKV,GAEKE,KAAa7c,EAAS,MACnB;AAAA,MACL;AAAA,MACAP,EAAM,UAAU,mBAAmB;AAAA,IAAA,EACnC,OAAO,OAAO,EAAE,KAAK,GAAG,CAC3B,GAEKqd,KAAa9c,EAAS,MAAM;AAChC,YAAMkH,IAAuB;AAAA,QAC3B,WAAWzH,EAAM,OAAO;AAAA,QACxB,iBAAiB;AAAA,MAAA;AAGnB,aAAIA,EAAM,UACRyH,EAAM,QAAQ,OAAOzH,EAAM,SAAU,WAAW,GAAGA,EAAM,KAAK,OAAOA,EAAM,QAGzEA,EAAM,WACRyH,EAAM,SAAS,OAAOzH,EAAM,UAAW,WAAW,GAAGA,EAAM,MAAM,OAAOA,EAAM,SAG5Ekd,GAAY,UACdzV,EAAM,eAAeyV,GAAY,QAG5BzV;AAAA,IACT,CAAC,GAEK6V,IAAqB/c,EAAS,MAC9Bqc,EAAW,QACNA,EAAW,QAEhB,MAAM,QAAQ5c,EAAM,cAAc,IAC7BA,EAAM,eAAe,KAAK,OAAO,KAAKA,EAAM,MAE9CA,EAAM,kBAAkBA,EAAM,GACtC,GAIKud,IAAoB,MAAM;AAC9B,YAAMC,IAAY,SAAS,cAAc,KAAK;AAC9C,MAAAA,EAAU,MAAM,UAAU,oFAC1B,SAAS,KAAK,YAAYA,CAAS;AACnC,YAAMvY,IAAiBuY,EAAU,cAAcA,EAAU;AACzD,sBAAS,KAAK,YAAYA,CAAS,GAC5BvY;AAAA,IACT,GAGMwY,IAAiB,MAAM;AAU3B,UARAV,EAAkB,QAAQ;AAAA,QACxB,UAAU,SAAS,KAAK,MAAM,YAAY;AAAA,QAC1C,cAAc,SAAS,KAAK,MAAM,gBAAgB;AAAA,MAAA,GAI/B,SAAS,KAAK,eAAe,OAAO,aAEvC;AAChB,cAAM9X,IAAiBsY,EAAA;AAEvB,iBAAS,KAAK,MAAM,eAAe,GAAGtY,CAAc;AAAA,MACtD;AAGA,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC,GAGMyY,IAAmB,MAAM;AAE7B,eAAS,KAAK,MAAM,WAAWX,EAAkB,MAAM,UACvD,SAAS,KAAK,MAAM,eAAeA,EAAkB,MAAM;AAAA,IAC7D;AAGA,QAAIY,KAAwC;AAE5C,UAAMC,KAA4B,MAAM;AACtC,MAAI,CAAC5d,EAAM,QAAQ,CAACmc,EAAa,UAEjCwB,KAAW,IAAI;AAAA,QACb,CAACE,MAAY;AACX,UAAAA,EAAQ,QAAQ,CAACC,MAAU;AACzB,YAAIA,EAAM,mBACRrB,EAAS,QAAQ,IACjBE,EAAO,QAAQ3c,EAAM,KACrB2d,MAAA,QAAAA,GAAU,UAAUG,EAAM;AAAA,UAE9B,CAAC;AAAA,QACH;AAAA,QACA;AAAA,UACE,YAAY;AAAA,QAAA;AAAA,MACd,GAGFH,GAAS,QAAQxB,EAAa,KAAK;AAAA,IACrC,GAGM4B,IAAa,CAACnN,MAAiB;AACnC,MAAA0L,EAAS,QAAQ,IACjBC,EAAU,QAAQ,IAClBC,EAAS,QAAQ,IACjBtc,EAAK,QAAQ0Q,CAAK;AAAA,IACpB,GAEMoN,KAAc,CAACpN,MAAiB;AACpC,MAAA4L,EAAS,QAAQ,IACjBD,EAAU,QAAQ,IAClBD,EAAS,QAAQ,IACjBpc,EAAK,SAAS0Q,CAAK;AAAA,IACrB,GAEMqN,IAAY,MAAM;AACtB,MAAAzB,EAAS,QAAQ,IACjBD,EAAU,QAAQ,IAClBD,EAAS,QAAQ,IAEjBnT,GAAS,MAAM;AACb,QAAIiT,EAAS,UACXA,EAAS,MAAM,MAAMpc,EAAM;AAAA,MAE/B,CAAC;AAAA,IACH,GAEMke,IAAgB,MAChB,MAAM,QAAQle,EAAM,cAAc,IAC7BA,EAAM,eAAe,KAAK,OAAO,KAAKA,EAAM,MAE9CA,EAAM,kBAAkBA,EAAM,KAGjCme,IAAmB,MAAM;AAE7B,MAAIne,EAAM,YAAYA,EAAM,kBAAkBA,EAAM,OAClDoe,EAAA,IAEAH,EAAA;AAAA,IAEJ,GAEMG,IAAgB,MAAM;AAC1B,UAAI,CAACpe,EAAM,QAAS;AAGpB,MAAA6c,EAAU,QAAQ;AAGlB,YAAMwB,IAAaH,EAAA;AAGnB,UAAI9B,EAAS,SAASA,EAAS,MAAM,YAAYA,EAAS,MAAM,eAAe,GAAG;AAChF,QAAAQ,EAAW,QAAQyB,GACnBlV,GAAS,MAAM;AACb,UAAAuT,EAAY,QAAQ,IACpBe,EAAA,GACAvd,EAAK,WAAWme,CAAU;AAAA,QAC5B,CAAC;AACD;AAAA,MACF;AAGA,YAAMC,IAAM,IAAI,MAAA;AAChB,UAAIC,KAAkD,MAClDC,KAAY;AAEhB,YAAMC,KAAmB,MAAM;AAC7B,QAAID,OACJA,KAAY,IAERD,OACF,aAAaA,EAAS,GACtBA,KAAY,OAGd3B,EAAW,QAAQyB,GACnBlV,GAAS,MAAM;AACb,UAAAuT,EAAY,QAAQ,IACpBe,EAAA,GACAvd,EAAK,WAAWme,CAAU;AAAA,QAC5B,CAAC;AAAA,MACH;AAGA,MAAAE,KAAY,WAAW,MAAM;AAC3B,QAAAE,GAAA;AAAA,MACF,GAAG,GAAG,GAENH,EAAI,SAAS,MAAM;AACjB,QAAAG,GAAA;AAAA,MACF,GAEAH,EAAI,UAAU,MAAM;AAElB,QAAAG,GAAA;AAAA,MACF,GAGAH,EAAI,MAAMD,GAGNC,EAAI,YACNG,GAAA;AAAA,IAEJ,GAEMC,IAAe,MAAM;AACzB,MAAAhC,EAAY,QAAQ,IAGpB,WAAW,MAAM;AACf,QAAAgB,EAAA;AAAA,MACF,GAAG,GAAG;AAAA,IACR,GAEMiB,IAAc,CAAC/N,MAAsB;AAEzC,YAAMgO,IAAgBhO,EAAM,SAAS,IAAI,IAAI;AAI7C,UAAIiO,KAAUhC,EAAU,QAAS+B,IADhB;AAIjB,MAAAC,KAAU,KAAK,IAAI,KAAK,KAAK,IAAI,GAAKA,EAAO,CAAC,GAG9ChC,EAAU,QAAQgC;AAAA,IACpB;AAGA,WAAAzS,GAAU,MAAM;AACd,MAAKpM,EAAM,OAGT4d,GAAA,IAFAnB,EAAS,QAAQ,IAKfA,EAAS,UACXF,EAAU,QAAQ,KAIpBO,EAAU,QAAQ;AAAA,IACpB,CAAC,GAEDxQ,GAAY,MAAM;AAChB,MAAIqR,MACFA,GAAS,WAAA,GAIPjB,EAAY,SACdgB,EAAA;AAAA,IAEJ,CAAC,GAWDvb,GAAM,MAAMwa,EAAO,OARF,MAAM;AACrB,MAAI3c,EAAM,OAAOyc,EAAS,UACxBF,EAAU,QAAQ,IAClBC,EAAS,QAAQ,IACjBF,EAAS,QAAQ;AAAA,IAErB,CAEkC,GAClCna,GAAM,MAAMnC,EAAM,KAAK,CAAC8e,MAAO;AAC7B,MAAAnC,EAAO,QAAQmC,KAAM;AAAA,IACvB,CAAC,GAED7J,EAAa;AAAA,MACX,WAAAgJ;AAAA,MACA,cAAAS;AAAA,IAAA,CACD,mBApdC9d,EA+FM,OAAA;AAAA,eA9FA;AAAA,MAAJ,KAAIub;AAAA,MACJ,OAAKtZ,EAAA,CAAC,oBACEoa,EAAA,KAAc,CAAA;AAAA,IAAA;OAIbX,EAAA,SAAQ,CAAKE,EAAA,SAAQ,CAAKC,EAAA,cADnC7b,EAUM,OAAA;AAAA;QARJ,OAAM;AAAA,QACL,UAAOuc,EAAA,KAAW;AAAA,MAAA;QAEnBhc,EAIM,OAAA,EAJD,OAAM,gCAA4B;AAAA,UACrCA,EAEM,OAAA;AAAA,YAFD,OAAM;AAAA,YAA0B,MAAK;AAAA,YAAO,QAAO;AAAA,YAAe,SAAQ;AAAA,UAAA;YAC7EA,EAA2O,QAAA;AAAA,cAArO,kBAAe;AAAA,cAAQ,mBAAgB;AAAA,cAAQ,gBAAa;AAAA,cAAI,GAAE;AAAA,YAAA;;;;MAOtEob,EAAA,UAAcC,EAAA,cADtB5b,EAQM,OAAA;AAAA;QANJ,OAAM;AAAA,QACL,UAAOuc,EAAA,KAAW;AAAA,MAAA;QAEnBhc,EAEM,OAAA,EAFD,OAAM,4BAAwB;AAAA,UACjCA,EAAkC,OAAA,EAA7B,OAAM,kBAAgB;AAAA,QAAA;;MAMvBqb,EAAA,cADR5b,EAYM,OAAA;AAAA;QAVJ,OAAM;AAAA,QACL,UAAOuc,EAAA,KAAW;AAAA,QAClB,SAAOgB;AAAA,MAAA;QAERhd,EAKE,OAAA;AAAA,UAJA,KAAI;AAAA,UACJ,KAAI;AAAA,UACJ,OAAM;AAAA,UACL,UAAOgc,EAAA,KAAW;AAAA,QAAA;;SAKvBhc,EAUE,OAAA;AAAA,iBARI;AAAA,QAAJ,KAAIib;AAAA,QACH,KAAKO,EAAA;AAAA,QACL,KAAK1c,EAAA;AAAA,QACL,SAAOmd,GAAA,KAAU;AAAA,QACjB,QAAMW;AAAA,QACN,SAAOC;AAAA,QACP,WAAYI,GAAa,CAAA,MAAA,CAAA;AAAA,QACzB,UAAOf,GAAA,KAAU;AAAA,MAAA;QARV,CAAA0B,IAAAzC,EAAA,UAAaE,EAAA,KAAQ;AAAA,MAAA;MAavBxc,EAAM,YAAO,CAAMsc,EAAA,SAAYC,EAAA,SAAaC,EAAA,SAAQ,CAAKC,EAAA,eADjE7b,EAIO,OAAA;AAAA;QAFL,OAAM;AAAA,QACL,WAAYwd,GAAa,CAAA,MAAA,CAAA;AAAA,MAAA;MAIFtB,EAAA,cAA1BhP,GA6BW0D,IAAA;AAAA;QA7BD,IAAG;AAAA,MAAA;QACX7E,GA2BaC,IAAA,EA3BD,MAAK,UAAM;AAAA,sBACrB,MAyBM;AAAA,YAxBE8P,EAAA,cADR9b,EAyBM,OAAA;AAAA;cAvBJ,OAAM;AAAA,cACL,WAAY8d,GAAY,CAAA,MAAA,CAAA;AAAA,cACxB,WAAeC,GAAW,CAAA,SAAA,CAAA;AAAA,YAAA;cAE3Bxd,EAWM,OAAA;AAAA,gBAXD,OAAK0B,EAAA,CAAC,0BAAwB,EAAA,aACR6Z,EAAA,OAAW,CAAA;AAAA,cAAA;gBAEpCvb,EAOE,OAAA;AAAA,2BANI;AAAA,kBAAJ,KAAIkb;AAAA,kBACH,KAAKiB,EAAA;AAAA,kBACL,KAAKrd,EAAA;AAAA,kBACN,OAAM;AAAA,kBACL,gCAA6B4c,EAAA,KAAS,KAAA;AAAA,kBACtC,2BAAD,MAAA;AAAA,kBAAA,GAAW,CAAA,MAAA,CAAA;AAAA,gBAAA;;;;;;;;;;;;;;;;;;ACtCzB,UAAM7c,IAAQC,GAORoS,IAAUvQ,EAAI,EAAK,GACnBkd,IAAcld,EAAA;AACpB,QAAImd,IAA2B;AAG/B,UAAMC,IAAY3e,EAAS,MAClB,qBAAqBP,EAAM,SAAS,EAC5C,GAEKmf,IAAY5e,EAAS,MAAM;AAC/B,UAAI,CAACP,EAAM,UAAW,QAAO,CAAA;AAC7B,YAAMkF,IACJ,OAAOlF,EAAM,aAAc,WACvB,GAAGA,EAAM,SAAS,OAClBA,EAAM;AACZ,aAAO;AAAA,QACL,OAAAkF;AAAA,QACA,UAAUA;AAAA,QACV,UAAUA;AAAA,MAAA;AAAA,IAEd,CAAC,GAGKka,IAAe,MAAM;AAEzB,MADA,QAAQ,IAAI,UAAU/M,EAAQ,KAAK,GAC/B,CAAArS,EAAM,aAGNif,MACF,aAAaA,CAAS,GACtBA,IAAY,OAGd5M,EAAQ,QAAQ,IAChB,QAAQ,IAAI,qBAAqBA,EAAQ,KAAK,GAG9ClJ,GAAS,MAAM;AACb,QAAAgL,EAAA;AAAA,MACF,CAAC;AAAA,IACH,GAGMkL,IAAe,MAAM;AACzB,cAAQ,IAAI,QAAQ,GAEpBJ,IAAY,WAAW,MAAM;AAC3B,QAAA5M,EAAQ,QAAQ,IAChB,QAAQ,IAAI,sBAAsBA,EAAQ,KAAK;AAAA,MACjD,GAAG,GAAG;AAAA,IACR,GAGM8B,IAAiB,MAAM;AAC3B,UAAI,CAAC6K,EAAY,MAAO;AAExB,YAAM5P,IAAU4P,EAAY,MAAM,cAAc,sBAAsB,GAChEM,IAAON,EAAY,MAAM,cAAc,mBAAmB;AAEhE,UAAI,CAAC5P,KAAW,CAACkQ,EAAM;AAGvB,YAAM/P,IAAcH,EAAQ,sBAAA,GACtBmQ,IAAWD,EAAK,sBAAA,GAChBvL,IAAgB,OAAO,YACvB1K,IAAiB,OAAO;AAG9B,MAAAiW,EAAK,MAAM,MAAM,IACjBA,EAAK,MAAM,OAAO,IAClBA,EAAK,MAAM,QAAQ,IACnBA,EAAK,MAAM,SAAS,IACpBA,EAAK,MAAM,YAAY;AAEvB,UAAIhM,IAAM,GACNC,IAAO;AAGX,cAAQvT,EAAM,WAAA;AAAA,QACZ,KAAK;AACH,UAAAsT,IAAM/D,EAAY,SAAS,GAC3BgE,IAAO;AACP;AAAA,QAEF,KAAK;AACH,UAAAD,IAAM,EAAEiM,EAAS,SAAS,IAC1BhM,IAAO;AACP;AAAA,QAEF,KAAK;AACH,UAAAD,IAAM,GACNC,IAAOhE,EAAY,QAAQ;AAC3B;AAAA,QAEF,KAAK;AACH,UAAA+D,IAAM,GACNC,IAAO,EAAEgM,EAAS,QAAQ;AAC1B;AAAA,MAAA;AAIJ,UAAIC,KAAcjQ,EAAY,MAAM+D,GAChCmM,IAAelQ,EAAY,OAAOgE;AAGtC,UAAIvT,EAAM,cAAc,YAAYA,EAAM,cAAc,OAAO;AAC7D,cAAM0f,KAAYH,EAAS,SAAS;AAGpC,QAAIE,IAAeC,KAAY3L,IAAgB,OAC7C0L,IAAe1L,IAAgB2L,KAAY,KAIzCD,IAAe,OACjBA,IAAe;AAAA,MAEnB;AAGA,UAAIzf,EAAM,cAAc,UAAUA,EAAM,cAAc,SAAS;AAC7D,cAAM2f,KAAaJ,EAAS,UAAU;AAGtC,QAAIC,KAAcG,KAAatW,IAAiB,OAC9CmW,KAAcnW,IAAiBsW,KAAa,KAI1CH,KAAc,OAChBA,KAAc;AAAA,MAElB;AAGA,MAAAF,EAAK,MAAM,MAAM,GAAGE,EAAW,MAC/BF,EAAK,MAAM,OAAO,GAAGG,CAAY;AAAA,IACnC,GAGMpO,IAAqB,CAACT,MAAsB;AAChD,MAAI5Q,EAAM,YAAY,WAAWgf,EAAY,SAAS,CAACA,EAAY,MAAM,SAASpO,EAAM,MAAc,MACpGyB,EAAQ,QAAQ;AAAA,IAEpB,GAGMvG,IAAe,MAAM;AACzB,MAAIuG,EAAQ,SACV8B,EAAA;AAAA,IAEJ;AAEA,WAAA/H,GAAU,MAAM;AACd,MAAIpM,EAAM,YAAY,WACpB,SAAS,iBAAiB,SAASqR,CAAkB,GAGvD,OAAO,iBAAiB,UAAUvF,CAAY,GAE9C,OAAO,iBAAiB,UAAUA,CAAY;AAAA,IAChD,CAAC,GAEDQ,GAAY,MAAM;AAChB,MAAItM,EAAM,YAAY,WACpB,SAAS,oBAAoB,SAASqR,CAAkB,GAGtD4N,KACF,aAAaA,CAAS,GAGxB,OAAO,oBAAoB,UAAUnT,CAAY,GACjD,OAAO,oBAAoB,UAAUA,CAAY;AAAA,IACnD,CAAC,GAED3J;AAAA,MACE,MAAMnC,EAAM;AAAA,MACZ,MAAM;AACJ,QAAIqS,EAAQ,SACVlJ,GAAS,MAAM;AACb,UAAAgL,EAAA;AAAA,QACF,CAAC;AAAA,MAEL;AAAA,IAAA,mBA3OAvT,EA+BM,OAAA;AAAA,MA/BD,OAAM;AAAA,eAAiB;AAAA,MAAJ,KAAIoe;AAAA,IAAA;MAE1B7d,EAUM,OAAA;AAAA,QATJ,OAAM;AAAA,QACL,cAAYie;AAAA,QACZ,cAAYC;AAAA,MAAA;QAEb1d,GAIOC,yBAJP,MAIO;AAAA,UAHLN,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAH,EAES,UAAA,EAFD,OAAM,wBAAqB,UAEnC,EAAA;AAAA,QAAA;;MAKJwL,GAeaC,IAAA;AAAA,QAfD,MAAK;AAAA,QAAgB,QAAA;AAAA,MAAA;oBAC/B,MAaM;AAAA,aAbNzL,EAaM,OAAA;AAAA,YAXJ,OAAK0B,EAAA,CAAC,oBACEqc,EAAA,KAAS,CAAA;AAAA,YAChB,UAAOC,EAAA,KAAS;AAAA,YAChB,cAAYC;AAAA,YACZ,cAAYC;AAAA,UAAA;YAEb1d,GAIOC,yBAJP,MAIO;AAAA,cAHLN,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAH,EAAwC,OAAA,EAAnC,OAAM,mBAAA,GAAmB,QAAI,EAAA;AAAA,cAClCG,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAH,EAAwC,OAAA,EAAnC,OAAM,mBAAA,GAAmB,QAAI,EAAA;AAAA,cAClCG,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAAH,EAAwC,OAAA,EAAnC,OAAM,sBAAmB,QAAI,EAAA;AAAA,YAAA;;iBAV5BkR,EAAA,KAAO;AAAA,UAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;ACuCvB,UAAMrS,IAAQC,GAsBRC,IAAOC,GAMPkS,IAAU9R,EAAS;AAAA,MACvB,KAAK,MAAMP,EAAM;AAAA,MACjB,KAAK,CAACsS,MAAepS,EAAK,qBAAqBoS,CAAC;AAAA,IAAA,CACjD,GAEKC,IAAWzQ,EAAwB,IAAI,GAEvC8d,IAAiBrf,EAAS,MAAMP,EAAM,cAAc,UAAU,uBAAuB,qBAAqB,GAE1G6f,IAAetf,EAAS,MAAMP,EAAM,cAAc,UAAU,iBAAiB,aAAa,GAE1FwS,IAAajS,EAAS,MAAM;AAChC,YAAMkH,IAAgC,CAAA;AACtC,aAAIzH,EAAM,cAAc,WACtByH,EAAM,QAAQ,OAAOzH,EAAM,SAAU,WAAW,GAAGA,EAAM,KAAK,OAAO,OAAOA,EAAM,KAAK,GACvFyH,EAAM,SAAS,QACfA,EAAM,QAAQ,KACdA,EAAM,MAAM,QAEZA,EAAM,SAAS,OAAOzH,EAAM,UAAW,WAAW,GAAGA,EAAM,MAAM,OAAO,OAAOA,EAAM,MAAM,GAC3FyH,EAAM,QAAQ,QACdA,EAAM,SAAS,KACfA,EAAM,OAAO,MAERA;AAAA,IACT,CAAC;AAED,aAASgL,IAAc;AACrB,MAAKzS,EAAM,gBACX0S,EAAA;AAAA,IACF;AAEA,aAASA,IAAQ;AACf,MAAKL,EAAQ,UACbA,EAAQ,QAAQ,IAChBnS,EAAK,OAAO;AAAA,IACd;AAEA,aAASyS,IAAQ;AACf,MAAI3S,EAAM,YAAU0S,EAAA;AAAA,IACtB;AAEA,aAASE,EAAU3H,GAAkB;AACnC,MAAIA,EAAE,QAAQ,YAAU0H,EAAA;AAAA,IAC1B;AAEA,WAAAxQ,GAAM,MAAMnC,EAAM,YAAY,CAACsS,MAAM;AACnC,MAAIA,KACFpS,EAAK,MAAM,GAEX,sBAAsB,MAAA;;AAAM,gBAAAe,IAAAsR,EAAS,UAAT,gBAAAtR,EAAgB;AAAA,OAAO,GACnD,SAAS,iBAAiB,WAAW2R,CAAS,GAC9C,SAAS,KAAK,MAAM,WAAW,aAE/B,SAAS,oBAAoB,WAAWA,CAAS,GACjD,SAAS,KAAK,MAAM,WAAW;AAAA,IAEnC,CAAC,GAEDxG,GAAU,MAAM;AACd,MAAIpM,EAAM,eACR,SAAS,iBAAiB,WAAW4S,CAAS,GAC9C,SAAS,KAAK,MAAM,WAAW;AAAA,IAEnC,CAAC,GAEDtG,GAAY,MAAM;AAChB,eAAS,oBAAoB,WAAWsG,CAAS,GACjD,SAAS,KAAK,MAAM,WAAW;AAAA,IACjC,CAAC,mBAzJC9E,GAkDW0D,IAAA,EAlDD,IAAG,UAAM;AAAA,SACjBrQ,EAgDM,OAAA;AAAA,QA9CJ,OAAM;AAAA,QACN,MAAK;AAAA,QACJ,cAAY;AAAA,QACZ,gBAAckR,EAAA;AAAA,QACd,OAAKlF,GAAA,EAAA,QAAY,OAAOlN,EAAA,MAAM,GAAA;AAAA,MAAA;QAE/BkB,EAGO,OAAA;AAAA,UAFL,OAAM;AAAA,UACL,SAAOsR;AAAA,QAAA;QAGV9F,GAkCaC,IAAA,EAlCA,MAAMgT,EAAA,SAAc;AAAA,sBAC/B,MAgCM;AAAA,eAhCNze,EAgCM,OAAA;AAAA,uBA9BA;AAAA,cAAJ,KAAIoR;AAAA,cACJ,UAAM,kBAAgB;AAAA,sBACOtS,EAAA,SAAS;AAAA,gBAAiB4f,EAAA;AAAA,cAAA;cAItD,UAAOrN,EAAA,KAAU;AAAA,cACjB,gBAA0BG,GAAK,CAAA,WAAA,MAAA,CAAA,GAAA,CAAA,KAAA,CAAA;AAAA,cAChC,UAAS;AAAA,YAAA;cAEE1S,EAAA,cAAXU,EAAA,GAAAC,EAWM,OAXNC,IAWM;AAAA,gBAVJM,EAA6C,OAA7C4L,IAA6CtL,GAAdxB,EAAA,KAAK,GAAA,CAAA;AAAA,gBAE5BA,EAAA,iBADRW,EAQS,UAAA;AAAA;kBANP,MAAK;AAAA,kBACL,OAAM;AAAA,kBACN,cAAW;AAAA,kBACV,SAAO8R;AAAA,gBAAA,GACT,KAED;;cAGFvR,EAEM,OAFNC,IAEM;AAAA,gBADJO,GAAQC,EAAA,QAAA,WAAA,CAAA,GAAA,QAAA,EAAA;AAAA,cAAA;cAGCiR,EAAAA,OAAO,UAAlBlS,KAAAC,EAEM,OAFNS,IAEM;AAAA,gBADJM,GAAsBC,EAAA,QAAA,UAAA,CAAA,GAAA,QAAA,EAAA;AAAA,cAAA;;mBA7BhByQ,EAAA,KAAO;AAAA,YAAA;;;;;aAdXA,EAAA,KAAO;AAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sEC6rBfyN,KACJ,oHACIC,KACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEF,UAAM/f,IAAQC,GAwCRC,IAAOC,GA6CP6f,IAAWzf,EAAS,OACxB,QAAQ,IAAI,mBAAmBP,EAAM,IAAI,GAClCA,EAAM,QAAQ,CAAA,EACtB,GAIKigB,IAAQne,EAAI;AAAA,MAChB,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,iCAAiB,IAAA;AAAA,MACjB,kCAAkB,IAAA;AAAA,MAClB,kCAAkB,IAAA;AAAA,MAClB,qCAAqB,IAAA;AAAA,IAAqB,CAC3C;AAED,IAAAyC,GAAQ,aAAa0b,CAAK;AAG1B,UAAMC,IAAyB3f,EAA6B,MAEnDP,EAAM,+BAA+BA,EAAM,8BAA8B,IAC5EA,EAAM,8BACN,MACL;AAED,aAASmgB,EAAWC,GAAiC;AACnD,aAAOA,EAAKpgB,EAAM,OAAO,KAAKogB,EAAK,MAAM,KAAK,OAAA;AAAA,IAChD;AAEA,aAASC,EAAaD,GAAwB;;AAC5C,eAAQnf,IAAAjB,EAAM,UAAN,QAAAiB,EAAa,QAAQmf,EAAKpgB,EAAM,MAAM,KAAK,IAAI,WAAcogB,EAAK,SAAS;AAAA,IACrF;AAEA,aAASE,EAAeF,GAAoB;;AAC1C,aAAO,IAAQnf,IAAAmf,KAAA,gBAAAA,EAAM,SAAN,QAAAnf,EAAY;AAAA,IAC7B;AAEA,aAASsf,EAAYH,GAAWI,GAA6B;;AAC3D,YAAMC,IAAOzgB,EAAM,eAAe8f,IAC5BY,IAAS1gB,EAAM,iBAAiB+f,IAChCY,IAAS3gB,EAAM,iBAAiB,IAChC4gB,IAAiB5gB,EAAM,qBAAqB;AAGlD,aAAIwgB,KAAYI,KAAkBC,EAAiBT,GAAMI,CAAQ,IACxDI,KAIL3f,IAAAmf,KAAA,gBAAAA,EAAM,SAAN,QAAAnf,EAAY,YAAY0f,IAAeA,IAEpCL,EAAeF,CAAI,IAAIM,IAASD;AAAA,IACzC;AAEA,aAASK,EAAYV,GAAyB;;AAC5C,YAAMW,MAAY9f,IAAAjB,EAAM,UAAN,QAAAiB,EAAa,WAAWmf,EAAKpgB,EAAM,MAAM,QAAQ,IAAI,WAAcogB,EAAK;AAC1F,aAAOW,KAAYA,EAAS,SAAS;AAAA,IACvC;AAEA,aAASC,EAAgBZ,GAA4B;;AACnD,eAAQnf,IAAAjB,EAAM,UAAN,QAAAiB,EAAa,WAAWmf,EAAKpgB,EAAM,MAAM,QAAQ,IAAI,WAAcogB,EAAK,YAAY,CAAA;AAAA,IAC9F;AAGA,aAASa,EACPb,GACAc,GACAC,IAAuB,GACf;AACR,UAAIf,MAASc;AACX,eAAOC;AAGT,YAAMJ,IAAWC,EAAgBZ,CAAI;AACrC,iBAAWgB,KAASL,GAAU;AAC5B,cAAMM,IAAQJ,EAAaG,GAAOF,GAAYC,IAAe,CAAC;AAC9D,YAAIE,IAAQ;AACV,iBAAOA;AAAA,MAEX;AAEA,aAAO;AAAA,IACT;AAGA,aAASR,EAAiBT,GAAgBI,GAA6B;AACrE,aAAI,CAACxgB,EAAM,mBAAmBA,EAAM,kBAAkB,IAC7C,KAEKihB,EAAaT,GAAUJ,CAAI,MACxBpgB,EAAM;AAAA,IACzB;AAOA,aAASshB,EAAelB,GAAyB;AAC/C,YAAMmB,IAAUpB,EAAWC,CAAI;AAC/B,aAAOH,EAAM,MAAM,aAAa,IAAIsB,CAAO;AAAA,IAC7C;AAEA,aAASC,EAAcpB,GAAyB;AAC9C,YAAMmB,IAAUpB,EAAWC,CAAI;AAI/B,UAHwBH,EAAM,MAAM,YAAY,IAAIsB,CAAO,GAGtC;AACnB,YAAIT,EAAYV,CAAI,GAAG;AACrB,gBAAMW,IAAWC,EAAgBZ,CAAI,GAC/BqB,IAAkBV,EAAS,OAAO,CAACK,MAAUI,EAAcJ,CAAK,CAAC,GACjEM,IAAwBX,EAAS;AAAA,YAAO,CAACK,MAC7CO,EAAoBP,CAAK;AAAA,UAAA;AAI3B,iBACEK,EAAgB,WAAWV,EAAS,UACpCW,EAAsB,WAAW;AAAA,QAErC;AACA,eAAO;AAAA,MACT;AAGA,UAAIZ,EAAYV,CAAI,GAAG;AACrB,cAAMW,IAAWC,EAAgBZ,CAAI;AAKrC,eAH8BW,EAAS;AAAA,UAAK,CAACK,MAC3CO,EAAoBP,CAAK;AAAA,QAAA,IAEO,KAGhCL,EAAS,SAAS,KAAKA,EAAS,MAAM,CAACK,MAAUI,EAAcJ,CAAK,CAAC;AAAA,MAEzE;AAEA,aAAO;AAAA,IACT;AAEA,aAASO,EAAoBvB,GAAyB;AACpD,UAAI,CAACU,EAAYV,CAAI,EAAG,QAAO;AAE/B,YAAMW,IAAWC,EAAgBZ,CAAI,GAC/BqB,IAAkBV,EAAS,OAAO,CAACK,MAAUI,EAAcJ,CAAK,CAAC,GACjEM,IAAwBX,EAAS;AAAA,QAAO,CAACK,MAC7CO,EAAoBP,CAAK;AAAA,MAAA;AAI3B,aAAIK,EAAgB,WAAWV,EAAS,SAAe,KAGhDU,EAAgB,SAAS,KAAKC,EAAsB,SAAS;AAAA,IACtE;AAEA,aAASE,EAAcxB,GAAyB;AAC9C,YAAMja,IAAMga,EAAWC,CAAI;AAC3B,aAAOH,EAAM,MAAM,eAAe9Z;AAAA,IACpC;AAEA,aAAS0b,GAAkBzB,GAAyB;AAClD,YAAMja,IAAMga,EAAWC,CAAI;AAC3B,aAAOH,EAAM,MAAM,gBAAgB,IAAI9Z,CAAG;AAAA,IAC5C;AAEA,aAAS2b,EAAiB1B,GAAgB;AAExC,UAAIpgB,EAAM,SAAU;AAEpB,YAAMuhB,IAAUpB,EAAWC,CAAI,GAEzB2B,IAAkB,CADN9B,EAAM,MAAM,YAAY,IAAIsB,CAAO,GAI/CS,IAAsB,IAAI,IAAI/B,EAAM,MAAM,YAAY;AAG5D,MAAI8B,IACF9B,EAAM,MAAM,YAAY,IAAIsB,CAAO,IAEnCtB,EAAM,MAAM,YAAY,OAAOsB,CAAO;AAIxC,eAASU,EAAgBlB,GAAsBmB,GAAgB;AAC7D,QAAAnB,EAAS,QAAQ,CAACK,MAAU;AAC1B,gBAAMe,KAAWhC,EAAWiB,CAAK;AACjC,UAAIc,IACFjC,EAAM,MAAM,YAAY,IAAIkC,EAAQ,IAEpClC,EAAM,MAAM,YAAY,OAAOkC,EAAQ,GAIrCrB,EAAYM,CAAK,KACnBa,EAAgBjB,EAAgBI,CAAK,GAAGc,CAAK;AAAA,QAEjD,CAAC;AAAA,MACH;AAGA,MAAAD,EAAgBjB,EAAgBZ,CAAI,GAAG2B,CAAe,GAGlDA,KACFK,GAAiC,GAInCC,EAAA,GAGApC,EAAM,MAAM,eAAe+B,GAG3B9hB,EAAK,gBAAgBkgB,GAAM2B,GAAiB,EAAK,GACjD7hB,EAAK,SAASkgB,GAAM2B,GAAiB,EAAK,GAC1C7hB,EAAK,uBAAuB,MAAM,KAAK+f,EAAM,MAAM,WAAW,CAAC;AAAA,IACjE;AAGA,aAASmC,GAA6BE,GAAiB;AAErD,MAAIpC,EAAuB,SACzB,QAAQ;AAAA,QACN,QAAQA,EAAuB,KAAK;AAAA,MAAA;AAAA,IAG1C;AAGA,aAASqC,GAAkBnC,GAAgB;AACzC,YAAMmB,IAAUpB,EAAWC,CAAI;AAG/B,MAFmBH,EAAM,MAAM,aAAa,IAAIsB,CAAO,KAIrDtB,EAAM,MAAM,aAAa,OAAOsB,CAAO,GACvCrhB,EAAK,iBAAiBkgB,GAAMA,GAAM,IAAI,MAGtCH,EAAM,MAAM,aAAa,IAAIsB,CAAO,GACpCrhB,EAAK,eAAekgB,GAAMA,GAAM,IAAI;AAAA,IAExC;AAGA,aAASiC,IAAuB;AAE9B,YAAMG,IAAuB,CAAA;AAE7B,eAASC,EAAgBC,GAAmB;AAC1C,QAAAA,EAAM,QAAQ,CAACtC,MAAS;AACtB,UAAAoC,EAAS,KAAKpC,CAAI,GACdU,EAAYV,CAAI,KAClBqC,EAAgBzB,EAAgBZ,CAAI,CAAC;AAAA,QAEzC,CAAC;AAAA,MACH;AAEA,MAAAqC,EAAgBzC,EAAS,KAAK;AAG9B,eAAS2C,EAAkBvC,GAAgB;AACzC,YAAIU,EAAYV,CAAI,GAAG;AACrB,gBAAMW,IAAWC,EAAgBZ,CAAI,GAC/BmB,IAAUpB,EAAWC,CAAI,GAGzBqB,IAAkBV,EAAS,OAAO,CAACK,MAAUI,EAAcJ,CAAK,CAAC,GACjEM,IAAwBX,EAAS;AAAA,YAAO,CAACK,MAC7CO,EAAoBP,CAAK;AAAA,UAAA;AAI3B,UACEK,EAAgB,WAAWV,EAAS,UACpCW,EAAsB,WAAW,KAIjCD,EAAgB,SAAS,KACzBC,EAAsB,SAAS,IAH/BzB,EAAM,MAAM,YAAY,IAAIsB,CAAO,IASnCtB,EAAM,MAAM,YAAY,OAAOsB,CAAO;AAAA,QAE1C;AAAA,MACF;AAGA,eAAS9a,IAAI+b,EAAS,SAAS,GAAG/b,KAAK,GAAGA;AACxC,QAAAkc,EAAkBH,EAAS/b,CAAC,CAAC;AAAA,IAEjC;AAEA,aAASmc,EAAgBC,GAAgBzC,GAAW0C,GAAoBtC,GAAqB;AAC3F,UAAIxgB,EAAM,SAAU;AAGpB,YAAM+iB,IAAevC,IAAWK,EAAiBgC,GAAMrC,CAAQ,IAAI;AAGnE,UAAIxgB,EAAM,+BAA+B+iB,GAAc;AACrD,QAAA7iB,EAAK,oBAAoB2iB,GAAMzC,GAAM0C,CAAa;AAClD;AAAA,MACF;AAEA,UAAI9iB,EAAM,qBAAqB8gB,EAAY+B,CAAI,GAAG;AAChD,QAAAN,GAAkBM,CAAI;AACtB;AAAA,MACF;AAEA,MAAA5C,EAAM,MAAM,cAAc4C,GAC1B5C,EAAM,MAAM,aAAaE,EAAW0C,CAAI,GAGpC7iB,EAAM,gBACR8hB,EAAiBe,CAAI,GAIvB3iB,EAAK,cAAc2iB,GAAMzC,GAAM0C,CAAa;AAAA,IAC9C;AAEA,aAASE,EACPpS,GACAiS,GACAzC,GACA0C,GACA;AACA,MAAI9iB,EAAM,YACVE,EAAK,oBAAoB0Q,GAAOiS,GAAMzC,GAAM0C,CAAa;AAAA,IAC3D;AAGA,IAAA3gB;AAAA,MACE,MAAMnC,EAAM;AAAA,MACZ,CAACijB,MAAS;AACR,YAAIA,GAAM;AACR,gBAAMC,IAAgBhD,EAAuB;AAC7C,cAAIgD,GAAe;AAKjB,gBAASC,IAAT,SAAuBC,GAA4BV,GAAmBW,IAAQ,GAAW;AACvF,yBAAWC,MAAKZ,GAAO;AACrB,oBAAIvC,EAAWmD,EAAC,MAAMF,EAAW,QAAOC;AACxC,oBAAIvC,EAAYwC,EAAC,GAAG;AAClB,wBAAMC,KAAIJ,EAAcC,GAAWpC,EAAgBsC,EAAC,GAAGD,IAAQ,CAAC;AAChE,sBAAIE,KAAI,EAAG,QAAOA;AAAA,gBACpB;AAAA,cACF;AACA,qBAAO;AAAA,YACT,GAUSC,IAAT,SAA4Bd,GAAmBW,GAAeI,GAAkB;AAC9E,cAAAf,EAAM,QAAQ,CAACtC,OAAS;AACtB,gBAAIiD,IAAQI,KAAY3C,EAAYV,EAAI,KACtCsD,EAAgB,IAAIvD,EAAWC,EAAI,CAAC,GACpCoD,EAAmBxC,EAAgBZ,EAAI,GAAGiD,IAAQ,GAAGI,CAAQ,KACpDJ,IAAQI,KAAa3C,EAAYV,EAAI;AAAA,cAKlD,CAAC;AAAA,YACH;AAlBA,kBAAMuD,KAAYV,KAAQ,CAAA,GAAI,OAAO,CAACza,MAAM;AAC1C,oBAAM6Y,IAAQ8B,EAAc3a,GAAUwX,EAAS,OAAO,CAAC;AACvD,qBAAOqB,IAAQ,KAAKA,IAAQ6B;AAAA,YAC9B,CAAC,GACKQ,IAAkB,IAAI,IAAIC,CAAQ;AAexC,YAAAH,EAAmBxD,EAAS,OAAO,GAAGkD,CAAa,GAGnDjD,EAAM,MAAM,aAAa,QAAQ,CAAC9Z,MAAQ;AAExC,cADcgd,EAAchd,GAAK6Z,EAAS,OAAO,CAAC,KACrCkD,KACXQ,EAAgB,IAAIvd,CAAG;AAAA,YAE3B,CAAC,GAED8Z,EAAM,MAAM,eAAeyD;AAAA,UAC7B;AACE,YAAAzD,EAAM,MAAM,eAAe,IAAI,IAAIgD,CAAI;AAAA,QAE3C;AAAA,MACF;AAAA,MACA,EAAE,WAAW,GAAA;AAAA,IAAK;AAIpB,aAASW,IAAiB;AACxB,UAAI5jB,EAAM,kBAAkB;AAM1B,YAAS6jB,IAAT,SAA+BnB,GAAmBW,IAAgB,GAAG;AACnE,UAAAX,EAAM,QAAQ,CAACtC,MAAS;AACtB,gBAAI,CAACU,EAAYV,CAAI,EAAG;AAExB,kBAAMW,IAAWC,EAAgBZ,CAAI;AAErC,gBAAI8C,GAAe;AAEjB,kBAAIG,KAASH,EAAe;AAI5B,cADgCG,IAAQ,MAAMH,KAE5CY,EAAkB,IAAI3D,EAAWC,CAAI,CAAC,GAExCyD,EAAsB9C,GAAUsC,IAAQ,CAAC;AAAA,YAC3C;AAEE,cAAAS,EAAkB,IAAI3D,EAAWC,CAAI,CAAC,GACtCyD,EAAsB9C,GAAUsC,IAAQ,CAAC;AAAA,UAE7C,CAAC;AAAA,QACH;AA1BA,cAAMS,wBAAwB,IAAA,GAExBZ,IAAgBhD,EAAuB;AA0B7C,QAAA2D,EAAsB7D,EAAS,OAAO,CAAC,GAEvCC,EAAM,MAAM,eAAe6D;AAAA,MAC7B;AAAA,IACF;AAGA,aAASC,KAAoC;AAC3C,UAAI/jB,EAAM,sBAAsBA,EAAM,mBAAmB,SAAS,GAAG;AAInE,YAASgkB,IAAT,SACEtB,GACAuB,IAAkC,CAAA,GAClC;AACA,UAAAvB,EAAM,QAAQ,CAACtC,MAAS;AACtB,kBAAMmB,IAAUpB,EAAWC,CAAI,GACzB8D,IAAc,CAAC,GAAGD,GAAY1C,CAAO;AAG3C,YAAI4C,EAAY,IAAI5C,CAAO,KACzB0C,EAAW,QAAQ,CAAC9d,OAAQie,EAAe,IAAIje,EAAG,CAAC,GAIjD2a,EAAYV,CAAI,KAClB4D,EAAwBhD,EAAgBZ,CAAI,GAAG8D,CAAW;AAAA,UAE9D,CAAC;AAAA,QACH;AArBA,cAAMC,IAAc,IAAI,IAAInkB,EAAM,kBAAkB,GAC9CokB,wBAAqB,IAAA;AAsB3B,QAAAJ,EAAwBhE,EAAS,KAAK;AAEtC,cAAMkD,IAAgBhD,EAAuB;AAC7C,YAAIgD,GAAe;AAEjB,kBAAQ;AAAA,YACN,QAAQA,CAAa;AAAA,UAAA;AAEvB;AAAA,QACF;AAEA,QAAAjD,EAAM,MAAM,eAAemE;AAAA,MAC7B;AAAA,IACF;AAmBA,IAAAjiB,GAAM,MAAMnC,EAAM,kBAAkB4jB,GAAgB,EAAE,WAAW,IAAM,GAGvEzhB,GAAM,MAAM6d,EAAS,OAAO4D,GAAgB,EAAE,MAAM,IAAM,GAE1DzhB;AAAA,MACE,MAAMnC,EAAM;AAAA,MACZ,CAACijB,MAAS;AACR,QAAIA,KACFhD,EAAM,MAAM,cAAc,IAAI,IAAIgD,CAAI,GAGjCjjB,EAAM,mCAIT,QAAQ,IAAI,yBAAyB,IAFrC+jB,GAAA,KAKF9D,EAAM,MAAM,YAAY,MAAA;AAAA,MAE5B;AAAA,MACA,EAAE,WAAW,GAAA;AAAA,IAAK;AAIpB,aAASoE,GAAwBC,GAA6B;AAC5D,UAAI;AAKF,YAASC,IAAT,SACE7B,GACAU,GACAjc,IAA4B,CAAA,GACA;AAC5B,qBAAWmc,KAAKZ,GAAO;AACrB,kBAAM8B,IAAKrE,EAAWmD,CAAC,GACjBmB,KAAU,CAAC,GAAGtd,GAAMqd,CAAE;AAC5B,gBAAIA,MAAOpB,EAAW,QAAOqB;AAC7B,gBAAI3D,EAAYwC,CAAC,GAAG;AAClB,oBAAMoB,KAAIH,EAAcvD,EAAgBsC,CAAC,GAAGF,GAAWqB,EAAO;AAC9D,kBAAIC,GAAG,QAAOA;AAAA,YAChB;AAAA,UACF;AACA,iBAAO;AAAA,QACT;AAnBA,cAAMC,IAAY,MAAM,QAAQL,CAAG,IAAIA,IAAM,CAAA;AAC7C,YAAIK,EAAU,WAAW,EAAG;AAqB5B,QAAA1E,EAAM,MAAM,gBAAgB,MAAA;AAG5B,cAAM2E,IAAe,IAAI,IAAqB3E,EAAM,MAAM,YAAY;AAEtE,QAAA0E,EAAU,QAAQ,CAACE,MAAa;AAC9B,gBAAM1d,IAAOod,EAAcvE,EAAS,OAAO6E,CAAQ;AACnD,UAAI1d,KAAQA,EAAK,SAAS,MAExBA,EAAK,MAAM,GAAG,EAAE,EAAE,QAAQ,CAACqB,MAAMoc,EAAa,IAAIpc,CAAC,CAAC,GAEpDyX,EAAM,MAAM,gBAAgB,IAAI9Y,EAAKA,EAAK,SAAS,CAAC,CAAC;AAAA,QAEzD,CAAC,GAGD8Y,EAAM,MAAM,eAAe2E;AAAA,MAC7B,SAAS3Z,GAAG;AACV,gBAAQ,KAAK,gCAAgCA,CAAC;AAAA,MAChD;AAAA,IACF;AAGA,aAAS6Z,IAAkB;AACzB,MAAA7E,EAAM,MAAM,gBAAgB,MAAA;AAAA,IAC9B;AAGA,aAAS8E,KAAmB;AAC1B,MAAA9E,EAAM,MAAM,cAAc,MAC1BA,EAAM,MAAM,aAAa;AAAA,IAC3B;AAEA,WAAAhL,EAAa,EAAE,yBAAAoP,IAAyB,iBAAAS,GAAiB,kBAAAC,GAAA,CAAkB,GAE3E5iB;AAAA,MACE,MAAMnC,EAAM;AAAA,MACZ,CAACijB,MAAS;AACR,QAAIA,MACFhD,EAAM,MAAM,eAAe,IAAI,IAAIgD,CAAI;AAAA,MAE3C;AAAA,MACA,EAAE,WAAW,GAAA;AAAA,IAAK,mBA36ClBriB,EAurBM,OAAA;AAAA,MAtrBJ,OAAKiC,EAAA,CAAC,SAAO,CAAA,UACM5C,EAAA,IAAI,yBAAyBA,EAAA,SAAA,CAAQ,CAAA,CAAA;AAAA,IAAA;MAExDkB,EAkrBM,OAlrBN0L,IAkrBM;AAAA,gBAjrBJjM,EAgrBME,IAAA,MAAAC,GA/qBWif,EAAA,OAAQ,CAAhBI,YADTxf,EAgrBM,OAAA;AAAA,UA9qBH,KAAKuf,EAAWC,CAAI;AAAA,UACrB,OAAKvd,EAAA,CAAC,cAAY,EAAA,uBACe+e,EAAcxB,CAAI,GAAA,yBAA4ByB,GAAkBzB,CAAI,EAAA,CAAA,CAAA;AAAA,QAAA;UAErGjf,EAqGM,OAAA;AAAA,YApGJ,UAAM,uBAAqB,EAAA,kBACC0f,EAAiBT,GAAMA,CAAI,EAAA,CAAA,CAAA;AAAA,YACtD,OAAO,EAAA,aAAA,MAAA;AAAA,YACP,cAAYa,EAAab,GAAMA,CAAI;AAAA,YACnC,gBAAOwC,EAAgBxC,GAAMA,SAAYA,CAAI;AAAA,YAC7C,sBAAa4C,EAAsB9hB,GAAQkf,GAAMA,GAAI,IAAA;AAAA,UAAA;YAI9CU,EAAYV,CAAI,UADxBxf,EAeO,QAAA;AAAA;cAbL,OAAKiC,EAAA,CAAC,2BAAyB,EAAA,eACNye,EAAelB,CAAI,EAAA,CAAA,CAAA;AAAA,cAC3C,SAAK9O,EAAA,CAAApQ,MAAOqhB,GAAkBnC,CAAI,GAAA,CAAA,MAAA,CAAA;AAAA,YAAA;cAEnCjf,EAQM,OAAA;AAAA,gBARD,OAAM;AAAA,gBAAK,QAAO;AAAA,gBAAK,SAAQ;AAAA,gBAAY,MAAK;AAAA,cAAA;gBACnDA,EAME,QAAA;AAAA,kBALA,GAAE;AAAA,kBACF,QAAO;AAAA,kBACP,gBAAa;AAAA,kBACb,kBAAe;AAAA,kBACf,mBAAgB;AAAA,gBAAA;;6BAKtBR,EAAA,GAAAC,EAAqC,QAArCmM,EAAqC;AAAA,YAI7B9M,EAAA,qBADRW,EAsCO,QAAA;AAAA;cApCL,UAAM,wBAAsB;AAAA,gBACU,cAAA4gB,EAAcpB,CAAI;AAAA,gBAAqC,oBAAAuB,EAAoBvB,CAAI;AAAA,cAAA;cAIpH,SAAK9O,EAAA,CAAApQ,MAAO4gB,EAAiB1B,CAAI,GAAA,CAAA,MAAA,CAAA;AAAA,YAAA;cAG1BoB,EAAcpB,CAAI,KAD1Bzf,EAAA,GAAAC,EAcM,OAdNS,IAcM,CAAA,GAAAC,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBAPJH,EAME,QAAA;AAAA,kBALA,GAAE;AAAA,kBACF,QAAO;AAAA,kBACP,gBAAa;AAAA,kBACb,kBAAe;AAAA,kBACf,mBAAgB;AAAA,gBAAA;sBAIPwgB,EAAoBvB,CAAI,KADrCzf,KAAAC,EAaM,OAbNW,IAaM,CAAA,GAAAD,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gBANJH,EAKE,QAAA;AAAA,kBAJA,GAAE;AAAA,kBACF,QAAO;AAAA,kBACP,gBAAa;AAAA,kBACb,kBAAe;AAAA,gBAAA;;;YAOblB,EAAA,kBADRW,EAIQ,QAAA;AAAA;cAFN,OAAKiC,EAAA,CAAC,oBACE5C,EAAA,SAAS,CAAA;AAAA,YAAA;YAInBkB,EAIE,OAAA;AAAA,cAHA,OAAM;AAAA,cACL,KAAKof,EAAYH,GAAMA,CAAI;AAAA,cAC3B,KAAKE,EAAeF,CAAI,IAAA,WAAA;AAAA,YAAA;YAI3Bjf,EAKO,QAAA;AAAA,cAJL,OAAK0B,EAAA,CAAC,qBAAmB,EAAA,eACAyd,EAAeF,CAAI,GAAA,CAAA;AAAA,YAAA,GAEzC3e,GAAA4e,EAAaD,CAAI,CAAA,GAAA,CAAA;AAAA,YAItBjf,EAQM,OARN6L,IAQM;AAAA,cAPJrL,GAMEC,EAAA,QAAA,gBAAA;AAAA,gBAJC,MAAAwe;AAAA,gBACA,WAAYwB,EAAcxB,CAAI;AAAA,gBAC9B,YAAakB,EAAelB,CAAI;AAAA,gBAChC,aAAcU,EAAYV,CAAI;AAAA,cAAA;;;UAMrCzT,GAikBaC,IAAA,EAjkBD,MAAK,gBAAY;AAAA,wBAC3B,MA+jBM;AAAA,cA9jBEkU,EAAYV,CAAI,KAAKkB,EAAelB,CAAI,KADhDzf,KAAAC,EA+jBM,OA/jBNqM,IA+jBM;AAAA,iBA3jBJtM,EAAA,EAAA,GAAAC,EA0jBME,IAAA,MAAAC,GAzjBYigB,EAAgBZ,CAAI,IAA7BgB,YADTxgB,EA0jBM,OAAA;AAAA,kBAxjBH,KAAKuf,EAAWiB,CAAK;AAAA,kBACtB,OAAKve,EAAA,CAAC,cAAY,EAAA,uBACe+e,EAAcR,CAAK,GAAA,yBAA4BS,GAAkBT,CAAK,EAAA,CAAA,CAAA;AAAA,gBAAA;kBAEvGjgB,EAoGM,OAAA;AAAA,oBAnGJ,UAAM,uBAAqB,EAAA,kBACC0f,EAAiBO,GAAOhB,CAAI,EAAA,CAAA,CAAA;AAAA,oBACvD,OAAO,EAAA,aAAA,OAAA;AAAA,oBACP,cAAYa,EAAab,GAAMgB,CAAK;AAAA,oBACpC,gBAAOwB,EAAgBxB,GAAOA,SAAahB,CAAI;AAAA,oBAC/C,sBAAa4C,EAAsB9hB,GAAQkgB,GAAOA,GAAK,IAAA;AAAA,kBAAA;oBAIhDN,EAAYM,CAAK,UADzBxgB,EAeO,QAAA;AAAA;sBAbL,OAAKiC,EAAA,CAAC,2BAAyB,EAAA,eACNye,EAAeF,CAAK,EAAA,CAAA,CAAA;AAAA,sBAC5C,SAAK9P,EAAA,CAAApQ,MAAOqhB,GAAkBnB,CAAK,GAAA,CAAA,MAAA,CAAA;AAAA,oBAAA;sBAEpCjgB,EAQM,OAAA;AAAA,wBARD,OAAM;AAAA,wBAAK,QAAO;AAAA,wBAAK,SAAQ;AAAA,wBAAY,MAAK;AAAA,sBAAA;wBACnDA,EAME,QAAA;AAAA,0BALA,GAAE;AAAA,0BACF,QAAO;AAAA,0BACP,gBAAa;AAAA,0BACb,kBAAe;AAAA,0BACf,mBAAgB;AAAA,wBAAA;;qCAItBR,EAAA,GAAAC,EAAqC,QAArCyM,EAAqC;AAAA,oBAI7BpN,EAAA,qBADRW,EAsCO,QAAA;AAAA;sBApCL,UAAM,wBAAsB;AAAA,wBACgB,cAAA4gB,EAAcJ,CAAK;AAAA,wBAA2C,oBAAAO,EAAoBP,CAAK;AAAA,sBAAA;sBAIlI,SAAK9P,EAAA,CAAApQ,MAAO4gB,EAAiBV,CAAK,GAAA,CAAA,MAAA,CAAA;AAAA,oBAAA;sBAG3BI,EAAcJ,CAAK,KAD3BzgB,EAAA,GAAAC,EAcM,OAdNqa,IAcM,CAAA,GAAA3Z,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,wBAPJH,EAME,QAAA;AAAA,0BALA,GAAE;AAAA,0BACF,QAAO;AAAA,0BACP,gBAAa;AAAA,0BACb,kBAAe;AAAA,0BACf,mBAAgB;AAAA,wBAAA;8BAIPwgB,EAAoBP,CAAK,KADtCzgB,KAAAC,EAaM,OAbN2M,IAaM,CAAA,GAAAjM,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,wBANJH,EAKE,QAAA;AAAA,0BAJA,GAAE;AAAA,0BACF,QAAO;AAAA,0BACP,gBAAa;AAAA,0BACb,kBAAe;AAAA,wBAAA;;;oBAOblB,EAAA,kBADRW,EAIQ,QAAA;AAAA;sBAFN,OAAKiC,EAAA,CAAC,oBACE5C,EAAA,SAAS,CAAA;AAAA,oBAAA;oBAInBkB,EAIE,OAAA;AAAA,sBAHA,OAAM;AAAA,sBACL,KAAKof,EAAYa,GAAOhB,CAAI;AAAA,sBAC5B,KAAKE,EAAec,CAAK,IAAA,WAAA;AAAA,oBAAA;oBAI5BjgB,EAKO,QAAA;AAAA,sBAJL,OAAK0B,EAAA,CAAC,qBAAmB,EAAA,eACAyd,EAAec,CAAK,GAAA,CAAA;AAAA,oBAAA,GAE1C3f,GAAA4e,EAAae,CAAK,CAAA,GAAA,CAAA;AAAA,oBAIvBjgB,EAQM,OARNuM,IAQM;AAAA,sBAPJ/L,GAMEC,EAAA,QAAA,gBAAA;AAAA,wBAJC,MAAMwf;AAAA,wBACN,WAAYQ,EAAcR,CAAK;AAAA,wBAC/B,YAAaE,EAAeF,CAAK;AAAA,wBACjC,aAAcN,EAAYM,CAAK;AAAA,sBAAA;;;kBAMtCzU,GA4caC,IAAA,EA5cD,MAAK,gBAAY;AAAA,gCAC3B,MA0cM;AAAA,sBAzcEkU,EAAYM,CAAK,KAAKE,EAAeF,CAAK,KADlDzgB,KAAAC,EA0cM,OA1cN+M,IA0cM;AAAA,yBAtcJhN,EAAA,EAAA,GAAAC,EAqcME,IAAA,MAAAC,GApciBigB,EAAgBI,CAAK,IAAnC4D,YADTpkB,EAqcM,OAAA;AAAA,0BAncH,KAAKuf,EAAW6E,CAAU;AAAA,0BAC3B,UAAM,cAAY;AAAA,4BACqC,uBAAApD,EAAcoD,CAAU;AAAA,4BAAkD,yBAAAnD,GAAkBmD,CAAU;AAAA,0BAAA;;0BAK7J7jB,EAgHM,OAAA;AAAA,4BA/GJ,UAAM,uBAAqB,EAAA,kBACC0f,EAAiBmE,GAAY5E,CAAI,EAAA,CAAA,CAAA;AAAA,4BAC5D,OAAO,EAAA,aAAA,OAAA;AAAA,4BACP,cAAYa,EAAab,GAAM4E,CAAU;AAAA,4BACzC,gBAAOpC,EAAgBoC,GAAYA,SAAkB5E,CAAI;AAAA,4BACzD,eAAW,CAAAlf,MAA2B8hB;AAAA,8BAAiD9hB;AAAA,8BAAkC8jB;AAAA,8BAAsCA;AAAA;;;4BAWxJlE,EAAYkE,CAAU,UAD9BpkB,EAoBO,QAAA;AAAA;8BAlBL,OAAKiC,EAAA,CAAC,2BAAyB,EAAA,eACNye,EAAe0D,CAAU,EAAA,CAAA,CAAA;AAAA,8BACjD,SAAK1T,EAAA,CAAApQ,MAAOqhB,GAAkByC,CAAU,GAAA,CAAA,MAAA,CAAA;AAAA,4BAAA;8BAEzC7jB,EAaM,OAAA;AAAA,gCAZJ,OAAM;AAAA,gCACN,QAAO;AAAA,gCACP,SAAQ;AAAA,gCACR,MAAK;AAAA,8BAAA;gCAELA,EAME,QAAA;AAAA,kCALA,GAAE;AAAA,kCACF,QAAO;AAAA,kCACP,gBAAa;AAAA,kCACb,kBAAe;AAAA,kCACf,mBAAgB;AAAA,gCAAA;;6CAItBR,EAAA,GAAAC,EAAqC,QAArCiN,EAAqC;AAAA,4BAI7B5N,EAAA,qBADRW,EAsCO,QAAA;AAAA;8BApCL,UAAM,wBAAsB;AAAA,gCACsB,cAAA4gB,EAAcwD,CAAU;AAAA,gCAAiD,oBAAArD,EAAoBqD,CAAU;AAAA,8BAAA;8BAIxJ,SAAK1T,EAAA,CAAApQ,MAAO4gB,EAAiBkD,CAAU,GAAA,CAAA,MAAA,CAAA;AAAA,4BAAA;8BAGhCxD,EAAcwD,CAAU,KADhCrkB,EAAA,GAAAC,EAcM,OAdN2a,IAcM,CAAA,GAAAja,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gCAPJH,EAME,QAAA;AAAA,kCALA,GAAE;AAAA,kCACF,QAAO;AAAA,kCACP,gBAAa;AAAA,kCACb,kBAAe;AAAA,kCACf,mBAAgB;AAAA,gCAAA;sCAIPwgB,EAAoBqD,CAAU,KAD3CrkB,KAAAC,EAaM,OAbN4a,IAaM,CAAA,GAAAla,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,gCANJH,EAKE,QAAA;AAAA,kCAJA,GAAE;AAAA,kCACF,QAAO;AAAA,kCACP,gBAAa;AAAA,kCACb,kBAAe;AAAA,gCAAA;;;4BAOblB,EAAA,kBADRW,EAIQ,QAAA;AAAA;8BAFN,OAAKiC,EAAA,CAAC,oBACE5C,EAAA,SAAS,CAAA;AAAA,4BAAA;4BAInBkB,EAIE,OAAA;AAAA,8BAHA,OAAM;AAAA,8BACL,KAAKof,EAAYyE,GAAY5E,CAAI;AAAA,8BACjC,KAAKE,EAAe0E,CAAU,IAAA,WAAA;AAAA,4BAAA;4BAIjC7jB,EAKO,QAAA;AAAA,8BAJL,OAAK0B,EAAA,CAAC,qBAAmB,EAAA,eACAyd,EAAe0E,CAAU,GAAA,CAAA;AAAA,4BAAA,GAE/CvjB,GAAA4e,EAAa2E,CAAU,CAAA,GAAA,CAAA;AAAA,4BAI5B7jB,EAQM,OARNua,IAQM;AAAA,8BAPJ/Z,GAMEC,EAAA,QAAA,gBAAA;AAAA,gCAJC,MAAMojB;AAAA,gCACN,WAAYpD,EAAcoD,CAAU;AAAA,gCACpC,YAAa1D,EAAe0D,CAAU;AAAA,gCACtC,aAAclE,EAAYkE,CAAU;AAAA,8BAAA;;;0BAM3CrY,GAwUaC,IAAA,EAxUD,MAAK,gBAAY;AAAA,wCAC3B,MAsUM;AAAA,8BArU6BkU,EAAYkE,CAAU,KAAK1D,EAAe0D,CAAU,KADvFrkB,KAAAC,EAsUM,OAtUN+a,IAsUM;AAAA,iCAhUJhb,EAAA,EAAA,GAAAC,EA+TME,IAAA,MAAAC,GA9TsBigB,EAAgBgE,CAAU,IAA7CC,YADTrkB,EA+TM,OAAA;AAAA,kCA7TH,KAAKuf,EAAW8E,CAAe;AAAA,kCAChC,UAAM,cAAY;AAAA,2DACyErD,EAAcqD,CAAe;AAAA,oCAAwD,yBAAApD,GAAkBoD,CAAe;AAAA,kCAAA;;kCAMjN9jB,EAkIM,OAAA;AAAA,oCAjIJ,UAAM,uBAAqB,EAAA,kBACC0f,EAAiBoE,GAAiB7E,CAAI,EAAA,CAAA,CAAA;AAAA,oCACjE,OAAO;AAAA;;oCAGP,cAAYa,EAAab,GAAM6E,CAAe;AAAA,oCAC9C,SAAK,CAAA/jB,MAAiC0hB;AAAA,sCAAiDqC;AAAA,sCAAiDA;AAAA;sCAAuF7E;AAAA,oCAAA;AAAA,oCAQ/N,eAAW,CAAAlf,MAAiC8hB;AAAA,sCAAuD9hB;AAAA,sCAAwC+jB;AAAA,sCAAiDA;AAAA;;;oCAWrLnE,EAAYmE,CAAe,UADnCrkB,EAsBO,QAAA;AAAA;sCApBL,UAAM,2BAAyB;AAAA,wCAC0B,eAAA0gB,EAAe2D,CAAe;AAAA,sCAAA;sCAGtF,SAAK3T,EAAA,CAAApQ,MAAOqhB,GAAkB0C,CAAe,GAAA,CAAA,MAAA,CAAA;AAAA,oCAAA;sCAE9C9jB,EAaM,OAAA;AAAA,wCAZJ,OAAM;AAAA,wCACN,QAAO;AAAA,wCACP,SAAQ;AAAA,wCACR,MAAK;AAAA,sCAAA;wCAELA,EAME,QAAA;AAAA,0CALA,GAAE;AAAA,0CACF,QAAO;AAAA,0CACP,gBAAa;AAAA,0CACb,kBAAe;AAAA,0CACf,mBAAgB;AAAA,wCAAA;;qDAItBR,EAAA,GAAAC,EAAqC,QAArCib,EAAqC;AAAA,oCAI7B5b,EAAA,qBADRW,EAuCO,QAAA;AAAA;sCArCL,UAAM,wBAAsB;AAAA,wCAC4B,cAAA4gB,EAAcyD,CAAe;AAAA,4DAAyFtD,EAAoBsD,CAAe;AAAA,sCAAA;sCAKhN,SAAK3T,EAAA,CAAApQ,MAAO4gB,EAAiBmD,CAAe,GAAA,CAAA,MAAA,CAAA;AAAA,oCAAA;sCAGrCzD,EAAcyD,CAAe,KADrCtkB,EAAA,GAAAC,EAcM,OAdNskB,IAcM,CAAA,GAAA5jB,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,wCAPJH,EAME,QAAA;AAAA,0CALA,GAAE;AAAA,0CACF,QAAO;AAAA,0CACP,gBAAa;AAAA,0CACb,kBAAe;AAAA,0CACf,mBAAgB;AAAA,wCAAA;8CAIPwgB,EAAoBsD,CAAe,KADhDtkB,KAAAC,EAaM,OAbNukB,IAaM,CAAA,GAAA7jB,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,wCANJH,EAKE,QAAA;AAAA,0CAJA,GAAE;AAAA,0CACF,QAAO;AAAA,0CACP,gBAAa;AAAA,0CACb,kBAAe;AAAA,wCAAA;;;oCAOblB,EAAA,kBADRW,EAIQ,QAAA;AAAA;sCAFN,OAAKiC,EAAA,CAAC,oBACE5C,EAAA,SAAS,CAAA;AAAA,oCAAA;oCAInBkB,EAQE,OAAA;AAAA,sCAPA,OAAM;AAAA,sCACL,KAAKof,EAAY0E,GAAiB7E,CAAI;AAAA,sCACtC,KAAsCE,EAAe2E,CAAe;;oCAQvE9jB,EAOO,QAAA;AAAA,sCANL,UAAM,qBAAmB;AAAA,wCACgC,eAAAmf,EAAe2E,CAAe;AAAA,sCAAA;uCAIpFxjB,GAAA4e,EAAa4E,CAAe,CAAA,GAAA,CAAA;AAAA,oCAIjC9jB,EAQM,OARNikB,IAQM;AAAA,sCAPJzjB,GAMEC,EAAA,QAAA,gBAAA;AAAA,wCAJC,MAAMqjB;AAAA,wCACN,WAAYrD,EAAcqD,CAAe;AAAA,wCACzC,YAAa3D,EAAe2D,CAAe;AAAA,wCAC3C,aAAcnE,EAAYmE,CAAe;AAAA,sCAAA;;;kCAMhDtY,GA+KaC,IAAA,EA/KD,MAAK,gBAAY;AAAA,gDAC3B,MA6KM;AAAA,sCA5KmCkU,EAAYmE,CAAe,KAAqC3D,EAAe2D,CAAe,KADvItkB,KAAAC,EA6KM,OA7KNykB,IA6KM;AAAA,yCAtKJ1kB,EAAA,EAAA,GAAAC,EAqKME,aApK2BkgB;AAAA,0CAAmDiE;AAAA,wCAAA,IAA3EK,YADT1kB,EAqKM,OAAA;AAAA,0CAjKH,KAAKuf,EAAWmF,CAAoB;AAAA,0CACrC,UAAM,cAAY;AAAA,mEACqF1D,EAAc0D,CAAoB;AAAA,0CAAA;;0CAKzInkB,EAyJM,OAAA;AAAA,4CAxJJ,UAAM,uBAAqB,EAAA,kBACC0f,EAAiByE,GAAsBlF,CAAI,EAAA,CAAA,CAAA;AAAA,4CACtE,OAAO;AAAA;;4CAKP,cAAiDa,EAAab,GAAMkF,CAAoB;AAAA,4CAGxF,SAAK,CAAApkB,MAAuC0hB;AAAA,8CAAuD0C;AAAA,8CAA4DA;AAAA;8CAAwGlF;AAAA,4CAAA;AAAA,4CAQvQ,eAAW,CAAAlf,MAAuC8hB;AAAA,8CAA6D9hB;AAAA,8CAA8CokB;AAAA,8CAA4DA;AAAA;;;4CAWlNxE,EAAYwE,CAAoB,UADxC1kB,EAyBO,QAAA;AAAA;8CAvBL,UAAM,2BAAyB;AAAA,+DACwE0gB,EAAegE,CAAoB;AAAA,8CAAA;8CAIzI,SAAKhU,EAAA,CAAApQ,MAA8CqhB,GAAkB+C,CAAoB;;8CAI1FnkB,EAaM,OAAA;AAAA,gDAZJ,OAAM;AAAA,gDACN,QAAO;AAAA,gDACP,SAAQ;AAAA,gDACR,MAAK;AAAA,8CAAA;gDAELA,EAME,QAAA;AAAA,kDALA,GAAE;AAAA,kDACF,QAAO;AAAA,kDACP,gBAAa;AAAA,kDACb,kBAAe;AAAA,kDACf,mBAAgB;AAAA,gDAAA;;6DAItBR,EAAA,GAAAC,EAAqC,QAArC2kB,EAAqC;AAAA,4CAI7BtlB,EAAA,qBADRW,EAgDO,QAAA;AAAA;8CA9CL,UAAM,wBAAsB;AAAA,8DAC0E4gB,EAAc8D,CAAoB;AAAA,oEAAqG3D;AAAA,kDAA+D2D;AAAA,gDAAA;AAAA;8CAQ3S,SAAKhU,EAAA,CAAApQ,MAA8C4gB,EAAiBwD,CAAoB;;8CAKjF9D,EAAc8D,CAAoB,KAD1C3kB,EAAA,GAAAC,EAcM,OAdN4kB,IAcM,CAAA,GAAAlkB,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,gDAPJH,EAME,QAAA;AAAA,kDALA,GAAE;AAAA,kDACF,QAAO;AAAA,kDACP,gBAAa;AAAA,kDACb,kBAAe;AAAA,kDACf,mBAAgB;AAAA,gDAAA;sDAIkCwgB;AAAA,gDAA+D2D;AAAA,8CAAA,KADrH3kB,EAAA,GAAAC,EAiBM,OAjBN6kB,IAiBM,CAAA,GAAAnkB,EAAA,EAAA,MAAAA,EAAA,EAAA,IAAA;AAAA,gDANJH,EAKE,QAAA;AAAA,kDAJA,GAAE;AAAA,kDACF,QAAO;AAAA,kDACP,gBAAa;AAAA,kDACb,kBAAe;AAAA,gDAAA;;;4CAOblB,EAAA,kBADRW,EAIQ,QAAA;AAAA;8CAFN,OAAKiC,EAAA,CAAC,oBACE5C,EAAA,SAAS,CAAA;AAAA,4CAAA;4CAInBkB,EAQE,OAAA;AAAA,8CAPA,OAAM;AAAA,8CACL,KAAKof,EAAY+E,GAAsBlF,CAAI;AAAA,8CAC3C,KAA4CE,EAAegF,CAAoB;;4CAQlFnkB,EAQO,QAAA;AAAA,8CAPL,UAAM,qBAAmB;AAAA,+DAC8Emf,EAAegF,CAAoB;AAAA,8CAAA;+CAKvI7jB,GAAA4e,EAAaiF,CAAoB,CAAA,GAAA,CAAA;AAAA,4CAItCnkB,EAcM,OAdNukB,IAcM;AAAA,8CAbJ/jB,GAYEC,EAAA,QAAA,gBAAA;AAAA,gDAVC,MAAM0jB;AAAA,gDACN,WAAqD1D,EAAc0D,CAAoB;AAAA,gDAGvF,YAAsDhE,EAAegE,CAAoB;AAAA,gDAGzF,aAAuDxE,EAAYwE,CAAoB;AAAA,8CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACthB9H,UAAMtlB,IAAQC,GAORC,IAAOC,GAQPwlB,IAAa7jB,EAAI,EAAK,GACtB8jB,IAAaC,GAA8B,EAAE,GAC7CC,IAAyC,CAAC,UAAU,QAAQ,aAAa,QAAQ;AACvF,QAAIC;AAGJ,UAAMC,IAAgBzlB,EAAS,MACtBP,EAAM,OAAO,OAAO,CAAC2F,MAAU,CAACA,EAAM,MAAM,CACpD,GAGKsgB,IAAkB1lB,EAAS,MAC3BolB,EAAW,QAAcK,EAAc,QACpCA,EAAc,MAAM,MAAM,GAAGhmB,EAAM,gBAAgB,CAC3D,GAMKkmB,IAAkB3lB,EAAS,MACxBylB,EAAc,MAAM,SAAShmB,EAAM,gBAC3C;AAGD,aAASmmB,EAAkBvM,GAAc;AACvC,cAAQA,GAAA;AAAA,QACN,KAAK;AACH,iBAAOwM;AAAA,QACT,KAAK;AAAA,QACL,KAAK;AACH,iBAAOC;AAAA,QACT,KAAK;AACH,iBAAOC;AAAA,QACT,KAAK;AAAA,QACL;AACE,iBAAOC;AAAA,MAAA;AAAA,IAEb;AAEA,aAASC,EAAiBrgB,GAAaP,GAAY;AACjD,MAAAggB,EAAWzf,CAAG,IAAIP;AAClB,YAAMD,IAAQ3F,EAAM,OAAO,KAAK,CAACymB,MAAMA,EAAE,QAAQtgB,CAAG;AACpD,MAAIR,KACF+gB,EAAkB/gB,CAAK;AAAA,IAE3B;AAEA,aAAS+gB,EAAkB/gB,GAAmB;AAC5C,MAAAzF,EAAK,gBAAgByF,GAAOigB,EAAWjgB,EAAM,GAAG,CAAC,GACjDzF,EAAK,qBAAqB,EAAE,GAAG0lB,GAAY,GACvCE,EAAiB,SAASngB,EAAM,IAAI,KACtCghB,GAAA;AAAA,IAEJ;AAEA,aAASC,EAAmBjhB,GAAmBC,GAAY;AAEzD,MAAID,EAAM,kBAAkB,OAAOA,EAAM,kBAAmB,cAC1DA,EAAM,eAAeC,GAAOD,CAAK,GAGnC+gB,EAAkB/gB,CAAK;AAAA,IACzB;AAEA,aAASkhB,IAAe;AAEtB,YAAMC,IAAeC,EAAkBnB,CAAU,GAG3CoB,IAAkBC,GAAmBH,CAAY,GAEjDI,IAAY,EAAE,GAAGtB,EAAA;AAGvB,MAAA1lB,EAAK,UAAU,EAAE,MAAM8mB,GAAiB,KAAKE,GAAW;AAAA,IAC1D;AAEA,aAASC,IAAc;AAErB,aAAO,KAAKvB,CAAU,EAAE,QAAQ,CAACzf,MAAQ;AACvC,cAAMR,IAAQ3F,EAAM,OAAO,KAAK,CAACymB,MAAMA,EAAE,QAAQtgB,CAAG;AACpD,SAAIR,KAAA,gBAAAA,EAAO,UAAS,cAClBigB,EAAWzf,CAAG,IAAI,EAAE,WAAW,MAAM,SAAS,KAAA,KACrCR,KAAA,gBAAAA,EAAO,UAAS,SACzBigB,EAAWzf,CAAG,IAAI,QACTR,KAAA,gBAAAA,EAAO,UAAS,WAEzBigB,EAAWzf,CAAG,IAAIR,EAAM,eAAe,SAAYA,EAAM,aAAa,KAEtEigB,EAAWzf,CAAG,IAAI;AAAA,MAEtB,CAAC,GACDjG,EAAK,OAAO,GACZA,EAAK,qBAAqB,EAAE,GAAG0lB,GAAY;AAAA,IAC7C;AAEA,aAASwB,IAAiB;AACxB,MAAAzB,EAAW,QAAQ,CAACA,EAAW;AAAA,IACjC;AAEA,aAAS0B,EAAkB1hB,GAAmB;AAE5C,aAAIA,EAAM,SAAS,UACV,CAAA,IAEF;AAAA,QACL,OAAO,MAAM2hB,EAAA;AAAA,QACb,OAAO,MAAMA,EAAA;AAAA,MAAuB;AAAA,IAExC;AAEA,mBAAeA,IAAyB;AACtC,YAAMne,GAAA,GACN0d,EAAA;AAAA,IACF;AAEA,aAASF,KAAqB;AAC5B,MAAIZ,KACF,aAAaA,CAAe,GAE9BA,IAAkB,WAAW,MAAM;AACjC,QAAAA,IAAkB,QAClB5c,KAAW,KAAK,MAAM0d,GAAc;AAAA,MACtC,GAAG,CAAC;AAAA,IACN;AAGA,aAASE,EAAkBQ,GAA6B;AACtD,YAAM5D,IAAgC,CAAA;AAEtC,oBAAO,KAAK4D,CAAM,EAAE,QAAQ,CAACphB,MAAQ;AACnC,cAAMR,IAAQ3F,EAAM,OAAO,KAAK,CAACymB,MAAMA,EAAE,QAAQtgB,CAAG,GAC9CqhB,KAAWD,EAAOphB,CAAG,GACrBP,KACJ,OAAO4hB,MAAa,WAAWA,GAAS,SAASA;AAEnD,YAAI,EAAA5hB,MAAU,QAA+BA,OAAU,KAIvD;AAAA,cACE,OAAOA,MAAU,YACjBA,GAAM,aACNA,GAAM,SACN;AACA,YAAIA,GAAM,aAAaA,GAAM,YAC3B+d,EAASxd,CAAG,IAAIP;AAElB;AAAA,UACF;AAEA,cAAID,MAAUA,EAAM,SAAS,UAAUA,EAAM,SAAS,cAAc;AAClE,YAAIC,OAAU,MACZ+d,EAASxd,CAAG,IAAIP;AAElB;AAAA,UACF;AAEA,UAAA+d,EAASxd,CAAG,IAAIP;AAAA;AAAA,MAClB,CAAC,GAEM+d;AAAA,IACT;AAGA,aAASsD,GAAmBM,GAA6B;AACvD,YAAME,IAAiC,CAAA;AAEvC,oBAAO,KAAKF,CAAM,EAAE,QAAQ,CAACphB,MAAQ;AACnC,cAAMP,IAAQ2hB,EAAOphB,CAAG,GAClBR,KAAQ3F,EAAM,OAAO,KAAK,CAACymB,OAAMA,GAAE,QAAQtgB,CAAG;AAEpD,YAAIR;AAEF,cAAIA,GAAM,SAAS,eAAe,OAAOC,KAAU,UAAU;AAE3D,kBAAM8hB,KAAW/hB,GAAM,YAAY,GAAGQ,CAAG,SACnCwhB,IAAShiB,GAAM,UAAU,GAAGQ,CAAG;AAGrC,YAAIP,EAAM,aAAaA,EAAM,WAAWA,EAAM,cAAc,KAAKA,EAAM,YAAY,MAC7ED,GAAM,WAAW,eACnB8hB,EAAUC,EAAQ,IAAI,IAAI,KAAK9hB,EAAM,SAAS,EAAE,QAAA,GAChD6hB,EAAUE,CAAM,IAAI,IAAI,KAAK/hB,EAAM,OAAO,EAAE,QAAA,MAE5C6hB,EAAUC,EAAQ,IAAI9hB,EAAM,WAC5B6hB,EAAUE,CAAM,IAAI/hB,EAAM;AAAA,UAGhC,OAAWD,GAAM,SAAS,UAAUC,KAASA,MAAU,KAEjDD,GAAM,WAAW,cACnB8hB,EAAUthB,CAAG,IAAI,IAAI,KAAKP,CAAK,EAAE,QAAA,IAMnC6hB,EAAUthB,CAAG,IAAIP;AAAA;AAInB,UAAA6hB,EAAUthB,CAAG,IAAIP;AAAA,MAErB,CAAC,GAEM6hB;AAAA,IACT;AAGA,aAASG,KAAe;AACtB,MAAA5nB,EAAM,OAAO,QAAQ,CAAC2F,MAAU;;AAC9B,QAAIigB,EAAWjgB,EAAM,GAAG,MAAM,WAExBA,EAAM,SAAS,cACjBigB,EAAWjgB,EAAM,GAAG,MAAI1E,IAAAjB,EAAM,eAAN,gBAAAiB,EAAmB0E,EAAM,SAAQ;AAAA,UACvD,WAAW;AAAA,UACX,SAAS;AAAA,QAAA,IAEFA,EAAM,SAAS,SACxBigB,EAAWjgB,EAAM,GAAG,MAAIkG,IAAA7L,EAAM,eAAN,gBAAA6L,EAAmBlG,EAAM,SAAQ,OAChDA,EAAM,SAAS,WAExBigB,EAAWjgB,EAAM,GAAG,MAAIkiB,IAAA7nB,EAAM,eAAN,gBAAA6nB,EAAmBliB,EAAM,UAAS,SACtD3F,EAAM,WAAW2F,EAAM,GAAG,IACzBA,EAAM,eAAe,SAAYA,EAAM,aAAa,KAEzDigB,EAAWjgB,EAAM,GAAG,MAAImiB,KAAA9nB,EAAM,eAAN,gBAAA8nB,GAAmBniB,EAAM,SAAQ;AAAA,MAG/D,CAAC;AAAA,IACH;AAGA,WAAAxD;AAAA,MACE,MAAMnC,EAAM;AAAA,MACZ,CAAC2a,MAAa;AACZ,QAAIA,KACF,OAAO,OAAOiL,GAAYjL,CAAQ;AAAA,MAEtC;AAAA,MACA,EAAE,MAAM,IAAM,WAAW,GAAA;AAAA,IAAK,GAIhCvO,GAAU,MAAM;AACd,MAAAwb,GAAA;AAAA,IACF,CAAC,GAEDG,GAAgB,MAAM;AACpB,MAAIhC,MACF,aAAaA,CAAe,GAC5BA,IAAkB;AAAA,IAEtB,CAAC,cA3ZCplB,EAAA,GAAAC,EAsFM,OAtFNiM,IAsFM;AAAA,MArFJ1L,EAoFM,OApFNO,IAoFM;AAAA,QAnFJP,EAkFM,OAlFNN,IAkFM;AAAA,UAhFJM,EA+EM,OA/EN4L,IA+EM;AAAA,YA7EJJ,GAyCmBqb,IAAA;AAAA,cAzCD,MAAK;AAAA,cAAK,KAAI;AAAA,cAAM,OAAM;AAAA,YAAA;0BAExC,MAAgC;AAAA,wBADlCpnB,EAuCME,IAAA,MAAAC,GAtCYklB,EAAA,OAAe,CAAxBtgB,YADT/E,EAuCM,OAAA;AAAA,kBArCH,KAAK+E,EAAM;AAAA,kBACZ,OAAM;AAAA,gBAAA;kBAGNhE,GAgCOC,EAAA,QAAA,SA/BW+D,EAAM,GAAG,IAAA;AAAA,oBACxB,OAAAA;AAAA,oBACA,OAAOigB,EAAWjgB,EAAM,GAAG;AAAA,oBAC3B,aAAY,CAAGvD,MAAaokB,EAAiB7gB,EAAM,KAAKvD,CAAG;AAAA,kBAAA,GAJ9D,MAgCO;AAAA,oBAzBLjB,EAwBM,OAxBNC,IAwBM;AAAA,sBAvBSnB,EAAA,WAAW0F,EAAM,SAAI,YAAlChF,EAAA,GAAAC,EAAmH,SAAnHS,IAAmHI,GAAtBkE,EAAM,KAAK,GAAA,CAAA;uBACxGhF,EAAA,GAAAmN,GAqBEma,GApBK9B,EAAkBxgB,EAAM,IAAI,IADnCuiB,GAqBE;AAAA,oCAnBStC,EAAWjgB,EAAM,GAAG;AAAA,sDAApBigB,EAAWjgB,EAAM,GAAG,IAAAzE;AAAA,wBAC5B,aAAayE,EAAM,eAAW,MAAUA,EAAM,KAAK;AAAA,wBACnD,SAASA,EAAM;AAAA,wBACf,WAAWA,EAAM,cAAS;AAAA,wBAC1B,MAAMA,EAAM,QAAI;AAAA,wBAChB,OAAOA,EAAM,SAAK;AAAA,wBAClB,QAAQA,EAAM,UAAM;AAAA,wBACpB,gBAAcA,EAAM,eAAW;AAAA,wBAC/B,YAAYA,EAAM,eAAU;AAAA,wBAC5B,cAAYA,EAAM;AAAA,wBAClB,eAAaA,EAAM;AAAA,wBACnB,eAAaA,EAAM;AAAA,wBACnB,iBAAeA,EAAM;AAAA,wBACrB,aAAWA,EAAM;AAAA,wBACjB,gBAAcA,EAAM,gBAAgBA,EAAM,SAAI,WAAA,YAA4B;AAAA,wBAC1E,kBAAgBA,EAAM;AAAA,sBAAA,GACvBwiB,GAA+Bd,EAAP1hB,CAAK,CAAA,GAAA;AAAA,wBAC5B,SAAK,CAAAzE,MAAEyE,EAAM,oBAAoB+gB,EAAkB/gB,CAAK,IAAI;AAAA,wBAC5D,UAAM,CAAAzE,MAAEyE,EAAM,SAAI,WAAgBihB,EAAmBjhB,GAAOzE,CAAM,IAAIwlB,EAAkB/gB,CAAK;AAAA,sBAAA;;;;;;;YAQzDugB,EAAA,SAA/CvlB,EAAA,GAAAC,EASM,OATNW,IASM;AAAA,cARJoL,GAOUyb,IAAA;AAAA,gBAPD,SAAQ;AAAA,gBAAY,MAAK;AAAA,gBAAS,SAAOhB;AAAA,cAAA;4BAChD,MAA8B;AAAA,kBAA3B7V,GAAA9P,GAAAkkB,EAAA,uBAA2B,KAC9B,CAAA;AAAA,kBAAAxkB,EAIC,QAAA;AAAA,oBAHC,OAAK0B,EAAA,CAAC,oCAAkC,EAAA,eACf8iB,EAAA,OAAU,CAAA;AAAA,kBAAA,GAClC,KAAC,CAAA;AAAA,gBAAA;;;;YAMRxkB,EAoBM,OApBNK,IAoBM;AAAA,cAnBJL,EAkBM,OAlBN6L,IAkBM;AAAA,gBAjBJL,GAOUyb,IAAA;AAAA,kBANR,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACJ,SAAOvB;AAAA,kBACP,SAAS5mB,EAAA;AAAA,gBAAA;8BACX,MAED,CAAA,GAAAqB,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,uBAFC,QAED,EAAA;AAAA,kBAAA;;;gBACAqL,GAOUyb,IAAA;AAAA,kBANR,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACJ,SAAOjB;AAAA,kBACP,SAASlnB,EAAA;AAAA,gBAAA;8BACX,MAED,CAAA,GAAAqB,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,uBAFC,QAED,EAAA;AAAA,kBAAA;;;gBACAK,GAAkCC,EAAA,QAAA,iBAAA,CAAA,GAAA,QAAA,EAAA;AAAA,cAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACvDhD,UAAM5B,IAAQC,GAeRoS,IAAUvQ,EAAI,EAAK;AACzB,QAAIumB,GACAC,IAAwB,GACxB5S,IAAoB;AAExB,IAAAtJ,GAAU,MAAM;AAEd,4BAAsB,MAAM;AAC1B,QAAAiG,EAAQ,QAAQ,IACZrS,EAAM,YAAYA,EAAM,WAAW,KACrCuoB,EAAWvoB,EAAM,QAAQ;AAAA,MAE7B,CAAC;AAAA,IACH,CAAC,GAED+nB,GAAgB,MAAM;AACpB,MAAAS,EAAA;AAAA,IACF,CAAC;AAED,aAASD,EAAWE,GAAkB;AACpC,MAAAH,IAAgBG,GAChB/S,IAAY,KAAK,IAAA,GACjB2S,IAAQ,OAAO,WAAW,MAAM3V,EAAA,GAAS+V,CAAQ;AAAA,IACnD;AAEA,aAASD,IAAa;AACpB,MAAIH,MACF,OAAO,aAAaA,CAAK,GACzBA,IAAQ;AAAA,IAEZ;AAEA,aAASxT,IAAmB;AAC1B,UAAIwT,KAASroB,EAAM,YAAYA,EAAM,WAAW,GAAG;AACjD,QAAAwoB,EAAA;AAEA,cAAME,IAAU,KAAK,IAAA,IAAQhT;AAC7B,QAAA4S,IAAgB,KAAK,IAAI,GAAGA,IAAgBI,CAAO;AAAA,MACrD;AAAA,IACF;AAEA,aAAS5T,IAAmB;AAC1B,MAAI9U,EAAM,YAAYA,EAAM,WAAW,KAAKsoB,IAAgB,KAE1DC,EAAWD,CAAa;AAAA,IAE5B;AAEA,aAAS5V,IAAQ;AACf,MAAAL,EAAQ,QAAQ;AAAA,IAClB;AAEA,aAASsW,IAAe;;AACtB,OAAA1nB,IAAAjB,EAAM,YAAN,QAAAiB,EAAA,KAAAjB,GAAgBA,EAAM;AAAA,IACxB;2BA9FE8N,GAmBalB,IAAA;AAAA,MAnBD,MAAK;AAAA,MAAc,cAAA+b;AAAA,IAAA;kBAC7B,MAiBM;AAAA,WAjBNxnB,EAiBM,OAAA;AAAA,UAfJ,OAAK0B,EAAA,CAAC,SAAO,CAAA,UACM5C,EAAA,IAAI,EAAA,CAAA,CAAA;AAAA,UACtB,oBAAiBA,EAAA,QAAM;AAAA,UACxB,MAAK;AAAA,UACL,aAAU;AAAA,UACT,cAAY4U;AAAA,UACZ,cAAYC;AAAA,QAAA;UAEb3T,EAIO,QAAA;AAAA,YAJD,OAAK0B,EAAA,CAAC,eAAa,gBAAyB5C,EAAA,IAAI,EAAA,CAAA;AAAA,YAAI,eAAY;AAAA,UAAA;YACzDA,EAAA,SAAI,aAAfU,EAAA,GAAAC,EAA2M,OAA3MiM,IAA2M,CAAA,GAAAvL,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAAvHH,EAAiH,QAAA;AAAA,gBAA3G,GAAE;AAAA,gBAAkB,QAAO;AAAA,gBAAe,gBAAa;AAAA,gBAAI,kBAAe;AAAA,gBAAQ,mBAAgB;AAAA,cAAA;oBAC5KlB,EAAA,SAAI,aAApBU,KAAAC,EAAwS,OAAxSc,IAAwS,CAAA,GAAAJ,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAA/MH,EAAyM,QAAA;AAAA,gBAAnM,GAAE;AAAA,gBAA0G,QAAO;AAAA,gBAAe,gBAAa;AAAA,gBAAI,kBAAe;AAAA,gBAAQ,mBAAgB;AAAA,cAAA;qBACzRR,KAAAC,EAA+N,OAA/NC,IAA+N,CAAA,GAAAS,EAAA,CAAA,MAAAA,EAAA,CAAA,IAAA;AAAA,cAA5JH,EAAsJ,QAAA;AAAA,gBAAhJ,GAAE;AAAA,gBAAuD,QAAO;AAAA,gBAAe,gBAAa;AAAA,gBAAI,kBAAe;AAAA,gBAAQ,mBAAgB;AAAA,cAAA;;;UAElNA,EAAmD,OAAA;AAAA,YAA9C,OAAM;AAAA,YAAiB,aAAAM,GAAQxB,EAAQ,OAAD;AAAA,UAAA;UAC7BA,EAAA,iBAAdW,EAAoF,UAAA;AAAA;YAA5D,OAAM;AAAA,YAAe,MAAK;AAAA,YAAU,SAAO8R;AAAA,UAAA,GAAO,GAAC;;eAfnEL,EAAA,KAAO;AAAA,QAAA;;;;;;ACArB,IAAIuW,KAAO;AACX,MAAMC,KAAM,IAENC,KAAiC,CAAA;AAWvC,SAASC,KAAqB;AAC5B,MAAIC,IAAS;AACb,SAAAF,GAAU,QAAQ,CAAAG,MAAQ;AAAE,IAAAD,KAAUC,EAAK,SAASJ;AAAA,EAAI,CAAC,GAClDG;AACT;AAEA,SAAStW,GAAMwW,GAAY;AACzB,QAAMloB,IAAQ8nB,GAAU,UAAU,CAAAriB,MAAKA,EAAE,OAAOyiB,CAAE;AAClD,MAAIloB,MAAU,GAAI;AAClB,QAAM,EAAE,IAAAoQ,EAAA,IAAO0X,GAAU9nB,CAAK,GACxBof,IAAOhP,EAAG;AAEhB,MAAIgP,GAAM;AACR,UAAM+I,IAAc,OAAO,iBAAiB/I,CAAI,EAAE;AAClD,IAAAA,EAAK,MAAM,MAAM+I,GACjB/I,EAAK,UAAU,IAAI,YAAY,GAE/BA,EAAK,MAAM,aAAa;AAAA,EAC1B;AACA,EAAA0I,GAAU9nB,CAAK,EAAE,UAAU,IAE3BooB,GAAA,GAGA,WAAW,MAAM;AACf,IAAAC,GAAO,MAAMjY,CAAE,GACfA,EAAG,cAAcA,EAAG,WAAW,YAAYA,CAAE;AAC7C,UAAMkY,IAAUR,GAAU,UAAU,CAAAriB,MAAKA,EAAE,OAAOyiB,CAAE;AACpD,IAAII,MAAY,MAAIR,GAAU,OAAOQ,GAAS,CAAC,GAC/CF,GAAA;AAAA,EACF,GAPiB,GAON;AACb;AAEA,SAASpV,GAAKuV,GAAyB;;AACrC,QAAML,IAAKN,MACLxX,IAAK,SAAS,cAAc,KAAK;AACvC,WAAS,KAAK,YAAYA,CAAE;AAE5B,QAAMoY,IAAKC,GAAYC,IAAe;AAAA,IACpC,IAAAR;AAAA,IACA,MAAMK,EAAQ,QAAQ;AAAA,IACtB,SAASA,EAAQ;AAAA,IACjB,UAAUA,EAAQ,YAAY;AAAA,IAC9B,QAAQR,GAAA;AAAA,IACR,QAAQ,MAAOG;AAAA,IACf,UAAUK,EAAQ,YAAY;AAAA,IAC9B,SAAS,CAACI,MAAgBjX,GAAMiX,CAAG;AAAA,EAAA,CACpC;AAED,EAAAN,GAAOG,GAAIpY,CAAE;AAEb,QAAMwY,MAAiB3oB,IAAAmQ,EAAG,sBAAH,gBAAAnQ,EAAsC,iBAAgB;AAC7E,SAAA6nB,GAAU,KAAK,EAAE,IAAAI,GAAI,IAAA9X,GAAI,IAAAoY,GAAI,QAAQI,GAAe,SAAS,IAAO,GACpER,GAAA,GAGA,sBAAsB,MAAM;AAC1B,UAAMhJ,IAAOhP,EAAG;AAChB,QAAI,CAACgP,EAAM;AACX,UAAMyJ,IAAazJ,EAAK,gBAAgBwJ,KAAiB,GACnDX,IAAOH,GAAU,KAAK,CAAAriB,MAAKA,EAAE,OAAOyiB,CAAE;AAC5C,IAAID,MACFA,EAAK,SAASY,GACdT,GAAA;AAAA,EAEJ,CAAC,GAEM,EAAE,OAAO,MAAM1W,GAAMwW,CAAE,EAAA;AAChC;AAEO,MAAMY,KAAW;AAAA,EACtB,QAAQC,GAAiBC,GAAiE;AAExF,WAAOhW,GAAK,EAAE,GADD,OAAOgW,KAAmB,WAAW,EAAE,UAAUA,EAAA,IAAoBA,KAAkB,CAAA,GAC7E,MAAM,WAAW,SAAAD,GAAS;AAAA,EACnD;AAAA,EACA,QAAQA,GAAiBC,GAAiE;AAExF,WAAOhW,GAAK,EAAE,GADD,OAAOgW,KAAmB,WAAW,EAAE,UAAUA,EAAA,IAAoBA,KAAkB,CAAA,GAC7E,MAAM,WAAW,SAAAD,GAAS;AAAA,EACnD;AAAA,EACA,MAAMA,GAAiBC,GAAiE;AAEtF,WAAOhW,GAAK,EAAE,GADD,OAAOgW,KAAmB,WAAW,EAAE,UAAUA,EAAA,IAAoBA,KAAkB,CAAA,GAC7E,MAAM,SAAS,SAAAD,GAAS;AAAA,EACjD;AACF;AAKI,OAAO,SAAW,QAClB,OAAe,WAAWD,IAExB,OAAQ,WAAmB,WAAa,QACxC,WAAmB,WAAWA;AAIpC,SAASV,KAAkB;AACzB,MAAIJ,IAAS;AACb,EAAAF,GAAU,QAAQ,CAAAG,MAAQ;AACxB,UAAM7I,IAAO6I,EAAK,GAAG;AACrB,QAAI,CAAC7I,EAAM;AAEX,UAAM6J,IAAYjB;AAMlB,QAHA5I,EAAK,MAAM,YAAY,mBAAmB6J,CAAS,OAE9C7J,EAAK,MAAM,QAAKA,EAAK,MAAM,MAAM,QAClC,CAAC6I,EAAK;AACR,MAAAD,MAAW5I,EAAK,gBAAgB6I,EAAK,UAAUJ;AAAA,SAC1C;AACL,YAAMqB,IAAgB9J,EAAK,gBAAgB6I,EAAK;AAChD,MAAAD,KAAUkB,IAAgBrB;AAAA,IAC5B;AAAA,EACF,CAAC;AACH;;;;;;;;;;;;ACnDA,UAAMlD,IAAa7jB,EATL7B,EASe,eAAe,GAEtCkqB,IAAS,MAAM;AACnB,MAAAxE,EAAW,QAAQ,CAACA,EAAW;AAAA,IACjC,GAGMyE,IAAW,MAAM;AACrB,MAAIzE,EAAW,UACbA,EAAW,QAAQ;AAAA,IAEvB,GAGM0E,IAAS,MAAM;AACnB,MAAK1E,EAAW,UACdA,EAAW,QAAQ;AAAA,IAEvB;AAGA,IAAA1Q,EAAa;AAAA,MACX,QAAAkV;AAAA,MACA,YAAAxE;AAAA,MACA,UAAAyE;AAAA,MACA,QAAAC;AAAA,IAAA,CACD;AAGD,UAAMpmB,IAAkBqmB,GAAgC,mBAAmB,IAAI,GACzEpmB,IAAoBomB,GAAgC,qBAAqB,IAAI,GAC7EhmB,IAA2BgmB,GAAmB,4BAA4B,IAAI,GAG9EvmB,IAAW;AAAA,MACf,UAAAqmB;AAAA,MACA,QAAAC;AAAA,MACA,QAAAF;AAAA,MACA,IAAI,aAAa;AACf,eAAOxE,EAAW;AAAA,MACpB;AAAA,IAAA;AAIF,WAAAxjB,GAAM,MAAMwjB,EAAW,OAAO,MAAM;AAClC,MAAIrhB,KACFA,EAAA;AAAA,IAEJ,CAAC,GAED8H,GAAU,MAAM;AACd,MAAInI,KACFA,EAAgBF,CAAQ;AAAA,IAE5B,CAAC,GAEDuI,GAAY,MAAM;AAChB,MAAIpI,KACFA,EAAkBH,CAAQ;AAAA,IAE9B,CAAC,mBA5ICnD,EAwDM,OAAA;AAAA,MAxDA,kDAAgDX,EAAA,QAAQ,EAAA,CAAA;AAAA,IAAA;MAC5D0M,GA6BaC,IAAA,EA7BD,MAAK,gBAAY;AAAA,oBAC3B,MA2BM;AAAA,aA3BNzL,EA2BM,OAAA;AAAA,YAzBH,kCAAgClB,EAAA,QAAQ,EAAA,CAAA;AAAA,YACxC,OAAKkN,GAAA;AAAA,qBAAsBlN,EAAA,aAAQ,SAAcA,EAAA,aAAQ,WAAA,SAAyBA,EAAA;AAAA,2BAA8BA,EAAA;AAAA,YAAA;;YAKjHkB,EAEM,OAFN0L,IAEM;AAAA,cADJlL,GAA0BC,yBAA1B,MAA0B;AAAA,sBAAjB3B,EAAA,OAAO,GAAA,CAAA;AAAA,cAAA;;YAElBkB,EAeM,OAAA;AAAA,cAfD,OAAM;AAAA,cAAmB,SAAOgpB;AAAA,YAAA;cACnChpB,EAaM,OAAA;AAAA,gBAZJ,OAAM;AAAA,gBACN,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,OAAM;AAAA,cAAA;gBAENA,EAME,QAAA;AAAA,kBALA,GAAE;AAAA,kBACF,QAAO;AAAA,kBACP,gBAAa;AAAA,kBACb,kBAAe;AAAA,kBACf,mBAAgB;AAAA,gBAAA;;;;iBAtBdwkB,EAAA,KAAU;AAAA,UAAA;;;;MA8BtBhZ,GAsBaC,IAAA,EAtBD,MAAK,sBAAkB;AAAA,oBACjC,MAoBM;AAAA,aApBNzL,EAoBM,OAAA;AAAA,YAlBH,gDAA8ClB,EAAA,QAAQ,EAAA,CAAA;AAAA,YACtD,SAAOkqB;AAAA,YACP,OAAOlqB,EAAA,WAAWA,EAAA;AAAA,UAAA;YAEnBkB,EAaM,OAAA;AAAA,cAZJ,OAAM;AAAA,cACN,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,OAAM;AAAA,YAAA;cAENA,EAME,QAAA;AAAA,gBALA,GAAE;AAAA,gBACF,QAAO;AAAA,gBACP,gBAAa;AAAA,gBACb,kBAAe;AAAA,gBACf,mBAAgB;AAAA,cAAA;;;kBAhBXwkB,EAAA,KAAU;AAAA,UAAA;;;;;;qEC4BrB4E,KAAa;AAAA,EACjB,SAAAnC;AAAA,EACA,QAAA7B;AAAA,EACA,QAAAiE;AAAA,EACA,SAAApE;AAAA,EACA,aAAAqE;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,OAAAvE;AAAA,EACA,SAAAC;AAAA,EACA,QAAAuE;AAAA,EACA,WAAAC;AAAA,EACA,SAAAC;AAAA,EACA,OAAAC;AAAA,EACA,oBAAAC;AAAA,EACA,SAAAC;AACF,GAEAlqB,KAAe;AAAA,EACb,QAAQmqB,GAAU;AAEhB,WAAO,KAAKZ,EAAU,EAAE,QAAQ,CAACpkB,MAAQ;AACvC,MAAAglB,EAAI,UAAUhlB,GAAKokB,GAAWpkB,CAA8B,CAAC;AAAA,IAC/D,CAAC,GAGDglB,EAAI,OAAO,iBAAiB,WAAWrB,IAGnC,OAAO,SAAW,QAClB,OAAe,WAAWA;AAAAA,EAEhC;AACF;"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/components/ybutton.vue","../src/components/yinput.vue","../src/components/ytable.vue","../src/components/yselect.vue","../src/components/ypagination.vue","../src/components/ybadge.vue","../src/components/ydialog.vue","../src/components/ypopover.vue","../src/components/ytime.vue","../src/components/yswitch.vue","../src/components/yimage.vue","../src/components/ydropdown.vue","../src/components/ydrawer.vue","../src/components/ytree.vue","../src/components/QueryEncapsulation.vue","../src/components/ymessage/ymessageToast.vue","../src/components/ymessage/ymessage.ts","../src/components/hintTag.vue","../src/index.ts"],"sourcesContent":["<template>\n <template v-if=\"!isGroup\">\n <button\n class=\"y-btn\"\n :class=\"[\n `y-btn--${variant}`,\n `y-btn--${size}`,\n { 'is-block': block, 'is-loading': loading },\n groupPosition !== 'single' ? 'is-grouped' : '',\n groupPositionClass\n ]\"\n :type=\"htmlType\"\n :disabled=\"disabled || loading\"\n :aria-busy=\"loading ? 'true' : 'false'\"\n :aria-disabled=\"(disabled || loading) ? 'true' : 'false'\"\n @click=\"onClick\"\n >\n <span class=\"content\"><slot /></span>\n </button>\n </template>\n <template v-else>\n <div class=\"y-btn-group\" role=\"group\">\n <button\n v-for=\"(item, index) in groupItems\"\n :key=\"item.value ?? index\"\n class=\"y-btn\"\n :class=\"[\n `y-btn--${item.variant ?? variant}`,\n `y-btn--${item.size ?? size}`,\n 'is-grouped',\n index === 0 ? 'group-pos-start' : (index === (groupItems?.length || 0) - 1 ? 'group-pos-end' : 'group-pos-middle'),\n { 'is-loading': item.loading || loading }\n ]\"\n :type=\"htmlType\"\n :disabled=\"(item.disabled ?? false) || disabled || loading || item.loading\"\n :aria-busy=\"(item.loading || loading) ? 'true' : 'false'\"\n :aria-disabled=\"((item.disabled ?? false) || disabled || loading || item.loading) ? 'true' : 'false'\"\n :aria-label=\"item.ariaLabel || item.label\"\n @click=\"onGroupItemClick(item, $event)\"\n >\n <span class=\"content\">\n <svg v-if=\"item.icon === 'chevron-left'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M12.78 15.22a.75.75 0 01-1.06 0l-5-5a.75.75 0 010-1.06l5-5a.75.75 0 111.06 1.06L8.81 10l3.97 3.97a.75.75 0 010 1.06z\" clip-rule=\"evenodd\" />\n </svg>\n <svg v-else-if=\"item.icon === 'chevron-right'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path fill-rule=\"evenodd\" d=\"M7.22 4.78a.75.75 0 011.06 0l5 5a.75.75 0 010 1.06l-5 5a.75.75 0 11-1.06-1.06L11.19 10 7.22 6.03a.75.75 0 010-1.06z\" clip-rule=\"evenodd\" />\n </svg>\n <span v-if=\"item.label && !item.onlyIcon\">{{ item.label }}</span>\n </span>\n </button>\n </div>\n </template>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nconst props = withDefaults(defineProps<{\n htmlType?: 'button' | 'submit' | 'reset'\n variant?: 'primary' | 'secondary' | 'danger' | 'success' | 'info'\n size?: 'tiny' | 'mini' | 'small' | 'medium' | 'large'\n disabled?: boolean\n loading?: boolean\n block?: boolean\n /**\n * 组合按钮位置:\n * - single: 非组合(默认)\n * - start: 组合按钮的第一个\n * - middle: 组合按钮中间\n * - end: 组合按钮最后一个\n */\n groupPosition?: 'single' | 'start' | 'middle' | 'end'\n /**\n * 若提供,则此组件内部渲染为按钮组\n */\n groupItems?: Array<{\n label: string\n value?: string | number\n disabled?: boolean\n loading?: boolean\n variant?: 'primary' | 'secondary' | 'danger' | 'success' | 'info'\n size?: 'tiny' | 'mini' | 'small' | 'medium' | 'large'\n icon?: 'chevron-left' | 'chevron-right'\n onlyIcon?: boolean\n ariaLabel?: string\n }>\n}>(), {\n htmlType: 'button',\n variant: 'primary',\n size: 'medium',\n disabled: false,\n loading: false,\n block: false,\n groupPosition: 'single',\n groupItems: undefined,\n})\n\nconst emit = defineEmits<{\n (e: 'click', ev: MouseEvent): void\n (e: 'group-click', value: string | number | undefined, ev: MouseEvent): void\n}>()\n\nfunction onClick(ev: MouseEvent) {\n if (props.disabled || props.loading) {\n ev.preventDefault()\n ev.stopPropagation()\n return\n }\n emit('click', ev)\n}\n\nconst groupPositionClass = computed(() => {\n switch (props.groupPosition) {\n case 'start':\n return 'group-pos-start'\n case 'middle':\n return 'group-pos-middle'\n case 'end':\n return 'group-pos-end'\n default:\n return 'group-pos-single'\n }\n})\n\nconst isGroup = computed(() => Array.isArray(props.groupItems) && props.groupItems.length > 0)\n\nfunction onGroupItemClick(item: { value?: string | number; disabled?: boolean; loading?: boolean }, ev: MouseEvent) {\n if (props.disabled || props.loading || item.disabled || item.loading) {\n ev.preventDefault()\n ev.stopPropagation()\n return\n }\n emit('group-click', item.value, ev)\n}\n</script>\n\n<style scoped>\n.y-btn {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n border: none;\n border-radius: 10px;\n font-weight: 600;\n cursor: pointer;\n transition: transform 0.05s ease, opacity 0.2s ease;\n outline: none;\n}\n\n/* 尺寸变体 */\n.y-btn--tiny {\n height: 20px;\n padding: 0 6px;\n font-size: 10px;\n border-radius: 3px;\n}\n\n.y-btn--mini {\n height: 24px;\n padding: 0 8px;\n font-size: 11px;\n border-radius: 4px;\n}\n\n.y-btn--small {\n height: 32px;\n padding: 0 12px;\n font-size: 12px;\n border-radius: 5px;\n}\n\n.y-btn--medium {\n height: 44px;\n padding: 0 16px;\n font-size: 14px;\n border-radius: 7px;\n}\n\n.y-btn--large {\n height: 52px;\n padding: 0 20px;\n font-size: 16px;\n border-radius: 8px;\n}\n\n/* 变体样式 */\n.y-btn--primary {\n background: linear-gradient(90deg, #111827, #1f2937);\n color: #fff;\n}\n\n.y-btn--primary:hover { \n background: linear-gradient(90deg, #1f2937, #374151);\n}\n\n.y-btn--secondary {\n background: #f7f7f7;\n color: #374151;\n border: 1px solid #E2E8F0;\n}\n\n.y-btn--secondary:hover {\n background: #ebecee;\n border-color: #9ca3af;\n}\n\n.y-btn--danger {\n background: #c41e3a;\n color: #fff;\n border: 1px solid #c41e3a;\n}\n\n.y-btn--danger:hover {\n background: #ad152e;\n border-color: #ad152e;\n}\n\n.y-btn--success {\n background: #008060;\n color: #fff;\n border: 1px solid #008060;\n}\n\n.y-btn--success:hover {\n background: #006b4f;\n border-color: #006b4f;\n}\n\n.y-btn--info {\n background: #34b4fa;\n color: #fff;\n border: 1px solid #34b4fa;\n}\n\n.y-btn--info:hover {\n background: #1e9bdc;\n border-color: #1e9bdc;\n}\n\n.y-btn:active { \n transform: translateY(1px); \n}\n\n.y-btn.is-block { \n width: 100%; \n}\n\n.y-btn.is-loading { \n cursor: wait; \n opacity: 0.92; \n}\n\n/* 禁用态样式(单按钮与组按钮通用) */\n.y-btn:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n}\n\n.y-btn.is-loading .content { \n opacity: 0; \n}\n\n.y-btn.is-loading::after {\n content: '';\n position: absolute;\n left: 50%;\n top: 50%;\n width: 16px;\n height: 16px;\n transform: translate(-50%, -50%);\n border-radius: 50%;\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: rgba(255,255,255,1);\n animation: spin 0.8s linear infinite;\n}\n\n.y-btn--tiny.is-loading::after {\n width: 10px;\n height: 10px;\n border-width: 1.5px;\n}\n\n.y-btn--mini.is-loading::after {\n width: 12px;\n height: 12px;\n border-width: 1.5px;\n}\n\n.y-btn--small.is-loading::after {\n width: 14px;\n height: 14px;\n border-width: 1.8px;\n}\n\n.y-btn--secondary.is-loading::after {\n border: 2px solid rgba(55, 65, 81, 0.3);\n border-top-color: rgba(55, 65, 81, 1);\n}\n\n.y-btn--danger.is-loading::after {\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: rgba(255,255,255,1);\n}\n\n.y-btn--success.is-loading::after {\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: rgba(255,255,255,1);\n}\n\n.y-btn--info.is-loading::after {\n border: 2px solid rgba(255,255,255,0.3);\n border-top-color: rgba(255,255,255,1);\n}\n\n/* 组合按钮样式(连体) */\n.y-btn-group { display: inline-flex; }\n.y-btn.is-grouped {\n border-radius: 0;\n}\n\n.y-btn.group-pos-start {\n border-top-left-radius: 7px;\n border-bottom-left-radius: 7px;\n}\n\n.y-btn.group-pos-middle {\n margin-left: -1px; /* 抵消边框以无缝连接 */\n}\n\n.y-btn.group-pos-end {\n margin-left: -1px; /* 抵消边框以无缝连接 */\n border-top-right-radius: 7px;\n border-bottom-right-radius: 7px;\n}\n\n/* 针对不同尺寸的圆角适配 */\n.y-btn--tiny.group-pos-start { border-top-left-radius: 3px; border-bottom-left-radius: 3px; }\n.y-btn--tiny.group-pos-end { border-top-right-radius: 3px; border-bottom-right-radius: 3px; }\n\n.y-btn--mini.group-pos-start { border-top-left-radius: 4px; border-bottom-left-radius: 4px; }\n.y-btn--mini.group-pos-end { border-top-right-radius: 4px; border-bottom-right-radius: 4px; }\n\n.y-btn--small.group-pos-start { border-top-left-radius: 5px; border-bottom-left-radius: 5px; }\n.y-btn--small.group-pos-end { border-top-right-radius: 5px; border-bottom-right-radius: 5px; }\n\n.y-btn--large.group-pos-start { border-top-left-radius: 8px; border-bottom-left-radius: 8px; }\n.y-btn--large.group-pos-end { border-top-right-radius: 8px; border-bottom-right-radius: 8px; }\n\n/* 提升 hover 时的层级,避免边框覆盖问题 */\n.y-btn.is-grouped { position: relative; z-index: 1; }\n.y-btn.is-grouped:hover { z-index: 2; }\n\n@keyframes spin {\n to { transform: translate(-50%, -50%) rotate(360deg); }\n}\n\n/* 图标尺寸与对齐 */\n.y-btn .icon {\n width: 16px;\n height: 16px;\n}\n\n@media (prefers-color-scheme: dark) {\n .y-btn--primary { \n background: linear-gradient(90deg, #0b1220, #111827); \n }\n \n .y-btn--secondary {\n background: rgba(2, 6, 23, 0.4);\n border-color: rgba(148, 163, 184, 0.18);\n color: #e5eef7;\n }\n \n .y-btn--secondary:hover {\n background: rgba(2, 6, 23, 0.6);\n border-color: rgba(148, 163, 184, 0.3);\n }\n}\n</style>","<template>\n <div class=\"y-input-wrap\" :class=\"{ 'is-block': block }\" :style=\"{ width: width }\">\n <input\n ref=\"inputRef\"\n class=\"y-input\"\n :class=\"`y-input--${size}`\"\n :id=\"id\"\n :name=\"name\"\n :type=\"type\"\n :placeholder=\"inputPlaceholder\"\n :autocomplete=\"autocomplete\"\n :inputmode=\"inputmode\"\n :min=\"min\"\n :max=\"max\"\n :disabled=\"disabled\"\n :required=\"required\"\n :value=\"modelValue\"\n @input=\"onInput\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n @keyup.enter=\"onEnter\"\n @paste=\"onPaste\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\n\nconst props = withDefaults(defineProps<{\n modelValue?: string\n type?: 'text' | 'email' | 'password' | 'search' | 'tel' | 'url' | 'number'\n placeholder?: string\n autocomplete?: string\n inputmode?: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url'\n id?: string\n name?: string\n disabled?: boolean\n required?: boolean\n block?: boolean\n size?: 'tiny' | 'mini' | 'small' | 'medium' | 'large'\n width?: string\n min?: string | number\n max?: string | number\n clearOnFocus?: boolean\n}>(), {\n modelValue: '',\n type: 'text',\n placeholder: '',\n autocomplete: 'off',\n inputmode: undefined,\n id: undefined,\n name: undefined,\n disabled: false,\n required: false,\n block: false,\n size: 'medium',\n width: '200px',\n min: undefined,\n max: undefined,\n clearOnFocus: false,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: string): void\n (e: 'enter', value: string): void\n (e: 'paste', value: string): void\n}>()\n\nconst inputRef = ref<HTMLInputElement | null>(null)\nconst previousValue = ref<string>('')\nconst hasChanged = ref<boolean>(false) // 标记用户是否修改了输入值\nconst isFocused = ref<boolean>(false) // 标记是否正在聚焦\nconst inputPlaceholder = ref<string>(props.placeholder || '')\n\nwatch(() => props.placeholder, (val) => {\n if (!isFocused.value) {\n inputPlaceholder.value = val || ''\n }\n})\n\nfunction onInput(ev: Event) {\n const target = ev.target as HTMLInputElement\n hasChanged.value = true // 标记用户已修改值\n emit('update:modelValue', target.value)\n}\n\nfunction onFocus() {\n isFocused.value = true\n if (props.clearOnFocus) {\n // 保存聚焦前的值\n previousValue.value = props.modelValue || ''\n // 重置修改标志\n hasChanged.value = false\n // 使用原值展示提示\n inputPlaceholder.value = previousValue.value || props.placeholder || ''\n // 清空输入框\n emit('update:modelValue', '')\n }\n}\n\nfunction onBlur() {\n isFocused.value = false\n if (props.clearOnFocus) {\n // 只有当用户没有修改值且失去焦点时值为空,才恢复之前的值\n if (!hasChanged.value && (!props.modelValue || props.modelValue === '')) {\n emit('update:modelValue', previousValue.value)\n }\n }\n\n // 如果传入了 min,并且当前值小于 min,则自动校正为最小值\n if (props.min !== undefined && props.modelValue !== undefined && props.modelValue !== '') {\n const current = Number(props.modelValue)\n const minVal = Number(props.min)\n if (!Number.isNaN(current) && !Number.isNaN(minVal) && current < minVal) {\n emit('update:modelValue', String(minVal))\n }\n }\n\n inputPlaceholder.value = props.placeholder || ''\n}\n\nfunction onEnter(ev: KeyboardEvent) {\n const target = ev.target as HTMLInputElement\n emit('enter', target.value)\n}\n\nfunction onPaste(ev: ClipboardEvent) {\n const target = ev.target as HTMLInputElement\n requestAnimationFrame(() => {\n emit('paste', target.value)\n })\n}\n</script>\n\n<style scoped>\n.y-input-wrap { width: 100%; }\n.y-input-wrap.is-block { display: block; width: 100%; }\n\n/* 继承登录页 .input 的视觉规范 */\n.y-input {\n width: 100%;\n max-width: 100%;\n box-sizing: border-box;\n border: 1px solid #e2e8f0;\n border-radius: 10px;\n padding: 0 12px;\n font-size: 14px;\n outline: none;\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n background: #ffffff;\n color: #0b1a29;\n}\n\n/* 尺寸变体 */\n.y-input--tiny {\n height: 19px;\n padding: 0 6px;\n font-size: 10px;\n border-radius: 4px;\n}\n\n.y-input--mini {\n height: 24px;\n padding: 0 8px;\n font-size: 11px;\n border-radius: 6px;\n}\n\n.y-input--small {\n height: 32px;\n padding: 0 10px;\n font-size: 12px;\n border-radius: 8px;\n}\n\n.y-input--medium {\n height: 44px;\n padding: 0 12px;\n font-size: 14px;\n border-radius: 10px;\n}\n\n.y-input--large {\n height: 52px;\n padding: 0 16px;\n font-size: 16px;\n border-radius: 12px;\n}\n\n.y-input:focus {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59,130,246,0.15);\n}\n\n@media (prefers-color-scheme: dark) {\n .y-input {\n background: rgba(2,6,23,0.4);\n border-color: rgba(148,163,184,0.18);\n color: #e5eef7;\n }\n}\n</style>\n\n\n","<template>\n <div class=\"ytable-container\" ref=\"tableContainer\">\n <!-- 批量操作栏 -->\n <transition name=\"bulk-slide\">\n <div class=\"bulk-bar\" v-if=\"selectedItems.length && showBulkActions\">\n <div class=\"bulk-left\">已选择 {{ selectedItems.length }} 项</div>\n <div class=\"bulk-actions\">\n <slot name=\"bulk-actions\" :selectedItems=\"selectedItems\" :clearSelection=\"clearSelection\">\n <YButton size=\"small\" class=\"btn\" @click=\"clearSelection\">清除选择</YButton>\n </slot>\n </div>\n </div>\n </transition>\n\n <!-- 表格容器 -->\n <div class=\"card\">\n <!-- 表头右上角收起/展开所有提示标签按钮 -->\n <div class=\"table-header-actions\" v-if=\"hasHintTags\">\n <button \n class=\"toggle-all-hints-btn\" \n :class=\"{ 'is-expanded': allHintsExpanded }\"\n @click=\"toggleAllHints\"\n :title=\"allHintsExpanded ? '收起所有提示标签' : '展开所有提示标签'\"\n >\n <svg \n v-if=\"allHintsExpanded\"\n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"toggle-icon\"\n >\n <path \n d=\"M15 18L9 12L15 6\" \n stroke=\"currentColor\" \n stroke-width=\"2\" \n stroke-linecap=\"round\" \n stroke-linejoin=\"round\"\n />\n </svg>\n <svg \n v-else\n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"toggle-icon\"\n >\n <path \n d=\"M9 18L15 12L9 6\" \n stroke=\"currentColor\" \n stroke-width=\"2\" \n stroke-linecap=\"round\" \n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n <!-- 表头固定区域 -->\n <div class=\"table-header\" ref=\"headerRef\">\n <table class=\"table\">\n <colgroup>\n <col v-if=\"props.expandable\" style=\"width: 34px; min-width: 34px;\" />\n <col v-if=\"selectable\" style=\"width: 60px; min-width: 60px;\" />\n <col v-for=\"(col, i) in columns\" :key=\"col.key\"\n :style=\"{ width: headerColWidths[i] || undefined, minWidth: headerColWidths[i] || '80px' }\" />\n </colgroup>\n <thead>\n <tr>\n <th v-if=\"props.expandable\" class=\"col-expand\"></th>\n <!-- 选择列 -->\n <th v-if=\"selectable\" class=\"col-select\">\n <div class=\"select-header\">\n <input \n type=\"checkbox\" \n :checked=\"isAllVisibleSelected\" \n :indeterminate=\"isPartiallySelected\"\n :disabled=\"isAllVisibleDisabled\"\n @change=\"toggleSelectAllVisible\" \n />\n <span v-if=\"selectedItems.length > 0\" class=\"select-count\">{{ selectedItems.length }}</span>\n </div>\n </th>\n <!-- 动态列头:如果有选中项且提供了自定义表头插槽,则显示自定义内容 -->\n <th \n v-if=\"selectedItems.length > 0 && $slots['selected-header']\"\n :colspan=\"columns.length\"\n class=\"col-selected-header\"\n >\n <div class=\"selected-header-wrapper\">\n <slot name=\"selected-header\" :selectedItems=\"selectedItems\" :clearSelection=\"clearSelection\"></slot>\n </div>\n </th>\n <template v-else>\n <th \n v-for=\"(column, colIndex) in columns\" \n :key=\"column.key\" \n :class=\"getColumnClass(column, true)\"\n :style=\"getColumnStyle(column, colIndex, true)\"\n >\n {{ column.title }}\n </th>\n </template>\n </tr>\n </thead>\n </table>\n </div>\n \n <!-- 表格内容滚动区域 -->\n <div class=\"table-body-wrap\" ref=\"bodyWrapRef\" :class=\"{ 'is-loading': loading, 'is-empty': !pagedData.length && !loading }\" :style=\"{ maxHeight: tableMaxHeight }\">\n <!-- Loading 状态 -->\n <div v-if=\"loading\" class=\"loading-overlay\">\n <div class=\"loading-spinner\"></div>\n <div class=\"loading-text\">加载中...</div>\n </div>\n\n <!-- 空数据覆盖层 -->\n <div v-if=\"!pagedData.length && !loading\" class=\"empty-overlay\">\n <slot name=\"empty\">\n {{ emptyText }}\n </slot>\n </div>\n \n <table class=\"table\" :class=\"{ 'loading-table': loading }\" ref=\"bodyTableRef\">\n <colgroup>\n <col v-if=\"props.expandable\" style=\"width: 34px; min-width: 34px;\" />\n <col v-if=\"selectable\" style=\"width: 60px; min-width: 60px;\" />\n <col v-for=\"(col, i) in columns\" :key=\"col.key\"\n :style=\"{ width: headerColWidths[i] || undefined, minWidth: headerColWidths[i] || '80px' }\" />\n </colgroup>\n <tbody>\n <template v-for=\"(item, index) in pagedData\" :key=\"getRowKey(item, index)\">\n <tr\n :class=\"{ 'row-selected': isRowSelected(item, index) }\"\n @click=\"handleRowClick(item, index)\"\n >\n <td v-if=\"props.expandable\" class=\"col-expand\">\n <button class=\"expand-btn\" type=\"button\" @click.stop=\"toggleRowExpand(getRowKey(item, index))\">\n <span :class=\"['expand-icon', { 'is-open': isRowExpanded(getRowKey(item, index)) }]\"></span>\n </button>\n </td>\n <!-- 选择列 -->\n <td v-if=\"selectable\" class=\"col-select\" @click.stop>\n <input \n type=\"checkbox\" \n :value=\"getRowKey(item, index)\"\n :checked=\"selectedItems.includes(getRowKey(item, index))\" \n :disabled=\"isRowDisabled(item, index)\"\n @change.stop=\"toggleSelect(getRowKey(item, index))\" \n />\n </td>\n <!-- 动态数据列 -->\n <td \n v-for=\"(column, colIndex) in columns\" \n :key=\"column.key\"\n :class=\"getColumnClass(column)\"\n :style=\"getColumnStyle(column, colIndex, false)\"\n >\n <slot \n :name=\"`cell-${column.key}`\" \n :item=\"item\" \n :value=\"getNestedValue(item, column.key)\"\n :index=\"index\"\n >\n {{ formatCellValue(item, column) }}\n </slot>\n </td>\n </tr>\n <tr\n v-if=\"props.expandable && isRowExpanded(getRowKey(item, index))\"\n :key=\"`${getRowKey(item, index)}-expand`\"\n class=\"expand-row\"\n >\n <td :colspan=\"totalTableColumns\" class=\"expand-cell\">\n <slot name=\"expand\" :item=\"item\" :index=\"index\" />\n </td>\n </tr>\n </template>\n </tbody>\n </table>\n </div>\n\n <!-- 分页 -->\n <YPagination\n class=\"align-right\"\n v-if=\"pagination\"\n v-model:current-page=\"currentPage\"\n v-model:page-size=\"pageSize\"\n :loading=\"props.loading\"\n :disable-next=\"shouldDisableNext\"\n :page-size-options=\"pageSizeOptions\"\n @page-change=\"handlePageChange\"\n @page-size-change=\"handlePageSizeChange\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch, onMounted, onUnmounted, nextTick, provide } from 'vue'\n\nexport interface TableColumn {\n key: string\n title: string\n width?: string | number\n align?: 'left' | 'center' | 'right'\n formatter?: (value: any, item: any) => string\n sortable?: boolean\n fixed?: 'left' | 'right'\n}\n\nexport interface TableProps {\n data: any[]\n columns: TableColumn[]\n selectable?: boolean\n showBulkActions?: boolean\n pagination?: boolean\n pageSize?: number\n currentPage?: number\n total?: number\n loading?: boolean\n pageSizeOptions?: Array<{ label: string; value: number }>\n rowKey?: string | ((item: any) => string | number)\n emptyText?: string\n searchKeyword?: string\n searchFields?: string[]\n stickyHeader?: boolean\n expandable?: boolean\n rowDisabled?: (item: any, index: number) => boolean\n selectedItems?: (string | number)[]\n rowSelectable?: boolean\n requireDeselectBeforeSelect?: boolean\n}\n\nconst props = withDefaults(defineProps<TableProps & {\n expandable?: boolean\n rowDisabled?: (item: any, index: number) => boolean\n selectedItems?: (string | number)[]\n rowSelectable?: boolean\n requireDeselectBeforeSelect?: boolean\n}>(), {\n selectable: false,\n showBulkActions: false,\n pagination: true,\n pageSize: 10,\n loading: false,\n pageSizeOptions: () => [\n { label: '1/页', value: 1 },\n { label: '20/页', value: 20 },\n { label: '50/页', value: 50 },\n { label: '100/页', value: 100 }\n ],\n rowKey: 'id',\n emptyText: '无数据',\n searchKeyword: '',\n searchFields: () => [],\n stickyHeader: false,\n rowDisabled: undefined,\n selectedItems: undefined,\n rowSelectable: false,\n requireDeselectBeforeSelect: true\n})\n\nconst emit = defineEmits<{\n edit: [item: any]\n select: [selectedItems: (string | number)[]]\n 'update:selectedItems': [selectedItems: (string | number)[]]\n 'page-change': [page: number]\n 'page-size-change': [size: number]\n 'row-click': [item: any, key: string | number | null]\n}>()\n\n// 响应式数据\nconst currentPage = ref(props.currentPage || 1)\nconst pageSize = ref(props.pageSize)\nconst selectedItems = ref<(string | number)[]>(props.selectedItems || [])\nconst selectedRowKey = ref<(string | number)[]>([])\nconst expandedKeys = ref<Set<string | number>>(new Set())\nconst tableMaxHeight = ref('none')\nconst tableContainer = ref<HTMLElement>()\nconst headerRef = ref<HTMLElement>()\nconst bodyWrapRef = ref<HTMLElement>()\nconst bodyTableRef = ref<HTMLTableElement>()\n// 头部列宽数组:优先使用外部列宽;未传则根据首行内容测量\nconst headerColWidths = ref<string[]>([])\nconst headerWidthMap = ref<Record<string, string>>({})\n// 存储默认表头的标准高度\nconst defaultHeaderHeight = ref<number>(35)\n\n// 管理所有 hintTag 实例\nconst hintTagInstances = ref<Set<any>>(new Set())\n\n// 计算是否有 hintTag 实例(用于控制按钮显示)\nconst hasHintTags = computed(() => hintTagInstances.value.size > 0)\n\n// 计算当前所有 hintTag 的展开状态\n// 使用 hintTagStateUpdateTrigger 确保响应式更新\nconst allHintsExpanded = computed(() => {\n // 引用 hintTagStateUpdateTrigger 以建立响应式依赖\n void hintTagStateUpdateTrigger.value\n \n if (hintTagInstances.value.size === 0) return false\n let expandedCount = 0\n hintTagInstances.value.forEach((instance) => {\n if (instance && instance.isExpanded) {\n expandedCount++\n }\n })\n return expandedCount === hintTagInstances.value.size\n})\n\n// 计算是否所有 hintTag 都已收起\nconst allHintsCollapsed = computed(() => {\n // 引用 hintTagStateUpdateTrigger 以建立响应式依赖\n void hintTagStateUpdateTrigger.value\n \n if (hintTagInstances.value.size === 0) return true\n let collapsedCount = 0\n hintTagInstances.value.forEach((instance) => {\n if (instance && !instance.isExpanded) {\n collapsedCount++\n }\n })\n return collapsedCount === hintTagInstances.value.size\n})\n\n// 注册 hintTag 实例\nfunction registerHintTag(instance: any) {\n hintTagInstances.value.add(instance)\n}\n\n// 注销 hintTag 实例\nfunction unregisterHintTag(instance: any) {\n hintTagInstances.value.delete(instance)\n}\n\n// 收起所有 hintTag\nfunction collapseAllHints() {\n hintTagInstances.value.forEach((instance) => {\n if (instance && typeof instance.collapse === 'function') {\n instance.collapse()\n }\n })\n}\n\n// 展开所有 hintTag\nfunction expandAllHints() {\n hintTagInstances.value.forEach((instance) => {\n if (instance && typeof instance.expand === 'function') {\n instance.expand()\n }\n })\n}\n\n// 切换所有 hintTag 的展开/收起状态\nfunction toggleAllHints() {\n if (allHintsExpanded.value) {\n // 如果全部展开,则全部收起\n collapseAllHints()\n } else {\n // 否则全部展开\n expandAllHints()\n }\n}\n\n// 用于触发计算属性重新计算的响应式变量\nconst hintTagStateUpdateTrigger = ref(0)\n\n// 通知 hintTag 状态变化的函数\nfunction notifyHintTagStateChange() {\n hintTagStateUpdateTrigger.value++\n}\n\n// 通过 provide 向子组件提供注册方法\nprovide('registerHintTag', registerHintTag)\nprovide('unregisterHintTag', unregisterHintTag)\nprovide('notifyHintTagStateChange', notifyHintTagStateChange)\n\nconst autoColumnKeys = computed(() =>\n props.columns\n .filter((col) => !normalizeWidth(col.width))\n .map((col) => col.key)\n)\n\nfunction getAutoColumnWidth(): string {\n const count = autoColumnKeys.value.length || 1\n const per = 100 / count\n return `${per.toFixed(6)}%`\n}\n\n// 自定义竖向滚动条状态\nconst vTrackRef = ref<HTMLElement>()\nconst vScroll = ref({\n show: false,\n thumbHeight: 40,\n thumbTop: 0\n})\nlet isDragging = false\nlet dragStartY = 0\nlet dragStartScrollTop = 0\n\n// 滚动条宽度(用于表头右侧固定列对齐)\nconst scrollbarWidth = ref(0)\n\nfunction normalizeWidth(width?: string | number): string | undefined {\n if (width === undefined || width === null) return undefined\n if (typeof width === 'number') {\n if (Number.isFinite(width)) {\n return `${width}px`\n }\n return undefined\n }\n const trimmed = String(width).trim()\n if (!trimmed) return undefined\n if (/^\\d+(\\.\\d+)?$/.test(trimmed)) {\n return `${trimmed}px`\n }\n return trimmed\n}\n\nfunction parseWidthNumber(width?: string | number): number | null {\n const normalized = normalizeWidth(width)\n if (!normalized) return null\n const parsed = parseFloat(normalized)\n return Number.isFinite(parsed) ? parsed : null\n}\n\n// 计算属性\n// const totalColumns = computed(() => {\n// let count = props.columns.length\n// if (props.selectable) count++\n// return count\n// })\n\nconst totalTableColumns = computed(() => {\n let count = props.columns.length\n if (props.selectable) count += 1\n if (props.expandable) count += 1\n return count\n})\n\nconst filteredData = computed(() => {\n if (!props.searchKeyword || !props.searchFields.length) {\n return props.data\n }\n \n const keyword = props.searchKeyword.toLowerCase()\n return props.data.filter((item) => {\n return props.searchFields!.some(field => {\n const value = getNestedValue(item, field)\n return String(value).toLowerCase().includes(keyword)\n })\n })\n})\n\n// 移除对 total 的依赖,不再计算总页数\n\nconst pagedData = computed(() => {\n if (!props.pagination) return filteredData.value\n // 服务端分页:不再依赖 total 和 totalPages,直接渲染传入数据\n return filteredData.value\n})\n\nconst isAllVisibleSelected = computed(() => {\n if (!props.selectable) return false\n const visibleKeys = pagedData.value\n .map((item, index) => ({ key: getRowKey(item, index), item, index }))\n .filter(({ item, index }) => !isRowDisabled(item, index))\n .map(({ key }) => key)\n return visibleKeys.length > 0 && visibleKeys.every(key => selectedItems.value.includes(key))\n})\n\n// 判断是否为部分选中状态(中间状态)\nconst isPartiallySelected = computed(() => {\n if (!props.selectable) return false\n if (isAllVisibleSelected.value) return false // 如果全选,则不是中间状态\n const visibleKeys = pagedData.value\n .map((item, index) => ({ key: getRowKey(item, index), item, index }))\n .filter(({ item, index }) => !isRowDisabled(item, index))\n .map(({ key }) => key)\n // 如果有可见的未禁用行,且部分被选中,则显示中间状态\n if (visibleKeys.length === 0) return false\n const selectedCount = visibleKeys.filter(key => selectedItems.value.includes(key)).length\n return selectedCount > 0 && selectedCount < visibleKeys.length\n})\n\nconst isAllVisibleDisabled = computed(() => {\n if (!props.selectable) return false\n // 如果所有可见行都被禁用,则全选按钮也禁用\n const visibleKeys = pagedData.value.map((item, index) => ({ item, index }))\n return visibleKeys.length > 0 && visibleKeys.every(({ item, index }) => isRowDisabled(item, index))\n})\n\n// 判断是否应该禁用下一页按钮\n// 当返回的数据量小于 pageSize 时,说明已经到最后一页了\nconst shouldDisableNext = computed(() => {\n if (!props.pagination) return false\n // 如果当前页数据量小于每页显示条数,说明已经是最后一页\n return pagedData.value.length < pageSize.value\n})\n\n// 计算固定列的累计宽度\nconst fixedLeftWidths = computed(() => {\n const widths: number[] = []\n let cumulativeWidth = props.selectable ? 60 : 0 // 选择列宽度\n \n for (let i = 0; i < props.columns.length; i++) {\n const col = props.columns[i]\n if (col.fixed === 'left') {\n let width = 80 // 默认宽度\n const parsedWidth = parseWidthNumber(col.width)\n if (parsedWidth !== null) {\n width = parsedWidth\n } else if (headerColWidths.value[i]) {\n const parsedHeaderWidth = parseWidthNumber(headerColWidths.value[i])\n width = parsedHeaderWidth ?? width\n }\n widths.push(cumulativeWidth)\n cumulativeWidth += width\n }\n }\n return widths\n})\n\nconst fixedRightWidths = computed(() => {\n const widths: number[] = []\n let cumulativeWidth = 0\n \n // 从右往左计算,但需要保证索引顺序正确\n // 先收集所有右侧固定列的宽度和索引\n const rightFixedColumns: Array<{ index: number; width: number }> = []\n for (let i = props.columns.length - 1; i >= 0; i--) {\n const col = props.columns[i]\n if (col.fixed === 'right') {\n let width = 80 // 默认宽度\n const parsedWidth = parseWidthNumber(col.width)\n if (parsedWidth !== null) {\n width = parsedWidth\n } else if (headerColWidths.value[i]) {\n const parsedHeaderWidth = parseWidthNumber(headerColWidths.value[i])\n width = parsedHeaderWidth ?? width\n }\n rightFixedColumns.push({ index: i, width })\n }\n }\n \n // 从右到左计算累计宽度(数组顺序:最右边的列索引最小)\n // widths[i] 对应第 i 个右侧固定列(从右往左数)的 right 偏移量\n for (let i = 0; i < rightFixedColumns.length; i++) {\n widths.push(cumulativeWidth)\n cumulativeWidth += rightFixedColumns[i].width\n }\n \n return widths\n})\n\n// 获取固定列的索引位置(用于查找对应的累计宽度)\nfunction getFixedColumnIndex(columnIndex: number, fixed: 'left' | 'right'): number {\n if (fixed === 'left') {\n let count = 0\n for (let i = 0; i < columnIndex; i++) {\n if (props.columns[i].fixed === 'left') {\n count++\n }\n }\n return count\n } else {\n // 对于右侧固定列,计算从右往左是第几个(索引0是最右边的)\n let count = 0\n for (let i = props.columns.length - 1; i > columnIndex; i--) {\n if (props.columns[i].fixed === 'right') {\n count++\n }\n }\n return count\n }\n}\n\n// 方法\nfunction getRowKey(item: any, index: number): string | number {\n if (typeof props.rowKey === 'function') {\n return props.rowKey(item)\n }\n return item[props.rowKey] || index\n}\n\n// 检查行是否被禁用\nfunction isRowDisabled(item: any, index: number): boolean {\n if (props.rowDisabled && typeof props.rowDisabled === 'function') {\n return props.rowDisabled(item, index)\n }\n return false\n}\n\nfunction isRowExpanded(key: string | number) {\n return expandedKeys.value.has(key)\n}\n\nfunction toggleRowExpand(key: string | number) {\n if (expandedKeys.value.has(key)) {\n expandedKeys.value.delete(key)\n } else {\n expandedKeys.value.add(key)\n }\n}\n\nfunction getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => current?.[key], obj)\n}\n\nfunction getColumnClass(column: TableColumn, isHeader = false): string {\n const classes = [] as string[]\n if (column.align) {\n classes.push(`text-${column.align}`)\n }\n if (column.fixed === 'right') {\n classes.push('col-fixed-right')\n if (isHeader) classes.push('col-fixed-right-header')\n }\n if (column.fixed === 'left') {\n classes.push('col-fixed-left')\n if (isHeader) classes.push('col-fixed-left-header')\n }\n return classes.join(' ')\n}\n\nfunction getColumnStyle(column: TableColumn, columnIndex: number, isHeader: boolean): Record<string, string> {\n const style: Record<string, string> = {}\n \n const normalizedWidth = normalizeWidth(column.width)\n if (normalizedWidth) {\n // 如果设置了固定宽度,使用固定宽度\n style.width = normalizedWidth\n style.minWidth = normalizedWidth\n style.maxWidth = normalizedWidth\n } else {\n // 如果没有设置宽度,使用均等分配的宽度,确保列宽稳定\n const autoWidth = getAutoColumnWidth()\n style.width = autoWidth\n style.minWidth = autoWidth\n style.maxWidth = autoWidth\n }\n \n // 处理固定列的位置\n if (column.fixed === 'left') {\n const fixedIndex = getFixedColumnIndex(columnIndex, 'left')\n const leftOffset = fixedLeftWidths.value[fixedIndex] || 0\n style.left = `${leftOffset}px`\n style.zIndex = isHeader ? `${10 + fixedIndex}` : `${5 + fixedIndex}`\n } else if (column.fixed === 'right') {\n const fixedIndex = getFixedColumnIndex(columnIndex, 'right')\n const rightOffset = fixedRightWidths.value[fixedIndex] || 0\n \n // 对于表头的右侧固定列,减去2px以精确对齐\n // 这可能是因为边框或间距导致的细微差异\n if (isHeader) {\n style.right = `${rightOffset - 3}px`\n } else {\n style.right = `${rightOffset}px`\n }\n \n style.zIndex = isHeader ? `${10 + fixedIndex}` : `${5 + fixedIndex}`\n }\n \n return style\n}\n\nfunction formatCellValue(item: any, column: TableColumn): string {\n const value = getNestedValue(item, column.key)\n if (column.formatter) {\n return column.formatter(value, item)\n }\n return value || ''\n}\n\nfunction toggleSelect(key: string | number) {\n // 找到对应的行数据\n const rowData = pagedData.value.find((item, index) => getRowKey(item, index) === key)\n const rowIndex = pagedData.value.findIndex((item, index) => getRowKey(item, index) === key)\n \n // 如果行被禁用,不允许选择\n if (rowData && rowIndex >= 0 && isRowDisabled(rowData, rowIndex)) {\n return\n }\n \n if (selectedItems.value.includes(key)) {\n selectedItems.value = selectedItems.value.filter(x => x !== key)\n } else {\n selectedItems.value = [...selectedItems.value, key]\n }\n emit('select', selectedItems.value)\n emit('update:selectedItems', selectedItems.value)\n}\n\nfunction toggleSelectAllVisible() {\n // 只处理未禁用的行\n const visibleKeys = pagedData.value\n .map((item, index) => ({ key: getRowKey(item, index), item, index }))\n .filter(({ item, index }) => !isRowDisabled(item, index))\n .map(({ key }) => key)\n \n if (visibleKeys.length === 0) return\n \n if (visibleKeys.every(key => selectedItems.value.includes(key))) {\n selectedItems.value = selectedItems.value.filter(key => !visibleKeys.includes(key))\n } else {\n const union = new Set([...selectedItems.value, ...visibleKeys])\n selectedItems.value = Array.from(union)\n }\n emit('select', selectedItems.value)\n emit('update:selectedItems', selectedItems.value)\n}\n\nfunction clearSelection() {\n selectedItems.value = []\n emit('select', selectedItems.value)\n emit('update:selectedItems', selectedItems.value)\n}\n\n// 行点击选中处理\nfunction handleRowClick(item: any, index: number) {\n if (!props.rowSelectable) return\n \n const key = getRowKey(item, index)\n \n // 如果行被禁用,不允许选择\n if (isRowDisabled(item, index)) {\n return\n }\n \n // 根据 requireDeselectBeforeSelect 决定行为\n if (props.requireDeselectBeforeSelect) {\n // 模式1:可以多选,再次点击为取消\n if (selectedRowKey.value.includes(key)) {\n // 如果已选中,则取消选中\n selectedRowKey.value = selectedRowKey.value.filter(k => k !== key)\n emit('row-click', item, null)\n } else {\n // 如果未选中,则添加到选中列表\n selectedRowKey.value = [...selectedRowKey.value, key]\n emit('row-click', item, key)\n }\n } else {\n // 模式2:点击其他行时,自动切换选中状态(单选模式)\n if (selectedRowKey.value.includes(key)) {\n selectedRowKey.value = []\n emit('row-click', item, null)\n } else {\n selectedRowKey.value = [key]\n emit('row-click', item, key)\n }\n }\n}\n\n// 判断行是否被选中\nfunction isRowSelected(item: any, index: number): boolean {\n if (!props.rowSelectable) return false\n const key = getRowKey(item, index)\n return selectedRowKey.value.includes(key)\n}\n\n// 监听外部传入的 selectedItems prop,同步到内部状态\nwatch(() => props.selectedItems, (newVal) => {\n if (newVal !== undefined && Array.isArray(newVal)) {\n // 只有当外部传入的值与内部值不同时才更新,避免循环更新\n const currentSet = new Set(selectedItems.value)\n const newSet = new Set(newVal)\n if (currentSet.size !== newSet.size || \n ![...currentSet].every(key => newSet.has(key))) {\n selectedItems.value = [...newVal]\n }\n } else if (newVal === undefined && selectedItems.value.length > 0) {\n // 如果外部传入 undefined 且内部有选中项,清空内部选中状态\n selectedItems.value = []\n }\n}, { deep: true, immediate: true })\n\n// 监听搜索关键词变化,重置页码\nwatch(() => props.searchKeyword, () => {\n currentPage.value = 1\n})\n\n// 监听数据变化,重置页码(仅在客户端分页时)并清空选中行\nwatch(() => props.data, () => {\n // 只有在没有外部 total 的情况下(客户端分页)才重置页码\n if (!props.total) {\n currentPage.value = 1\n }\n // 数据变化时清空选中行状态\n if (props.rowSelectable) {\n selectedRowKey.value = []\n }\n}, { deep: true })\n\n// 分页事件处理\nfunction handlePageChange(page: number) {\n currentPage.value = page\n // 分页变化时清空选中行状态\n if (props.rowSelectable) {\n selectedRowKey.value = []\n }\n emit('page-change', page)\n}\n\nfunction handlePageSizeChange(size: number) {\n pageSize.value = size\n currentPage.value = 1 // 切换每页条数后重置到第一页\n // 分页大小变化时清空选中行状态\n if (props.rowSelectable) {\n selectedRowKey.value = []\n }\n emit('page-size-change', size)\n}\n\n// 父组件重置分页时,同步内部选中状态\nwatch(() => props.currentPage, (val) => {\n const next = typeof val === 'number' && val > 0 ? val : 1\n if (currentPage.value !== next) currentPage.value = next\n})\n\nwatch(() => props.pageSize, (val) => {\n const next = typeof val === 'number' && val > 0 ? val : 10\n if (pageSize.value !== next) pageSize.value = next\n})\n\n// 计算表格最大高度\nfunction calculateTableMaxHeight() {\n if (!tableContainer.value) return\n \n nextTick(() => {\n const containerRect = tableContainer.value!.getBoundingClientRect()\n const viewportHeight = window.innerHeight\n const containerTop = containerRect.top\n \n // 获取表头高度\n const headerElement = tableContainer.value!.querySelector('.table-header') as HTMLElement\n const headerHeight = headerElement ? headerElement.offsetHeight : 40\n \n // 获取分页组件高度\n let paginationHeight = 0\n if (props.pagination) {\n const paginationElement = tableContainer.value!.querySelector('.ypagination') as HTMLElement\n paginationHeight = paginationElement ? paginationElement.offsetHeight : 60\n }\n \n // 获取批量操作栏高度\n const bulkBarElement = tableContainer.value!.querySelector('.bulk-bar') as HTMLElement\n const bulkBarHeight = bulkBarElement ? bulkBarElement.offsetHeight : 0\n \n // 计算可用空间\n // 有分页时:减去表头高度、分页组件高度、批量操作栏高度、安全边距(20px)\n // 无分页时:减去表头高度、批量操作栏高度、安全边距(40px,离底部更远)\n const safeMargin = 20\n const reservedHeight = headerHeight + paginationHeight + bulkBarHeight + safeMargin\n const availableHeight = viewportHeight - containerTop - reservedHeight\n \n // 设置最小高度为200px,最大高度为可用空间\n const minHeight = 200\n const maxHeight = Math.max(minHeight, availableHeight)\n \n // 获取表格内容高度\n const tableContent = tableContainer.value!.querySelector('.table-body-wrap .table') as HTMLElement\n if (tableContent) {\n const contentHeight = tableContent.offsetHeight\n \n // 如果内容高度超过可用空间,则限制高度并显示滚动条\n if (contentHeight > availableHeight) {\n tableMaxHeight.value = `${maxHeight}px`\n } else {\n // 如果内容高度小于可用空间,则不限制高度\n tableMaxHeight.value = 'none'\n }\n }\n })\n}\n\n// 同步表头与内容的横向滚动\nlet isSyncingScroll = false // 防止循环同步\nfunction syncHeaderScroll() {\n if (!headerRef.value || !bodyWrapRef.value || isSyncingScroll) return\n if (headerRef.value.scrollLeft !== bodyWrapRef.value.scrollLeft) {\n isSyncingScroll = true\n headerRef.value.scrollLeft = bodyWrapRef.value.scrollLeft\n requestAnimationFrame(() => {\n isSyncingScroll = false\n })\n }\n}\n\n// 同步表头滚动到内容区域\nfunction syncBodyScroll() {\n if (!headerRef.value || !bodyWrapRef.value || isSyncingScroll) return\n if (bodyWrapRef.value.scrollLeft !== headerRef.value.scrollLeft) {\n isSyncingScroll = true\n bodyWrapRef.value.scrollLeft = headerRef.value.scrollLeft\n requestAnimationFrame(() => {\n isSyncingScroll = false\n })\n }\n}\n\n// 计算虚拟竖向滚动条尺寸与位置\nfunction updateVirtualScrollbar() {\n nextTick(() => {\n if (!bodyWrapRef.value) return\n const wrap = bodyWrapRef.value\n const contentHeight = wrap.scrollHeight\n const viewport = wrap.clientHeight\n const scrollTop = wrap.scrollTop\n const needVBar = contentHeight > viewport + 1\n vScroll.value.show = needVBar\n if (!needVBar) return\n\n const minThumb = 24\n const ratio = viewport / contentHeight\n const trackHeight = vTrackRef.value ? vTrackRef.value.clientHeight : viewport\n const thumbHeight = Math.max(minThumb, Math.floor(trackHeight * ratio))\n vScroll.value.thumbHeight = thumbHeight\n\n const maxThumbTop = Math.max(0, trackHeight - thumbHeight)\n const maxScrollTop = Math.max(1, contentHeight - viewport)\n vScroll.value.thumbTop = Math.min(maxThumbTop, Math.floor((scrollTop / maxScrollTop) * maxThumbTop))\n })\n}\n\nfunction onThumbMousemove(e: MouseEvent) {\n if (!isDragging || !bodyWrapRef.value || !vTrackRef.value) return\n e.preventDefault()\n const trackHeight = vTrackRef.value.clientHeight\n const maxThumbTop = Math.max(0, trackHeight - vScroll.value.thumbHeight)\n const wrap = bodyWrapRef.value\n const contentHeight = wrap.scrollHeight\n const viewport = wrap.clientHeight\n const maxScrollTop = Math.max(1, contentHeight - viewport)\n const deltaY = e.clientY - dragStartY\n const scrollDelta = (deltaY / Math.max(1, maxThumbTop)) * maxScrollTop\n wrap.scrollTop = Math.min(maxScrollTop, Math.max(0, dragStartScrollTop + scrollDelta))\n updateVirtualScrollbar()\n}\n\nfunction onThumbMouseup() {\n isDragging = false\n window.removeEventListener('mousemove', onThumbMousemove)\n window.removeEventListener('mouseup', onThumbMouseup)\n}\n\n// function onTrackMousedown(e: MouseEvent) {\n// if (!bodyWrapRef.value || !vTrackRef.value) return\n// // 点击轨道跳转:将滑块中心移动到点击处\n// const rect = vTrackRef.value.getBoundingClientRect()\n// const y = e.clientY - rect.top\n// const trackHeight = vTrackRef.value.clientHeight\n// const thumbHeight = vScroll.value.thumbHeight\n// const targetTop = Math.min(Math.max(0, y - thumbHeight / 2), Math.max(0, trackHeight - thumbHeight))\n//\n// const wrap = bodyWrapRef.value\n// const contentHeight = wrap.scrollHeight\n// const viewport = wrap.clientHeight\n// const maxScrollTop = Math.max(1, contentHeight - viewport)\n// const maxThumbTop = Math.max(1, trackHeight - thumbHeight)\n// const targetScrollTop = (targetTop / maxThumbTop) * maxScrollTop\n// wrap.scrollTop = targetScrollTop\n// updateVirtualScrollbar()\n// }\n\n// 计算/测量列宽:对未设置 width 的列,使用首行单元格的内容宽度\nfunction measureAutoColumnWidths() {\n nextTick(() => {\n // 如果已完整测量过列宽,则不再重复测量,避免分页切换时轻微跳动\n if (headerColWidths.value.length === props.columns.length && headerColWidths.value.every(w => !!w)) {\n return\n }\n const widths: string[] = []\n // 先用 props.columns 中显式宽度填充\n props.columns.forEach((col, index) => {\n const normalizedWidth = normalizeWidth(col.width)\n if (normalizedWidth) {\n widths.push(normalizedWidth)\n headerWidthMap.value[col.key] = normalizedWidth\n } else if (headerWidthMap.value[col.key]) {\n widths.push(headerWidthMap.value[col.key])\n } else {\n const fallback = headerColWidths.value[index]\n if (fallback) {\n widths.push(fallback)\n headerWidthMap.value[col.key] = fallback\n } else {\n const autoWidth = getAutoColumnWidth()\n widths.push(autoWidth)\n headerWidthMap.value[col.key] = autoWidth\n }\n }\n })\n\n const firstRow = bodyTableRef.value?.querySelector('tbody tr') as HTMLTableRowElement | null\n if (firstRow) {\n // 计算 data 列在 tbody 中的起始索引\n const startIndex = props.selectable ? 1 : 0\n const tds = Array.from(firstRow.children) as HTMLElement[]\n for (let i = 0; i < props.columns.length; i++) {\n if (!widths[i]) {\n const td = tds[startIndex + i] as HTMLElement | undefined\n if (td && td.clientWidth > 0) {\n const measured = `${td.clientWidth}px`\n widths[i] = measured\n headerWidthMap.value[props.columns[i].key] = measured\n } else {\n const autoWidth = getAutoColumnWidth()\n widths[i] = autoWidth\n headerWidthMap.value[props.columns[i].key] = autoWidth\n }\n }\n }\n } else {\n // 没有数据时,尽量沿用上一次测量结果,避免列宽跳动\n for (let i = 0; i < widths.length; i++) {\n if (!widths[i]) {\n const stored = headerWidthMap.value[props.columns[i]?.key || '']\n widths[i] = stored || headerColWidths.value[i] || '80px'\n if (props.columns[i]) {\n headerWidthMap.value[props.columns[i].key] = widths[i]\n }\n }\n }\n }\n headerColWidths.value = widths\n })\n}\n\n// 窗口大小变化和滚动时重新计算\nfunction handleResize() {\n calculateTableMaxHeight()\n updateHeaderScrollbarGutter()\n syncSelectedHeaderHeight()\n}\n\n// 监听数据变化,重新计算高度\nwatch(() => props.data, () => {\n nextTick(() => {\n calculateTableMaxHeight()\n // 不在数据变化时重新测量列宽,避免分页切换引起的列宽抖动\n syncHeaderScroll()\n updateHeaderScrollbarGutter()\n expandedKeys.value.clear()\n })\n}, { deep: true })\n\n// 监听分页变化,重新计算高度\nwatch([currentPage, pageSize], () => {\n nextTick(() => {\n calculateTableMaxHeight()\n // 分页切换不再重新测量列宽\n syncHeaderScroll()\n updateHeaderScrollbarGutter()\n })\n})\n\n// 列配置变化时,重置并测量列宽\nwatch(() => props.columns, () => {\n const nextWidths: string[] = []\n const nextMap: Record<string, string> = { ...headerWidthMap.value }\n\n props.columns.forEach((col, idx) => {\n const normalizedWidth = normalizeWidth(col.width)\n if (normalizedWidth) {\n nextWidths.push(normalizedWidth)\n nextMap[col.key] = normalizedWidth\n } else if (nextMap[col.key]) {\n nextWidths.push(nextMap[col.key])\n } else if (headerColWidths.value[idx]) {\n nextWidths.push(headerColWidths.value[idx])\n nextMap[col.key] = headerColWidths.value[idx]\n } else {\n nextWidths.push('')\n }\n })\n\n // 移除已经不存在的列的缓存\n const currentKeys = new Set(props.columns.map(col => col.key))\n Object.keys(nextMap).forEach((key) => {\n if (!currentKeys.has(key)) {\n delete nextMap[key]\n }\n })\n\n headerWidthMap.value = nextMap\n headerColWidths.value = nextWidths\n\n nextTick(() => {\n measureAutoColumnWidths()\n syncHeaderScroll()\n updateHeaderScrollbarGutter()\n syncSelectedHeaderHeight()\n })\n}, { deep: true })\n\n// 测量并存储默认表头的标准高度\nfunction measureDefaultHeaderHeight() {\n nextTick(() => {\n if (!headerRef.value) return\n const headerTable = headerRef.value.querySelector('.table')\n if (!headerTable) return\n \n // 只有当没有选中项时(显示默认表头)才测量\n if (selectedItems.value.length === 0) {\n const firstNormalTh = headerTable.querySelector('thead th:not(.col-select):not(.col-expand)') as HTMLElement\n if (firstNormalTh && firstNormalTh.offsetHeight > 0) {\n defaultHeaderHeight.value = firstNormalTh.offsetHeight\n }\n }\n })\n}\n\n// 同步自定义表头高度与默认表头高度\nfunction syncSelectedHeaderHeight() {\n nextTick(() => {\n if (!headerRef.value) return\n const headerTable = headerRef.value.querySelector('.table')\n if (!headerTable) return\n \n // 如果当前显示的是自定义表头,应用存储的默认高度\n const selectedHeader = headerTable.querySelector('.col-selected-header') as HTMLElement\n if (selectedHeader) {\n const wrapper = selectedHeader.querySelector('.selected-header-wrapper') as HTMLElement\n if (wrapper) {\n wrapper.style.height = `${defaultHeaderHeight.value}px`\n }\n } else {\n // 如果显示的是默认表头,更新存储的高度\n measureDefaultHeaderHeight()\n }\n })\n}\n\n// 监听选中项变化,重新计算高度(批量操作栏显示/隐藏)\nwatch(() => selectedItems.value, () => {\n nextTick(() => {\n calculateTableMaxHeight()\n updateHeaderScrollbarGutter()\n syncSelectedHeaderHeight()\n })\n}, { deep: true })\n\n// 监听 loading 状态变化,更新滚动条补偿\nwatch(() => props.loading, () => {\n nextTick(() => {\n updateHeaderScrollbarGutter()\n })\n})\n\n// 生命周期\nonMounted(() => {\n nextTick(() => {\n calculateTableMaxHeight()\n measureAutoColumnWidths()\n updateHeaderScrollbarGutter()\n updateVirtualScrollbar()\n measureDefaultHeaderHeight()\n syncSelectedHeaderHeight()\n })\n window.addEventListener('resize', handleResize)\n window.addEventListener('scroll', handleResize, true)\n // 监听内容滚动以同步表头\n bodyWrapRef.value?.addEventListener('scroll', () => {\n syncHeaderScroll()\n updateVirtualScrollbar()\n // 滚动时也更新滚动条补偿(因为滚动可能导致内容高度变化)\n updateHeaderScrollbarGutter()\n }, { passive: true })\n // 监听表头滚动以同步内容区域\n headerRef.value?.addEventListener('scroll', () => {\n syncBodyScroll()\n }, { passive: true })\n // 初始同步一次\n nextTick(() => syncHeaderScroll())\n \n // 使用 ResizeObserver 监听内容区域大小变化,实时更新滚动条补偿\n if (bodyWrapRef.value && typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(() => {\n updateHeaderScrollbarGutter()\n })\n resizeObserver.observe(bodyWrapRef.value)\n }\n})\n\nonUnmounted(() => {\n window.removeEventListener('resize', handleResize)\n window.removeEventListener('scroll', handleResize, true)\n bodyWrapRef.value?.removeEventListener('scroll', syncHeaderScroll)\n headerRef.value?.removeEventListener('scroll', syncBodyScroll)\n window.removeEventListener('mousemove', onThumbMousemove)\n window.removeEventListener('mouseup', onThumbMouseup)\n // 清理 ResizeObserver\n if (resizeObserver) {\n resizeObserver.disconnect()\n resizeObserver = null\n }\n})\n\n// 为表头添加与内容滚动条同宽的内边距,避免列错位\nlet lastScrollbarWidth = -1 // 缓存上次的滚动条宽度,避免不必要的 DOM 操作\nfunction updateHeaderScrollbarGutter() {\n if (!headerRef.value || !bodyWrapRef.value) return\n \n // 使用 requestAnimationFrame 确保在浏览器重绘后计算\n requestAnimationFrame(() => {\n if (!headerRef.value || !bodyWrapRef.value) return\n \n const wrap = bodyWrapRef.value\n // 计算滚动条宽度(容器总宽度 - 内容可见宽度)\n // 注意:这里需要考虑竖向滚动条(占用右侧空间)\n const currentScrollbarWidth = Math.ceil(wrap.offsetWidth - wrap.clientWidth)\n \n // 更新响应式变量\n scrollbarWidth.value = currentScrollbarWidth\n \n // 只有当滚动条宽度发生变化时才更新 DOM,避免不必要的操作\n if (currentScrollbarWidth !== lastScrollbarWidth) {\n lastScrollbarWidth = currentScrollbarWidth\n const headerTable = headerRef.value.querySelector('.table') as HTMLElement\n const bodyTable = bodyTableRef.value\n \n if (headerTable && bodyTable) {\n // 先移除之前的样式,确保测量准确\n headerRef.value.style.paddingRight = '0px'\n headerTable.style.width = ''\n headerTable.style.marginRight = ''\n \n // 测量表头和内容区域的 table 实际宽度\n // const headerTableWidth = headerTable.offsetWidth\n // const bodyTableWidth = bodyTable.offsetWidth\n \n // 计算宽度差异\n // const widthDiff = bodyTableWidth - headerTableWidth\n \n if (currentScrollbarWidth > 0) {\n // 如果有滚动条,需要补偿\n // 表头容器的 padding-right 用于补偿滚动条宽度\n headerRef.value.style.paddingRight = `${currentScrollbarWidth}px`\n // table 的宽度设置为 100%(相对于容器内容区域,不包括 padding)\n // 这样表头 table 的宽度就会和内容区域 table 的实际宽度一致\n headerTable.style.width = '100%'\n // 使用负 margin 让 table 向右偏移,填充 padding 区域\n // 这样表头 table 的右边缘就会和内容区域 table 的右边缘对齐\n headerTable.style.marginRight = `-${currentScrollbarWidth}px`\n } else {\n headerRef.value.style.paddingRight = '0px'\n headerTable.style.width = '100%'\n headerTable.style.marginRight = '0px'\n }\n }\n }\n })\n}\n\n// 使用 ResizeObserver 监听内容区域大小变化,自动更新滚动条补偿\nlet resizeObserver: ResizeObserver | null = null\n\n// 清理 hintTag 实例(组件卸载时)\nonUnmounted(() => {\n hintTagInstances.value.clear()\n})\n</script>\n\n<style scoped lang=\"less\">\n.ytable-container {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.bulk-bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 10px;\n background: #FFFFFF;\n border: 1px solid #dfe3e8;\n border-radius: 6px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n\n.bulk-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* 批量操作栏出现/消失动画 */\n.bulk-slide-enter-active,\n.bulk-slide-leave-active {\n transition: all 0.2s ease;\n}\n\n.bulk-slide-enter-from,\n.bulk-slide-leave-to {\n transform: translateY(-8px);\n opacity: 0;\n}\n\n.card {\n border-radius: 6px;\n background: #fff;\n padding: 4px 5px;\n box-shadow: 0rem 0.3125rem 0.3125rem -0.15625rem rgba(0, 0, 0, 0.03),\n 0rem 0.1875rem 0.1875rem -0.09375rem rgba(0, 0, 0, 0.02),\n 0rem 0.125rem 0.125rem -0.0625rem rgba(0, 0, 0, 0.02),\n 0rem 0.0625rem 0.0625rem -0.03125rem rgba(0, 0, 0, 0.03),\n 0rem 0.03125rem 0.03125rem 0rem rgba(0, 0, 0, 0.04),\n 0rem 0rem 0rem 0.0625rem rgba(0, 0, 0, 0.06);\n position: relative;\n}\n\n/* 表头右上角操作按钮区域 */\n.table-header-actions {\n position: absolute;\n top: 8px;\n right: 12px;\n z-index: 10;\n pointer-events: auto;\n}\n\n.toggle-all-hints-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n background: #ffffff;\n color: #666666;\n border: 1px solid #e5e7eb;\n border-radius: 6px;\n cursor: pointer;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);\n transition: all 0.2s ease;\n padding: 0;\n}\n\n.toggle-all-hints-btn:hover {\n color: #333333;\n background: #f5f5f5;\n border-color: #d1d5db;\n box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);\n}\n\n.toggle-all-hints-btn:active {\n transform: scale(0.95);\n}\n\n.toggle-all-hints-btn.is-expanded {\n color: #008060;\n border-color: #008060;\n}\n\n.toggle-all-hints-btn.is-expanded:hover {\n background: #f0f9f7;\n border-color: #006b52;\n}\n\n.toggle-icon {\n width: 16px;\n height: 16px;\n transition: transform 0.2s ease;\n}\n\n/* 表头固定区域 */\n.table-header {\n width: 100%;\n overflow-x: auto; /* 允许水平滚动 */\n overflow-y: hidden; /* 禁止垂直滚动 */\n /* 隐藏滚动条,但保持滚动功能 */\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE/Edge */\n /* 通过 JavaScript 动态设置 table 的 margin-right 来补偿滚动条宽度 */\n box-sizing: border-box;\n position: relative;\n}\n\n/* 隐藏表头区域的滚动条 */\n.table-header::-webkit-scrollbar {\n display: none;\n}\n\n/* 选中状态下的自定义表头 */\n.col-selected-header {\n padding: 0 !important;\n border-bottom: none !important;\n vertical-align: middle; /* 确保垂直对齐与默认表头一致 */\n}\n\n.selected-header-wrapper {\n width: 100%;\n background: #f8f9fa;\n border-bottom: 1px solid #dfe3e8;\n padding: 8px 12px; /* 上下 padding 与默认表头的 8px 8px 保持一致 */\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 8px;\n box-sizing: border-box;\n line-height: 1.5; /* 与默认表头的行高保持一致 */\n /* 使用固定高度确保与默认表头完全一致 */\n /* 默认表头: padding(8px * 2) + 内容高度(约12px * 1.5 = 18px) = 34px */\n height: 35px; /* 包含边框后的总高度 */\n}\n\n/* 表格内容滚动区域 */\n.table-body-wrap {\n width: 100%;\n overflow: auto;\n position: relative;\n padding-right: 0; // 右侧不留 padding\n /* 滚动条会占用空间,通过动态补偿表头来保持对齐 */\n}\n\n// 加载中时,确保最小高度存在,避免高度被收缩\n.table-body-wrap.is-loading {\n min-height: 200px;\n}\n\n// 空数据时保证最小高度,用于承载覆盖层\n.table-body-wrap.is-empty {\n min-height: 200px;\n}\n\n// 空数据覆盖层(不改变表格布局,避免副作用)\n.empty-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n pointer-events: none; // 允许滚动容器继续滚动(若需要)\n}\n\n// 仅在卡片内的滚动区域做“贴边”处理\n.card > .table-body-wrap {\n width: calc(100% + 4px);\n margin-right: -4px; // 抵消 .card 的 5px 右内边距\n}\n\n// 移除已废弃的 overflow: overlay,使用动态计算滚动条宽度来保持对齐\n\n/* 滚动条样式 - 只在内容区域 */\n.table-body-wrap::-webkit-scrollbar {\n width: 4px;\n height: 6px;\n}\n// 隐藏原生竖向滚动条(保留横向)\n.table-body-wrap::-webkit-scrollbar:vertical {\n width: 0;\n}\n\n// 明确指定水平滚动条厚度与侧边一致\n.table-body-wrap::-webkit-scrollbar:horizontal {\n height: 6px;\n}\n\n.table-body-wrap::-webkit-scrollbar-track {\n background: transparent;\n position: relative;\n \n // 添加顶部箭头\n &::before {\n content: '';\n position: absolute;\n top: 1px;\n left: 50%;\n transform: translateX(-50%);\n width: 0;\n height: 0;\n border-left: 2px solid transparent;\n border-right: 2px solid transparent;\n border-bottom: 3px solid #9ca3af;\n z-index: 1;\n transition: all 0.2s ease;\n }\n \n // 添加底部箭头\n &::after {\n content: '';\n position: absolute;\n bottom: 1px;\n left: 50%;\n transform: translateX(-50%);\n width: 0;\n height: 0;\n border-left: 2px solid transparent;\n border-right: 2px solid transparent;\n border-top: 3px solid #9ca3af;\n z-index: 1;\n transition: all 0.2s ease;\n }\n}\n\n// 水平滚动条轨道与左右箭头\n.table-body-wrap::-webkit-scrollbar-track:horizontal {\n background: transparent;\n position: relative;\n}\n\n.table-body-wrap::-webkit-scrollbar-track:horizontal::before {\n content: '';\n position: absolute;\n left: 1px;\n top: 50%;\n transform: translateY(-50%);\n width: 0;\n height: 0;\n border-top: 2px solid transparent;\n border-bottom: 2px solid transparent;\n border-right: 3px solid #9ca3af; // 左侧指向右的三角\n z-index: 1;\n transition: all 0.2s ease;\n}\n\n.table-body-wrap::-webkit-scrollbar-track:horizontal::after {\n content: '';\n position: absolute;\n right: 1px;\n top: 50%;\n transform: translateY(-50%);\n width: 0;\n height: 0;\n border-top: 2px solid transparent;\n border-bottom: 2px solid transparent;\n border-left: 3px solid #9ca3af; // 右侧指向左的三角\n z-index: 1;\n transition: all 0.2s ease;\n}\n\n.table-body-wrap::-webkit-scrollbar-thumb {\n background: #bac0ca;\n border-radius: 2px;\n transition: all 0.2s ease;\n margin: 4px 0; // 为箭头留出空间\n \n &:hover {\n background: #6b7280;\n }\n \n &:active {\n background: #4b5563;\n }\n}\n\n// 水平 thumb 预留左右边距,避免遮挡左右箭头\n.table-body-wrap::-webkit-scrollbar-thumb:horizontal {\n margin: 0 4px;\n}\n\n.table-body-wrap::-webkit-scrollbar-corner {\n background: transparent;\n}\n\n// Firefox 滚动条厚度与颜色(与侧边一致)\n.table-body-wrap {\n scrollbar-width: thin;\n scrollbar-color: #bac0ca transparent;\n}\n\n// 滚动条按钮样式(兼容性)\n.table-body-wrap::-webkit-scrollbar-button {\n display: block;\n height: 4px;\n background: transparent;\n \n // 顶部按钮\n &:vertical:start:decrement {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 3'%3E%3Cpath fill='%239ca3af' d='M2 0L0 3h4z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: center;\n background-size: 4px 3px;\n }\n \n // 底部按钮\n &:vertical:end:increment {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 3'%3E%3Cpath fill='%239ca3af' d='M2 3L0 0h4z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: center;\n background-size: 4px 3px;\n }\n \n &:hover {\n // 悬停时箭头颜色变深\n &:vertical:start:decrement {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 3'%3E%3Cpath fill='%236b7280' d='M2 0L0 3h4z'/%3E%3C/svg%3E\");\n }\n \n &:vertical:end:increment {\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 3'%3E%3Cpath fill='%236b7280' d='M2 3L0 0h4z'/%3E%3C/svg%3E\");\n }\n }\n}\n\n.table {\n width: 100%;\n border-collapse: separate;\n border-spacing: 0;\n table-layout: fixed;\n}\n\n.table thead th {\n text-align: left;\n // font-weight: 600;\n font-size: 12px;\n color: #7c7c7c;\n background: #f8f9fa;\n border-bottom: 1px solid #dfe3e8;\n padding: 8px 8px;\n white-space: nowrap;\n}\n\n\n.table tbody td {\n padding: 4px 8px;\n border-bottom: 1px solid #f1f3f4;\n vertical-align: middle;\n text-align: left;\n font-size: 12px;\n // font-weight: 550;\n color: #535353;\n transition: background-color 0.3s ease;\n}\n\n/* 行选中样式 */\n.table tbody tr {\n transition: background-color 0.3s ease;\n}\n\n.table tbody tr.row-selected {\n background-color: #e6f4ff;\n}\n\n.table tbody tr.row-selected td {\n background-color: #e6f4ff;\n}\n\n.table tbody tr:hover:not(.row-selected) {\n background-color: #f5f5f5;\n}\n\n.col-select {\n width: auto;\n min-width: 60px;\n}\n\n.select-header {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n}\n\n.select-count {\n font-size: 11px;\n color: #1A1A1A;\n font-weight: 600;\n background: #f0f0f0;\n padding: 0 4px;\n border-radius: 3px;\n line-height: 1.4;\n white-space: nowrap;\n}\n\n.col-expand {\n width: 28px;\n text-align: center;\n}\n\n.expand-btn {\n width: 20px;\n height: 20px;\n border: none;\n border-radius: 4px;\n background: transparent;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s ease;\n}\n\n.expand-btn:hover {\n background: rgba(0, 0, 0, 0.05);\n}\n\n.expand-icon {\n display: inline-block;\n width: 0;\n height: 0;\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n border-top: 7px solid #6b7280;\n transition: transform 0.2s ease;\n}\n\n.expand-icon.is-open {\n transform: rotate(180deg);\n}\n\n.expand-row .expand-cell {\n background: #f9fafb;\n}\n\n/* 通用固定列样式(右侧) */\n.table thead th.col-fixed-right,\n.table tbody td.col-fixed-right {\n position: sticky;\n /* right 值通过 JavaScript 动态设置 */\n background: #fff;\n /* z-index 通过 JavaScript 动态设置 */\n transition: background-color 0.3s ease;\n}\n.table tbody td.col-fixed-right {\n box-shadow: -6px 0 6px -6px rgba(0,0,0,0.08);\n}\n\n/* 通用固定列样式(左侧) */\n.table thead th.col-fixed-left,\n.table tbody td.col-fixed-left {\n position: sticky;\n /* left 值通过 JavaScript 动态设置 */\n background: #fff;\n /* z-index 通过 JavaScript 动态设置 */\n transition: background-color 0.3s ease;\n}\n.table tbody td.col-fixed-left {\n box-shadow: 6px 0 6px -6px rgba(0,0,0,0.08);\n}\n\n/* 选中行时固定列的背景色 */\n.table tbody tr.row-selected td.col-fixed-right,\n.table tbody tr.row-selected td.col-fixed-left {\n background-color: #e6f4ff;\n}\n\n.text-left { text-align: left; }\n.text-center { text-align: center; }\n.text-right { text-align: right; }\n\n\n.link {\n background: transparent;\n border: none;\n color: #2563eb;\n cursor: pointer;\n}\n\n.empty {\n text-align: center;\n color: #888;\n padding: 0;\n height: 200px; // 保底高度\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* 复选框主题色为 #1A1A1A */\n.table input[type=\"checkbox\"],\n.bulk-bar input[type=\"checkbox\"] {\n accent-color: #1A1A1A;\n}\n\n/* 复选框中间状态(indeterminate)样式 */\n.table input[type=\"checkbox\"]:indeterminate,\n.bulk-bar input[type=\"checkbox\"]:indeterminate {\n accent-color: #1A1A1A;\n}\n\n/* 聚焦时轻微外发光,保持无侵入 */\n.table input[type=\"checkbox\"]:focus-visible,\n.bulk-bar input[type=\"checkbox\"]:focus-visible {\n outline: none;\n box-shadow: 0 0 0 3px rgba(26, 26, 26, 0.2);\n border-radius: 3px;\n}\n\n/* Loading 状态样式 */\n.loading-overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.8);\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n z-index: 10;\n}\n\n.loading-spinner {\n width: 32px;\n height: 32px;\n border: 3px solid #f3f3f3;\n border-top: 3px solid #1A1A1A;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n margin-bottom: 8px;\n}\n\n.loading-text {\n font-size: 14px;\n color: #666;\n}\n\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.loading-table {\n opacity: 0.6;\n pointer-events: none;\n}\n\n/* 右对齐分页(覆盖子组件内部的 space-between) */\n:deep(.ypagination.align-right) {\n justify-content: flex-end !important;\n}\n\n/* 自定义悬浮竖向滚动条 */\n.v-scrollbar {\n position: absolute;\n top: 0;\n right: 2px;\n bottom: 0;\n width: 8px;\n display: flex;\n align-items: stretch;\n z-index: 5;\n pointer-events: none; // 仅轨道与滑块可交互\n}\n\n.v-scrollbar-track {\n position: relative;\n width: 100%;\n margin: 4px 0;\n border-radius: 4px;\n background: rgba(0,0,0,0.03);\n transition: background 0.2s ease;\n pointer-events: auto;\n}\n\n.v-scrollbar:hover .v-scrollbar-track {\n background: rgba(0,0,0,0.06);\n}\n\n.v-scrollbar-thumb {\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n border-radius: 4px;\n background: rgba(0,0,0,0.24);\n cursor: grab;\n pointer-events: auto;\n transition: background 0.2s ease, opacity 0.2s ease;\n}\n\n.v-scrollbar-thumb:hover {\n background: rgba(0,0,0,0.34);\n}\n\n.v-scrollbar-thumb:active {\n cursor: grabbing;\n background: rgba(0,0,0,0.42);\n}\n</style>\n","<template>\n <div class=\"yselect\" :class=\"{ 'yselect--disabled': disabled, [`yselect--${size}`]: true }\" :style=\"{ width: width }\" ref=\"selectContainer\">\n <div \n ref=\"triggerElement\"\n class=\"yselect__trigger\"\n :class=\"{ \n 'yselect__trigger--open': isOpen,\n 'yselect__trigger--disabled': disabled,\n 'yselect__trigger--error': error\n }\"\n @mousedown.prevent.stop=\"toggleDropdown\"\n @keydown.enter.prevent=\"toggleDropdown\"\n @keydown.space.prevent=\"toggleDropdown\"\n @keydown.escape=\"closeDropdown\"\n @keydown.arrow-down.prevent=\"openDropdown\"\n @keydown.arrow-up.prevent=\"openDropdown\"\n tabindex=\"0\"\n role=\"combobox\"\n :aria-expanded=\"isOpen\"\n :aria-haspopup=\"true\"\n >\n <span class=\"yselect__value\" :class=\"{ 'yselect__placeholder': !selectedLabel }\" v-if=\"!filterable || !isOpen\">\n <slot name=\"value\" :value=\"props.multiple ? selectedOptions : selectedOption\" :label=\"selectedLabel\" :multiple=\"props.multiple\">\n <template v-if=\"props.multiple\">\n <div class=\"yselect__tags\" v-if=\"selectedOptions.length > 0\">\n <span \n v-for=\"(option, idx) in selectedOptions\" \n :key=\"getOptionKey(option, idx)\"\n class=\"yselect__tag\"\n >\n <img \n v-if=\"(option as any)?.flagImg\"\n class=\"yselect__flag\"\n :src=\"(option as any).flagImg\"\n alt=\"flag\"\n />\n <span class=\"yselect__tag-text\">{{ getOptionLabel(option) }}</span>\n <span \n v-if=\"clearable && !disabled\"\n class=\"yselect__tag-close\"\n @click.stop=\"removeTag(option, $event)\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M2.5 2.5l5 5M7.5 2.5l-5 5\" stroke=\"currentColor\" stroke-width=\"1.2\" stroke-linecap=\"round\"/>\n </svg>\n </span>\n </span>\n </div>\n <span v-else class=\"yselect__placeholder-text\">{{ placeholder }}</span>\n </template>\n <template v-else>\n <template v-if=\"selectedOption\">\n <img \n v-if=\"(selectedOption as any)?.flagImg\"\n class=\"yselect__flag\"\n :src=\"(selectedOption as any).flagImg\"\n alt=\"flag\"\n />\n {{ selectedLabel }}\n </template>\n <template v-else>\n {{ placeholder }}\n </template>\n </template>\n </slot>\n </span>\n <input\n v-else\n ref=\"inputElement\"\n class=\"yselect__input\"\n type=\"text\"\n :placeholder=\"props.multiple ? (selectedOptions.length > 0 ? `已选择 ${selectedOptions.length} 项` : placeholder) : (selectedLabel || placeholder)\"\n v-model=\"searchQuery\"\n @keydown.stop\n @keydown.arrow-down.prevent=\"moveHover(1)\"\n @keydown.arrow-up.prevent=\"moveHover(-1)\"\n @keydown.enter.prevent=\"selectHovered()\"\n @keydown.esc.prevent=\"closeDropdown\"\n @keydown.delete.prevent=\"handleClear\"\n />\n <span \n v-if=\"clearable && !disabled && (props.multiple ? selectedOptions.length > 0 : selectedOption)\"\n class=\"yselect__clear\"\n title=\"清空\"\n @click.stop=\"handleClear\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path d=\"M3 3l6 6M9 3L3 9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n </span>\n <span class=\"yselect__arrow\" :class=\"{ 'yselect__arrow--open': isOpen }\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path d=\"M3 4.5L6 7.5L9 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n </div>\n\n <transition name=\"yselect-dropdown\">\n <teleport to=\"body\">\n <div \n v-if=\"isOpen\" \n class=\"yselect__dropdown yselect__dropdown--portal\"\n :class=\"{ 'yselect__dropdown--top': shouldOpenUpward }\"\n :style=\"portalDropdownStyle\"\n @mousedown.stop\n @click.stop\n >\n <div class=\"yselect__options\" ref=\"optionsContainer\">\n <div\n v-for=\"(option, index) in displayedOptions\"\n :key=\"getOptionKey(option, index)\"\n class=\"yselect__option\"\n :class=\"{\n 'yselect__option--selected': isSelected(option),\n 'yselect__option--disabled': isOptionDisabled(option),\n 'yselect__option--hover': hoveredIndex === index\n }\"\n @click=\"selectOption(option, index)\"\n @mouseenter=\"hoveredIndex = index\"\n @mouseleave=\"hoveredIndex = -1\"\n >\n <slot name=\"option\" :option=\"option\" :index=\"index\" :selected=\"isSelected(option)\">\n <span v-if=\"props.multiple\" class=\"yselect__option-check\">\n <svg \n v-if=\"isSelected(option)\"\n width=\"14\" \n height=\"14\" \n viewBox=\"0 0 14 14\" \n fill=\"none\"\n >\n <path d=\"M2 7l3 3 7-7\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n <img \n v-if=\"(option as any)?.flagImg\"\n class=\"yselect__flag\"\n :src=\"(option as any).flagImg\"\n alt=\"flag\"\n />\n {{ getOptionLabel(option) }}\n </slot>\n </div>\n </div>\n </div>\n </teleport>\n </transition>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch, nextTick, onMounted, onUnmounted } from 'vue'\n\nexport interface SelectOption {\n label: string\n value: any\n disabled?: boolean\n [key: string]: any\n}\n\nexport interface SelectProps {\n modelValue?: any | any[]\n options: SelectOption[] | any[]\n placeholder?: string\n disabled?: boolean\n error?: boolean\n clearable?: boolean\n clearTo?: any\n filterable?: boolean\n multiple?: boolean\n valueKey?: string\n labelKey?: string\n disabledKey?: string\n size?: 'small' | 'medium' | 'large'\n width?: string\n}\n\nconst props = withDefaults(defineProps<SelectProps>(), {\n placeholder: '请选择',\n disabled: false,\n error: false,\n clearable: true,\n clearTo: undefined,\n filterable: false,\n multiple: false,\n valueKey: 'value',\n labelKey: 'label',\n disabledKey: 'disabled',\n size: 'medium',\n width: '200px'\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: any | any[]]\n 'change': [value: any | any[], option: SelectOption | SelectOption[] | null]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n 'clear': []\n}>()\n\n// 响应式数据\nconst isOpen = ref(false)\nconst hoveredIndex = ref(-1)\nconst optionsContainer = ref<HTMLElement>()\nconst triggerElement = ref<HTMLElement>()\nconst selectContainer = ref<HTMLElement>()\nconst shouldOpenUpward = ref(false)\nconst inputElement = ref<HTMLInputElement>()\nconst searchQuery = ref('')\n\n// 计算属性\nconst selectedOption = computed(() => {\n if (props.multiple) return null\n return props.options.find(option => getOptionValue(option) === props.modelValue) || null\n})\n\nconst selectedOptions = computed(() => {\n if (!props.multiple) return []\n const values = Array.isArray(props.modelValue) ? props.modelValue : []\n return props.options.filter(option => values.includes(getOptionValue(option)))\n})\n\nconst selectedLabel = computed(() => {\n if (props.multiple) {\n const count = selectedOptions.value.length\n if (count === 0) return ''\n return `已选择 ${count} 项`\n }\n return selectedOption.value ? getOptionLabel(selectedOption.value) : ''\n})\n\nconst displayedOptions = computed(() => {\n if (!props.filterable) return props.options\n const query = searchQuery.value.trim().toLowerCase()\n if (!query) return props.options\n return props.options.filter((opt: any) => {\n const label = getOptionLabel(opt)\n return String(label).toLowerCase().includes(query)\n })\n})\n\n// const dropdownStyle = computed(() => {\n// const style: Record<string, string> = {}\n// \n// if (props.width === 'auto') {\n// style.width = '100%'\n// style.minWidth = 'auto'\n// } else {\n// style.width = props.width\n// style.minWidth = props.width\n// }\n// \n// return style\n// })\n\nconst portalDropdownStyle = computed(() => {\n const style: Record<string, string> = { position: 'fixed', zIndex: '4000' }\n const trigger = triggerElement.value\n if (!trigger) return style\n const rect = trigger.getBoundingClientRect()\n const width = (selectContainer.value?.getBoundingClientRect().width || rect.width)\n style.left = `${rect.left}px`\n style.width = `${width}px`\n if (shouldOpenUpward.value) {\n // 向上展开时,使用 bottom 定位而不是 top,这样更准确\n style.bottom = `${window.innerHeight - rect.top + 4}px`\n style.top = 'auto'\n } else {\n style.top = `${rect.bottom + 4}px`\n }\n return style\n})\n\n// 计算是否应该向上展开\nfunction calculateDropdownPosition() {\n if (!isOpen.value || !triggerElement.value) return\n \n nextTick(() => {\n const trigger = triggerElement.value\n if (!trigger) return\n \n const triggerRect = trigger.getBoundingClientRect()\n const viewportHeight = window.innerHeight\n const dropdownHeight = 200 // 预估下拉菜单高度\n \n // 计算下拉菜单底部位置\n const dropdownBottom = triggerRect.bottom + dropdownHeight + 4 // 4px 是 margin-top\n \n // 计算向上展开时下拉菜单顶部位置\n const dropdownTop = triggerRect.top - dropdownHeight - 4 // 4px 是 margin-bottom\n \n // 如果下拉菜单会超出视口底部,且向上展开不会超出视口顶部,则向上展开\n const shouldOpenDown = dropdownBottom <= viewportHeight - 20 // 20px 安全边距\n const canOpenUp = dropdownTop >= 20 // 20px 安全边距\n \n shouldOpenUpward.value = !shouldOpenDown && canOpenUp\n })\n}\n\n// 方法\nfunction getOptionValue(option: any): any {\n if (typeof option === 'object' && option !== null) {\n return option[props.valueKey]\n }\n return option\n}\n\nfunction getOptionLabel(option: any): string {\n if (typeof option === 'object' && option !== null) {\n return option[props.labelKey] || String(option[props.valueKey])\n }\n return String(option)\n}\n\nfunction getOptionKey(option: any, index: number): string | number {\n if (typeof option === 'object' && option !== null && option.id !== undefined) {\n return option.id\n }\n return getOptionValue(option) || index\n}\n\nfunction isSelected(option: any): boolean {\n if (props.multiple) {\n const values = Array.isArray(props.modelValue) ? props.modelValue : []\n return values.includes(getOptionValue(option))\n }\n return getOptionValue(option) === props.modelValue\n}\n\nfunction isOptionDisabled(option: any): boolean {\n if (typeof option === 'object' && option !== null) {\n return option[props.disabledKey] === true\n }\n return false\n}\n\nfunction toggleDropdown() {\n if (props.disabled) return\n isOpen.value ? closeDropdown() : openDropdown()\n}\n\nfunction openDropdown() {\n if (props.disabled) return\n isOpen.value = true\n nextTick(() => {\n calculateDropdownPosition()\n scrollToSelected()\n if (props.filterable && inputElement.value) {\n inputElement.value.focus()\n // 打开时默认清空,便于直接输入筛选\n searchQuery.value = ''\n }\n })\n}\n\nfunction closeDropdown() {\n isOpen.value = false\n hoveredIndex.value = -1\n shouldOpenUpward.value = false\n if (props.filterable) {\n searchQuery.value = ''\n }\n}\n\nfunction selectOption(option: any, _index: number) {\n if (isOptionDisabled(option)) return\n \n const value = getOptionValue(option)\n \n if (props.multiple) {\n const currentValues = Array.isArray(props.modelValue) ? [...props.modelValue] : []\n const optionValue = getOptionValue(option)\n const valueIndex = currentValues.indexOf(optionValue)\n \n if (valueIndex > -1) {\n // 取消选择\n currentValues.splice(valueIndex, 1)\n } else {\n // 添加选择\n currentValues.push(optionValue)\n }\n \n emit('update:modelValue', currentValues)\n emit('change', currentValues, selectedOptions.value)\n // 多选模式下不关闭下拉框\n } else {\n emit('update:modelValue', value)\n emit('change', value, option)\n closeDropdown()\n }\n}\n\nfunction handleClear() {\n if (!props.clearable || props.disabled) return\n const cleared = props.multiple ? (props.clearTo !== undefined ? props.clearTo : []) : props.clearTo\n emit('update:modelValue', cleared)\n emit('change', cleared, props.multiple ? [] : null)\n emit('clear')\n // 清空后关闭下拉并重置搜索\n if (!props.multiple) {\n closeDropdown()\n }\n}\n\nfunction removeTag(option: any, event: Event) {\n event.stopPropagation()\n if (props.disabled || !props.multiple) return\n \n const currentValues = Array.isArray(props.modelValue) ? [...props.modelValue] : []\n const optionValue = getOptionValue(option)\n const index = currentValues.indexOf(optionValue)\n \n if (index > -1) {\n currentValues.splice(index, 1)\n emit('update:modelValue', currentValues)\n emit('change', currentValues, selectedOptions.value)\n }\n}\n\nfunction moveHover(delta: number) {\n if (!displayedOptions.value || displayedOptions.value.length === 0) {\n hoveredIndex.value = -1\n return\n }\n let next = hoveredIndex.value\n const total = displayedOptions.value.length\n // 初次移动时从 -1 开始\n if (next === -1) {\n next = delta > 0 ? 0 : total - 1\n } else {\n next = (next + delta + total) % total\n }\n // 跳过禁用项,最多循环 total 次避免死循环\n let attempts = 0\n while (attempts < total && isOptionDisabled(displayedOptions.value[next])) {\n next = (next + delta + total) % total\n attempts++\n }\n hoveredIndex.value = attempts >= total ? -1 : next\n scrollHoverIntoView()\n}\n\nfunction selectHovered() {\n if (hoveredIndex.value < 0) return\n const option = displayedOptions.value[hoveredIndex.value]\n if (!option || isOptionDisabled(option)) return\n selectOption(option, hoveredIndex.value)\n}\n\nfunction scrollToSelected() {\n if (!optionsContainer.value) return\n \n const selectedElement = optionsContainer.value.querySelector('.yselect__option--selected') as HTMLElement | null\n if (selectedElement) {\n selectedElement.scrollIntoView({ block: 'nearest' })\n }\n}\n\nfunction scrollHoverIntoView() {\n if (!optionsContainer.value) return\n if (hoveredIndex.value < 0) return\n const optionNodes = optionsContainer.value.querySelectorAll('.yselect__option')\n const el = optionNodes[hoveredIndex.value] as HTMLElement | undefined\n if (el) el.scrollIntoView({ block: 'nearest' })\n}\n\nfunction handleClickOutside(event: Event) {\n const target = event.target as HTMLElement\n if (!selectContainer.value || !selectContainer.value.contains(target)) {\n closeDropdown()\n }\n}\n\n// 监听器\nwatch(() => props.modelValue, () => {\n hoveredIndex.value = -1\n})\n\n// 窗口大小变化和滚动时重新计算位置\nfunction handleResize() {\n if (isOpen.value) {\n calculateDropdownPosition()\n }\n}\n\n// 生命周期\nonMounted(() => {\n document.addEventListener('click', handleClickOutside)\n window.addEventListener('resize', handleResize)\n window.addEventListener('scroll', handleResize, true)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', handleClickOutside)\n window.removeEventListener('resize', handleResize)\n window.removeEventListener('scroll', handleResize, true)\n})\n</script>\n\n<style scoped lang=\"less\">\n.yselect {\n position: relative;\n display: inline-block;\n width: 100%;\n min-width: 0;\n flex-shrink: 0;\n}\n\n.yselect--disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.yselect__trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n min-width: 0;\n flex-shrink: 0;\n border: 1px solid #e2e8f0;\n background: #ffffff;\n cursor: pointer;\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n outline: none;\n line-height: 1.5;\n color: #0b1a29;\n box-sizing: border-box;\n}\n\n.yselect__trigger:hover:not(.yselect__trigger--disabled) {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15);\n}\n\n.yselect__trigger:focus {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15);\n}\n\n.yselect__trigger--open {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15);\n}\n\n.yselect__trigger--disabled {\n background: #f9fafb;\n cursor: not-allowed;\n color: #9ca3af;\n}\n\n.yselect__trigger--error {\n border-color: #ef4444;\n}\n\n.yselect__trigger--error:focus {\n border-color: #ef4444;\n box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.15);\n}\n\n.yselect__value {\n flex: 1;\n overflow: hidden;\n color: #0b1a29;\n display: flex;\n align-items: center;\n min-width: 0;\n}\n\n.yselect__tags {\n display: flex;\n flex-wrap: nowrap;\n gap: 4px;\n align-items: center;\n flex: 1;\n min-width: 0;\n overflow: hidden;\n}\n\n.yselect__tag {\n display: inline-flex;\n align-items: center;\n padding: 2px 6px;\n background: #eff6ff;\n color: #1d4ed8;\n border-radius: 4px;\n font-size: 12px;\n line-height: 1.4;\n max-width: 120px;\n flex-shrink: 1;\n min-width: 0;\n}\n\n.yselect__tag-text {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin-right: 4px;\n}\n\n.yselect__tag-close {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n cursor: pointer;\n color: #1d4ed8;\n flex-shrink: 0;\n margin-left: 2px;\n}\n\n.yselect__tag-close:hover {\n color: #1e40af;\n}\n\n.yselect__placeholder-text {\n color: #9ca3af;\n}\n\n.yselect__flag {\n width: 14px;\n height: 14px;\n object-fit: cover;\n border-radius: 2px;\n margin-right: 6px;\n}\n\n.yselect__placeholder {\n color: #9ca3af;\n}\n\n.yselect__input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n color: #0b1a29;\n font-size: inherit;\n line-height: 1.5;\n min-width: 0;\n}\n\n.yselect__input::placeholder {\n color: #9ca3af;\n}\n\n.yselect__trigger--disabled .yselect__value {\n color: #9ca3af;\n}\n\n.yselect__arrow {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n color: #6b7280;\n transition: transform 0.2s ease;\n flex-shrink: 0;\n}\n\n.yselect__clear {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n color: #9ca3af;\n margin-left: 6px;\n cursor: pointer;\n}\n\n.yselect__clear:hover {\n color: #6b7280;\n}\n\n.yselect__arrow--open {\n transform: rotate(180deg);\n}\n\n.yselect__dropdown {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n z-index: 1000;\n margin-top: 4px;\n background: #ffffff;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n box-shadow: 0 8px 20px rgba(2, 6, 23, 0.15);\n overflow: hidden;\n}\n\n.yselect__dropdown--top {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 4px;\n}\n\n.yselect__options {\n max-height: 200px;\n overflow-y: auto;\n padding: 4px 0;\n}\n\n.yselect__option {\n display: flex;\n align-items: center;\n height: 36px;\n padding: 0 12px;\n cursor: pointer;\n transition: background-color 0.2s ease, color 0.2s ease;\n font-size: 13px;\n line-height: 1.5;\n color: #0b1a29;\n}\n\n.yselect__option-check {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-right: 8px;\n flex-shrink: 0;\n color: #1d4ed8;\n}\n\n.yselect__option:hover:not(.yselect__option--disabled) {\n background-color: #F6F6F7;\n color: #303061;\n}\n\n.yselect__option--selected {\n background: #eff6ff;\n color: #1d4ed8;\n font-weight: 500;\n}\n\n.yselect__option--selected:hover {\n background: #dbeafe;\n}\n\n.yselect__option--disabled {\n color: #9ca3af;\n cursor: not-allowed;\n background: transparent;\n}\n\n.yselect__option--hover {\n background-color: #F6F6F7;\n color: #303061;\n}\n\n/* 尺寸变体 */\n.yselect--small .yselect__trigger {\n height: 32px;\n padding: 0 10px;\n font-size: 12px;\n border-radius: 6px;\n min-width: 80px;\n}\n\n.yselect--medium .yselect__trigger {\n height: 44px;\n padding: 0 12px;\n font-size: 14px;\n border-radius: 8px;\n min-width: 100px;\n}\n\n.yselect--multiple .yselect__trigger {\n min-height: 44px;\n height: auto;\n padding-top: 4px;\n padding-bottom: 4px;\n}\n\n.yselect--multiple.yselect--small .yselect__trigger {\n min-height: 32px;\n padding-top: 2px;\n padding-bottom: 2px;\n}\n\n.yselect--multiple.yselect--large .yselect__trigger {\n min-height: 52px;\n padding-top: 6px;\n padding-bottom: 6px;\n}\n\n.yselect--large .yselect__trigger {\n height: 52px;\n padding: 0 16px;\n font-size: 16px;\n border-radius: 10px;\n min-width: 120px;\n}\n\n/* 过渡动画 */\n.yselect-dropdown-enter-active,\n.yselect-dropdown-leave-active {\n transition: all 0.2s ease;\n transform-origin: top;\n}\n\n.yselect-dropdown-enter-from {\n opacity: 0;\n transform: scaleY(0.8) translateY(-8px);\n}\n\n.yselect-dropdown-leave-to {\n opacity: 0;\n transform: scaleY(0.8) translateY(-8px);\n}\n\n/* 滚动条样式 */\n.yselect__options::-webkit-scrollbar {\n width: 6px;\n}\n\n.yselect__options::-webkit-scrollbar-track {\n background: #f1f5f9;\n}\n\n.yselect__options::-webkit-scrollbar-thumb {\n background: #cbd5e1;\n border-radius: 3px;\n}\n\n.yselect__options::-webkit-scrollbar-thumb:hover {\n background: #94a3b8;\n}\n\n/* 暗色主题支持 */\n@media (prefers-color-scheme: dark) {\n .yselect__trigger {\n background: rgba(2, 6, 23, 0.4);\n border-color: rgba(148, 163, 184, 0.18);\n color: #e5eef7;\n }\n \n .yselect__placeholder {\n color: #9aa6b2;\n }\n \n .yselect__input::placeholder {\n color: #9aa6b2;\n }\n \n .yselect__trigger--disabled {\n background: rgba(2, 6, 23, 0.2);\n color: #9ca3af;\n }\n \n .yselect__value {\n color: #e5eef7;\n }\n \n .yselect__dropdown {\n background: rgba(2, 6, 23, 0.9);\n border-color: rgba(148, 163, 184, 0.18);\n }\n \n .yselect__option {\n color: #e5eef7;\n }\n \n .yselect__option:hover:not(.yselect__option--disabled) {\n background-color: #F6F6F7;\n color: #303061;\n }\n \n .yselect__option--hover {\n background-color: #F6F6F7;\n color: #303061;\n }\n}\n</style>\n","<template>\n <div class=\"ypagination\">\n <div class=\"page-actions\">\n <!-- 上一页按钮 -->\n <YButton\n size=\"small\"\n variant=\"secondary\"\n :disabled=\"currentPage === 1 || loading\"\n @click=\"goToPage(1)\"\n >首页</YButton\n >\n <!-- 在一个 YButton 中生成上一页/下一页组合按钮 -->\n <YButton\n class=\"ml-1\"\n variant=\"secondary\"\n size=\"small\"\n :groupItems=\"[\n { label: '上一页', value: 'prev', disabled: currentPage === 1 || loading, icon: 'chevron-left', onlyIcon: true, ariaLabel: '上一页' },\n { label: '下一页', value: 'next', disabled: loading || disableNext, icon: 'chevron-right', onlyIcon: true, ariaLabel: '下一页' }\n ]\"\n @group-click=\"onPagerGroupClick\"\n />\n\n <!-- 每页条数选择 -->\n <div class=\"page-size-select\">\n <YSelect\n v-model=\"pageSize\"\n :options=\"pageSizeOptions\"\n size=\"small\"\n width=\"105px\"\n :clearable=\"false\"\n :disabled=\"loading\"\n @change=\"handlePageSizeChange\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch } from \"vue\"\n// import type { SelectOption } from \"./YSelect.vue\";\n\nexport interface PaginationProps {\n currentPage: number;\n pageSize: number;\n loading?: boolean;\n pageSizeOptions?: Array<{ label: string; value: number }>;\n disableNext?: boolean; // 是否禁用下一页按钮\n}\n\nconst props = withDefaults(defineProps<PaginationProps>(), {\n loading: false,\n disableNext: false,\n pageSizeOptions: () => [\n { label: \"10/页\", value: 10 },\n { label: \"20/页\", value: 20 },\n { label: \"50/页\", value: 50 },\n { label: \"100/页\", value: 100 },\n ],\n});\n\nconst emit = defineEmits<{\n \"update:currentPage\": [page: number];\n \"update:pageSize\": [size: number];\n \"page-change\": [page: number];\n \"page-size-change\": [size: number];\n}>();\n\n// 响应式数据\nconst pageSize = ref(props.pageSize);\n\n// 每页条数选项\nconst pageSizeOptions = computed(() => props.pageSizeOptions);\n\n// 计算属性\n// 简化:不再计算总页数与页码列表\n\n// 使用计算属性来获取当前页,支持双向绑定\nconst currentPage = computed({\n get: () => props.currentPage,\n set: (value) => {\n emit(\"update:currentPage\", value);\n emit(\"page-change\", value);\n },\n});\n\n// 方法\nfunction goToPage(page: number) {\n if (props.loading) return;\n if (page >= 1 && page !== props.currentPage) {\n currentPage.value = page;\n }\n}\n\nfunction handlePageSizeChange(value: number) {\n if (props.loading) return; // loading 时不允许切换每页条数\n pageSize.value = value;\n emit(\"update:pageSize\", value);\n emit(\"page-size-change\", value);\n // 切换每页条数后,重置到第一页\n currentPage.value = 1;\n}\n\nfunction onPagerGroupClick(action?: string | number) {\n if (props.loading) return;\n if (action === 'prev') {\n goToPage(currentPage.value - 1);\n } else if (action === 'next') {\n goToPage(currentPage.value + 1);\n }\n}\n\n// 同步外部 pageSize\n// (不再根据 totalPages 回调修正 currentPage)\n// 外部如需限制页码由父组件控制\npageSize.value = props.pageSize;\n\n// 监听父组件变更以同步内部状态(确保选中项更新)\nwatch(\n () => props.pageSize,\n (val) => {\n if (typeof val === 'number' && pageSize.value !== val) {\n pageSize.value = val;\n }\n }\n);\n</script>\n\n<style scoped lang=\"less\">\n.ypagination {\n border-top: 1px solid #E6ECF2;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 10px 2px;\n gap: 12px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.page-info {\n font-size: 14px;\n color: #666;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.page-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n min-width: 0;\n}\n\n.btn-group {\n display: inline-flex;\n}\n\n.page-numbers {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n min-width: 0;\n}\n\n.btn {\n height: 28px;\n padding: 0 6px;\n border-radius: 8px;\n border: 1px solid #ddd;\n background: #fff;\n cursor: pointer;\n font-size: 12px;\n transition: all 0.2s ease;\n white-space: nowrap;\n flex-shrink: 0;\n min-width: auto;\n}\n\n.btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.btn:hover:not(:disabled) {\n border-color: #999;\n background: #f8f8f8;\n}\n\n.page-btn {\n min-width: 28px;\n height: 28px;\n padding: 0 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n font-size: 12px;\n}\n\n.page-btn.active {\n background: #474747;\n color: #fff;\n border-color: #474747;\n}\n\n.page-btn.active:hover {\n background: #121820;\n border-color: #121820;\n}\n\n.ellipsis {\n padding: 0 2px;\n color: #999;\n font-size: 12px;\n user-select: none;\n min-width: 12px;\n text-align: center;\n flex-shrink: 0;\n}\n\n.page-size-select {\n flex-shrink: 0;\n min-width: 75px;\n margin-left: 25px;\n}\n\n/* 响应式设计 */\n@media (max-width: 768px) {\n .ypagination {\n flex-direction: column;\n gap: 8px;\n align-items: stretch;\n }\n\n .page-info {\n text-align: center;\n }\n\n .page-actions {\n justify-content: center;\n flex-wrap: wrap;\n }\n\n .page-numbers {\n order: 1;\n justify-content: center;\n }\n\n .btn:first-child,\n .btn:last-child {\n order: 2;\n }\n\n .select {\n order: 3;\n }\n}\n\n@media (max-width: 480px) {\n .page-numbers {\n gap: 2px;\n }\n\n .page-btn {\n min-width: 28px;\n height: 26px;\n padding: 0 6px;\n font-size: 12px;\n }\n\n .btn {\n height: 26px;\n padding: 0 8px;\n font-size: 12px;\n }\n\n .select {\n height: 26px;\n font-size: 12px;\n }\n}\n</style>\n","<template>\r\n <span\r\n class=\"y-badge\"\r\n :class=\"[\r\n `y-badge--${toneClass}`,\r\n `y-badge--${size}`,\r\n { 'is-outline': outline, 'is-pill': pill },\r\n progress ? `y-badge--progress-${progress}` : ''\r\n ]\"\r\n role=\"status\"\r\n :aria-label=\"ariaLabel\"\r\n >\r\n <span class=\"y-badge__inner\">\r\n <!-- 进度/图标优先渲染 -->\r\n <span v-if=\"progress\" class=\"y-badge__progress\" aria-hidden=\"true\">\r\n <svg v-if=\"progress === 'incomplete'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <circle cx=\"10\" cy=\"10\" r=\"5\" />\r\n </svg>\r\n <svg v-else-if=\"progress === 'partiallyComplete'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path d=\"M10 5a5 5 0 100 10V5z\" />\r\n <circle cx=\"10\" cy=\"10\" r=\"5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" />\r\n </svg>\r\n <svg v-else-if=\"progress === 'complete'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path fill-rule=\"evenodd\" d=\"M16.707 5.293a1 1 0 010 1.414l-7.25 7.25a1 1 0 01-1.414 0l-4-4a1 1 0 111.414-1.414L8.75 11.086l6.543-6.543a1 1 0 011.414 0z\" clip-rule=\"evenodd\" />\r\n </svg>\r\n </span>\r\n\r\n <span v-else-if=\"icon\" class=\"y-badge__icon\" aria-hidden=\"true\">\r\n <svg v-if=\"icon === 'dot'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><circle cx=\"10\" cy=\"10\" r=\"4\"/></svg>\r\n <svg v-else-if=\"icon === 'check'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path fill-rule=\"evenodd\" d=\"M16.707 5.293a1 1 0 010 1.414l-7.25 7.25a1 1 0 01-1.414 0l-4-4a1 1 0 111.414-1.414L8.75 11.086l6.543-6.543a1 1 0 011.414 0z\" clip-rule=\"evenodd\" /></svg>\r\n <svg v-else-if=\"icon === 'alert'\" class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path fill-rule=\"evenodd\" d=\"M8.257 3.099c.765-1.36 2.721-1.36 3.486 0l6.518 11.59c.75 1.334-.214 3.011-1.743 3.011H3.482c-1.53 0-2.493-1.677-1.743-3.01L8.257 3.1zM11 14a1 1 0 10-2 0 1 1 0 002 0zm-1-2a1 1 0 01-1-1V8a1 1 0 112 0v3a1 1 0 01-1 1z\" clip-rule=\"evenodd\"/></svg>\r\n <svg v-else class=\"icon\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><circle cx=\"10\" cy=\"10\" r=\"4\"/></svg>\r\n </span>\r\n\r\n <span class=\"y-badge__label\"><slot>{{ label }}</slot></span>\r\n </span>\r\n </span>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from 'vue'\r\n\r\nconst props = withDefaults(defineProps<{\r\n /** 视觉语气 */\r\n tone?: 'default' | 'informational' | 'success' | 'attention' | 'warning' | 'critical'\r\n /** 尺寸 */\r\n size?: 'small' | 'medium'\r\n /** 进度状态(与 icon 互斥,优先级更高) */\r\n progress?: 'incomplete' | 'partiallyComplete' | 'complete'\r\n /** 内置图标:dot | check | alert | placeholder(string 亦以 dot 代替) */\r\n icon?: 'dot' | 'check' | 'alert' | 'placeholder' | string | undefined\r\n /** 是否圆角胶囊 */\r\n pill?: boolean\r\n /** 描边样式(浅背景 + 边框) */\r\n outline?: boolean\r\n /** 文本标签(未提供 slot 时兜底) */\r\n label?: string\r\n}>(), {\r\n tone: 'default',\r\n size: 'medium',\r\n progress: undefined,\r\n icon: undefined,\r\n pill: true,\r\n outline: false,\r\n label: ''\r\n})\r\n\r\nconst toneClass = computed(() => props.tone || 'default')\r\n\r\nconst ariaLabel = computed(() => {\r\n const text = (props.label || '').trim()\r\n const tone = props.tone\r\n const prog = props.progress\r\n if (prog) {\r\n const progMap: Record<string, string> = {\r\n incomplete: '未完成',\r\n partiallyComplete: '部分完成',\r\n complete: '已完成',\r\n }\r\n return text ? `${text},进度:${progMap[prog] || prog}` : `进度:${progMap[prog] || prog}`\r\n }\r\n if (tone && tone !== 'default') {\r\n const toneMap: Record<string, string> = {\r\n informational: '信息',\r\n success: '成功',\r\n attention: '注意',\r\n warning: '警告',\r\n critical: '严重',\r\n default: '默认'\r\n }\r\n return text ? `${text},语气:${toneMap[tone] || tone}` : `语气:${toneMap[tone] || tone}`\r\n }\r\n return text || '标记'\r\n})\r\n</script>\r\n\r\n<style scoped>\r\n.y-badge {\r\n display: inline-flex;\r\n vertical-align: middle;\r\n line-height: 1;\r\n}\r\n\r\n.y-badge__inner {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 6px;\r\n border: 1px solid transparent;\r\n border-radius: 6px;\r\n padding: 2px 8px;\r\n font-weight: 600;\r\n font-size: 12px;\r\n color: #111827;\r\n background-color: #f3f4f6;\r\n}\r\n\r\n/* 尺寸 */\r\n.y-badge--small .y-badge__inner { padding: 1px 6px; font-size: 11px; border-radius: 6px; }\r\n.y-badge--medium .y-badge__inner { padding: 3px 10px; font-size: 12px; border-radius: 8px; }\r\n\r\n/* 胶囊圆角 */\r\n.is-pill .y-badge__inner { border-radius: 9999px; }\r\n\r\n/* 图标与进度图标统一尺寸 */\r\n.y-badge .icon { width: 12px; height: 12px; }\r\n\r\n/* 语气色板(尽量贴近 Polaris 感觉) */\r\n/* default */\r\n.y-badge--default .y-badge__inner { color: #374151; background-color: #F3F4F6; border-color: transparent; }\r\n.is-outline.y-badge--default .y-badge__inner { background-color: #fff; color: #374151; border-color: #E5E7EB; }\r\n\r\n/* informational */\r\n.y-badge--informational .y-badge__inner { color: #0b5394; background-color: #eaf3ff; }\r\n.is-outline.y-badge--informational .y-badge__inner { background-color: #fff; color: #0b5394; border-color: #b3d4ff; }\r\n\r\n/* success */\r\n.y-badge--success .y-badge__inner { color: #006c4f; background-color: #e7f5f0; }\r\n.is-outline.y-badge--success .y-badge__inner { background-color: #fff; color: #006c4f; border-color: #a8e0cf; }\r\n\r\n/* attention(信息但强调) */\r\n.y-badge--attention .y-badge__inner { color: #5b3a00; background-color: #fff3cd; }\r\n.is-outline.y-badge--attention .y-badge__inner { background-color: #fff; color: #5b3a00; border-color: #ffe69c; }\r\n\r\n/* warning */\r\n.y-badge--warning .y-badge__inner { color: #7a4400; background-color: #fdecc8; }\r\n.is-outline.y-badge--warning .y-badge__inner { background-color: #fff; color: #7a4400; border-color: #fbd38d; }\r\n\r\n/* critical */\r\n.y-badge--critical .y-badge__inner { color: #9b1c1c; background-color: #fde8e8; }\r\n.is-outline.y-badge--critical .y-badge__inner { background-color: #fff; color: #9b1c1c; border-color: #f5b5b5; }\r\n\r\n/* 进度类修饰,主要影响图标颜色与对比度(背景跟随 tone) */\r\n.y-badge__progress .icon { opacity: 0.9; }\r\n\r\n/* 深色模式粗略处理 */\r\n@media (prefers-color-scheme: dark) {\r\n .y-badge__inner { color: #e5eef7; background-color: rgba(2, 6, 23, 0.4); border-color: rgba(148, 163, 184, 0.18); }\r\n .y-badge--default .y-badge__inner { color: #e5eef7; background-color: rgba(2, 6, 23, 0.4); }\r\n .is-outline .y-badge__inner { background-color: transparent; }\r\n\r\n .y-badge--informational .y-badge__inner { color: #b7d4ff; background-color: rgba(30, 64, 175, 0.3); border-color: rgba(96, 165, 250, 0.35); }\r\n .y-badge--success .y-badge__inner { color: #b7f0da; background-color: rgba(2, 44, 34, 0.4); border-color: rgba(45, 212, 191, 0.35); }\r\n .y-badge--attention .y-badge__inner { color: #ffe3a3; background-color: rgba(120, 53, 15, 0.35); border-color: rgba(251, 191, 36, 0.35); }\r\n .y-badge--warning .y-badge__inner { color: #ffd9a3; background-color: rgba(120, 53, 15, 0.35); border-color: rgba(251, 191, 36, 0.35); }\r\n .y-badge--critical .y-badge__inner { color: #ffc3c3; background-color: rgba(127, 29, 29, 0.35); border-color: rgba(248, 113, 113, 0.35); }\r\n}\r\n</style>\r\n","<template>\n <teleport to=\"body\">\n <div\n v-show=\"visible\"\n class=\"y-dialog-root\"\n role=\"dialog\"\n :aria-modal=\"true\"\n :aria-hidden=\"!visible\"\n :style=\"{ zIndex: String(zIndex) }\"\n >\n <div\n class=\"y-dialog-mask\"\n @click=\"onMaskClick\"\n ></div>\n\n <transition name=\"dialog-zoom-fade\">\n <div\n v-show=\"visible\"\n ref=\"panelRef\"\n class=\"y-dialog-panel\"\n :class=\"[ center ? 'is-center' : '' ]\"\n :style=\"panelStyle\"\n @keydown.esc.prevent.stop=\"onEsc\"\n tabindex=\"-1\"\n >\n <div v-if=\"showHeader\" class=\"y-dialog-header\">\n <slot name=\"header\">\n <div class=\"y-dialog-title\">{{ title }}</div>\n </slot>\n <button\n v-if=\"closable\"\n type=\"button\"\n class=\"y-dialog-close\"\n aria-label=\"Close\"\n @click=\"close\"\n >\n ✕\n </button>\n </div>\n\n <div class=\"y-dialog-body\">\n <slot />\n </div>\n\n <div v-if=\"$slots.footer\" class=\"y-dialog-footer\">\n <slot name=\"footer\" />\n </div>\n </div>\n </transition>\n </div>\n </teleport>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue'\n\nconst props = withDefaults(defineProps<{\n modelValue?: boolean\n title?: string\n width?: string | number\n top?: string\n closable?: boolean\n maskClosable?: boolean\n zIndex?: number\n showHeader?: boolean\n center?: boolean\n}>(), {\n modelValue: false,\n title: '',\n width: '520px',\n top: '15vh',\n closable: true,\n maskClosable: true,\n zIndex: 3000,\n showHeader: true,\n center: false,\n})\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void\n (e: 'open'): void\n (e: 'close'): void\n}>()\n\nconst visible = computed({\n get: () => props.modelValue,\n set: (v: boolean) => emit('update:modelValue', v),\n})\n\nconst panelRef = ref<HTMLElement | null>(null)\n\nconst panelStyle = computed(() => {\n const style: Record<string, string> = {}\n style.width = typeof props.width === 'number' ? `${props.width}px` : String(props.width)\n style.margin = '0 auto'\n style.top = props.top\n return style\n})\n\nfunction onMaskClick() {\n if (!props.maskClosable) return\n close()\n}\n\nfunction close() {\n if (!visible.value) return\n visible.value = false\n emit('close')\n}\n\nfunction onEsc() {\n if (props.closable) close()\n}\n\nfunction onKeydown(e: KeyboardEvent) {\n if (e.key === 'Escape') onEsc()\n}\n\nwatch(() => props.modelValue, (v) => {\n if (v) {\n emit('open')\n requestAnimationFrame(() => panelRef.value?.focus())\n document.addEventListener('keydown', onKeydown)\n document.body.style.overflow = 'hidden'\n } else {\n document.removeEventListener('keydown', onKeydown)\n document.body.style.overflow = ''\n }\n})\n\nonMounted(() => {\n if (props.modelValue) {\n document.addEventListener('keydown', onKeydown)\n document.body.style.overflow = 'hidden'\n }\n})\n\nonUnmounted(() => {\n document.removeEventListener('keydown', onKeydown)\n document.body.style.overflow = ''\n})\n</script>\n\n<style scoped lang=\"less\">\n.y-dialog-root {\n position: fixed;\n inset: 0;\n}\n\n.y-dialog-mask {\n position: absolute;\n inset: 0;\n background: rgba(2, 6, 23, 0.55);\n backdrop-filter: blur(2px);\n}\n\n.y-dialog-panel {\n position: relative;\n background: #ffffff;\n border-radius: 12px;\n border: 1px solid rgba(15, 23, 42, 0.06);\n box-shadow: 0 12px 40px rgba(2, 6, 23, 0.18);\n}\n\n.y-dialog-panel.is-center .y-dialog-title { text-align: center; width: 100%; }\n\n.y-dialog-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 14px 16px;\n border-bottom: 1px solid rgba(15, 23, 42, 0.06);\n}\n\n.y-dialog-title {\n font-size: 16px;\n font-weight: 600;\n color: #0b1a29;\n}\n\n.y-dialog-close {\n appearance: none;\n border: none;\n background: transparent;\n color: #334155;\n font-size: 16px;\n line-height: 1;\n cursor: pointer;\n padding: 6px;\n border-radius: 8px;\n}\n.y-dialog-close:hover { background: rgba(15,23,42,0.05); }\n\n.y-dialog-body {\n padding: 16px;\n max-height: calc(85vh - 110px);\n overflow: auto;\n}\n\n.y-dialog-footer {\n padding: 12px 16px;\n border-top: 1px solid rgba(15, 23, 42, 0.06);\n}\n\n/* 进入/离场动画:缩放淡入 */\n.dialog-zoom-fade-enter-from,\n.dialog-zoom-fade-leave-to { transform: scale(0.96); opacity: 0; }\n.dialog-zoom-fade-enter-active,\n.dialog-zoom-fade-leave-active { transition: transform 200ms cubic-bezier(0.2, 0.6, 0.4, 1), opacity 200ms cubic-bezier(0.2, 0.6, 0.4, 1); }\n.dialog-zoom-fade-enter-to,\n.dialog-zoom-fade-leave-from { transform: scale(1); opacity: 1; }\n\n@media (prefers-color-scheme: dark) {\n .y-dialog-panel {\n background: rgba(15, 23, 42, 0.7);\n border-color: rgba(148, 163, 184, 0.12);\n box-shadow: 0 12px 40px rgba(2, 6, 23, 0.5);\n }\n .y-dialog-title { color: #e5eef7; }\n .y-dialog-close { color: #cbd5e1; }\n .y-dialog-close:hover { background: rgba(148,163,184,0.12); }\n}\n</style>\n\n\n","<template>\n <div class=\"ypopover\" ref=\"popoverRef\">\n <!-- 触发器 -->\n <div \n ref=\"triggerRef\"\n @click=\"handleTriggerClick\"\n @mouseenter=\"handleMouseEnter\"\n @mouseleave=\"handleMouseLeave\"\n >\n <slot name=\"reference\"></slot>\n </div>\n \n <!-- 弹出内容 -->\n <Teleport to=\"body\">\n <Transition name=\"ypopover-fade\">\n <div\n v-if=\"visible\"\n ref=\"contentRef\"\n class=\"ypopover__content\"\n :class=\"[\n `ypopover__content--${placement}`,\n {\n 'ypopover__content--dark': dark,\n 'ypopover__content--no-padding': !showPadding\n }\n ]\"\n :style=\"contentStyle\"\n @click.stop\n @mouseenter=\"handleContentMouseEnter\"\n @mouseleave=\"handleContentMouseLeave\"\n >\n <!-- 箭头 -->\n <div \n v-if=\"showArrow\"\n class=\"ypopover__arrow\"\n :class=\"`ypopover__arrow--${placement}`\"\n :style=\"arrowStyle\"\n ></div>\n \n <!-- 内容 -->\n <div class=\"ypopover__inner\">\n <slot></slot>\n </div>\n </div>\n </Transition>\n </Teleport>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { ref, computed, onMounted, onUnmounted, nextTick, watch } from 'vue'\n\ninterface Props {\n // 触发方式\n trigger?: 'click' | 'hover' | 'focus' | 'manual'\n // 弹出位置\n placement?: 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end'\n // 是否显示箭头\n showArrow?: boolean\n // 是否显示内边距\n showPadding?: boolean\n // 是否深色主题\n dark?: boolean\n // 是否禁用\n disabled?: boolean\n // 延迟显示时间(hover模式)\n openDelay?: number\n // 延迟隐藏时间(hover模式)\n closeDelay?: number\n // 是否点击外部关闭\n closeOnClickOutside?: boolean\n // 是否点击内容关闭\n closeOnClickContent?: boolean\n // 弹出框宽度\n width?: string | number\n // 弹出框最大宽度\n maxWidth?: string | number\n // 弹出框偏移量\n offset?: number\n // 手动控制显示状态\n modelValue?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n trigger: 'click',\n placement: 'bottom',\n showArrow: true,\n showPadding: true,\n dark: false,\n disabled: false,\n openDelay: 0,\n closeDelay: 200,\n closeOnClickOutside: true,\n closeOnClickContent: false,\n width: 'auto',\n maxWidth: '300px',\n offset: 8,\n modelValue: false\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n 'show': []\n 'hide': []\n 'before-show': []\n 'before-hide': []\n}>()\n\n// 响应式数据\nconst popoverRef = ref<HTMLElement>()\nconst triggerRef = ref<HTMLElement>()\nconst contentRef = ref<HTMLElement>()\nconst visible = ref(false)\nconst triggerRect = ref<DOMRect>()\nconst contentRect = ref<DOMRect>()\nconst arrowPosition = ref<Record<string, string>>({})\n\n// 定时器\nlet openTimer: number | null = null\nlet closeTimer: number | null = null\n\n// 计算属性\nconst contentStyle = computed(() => {\n if (!visible.value || !triggerRect.value) return {}\n \n const style: Record<string, string> = {}\n \n // 设置宽度\n if (props.width !== 'auto') {\n style.width = typeof props.width === 'number' ? `${props.width}px` : props.width\n }\n \n // 设置最大宽度\n if (props.maxWidth) {\n style.maxWidth = typeof props.maxWidth === 'number' ? `${props.maxWidth}px` : props.maxWidth\n }\n \n // 计算位置\n const { top, left } = calculatePosition()\n style.top = `${top}px`\n style.left = `${left}px`\n \n return style\n})\n\nconst arrowStyle = computed(() => {\n if (!props.showArrow) return {}\n \n // 返回计算好的箭头位置,如果没有则使用默认居中\n if (Object.keys(arrowPosition.value).length > 0) {\n return arrowPosition.value\n }\n \n // 默认居中位置\n const style: Record<string, string> = {}\n if (props.placement.startsWith('top') || props.placement.startsWith('bottom')) {\n style.left = '50%'\n } else {\n style.top = '50%'\n }\n return style\n})\n\n// 计算弹出框位置\nfunction calculatePosition() {\n if (!triggerRect.value) return { top: 0, left: 0 }\n \n const { width: triggerWidth, height: triggerHeight, top: triggerTop, left: triggerLeft } = triggerRect.value\n const contentWidth = contentRef.value?.offsetWidth || 200\n const contentHeight = contentRef.value?.offsetHeight || 100\n \n let top = 0\n let left = 0\n \n switch (props.placement) {\n case 'top':\n top = triggerTop - contentHeight - props.offset\n left = triggerLeft + (triggerWidth - contentWidth) / 2\n break\n case 'top-start':\n top = triggerTop - contentHeight - props.offset\n left = triggerLeft\n break\n case 'top-end':\n top = triggerTop - contentHeight - props.offset\n left = triggerLeft + triggerWidth - contentWidth\n break\n case 'bottom':\n top = triggerTop + triggerHeight + props.offset\n left = triggerLeft + (triggerWidth - contentWidth) / 2\n break\n case 'bottom-start':\n top = triggerTop + triggerHeight + props.offset\n left = triggerLeft\n break\n case 'bottom-end':\n top = triggerTop + triggerHeight + props.offset\n left = triggerLeft + triggerWidth - contentWidth\n break\n case 'left':\n top = triggerTop + (triggerHeight - contentHeight) / 2\n left = triggerLeft - contentWidth - props.offset\n break\n case 'left-start':\n top = triggerTop\n left = triggerLeft - contentWidth - props.offset\n break\n case 'left-end':\n top = triggerTop + triggerHeight - contentHeight\n left = triggerLeft - contentWidth - props.offset\n break\n case 'right':\n top = triggerTop + (triggerHeight - contentHeight) / 2\n left = triggerLeft + triggerWidth + props.offset\n break\n case 'right-start':\n top = triggerTop\n left = triggerLeft + triggerWidth + props.offset\n break\n case 'right-end':\n top = triggerTop + triggerHeight - contentHeight\n left = triggerLeft + triggerWidth + props.offset\n break\n }\n \n // 边界检测\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n \n // 水平边界检测\n if (left < 8) left = 8\n if (left + contentWidth > viewportWidth - 8) {\n left = viewportWidth - contentWidth - 8\n }\n \n // 垂直边界检测\n if (top < 8) top = 8\n if (top + contentHeight > viewportHeight - 8) {\n top = viewportHeight - contentHeight - 8\n }\n \n return { top, left }\n}\n\n// 显示弹出框\nfunction show() {\n if (props.disabled || visible.value) return\n \n clearTimers()\n \n if (props.openDelay > 0) {\n openTimer = setTimeout(() => {\n doShow()\n }, props.openDelay)\n } else {\n doShow()\n }\n}\n\nfunction doShow() {\n emit('before-show')\n visible.value = true\n emit('update:modelValue', true)\n emit('show')\n \n // 使用双重 nextTick 确保 DOM 完全更新\n nextTick(() => {\n nextTick(() => {\n updatePosition()\n })\n })\n}\n\n// 隐藏弹出框\nfunction hide() {\n if (!visible.value) return\n \n clearTimers()\n \n if (props.closeDelay > 0) {\n closeTimer = setTimeout(() => {\n doHide()\n }, props.closeDelay)\n } else {\n doHide()\n }\n}\n\nfunction doHide() {\n emit('before-hide')\n visible.value = false\n emit('update:modelValue', false)\n emit('hide')\n}\n\n// 清除定时器\nfunction clearTimers() {\n if (openTimer) {\n clearTimeout(openTimer)\n openTimer = null\n }\n if (closeTimer) {\n clearTimeout(closeTimer)\n closeTimer = null\n }\n}\n\n// 计算箭头位置\nfunction calculateArrowPosition() {\n if (!props.showArrow || !triggerRect.value || !contentRef.value) {\n arrowPosition.value = {}\n return\n }\n \n const trigger = triggerRect.value\n const contentRect = contentRef.value.getBoundingClientRect()\n \n // 如果弹出框还没有正确的尺寸,使用默认居中\n if (contentRect.width === 0 || contentRect.height === 0) {\n const style: Record<string, string> = {}\n if (props.placement.startsWith('top') || props.placement.startsWith('bottom')) {\n style.left = '50%'\n } else {\n style.top = '50%'\n }\n arrowPosition.value = style\n return\n }\n \n const style: Record<string, string> = {}\n \n // 根据位置计算箭头位置\n if (props.placement.startsWith('top')) {\n style.bottom = '-6px'\n // 水平居中\n const triggerCenterX = trigger.left + trigger.width / 2\n const contentLeft = contentRect.left\n const arrowOffset = triggerCenterX - contentLeft\n style.left = `${Math.max(12, Math.min(arrowOffset, contentRect.width - 12))}px`\n } else if (props.placement.startsWith('bottom')) {\n style.top = '-6px'\n // 水平居中\n const triggerCenterX = trigger.left + trigger.width / 2\n const contentLeft = contentRect.left\n const arrowOffset = triggerCenterX - contentLeft\n style.left = `${Math.max(12, Math.min(arrowOffset, contentRect.width - 12))}px`\n } else if (props.placement.startsWith('left')) {\n style.right = '-6px'\n // 垂直居中\n const triggerCenterY = trigger.top + trigger.height / 2\n const contentTop = contentRect.top\n const arrowOffset = triggerCenterY - contentTop\n style.top = `${Math.max(12, Math.min(arrowOffset, contentRect.height - 12))}px`\n } else if (props.placement.startsWith('right')) {\n style.left = '-6px'\n // 垂直居中\n const triggerCenterY = trigger.top + trigger.height / 2\n const contentTop = contentRect.top\n const arrowOffset = triggerCenterY - contentTop\n style.top = `${Math.max(12, Math.min(arrowOffset, contentRect.height - 12))}px`\n }\n \n arrowPosition.value = style\n}\n\n// 更新位置\nfunction updatePosition() {\n if (!triggerRef.value) return\n \n triggerRect.value = triggerRef.value.getBoundingClientRect()\n \n if (contentRef.value) {\n contentRect.value = contentRef.value.getBoundingClientRect()\n \n // 计算箭头位置\n calculateArrowPosition()\n \n // 如果弹出框刚显示,使用 requestAnimationFrame 确保位置正确\n if (visible.value) {\n requestAnimationFrame(() => {\n if (contentRef.value) {\n contentRect.value = contentRef.value.getBoundingClientRect()\n calculateArrowPosition()\n }\n })\n }\n }\n}\n\n// 事件处理\nfunction handleTriggerClick() {\n if (props.disabled) return\n \n if (props.trigger === 'click') {\n if (visible.value) {\n hide()\n } else {\n show()\n }\n }\n}\n\nfunction handleMouseEnter() {\n if (props.disabled || props.trigger !== 'hover') return\n \n clearTimers()\n show()\n}\n\nfunction handleMouseLeave() {\n if (props.disabled || props.trigger !== 'hover') return\n \n hide()\n}\n\n// 鼠标进入弹出框内容\nfunction handleContentMouseEnter() {\n if (props.disabled || props.trigger !== 'hover') return\n \n clearTimers()\n}\n\n// 鼠标离开弹出框内容\nfunction handleContentMouseLeave() {\n if (props.disabled || props.trigger !== 'hover') return\n \n hide()\n}\n\n// 点击外部关闭\nfunction handleClickOutside(event: MouseEvent) {\n if (!props.closeOnClickOutside || !visible.value) return\n \n const target = event.target as HTMLElement\n if (\n popoverRef.value &&\n !popoverRef.value.contains(target) &&\n contentRef.value &&\n !contentRef.value.contains(target)\n ) {\n hide()\n }\n}\n\n// 点击内容关闭\n// function handleContentClick() {\n// if (props.closeOnClickContent) {\n// hide()\n// }\n// }\n\n// 监听 modelValue 变化\nwatch(() => props.modelValue, (newVal) => {\n if (newVal !== visible.value) {\n if (newVal) {\n show()\n } else {\n hide()\n }\n }\n})\n\n// 监听 visible 变化\nwatch(visible, (newVal) => {\n if (newVal) {\n document.addEventListener('click', handleClickOutside)\n window.addEventListener('resize', updatePosition)\n window.addEventListener('scroll', updatePosition, true)\n\n // 初次显示时可能由于 Teleport 尚未完成渲染导致定位不准确,这里增加多次异步更新保证贴边自适应\n nextTick(() => {\n updatePosition()\n requestAnimationFrame(() => {\n updatePosition()\n })\n setTimeout(() => {\n updatePosition()\n }, 0)\n })\n } else {\n document.removeEventListener('click', handleClickOutside)\n window.removeEventListener('resize', updatePosition)\n window.removeEventListener('scroll', updatePosition, true)\n }\n})\n\n// 生命周期\nonMounted(() => {\n if (props.modelValue) {\n show()\n }\n})\n\nonUnmounted(() => {\n clearTimers()\n document.removeEventListener('click', handleClickOutside)\n window.removeEventListener('resize', updatePosition)\n window.removeEventListener('scroll', updatePosition, true)\n})\n\n// 暴露方法\ndefineExpose({\n show,\n hide,\n updatePosition\n})\n</script>\n\n<style scoped lang=\"less\">\n.ypopover {\n display: inline-block;\n}\n\n.ypopover__content {\n position: fixed;\n z-index: 2000;\n background: #ffffff;\n border: 1px solid #e4e7ed;\n border-radius: 4px;\n box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);\n word-wrap: break-word;\n max-width: 300px;\n}\n\n.ypopover__content--dark {\n background: #303133;\n border-color: #303133;\n color: #ffffff;\n}\n\n.ypopover__content--no-padding .ypopover__inner {\n padding: 0;\n}\n\n.ypopover__inner {\n padding: 8px 12px;\n font-size: 14px;\n line-height: 1.4;\n color: #606266;\n}\n\n.ypopover__content--dark .ypopover__inner {\n color: #ffffff;\n}\n\n// 滚动条样式优化\n.ypopover__content,\n.ypopover__inner {\n &::-webkit-scrollbar {\n width: 4px;\n height: 4px;\n }\n\n &::-webkit-scrollbar-track {\n background: transparent;\n border-radius: 2px;\n }\n\n &::-webkit-scrollbar-thumb {\n background: #E7E7E7;\n border-radius: 2px;\n transition: background 0.2s;\n\n &:hover {\n background: #D0D0D0;\n }\n }\n}\n\n.ypopover__content--dark {\n &::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n\n &:hover {\n background: rgba(255, 255, 255, 0.4);\n }\n }\n}\n\n// 穿透样式,应用到 slot 内容中的滚动元素\n:deep(*) {\n &::-webkit-scrollbar {\n width: 4px;\n height: 4px;\n }\n\n &::-webkit-scrollbar-track {\n background: transparent;\n border-radius: 2px;\n }\n\n &::-webkit-scrollbar-thumb {\n background: #E7E7E7;\n border-radius: 2px;\n transition: background 0.2s;\n\n &:hover {\n background: #D0D0D0;\n }\n }\n}\n\n.ypopover__content--dark :deep(*) {\n &::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.3);\n\n &:hover {\n background: rgba(255, 255, 255, 0.4);\n }\n }\n}\n\n.ypopover__arrow {\n position: absolute;\n width: 0;\n height: 0;\n border: 6px solid transparent;\n}\n\n.ypopover__arrow--top {\n border-top-color: #e4e7ed;\n border-bottom: none;\n transform: translateX(-50%);\n}\n\n.ypopover__arrow--top::after {\n content: '';\n position: absolute;\n top: -5px;\n left: -6px;\n border: 6px solid transparent;\n border-top-color: #ffffff;\n border-bottom: none;\n}\n\n.ypopover__arrow--bottom {\n border-bottom-color: #e4e7ed;\n border-top: none;\n transform: translateX(-50%);\n}\n\n.ypopover__arrow--bottom::after {\n content: '';\n position: absolute;\n bottom: -5px;\n left: -6px;\n border: 6px solid transparent;\n border-bottom-color: #ffffff;\n border-top: none;\n}\n\n.ypopover__arrow--left {\n border-left-color: #e4e7ed;\n border-right: none;\n transform: translateY(-50%);\n}\n\n.ypopover__arrow--left::after {\n content: '';\n position: absolute;\n left: -5px;\n top: -6px;\n border: 6px solid transparent;\n border-left-color: #ffffff;\n border-right: none;\n}\n\n.ypopover__arrow--right {\n border-right-color: #e4e7ed;\n border-left: none;\n transform: translateY(-50%);\n}\n\n.ypopover__arrow--right::after {\n content: '';\n position: absolute;\n right: -5px;\n top: -6px;\n border: 6px solid transparent;\n border-right-color: #ffffff;\n border-left: none;\n}\n\n// 深色主题箭头\n.ypopover__content--dark .ypopover__arrow--top {\n border-top-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--top::after {\n border-top-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--bottom {\n border-bottom-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--bottom::after {\n border-bottom-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--left {\n border-left-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--left::after {\n border-left-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--right {\n border-right-color: #303133;\n}\n\n.ypopover__content--dark .ypopover__arrow--right::after {\n border-right-color: #303133;\n}\n\n// 过渡动画\n.ypopover-fade-enter-active,\n.ypopover-fade-leave-active {\n transition: opacity 0.2s ease;\n}\n\n.ypopover-fade-enter-from,\n.ypopover-fade-leave-to {\n opacity: 0;\n}\n</style>\n","<template>\n <div class=\"nh-time-search\" :class=\"[`nh-time--${size}`]\">\n <!-- 主要输入区域 -->\n <div class=\"relative\">\n <div\n ref=\"trigger\"\n @click=\"toggleDropdown\"\n @keydown=\"handleTriggerKeydown\"\n :class=\"['nh-time-trigger', { 'is-focus': isOpen, 'has-value': hasValue }]\"\n tabindex=\"0\"\n >\n <input\n readonly\n :value=\"displayText\"\n :placeholder=\"placeholder\"\n class=\"nh-time-input\"\n />\n <span class=\"nh-time-suffix\">\n <i \n v-if=\"clearable && hasValue\" \n @click.stop=\"handleClearClick\"\n class=\"nh-time-clear\"\n >\n <svg viewBox=\"0 0 1024 1024\" width=\"14\" height=\"14\">\n <path d=\"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm165.4 618.2l-66-.3L512 563.4l-99.3 118.4-66.1.3c-4.4 0-8-3.5-8-8 0-1.9.7-3.7 1.9-5.2l130.1-155L340.5 359a8.32 8.32 0 0 1 1.9-11.2c1.5-1.2 3.3-1.9 5.2-1.9l66.1.3L512 464.6l99.3-118.4 66-.3c4.4 0 8 3.5 8 8 0 1.9-.7 3.7-1.9 5.2L553.5 514l130.1 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z\" fill=\"currentColor\"/>\n </svg>\n </i>\n \n <i class=\"nh-time-icon\">\n <svg viewBox=\"0 0 1024 1024\" width=\"14\" height=\"14\">\n <path d=\"M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32zM648 248v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h112v120H152V248h112v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h312zm184 584H192V424h640v408z\" fill=\"currentColor\"/>\n </svg>\n </i>\n \n <i class=\"nh-time-arrow\" :class=\"{ 'is-reverse': isOpen }\">\n <svg viewBox=\"0 0 1024 1024\" width=\"12\" height=\"12\">\n <path d=\"M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3 0.1-12.7-6.4-12.7z\" fill=\"currentColor\"/>\n </svg>\n </i>\n </span>\n </div>\n\n <!-- 下拉面板 -->\n <transition name=\"el-zoom-in-top\">\n <div\n v-if=\"isOpen\"\n ref=\"dropdown\"\n :class=\"dropdownClasses\"\n @keydown=\"handleDropdownKeydown\"\n >\n <!-- 快捷选项 -->\n <div class=\"nh-time-shortcuts\">\n <div class=\"nh-time-shortcuts-title\">快捷选项</div>\n <ul class=\"nh-time-shortcuts-list\">\n <li\n v-for=\"(shortcut, index) in shortcuts\"\n :key=\"shortcut.label\"\n @click=\"selectShortcut(shortcut)\"\n @keydown=\"handleShortcutKeydown($event, index)\"\n @mouseenter=\"handleShortcutMouseEnter(index)\"\n @mouseleave=\"handleShortcutMouseLeave\"\n :class=\"[\n 'nh-time-shortcut', \n { \n 'is-active': activeShortcutIndex === index,\n 'is-selected': selectedShortcutIndex === index\n }\n ]\"\n tabindex=\"0\"\n >\n {{ shortcut.label }}\n </li>\n </ul>\n </div>\n\n <!-- 自定义时间选择 -->\n <div class=\"nh-time-custom\">\n <div class=\"nh-time-custom-header\">\n <span>自定义时间</span>\n <!-- 新增:选择状态提示 -->\n <div class=\"nh-time-selection-status\">\n <span v-if=\"!tempStartDate && !tempEndDate\" class=\"status-text\">\n 请选择开始日期\n </span>\n <span v-else-if=\"tempStartDate && !tempEndDate\" class=\"status-text\">\n 请选择结束日期\n </span>\n <span v-else-if=\"tempStartDate && tempEndDate\" class=\"status-text status-complete\">\n 已选择完整范围\n </span>\n </div>\n </div>\n \n <!-- 日期选择器容器 -->\n <div class=\"nh-time-pickers\">\n <!-- 开始日期选择器 - 修改为通用日历 -->\n <div class=\"nh-time-picker\">\n <div class=\"nh-date-picker\">\n <!-- 年月选择器 -->\n <div class=\"nh-date-picker-header\">\n <button \n @click=\"changeMonth('start', -1)\"\n class=\"nh-date-picker-btn nh-date-picker-prev-btn\"\n type=\"button\"\n >\n <svg viewBox=\"0 0 1024 1024\" width=\"12\" height=\"12\">\n <path d=\"M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 0 0 0 50.3l450.8 352.1c5.2 4.1 12.9 0.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z\" fill=\"currentColor\"/>\n </svg>\n </button>\n <span class=\"nh-date-picker-header-label\">\n {{ formatYearMonth(startCalendar.year, startCalendar.month) }}\n </span>\n <button \n @click=\"changeMonth('start', 1)\"\n class=\"nh-date-picker-btn nh-date-picker-next-btn\"\n type=\"button\"\n >\n <svg viewBox=\"0 0 1024 1024\" width=\"12\" height=\"12\">\n <path d=\"M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.8 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z\" fill=\"currentColor\"/>\n </svg>\n </button>\n </div>\n \n <!-- 星期标题 -->\n <div class=\"nh-date-picker-content\">\n <table class=\"nh-date-table\">\n <thead>\n <tr>\n <th v-for=\"day in weekDays\" :key=\"day\" class=\"nh-date-table-th\">{{ day }}</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(week, weekIndex) in startCalendarDays\" :key=\"`start-week-${weekIndex}`\">\n <td \n v-for=\"(day, dayIndex) in week\" \n :key=\"`start-day-${weekIndex}-${dayIndex}`\"\n :class=\"getDateCellClass(day, 'start')\"\n @click=\"selectDate(day, 'start')\"\n >\n <div class=\"nh-date-table-cell\">\n <span v-if=\"day\">{{ day.day }}</span>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n \n <!-- 结束日期选择器 - 修改为通用日历 -->\n <div class=\"nh-time-picker\">\n <div class=\"nh-date-picker\">\n <!-- 年月选择器 -->\n <div class=\"nh-date-picker-header\">\n <button \n @click=\"changeMonth('end', -1)\"\n class=\"nh-date-picker-btn nh-date-picker-prev-btn\"\n type=\"button\"\n >\n <svg viewBox=\"0 0 1024 1024\" width=\"12\" height=\"12\">\n <path d=\"M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 0 0 0 50.3l450.8 352.1c5.2 4.1 12.9 0.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z\" fill=\"currentColor\"/>\n </svg>\n </button>\n <span class=\"nh-date-picker-header-label\">\n {{ formatYearMonth(endCalendar.year, endCalendar.month) }}\n </span>\n <button \n @click=\"changeMonth('end', 1)\"\n class=\"nh-date-picker-btn nh-date-picker-next-btn\"\n type=\"button\"\n >\n <svg viewBox=\"0 0 1024 1024\" width=\"12\" height=\"12\">\n <path d=\"M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.8 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z\" fill=\"currentColor\"/>\n </svg>\n </button>\n </div>\n \n <!-- 日期表格 -->\n <div class=\"nh-date-picker-content\">\n <table class=\"nh-date-table\">\n <thead>\n <tr>\n <th v-for=\"day in weekDays\" :key=\"day\" class=\"nh-date-table-th\">{{ day }}</th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(week, weekIndex) in endCalendarDays\" :key=\"`end-week-${weekIndex}`\">\n <td \n v-for=\"(day, dayIndex) in week\" \n :key=\"`end-day-${weekIndex}-${dayIndex}`\"\n :class=\"getDateCellClass(day, 'end')\"\n @click=\"selectDate(day, 'end')\"\n >\n <div class=\"nh-date-table-cell\">\n <span v-if=\"day\">{{ day.day }}</span>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"nh-time-actions\">\n <YButton\n v-if=\"clearable\"\n @click=\"clearSelection\"\n :variant=\"'secondary'\"\n :size=\"size\"\n >\n 清空\n </YButton>\n <!-- 修改:优化确定按钮的状态提示 -->\n <YButton\n @click=\"confirmSelection\"\n :disabled=\"!canConfirm\"\n :variant=\"'primary'\"\n :size=\"size\"\n >\n {{ tempStartDate && !tempEndDate ? '继续选择结束日期' : '确认' }}\n </YButton>\n </div>\n </div>\n </div>\n </transition>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'\n\n// 定义类型\ninterface TimeRange {\n startDate: Date | null\n endDate: Date | null\n}\n\ninterface Shortcut {\n label: string\n getValue: () => TimeRange\n}\n\ninterface Props {\n modelValue?: TimeRange | { startDate: string | Date | number | null, endDate: string | Date | number | null }\n placeholder?: string\n shortcuts?: Shortcut[]\n clearable?: boolean\n format?: 'timestamp' | 'string' | 'date'\n includeTime?: boolean\n size?: 'mini' | 'small' | 'medium' | 'large'\n}\n\ninterface CalendarDay {\n date: Date\n day: number\n isCurrentMonth: boolean\n isToday: boolean\n isSelected: boolean\n isInRange: boolean\n isDisabled: boolean\n}\n\n// 定义 props,添加 includeTime 属性并提供默认值\nconst props = withDefaults(defineProps<Props>(), {\n modelValue: () => ({ startDate: null, endDate: null }),\n placeholder: '请选择日期范围',\n clearable: true,\n format: 'timestamp',\n includeTime: false,\n size: 'small',\n shortcuts: () => [\n {\n label: '今天',\n getValue: () => {\n const today = new Date()\n const start = new Date(today.getFullYear(), today.getMonth(), today.getDate())\n const end = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59)\n return { startDate: start, endDate: end }\n }\n },\n {\n label: '昨天',\n getValue: () => {\n const yesterday = new Date()\n yesterday.setDate(yesterday.getDate() - 1)\n const start = new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate())\n const end = new Date(yesterday.getFullYear(), yesterday.getMonth(), yesterday.getDate(), 23, 59, 59)\n return { startDate: start, endDate: end }\n }\n },\n {\n label: '近7天',\n getValue: () => {\n const end = new Date()\n const start = new Date()\n start.setDate(start.getDate() - 6)\n start.setHours(0, 0, 0, 0)\n end.setHours(23, 59, 59, 999)\n return { startDate: start, endDate: end }\n }\n },\n {\n label: '近30天',\n getValue: () => {\n const end = new Date()\n const start = new Date()\n start.setDate(start.getDate() - 29)\n start.setHours(0, 0, 0, 0)\n end.setHours(23, 59, 59, 999)\n return { startDate: start, endDate: end }\n }\n },\n {\n label: '近3个月',\n getValue: () => {\n const end = new Date()\n const start = new Date()\n start.setMonth(start.getMonth() - 3)\n start.setHours(0, 0, 0, 0)\n end.setHours(23, 59, 59, 999)\n return { startDate: start, endDate: end }\n }\n }\n ]\n})\n\n// 定义 emits\nconst emit = defineEmits<{\n 'update:modelValue': [value: TimeRange | { startDate: string | number | null, endDate: string | number | null }]\n 'change': [value: TimeRange | { startDate: string | number | null, endDate: string | number | null }]\n}>()\n\n// 响应式数据\nconst isOpen = ref(false)\nconst activeShortcutIndex = ref(-1)\nconst selectedShortcutIndex = ref(-1)\nconst pendingValue = ref<TimeRange | null>(null)\nconst trigger = ref<HTMLElement>()\nconst dropdown = ref<HTMLElement>()\nconst dropdownPosition = ref({\n top: true,\n left: true\n})\n\n// 修改:日历相关的响应式数据\nconst startCalendar = ref({\n year: new Date().getFullYear(),\n month: new Date().getMonth()\n})\n\nconst endCalendar = ref({\n year: new Date().getFullYear(),\n month: new Date().getMonth() + 1\n})\n\n// 新增:确保结束日历月份不会与开始日历相同的函数\nconst ensureDifferentMonths = () => {\n const startTime = new Date(startCalendar.value.year, startCalendar.value.month).getTime()\n const endTime = new Date(endCalendar.value.year, endCalendar.value.month).getTime()\n \n if (startTime >= endTime) {\n // 如果开始月份大于等于结束月份,将结束月份设为开始月份的下一个月\n const nextMonth = new Date(startCalendar.value.year, startCalendar.value.month + 1)\n endCalendar.value.year = nextMonth.getFullYear()\n endCalendar.value.month = nextMonth.getMonth()\n }\n}\n\n// 新增:确保开始日历月份不会与结束日历相同的函数\nconst ensureDifferentMonthsReverse = () => {\n const startTime = new Date(startCalendar.value.year, startCalendar.value.month).getTime()\n const endTime = new Date(endCalendar.value.year, endCalendar.value.month).getTime()\n \n if (endTime <= startTime) {\n // 如果结束月份小于等于开始月份,将开始月份设为结束月份的上一个月\n const prevMonth = new Date(endCalendar.value.year, endCalendar.value.month - 1)\n startCalendar.value.year = prevMonth.getFullYear()\n startCalendar.value.month = prevMonth.getMonth()\n }\n}\n\nconst weekDays = ['一', '二', '三', '四', '五', '六', '日']\n\nconst tempStartDate = ref<Date | null>(null)\nconst tempEndDate = ref<Date | null>(null)\n\n// 修改:日期转换工具函数 - 支持时间戳\nconst parseDate = (date: string | Date | number | null): Date | null => {\n if (!date) return null\n if (date instanceof Date) return date\n if (typeof date === 'number') {\n // 时间戳格式\n return new Date(date)\n }\n if (typeof date === 'string') {\n const parsed = new Date(date)\n return isNaN(parsed.getTime()) ? null : parsed\n }\n return null\n}\n\n// 修改:格式化为字符串 - 根据 includeTime 决定返回格式\nconst formatDateToString = (date: Date | null): string | null => {\n if (!date) return null\n \n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n \n if (props.includeTime) {\n // 年月日时分秒格式: YYYY-MM-DD HH:mm:ss\n const hours = String(date.getHours()).padStart(2, '0')\n const minutes = String(date.getMinutes()).padStart(2, '0')\n const seconds = String(date.getSeconds()).padStart(2, '0')\n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`\n } else {\n // 年月日格式: YYYY-MM-DD\n return `${year}-${month}-${day}`\n }\n}\n\n// 格式化为时间戳\nconst formatDateToTimestamp = (date: Date | null): number | null => {\n if (!date) return null\n return date.getTime()\n}\n\n// 修改:标准化输入值\nconst normalizeValue = (value: any): TimeRange => {\n if (!value) return { startDate: null, endDate: null }\n \n return {\n startDate: parseDate(value.startDate),\n endDate: parseDate(value.endDate)\n }\n}\n\n// 修改:格式化输出值 - 确保根据 includeTime 属性决定时间戳的精度\nconst formatOutputValue = (value: TimeRange) => {\n if (props.format === 'string') {\n // 返回根据 includeTime 决定的字符串格式\n return {\n startDate: formatDateToString(value.startDate),\n endDate: formatDateToString(value.endDate)\n }\n } else if (props.format === 'timestamp') {\n // 返回时间戳\n return {\n startDate: formatDateToTimestamp(value.startDate),\n endDate: formatDateToTimestamp(value.endDate)\n }\n } else {\n // format === 'date',返回Date对象\n return value\n }\n}\n\n// 工具函数\nconst formatYearMonth = (year: number, month: number) => {\n return `${String(month + 1).padStart(2, '0')}/${year}`\n}\n\nconst isSameDay = (date1: Date, date2: Date) => {\n return date1.getFullYear() === date2.getFullYear() &&\n date1.getMonth() === date2.getMonth() &&\n date1.getDate() === date2.getDate()\n}\n\nconst isDateInRange = (date: Date, start: Date | null, end: Date | null) => {\n if (!start || !end) return false\n return date >= start && date <= end\n}\n\n// 修改:检查当前值是否匹配某个快捷选项\nconst findMatchingShortcutIndex = (currentValue: any): number => {\n const normalizedValue = normalizeValue(currentValue)\n \n if (!normalizedValue?.startDate || !normalizedValue?.endDate) {\n return -1\n }\n\n for (let i = 0; i < props.shortcuts.length; i++) {\n const shortcutValue = props.shortcuts[i].getValue()\n \n if (shortcutValue.startDate && shortcutValue.endDate &&\n normalizedValue.startDate && normalizedValue.endDate) {\n \n // 比较日期时忽略时间部分\n const currentStart = new Date(normalizedValue.startDate.getFullYear(), \n normalizedValue.startDate.getMonth(), \n normalizedValue.startDate.getDate())\n const currentEnd = new Date(normalizedValue.endDate.getFullYear(), \n normalizedValue.endDate.getMonth(), \n normalizedValue.endDate.getDate())\n \n const shortcutStart = new Date(shortcutValue.startDate.getFullYear(), \n shortcutValue.startDate.getMonth(), \n shortcutValue.startDate.getDate())\n const shortcutEnd = new Date(shortcutValue.endDate.getFullYear(), \n shortcutValue.endDate.getMonth(), \n shortcutValue.endDate.getDate())\n \n if (currentStart.getTime() === shortcutStart.getTime() && \n currentEnd.getTime() === shortcutEnd.getTime()) {\n return i\n }\n }\n }\n \n return -1\n}\n\n// 修改:生成日历天数数据,调整日历布局\nconst generateCalendarDays = (year: number, month: number): CalendarDay[][] => {\n const firstDay = new Date(year, month, 1)\n const lastDay = new Date(year, month + 1, 0)\n const firstDayWeek = firstDay.getDay()\n const daysInMonth = lastDay.getDate()\n \n const days: CalendarDay[] = []\n const today = new Date()\n \n // 修改:确保每个月的第一天不在第一个位置\n // 如果当月第一天是周日(0),则显示上个月的6天\n // 否则显示上个月的(firstDayWeek-1)天\n const prevDaysCount = firstDayWeek === 0 ? 6 : firstDayWeek - 1\n \n // 添加上个月的日期 - 设为禁用\n // 修复:应基于当前月份计算上个月的最后一天,避免出现溢出到当月的日期(如 09/31 -> 10/01)\n const prevMonth = new Date(year, month, 0)\n for (let i = prevDaysCount - 1; i >= 0; i--) {\n const date = new Date(year, month - 1, prevMonth.getDate() - i)\n days.push({\n date,\n day: date.getDate(),\n isCurrentMonth: false,\n isToday: isSameDay(date, today),\n isSelected: false,\n isInRange: false,\n isDisabled: true // 禁用非当前月的日期\n })\n }\n \n // 添加当前月的日期\n for (let i = 1; i <= daysInMonth; i++) {\n const date = new Date(year, month, i)\n days.push({\n date,\n day: i,\n isCurrentMonth: true,\n isToday: isSameDay(date, today),\n isSelected: false,\n isInRange: false,\n isDisabled: false\n })\n }\n \n // 添加下个月的日期 - 设为禁用\n const remainingDays = 42 - days.length\n for (let i = 1; i <= remainingDays; i++) {\n const date = new Date(year, month + 1, i)\n days.push({\n date,\n day: i,\n isCurrentMonth: false,\n isToday: isSameDay(date, today),\n isSelected: false,\n isInRange: false,\n isDisabled: true // 禁用非当前月的日期\n })\n }\n \n // 将天数数组分组为周\n const weeks: CalendarDay[][] = []\n for (let i = 0; i < days.length; i += 7) {\n weeks.push(days.slice(i, i + 7))\n }\n \n return weeks\n}\n\n// 方法\nconst updateValue = (value: TimeRange) => {\n const formattedValue = formatOutputValue(value)\n emit('update:modelValue', formattedValue)\n emit('change', formattedValue)\n}\n\n// 新增:计算下拉面板最佳位置的函数\nconst calculateDropdownPosition = () => {\n if (!trigger.value || !dropdown.value) return\n\n const triggerRect = trigger.value.getBoundingClientRect()\n const dropdownRect = dropdown.value.getBoundingClientRect()\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n\n const spaceBelow = viewportHeight - triggerRect.bottom\n const spaceAbove = triggerRect.top\n const dropdownHeight = dropdownRect.height || 400\n \n if (spaceBelow < dropdownHeight && spaceAbove > dropdownHeight) {\n dropdownPosition.value.top = false\n } else {\n dropdownPosition.value.top = true\n }\n\n const spaceRight = viewportWidth - triggerRect.left\n const dropdownWidth = dropdownRect.width || 640\n \n if (spaceRight < dropdownWidth) {\n dropdownPosition.value.left = false\n } else {\n dropdownPosition.value.left = true\n }\n}\n\nconst toggleDropdown = () => {\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n // 初始化临时日期 - 使用标准化的值\n const normalizedValue = normalizeValue(props.modelValue)\n tempStartDate.value = normalizedValue?.startDate || null\n tempEndDate.value = normalizedValue?.endDate || null\n \n // 更新选中的快捷选项索引\n selectedShortcutIndex.value = findMatchingShortcutIndex(props.modelValue)\n \n // 重置键盘导航索引\n activeShortcutIndex.value = -1\n \n // 初始化日历显示月份\n if (normalizedValue?.startDate) {\n startCalendar.value.year = normalizedValue.startDate.getFullYear()\n startCalendar.value.month = normalizedValue.startDate.getMonth()\n }\n \n if (normalizedValue?.endDate) {\n endCalendar.value.year = normalizedValue.endDate.getFullYear()\n endCalendar.value.month = normalizedValue.endDate.getMonth()\n } else {\n // 如果没有结束日期,默认显示开始日期的下一个月\n const nextMonth = new Date(startCalendar.value.year, startCalendar.value.month + 1)\n endCalendar.value.year = nextMonth.getFullYear()\n endCalendar.value.month = nextMonth.getMonth()\n }\n \n // 确保两个日历显示不同的月份\n ensureDifferentMonths()\n \n nextTick(() => {\n calculateDropdownPosition()\n })\n }\n}\n\nconst handleClickOutside = (event: Event) => {\n const target = event.target as HTMLElement\n const triggerEl = trigger.value\n const dropdownEl = dropdown.value\n \n if (triggerEl && dropdownEl && \n !triggerEl.contains(target) && \n !dropdownEl.contains(target)) {\n isOpen.value = false\n activeShortcutIndex.value = -1\n }\n}\n\nconst handleTriggerKeydown = (event: KeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n toggleDropdown()\n } else if (event.key === 'ArrowDown') {\n event.preventDefault()\n isOpen.value = true\n nextTick(() => {\n calculateDropdownPosition()\n focusFirstShortcut()\n })\n }\n}\n\nconst handleDropdownKeydown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n isOpen.value = false\n activeShortcutIndex.value = -1\n trigger.value?.focus()\n }\n}\n \nconst handleShortcutKeydown = (event: KeyboardEvent, index: number) => {\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n activeShortcutIndex.value = Math.min(index + 1, props.shortcuts.length - 1)\n focusShortcut(activeShortcutIndex.value)\n } else if (event.key === 'ArrowUp') {\n event.preventDefault()\n activeShortcutIndex.value = Math.max(index - 1, 0)\n focusShortcut(activeShortcutIndex.value)\n } else if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n selectShortcut(props.shortcuts[index])\n }\n}\n\nconst handleShortcutMouseEnter = (index: number) => {\n activeShortcutIndex.value = index\n}\n\nconst handleShortcutMouseLeave = () => {\n activeShortcutIndex.value = -1\n}\n\nconst focusFirstShortcut = () => {\n activeShortcutIndex.value = 0\n focusShortcut(0)\n}\n\nconst focusShortcut = (index: number) => {\n if (dropdown.value) {\n const shortcuts = dropdown.value.querySelectorAll('.nh-time-shortcut')\n const shortcutElement = shortcuts[index] as HTMLElement\n if (shortcutElement) {\n shortcutElement.focus()\n }\n }\n}\n\nconst selectShortcut = (shortcut: Shortcut) => {\n const value = shortcut.getValue()\n \n // 如果需要包含时间,确保时间部分正确设置\n if (props.includeTime && value.startDate && value.endDate) {\n value.startDate.setHours(0, 0, 0, 0)\n value.endDate.setHours(23, 59, 59, 999)\n }\n \n updateValue(value)\n \n // 更新选中的快捷选项索引\n selectedShortcutIndex.value = props.shortcuts.findIndex(s => s.label === shortcut.label)\n \n // 重置键盘导航索引\n activeShortcutIndex.value = -1\n \n isOpen.value = false\n}\n\n// 修改:选择日期时设置时间部分\nconst selectDate = (day: CalendarDay | null, type: 'start' | 'end') => {\n if (!day || day.isDisabled) return\n \n // 创建日期对象,根据是否需要保留时间部分设置时间\n let selectedDate: Date\n \n if (props.includeTime) {\n // 如果需要保留时分秒,则根据开始/结束位置设置不同的时间值\n selectedDate = new Date(day.date)\n if (type === 'start' || !tempStartDate.value) {\n // 开始日期设置为当天 00:00:00\n selectedDate.setHours(0, 0, 0, 0)\n } else {\n // 结束日期设置为当天 23:59:59\n selectedDate.setHours(23, 59, 59, 999)\n }\n } else {\n // 如果不需要保留时分秒,只保留年月日\n selectedDate = new Date(day.date.getFullYear(), day.date.getMonth(), day.date.getDate())\n }\n \n // 智能选择逻辑:\n // 1. 如果没有选择任何日期,当前选择的日期作为开始日期\n // 2. 如果已有开始日期但没有结束日期:\n // - 如果新选择的日期 >= 开始日期,设为结束日期\n // - 如果新选择的日期 < 开始日期,将新日期设为开始日期,原开始日期设为结束日期\n // 3. 如果已有开始和结束日期,重新开始选择:设为新的开始日期,清空结束日期\n \n if (!tempStartDate.value && !tempEndDate.value) {\n // 情况1:没有选择任何日期\n tempStartDate.value = selectedDate\n tempEndDate.value = null\n } else if (tempStartDate.value && !tempEndDate.value) {\n // 情况2:已有开始日期,没有结束日期\n if (selectedDate >= tempStartDate.value) {\n // 选择的日期大于等于开始日期,设为结束日期\n // 确保结束日期总是设置为 23:59:59\n if (props.includeTime) {\n selectedDate.setHours(23, 59, 59, 999)\n }\n tempEndDate.value = selectedDate\n } else {\n // 选择的日期小于开始日期,自动交换:新日期作为开始日期,原开始日期作为结束日期\n const endDate = tempStartDate.value\n // 确保结束日期总是设置为 23:59:59\n if (props.includeTime) {\n endDate.setHours(23, 59, 59, 999)\n }\n tempEndDate.value = endDate\n tempStartDate.value = selectedDate\n }\n } else {\n // 情况3:已有开始和结束日期,重新开始选择\n tempStartDate.value = selectedDate\n tempEndDate.value = null\n }\n \n // 清除快捷选项的选中状态,因为用户选择了自定义日期\n selectedShortcutIndex.value = -1\n \n // 更新待确认的值\n if (tempStartDate.value && tempEndDate.value) {\n // 确保结束日期总是设置为 23:59:59(如果启用了时间)\n const endDate = new Date(tempEndDate.value)\n if (props.includeTime) {\n endDate.setHours(23, 59, 59, 999)\n }\n pendingValue.value = { \n startDate: tempStartDate.value, \n endDate: endDate \n }\n } else {\n pendingValue.value = null\n }\n}\n\nconst getDateCellClass = (day: CalendarDay | null, type: 'start' | 'end') => {\n if (!day) return ['nh-date-table-td']\n \n const classes = ['nh-date-table-td']\n \n if (!day.isCurrentMonth) {\n classes.push('is-prev-month')\n }\n \n if (day.isToday) {\n classes.push('is-today')\n }\n \n if (day.isDisabled) {\n classes.push('is-disabled')\n }\n \n // 检查是否是选中的日期\n if (tempStartDate.value && isSameDay(day.date, tempStartDate.value)) {\n classes.push('is-selected', 'is-start')\n }\n \n if (tempEndDate.value && isSameDay(day.date, tempEndDate.value)) {\n classes.push('is-selected', 'is-end')\n }\n \n // 检查是否在选中范围内\n if (tempStartDate.value && tempEndDate.value && \n isDateInRange(day.date, tempStartDate.value, tempEndDate.value)) {\n classes.push('is-in-range')\n }\n \n return classes\n}\n\nconst confirmSelection = () => {\n if (pendingValue.value) {\n // 再次确保结束日期设置为 23:59:59(如果启用了时间)\n if (props.includeTime && pendingValue.value.endDate) {\n pendingValue.value.endDate.setHours(23, 59, 59, 999)\n }\n \n updateValue(pendingValue.value)\n // 检查新的值是否匹配某个快捷选项\n selectedShortcutIndex.value = findMatchingShortcutIndex(pendingValue.value)\n isOpen.value = false\n }\n}\n\nconst clearSelection = () => {\n updateValue({ startDate: null, endDate: null })\n resetSelection()\n activeShortcutIndex.value = -1\n isOpen.value = false\n}\n\n// 新增:监听窗口大小变化,重新计算位置\nconst handleResize = () => {\n if (isOpen.value) {\n nextTick(() => {\n calculateDropdownPosition()\n })\n }\n}\n\n// 计算属性\nconst startCalendarDays = computed(() => {\n return generateCalendarDays(startCalendar.value.year, startCalendar.value.month)\n})\n\nconst endCalendarDays = computed(() => {\n return generateCalendarDays(endCalendar.value.year, endCalendar.value.month)\n})\n\nconst displayText = computed(() => {\n const normalizedValue = normalizeValue(props.modelValue)\n \n if (!normalizedValue || !normalizedValue.startDate || !normalizedValue.endDate) {\n return ''\n }\n \n const formatDate = (date: Date) => {\n const year = String(date.getFullYear())\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n return `${year}/${month}/${day}`\n }\n \n const startStr = formatDate(normalizedValue.startDate)\n const endStr = formatDate(normalizedValue.endDate)\n \n // 如果是同一天且不包含时间,只显示一个日期\n if (!props.includeTime && startStr === endStr) {\n return startStr\n }\n \n return `${startStr} - ${endStr}`\n})\n\nconst dropdownClasses = computed(() => {\n return [\n 'nh-time-dropdown',\n {\n 'nh-time-dropdown-top': !dropdownPosition.value.top,\n 'nh-time-dropdown-right': !dropdownPosition.value.left\n }\n ]\n})\n\n// 新增计算属性:检查是否有值\nconst hasValue = computed(() => {\n const normalizedValue = normalizeValue(props.modelValue)\n return !!(normalizedValue?.startDate && normalizedValue?.endDate)\n})\n\n// 新增计算属性:检查是否可以确认 - 修改逻辑\nconst canConfirm = computed(() => {\n return !!(tempStartDate.value && tempEndDate.value)\n})\n\n// 修改:格式化显示日期(用于选择器标题)- 增强显示格式\n// const formatDisplayDate = (date: Date) => {\n// return new Intl.DateTimeFormat('zh-CN', {\n// month: '2-digit',\n// day: '2-digit'\n// }).format(date)\n// }\n\n// 新增:重置选择状态的方法\nconst resetSelection = () => {\n tempStartDate.value = null\n tempEndDate.value = null\n pendingValue.value = null\n selectedShortcutIndex.value = -1\n}\n\n// 监听器 - 修改以确保日历月份正确初始化\nwatch(() => props.modelValue, (newValue) => {\n const normalizedValue = normalizeValue(newValue)\n \n if (normalizedValue?.startDate) {\n const startDate = normalizedValue.startDate\n startCalendar.value.year = startDate.getFullYear()\n startCalendar.value.month = startDate.getMonth()\n }\n \n if (normalizedValue?.endDate) {\n const endDate = normalizedValue.endDate\n endCalendar.value.year = endDate.getFullYear()\n endCalendar.value.month = endDate.getMonth()\n } else if (normalizedValue?.startDate) {\n // 如果只有开始日期,结束日历显示下一个月\n const nextMonth = new Date(startCalendar.value.year, startCalendar.value.month + 1)\n endCalendar.value.year = nextMonth.getFullYear()\n endCalendar.value.month = nextMonth.getMonth()\n }\n \n // 确保两个日历显示不同的月份\n if (normalizedValue?.startDate || normalizedValue?.endDate) {\n ensureDifferentMonths()\n }\n \n // 当外部值改变时,更新选中的快捷选项\n if (!isOpen.value) {\n selectedShortcutIndex.value = findMatchingShortcutIndex(newValue)\n }\n}, { immediate: true, deep: true })\n\n// 新增:监听日历月份变化,确保不会显示相同月份\nwatch([startCalendar, endCalendar], () => {\n const startTime = new Date(startCalendar.value.year, startCalendar.value.month).getTime()\n const endTime = new Date(endCalendar.value.year, endCalendar.value.month).getTime()\n \n // 如果两个日历显示相同月份,自动调整\n if (startTime === endTime) {\n const nextMonth = new Date(startCalendar.value.year, startCalendar.value.month + 1)\n endCalendar.value.year = nextMonth.getFullYear()\n endCalendar.value.month = nextMonth.getMonth()\n }\n}, { deep: true })\n\n// 生命周期\nonMounted(() => {\n document.addEventListener('click', handleClickOutside)\n window.addEventListener('resize', handleResize)\n window.addEventListener('scroll', handleResize)\n \n // 初始化时设置选中的快捷选项和日历月份\n selectedShortcutIndex.value = findMatchingShortcutIndex(props.modelValue)\n \n // 修复:初始化日历月份时使用标准化的值\n const normalizedValue = normalizeValue(props.modelValue)\n \n if (normalizedValue?.startDate) {\n startCalendar.value.year = normalizedValue.startDate.getFullYear()\n startCalendar.value.month = normalizedValue.startDate.getMonth()\n }\n \n if (normalizedValue?.endDate) {\n endCalendar.value.year = normalizedValue.endDate.getFullYear()\n endCalendar.value.month = normalizedValue.endDate.getMonth()\n } else {\n // 默认显示当前月和下个月\n const nextMonth = new Date(startCalendar.value.year, startCalendar.value.month + 1)\n endCalendar.value.year = nextMonth.getFullYear()\n endCalendar.value.month = nextMonth.getMonth()\n }\n \n ensureDifferentMonths()\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', handleClickOutside)\n window.removeEventListener('resize', handleResize)\n window.removeEventListener('scroll', handleResize)\n})\n\n// 新增:处理输入框清空按钮点击\nconst handleClearClick = () => {\n if (!props.clearable) return\n \n updateValue({ startDate: null, endDate: null })\n resetSelection()\n activeShortcutIndex.value = -1\n}\n\n// 修改:日期选择相关方法\nconst changeMonth = (type: 'start' | 'end', direction: number) => {\n if (type === 'start') {\n const newDate = new Date(startCalendar.value.year, startCalendar.value.month + direction, 1)\n startCalendar.value.year = newDate.getFullYear()\n startCalendar.value.month = newDate.getMonth()\n \n // 确保结束月份不会与开始月份相同\n ensureDifferentMonths()\n } else {\n const newDate = new Date(endCalendar.value.year, endCalendar.value.month + direction, 1)\n endCalendar.value.year = newDate.getFullYear()\n endCalendar.value.month = newDate.getMonth()\n \n // 确保开始月份不会与结束月份相同\n ensureDifferentMonthsReverse()\n }\n}\n</script>\n\n<style scoped>\n/* 基础样式,与 YInput/YSelect 风格统一 */\n.nh-time-search {\n position: relative;\n display: inline-block;\n width: 250px;\n font-size: 14px;\n color: #0b1a29;\n}\n\n.nh-time-trigger {\n position: relative;\n display: inline-block;\n width: 100%;\n cursor: pointer;\n}\n\n.nh-time-trigger.is-focus .nh-time-input {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59,130,246,0.15);\n}\n\n.nh-time-input {\n background-color: #ffffff;\n border: 1px solid #e2e8f0;\n border-radius: 10px;\n box-sizing: border-box;\n color: #0b1a29;\n display: inline-block;\n font-size: inherit;\n outline: none;\n padding: 0 40px 0 12px;\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n width: 100%;\n cursor: pointer;\n font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif;\n}\n\n.nh-time-input:hover { border-color: #60a5fa; }\n\n.nh-time-input:focus {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59,130,246,0.15);\n outline: none;\n}\n\n.nh-time-input::placeholder {\n color: #9ca3af;\n}\n\n.nh-time-suffix {\n position: absolute;\n height: 100%;\n right: 8px;\n top: 0;\n display: flex;\n align-items: center;\n color: #6b7280;\n font-size: 14px;\n pointer-events: none;\n gap: 4px;\n}\n\n.nh-time-icon { display: flex; align-items: center; }\n\n.nh-time-arrow {\n display: flex;\n align-items: center;\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n}\n\n.nh-time-clear {\n display: flex;\n align-items: center;\n cursor: pointer;\n color: #9ca3af;\n transition: all 0.2s ease;\n pointer-events: auto;\n}\n\n.nh-time-clear:hover {\n color: #6b7280;\n}\n\n.nh-time-clear:active {\n transform: scale(0.9);\n}\n\n/* 下拉面板样式 */\n.nh-time-dropdown {\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n z-index: 50;\n background: #ffffff;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n box-shadow: 0 8px 20px rgba(2,6,23,0.15);\n display: flex;\n min-width: 640px;\n max-width: calc(100vw - 20px);\n box-sizing: border-box;\n overflow: hidden;\n}\n\n.nh-time-dropdown-top {\n top: auto;\n bottom: calc(100% + 4px);\n}\n\n.nh-time-dropdown-right {\n left: auto;\n right: 0;\n}\n\n/* 快捷选项样式 */\n.nh-time-shortcuts {\n width: 140px;\n border-right: 1px solid #e5e7eb;\n background-color: #f9fafb;\n}\n\n.nh-time-shortcuts-title {\n padding: 12px 16px 8px;\n color: #374151;\n font-size: 12px;\n font-weight: 500;\n border-bottom: 1px solid #e5e7eb;\n background-color: #f9fafb;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.nh-time-shortcuts-list {\n margin: 0;\n padding: 4px 0;\n list-style: none;\n}\n\n.nh-time-shortcut {\n display: block;\n width: 100%;\n padding: 8px 16px;\n margin: 0;\n font-size: 13px;\n color: #374151;\n cursor: pointer;\n border: none;\n background: none;\n text-align: left;\n outline: none;\n transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out;\n font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif;\n}\n\n.nh-time-shortcut:hover,\n.nh-time-shortcut.is-active {\n background-color: #f3f4f6;\n color: #1f2937;\n}\n\n.nh-time-shortcut:focus {\n background-color: #f3f4f6;\n outline: none;\n}\n\n.nh-time-shortcut.is-selected {\n background-color: #313B4A !important;\n color: #ffffff !important;\n}\n\n.nh-time-shortcut.is-selected:hover {\n background-color: #354051 !important;\n color: #ffffff !important;\n}\n\n.nh-time-shortcut:active {\n background-color: #e5e7eb;\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n transform: translateY(1px);\n}\n\n/* 自定义时间选择样式 */\n.nh-time-custom {\n flex: 1;\n padding: 8px 16px;\n background-color: #ffffff;\n}\n\n.nh-time-custom-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.nh-time-custom-header span {\n font-size: 14px;\n font-weight: 500;\n color: #374151;\n}\n\n/* 选择状态提示样式 */\n.nh-time-selection-status {\n display: flex;\n align-items: center;\n}\n\n.status-text {\n font-size: 12px;\n color: #6b7280;\n padding: 4px 8px;\n border-radius: 4px;\n background-color: #f3f4f6;\n font-weight: 500;\n}\n\n.status-text.status-complete {\n color: #059669;\n background-color: #d1fae5;\n}\n\n.nh-time-pickers {\n display: flex;\n gap: 24px;\n margin-bottom: 8px;\n}\n\n.nh-time-picker {\n flex: 1;\n}\n\n.nh-time-picker-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid #f3f4f6;\n min-height: 40px;\n}\n\n.nh-time-picker-title {\n font-size: 13px;\n color: #6b7280;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.nh-time-picker-dates {\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n gap: 2px;\n}\n\n.nh-time-picker-date {\n font-size: 11px;\n padding: 2px 6px;\n border-radius: 3px;\n font-weight: 500;\n}\n\n.nh-time-picker-date.start-date {\n color: #313B4A;\n background-color: #e4f0fd;\n}\n\n.nh-time-picker-date.end-date {\n color: #059669;\n background-color: #d1fae5;\n}\n\n.nh-time-picker-hint {\n display: flex;\n align-items: center;\n}\n\n.hint-text {\n font-size: 11px;\n color: #9ca3af;\n text-align: right;\n line-height: 1.3;\n max-width: 120px;\n}\n\n/* 日期选择器样式 */\n.nh-date-picker {\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: #ffffff;\n overflow: hidden;\n}\n\n.nh-date-picker:before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: 8px;\n padding: 1px;\n background: linear-gradient(to bottom, rgba(255, 255, 255, 0.8), rgba(229, 231, 235, 0.5));\n mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask-composite: xor;\n mask-composite: exclude;\n pointer-events: none;\n}\n\n.nh-date-picker-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background-color: #f9fafb;\n border-bottom: 1px solid #e5e7eb;\n}\n\n.nh-date-picker-header-label {\n font-size: 14px;\n font-weight: 600;\n color: #374151;\n}\n\n.nh-date-picker-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: none;\n background: none;\n cursor: pointer;\n border-radius: 6px;\n color: #6b7280;\n transition: all 0.15s ease-in-out;\n}\n\n.nh-date-picker-btn:hover {\n background-color: #f3f4f6;\n color: #374151;\n}\n\n.nh-date-picker-btn:focus {\n outline: none;\n background-color: #f3f4f6;\n}\n\n.nh-date-picker-btn:active {\n transform: translateY(0);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.05);\n background: linear-gradient(to bottom, #f3f4f6, #e5e7eb);\n}\n\n.nh-date-picker-content {\n padding: 12px;\n background: linear-gradient(135deg, #ffffff, #fafafa);\n}\n\n/* 日期表格样式 */\n.nh-date-table {\n width: 100%;\n border-collapse: collapse;\n table-layout: fixed;\n}\n\n.nh-date-table-th {\n padding: 8px 4px;\n text-align: center;\n font-size: 11px;\n color: #6b7280;\n font-weight: 500;\n border-bottom: 1px solid #f3f4f6;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.nh-date-table-td {\n width: 32px;\n height: 32px;\n padding: 3px;\n box-sizing: border-box;\n}\n\n.nh-date-table-cell {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 26px;\n width: 26px;\n margin: 0 auto;\n border-radius: 6px;\n font-size: 13px;\n color: #374151;\n transition: all 0.15s ease-in-out;\n position: relative;\n font-weight: 400;\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.02);\n}\n\n.nh-date-table-td:hover .nh-date-table-cell {\n background-color: #f3f4f6;\n color: #1f2937;\n}\n\n/* 日期状态样式 - 修改禁用状态但保留选中样式 */\n.nh-date-table-td.is-prev-month .nh-date-table-cell {\n color: #d1d5db;\n background-color: #f9fafb;\n cursor: not-allowed;\n}\n\n.nh-date-table-td.is-prev-month:hover .nh-date-table-cell {\n background-color: #f9fafb;\n color: #d1d5db;\n}\n\n/* 禁用状态的通用样式 */\n.nh-date-table-td.is-disabled .nh-date-table-cell {\n background-color: #f9fafb;\n color: #d1d5db;\n cursor: not-allowed;\n}\n\n.nh-date-table-td.is-disabled:hover .nh-date-table-cell {\n background-color: #f9fafb;\n color: #d1d5db;\n}\n\n/* 保留正常的选中状态样式 */\n.nh-date-table-td.is-selected .nh-date-table-cell {\n background-color: #313B4A;\n color: #ffffff;\n font-weight: 500;\n}\n\n.nh-date-table-td.is-in-range .nh-date-table-cell {\n background-color: #e4f0fd;\n color: #313B4A;\n}\n\n.nh-date-table-td.is-start .nh-date-table-cell,\n.nh-date-table-td.is-end .nh-date-table-cell {\n background-color: #313B4A;\n color: #ffffff;\n font-weight: 500;\n}\n\n/* 今天标记 */\n.nh-date-table-td.is-today .nh-date-table-cell {\n color: #c23616;\n font-weight: 600;\n}\n\n/* 修改:禁用且在选中范围内的日期显示为灰色背景 */\n.nh-date-table-td.is-disabled.is-in-range .nh-date-table-cell {\n background-color: #f3f4f6 !important;\n color: #9ca3af !important;\n cursor: not-allowed;\n}\n\n/* 修改:禁用且是开始/结束日期的样式 */\n.nh-date-table-td.is-disabled.is-start .nh-date-table-cell,\n.nh-date-table-td.is-disabled.is-end .nh-date-table-cell {\n background-color: #9ca3af !important;\n color: #ffffff !important;\n cursor: not-allowed;\n}\n\n.nh-date-table-td.is-disabled.is-selected .nh-date-table-cell {\n background-color: #9ca3af !important;\n color: #ffffff !important;\n cursor: not-allowed;\n}\n\n/* 修改:只有禁用且未选中的日期才显示完全禁用样式 */\n.nh-date-table-td.is-disabled:not(.is-selected):not(.is-start):not(.is-end):not(.is-in-range) .nh-date-table-cell {\n background-color: #f9fafb;\n color: #d1d5db;\n cursor: not-allowed;\n}\n\n.nh-date-table-td.is-disabled:not(.is-selected):not(.is-start):not(.is-end):not(.is-in-range):hover .nh-date-table-cell {\n background-color: #f9fafb;\n color: #d1d5db;\n}\n\n/* 今天标记 - 非当前月的禁用状态 */\n.nh-date-table-td.is-disabled.is-today:not(.is-selected):not(.is-start):not(.is-end):not(.is-in-range) .nh-date-table-cell {\n color: #d1d5db;\n font-weight: 600;\n background-color: #f9fafb;\n}\n\n/* 修改:禁用范围内日期的连接线样式 */\n.nh-date-table-td.is-disabled.is-in-range::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 0;\n right: 0;\n height: 26px;\n background-color: rgba(156, 163, 175, 0.2);\n transform: translateY(-50%);\n z-index: -1;\n border: 1px solid rgba(156, 163, 175, 0.3);\n}\n\n/* 保留选中范围的连续效果 - 正常状态 */\n.nh-date-table-td.is-in-range:not(.is-disabled)::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 0;\n right: 0;\n height: 26px;\n background-color: rgba(49, 59, 74, 0.1);\n transform: translateY(-50%);\n z-index: -1;\n border: 1px solid rgba(49, 59, 74, 0.2);\n}\n\n.nh-date-table-td.is-start.is-in-range::before {\n left: 50%;\n}\n\n.nh-date-table-td.is-end.is-in-range::before {\n right: 50%;\n}\n\n.nh-date-table-td.is-start.is-end.is-in-range::before {\n display: none;\n}\n\n/* 修改:禁用日期的视觉标记为灰色 */\n.nh-date-table-td.is-disabled.is-start .nh-date-table-cell::before {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 6px;\n height: 6px;\n background-color: #d1d5db;\n border-radius: 50%;\n z-index: 1;\n}\n\n.nh-date-table-td.is-disabled.is-end .nh-date-table-cell::after {\n content: '';\n position: absolute;\n bottom: 2px;\n right: 2px;\n width: 6px;\n height: 6px;\n background-color: #d1d5db;\n border-radius: 50%;\n z-index: 1;\n}\n\n/* 保留正常日期范围视觉标记 */\n.nh-date-table-td.is-start:not(.is-disabled) .nh-date-table-cell::before {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: 6px;\n height: 6px;\n background-color: #ffffff;\n border-radius: 50%;\n z-index: 1;\n}\n\n.nh-date-table-td.is-end:not(.is-disabled) .nh-date-table-cell::after {\n content: '';\n position: absolute;\n bottom: 2px;\n right: 2px;\n width: 6px;\n height: 6px;\n background-color: #ffffff;\n border-radius: 50%;\n z-index: 1;\n}\n\n/* 只有完全禁用且未选中的日期才隐藏范围连接线和标记 */\n.nh-date-table-td.is-disabled:not(.is-selected):not(.is-start):not(.is-end):not(.is-in-range) .nh-date-table-cell::before,\n.nh-date-table-td.is-disabled:not(.is-selected):not(.is-start):not(.is-end):not(.is-in-range) .nh-date-table-cell::after {\n display: none;\n}\n\n.nh-time-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n padding-top: 2px;\n}\n\n/* 尺寸适配,与 YInput/YButton 保持一致 */\n.nh-time--mini .nh-time-input { height: 24px; border-radius: 6px; font-size: 11px; }\n.nh-time--small .nh-time-input { height: 32px; border-radius: 8px; font-size: 12px; }\n.nh-time--medium .nh-time-input { height: 44px; border-radius: 10px; font-size: 14px; }\n.nh-time--large .nh-time-input { height: 52px; border-radius: 12px; font-size: 16px; }\n\n/* 过渡动画 */\n.el-zoom-in-top-enter-active,\n.el-zoom-in-top-leave-active {\n opacity: 1;\n transform: scale(1);\n transition: opacity 0.2s ease-out, transform 0.2s ease-out;\n transform-origin: top;\n}\n\n.el-zoom-in-top-enter-from,\n.el-zoom-in-top-leave-to {\n opacity: 0;\n transform: scale(0.95);\n}\n\n/* 输入框状态优化 */\n.nh-time-trigger.has-value .nh-time-input {\n color: #1f2937;\n font-weight: 500;\n background-image: linear-gradient(to bottom, #ffffff, #f9fafb);\n}\n\n.nh-time-trigger:not(.has-value) .nh-time-input {\n color: #9ca3af;\n}\n\n/* 箭头旋转动画 */\n.nh-time-arrow {\n transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n}\n\n.nh-time-arrow.is-reverse {\n transform: rotate(180deg);\n}\n\n/* 日历图标优化 */\n.nh-time-icon {\n display: flex;\n align-items: center;\n color: #6b7280;\n filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.1));\n}\n\n.nh-time-trigger.is-focus .nh-time-icon {\n color: #313B4A;\n filter: drop-shadow(0 1px 2px rgba(49, 59, 74, 0.2));\n}\n\n/* 输入框聚焦状态优化 */\n.nh-time-trigger.is-focus {\n box-shadow: 0 0 0 2px rgba(49, 59, 74, 0.2), 0 2px 5px rgba(0, 0, 0, 0.1);\n border-radius: 6px;\n}\n\n/* 清空按钮优化 */\n.nh-time-clear {\n opacity: 0;\n transition: all 0.2s ease;\n transform-origin: center;\n}\n\n.nh-time-trigger:hover .nh-time-clear,\n.nh-time-trigger.is-focus .nh-time-clear {\n opacity: 1;\n}\n\n/* 响应式设计 */\n@media (max-width: 768px) {\n .nh-time-search {\n width: 200px;\n }\n \n .nh-time-dropdown {\n min-width: 320px;\n max-width: calc(100vw - 20px);\n flex-direction: column;\n }\n \n .nh-time-shortcuts {\n width: 100%;\n border-right: none;\n border-bottom: 1px solid #e5e7eb;\n box-shadow: 0 2px 4px -2px rgba(0, 0, 0, 0.05);\n }\n \n .nh-time-shortcuts-list {\n display: flex;\n flex-wrap: wrap;\n padding: 8px;\n gap: 4px;\n }\n \n .nh-time-shortcut {\n flex: 1;\n min-width: 80px;\n text-align: center;\n padding: 6px 8px;\n border-radius: 4px;\n }\n \n .nh-time-pickers {\n flex-direction: column;\n gap: 12px;\n }\n \n .nh-date-picker-header-label {\n font-size: 13px;\n }\n \n .nh-date-table-cell {\n height: 24px;\n width: 24px;\n font-size: 12px;\n }\n \n .nh-date-table-td {\n height: 24px;\n width: 24px;\n }\n \n .nh-time-picker-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n min-height: auto;\n }\n \n .nh-time-picker-dates {\n align-items: flex-start;\n width: 100%;\n }\n \n .hint-text {\n max-width: 100%;\n text-align: left;\n }\n \n .nh-time-actions {\n flex-direction: row;\n gap: 8px;\n }\n}\n\n/* 增强立体感的额外效果 */\n/* 悬停时的提升效果 */\n.nh-date-table-td:not(.is-disabled):hover {\n z-index: 1;\n}\n\n.nh-date-table-td:not(.is-disabled):active .nh-date-table-cell {\n transform: translateY(0);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n transition: all 0.1s ease;\n}\n\n/* 选中日期的脉冲动画效果 */\n@keyframes pulse {\n 0% {\n box-shadow: 0 0 0 0 rgba(49, 59, 74, 0.4);\n }\n 70% {\n box-shadow: 0 0 0 6px rgba(49, 59, 74, 0);\n }\n 100% {\n box-shadow: 0 0 0 0 rgba(49, 59, 74, 0);\n }\n}\n\n.nh-date-table-td.is-selected:not(.is-disabled) .nh-date-table-cell {\n animation: pulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) 1;\n}\n\n/* 日期选择器边框渐变效果 */\n.nh-date-picker {\n position: relative;\n}\n\n.nh-date-picker:before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: 8px;\n padding: 1px;\n background: linear-gradient(to bottom, rgba(255, 255, 255, 0.8), rgba(229, 231, 235, 0.5));\n mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask-composite: xor;\n mask-composite: exclude;\n pointer-events: none;\n}\n\n/* 月份切换按钮的点击效果 */\n.nh-date-picker-btn:active {\n transform: translateY(0);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.05);\n background: linear-gradient(to bottom, #f3f4f6, #e5e7eb);\n}\n\n/* 快捷选项的点击效果 */\n.nh-time-shortcut:active {\n background-color: #e5e7eb;\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n transform: translateY(1px);\n}\n\n/* 下拉面板的内阴影效果 */\n.nh-time-dropdown:before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: 10px;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5);\n pointer-events: none;\n}\n\n/* 日期选择器内容区域的微妙渐变 */\n.nh-date-picker-content {\n background: linear-gradient(135deg, #ffffff, #fafafa);\n}\n\n/* 日期单元格的微妙阴影 */\n.nh-date-table-cell {\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.02);\n}\n\n/* 当前日期的特殊标记 */\n.nh-date-table-td.is-today .nh-date-table-cell:after {\n content: '';\n position: absolute;\n bottom: 3px;\n left: 50%;\n transform: translateX(-50%);\n width: 4px;\n height: 4px;\n background-color: #313B4A;\n border-radius: 50%;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n/* 选择状态完成的微妙动画 */\n@keyframes completeStatus {\n 0% {\n transform: scale(0.9);\n opacity: 0.7;\n }\n 50% {\n transform: scale(1.05);\n opacity: 1;\n }\n 100% {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n.status-text.status-complete {\n animation: completeStatus 0.3s ease-out;\n}\n\n/* 日历标题的微妙阴影 */\n.nh-date-picker-header-label {\n position: relative;\n z-index: 1;\n}\n\n.nh-date-picker-header-label:after {\n content: '';\n position: absolute;\n bottom: -2px;\n left: 0;\n width: 100%;\n height: 4px;\n background: linear-gradient(to right, rgba(49, 59, 74, 0), rgba(49, 59, 74, 0.1), rgba(49, 59, 74, 0));\n border-radius: 2px;\n z-index: -1;\n}\n\n/* 日期范围选择的过渡效果 */\n.nh-date-table-td.is-in-range .nh-date-table-cell {\n transition: background 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;\n}\n\n/* 日期选择器的整体边框效果 */\n.nh-time-picker {\n position: relative;\n overflow: visible;\n}\n\n.nh-time-picker:after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: 10px;\n box-shadow: 0 0 0 1px rgba(229, 231, 235, 0.8);\n pointer-events: none;\n}\n</style>","<template>\n <button\n ref=\"rootEl\"\n class=\"yswitch\"\n :class=\"[\n `yswitch--${size}`,\n { 'yswitch--checked': isChecked, 'yswitch--disabled': disabled, 'yswitch--loading': loading }\n ]\"\n :style=\"switchStyle\"\n role=\"switch\"\n :aria-checked=\"isChecked\"\n :aria-disabled=\"disabled\"\n :disabled=\"disabled || loading\"\n @click=\"onToggle\"\n @keydown.enter.prevent=\"onToggle\"\n @keydown.space.prevent=\"onToggle\"\n >\n <span class=\"yswitch__track\"></span>\n <span class=\"yswitch__thumb\">\n <span v-if=\"loading\" class=\"yswitch__spinner\" aria-hidden=\"true\"></span>\n </span>\n <span v-if=\"showText\" class=\"yswitch__label\" :class=\"{ 'yswitch__label--left': !isChecked, 'yswitch__label--right': isChecked }\">\n {{ isChecked ? activeText : inactiveText }}\n </span>\n </button>\n \n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, onMounted } from 'vue'\n\nexport interface SwitchProps<T = boolean> {\n modelValue?: T\n trueValue?: T\n falseValue?: T\n disabled?: boolean\n loading?: boolean\n size?: 'small' | 'medium' | 'large'\n activeColor?: string\n inactiveColor?: string\n activeText?: string\n inactiveText?: string\n showText?: boolean\n}\n\nconst props = withDefaults(defineProps<SwitchProps>(), {\n modelValue: false,\n trueValue: true,\n falseValue: false,\n disabled: false,\n loading: false,\n size: 'medium',\n activeColor: '#10b981',\n inactiveColor: '#e5e7eb',\n activeText: '开',\n inactiveText: '关',\n showText: false,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: any]\n 'change': [value: any]\n 'focus': [event: FocusEvent]\n 'blur': [event: FocusEvent]\n}>()\n\nconst rootEl = ref<HTMLButtonElement>()\n\nconst isChecked = computed(() => props.modelValue === props.trueValue)\n\nconst switchStyle = computed(() => {\n const style: Record<string, string> = {}\n // 轨道背景色\n style.background = isChecked.value ? props.activeColor : props.inactiveColor\n return style\n})\n\nfunction onToggle() {\n if (props.disabled || props.loading) return\n const next = isChecked.value ? props.falseValue : props.trueValue\n emit('update:modelValue', next)\n emit('change', next)\n}\n\nonMounted(() => {\n const el = rootEl.value\n if (!el) return\n el.addEventListener('focus', (e) => emit('focus', e as FocusEvent))\n el.addEventListener('blur', (e) => emit('blur', e as FocusEvent))\n})\n\n</script>\n\n<style scoped lang=\"less\">\n.yswitch {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: flex-start;\n border: none;\n cursor: pointer;\n outline: none;\n user-select: none;\n background: #e5e7eb;\n border-radius: 999px;\n transition: background-color 0.2s ease, box-shadow 0.2s ease;\n padding: 0;\n}\n\n.yswitch:focus-visible {\n box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.2);\n}\n\n.yswitch--disabled {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n.yswitch__track {\n position: absolute;\n inset: 0;\n border-radius: 999px;\n}\n\n.yswitch__thumb {\n position: relative;\n background: #ffffff;\n border-radius: 50%;\n transition: transform 0.2s ease;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.yswitch--small {\n width: 36px;\n height: 20px;\n}\n.yswitch--small .yswitch__thumb {\n width: 16px;\n height: 16px;\n transform: translateX(2px);\n}\n.yswitch--small.yswitch--checked .yswitch__thumb {\n transform: translateX(18px);\n}\n\n.yswitch--medium {\n width: 44px;\n height: 24px;\n}\n.yswitch--medium .yswitch__thumb {\n width: 20px;\n height: 20px;\n transform: translateX(2px);\n}\n.yswitch--medium.yswitch--checked .yswitch__thumb {\n transform: translateX(22px);\n}\n\n.yswitch--large {\n width: 45px;\n height: 32px;\n}\n.yswitch--large .yswitch__thumb {\n width: 28px;\n height: 28px;\n transform: translateX(2px);\n}\n.yswitch--large.yswitch--checked .yswitch__thumb {\n transform: translateX(26px);\n}\n\n.yswitch__label {\n margin-left: 8px;\n font-size: 12px;\n color: #4b5563;\n white-space: nowrap;\n}\n\n.yswitch__spinner {\n width: 12px;\n height: 12px;\n border: 2px solid rgba(0,0,0,0.15);\n border-top-color: rgba(0,0,0,0.45);\n border-radius: 50%;\n animation: yswitch-spin 0.8s linear infinite;\n}\n\n@keyframes yswitch-spin {\n to { transform: rotate(360deg); }\n}\n\n/* 暗色主题适配 */\n@media (prefers-color-scheme: dark) {\n .yswitch__label { color: #cbd5e1; }\n}\n\n</style>\n\n\n","<template>\n <div \n ref=\"containerRef\"\n class=\"yimage-container\"\n :class=\"containerClass\"\n >\n <!-- 懒加载占位符 -->\n <div \n v-if=\"!isLoaded && !hasError && !isInView\"\n class=\"yimage-placeholder\"\n :style=\"radiusStyle\"\n >\n <div class=\"yimage-placeholder-content\">\n <svg class=\"yimage-placeholder-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"></path>\n </svg>\n </div>\n </div>\n\n <!-- 加载动画 -->\n <div \n v-if=\"isLoading && !hasError\"\n class=\"yimage-loading\"\n :style=\"radiusStyle\"\n >\n <div class=\"yimage-loading-content\">\n <div class=\"yimage-spinner\"></div>\n </div>\n </div>\n\n <!-- 错误占位图 -->\n <div \n v-if=\"hasError\"\n class=\"yimage-error\"\n :style=\"radiusStyle\"\n @click=\"handleErrorClick\"\n >\n <img \n src=\"https://img.nihaojewelry.com/media/2025/6/27/1938511770352222208.png\" \n alt=\"Error Image\" \n class=\"yimage-error-image\"\n :style=\"radiusStyle\"\n />\n </div>\n\n <!-- 实际图片 -->\n <img\n v-show=\"isLoaded && !hasError\"\n ref=\"imageRef\"\n :src=\"imgSrc\"\n :alt=\"alt\"\n :class=\"imageClass\"\n @load=\"handleLoad\"\n @error=\"handleError\"\n @click.stop=\"handlePreview\"\n :style=\"imageStyle\"\n />\n \n <!-- 点击区域覆盖层,确保即使图片未完全加载也能点击 -->\n <div\n v-if=\"props.preview && (!isLoaded || isLoading || hasError || !isInView)\"\n class=\"yimage-preview-trigger\"\n @click.stop=\"handlePreview\"\n ></div>\n\n <!-- 大图预览遮罩 -->\n <Teleport to=\"body\" v-if=\"isMounted\">\n <transition name=\"fade\">\n <div \n v-if=\"showPreview\"\n class=\"yimage-preview-mask\"\n @click.self=\"closePreview\"\n @wheel.prevent=\"handleWheel\"\n >\n <div class=\"yimage-preview-content\" \n :class=\"{'is-active': showPreview}\">\n <!-- 预览图片 -->\n <img\n ref=\"previewImageRef\"\n :src=\"resolvedPreviewSrc\"\n :alt=\"alt\"\n class=\"yimage-preview-image\"\n :style=\"{ transform: `scale(${zoomLevel})` }\"\n @click.stop\n />\n </div>\n \n <!-- 图片信息 - 右下角,完整展示链接 -->\n <!-- <div class=\"fixed bottom-4 right-4 bg-black/50 text-white p-3 rounded max-w-md\">\n <p class=\"text-sm\">{{ alt || '图片预览' }}</p>\n <p class=\"text-xs text-gray-300 mt-1 break-all\">{{ previewSrc || props.src }}</p>\n <p class=\"text-xs text-gray-300 mt-1\">缩放: {{ Math.round(zoomLevel * 100) }}%</p>\n </div> -->\n </div>\n </transition>\n </Teleport>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'\nimport { Teleport } from 'vue'\nimport type { CSSProperties } from 'vue'\n\ninterface Props {\n src: string\n alt?: string\n width?: string | number\n height?: string | number\n lazy?: boolean\n preview?: boolean\n fit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\n radius?: string | number\n className?: string\n previewSrcList?: string | string[]\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n alt: '',\n lazy: true,\n preview: true,\n fit: 'cover',\n radius: '0',\n className: ''\n})\n\nconst emit = defineEmits<{\n load: [event: Event]\n error: [event: Event]\n preview: [src: string]\n}>()\n\n// 响应式状态\nconst containerRef = ref<HTMLElement>()\nconst imageRef = ref<HTMLImageElement>()\nconst previewImageRef = ref<HTMLImageElement>()\nconst isLoaded = ref(false)\nconst isLoading = ref(false)\nconst hasError = ref(false)\nconst isInView = ref(false)\nconst showPreview = ref(false)\nconst imgSrc = ref('data:image/svg+xml;charset=utf-8;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgdmlld0JveD0iMCAwIDIwMCAyMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPCEtLSDog4zmma8gLS0+CiAgPHJlY3Qgd2lkdGg9IjIwMCIgaGVpZ2h0PSIyMDAiIGZpbGw9IiNGM0Y0RjYiLz4KICAKICA8IS0tIOWbvueJh+WbvuaghyAtLT4KICA8cmVjdCB4PSI1MCIgeT0iNDAiIHdpZHRoPSIxMDAiIGhlaWdodD0iODAiIHJ4PSI0IiBmaWxsPSIjRDFENURCIiBzdHJva2U9IiM5Q0EzQUYiIHN0cm9rZS13aWR0aD0iMiIvPgogIAogIDwhLS0g5Zu+54mH5YaF6YOo6KOF6aWwIC0tPgogIDxjaXJjbGUgY3g9IjgwIiBjeT0iNzAiIHI9IjgiIGZpbGw9IiM5Q0EzQUYiLz4KICA8cGF0aCBkPSJNNjAgMTAwIEw5MCA4NSBMMTIwIDk1IEwxNDAgODAiIHN0cm9rZT0iIzlDQTNBRiIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4KICAKICA8IS0tIOaWh+WtlyAtLT4KICA8dGV4dCB4PSIxMDAiIHk9IjE2MCIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZmlsbD0iIzZCNzI4MCIgZm9udC1mYW1pbHk9IkFyaWFsLCBzYW5zLXNlcmlmIiBmb250LXNpemU9IjEyIiBmb250LXdlaWdodD0iNTAwIj4KICAgIEltYWdlIG5vdCBhdmFpbGFibGUKICA8L3RleHQ+Cjwvc3ZnPiA=')\nconst previewSrc = ref('')\nconst zoomLevel = ref(1)\nconst isMounted = ref(false)\n\n// 新增:保存原始滚动条状态\nconst originalBodyStyle = ref<{\n overflow: string\n paddingRight: string\n}>({\n overflow: '',\n paddingRight: ''\n})\n\n// 计算属性\nconst RADIUS_TOKEN_MAP: Record<string, string> = {\n none: '0px',\n sm: '0.125rem',\n md: '0.375rem',\n lg: '0.5rem',\n xl: '0.75rem',\n '2xl': '1rem',\n full: '9999px'\n}\n\nconst containerClass = computed(() => props.className || '')\n\nconst radiusValue = computed(() => {\n if (typeof props.radius === 'number') {\n return `${props.radius}px`\n }\n if (typeof props.radius === 'string') {\n if (/(px|%|rem|em)$/.test(props.radius)) {\n return props.radius\n }\n if (RADIUS_TOKEN_MAP[props.radius]) {\n return RADIUS_TOKEN_MAP[props.radius]\n }\n }\n return ''\n})\n\nconst radiusStyle = computed<CSSProperties>(() => {\n if (!radiusValue.value) {\n return {}\n }\n return {\n borderRadius: radiusValue.value\n }\n})\n\nconst imageClass = computed(() => {\n return [\n 'yimage-image',\n props.preview ? 'is-previewable' : ''\n ].filter(Boolean).join(' ')\n})\n\nconst imageStyle = computed(() => {\n const style: CSSProperties = {\n objectFit: props.fit || 'cover',\n backgroundColor: '#fff'\n }\n \n if (props.width) {\n style.width = typeof props.width === 'number' ? `${props.width}px` : props.width\n }\n \n if (props.height) {\n style.height = typeof props.height === 'number' ? `${props.height}px` : props.height\n }\n \n if (radiusValue.value) {\n style.borderRadius = radiusValue.value\n }\n \n return style\n})\n\nconst resolvedPreviewSrc = computed(() => {\n if (previewSrc.value) {\n return previewSrc.value\n }\n if (Array.isArray(props.previewSrcList)) {\n return props.previewSrcList.find(Boolean) || props.src\n }\n return props.previewSrcList || props.src\n})\n\n// 工具函数\n// 新增:获取滚动条宽度\nconst getScrollbarWidth = () => {\n const scrollDiv = document.createElement('div')\n scrollDiv.style.cssText = 'width: 100px; height: 100px; overflow: scroll; position: absolute; top: -9999px;'\n document.body.appendChild(scrollDiv)\n const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth\n document.body.removeChild(scrollDiv)\n return scrollbarWidth\n}\n\n// 新增:锁定页面滚动\nconst lockBodyScroll = () => {\n // 保存原始样式\n originalBodyStyle.value = {\n overflow: document.body.style.overflow || '',\n paddingRight: document.body.style.paddingRight || ''\n }\n \n // 检查是否有滚动条\n const hasScrollbar = document.body.scrollHeight > window.innerHeight\n \n if (hasScrollbar) {\n const scrollbarWidth = getScrollbarWidth()\n // 设置右边距来防止页面跳动\n document.body.style.paddingRight = `${scrollbarWidth}px`\n }\n \n // 隐藏滚动条\n document.body.style.overflow = 'hidden'\n}\n\n// 新增:解锁页面滚动\nconst unlockBodyScroll = () => {\n // 恢复原始样式\n document.body.style.overflow = originalBodyStyle.value.overflow\n document.body.style.paddingRight = originalBodyStyle.value.paddingRight\n}\n\n// 懒加载逻辑\nlet observer: IntersectionObserver | null = null\n\nconst setupIntersectionObserver = () => {\n if (!props.lazy || !containerRef.value) return\n \n observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n isInView.value = true\n imgSrc.value = props.src\n observer?.unobserve(entry.target)\n }\n })\n },\n {\n rootMargin: '50px'\n }\n )\n \n observer.observe(containerRef.value)\n}\n\n// 事件处理\nconst handleLoad = (event: Event) => {\n isLoaded.value = true\n isLoading.value = false\n hasError.value = false\n emit('load', event)\n}\n\nconst handleError = (event: Event) => {\n hasError.value = true\n isLoading.value = false\n isLoaded.value = false\n emit('error', event)\n}\n\nconst retryLoad = () => {\n hasError.value = false\n isLoading.value = true\n isLoaded.value = false\n \n nextTick(() => {\n if (imageRef.value) {\n imageRef.value.src = props.src\n }\n })\n}\n\nconst getPreviewUrl = () => {\n if (Array.isArray(props.previewSrcList)) {\n return props.previewSrcList.find(Boolean) || props.src\n }\n return props.previewSrcList || props.src\n}\n\nconst handleErrorClick = () => {\n // 如果有预览源,即使加载失败也允许预览\n if (props.preview && (props.previewSrcList || props.src)) {\n handlePreview()\n } else {\n retryLoad()\n }\n}\n\nconst handlePreview = () => {\n if (!props.preview) return\n \n // 重置缩放级别\n zoomLevel.value = 1;\n \n // 使用预览源或原始源\n const previewUrl = getPreviewUrl();\n\n // 如果图片已经在当前 img 元素中加载完成,直接显示预览\n if (imageRef.value && imageRef.value.complete && imageRef.value.naturalWidth > 0) {\n previewSrc.value = previewUrl;\n nextTick(() => {\n showPreview.value = true;\n lockBodyScroll();\n emit('preview', previewUrl);\n });\n return;\n }\n \n // 预加载图片以避免闪烁\n const img = new Image();\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let isHandled = false;\n \n const showPreviewModal = () => {\n if (isHandled) return;\n isHandled = true;\n \n if (timeoutId) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n \n previewSrc.value = previewUrl;\n nextTick(() => {\n showPreview.value = true;\n lockBodyScroll();\n emit('preview', previewUrl);\n });\n };\n \n // 设置超时,防止预加载卡住\n timeoutId = setTimeout(() => {\n showPreviewModal();\n }, 500);\n \n img.onload = () => {\n showPreviewModal();\n };\n \n img.onerror = () => {\n // 如果预加载失败,仍然尝试显示\n showPreviewModal();\n };\n \n // 如果图片已经在缓存中,complete 会立即为 true\n img.src = previewUrl;\n \n // 检查图片是否已经在缓存中\n if (img.complete) {\n showPreviewModal();\n }\n}\n\nconst closePreview = () => {\n showPreview.value = false;\n \n // 等待过渡动画完成后恢复滚动\n setTimeout(() => {\n unlockBodyScroll();\n }, 300); // 与CSS过渡时间一致\n}\n\nconst handleWheel = (event: WheelEvent) => {\n // 确定缩放方向 (向上滚动放大,向下滚动缩小)\n const zoomDirection = event.deltaY < 0 ? 1 : -1;\n \n // 计算新的缩放级别 (每次缩放10%)\n const zoomStep = 0.1;\n let newZoom = zoomLevel.value + (zoomDirection * zoomStep);\n \n // 限制缩放范围在50%到200%之间\n newZoom = Math.max(0.5, Math.min(2.0, newZoom));\n \n // 更新缩放级别\n zoomLevel.value = newZoom;\n}\n\n// 生命周期\nonMounted(() => {\n if (!props.lazy) {\n isInView.value = true\n } else {\n setupIntersectionObserver()\n }\n \n if (isInView.value) {\n isLoading.value = true\n }\n\n // 设置客户端渲染标志\n isMounted.value = true\n})\n\nonUnmounted(() => {\n if (observer) {\n observer.disconnect()\n }\n \n // 确保组件销毁时恢复滚动状态\n if (showPreview.value) {\n unlockBodyScroll()\n }\n})\n\n// 监听src变化\nconst watchSrc = () => {\n if (props.src && isInView.value) {\n isLoading.value = true\n hasError.value = false\n isLoaded.value = false\n }\n}\n\nwatch(() => imgSrc.value, watchSrc)\nwatch(() => props.src, (nv) => {\n imgSrc.value = nv || ''\n})\n// 暴露方法\ndefineExpose({\n retryLoad,\n closePreview\n})\n</script>\n\n<style scoped>\n.yimage-container {\n position: relative;\n display: inline-block;\n overflow: hidden;\n}\n\n.yimage-placeholder,\n.yimage-loading,\n.yimage-error {\n width: 100%;\n height: 100%;\n}\n\n.yimage-placeholder {\n background-color: #e5e7eb;\n animation: yimage-pulse 2s ease-in-out infinite;\n}\n\n.yimage-placeholder-content {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n\n.yimage-placeholder-icon {\n width: 24px;\n height: 24px;\n color: #9ca3af;\n}\n\n.yimage-loading {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(249, 250, 251, 0.9);\n pointer-events: none;\n}\n\n.yimage-loading-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n}\n\n.yimage-spinner {\n width: 32px;\n height: 32px;\n border: 4px solid rgba(26, 26, 26, 0.2);\n border-top-color: #1A1A1A;\n border-radius: 999px;\n animation: yimage-spin 1s linear infinite;\n}\n\n.yimage-error {\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: #f3f4f6;\n cursor: pointer;\n}\n\n.yimage-error-image {\n width: 70%;\n height: 70%;\n object-fit: contain;\n cursor: pointer;\n}\n\n.yimage-image {\n width: 100%;\n height: 100%;\n display: block;\n transition: opacity 0.2s ease, transform 0.2s ease;\n}\n\n.yimage-image.is-previewable {\n cursor: pointer;\n}\n\n.yimage-image.is-previewable:hover {\n opacity: 0.9;\n}\n\n.yimage-preview-trigger {\n position: absolute;\n inset: 0;\n cursor: pointer;\n z-index: 10;\n}\n\n.yimage-preview-mask {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.75);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 99999;\n}\n\n.yimage-preview-content {\n position: relative;\n max-width: 64rem;\n max-height: 100%;\n padding: 1rem;\n transform: scale(0.95);\n transition: transform 0.3s ease;\n}\n\n.yimage-preview-content.is-active {\n transform: scale(1);\n}\n\n.yimage-preview-image {\n max-width: 100%;\n max-height: 100%;\n object-fit: contain;\n border-radius: 0.5rem;\n box-shadow: 0 20px 45px rgba(0, 0, 0, 0.35);\n transition: transform 0.2s ease;\n}\n\n/* 过渡动画 */\n.fade-enter-active,\n.fade-leave-active {\n transition: opacity 0.3s ease;\n}\n\n.fade-enter-from,\n.fade-leave-to {\n opacity: 0;\n}\n\n/* 基础图片设置 */\nimg {\n display: block;\n -webkit-user-drag: none;\n user-select: none;\n -moz-user-select: none;\n -webkit-user-select: none;\n -ms-user-select: none;\n}\n\n@keyframes yimage-pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n\n@keyframes yimage-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n</style> ","<template>\n <div class=\"y-dropdown\" ref=\"dropdownRef\">\n <!-- 触发器 -->\n <div \n class=\"y-dropdown__trigger\" \n @mouseenter=\"showDropdown\"\n @mouseleave=\"hideDropdown\"\n >\n <slot name=\"trigger\">\n <button class=\"y-dropdown__button\">\n 下拉菜单\n </button>\n </slot>\n </div>\n\n <!-- 下拉菜单 -->\n <transition name=\"dropdown-fade\" appear>\n <div \n v-show=\"visible\"\n class=\"y-dropdown__menu\"\n :class=\"menuClass\"\n :style=\"menuStyle\"\n @mouseenter=\"showDropdown\"\n @mouseleave=\"hideDropdown\"\n >\n <slot>\n <div class=\"y-dropdown__item\">选项 1</div>\n <div class=\"y-dropdown__item\">选项 2</div>\n <div class=\"y-dropdown__item\">选项 3</div>\n </slot>\n </div>\n </transition>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'\n\ninterface Props {\n trigger?: 'hover' | 'click'\n placement?: 'bottom' | 'top' | 'left' | 'right'\n disabled?: boolean\n menuWidth?: number | string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n trigger: 'hover',\n placement: 'bottom',\n disabled: false,\n menuWidth: undefined\n})\n\nconst visible = ref(false)\nconst dropdownRef = ref<HTMLElement>()\nlet hideTimer: number | null = null\n\n// 计算菜单类名\nconst menuClass = computed(() => {\n return `y-dropdown__menu--${props.placement}`\n})\n\nconst menuStyle = computed(() => {\n if (!props.menuWidth) return {}\n const width =\n typeof props.menuWidth === 'number'\n ? `${props.menuWidth}px`\n : props.menuWidth\n return {\n width,\n minWidth: width,\n maxWidth: width\n }\n})\n\n// 显示下拉菜单\nconst showDropdown = () => {\n console.log('显示下拉菜单', visible.value)\n if (props.disabled) return\n \n // 清除隐藏定时器\n if (hideTimer) {\n clearTimeout(hideTimer)\n hideTimer = null\n }\n \n visible.value = true\n console.log('设置 visible 为 true', visible.value)\n \n // 立即计算位置,确保菜单在显示时就在正确位置\n nextTick(() => {\n updatePosition()\n })\n}\n\n// 隐藏下拉菜单\nconst hideDropdown = () => {\n console.log('隐藏下拉菜单')\n // 添加延迟,给用户时间移入菜单\n hideTimer = setTimeout(() => {\n visible.value = false\n console.log('设置 visible 为 false', visible.value)\n }, 150)\n}\n\n// 更新菜单位置\nconst updatePosition = () => {\n if (!dropdownRef.value) return\n \n const trigger = dropdownRef.value.querySelector('.y-dropdown__trigger') as HTMLElement\n const menu = dropdownRef.value.querySelector('.y-dropdown__menu') as HTMLElement\n \n if (!trigger || !menu) return\n \n // 获取触发器和菜单的尺寸信息\n const triggerRect = trigger.getBoundingClientRect()\n const menuRect = menu.getBoundingClientRect()\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n \n // 重置位置样式\n menu.style.top = ''\n menu.style.left = ''\n menu.style.right = ''\n menu.style.bottom = ''\n menu.style.transform = ''\n \n let top = 0\n let left = 0\n \n // 根据 placement 设置基本位置\n switch (props.placement) {\n case 'bottom':\n top = triggerRect.height + 4\n left = 0\n break\n \n case 'top':\n top = -(menuRect.height + 4)\n left = 0\n break\n \n case 'right':\n top = 0\n left = triggerRect.width + 4\n break\n \n case 'left':\n top = 0\n left = -(menuRect.width + 4)\n break\n }\n \n // 计算相对于视口的绝对位置\n let absoluteTop = triggerRect.top + top\n let absoluteLeft = triggerRect.left + left\n \n // 水平边界检测和调整\n if (props.placement === 'bottom' || props.placement === 'top') {\n const menuWidth = menuRect.width || 260 // 使用实际菜单宽度\n \n // 如果菜单会超出右边界,向左偏移保持10px边距\n if (absoluteLeft + menuWidth > viewportWidth - 10) {\n absoluteLeft = viewportWidth - menuWidth - 10\n }\n \n // 如果菜单会超出左边界,向右偏移保持10px边距\n if (absoluteLeft < 10) {\n absoluteLeft = 10\n }\n }\n \n // 垂直边界检测和调整\n if (props.placement === 'left' || props.placement === 'right') {\n const menuHeight = menuRect.height || 200 // 使用实际菜单高度\n \n // 如果菜单会超出下边界,向上偏移保持10px边距\n if (absoluteTop + menuHeight > viewportHeight - 10) {\n absoluteTop = viewportHeight - menuHeight - 10\n }\n \n // 如果菜单会超出上边界,向下偏移保持10px边距\n if (absoluteTop < 10) {\n absoluteTop = 10\n }\n }\n \n // 应用位置(使用固定定位的绝对坐标)\n menu.style.top = `${absoluteTop}px`\n menu.style.left = `${absoluteLeft}px`\n}\n\n// 点击外部关闭\nconst handleClickOutside = (event: MouseEvent) => {\n if (props.trigger === 'click' && dropdownRef.value && !dropdownRef.value.contains(event.target as Node)) {\n visible.value = false\n }\n}\n\n// 窗口大小变化时重新计算位置\nconst handleResize = () => {\n if (visible.value) {\n updatePosition()\n }\n}\n\nonMounted(() => {\n if (props.trigger === 'click') {\n document.addEventListener('click', handleClickOutside)\n }\n // 监听窗口大小变化\n window.addEventListener('resize', handleResize)\n // 监听滚动事件\n window.addEventListener('scroll', handleResize)\n})\n\nonUnmounted(() => {\n if (props.trigger === 'click') {\n document.removeEventListener('click', handleClickOutside)\n }\n // 清理定时器\n if (hideTimer) {\n clearTimeout(hideTimer)\n }\n // 清理事件监听器\n window.removeEventListener('resize', handleResize)\n window.removeEventListener('scroll', handleResize)\n})\n\nwatch(\n () => props.menuWidth,\n () => {\n if (visible.value) {\n nextTick(() => {\n updatePosition()\n })\n }\n }\n)\n</script>\n\n<style scoped lang=\"less\">\n.y-dropdown {\n position: relative;\n display: inline-block;\n\n &__trigger {\n cursor: pointer;\n }\n\n &__button {\n height: 44px;\n padding: 0 16px;\n border: 1px solid #e2e8f0;\n border-radius: 10px;\n background: #fff;\n color: #0b1a29;\n cursor: pointer;\n font-size: 14px;\n transition: box-shadow 0.2s ease, border-color 0.2s ease;\n\n &:hover {\n border-color: #60a5fa;\n box-shadow: 0 0 0 4px rgba(59,130,246,0.15);\n }\n }\n\n &__menu {\n position: fixed;\n z-index: 9999;\n min-width: 100px;\n max-width: 300px;\n background: #fff;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n box-shadow: 0 8px 20px rgba(2,6,23,0.15);\n white-space: nowrap;\n\n &--bottom {\n top: calc(100% + 4px);\n left: 0;\n }\n\n &--top {\n bottom: calc(100% + 4px);\n left: 0;\n }\n\n &--left {\n top: 0;\n right: calc(100% + 4px);\n }\n\n &--right {\n top: 0;\n left: calc(100% + 4px);\n }\n }\n\n &__item {\n height: 36px;\n padding: 0 12px;\n color: #0b1a29;\n cursor: pointer;\n display: flex;\n align-items: center;\n font-size: 13px;\n transition: background-color 0.2s ease, color 0.2s ease;\n\n &:hover {\n background-color: #F6F6F7;\n color: #303061;\n }\n\n &:not(:last-child) {\n border-bottom: 1px solid #f1f5f9;\n }\n }\n}\n\n// 动画效果 - 只使用透明度变化,不改变位置\n.dropdown-fade-enter-active {\n transition: opacity 0.15s ease-out;\n}\n\n.dropdown-fade-leave-active {\n transition: opacity 0.1s ease-in;\n}\n\n.dropdown-fade-enter-from,\n.dropdown-fade-leave-to {\n opacity: 0;\n}\n\n.dropdown-fade-enter-to,\n.dropdown-fade-leave-from {\n opacity: 1;\n}\n\n// 暗色主题支持\n@media (prefers-color-scheme: dark) {\n .y-dropdown__button {\n background: rgba(2,6,23,0.4);\n border-color: rgba(148,163,184,0.18);\n color: #e5eef7;\n }\n \n .y-dropdown__menu {\n background: rgba(2,6,23,0.9);\n border-color: rgba(148,163,184,0.18);\n }\n \n .y-dropdown__item {\n color: #e5eef7;\n \n &:hover {\n background-color: #F6F6F7;\n color: #303061;\n }\n \n &:not(:last-child) {\n border-bottom-color: rgba(148,163,184,0.1);\n }\n }\n}\n</style>\n","<template>\r\n <teleport to=\"body\">\r\n <div\r\n v-show=\"visible\"\r\n class=\"y-drawer-root\"\r\n role=\"dialog\"\r\n :aria-modal=\"true\"\r\n :aria-hidden=\"!visible\"\r\n :style=\"{ zIndex: String(zIndex) }\"\r\n >\r\n <div\r\n class=\"y-drawer-mask\"\r\n @click=\"onMaskClick\"\r\n ></div>\r\n\r\n <transition :name=\"transitionName\">\r\n <div\r\n v-show=\"visible\"\r\n ref=\"panelRef\"\r\n class=\"y-drawer-panel\"\r\n :class=\"[\r\n `is-${placement}`,\r\n roundedClass,\r\n ]\"\r\n :style=\"panelStyle\"\r\n @keydown.esc.prevent.stop=\"onEsc\"\r\n tabindex=\"-1\"\r\n >\r\n <div v-if=\"showHeader\" class=\"y-drawer-header\">\r\n <div class=\"y-drawer-title\">{{ title }}</div>\r\n <button\r\n v-if=\"closable\"\r\n type=\"button\"\r\n class=\"y-drawer-close\"\r\n aria-label=\"Close\"\r\n @click=\"close\"\r\n >\r\n ✕\r\n </button>\r\n </div>\r\n\r\n <div class=\"y-drawer-body\">\r\n <slot />\r\n </div>\r\n\r\n <div v-if=\"$slots.footer\" class=\"y-drawer-footer\">\r\n <slot name=\"footer\" />\r\n </div>\r\n </div>\r\n </transition>\r\n </div>\r\n </teleport>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue'\r\n\r\nconst props = withDefaults(defineProps<{\r\n modelValue?: boolean\r\n placement?: 'right' | 'bottom'\r\n width?: string | number\r\n height?: string | number\r\n title?: string\r\n closable?: boolean\r\n maskClosable?: boolean\r\n zIndex?: number\r\n showHeader?: boolean\r\n}>(), {\r\n modelValue: false,\r\n placement: 'right',\r\n width: '420px',\r\n height: '60vh',\r\n title: '',\r\n closable: true,\r\n maskClosable: true,\r\n zIndex: 3000,\r\n showHeader: true,\r\n})\r\n\r\nconst emit = defineEmits<{\r\n (e: 'update:modelValue', value: boolean): void\r\n (e: 'open'): void\r\n (e: 'close'): void\r\n}>()\r\n\r\nconst visible = computed({\r\n get: () => props.modelValue,\r\n set: (v: boolean) => emit('update:modelValue', v),\r\n})\r\n\r\nconst panelRef = ref<HTMLElement | null>(null)\r\n\r\nconst transitionName = computed(() => props.placement === 'right' ? 'drawer-slide-right' : 'drawer-slide-bottom')\r\n\r\nconst roundedClass = computed(() => props.placement === 'right' ? 'rounded-left' : 'rounded-top')\r\n\r\nconst panelStyle = computed(() => {\r\n const style: Record<string, string> = {}\r\n if (props.placement === 'right') {\r\n style.width = typeof props.width === 'number' ? `${props.width}px` : String(props.width)\r\n style.height = '100%'\r\n style.right = '0'\r\n style.top = '0'\r\n } else {\r\n style.height = typeof props.height === 'number' ? `${props.height}px` : String(props.height)\r\n style.width = '100%'\r\n style.bottom = '0'\r\n style.left = '0'\r\n }\r\n return style\r\n})\r\n\r\nfunction onMaskClick() {\r\n if (!props.maskClosable) return\r\n close()\r\n}\r\n\r\nfunction close() {\r\n if (!visible.value) return\r\n visible.value = false\r\n emit('close')\r\n}\r\n\r\nfunction onEsc() {\r\n if (props.closable) close()\r\n}\r\n\r\nfunction onKeydown(e: KeyboardEvent) {\r\n if (e.key === 'Escape') onEsc()\r\n}\r\n\r\nwatch(() => props.modelValue, (v) => {\r\n if (v) {\r\n emit('open')\r\n // 聚焦,便于 Esc 关闭\r\n requestAnimationFrame(() => panelRef.value?.focus())\r\n document.addEventListener('keydown', onKeydown)\r\n document.body.style.overflow = 'hidden'\r\n } else {\r\n document.removeEventListener('keydown', onKeydown)\r\n document.body.style.overflow = ''\r\n }\r\n})\r\n\r\nonMounted(() => {\r\n if (props.modelValue) {\r\n document.addEventListener('keydown', onKeydown)\r\n document.body.style.overflow = 'hidden'\r\n }\r\n})\r\n\r\nonUnmounted(() => {\r\n document.removeEventListener('keydown', onKeydown)\r\n document.body.style.overflow = ''\r\n})\r\n</script>\r\n\r\n<style scoped>\r\n.y-drawer-root {\r\n position: fixed;\r\n inset: 0;\r\n}\r\n\r\n.y-drawer-mask {\r\n position: absolute;\r\n inset: 0;\r\n background: rgba(2, 6, 23, 0.55);\r\n backdrop-filter: blur(2px);\r\n}\r\n\r\n.y-drawer-panel {\r\n position: absolute;\r\n display: flex;\r\n flex-direction: column;\r\n background: #ffffff;\r\n border: 1px solid rgba(15, 23, 42, 0.06);\r\n box-shadow: 0 12px 40px rgba(2, 6, 23, 0.18);\r\n}\r\n\r\n/* 圆角根据拉出方向,仅对露出的边做圆角 */\r\n.rounded-left { border-radius: 12px 0 0 12px; }\r\n.rounded-top { border-radius: 12px 12px 0 0; }\r\n\r\n.y-drawer-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 14px 16px;\r\n border-bottom: 1px solid rgba(15, 23, 42, 0.06);\r\n}\r\n\r\n.y-drawer-title {\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: #0b1a29;\r\n}\r\n\r\n.y-drawer-close {\r\n appearance: none;\r\n border: none;\r\n background: transparent;\r\n color: #334155;\r\n font-size: 16px;\r\n line-height: 1;\r\n cursor: pointer;\r\n padding: 6px;\r\n border-radius: 8px;\r\n}\r\n.y-drawer-close:hover { background: rgba(15,23,42,0.05); }\r\n\r\n.y-drawer-body {\r\n padding: 16px;\r\n overflow: auto;\r\n}\r\n\r\n.y-drawer-footer {\r\n padding: 12px 16px;\r\n border-top: 1px solid rgba(15, 23, 42, 0.06);\r\n}\r\n\r\n/* 进入/离场动画:右侧 */\r\n.drawer-slide-right-enter-from,\r\n.drawer-slide-right-leave-to { transform: translateX(100%); opacity: 0.98; }\r\n.drawer-slide-right-enter-active,\r\n.drawer-slide-right-leave-active { transition: transform 220ms ease, opacity 220ms ease; }\r\n.drawer-slide-right-enter-to,\r\n.drawer-slide-right-leave-from { transform: translateX(0%); opacity: 1; }\r\n\r\n/* 进入/离场动画:底部 */\r\n.drawer-slide-bottom-enter-from,\r\n.drawer-slide-bottom-leave-to { transform: translateY(100%); opacity: 0.98; }\r\n.drawer-slide-bottom-enter-active,\r\n.drawer-slide-bottom-leave-active { transition: transform 220ms ease, opacity 220ms ease; }\r\n.drawer-slide-bottom-enter-to,\r\n.drawer-slide-bottom-leave-from { transform: translateY(0%); opacity: 1; }\r\n\r\n/* 位置占位 */\r\n.y-drawer-panel.is-right { right: 0; top: 0; bottom: 0; }\r\n.y-drawer-panel.is-bottom { left: 0; right: 0; bottom: 0; }\r\n\r\n@media (prefers-color-scheme: dark) {\r\n .y-drawer-panel {\r\n background: rgba(15, 23, 42, 0.7);\r\n border-color: rgba(148, 163, 184, 0.12);\r\n box-shadow: 0 12px 40px rgba(2, 6, 23, 0.5);\r\n }\r\n .y-drawer-title { color: #e5eef7; }\r\n .y-drawer-close { color: #cbd5e1; }\r\n .y-drawer-close:hover { background: rgba(148,163,184,0.12); }\r\n}\r\n</style>\r\n\r\n\r\n","<template>\n <div\n class=\"ytree\"\n :class=\"[`ytree--${size}`, { 'ytree--disabled': disabled }]\"\n >\n <div class=\"ytree__container\">\n <div\n v-for=\"node in treeData\"\n :key=\"getNodeKey(node)\"\n class=\"ytree-node\"\n :class=\"{ 'ytree-node--current': isNodeCurrent(node), 'ytree-node--highlight': isNodeHighlighted(node) }\"\n >\n <div\n class=\"ytree-node__content\"\n :class=\"{ 'is-child-style': isChildStyleNode(node, node) }\"\n :style=\"{ paddingLeft: '8px' }\"\n :data-level=\"getNodeDepth(node, node)\"\n @click=\"handleNodeClick(node, node, null, node)\"\n @contextmenu=\"handleNodeContextMenu($event, node, node, null)\"\n >\n <!-- 展开/收起图标 -->\n <span\n v-if=\"hasChildren(node)\"\n class=\"ytree-node__expand-icon\"\n :class=\"{ 'is-expanded': isNodeExpanded(node) }\"\n @click.stop=\"handleExpandClick(node)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path\n d=\"M4.5 3L7.5 6L4.5 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n\n <span v-else class=\"w-[16px]\"></span>\n\n <!-- 复选框 -->\n <span\n v-if=\"showCheckbox\"\n class=\"ytree-node__checkbox\"\n :class=\"{\n 'is-checked': isNodeChecked(node),\n 'is-indeterminate': isNodeIndeterminate(node),\n }\"\n @click.stop=\"handleCheckClick(node)\"\n >\n <svg\n v-if=\"isNodeChecked(node)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L4.5 8.5L10 3\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <svg\n v-else-if=\"isNodeIndeterminate(node)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L10 6\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </span>\n\n <!-- 节点图标 -->\n <span\n v-if=\"iconClass\"\n class=\"ytree-node__icon\"\n :class=\"iconClass\"\n ></span>\n\n <!-- 节点头像/图标 -->\n <img\n class=\"ytree-node__avatar\"\n :src=\"getNodeIcon(node, node)\"\n :alt=\"isEmployeeNode(node) ? 'person' : 'dept'\"\n />\n\n <!-- 节点标签 -->\n <span\n class=\"ytree-node__label\"\n :class=\"{ 'is-employee': isEmployeeNode(node) }\"\n >\n {{ getNodeLabel(node) }}\n </span>\n\n <!-- 自定义节点内容插槽 -->\n <div class=\"ytree-node__custom-content\">\n <slot\n name=\"node-content\"\n :node=\"node\"\n :is-current=\"isNodeCurrent(node)\"\n :is-expanded=\"isNodeExpanded(node)\"\n :has-children=\"hasChildren(node)\"\n />\n </div>\n </div>\n\n <!-- 子节点 - 递归渲染 -->\n <transition name=\"ytree-node\">\n <div\n v-if=\"hasChildren(node) && isNodeExpanded(node)\"\n class=\"ytree-node__children\"\n >\n <div\n v-for=\"child in getNodeChildren(node)\"\n :key=\"getNodeKey(child)\"\n class=\"ytree-node\"\n :class=\"{ 'ytree-node--current': isNodeCurrent(child), 'ytree-node--highlight': isNodeHighlighted(child) }\"\n >\n <div\n class=\"ytree-node__content\"\n :class=\"{ 'is-child-style': isChildStyleNode(child, node) }\"\n :style=\"{ paddingLeft: `${6 + 14 + 2}px` }\"\n :data-level=\"getNodeDepth(node, child)\"\n @click=\"handleNodeClick(child, child, null, node)\"\n @contextmenu=\"handleNodeContextMenu($event, child, child, null)\"\n >\n <!-- 展开/收起图标 -->\n <span\n v-if=\"hasChildren(child)\"\n class=\"ytree-node__expand-icon\"\n :class=\"{ 'is-expanded': isNodeExpanded(child) }\"\n @click.stop=\"handleExpandClick(child)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\">\n <path\n d=\"M4.5 3L7.5 6L4.5 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n <span v-else class=\"w-[16px]\"></span>\n\n <!-- 复选框 -->\n <span\n v-if=\"showCheckbox\"\n class=\"ytree-node__checkbox\"\n :class=\"{\n 'is-checked': isNodeChecked(child),\n 'is-indeterminate': isNodeIndeterminate(child),\n }\"\n @click.stop=\"handleCheckClick(child)\"\n >\n <svg\n v-if=\"isNodeChecked(child)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L4.5 8.5L10 3\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <svg\n v-else-if=\"isNodeIndeterminate(child)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L10 6\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </span>\n\n <!-- 节点图标 -->\n <span\n v-if=\"iconClass\"\n class=\"ytree-node__icon\"\n :class=\"iconClass\"\n ></span>\n\n <!-- 节点头像/图标 -->\n <img\n class=\"ytree-node__avatar\"\n :src=\"getNodeIcon(child, node)\"\n :alt=\"isEmployeeNode(child) ? 'person' : 'dept'\"\n />\n\n <!-- 节点标签 -->\n <span\n class=\"ytree-node__label\"\n :class=\"{ 'is-employee': isEmployeeNode(child) }\"\n >\n {{ getNodeLabel(child) }}\n </span>\n\n <!-- 自定义节点内容插槽 -->\n <div class=\"ytree-node__custom-content\">\n <slot\n name=\"node-content\"\n :node=\"child\"\n :is-current=\"isNodeCurrent(child)\"\n :is-expanded=\"isNodeExpanded(child)\"\n :has-children=\"hasChildren(child)\"\n />\n </div>\n </div>\n\n <!-- 第三级子节点 -->\n <transition name=\"ytree-node\">\n <div\n v-if=\"hasChildren(child) && isNodeExpanded(child)\"\n class=\"ytree-node__children\"\n >\n <div\n v-for=\"grandChild in getNodeChildren(child)\"\n :key=\"getNodeKey(grandChild)\"\n class=\"ytree-node\"\n :class=\"{\n 'ytree-node--current': isNodeCurrent(grandChild),\n 'ytree-node--highlight': isNodeHighlighted(grandChild),\n }\"\n >\n <div\n class=\"ytree-node__content\"\n :class=\"{ 'is-child-style': isChildStyleNode(grandChild, node) }\"\n :style=\"{ paddingLeft: `${6 + 14 + 2 + 14 + 2}px` }\"\n :data-level=\"getNodeDepth(node, grandChild)\"\n @click=\"handleNodeClick(grandChild, grandChild, null, node)\"\n @contextmenu=\"\n handleNodeContextMenu(\n $event,\n grandChild,\n grandChild,\n null\n )\n \"\n >\n <!-- 展开/收起图标 -->\n <span\n v-if=\"hasChildren(grandChild)\"\n class=\"ytree-node__expand-icon\"\n :class=\"{ 'is-expanded': isNodeExpanded(grandChild) }\"\n @click.stop=\"handleExpandClick(grandChild)\"\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M4.5 3L7.5 6L4.5 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n <span v-else class=\"w-[16px]\"></span>\n\n <!-- 复选框 -->\n <span\n v-if=\"showCheckbox\"\n class=\"ytree-node__checkbox\"\n :class=\"{\n 'is-checked': isNodeChecked(grandChild),\n 'is-indeterminate': isNodeIndeterminate(grandChild),\n }\"\n @click.stop=\"handleCheckClick(grandChild)\"\n >\n <svg\n v-if=\"isNodeChecked(grandChild)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L4.5 8.5L10 3\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <svg\n v-else-if=\"isNodeIndeterminate(grandChild)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L10 6\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </span>\n\n <!-- 节点图标 -->\n <span\n v-if=\"iconClass\"\n class=\"ytree-node__icon\"\n :class=\"iconClass\"\n ></span>\n\n <!-- 节点头像/图标 -->\n <img\n class=\"ytree-node__avatar\"\n :src=\"getNodeIcon(grandChild, node)\"\n :alt=\"isEmployeeNode(grandChild) ? 'person' : 'dept'\"\n />\n\n <!-- 节点标签 -->\n <span\n class=\"ytree-node__label\"\n :class=\"{ 'is-employee': isEmployeeNode(grandChild) }\"\n >\n {{ getNodeLabel(grandChild) }}\n </span>\n\n <!-- 自定义节点内容插槽 -->\n <div class=\"ytree-node__custom-content\">\n <slot\n name=\"node-content\"\n :node=\"grandChild\"\n :is-current=\"isNodeCurrent(grandChild)\"\n :is-expanded=\"isNodeExpanded(grandChild)\"\n :has-children=\"hasChildren(grandChild)\"\n />\n </div>\n </div>\n\n <!-- 第四级子节点 -->\n <transition name=\"ytree-node\">\n <div\n v-if=\"\n hasChildren(grandChild) && isNodeExpanded(grandChild)\n \"\n class=\"ytree-node__children\"\n >\n <div\n v-for=\"greatGrandChild in getNodeChildren(grandChild)\"\n :key=\"getNodeKey(greatGrandChild)\"\n class=\"ytree-node\"\n :class=\"{\n 'ytree-node--current':\n isNodeCurrent(greatGrandChild),\n 'ytree-node--highlight': isNodeHighlighted(greatGrandChild),\n }\"\n >\n <div\n class=\"ytree-node__content\"\n :class=\"{ 'is-child-style': isChildStyleNode(greatGrandChild, node) }\"\n :style=\"{\n paddingLeft: `${6 + 14 + 2 + 14 + 2 + 14 + 2}px`,\n }\"\n :data-level=\"getNodeDepth(node, greatGrandChild)\"\n @click=\"\n handleNodeClick(\n greatGrandChild,\n greatGrandChild,\n null,\n node\n )\n \"\n @contextmenu=\"\n handleNodeContextMenu(\n $event,\n greatGrandChild,\n greatGrandChild,\n null\n )\n \"\n >\n <!-- 展开/收起图标 -->\n <span\n v-if=\"hasChildren(greatGrandChild)\"\n class=\"ytree-node__expand-icon\"\n :class=\"{\n 'is-expanded': isNodeExpanded(greatGrandChild),\n }\"\n @click.stop=\"handleExpandClick(greatGrandChild)\"\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M4.5 3L7.5 6L4.5 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n <span v-else class=\"w-[16px]\"></span>\n\n <!-- 复选框 -->\n <span\n v-if=\"showCheckbox\"\n class=\"ytree-node__checkbox\"\n :class=\"{\n 'is-checked': isNodeChecked(greatGrandChild),\n 'is-indeterminate':\n isNodeIndeterminate(greatGrandChild),\n }\"\n @click.stop=\"handleCheckClick(greatGrandChild)\"\n >\n <svg\n v-if=\"isNodeChecked(greatGrandChild)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L4.5 8.5L10 3\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <svg\n v-else-if=\"isNodeIndeterminate(greatGrandChild)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L10 6\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </span>\n\n <!-- 节点图标 -->\n <span\n v-if=\"iconClass\"\n class=\"ytree-node__icon\"\n :class=\"iconClass\"\n ></span>\n\n <!-- 节点头像/图标 -->\n <img\n class=\"ytree-node__avatar\"\n :src=\"getNodeIcon(greatGrandChild, node)\"\n :alt=\"\n isEmployeeNode(greatGrandChild)\n ? 'person'\n : 'dept'\n \"\n />\n\n <!-- 节点标签 -->\n <span\n class=\"ytree-node__label\"\n :class=\"{\n 'is-employee': isEmployeeNode(greatGrandChild),\n }\"\n >\n {{ getNodeLabel(greatGrandChild) }}\n </span>\n\n <!-- 自定义节点内容插槽 -->\n <div class=\"ytree-node__custom-content\">\n <slot\n name=\"node-content\"\n :node=\"greatGrandChild\"\n :is-current=\"isNodeCurrent(greatGrandChild)\"\n :is-expanded=\"isNodeExpanded(greatGrandChild)\"\n :has-children=\"hasChildren(greatGrandChild)\"\n />\n </div>\n </div>\n\n <!-- 第五级子节点 -->\n <transition name=\"ytree-node\">\n <div\n v-if=\"\n hasChildren(greatGrandChild) &&\n isNodeExpanded(greatGrandChild)\n \"\n class=\"ytree-node__children\"\n >\n <div\n v-for=\"greatGreatGrandChild in getNodeChildren(\n greatGrandChild\n )\"\n :key=\"getNodeKey(greatGreatGrandChild)\"\n class=\"ytree-node\"\n :class=\"{\n 'ytree-node--current':\n isNodeCurrent(greatGreatGrandChild),\n }\"\n >\n <div\n class=\"ytree-node__content\"\n :class=\"{ 'is-child-style': isChildStyleNode(greatGreatGrandChild, node) }\"\n :style=\"{\n paddingLeft: `${\n 6 + 14 + 2 + 14 + 2 + 14 + 2 + 14 + 2\n }px`,\n }\"\n :data-level=\"\n getNodeDepth(node, greatGreatGrandChild)\n \"\n @click=\"\n handleNodeClick(\n greatGreatGrandChild,\n greatGreatGrandChild,\n null,\n node\n )\n \"\n @contextmenu=\"\n handleNodeContextMenu(\n $event,\n greatGreatGrandChild,\n greatGreatGrandChild,\n null\n )\n \"\n >\n <!-- 展开/收起图标 -->\n <span\n v-if=\"hasChildren(greatGreatGrandChild)\"\n class=\"ytree-node__expand-icon\"\n :class=\"{\n 'is-expanded':\n isNodeExpanded(greatGreatGrandChild),\n }\"\n @click.stop=\"\n handleExpandClick(greatGreatGrandChild)\n \"\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M4.5 3L7.5 6L4.5 9\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n <span v-else class=\"w-[16px]\"></span>\n\n <!-- 复选框 -->\n <span\n v-if=\"showCheckbox\"\n class=\"ytree-node__checkbox\"\n :class=\"{\n 'is-checked':\n isNodeChecked(greatGreatGrandChild),\n 'is-indeterminate':\n isNodeIndeterminate(\n greatGreatGrandChild\n ),\n }\"\n @click.stop=\"\n handleCheckClick(greatGreatGrandChild)\n \"\n >\n <svg\n v-if=\"isNodeChecked(greatGreatGrandChild)\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L4.5 8.5L10 3\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <svg\n v-else-if=\"\n isNodeIndeterminate(\n greatGreatGrandChild\n )\n \"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n >\n <path\n d=\"M2 6L10 6\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </span>\n\n <!-- 节点图标 -->\n <span\n v-if=\"iconClass\"\n class=\"ytree-node__icon\"\n :class=\"iconClass\"\n ></span>\n\n <!-- 节点头像/图标 -->\n <img\n class=\"ytree-node__avatar\"\n :src=\"getNodeIcon(greatGreatGrandChild, node)\"\n :alt=\"\n isEmployeeNode(greatGreatGrandChild)\n ? 'person'\n : 'dept'\n \"\n />\n\n <!-- 节点标签 -->\n <span\n class=\"ytree-node__label\"\n :class=\"{\n 'is-employee':\n isEmployeeNode(greatGreatGrandChild),\n }\"\n >\n {{ getNodeLabel(greatGreatGrandChild) }}\n </span>\n\n <!-- 自定义节点内容插槽 -->\n <div class=\"ytree-node__custom-content\">\n <slot\n name=\"node-content\"\n :node=\"greatGreatGrandChild\"\n :is-current=\"\n isNodeCurrent(greatGreatGrandChild)\n \"\n :is-expanded=\"\n isNodeExpanded(greatGreatGrandChild)\n \"\n :has-children=\"\n hasChildren(greatGreatGrandChild)\n \"\n />\n </div>\n </div>\n </div>\n </div>\n </transition>\n </div>\n </div>\n </transition>\n </div>\n </div>\n </transition>\n </div>\n </div>\n </transition>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, provide, watch } from \"vue\";\n// import YTreeNode from './ytree-node.vue'\n\n// 节点图标地址(部门/人员)\nconst DEPT_ICON_URL =\n \"https://image.nhdropshipping.com/fit-in/500x500/filters:format(webp)/media/2025/10/17/1979094146203385856/32.png\";\nconst PERSON_ICON_URL =\n \"https://image.nhdropshipping.com/fit-in/500x500/filters:format(webp)/media/2025/10/17/1979095296159907840/32.png\";\n\nexport interface TreeNode {\n id?: string | number;\n label: string;\n children?: TreeNode[];\n disabled?: boolean;\n isLeaf?: boolean;\n expanded?: boolean;\n checked?: boolean;\n indeterminate?: boolean;\n data?: any;\n [key: string]: any;\n}\n\nexport interface TreeProps {\n data?: TreeNode[];\n emptyText?: string;\n nodeKey?: string;\n props?: {\n children?: string;\n label?: string;\n disabled?: string;\n isLeaf?: string;\n };\n renderAfterExpand?: boolean;\n defaultExpandAll?: boolean;\n defaultExpandedKeys?: (string | number)[];\n defaultCheckedKeys?: (string | number)[];\n defaultSelectedKeys?: (string | number)[];\n checkStrictly?: boolean;\n checkOnClickNode?: boolean;\n checkDescendants?: boolean;\n autoExpandParent?: boolean;\n defaultChecked?: boolean;\n filterNodeMethod?: (value: any, data: TreeNode, node: any) => boolean;\n lazy?: boolean;\n load?: (node: TreeNode, resolve: (data: TreeNode[]) => void) => void;\n renderContent?: (h: any, node: TreeNode, data: any, store: any) => any;\n highlightCurrent?: boolean;\n expandOnClickNode?: boolean;\n currentNodeKey?: string | number;\n accordion?: boolean;\n indent?: number;\n iconClass?: string;\n showCheckbox?: boolean;\n draggable?: boolean;\n allowDrag?: (node: TreeNode) => boolean;\n allowDrop?: (\n draggingNode: TreeNode,\n dropNode: TreeNode,\n type: \"prev\" | \"inner\" | \"next\"\n ) => boolean;\n size?: \"small\" | \"medium\" | \"large\";\n disabled?: boolean;\n deptIconUrl?: string;\n personIconUrl?: string;\n buttonIconUrl?: string;\n // 是否启用第四级节点特殊处理(已废弃)\n enableFourthLevelSpecialHandling?: boolean;\n // 从第几级开始不进行任何\"默认/自动展开\"的级别阈值(如传 4 表示第4级及其以下不自动展开)\n restrictAutoExpandFromLevel?: number | undefined;\n // 子样式节点配置:定义第几级节点为子样式节点及其图标\n childStyleLevel?: number | undefined;\n childStyleIconUrl?: string;\n // 是否启用子样式节点自定义点击事件(如果启用,子样式节点点击会触发 child-node-click 事件而不是 node-click)\n enableChildStyleCustomClick?: boolean;\n}\n\nconst props = withDefaults(defineProps<TreeProps>(), {\n data: () => [],\n emptyText: \"暂无数据\",\n nodeKey: \"id\",\n props: () => ({\n children: \"children\",\n label: \"label\",\n disabled: \"disabled\",\n isLeaf: \"isLeaf\",\n }),\n renderAfterExpand: true,\n defaultExpandAll: false,\n defaultExpandedKeys: () => [],\n defaultCheckedKeys: () => [],\n defaultSelectedKeys: () => [],\n checkStrictly: false,\n checkOnClickNode: false,\n checkDescendants: true,\n autoExpandParent: true,\n defaultChecked: false,\n lazy: false,\n highlightCurrent: false,\n expandOnClickNode: true,\n accordion: false,\n indent: 18,\n iconClass: \"\",\n showCheckbox: false,\n draggable: false,\n size: \"medium\",\n disabled: false,\n deptIconUrl: \"\",\n personIconUrl: \"\",\n buttonIconUrl: \"\",\n enableFourthLevelSpecialHandling: false,\n restrictAutoExpandFromLevel: undefined,\n childStyleLevel: undefined,\n childStyleIconUrl: \"\",\n enableChildStyleCustomClick: false,\n});\n\nconst emit = defineEmits<{\n \"node-click\": [data: TreeNode, node: any, nodeComponent: any];\n \"node-contextmenu\": [\n event: Event,\n data: TreeNode,\n node: any,\n nodeComponent: any\n ];\n \"check-change\": [data: TreeNode, checked: boolean, indeterminate: boolean];\n check: [data: TreeNode, checked: any, indeterminate: any];\n \"current-change\": [data: TreeNode, node: any];\n \"node-expand\": [data: TreeNode, node: any, nodeComponent: any];\n \"node-collapse\": [data: TreeNode, node: any, nodeComponent: any];\n \"node-drag-start\": [node: TreeNode, event: DragEvent];\n \"node-drag-enter\": [\n draggingNode: TreeNode,\n dropNode: TreeNode,\n event: DragEvent\n ];\n \"node-drag-leave\": [\n draggingNode: TreeNode,\n dropNode: TreeNode,\n event: DragEvent\n ];\n \"node-drag-over\": [\n draggingNode: TreeNode,\n dropNode: TreeNode,\n event: DragEvent\n ];\n \"node-drag-end\": [\n draggingNode: TreeNode,\n dropNode: TreeNode,\n event: DragEvent\n ];\n \"node-drop\": [\n draggingNode: TreeNode,\n dropNode: TreeNode,\n dropType: \"before\" | \"after\" | \"inner\",\n event: DragEvent\n ];\n \"checked-keys-change\": [keys: Array<string | number>];\n \"child-node-click\": [data: TreeNode, node: any, nodeComponent: any];\n}>();\n\n// 计算属性\nconst treeData = computed(() => {\n console.log(\"ytree 组件接收到的数据:\", props.data);\n return props.data || [];\n});\n// const nodeProps = computed(() => props.props || {});\n\n// 提供全局状态\nconst store = ref({\n currentNode: null as TreeNode | null,\n currentKey: null as string | number | null,\n checkedKeys: new Set<string | number>(),\n expandedKeys: new Set<string | number>(),\n selectedKeys: new Set<string | number>(),\n highlightedKeys: new Set<string | number>(),\n});\n\nprovide(\"treeStore\", store);\n\n// 方法\nconst effectiveRestrictLevel = computed<number | undefined>(() => {\n // 仅以新属性为准(组件化配置)。传入有效正数才启用限制\n return props.restrictAutoExpandFromLevel && props.restrictAutoExpandFromLevel > 0\n ? props.restrictAutoExpandFromLevel\n : undefined;\n});\n\nfunction getNodeKey(node: TreeNode): string | number {\n return node[props.nodeKey] || node.id || Math.random();\n}\n\nfunction getNodeLabel(node: TreeNode): string {\n return (props.props?.label ? node[props.props.label] : undefined) || node.label || \"\";\n}\n\nfunction isEmployeeNode(node: any): boolean {\n return Boolean(node?.data?.isEmployee);\n}\n\nfunction getNodeIcon(node: any, rootNode?: TreeNode): string {\n const dept = props.deptIconUrl || DEPT_ICON_URL;\n const person = props.personIconUrl || PERSON_ICON_URL;\n const button = props.buttonIconUrl || \"\";\n const childStyleIcon = props.childStyleIconUrl || \"\";\n \n // 优先检查是否是子样式节点\n if (rootNode && childStyleIcon && isChildStyleNode(node, rootNode)) {\n return childStyleIcon;\n }\n \n // 兼容旧的按钮节点判断逻辑\n if (node?.data?.isButton && button) return button;\n \n return isEmployeeNode(node) ? person : dept;\n}\n\nfunction hasChildren(node: TreeNode): boolean {\n const children = (props.props?.children ? node[props.props.children] : undefined) || node.children;\n return children && children.length > 0;\n}\n\nfunction getNodeChildren(node: TreeNode): TreeNode[] {\n return (props.props?.children ? node[props.props.children] : undefined) || node.children || [];\n}\n\n// 计算节点在树中的深度\nfunction getNodeDepth(\n node: TreeNode,\n targetNode: TreeNode,\n currentDepth: number = 1\n): number {\n if (node === targetNode) {\n return currentDepth;\n }\n\n const children = getNodeChildren(node);\n for (const child of children) {\n const depth = getNodeDepth(child, targetNode, currentDepth + 1);\n if (depth > 0) {\n return depth;\n }\n }\n\n return 0;\n}\n\n// 判断节点是否是子样式节点\nfunction isChildStyleNode(node: TreeNode, rootNode: TreeNode): boolean {\n if (!props.childStyleLevel || props.childStyleLevel < 1) {\n return false;\n }\n const depth = getNodeDepth(rootNode, node);\n return depth === props.childStyleLevel;\n}\n\n// 检查节点是否为第四级节点(按钮权限)\n// function isFourthLevelNode(node: TreeNode): boolean {\n// return Boolean(node.data?.isButton);\n// }\n\nfunction isNodeExpanded(node: TreeNode): boolean {\n const nodeKey = getNodeKey(node);\n return store.value.expandedKeys.has(nodeKey);\n}\n\nfunction isNodeChecked(node: TreeNode): boolean {\n const nodeKey = getNodeKey(node);\n const directlyChecked = store.value.checkedKeys.has(nodeKey);\n\n // 如果直接选中,检查是否真的是全选状态\n if (directlyChecked) {\n if (hasChildren(node)) {\n const children = getNodeChildren(node);\n const checkedChildren = children.filter((child) => isNodeChecked(child));\n const indeterminateChildren = children.filter((child) =>\n isNodeIndeterminate(child)\n );\n\n // 只有当所有子节点都被选中且没有中间状态时,才显示为选中状态\n return (\n checkedChildren.length === children.length &&\n indeterminateChildren.length === 0\n );\n }\n return true;\n }\n\n // 如果有子节点且子节点全部选中,也返回true\n if (hasChildren(node)) {\n const children = getNodeChildren(node);\n // 检查是否有子节点处于中间状态\n const hasIndeterminateChild = children.some((child) =>\n isNodeIndeterminate(child)\n );\n if (hasIndeterminateChild) return false;\n\n return (\n children.length > 0 && children.every((child) => isNodeChecked(child))\n );\n }\n\n return false;\n}\n\nfunction isNodeIndeterminate(node: TreeNode): boolean {\n if (!hasChildren(node)) return false;\n\n const children = getNodeChildren(node);\n const checkedChildren = children.filter((child) => isNodeChecked(child));\n const indeterminateChildren = children.filter((child) =>\n isNodeIndeterminate(child)\n );\n\n // 如果子节点全部选中,则当前节点应该显示为选中状态(不是中间状态)\n if (checkedChildren.length === children.length) return false;\n\n // 如果子节点部分选中或有中间状态,则显示中间状态\n return checkedChildren.length > 0 || indeterminateChildren.length > 0;\n}\n\nfunction isNodeCurrent(node: TreeNode): boolean {\n const key = getNodeKey(node);\n return store.value.currentKey === key;\n}\n\nfunction isNodeHighlighted(node: TreeNode): boolean {\n const key = getNodeKey(node);\n return store.value.highlightedKeys.has(key);\n}\n\nfunction handleCheckClick(node: TreeNode) {\n // 如果组件被禁用,不允许勾选操作\n if (props.disabled) return;\n\n const nodeKey = getNodeKey(node);\n const isChecked = store.value.checkedKeys.has(nodeKey);\n const newCheckedState = !isChecked;\n\n // 保存当前的展开状态,避免被勾选操作影响\n const currentExpandedKeys = new Set(store.value.expandedKeys);\n\n // Update current node\n if (newCheckedState) {\n store.value.checkedKeys.add(nodeKey);\n } else {\n store.value.checkedKeys.delete(nodeKey);\n }\n\n // Cascade to children - 选中功能保持正常,但展开逻辑特殊处理\n function cascadeChildren(children: TreeNode[], check: boolean) {\n children.forEach((child) => {\n const childKey = getNodeKey(child);\n if (check) {\n store.value.checkedKeys.add(childKey);\n } else {\n store.value.checkedKeys.delete(childKey);\n }\n\n // 递归处理所有子节点,确保选中功能正常\n if (hasChildren(child)) {\n cascadeChildren(getNodeChildren(child), check);\n }\n });\n }\n\n // 正常递归选中所有子节点\n cascadeChildren(getNodeChildren(node), newCheckedState);\n\n // 特殊处理:如果选中了包含第四级子节点的节点,不自动展开第四级节点\n if (newCheckedState) {\n preventAutoExpandFourthLevel(node);\n }\n\n // Update all parent nodes recursively from bottom to top\n updateAllParentNodes();\n\n // 恢复展开状态,确保勾选操作不影响节点的展开收缩\n store.value.expandedKeys = currentExpandedKeys;\n\n // Emit change\n emit(\"check-change\", node, newCheckedState, false);\n emit(\"check\", node, newCheckedState, false);\n emit(\"checked-keys-change\", Array.from(store.value.checkedKeys));\n}\n\n// 防止自动展开第四级节点的函数\nfunction preventAutoExpandFourthLevel(_node: TreeNode) {\n // 兼容旧日志,统一到可配置级别\n if (effectiveRestrictLevel.value) {\n console.log(\n `已启用从第${effectiveRestrictLevel.value}级开始不默认展开的限制(不主动收起已展开节点)`\n );\n }\n}\n\n// 重写 handleExpandClick 函数,确保第四级节点只能手动展开\nfunction handleExpandClick(node: TreeNode) {\n const nodeKey = getNodeKey(node);\n const isExpanded = store.value.expandedKeys.has(nodeKey);\n\n if (isExpanded) {\n // 收起节点\n store.value.expandedKeys.delete(nodeKey);\n emit(\"node-collapse\", node, node, null);\n } else {\n // 展开节点 - 第四级节点只能手动展开\n store.value.expandedKeys.add(nodeKey);\n emit(\"node-expand\", node, node, null);\n }\n}\n\n// 递归更新所有父节点,从叶子节点向上更新\nfunction updateAllParentNodes() {\n // 收集所有节点\n const allNodes: TreeNode[] = [];\n\n function collectAllNodes(nodes: TreeNode[]) {\n nodes.forEach((node) => {\n allNodes.push(node);\n if (hasChildren(node)) {\n collectAllNodes(getNodeChildren(node));\n }\n });\n }\n\n collectAllNodes(treeData.value);\n\n // 从叶子节点开始,向上更新父节点状态\n function updateNodeParents(node: TreeNode) {\n if (hasChildren(node)) {\n const children = getNodeChildren(node);\n const nodeKey = getNodeKey(node);\n\n // 检查子节点状态\n const checkedChildren = children.filter((child) => isNodeChecked(child));\n const indeterminateChildren = children.filter((child) =>\n isNodeIndeterminate(child)\n );\n\n // 如果所有子节点都被选中且没有中间状态,添加父节点到checkedKeys\n if (\n checkedChildren.length === children.length &&\n indeterminateChildren.length === 0\n ) {\n store.value.checkedKeys.add(nodeKey);\n } else if (\n checkedChildren.length > 0 ||\n indeterminateChildren.length > 0\n ) {\n // 如果有子节点被选中或有中间状态,也添加父节点到checkedKeys(用于中间状态传值)\n store.value.checkedKeys.add(nodeKey);\n } else {\n // 否则从checkedKeys中移除父节点\n store.value.checkedKeys.delete(nodeKey);\n }\n }\n }\n\n // 从叶子节点开始更新(倒序遍历)\n for (let i = allNodes.length - 1; i >= 0; i--) {\n updateNodeParents(allNodes[i]);\n }\n}\n\nfunction handleNodeClick(data: TreeNode, node: any, nodeComponent: any, rootNode?: TreeNode) {\n if (props.disabled) return;\n \n // 判断是否是子样式节点\n const isChildStyle = rootNode ? isChildStyleNode(data, rootNode) : false;\n \n // 如果启用了子样式节点自定义点击事件且是子样式节点,触发 child-node-click 事件\n if (props.enableChildStyleCustomClick && isChildStyle) {\n emit(\"child-node-click\", data, node, nodeComponent);\n return;\n }\n // 需求:当 expandOnClickNode=true 且为父节点时,优先展开/收起且不触发事件\n if (props.expandOnClickNode && hasChildren(data)) {\n handleExpandClick(data);\n return;\n }\n\n store.value.currentNode = data;\n store.value.currentKey = getNodeKey(data);\n\n // 权限树可用性:若展示复选框,点击整行也进行勾选切换\n if (props.showCheckbox) {\n handleCheckClick(data);\n }\n\n // 有无监听器都 emit,Vue 会按需处理\n emit(\"node-click\", data, node, nodeComponent);\n}\n\nfunction handleNodeContextMenu(\n event: Event,\n data: TreeNode,\n node: any,\n nodeComponent: any\n) {\n if (props.disabled) return;\n emit(\"node-contextmenu\", event, data, node, nodeComponent);\n}\n\n// 初始化默认状态\nwatch(\n () => props.defaultExpandedKeys,\n (keys) => {\n if (keys) {\n const restrictLevel = effectiveRestrictLevel.value;\n if (restrictLevel) {\n // 允许外部传入默认展开 keys,但需过滤:从 restrictLevel 起不自动展开\n // 同时保留“已手动展开”的受限级别节点\n\n // 计算节点深度工具\n function getDepthByKey(targetKey: string | number, nodes: TreeNode[], level = 1): number {\n for (const n of nodes) {\n if (getNodeKey(n) === targetKey) return level;\n if (hasChildren(n)) {\n const d = getDepthByKey(targetKey, getNodeChildren(n), level + 1);\n if (d > 0) return d;\n }\n }\n return 0;\n }\n\n // 仅保留小于限制级别的默认展开 keys\n const filtered = (keys || []).filter((k) => {\n const depth = getDepthByKey(k as any, treeData.value, 1);\n return depth > 0 && depth < restrictLevel;\n });\n const newExpandedKeys = new Set(filtered);\n\n // 自动补齐:将第 1 至 restrictLevel-1 级的所有可展开节点加入(确保 3/4 层也会展开)\n function collectKeysToDepth(nodes: TreeNode[], level: number, maxDepth: number) {\n nodes.forEach((node) => {\n if (level < maxDepth && hasChildren(node)) {\n newExpandedKeys.add(getNodeKey(node));\n collectKeysToDepth(getNodeChildren(node), level + 1, maxDepth);\n } else if (level < maxDepth && !hasChildren(node)) {\n // 叶子节点无需加入,但继续一致的遍历结构\n } else if (level >= maxDepth) {\n // 达到限制深度,停止自动补齐\n }\n });\n }\n collectKeysToDepth(treeData.value, 1, restrictLevel);\n\n // 保留当前“已展开”的受限级别节点(通常由用户手动展开)\n store.value.expandedKeys.forEach((key) => {\n const depth = getDepthByKey(key, treeData.value, 1);\n if (depth >= restrictLevel) {\n newExpandedKeys.add(key);\n }\n });\n\n store.value.expandedKeys = newExpandedKeys;\n } else {\n store.value.expandedKeys = new Set(keys);\n }\n }\n },\n { immediate: true }\n);\n\n// 处理 defaultExpandAll\nfunction expandAllNodes() {\n if (props.defaultExpandAll) {\n // 收集所有有子节点的节点ID\n const allExpandableKeys = new Set<string | number>();\n\n const restrictLevel = effectiveRestrictLevel.value;\n\n function collectExpandableKeys(nodes: TreeNode[], level: number = 1) {\n nodes.forEach((node) => {\n if (!hasChildren(node)) return;\n\n const children = getNodeChildren(node);\n\n if (restrictLevel) {\n // 达到或超过限制级别,则不再自动展开\n if (level >= restrictLevel) return;\n\n // 若下一层就是限制级别,则当前父节点也不自动展开,但递归子节点以便后续逻辑使用\n const hasChildAtRestrictLevel = level + 1 === restrictLevel;\n if (!hasChildAtRestrictLevel) {\n allExpandableKeys.add(getNodeKey(node));\n }\n collectExpandableKeys(children, level + 1);\n } else {\n // 普通模式:所有有子节点的层级默认展开\n allExpandableKeys.add(getNodeKey(node));\n collectExpandableKeys(children, level + 1);\n }\n });\n }\n\n collectExpandableKeys(treeData.value, 1);\n\n store.value.expandedKeys = allExpandableKeys;\n }\n}\n\n// 展开包含选中权限的节点路径\nfunction expandNodesWithCheckedPermissions() {\n if (props.defaultCheckedKeys && props.defaultCheckedKeys.length > 0) {\n const checkedKeys = new Set(props.defaultCheckedKeys);\n const expandableKeys = new Set<string | number>();\n\n function findPathsToCheckedNodes(\n nodes: TreeNode[],\n parentPath: (string | number)[] = []\n ) {\n nodes.forEach((node) => {\n const nodeKey = getNodeKey(node);\n const currentPath = [...parentPath, nodeKey];\n\n // 如果当前节点被选中,展开到它的所有父节点\n if (checkedKeys.has(nodeKey)) {\n parentPath.forEach((key) => expandableKeys.add(key));\n }\n\n // 递归处理子节点\n if (hasChildren(node)) {\n findPathsToCheckedNodes(getNodeChildren(node), currentPath);\n }\n });\n }\n\n findPathsToCheckedNodes(treeData.value);\n\n const restrictLevel = effectiveRestrictLevel.value;\n if (restrictLevel) {\n // 启用限制:保持当前展开状态,不进行自动展开\n console.log(\n `已启用从第${restrictLevel}级开始不默认展开:保持当前展开状态不变`\n );\n return;\n }\n // 普通模式:自动展开到包含选中权限的路径\n store.value.expandedKeys = expandableKeys;\n }\n}\n\n// 根据key查找节点\n// function findNodeByKey(key: string | number): TreeNode | null {\n// function searchNodes(nodes: TreeNode[]): TreeNode | null {\n// for (const node of nodes) {\n// if (getNodeKey(node) === key) {\n// return node;\n// }\n// if (hasChildren(node)) {\n// const found = searchNodes(getNodeChildren(node));\n// if (found) return found;\n// }\n// }\n// return null;\n// }\n// return searchNodes(treeData.value);\n// }\n\nwatch(() => props.defaultExpandAll, expandAllNodes, { immediate: true });\n\n// 当树数据变化时,如果设置了 defaultExpandAll,重新展开所有节点\nwatch(() => treeData.value, expandAllNodes, { deep: true });\n\nwatch(\n () => props.defaultCheckedKeys,\n (keys) => {\n if (keys) {\n store.value.checkedKeys = new Set(keys);\n\n // 在权限树模式下,完全跳过自动展开逻辑,保持当前展开状态不变\n if (!props.enableFourthLevelSpecialHandling) {\n // 当选中权限变化时,展开包含这些权限的节点路径\n expandNodesWithCheckedPermissions();\n } else {\n console.log(\"权限树模式:跳过自动展开逻辑,保持当前展开状态\");\n }\n } else {\n store.value.checkedKeys.clear();\n }\n },\n { immediate: true }\n);\n\n// 根据传入的一组 id,展开到对应节点并高亮这些节点\nfunction highlightAndExpandByIds(ids: Array<string | number>) {\n try {\n const targetIds = Array.isArray(ids) ? ids : [];\n if (targetIds.length === 0) return;\n\n // 工具:查找到目标 key 的路径(返回 key 数组路径)\n function findPathToKey(\n nodes: TreeNode[],\n targetKey: string | number,\n path: (string | number)[] = []\n ): (string | number)[] | null {\n for (const n of nodes) {\n const nk = getNodeKey(n);\n const newPath = [...path, nk];\n if (nk === targetKey) return newPath;\n if (hasChildren(n)) {\n const p = findPathToKey(getNodeChildren(n), targetKey, newPath);\n if (p) return p;\n }\n }\n return null;\n }\n\n // 清除旧的高亮\n store.value.highlightedKeys.clear();\n\n // 累积需要展开的父级 key\n const keysToExpand = new Set<string | number>(store.value.expandedKeys);\n\n targetIds.forEach((targetId) => {\n const path = findPathToKey(treeData.value, targetId);\n if (path && path.length > 0) {\n // 父级全部加入展开集合(除最后一个自身)\n path.slice(0, -1).forEach((k) => keysToExpand.add(k));\n // 目标节点加入高亮集合\n store.value.highlightedKeys.add(path[path.length - 1]);\n }\n });\n\n // 应用展开\n store.value.expandedKeys = keysToExpand;\n } catch (e) {\n console.warn('highlightAndExpandByIds 执行失败', e);\n }\n}\n\n// 清除高亮\nfunction clearHighlights() {\n store.value.highlightedKeys.clear();\n}\n\n// 清除当前选中节点\nfunction clearCurrentNode() {\n store.value.currentNode = null;\n store.value.currentKey = null;\n}\n\ndefineExpose({ highlightAndExpandByIds, clearHighlights, clearCurrentNode });\n\nwatch(\n () => props.defaultSelectedKeys,\n (keys) => {\n if (keys) {\n store.value.selectedKeys = new Set(keys);\n }\n },\n { immediate: true }\n);\n</script>\n\n<style scoped>\n.ytree {\n position: relative;\n font-size: 14px;\n line-height: 1.5;\n color: #0b1a29;\n}\n\n.ytree--disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.ytree__container {\n position: relative;\n overflow: auto;\n}\n\n/* 尺寸变体 */\n.ytree--small {\n font-size: 12px;\n}\n\n.ytree--small .ytree__container {\n padding: 2px 0;\n}\n\n.ytree--medium {\n font-size: 13px;\n}\n\n.ytree--medium .ytree__container {\n padding: 4px 0;\n}\n\n.ytree--large {\n font-size: 14px;\n}\n\n.ytree--large .ytree__container {\n padding: 6px 0;\n}\n\n/* 树节点样式 */\n.ytree-node {\n position: relative;\n}\n\n.ytree-node__content {\n display: flex;\n align-items: center;\n height: 24px;\n padding: 0 6px;\n cursor: pointer;\n transition: background-color 0.2s ease, color 0.2s ease;\n border-radius: 4px;\n margin: 0.5px 0;\n}\n\n.ytree-node__content:hover:not(.ytree-node--disabled .ytree-node__content) {\n background-color: #f6f6f7;\n color: #303061;\n}\n\n.ytree-node--current > .ytree-node__content {\n background-color: #f0f0f0;\n font-weight: bold;\n}\n\n/* 高亮节点样式(仅文本变绿,无背景) */\n.ytree-node--highlight > .ytree-node__content .ytree-node__label {\n color: #10b981 !important;\n font-weight: 600;\n}\n\n.ytree-node--disabled .ytree-node__content {\n color: #9ca3af;\n cursor: not-allowed;\n}\n\n.ytree-node__expand-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n margin-right: 2px;\n color: #6b7280;\n transition: transform 0.2s ease, color 0.2s ease;\n cursor: pointer;\n border-radius: 2px;\n}\n\n.ytree-node__expand-icon:hover {\n color: #374151;\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n.ytree-node__expand-icon.is-expanded {\n transform: rotate(90deg);\n}\n\n.ytree-node__expand-icon--empty {\n width: 14px;\n height: 14px;\n margin-right: 4px;\n}\n\n.ytree-node__checkbox {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 10px;\n height: 10px;\n margin-right: 4px;\n border: 1px solid #d1d5db;\n border-radius: 2px;\n background: #ffffff;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n/* .ytree-node__checkbox:hover:not(.is-disabled) {\n border-color: #60a5fa;\n background-color: #f0f9ff;\n} */\n\n.ytree-node__checkbox.is-checked {\n background-color: #3f8682;\n color: #ffffff;\n}\n\n.ytree-node__checkbox.is-indeterminate {\n background-color: #3f8682;\n border-color: #3f8682;\n color: #ffffff;\n}\n\n.ytree-node__checkbox.is-disabled {\n background-color: #f9fafb;\n border-color: #e5e7eb;\n color: #9ca3af;\n cursor: not-allowed;\n}\n\n.ytree-node__icon {\n margin-right: 4px;\n font-size: 12px;\n color: #6b7280;\n}\n\n.ytree-node__label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 13px;\n line-height: 1.4;\n font-weight:500;\n}\n\n/* 子样式节点特殊样式 - 通过配置的级别动态应用 */\n.ytree-node__content.is-child-style .ytree-node__label {\n font-weight: 500 !important;\n color: #636363 !important;\n font-size: 12px !important;\n}\n\n/* 兼容旧的第四级节点样式(已废弃,保留以兼容旧代码) */\n.ytree--permission-tree .ytree-node__content[data-level=\"4\"] .ytree-node__label,\n.ytree--permission-tree .ytree-node[data-level=\"4\"] .ytree-node__label,\n.permission-tree .ytree-node__content[data-level=\"4\"] .ytree-node__label,\n.permission-tree .ytree-node[data-level=\"4\"] .ytree-node__label {\n font-weight: 500 !important;\n color: #636363 !important;\n font-size: 12px !important;\n}\n\n/* 员工节点颜色样式 */\n.ytree-node__label.is-employee {\n font-weight: 500;\n color: #777777;\n font-size: 12px;\n}\n\n/* 高亮覆盖(优先级更高,放在子样式规则之后) */\n.ytree-node.ytree-node--highlight > .ytree-node__content .ytree-node__label,\n.ytree-node.ytree-node--highlight > .ytree-node__content.is-child-style .ytree-node__label {\n color: #00a761 !important;\n font-weight: bold !important;\n}\n\n.ytree-node__custom-content {\n display: flex;\n align-items: center;\n margin-left: auto;\n flex-shrink: 0;\n}\n\n.ytree-node__avatar {\n width: 14px;\n height: 14px;\n margin-right: 4px;\n border-radius: 2px;\n object-fit: cover;\n}\n\n.ytree-node__label.is-current {\n font-weight: 500;\n}\n\n/* 暗色主题支持 */\n@media (prefers-color-scheme: dark) {\n .ytree {\n color: #e5eef7;\n }\n\n .ytree-node__content {\n color: #e5eef7;\n }\n\n .ytree-node__content:hover:not(.ytree-node--disabled .ytree-node__content) {\n background-color: rgba(2, 6, 23, 0.4);\n color: #e5eef7;\n }\n\n .ytree-node--current .ytree-node__content {\n background-color: rgba(59, 130, 246, 0.2);\n color: #60a5fa;\n }\n\n .ytree-node--disabled .ytree-node__content {\n color: #9ca3af;\n }\n\n .ytree-node__expand-icon {\n color: #9ca3af;\n }\n\n .ytree-node__expand-icon:hover {\n color: #cbd5e1;\n background-color: rgba(148, 163, 184, 0.1);\n }\n\n .ytree-node__checkbox {\n background: rgba(2, 6, 23, 0.4);\n border-color: rgba(148, 163, 184, 0.3);\n }\n\n .ytree-node__checkbox:hover:not(.is-disabled) {\n border-color: #60a5fa;\n background-color: rgba(59, 130, 246, 0.1);\n }\n\n .ytree-node__icon {\n color: #9ca3af;\n }\n\n /* 子样式节点暗色主题样式 */\n .ytree-node__content.is-child-style .ytree-node__label {\n color: #9ca3af !important;\n }\n\n /* 兼容旧的第四级节点暗色主题样式(已废弃,保留以兼容旧代码) */\n .ytree--permission-tree\n .ytree-node__content[data-level=\"4\"]\n .ytree-node__label,\n .ytree--permission-tree .ytree-node[data-level=\"4\"] .ytree-node__label,\n .permission-tree .ytree-node__content[data-level=\"4\"] .ytree-node__label,\n .permission-tree .ytree-node[data-level=\"4\"] .ytree-node__label {\n color: #9ca3af !important;\n }\n}\n</style>\n","<template>\n <div class=\"query-encapsulation\">\n <div class=\"query-encapsulation__container\">\n <div class=\"query-encapsulation__content\">\n <!-- 查询字段和操作按钮 -->\n <div class=\"query-encapsulation__fields\">\n <!-- 所有查询字段(带过渡动画,且不影响原有布局) -->\n <transition-group name=\"qf\" tag=\"div\" class=\"query-encapsulation__fields-group\">\n <div\n v-for=\"field in displayedFields\"\n :key=\"field.key\"\n class=\"query-encapsulation__field-item\"\n >\n <!-- 优先使用插槽自定义字段 -->\n <slot \n :name=\"`field-${field.key}`\" \n :field=\"field\" \n :value=\"searchForm[field.key]\"\n :update-value=\"(val: any) => updateFieldValue(field.key, val)\"\n >\n <!-- 默认渲染 -->\n <div class=\"query-encapsulation__field-wrapper\">\n <label v-if=\"Iflabel || field.type === 'switch'\" class=\"query-encapsulation__field-label\">{{ field.label }}</label>\n <component\n :is=\"getFieldComponent(field.type)\"\n v-model=\"searchForm[field.key]\"\n :placeholder=\"field.placeholder || `请输入${field.label}`\"\n :options=\"field.options\"\n :clearable=\"field.clearable !== false\"\n :size=\"field.size || 'small'\"\n :width=\"field.width || '180px'\"\n :format=\"field.format || 'timestamp'\"\n :include-time=\"field.includeTime || false\"\n :filterable=\"field.filterable === true\"\n :multiple=\"field.multiple === true\"\n :true-value=\"field.trueValue\"\n :false-value=\"field.falseValue\"\n :active-text=\"field.activeText\"\n :inactive-text=\"field.inactiveText\"\n :show-text=\"field.showText\"\n :active-color=\"field.activeColor || (field.type === 'switch' ? '#1B2433' : undefined)\"\n :inactive-color=\"field.inactiveColor\"\n v-on=\"getFieldListeners(field)\"\n @input=\"field.type !== 'switch' ? handleFieldChange(field) : undefined\"\n @change=\"field.type === 'switch' ? handleSwitchChange(field, $event) : handleFieldChange(field)\"\n />\n </div>\n </slot>\n </div>\n </transition-group>\n\n <!-- 展开/收起按钮 -->\n <div class=\"query-encapsulation__toggle\" v-if=\"hasHiddenFields\">\n <YButton variant=\"secondary\" size=\"small\" @click=\"toggleExpanded\">\n {{ isExpanded ? \"收起\" : \"展开\" }}\n <span\n class=\"query-encapsulation__toggle-icon\"\n :class=\"{ 'is-expanded': isExpanded }\"\n >▼</span\n >\n </YButton>\n </div>\n\n <!-- 操作按钮 -->\n <div class=\"query-encapsulation__actions\">\n <div class=\"query-encapsulation__actions-group\">\n <YButton\n variant=\"primary\"\n size=\"small\"\n @click=\"handleSearch\"\n :loading=\"loading\"\n >\n 搜索\n </YButton>\n <YButton\n variant=\"secondary\"\n size=\"small\"\n @click=\"handleReset\"\n :loading=\"loading\"\n >\n 重置\n </YButton>\n <slot name=\"extra-actions\"></slot>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n ref,\n reactive,\n computed,\n watch,\n onMounted,\n onBeforeUnmount,\n nextTick,\n} from \"vue\";\nimport YInput from \"./yinput.vue\";\nimport YSelect from \"./yselect.vue\";\nimport YButton from \"./ybutton.vue\";\nimport YTime from \"./ytime.vue\";\nimport YSwitch from \"./yswitch.vue\";\nimport type { SelectOption } from \"./yselect.vue\";\n\nexport interface QueryField {\n key: string;\n label: string;\n type: \"input\" | \"select\" | \"date\" | \"daterange\" | \"switch\";\n placeholder?: string;\n options?: SelectOption[];\n clearable?: boolean;\n size?: \"mini\" | \"small\" | \"medium\" | \"large\";\n width?: string;\n required?: boolean;\n hidden?: boolean; // 是否默认隐藏\n format?: \"timestamp\" | \"string\" | \"date\"; // 时间格式\n includeTime?: boolean; // 是否包含时间\n startKey?: string; // 开始时间的 key\n endKey?: string; // 结束时间的 key\n filterable?: boolean; // 可输入搜索(仅 select 支持)\n multiple?: boolean; // 是否多选(仅 select 支持)\n // switch 相关配置\n trueValue?: any; // switch 开启时的值\n falseValue?: any; // switch 关闭时的值\n activeText?: string; // switch 开启时的文本\n inactiveText?: string; // switch 关闭时的文本\n showText?: boolean; // switch 是否显示文本\n activeColor?: string; // switch 开启时的颜色\n inactiveColor?: string; // switch 关闭时的颜色\n onSwitchChange?: (value: any, field: QueryField) => void; // switch 切换时的自定义处理函数\n}\n\nexport interface QueryEncapsulationProps {\n Iflabel?: boolean;\n fields: QueryField[];\n maxVisibleFields?: number;\n loading?: boolean;\n modelValue?: Record<string, any>;\n}\n\nconst props = withDefaults(defineProps<QueryEncapsulationProps>(), {\n Iflabel: true,\n maxVisibleFields: 5,\n loading: false,\n modelValue: () => ({}),\n});\n\nconst emit = defineEmits<{\n \"update:modelValue\": [value: Record<string, any>];\n search: [payload: { data: Record<string, any>; raw: Record<string, any> }];\n reset: [];\n \"field-change\": [field: QueryField, value: any];\n}>();\n\n// 响应式数据\nconst isExpanded = ref(false);\nconst searchForm = reactive<Record<string, any>>({});\nconst autoTriggerTypes: QueryField[\"type\"][] = [\"select\", \"date\", \"daterange\", \"switch\"];\nlet autoSearchTimer: ReturnType<typeof setTimeout> | undefined;\n\n// 计算属性\nconst visibleFields = computed(() => {\n return props.fields.filter((field) => !field.hidden);\n});\n\n// 展示的字段(受展开/收起控制)\nconst displayedFields = computed(() => {\n if (isExpanded.value) return visibleFields.value;\n return visibleFields.value.slice(0, props.maxVisibleFields);\n});\n\n// const hiddenFields = computed(() => {\n// return visibleFields.value.slice(props.maxVisibleFields);\n// });\n\nconst hasHiddenFields = computed(() => {\n return visibleFields.value.length > props.maxVisibleFields;\n});\n\n// 方法\nfunction getFieldComponent(type: string) {\n switch (type) {\n case \"select\":\n return YSelect;\n case \"date\":\n case \"daterange\":\n return YTime;\n case \"switch\":\n return YSwitch;\n case \"input\":\n default:\n return YInput;\n }\n}\n\nfunction updateFieldValue(key: string, value: any) {\n searchForm[key] = value;\n const field = props.fields.find((f) => f.key === key);\n if (field) {\n handleFieldChange(field);\n }\n}\n\nfunction handleFieldChange(field: QueryField) {\n emit(\"field-change\", field, searchForm[field.key]);\n emit(\"update:modelValue\", { ...searchForm });\n if (autoTriggerTypes.includes(field.type)) {\n scheduleAutoSearch();\n }\n}\n\nfunction handleSwitchChange(field: QueryField, value: any) {\n // 如果配置了自定义处理函数,则调用它\n if (field.onSwitchChange && typeof field.onSwitchChange === 'function') {\n field.onSwitchChange(value, field);\n }\n // 仍然触发默认的字段变化处理(会自动触发搜索,因为 switch 已添加到 autoTriggerTypes)\n handleFieldChange(field);\n}\n\nfunction handleSearch() {\n // 过滤空值参数\n const searchParams = filterEmptyParams(searchForm);\n\n // 格式化参数(处理日期范围等特殊字段)\n const formattedParams = formatSearchParams(searchParams);\n\n const rawParams = { ...searchForm };\n\n // 将参数包裹在data对象中\n emit(\"search\", { data: formattedParams, raw: rawParams });\n}\n\nfunction handleReset() {\n // 重置所有字段\n Object.keys(searchForm).forEach((key) => {\n const field = props.fields.find((f) => f.key === key);\n if (field?.type === \"daterange\") {\n searchForm[key] = { startDate: null, endDate: null };\n } else if (field?.type === \"date\") {\n searchForm[key] = null;\n } else if (field?.type === \"switch\") {\n // switch 类型重置为 falseValue 或 false\n searchForm[key] = field.falseValue !== undefined ? field.falseValue : false;\n } else if (field?.type === \"select\" && field.multiple) {\n // 多选 select 类型重置为空数组\n searchForm[key] = [];\n } else {\n searchForm[key] = \"\";\n }\n });\n emit(\"reset\");\n emit(\"update:modelValue\", { ...searchForm });\n}\n\nfunction toggleExpanded() {\n isExpanded.value = !isExpanded.value;\n}\n\nfunction getFieldListeners(field: QueryField) {\n // 只有 input 类型需要特殊的事件监听\n if (field.type !== \"input\") {\n return {};\n }\n return {\n enter: () => handleInputQuickSearch(),\n paste: () => handleInputQuickSearch(),\n };\n}\n\nasync function handleInputQuickSearch() {\n await nextTick();\n handleSearch();\n}\n\nfunction scheduleAutoSearch() {\n if (autoSearchTimer) {\n clearTimeout(autoSearchTimer);\n }\n autoSearchTimer = setTimeout(() => {\n autoSearchTimer = undefined;\n nextTick().then(() => handleSearch());\n }, 0);\n}\n\n// 过滤空值参数\nfunction filterEmptyParams(params: Record<string, any>) {\n const filtered: Record<string, any> = {};\n\n Object.keys(params).forEach((key) => {\n const field = props.fields.find((f) => f.key === key);\n const rawValue = params[key];\n const value =\n typeof rawValue === \"string\" ? rawValue.trim() : rawValue;\n\n // 处理数组类型(多选字段)\n if (Array.isArray(value)) {\n if (value.length > 0) {\n filtered[key] = value;\n }\n return;\n }\n\n if (value === null || value === undefined || value === \"\") {\n return;\n }\n\n if (\n typeof value === \"object\" &&\n value.startDate &&\n value.endDate\n ) {\n if (value.startDate && value.endDate) {\n filtered[key] = value;\n }\n return;\n }\n\n if (field && (field.type === \"date\" || field.type === \"daterange\")) {\n if (value !== 0) {\n filtered[key] = value;\n }\n return;\n }\n\n filtered[key] = value;\n });\n\n return filtered;\n}\n\n// 格式化搜索参数\nfunction formatSearchParams(params: Record<string, any>) {\n const formatted: Record<string, any> = {};\n\n Object.keys(params).forEach((key) => {\n const value = params[key];\n const field = props.fields.find((f) => f.key === key);\n\n if (field) {\n // 根据字段类型格式化参数\n if (field.type === \"daterange\" && typeof value === \"object\") {\n // 日期范围字段:使用自定义的 key 或默认 key\n const startKey = field.startKey || `${key}Start`;\n const endKey = field.endKey || `${key}End`;\n\n // 只有当开始和结束日期都存在且不为0时才添加\n if (value.startDate && value.endDate && value.startDate !== 0 && value.endDate !== 0) {\n if (field.format === \"timestamp\") {\n formatted[startKey] = new Date(value.startDate).getTime();\n formatted[endKey] = new Date(value.endDate).getTime();\n } else {\n formatted[startKey] = value.startDate;\n formatted[endKey] = value.endDate;\n }\n }\n } else if (field.type === \"date\" && value && value !== 0) {\n // 单个日期字段\n if (field.format === \"timestamp\") {\n formatted[key] = new Date(value).getTime();\n } else {\n formatted[key] = value;\n }\n } else {\n // 普通字段直接传递\n formatted[key] = value;\n }\n } else {\n // 没有找到字段定义,直接传递\n formatted[key] = value;\n }\n });\n\n return formatted;\n}\n\n// 初始化表单数据\nfunction initFormData() {\n props.fields.forEach((field) => {\n if (searchForm[field.key] === undefined) {\n // 根据字段类型设置默认值\n if (field.type === \"daterange\") {\n searchForm[field.key] = props.modelValue?.[field.key] || {\n startDate: null,\n endDate: null,\n };\n } else if (field.type === \"date\") {\n searchForm[field.key] = props.modelValue?.[field.key] || null;\n } else if (field.type === \"switch\") {\n // switch 类型使用 falseValue 或 false 作为默认值\n searchForm[field.key] = props.modelValue?.[field.key] !== undefined \n ? props.modelValue[field.key] \n : (field.falseValue !== undefined ? field.falseValue : false);\n } else if (field.type === \"select\" && field.multiple) {\n // 多选 select 类型使用空数组作为默认值\n searchForm[field.key] = props.modelValue?.[field.key] !== undefined \n ? props.modelValue[field.key] \n : [];\n } else {\n searchForm[field.key] = props.modelValue?.[field.key] || \"\";\n }\n }\n });\n}\n\n// 监听外部数据变化\nwatch(\n () => props.modelValue,\n (newValue) => {\n if (newValue) {\n Object.assign(searchForm, newValue);\n }\n },\n { deep: true, immediate: true }\n);\n\n// 生命周期\nonMounted(() => {\n initFormData();\n});\n\nonBeforeUnmount(() => {\n if (autoSearchTimer) {\n clearTimeout(autoSearchTimer);\n autoSearchTimer = undefined;\n }\n});\n\n// 暴露方法供外部调用\ndefineExpose({\n search: handleSearch,\n reset: handleReset,\n});\n</script>\n\n<style scoped>\n/* 主容器 */\n.query-encapsulation {\n width: 100%;\n}\n\n.query-encapsulation__container {\n background: #ffffff;\n border-radius: 10px;\n padding: 16px;\n margin-bottom: 8px;\n box-shadow: \n 0rem 0.3125rem 0.3125rem -0.15625rem rgba(0, 0, 0, 0.03),\n 0rem 0.1875rem 0.1875rem -0.09375rem rgba(0, 0, 0, 0.02),\n 0rem 0.125rem 0.125rem -0.0625rem rgba(0, 0, 0, 0.02),\n 0rem 0.0625rem 0.0625rem -0.03125rem rgba(0, 0, 0, 0.03),\n 0rem 0.03125rem 0.03125rem 0rem rgba(0, 0, 0, 0.04),\n 0rem 0rem 0rem 0.0625rem rgba(0, 0, 0, 0.06);\n}\n\n.query-encapsulation__content {\n width: 100%;\n}\n\n/* 查询字段容器 */\n.query-encapsulation__fields {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 12px;\n margin-bottom: 12px;\n}\n\n.query-encapsulation__fields:last-child {\n margin-bottom: 0;\n}\n\n/* 字段组容器 - 修复 transition-group 布局问题 */\n.query-encapsulation__fields-group {\n display: contents;\n}\n\n/* 单个字段项 */\n.query-encapsulation__field-item {\n display: flex;\n align-items: center;\n transition: all 0.3s ease;\n}\n\n.query-encapsulation__field-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n/* 字段标签 */\n.query-encapsulation__field-label {\n font-size: 13px;\n font-weight: 500;\n color: #374151;\n white-space: nowrap;\n min-width: fit-content;\n flex-shrink: 0;\n margin-right: 8px;\n}\n\n/* 展开/收起按钮 */\n.query-encapsulation__toggle {\n display: flex;\n align-items: center;\n margin-left: 0;\n}\n\n/* 展开/收起图标 */\n.query-encapsulation__toggle-icon {\n display: inline-block;\n margin-left: 4px;\n transition: transform 0.3s ease;\n font-size: 10px;\n}\n\n.query-encapsulation__toggle-icon.is-expanded {\n transform: rotate(180deg);\n}\n\n/* 操作按钮容器 */\n.query-encapsulation__actions {\n display: flex;\n align-items: center;\n}\n\n.query-encapsulation__actions-group {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n/* 查询字段进出场与移动动画 */\n.qf-enter-active,\n.qf-leave-active {\n transition: all 0.2s ease;\n}\n\n.qf-enter-from,\n.qf-leave-to {\n opacity: 0;\n transform: translateY(-6px);\n}\n\n.qf-move {\n transition: transform 0.2s ease;\n}\n\n/* 响应式设计 - 移动优先 */\n/* 超大屏幕(1024px 及以下) */\n@media (max-width: 1024px) {\n .query-encapsulation__fields {\n gap: 10px;\n }\n}\n\n/* 中等屏幕(768px 及以下) */\n@media (max-width: 768px) {\n .query-encapsulation__container {\n padding: 10px;\n }\n}\n\n/* 小屏幕(640px 及以下) */\n@media (max-width: 640px) {\n .query-encapsulation__container {\n padding: 10px;\n }\n \n .query-encapsulation__fields {\n gap: 8px;\n }\n}\n\n/* 兼容性处理:如果浏览器不支持 contents,使用 flex 布局 */\n@supports not (display: contents) {\n .query-encapsulation__fields-group {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 12px;\n }\n \n @media (max-width: 1024px) {\n .query-encapsulation__fields-group {\n gap: 10px;\n }\n }\n \n @media (max-width: 640px) {\n .query-encapsulation__fields-group {\n gap: 8px;\n }\n }\n}\n</style>\n","<template>\n <transition name=\"y-msg-fade\" @after-leave=\"onAfterLeave\">\n <div\n v-show=\"visible\"\n class=\"y-msg\"\n :class=\"[`y-msg--${type}`]\"\n :style=\"{ zIndex: zIndex }\"\n role=\"status\"\n aria-live=\"polite\"\n @mouseenter=\"handleMouseEnter\"\n @mouseleave=\"handleMouseLeave\"\n >\n <span class=\"y-msg__icon\" :class=\"`y-msg__icon--${type}`\" aria-hidden=\"true\">\n <svg v-if=\"type==='success'\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M20 6L9 17l-5-5\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <svg v-else-if=\"type==='warning'\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M12 9v4m0 4h.01M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n <svg v-else width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M12 9v4m0 4h.01M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>\n </span>\n <div class=\"y-msg__content\" v-text=\"message\"></div>\n <button v-if=\"closable\" class=\"y-msg__close\" type=\"button\" @click=\"close\">✕</button>\n </div>\n </transition>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted, onBeforeUnmount, ref } from 'vue'\n\nconst props = withDefaults(defineProps<{\n id: number\n type?: 'success' | 'warning' | 'error'\n message: string\n duration?: number\n offset: number\n zIndex: number\n closable?: boolean\n onClose?: (id: number) => void\n}>(), {\n type: 'success',\n duration: 3000,\n closable: false,\n})\n\nconst visible = ref(false)\nlet timer: number | undefined\nlet remainingTime: number = 0\nlet startTime: number = 0\n\nonMounted(() => {\n // 先隐藏,下一帧再显示以触发过渡\n requestAnimationFrame(() => {\n visible.value = true\n if (props.duration && props.duration > 0) {\n startTimer(props.duration)\n }\n })\n})\n\nonBeforeUnmount(() => { \n clearTimer()\n})\n\nfunction startTimer(duration: number) {\n remainingTime = duration\n startTime = Date.now()\n timer = window.setTimeout(() => close(), duration)\n}\n\nfunction clearTimer() {\n if (timer) {\n window.clearTimeout(timer)\n timer = undefined\n }\n}\n\nfunction handleMouseEnter() {\n if (timer && props.duration && props.duration > 0) {\n clearTimer()\n // 计算剩余时间\n const elapsed = Date.now() - startTime\n remainingTime = Math.max(0, remainingTime - elapsed)\n }\n}\n\nfunction handleMouseLeave() {\n if (props.duration && props.duration > 0 && remainingTime > 0) {\n // 使用剩余时间重新启动计时器\n startTimer(remainingTime)\n }\n}\n\nfunction close() {\n visible.value = false\n}\n\nfunction onAfterLeave() {\n props.onClose?.(props.id)\n}\n</script>\n\n<style scoped>\n.y-msg {\n position: fixed;\n left: 50%;\n top: 0;\n transform: translate(-50%, 0);\n min-width: 260px;\n max-width: 86vw;\n box-sizing: border-box;\n padding: 10px 14px;\n border-radius: 12px;\n background: #ffffff;\n color: #0b1a29;\n display: flex;\n align-items: center;\n gap: 10px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n border: 1px solid rgba(15, 23, 42, 0.08);\n border-left-width: 3px;\n will-change: opacity, transform;\n transition:\n transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1),\n opacity 200ms ease;\n}\n\n.y-msg__icon { \n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n border-radius: 6px;\n padding: 4px;\n box-sizing: border-box;\n}\n.y-msg__icon--success { \n background-color: #047B5D; \n color: #ffffff; \n}\n.y-msg__icon--warning { \n background-color: #FFB800; \n color: #ffffff; \n}\n.y-msg__icon--error { \n background-color: #C41E3A; \n color: #ffffff; \n}\n.y-msg__content { \n margin-top: 2px;\n white-space: pre-wrap; \n word-break: break-word; \n line-height: 1.4;\n display: flex;\n align-items: center;\n /* font-weight: bold; */\n}\n.y-msg__close {\n margin-left: 8px;\n height: 22px; width: 22px;\n border: none; border-radius: 6px; background: transparent; color: inherit; cursor: pointer;\n}\n.y-msg__close:hover { background: rgba(2,6,23,0.06); }\n\n/* 状态色 - 背景统一为白色,通过图标和边框区分 */\n.y-msg--success { \n background: #ffffff; \n color: #0b1a29;\n}\n.y-msg--warning { \n background: #ffffff; \n color: #0b1a29;\n}\n.y-msg--error { \n background: #ffffff; \n color: #0b1a29;\n}\n\n@media (prefers-color-scheme: dark) {\n .y-msg { \n background: #1f2937; \n color: #ffffff;\n border-color: rgba(148, 163, 184, 0.2);\n border-left-width: 3px;\n }\n .y-msg--success { \n background: #1f2937; \n color: #ffffff;\n border-left-color: #047B5D;\n }\n .y-msg--warning { \n background: #1f2937; \n color: #ffffff;\n border-left-color: #FFB800;\n }\n .y-msg--error { \n background: #1f2937; \n color: #ffffff;\n border-left-color: #C41E3A;\n }\n}\n\n/* 进入/离开动效(自然惯性:更慢进入,稍快离开) */\n.y-msg-fade-enter-from { opacity: 0; transform: translate(-50%, -18px) scale(0.972); }\n.y-msg-fade-enter-active { transition: opacity 360ms cubic-bezier(0.22, 1, 0.36, 1), transform 360ms cubic-bezier(0.22, 1, 0.36, 1); }\n.y-msg-fade-leave-active { transition: opacity 200ms cubic-bezier(0.4, 0, 0.2, 1), transform 220ms cubic-bezier(0.4, 0, 0.2, 1); }\n.y-msg-fade-leave-to { opacity: 0; transform: translate(-50%, -10px) scale(0.982); }\n\n/* 离场节点固定 top,不参与 top 过渡,仅做自身淡出/轻微位移,避免与重排叠加 */\n.y-msg.is-leaving { transition-property: opacity, transform; pointer-events: none; }\n\n@media (prefers-reduced-motion: reduce) {\n .y-msg, .y-msg-fade-enter-active, .y-msg-fade-leave-active { transition: none; }\n}\n</style>\n\n\n","import { createVNode, render } from 'vue'\nimport YMessageToast from './ymessageToast.vue'\n\nlet seed = 1\nconst GAP = 12\ntype InstanceItem = { id: number; el: HTMLElement; vm: any; height: number; leaving?: boolean }\nconst instances: Array<InstanceItem> = []\n\ntype YMessageType = 'success' | 'warning' | 'error'\n\ninterface MessageOptions {\n type?: YMessageType\n message: string\n duration?: number\n closable?: boolean\n}\n\nfunction calcOffset(): number {\n let offset = 20\n instances.forEach(inst => { offset += inst.height + GAP })\n return offset\n}\n\nfunction close(id: number) {\n const index = instances.findIndex(i => i.id === id)\n if (index === -1) return\n const { el } = instances[index]\n const node = el.firstElementChild as HTMLElement | null\n // 标记离场,锁定自身 top,避免与重排上移动画叠加造成闪烁\n if (node) {\n const computedTop = window.getComputedStyle(node).top\n node.style.top = computedTop\n node.classList.add('is-leaving')\n // 同步触发离场过渡(添加离场类后,不再参与 top 过渡)\n node.style.willChange = 'opacity, transform'\n }\n instances[index].leaving = true\n // 先让其他实例平滑上移,跳过离场中的实例\n updatePositions()\n // 等待过渡完成再卸载(避免闪断)\n const LEAVE_MS = 260\n setTimeout(() => {\n render(null, el)\n el.parentNode && el.parentNode.removeChild(el)\n const rmIndex = instances.findIndex(i => i.id === id)\n if (rmIndex !== -1) instances.splice(rmIndex, 1)\n updatePositions()\n }, LEAVE_MS)\n}\n\nfunction show(options: MessageOptions) {\n const id = seed++\n const el = document.createElement('div')\n document.body.appendChild(el)\n\n const vm = createVNode(YMessageToast, {\n id,\n type: options.type || 'success',\n message: options.message,\n duration: options.duration ?? 2500,\n offset: calcOffset(),\n zIndex: 3000 + id,\n closable: options.closable ?? false,\n onClose: (cid: number) => close(cid),\n })\n\n render(vm, el)\n\n const initialHeight = (el.firstElementChild as HTMLElement)?.offsetHeight || 0\n instances.push({ id, el, vm, height: initialHeight, leaving: false })\n updatePositions()\n\n // 等待一帧让过渡进入可见后,重新测量实际高度,避免初始为 0 导致重叠\n requestAnimationFrame(() => {\n const node = el.firstElementChild as HTMLElement | null\n if (!node) return\n const realHeight = node.offsetHeight || initialHeight || 0\n const inst = instances.find(i => i.id === id)\n if (inst) {\n inst.height = realHeight\n updatePositions()\n }\n })\n\n return { close: () => close(id) }\n}\n\nexport const YMessage = {\n success(message: string, durationOrOpts?: number | Omit<MessageOptions,'type'|'message'>) {\n const opts = typeof durationOrOpts === 'number' ? { duration: durationOrOpts } : (durationOrOpts || {})\n return show({ ...opts, type: 'success', message })\n },\n warning(message: string, durationOrOpts?: number | Omit<MessageOptions,'type'|'message'>) {\n const opts = typeof durationOrOpts === 'number' ? { duration: durationOrOpts } : (durationOrOpts || {})\n return show({ ...opts, type: 'warning', message })\n },\n error(message: string, durationOrOpts?: number | Omit<MessageOptions,'type'|'message'>) {\n const opts = typeof durationOrOpts === 'number' ? { duration: durationOrOpts } : (durationOrOpts || {})\n return show({ ...opts, type: 'error', message })\n },\n}\n\nexport type { YMessageType, MessageOptions }\n\n// 自动挂载到全局,无需 import 即可使用\nif (typeof window !== 'undefined') {\n ;(window as any).YMessage = YMessage\n // 同时挂载为全局变量(在非严格模式下可用)\n if (typeof (globalThis as any).YMessage === 'undefined') {\n ;(globalThis as any).YMessage = YMessage\n }\n}\n\nfunction updatePositions() {\n let offset = 20\n instances.forEach(inst => {\n const node = inst.el.firstElementChild as HTMLElement | null\n if (!node) return\n // const currentTop = parseFloat(node.style.top || '20') || 20\n const targetTop = offset\n // const dy = targetTop - currentTop\n // 用 transform 做平滑上移,避免频繁 top 导致回流\n node.style.transform = `translate(-50%, ${targetTop}px)`\n // 仅在首次定位时写入 top 以保证初始位置\n if (!node.style.top) node.style.top = '0px'\n if (!inst.leaving) {\n offset += (node.offsetHeight || inst.height) + GAP\n } else {\n const currentHeight = node.offsetHeight || inst.height\n offset += currentHeight + GAP\n }\n })\n}\n\n\n","<template>\n <div :class=\"['hint-tag-wrapper', `hint-tag-wrapper-${position}`]\">\n <transition name=\"hint-slide\">\n <div \n v-show=\"isExpanded\" \n :class=\"['hint-tag', `hint-tag-${position}`]\"\n :style=\"{ \n width: position === 'top' || position === 'bottom' ? 'auto' : width,\n borderColor: borderColor\n }\"\n >\n <div class=\"hint-tag-content\">\n <slot>{{ content }}</slot>\n </div>\n <div class=\"hint-tag-toggle\" @click=\"toggle\">\n <svg \n class=\"hint-tag-icon\"\n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path \n d=\"M15 18L9 12L15 6\" \n stroke=\"currentColor\" \n stroke-width=\"2\" \n stroke-linecap=\"round\" \n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n </div>\n </transition>\n \n <!-- 收起后的小按钮 -->\n <transition name=\"hint-button-fade\">\n <div \n v-show=\"!isExpanded\" \n :class=\"['hint-tag-button', `hint-tag-button-${position}`]\"\n @click=\"toggle\"\n :title=\"tooltip || content\"\n >\n <svg \n class=\"hint-tag-button-icon\" \n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path \n d=\"M9 18L15 12L9 6\" \n stroke=\"currentColor\" \n stroke-width=\"2\" \n stroke-linecap=\"round\" \n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n </transition>\n </div>\n</template>\n\n<script lang=\"ts\" setup>\nimport { ref, inject, onMounted, onUnmounted, watch } from 'vue'\n\ninterface Props {\n content?: string\n position?: 'top' | 'right' | 'bottom' | 'left'\n defaultExpanded?: boolean\n width?: string\n tooltip?: string\n borderColor?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n content: '',\n position: 'right',\n defaultExpanded: true,\n width: '280px',\n tooltip: '',\n borderColor: '#00a8e8'\n})\n\nconst isExpanded = ref(props.defaultExpanded)\n\nconst toggle = () => {\n isExpanded.value = !isExpanded.value\n}\n\n// 收起方法(用于批量收起)\nconst collapse = () => {\n if (isExpanded.value) {\n isExpanded.value = false\n }\n}\n\n// 展开方法(用于批量展开)\nconst expand = () => {\n if (!isExpanded.value) {\n isExpanded.value = true\n }\n}\n\n// 暴露方法供外部调用\ndefineExpose({\n toggle,\n isExpanded,\n collapse,\n expand\n})\n\n// 尝试注册到父级 ytable 组件\nconst registerHintTag = inject<(instance: any) => void>('registerHintTag', null)\nconst unregisterHintTag = inject<(instance: any) => void>('unregisterHintTag', null)\nconst notifyHintTagStateChange = inject<() => void>('notifyHintTagStateChange', null)\n\n// 创建实例对象用于注册\nconst instance = {\n collapse,\n expand,\n toggle,\n get isExpanded() {\n return isExpanded.value\n }\n}\n\n// 监听状态变化,通知父组件更新\nwatch(() => isExpanded.value, () => {\n if (notifyHintTagStateChange) {\n notifyHintTagStateChange()\n }\n})\n\nonMounted(() => {\n if (registerHintTag) {\n registerHintTag(instance)\n }\n})\n\nonUnmounted(() => {\n if (unregisterHintTag) {\n unregisterHintTag(instance)\n }\n})\n</script>\n\n<style scoped lang=\"less\">\n.hint-tag-wrapper {\n display: inline-block;\n position: relative;\n vertical-align: middle;\n margin-left: 4px;\n z-index: 1000;\n pointer-events: none;\n}\n\n.hint-tag {\n position: absolute;\n background: #ffffff;\n color: #333333;\n border-radius: 6px;\n border: 1px solid;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n display: flex;\n align-items: stretch;\n font-size: 12px;\n white-space: nowrap;\n pointer-events: auto;\n \n &.hint-tag-right {\n left: 0;\n top: 50%;\n transform: translateY(-50%);\n flex-direction: row;\n }\n \n &.hint-tag-left {\n right: 0;\n top: 50%;\n transform: translateY(-50%);\n flex-direction: row-reverse;\n }\n \n &.hint-tag-top {\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%);\n flex-direction: column-reverse;\n margin-bottom: 4px;\n }\n \n &.hint-tag-bottom {\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n flex-direction: column;\n margin-top: 4px;\n }\n}\n\n.hint-tag-content {\n flex: 1;\n padding: 6px 10px;\n line-height: 1.5;\n max-height: 150px;\n overflow-y: auto;\n white-space: normal;\n word-break: break-word;\n \n &::-webkit-scrollbar {\n width: 4px;\n }\n \n &::-webkit-scrollbar-track {\n background: #f3f4f6;\n border-radius: 4px;\n }\n \n &::-webkit-scrollbar-thumb {\n background: #d1d5db;\n border-radius: 4px;\n \n &:hover {\n background: #9ca3af;\n }\n }\n}\n\n.hint-tag-toggle {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 6px;\n cursor: pointer;\n background: #f3f4f6;\n transition: background 0.2s ease;\n flex-shrink: 0;\n color: #666666;\n \n &:hover {\n background: #e5e7eb;\n }\n \n .hint-tag-right & {\n border-radius: 0 6px 6px 0;\n }\n \n .hint-tag-left & {\n border-radius: 6px 0 0 6px;\n }\n \n .hint-tag-top & {\n border-radius: 6px 6px 0 0;\n }\n \n .hint-tag-bottom & {\n border-radius: 0 0 6px 6px;\n }\n}\n\n.hint-tag-icon {\n width: 16px;\n height: 16px;\n transition: transform 0.2s ease;\n \n .hint-tag-right & {\n transform: rotate(0deg); // 向左箭头(展开状态,点击后收起)\n }\n \n .hint-tag-left & {\n transform: rotate(180deg); // 向右箭头(展开状态,点击后收起)\n }\n \n .hint-tag-top & {\n transform: rotate(-90deg); // 向上箭头(展开状态,点击后收起)\n }\n \n .hint-tag-bottom & {\n transform: rotate(90deg); // 向下箭头(展开状态,点击后收起)\n }\n}\n\n.hint-tag-button {\n width: 20px;\n height: 20px;\n background: #ffffff;\n color: #666666;\n border: 1px solid #e5e7eb;\n border-radius: 50%;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);\n transition: transform 0.2s ease, box-shadow 0.2s ease, color 0.2s ease;\n pointer-events: auto;\n vertical-align: middle;\n \n &:hover {\n color: #333333;\n transform: scale(1.1);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n }\n}\n\n.hint-tag-button-icon {\n width: 12px;\n height: 12px;\n transition: transform 0.2s ease;\n \n .hint-tag-button-right & {\n transform: rotate(0deg); // 收起状态,点击后展开,显示→\n }\n \n .hint-tag-button-left & {\n transform: rotate(180deg); // 收起状态,点击后展开,显示←\n }\n \n .hint-tag-button-top & {\n transform: rotate(-90deg); // 收起状态,点击后展开,显示↑\n }\n \n .hint-tag-button-bottom & {\n transform: rotate(90deg); // 收起状态,点击后展开,显示↓\n }\n}\n\n// 动画效果\n.hint-slide-enter-active,\n.hint-slide-leave-active {\n transition: all 0.3s ease;\n}\n\n.hint-tag-right {\n &.hint-slide-enter-from,\n &.hint-slide-leave-to {\n transform: translateY(-50%) translateX(-20px);\n opacity: 0;\n }\n}\n\n.hint-tag-left {\n &.hint-slide-enter-from,\n &.hint-slide-leave-to {\n transform: translateY(-50%) translateX(20px);\n opacity: 0;\n }\n}\n\n.hint-tag-top {\n &.hint-slide-enter-from,\n &.hint-slide-leave-to {\n transform: translateX(-50%) translateY(20px);\n opacity: 0;\n }\n}\n\n.hint-tag-bottom {\n &.hint-slide-enter-from,\n &.hint-slide-leave-to {\n transform: translateX(-50%) translateY(-20px);\n opacity: 0;\n }\n}\n\n.hint-button-fade-enter-active,\n.hint-button-fade-leave-active {\n transition: all 0.2s ease;\n}\n\n.hint-button-fade-enter-from,\n.hint-button-fade-leave-to {\n opacity: 0;\n transform: scale(0.5);\n}\n</style>\n","// 全局类型声明(确保 YMessage 全局类型可用)\ndeclare global {\n interface Window {\n YMessage: {\n success(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n warning(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n error(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n }\n }\n \n // 允许在全局作用域直接使用 YMessage(非严格模式)\n var YMessage: {\n success(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n warning(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n error(message: string, opts?: { duration?: number; closable?: boolean }): { close: () => void }\n }\n}\n\n// 导出所有组件\nexport { default as YButton } from './components/ybutton.vue'\nexport { default as YInput } from './components/yinput.vue'\nexport { default as YTable } from './components/ytable.vue'\nexport { default as YSelect } from './components/yselect.vue'\nexport { default as YPagination } from './components/ypagination.vue'\nexport { default as YBadge } from './components/ybadge.vue'\nexport { default as YDialog } from './components/ydialog.vue'\nexport { default as YPopover } from './components/ypopover.vue'\nexport { default as YTime } from './components/ytime.vue'\nexport { default as YSwitch } from './components/yswitch.vue'\nexport { default as YImage } from './components/yimage.vue'\nexport { default as YDropdown } from './components/ydropdown.vue'\nexport { default as YDrawer } from './components/ydrawer.vue'\nexport { default as YTree } from './components/ytree.vue'\nexport { default as QueryEncapsulation } from './components/QueryEncapsulation.vue'\n\n// 导出 YMessage\nexport { YMessage } from './components/ymessage/ymessage'\nexport type { YMessageType, MessageOptions } from './components/ymessage/ymessage'\n\n// 导出类型\nexport type { SwitchProps } from './components/yswitch.vue'\nexport type { SelectOption } from './components/yselect.vue'\nexport type { PaginationProps } from './components/ypagination.vue'\n\n// 安装函数(用于 Vue.use())\nimport type { App } from 'vue'\nimport YButton from './components/ybutton.vue'\nimport YInput from './components/yinput.vue'\nimport YTable from './components/ytable.vue'\nimport YSelect from './components/yselect.vue'\nimport YPagination from './components/ypagination.vue'\nimport YBadge from './components/ybadge.vue'\nimport YDialog from './components/ydialog.vue'\nimport YPopover from './components/ypopover.vue'\nimport YTime from './components/ytime.vue'\nimport YSwitch from './components/yswitch.vue'\nimport YImage from './components/yimage.vue'\nimport YDropdown from './components/ydropdown.vue'\nimport YDrawer from './components/ydrawer.vue'\nimport YTree from './components/ytree.vue'\nimport HintTag from './components/hintTag.vue'\nimport QueryEncapsulation from './components/QueryEncapsulation.vue'\nimport { YMessage } from './components/ymessage/ymessage'\n\nconst components = {\n YButton,\n YInput,\n YTable,\n YSelect,\n YPagination,\n YBadge,\n YDialog,\n YPopover,\n YTime,\n YSwitch,\n YImage,\n YDropdown,\n YDrawer,\n YTree,\n QueryEncapsulation,\n HintTag,\n}\n\nexport default {\n install(app: App) {\n // 注册所有组件\n Object.keys(components).forEach((key) => {\n app.component(key, components[key as keyof typeof components])\n })\n \n // 将 YMessage 挂载到 Vue 全局属性,方便在模板中使用 this.$message\n app.config.globalProperties.$message = YMessage\n \n // 确保挂载到 window 对象,实现全局直接使用(无需 import)\n if (typeof window !== 'undefined') {\n ;(window as any).YMessage = YMessage\n }\n },\n}\n\n"],"names":["props","__props","emit","__emit","onClick","ev","groupPositionClass","computed","isGroup","onGroupItemClick","item","_openBlock","_createElementBlock","_hoisted_3","_Fragment","_renderList","index","_a","$event","_createElementVNode","_hoisted_5","_hoisted_6","_cache","_hoisted_7","_hoisted_8","_toDisplayString","_hoisted_2","_renderSlot","_ctx","inputRef","ref","previousValue","hasChanged","isFocused","inputPlaceholder","watch","val","onInput","target","onFocus","onBlur","current","minVal","onEnter","onPaste","_normalizeClass","currentPage","pageSize","selectedItems","selectedRowKey","expandedKeys","tableMaxHeight","tableContainer","headerRef","bodyWrapRef","bodyTableRef","headerColWidths","headerWidthMap","defaultHeaderHeight","hintTagInstances","hasHintTags","allHintsExpanded","hintTagStateUpdateTrigger","expandedCount","instance","collapsedCount","registerHintTag","unregisterHintTag","collapseAllHints","expandAllHints","toggleAllHints","notifyHintTagStateChange","provide","autoColumnKeys","col","normalizeWidth","getAutoColumnWidth","vTrackRef","vScroll","isDragging","dragStartY","dragStartScrollTop","scrollbarWidth","width","trimmed","parseWidthNumber","normalized","parsed","totalTableColumns","count","filteredData","keyword","field","value","getNestedValue","pagedData","isAllVisibleSelected","visibleKeys","getRowKey","isRowDisabled","key","isPartiallySelected","selectedCount","isAllVisibleDisabled","shouldDisableNext","fixedLeftWidths","widths","cumulativeWidth","i","parsedWidth","fixedRightWidths","rightFixedColumns","getFixedColumnIndex","columnIndex","fixed","isRowExpanded","toggleRowExpand","obj","path","getColumnClass","column","isHeader","classes","getColumnStyle","style","normalizedWidth","autoWidth","fixedIndex","leftOffset","rightOffset","formatCellValue","toggleSelect","rowData","rowIndex","x","toggleSelectAllVisible","union","clearSelection","handleRowClick","k","isRowSelected","newVal","currentSet","newSet","handlePageChange","page","handlePageSizeChange","size","next","calculateTableMaxHeight","nextTick","containerRect","viewportHeight","containerTop","headerElement","headerHeight","paginationHeight","paginationElement","bulkBarElement","bulkBarHeight","reservedHeight","availableHeight","maxHeight","tableContent","isSyncingScroll","syncHeaderScroll","syncBodyScroll","updateVirtualScrollbar","wrap","contentHeight","viewport","scrollTop","needVBar","minThumb","ratio","trackHeight","thumbHeight","maxThumbTop","maxScrollTop","onThumbMousemove","e","scrollDelta","onThumbMouseup","measureAutoColumnWidths","w","fallback","firstRow","startIndex","tds","td","measured","stored","_b","handleResize","updateHeaderScrollbarGutter","syncSelectedHeaderHeight","nextWidths","nextMap","idx","currentKeys","measureDefaultHeaderHeight","headerTable","firstNormalTh","selectedHeader","wrapper","onMounted","resizeObserver","onUnmounted","lastScrollbarWidth","currentScrollbarWidth","bodyTable","_createVNode","_Transition","_hoisted_1","_component_YButton","_hoisted_4","_hoisted_9","_hoisted_10","_hoisted_11","_normalizeStyle","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_16","$slots","_hoisted_18","colIndex","_hoisted_19","_hoisted_20","_hoisted_21","_hoisted_22","_hoisted_24","_createBlock","_component_YPagination","isOpen","hoveredIndex","optionsContainer","triggerElement","selectContainer","shouldOpenUpward","inputElement","searchQuery","selectedOption","option","getOptionValue","selectedOptions","values","selectedLabel","getOptionLabel","displayedOptions","query","opt","label","portalDropdownStyle","trigger","rect","calculateDropdownPosition","triggerRect","dropdownHeight","dropdownBottom","dropdownTop","shouldOpenDown","canOpenUp","getOptionKey","isSelected","isOptionDisabled","toggleDropdown","closeDropdown","openDropdown","scrollToSelected","selectOption","_index","currentValues","optionValue","valueIndex","handleClear","cleared","removeTag","event","moveHover","delta","total","attempts","scrollHoverIntoView","selectHovered","selectedElement","el","handleClickOutside","_withModifiers","_createTextVNode","_Teleport","pageSizeOptions","goToPage","onPagerGroupClick","action","_component_YSelect","toneClass","ariaLabel","text","tone","prog","progMap","toneMap","visible","v","panelRef","panelStyle","onMaskClick","close","onEsc","onKeydown","popoverRef","triggerRef","contentRef","contentRect","arrowPosition","openTimer","closeTimer","contentStyle","top","left","calculatePosition","arrowStyle","triggerWidth","triggerHeight","triggerTop","triggerLeft","contentWidth","viewportWidth","show","clearTimers","doShow","updatePosition","hide","doHide","calculateArrowPosition","triggerCenterX","contentLeft","arrowOffset","triggerCenterY","contentTop","handleTriggerClick","handleMouseEnter","handleMouseLeave","handleContentMouseEnter","handleContentMouseLeave","__expose","activeShortcutIndex","selectedShortcutIndex","pendingValue","dropdown","dropdownPosition","startCalendar","endCalendar","ensureDifferentMonths","startTime","endTime","nextMonth","ensureDifferentMonthsReverse","prevMonth","weekDays","tempStartDate","tempEndDate","parseDate","date","formatDateToString","year","month","day","hours","minutes","seconds","formatDateToTimestamp","normalizeValue","formatOutputValue","formatYearMonth","isSameDay","date1","date2","isDateInRange","start","end","findMatchingShortcutIndex","currentValue","normalizedValue","shortcutValue","currentStart","currentEnd","shortcutStart","shortcutEnd","generateCalendarDays","firstDay","lastDay","firstDayWeek","daysInMonth","days","today","prevDaysCount","remainingDays","weeks","updateValue","formattedValue","dropdownRect","spaceBelow","spaceAbove","spaceRight","dropdownWidth","triggerEl","dropdownEl","handleTriggerKeydown","focusFirstShortcut","handleDropdownKeydown","handleShortcutKeydown","focusShortcut","selectShortcut","handleShortcutMouseEnter","handleShortcutMouseLeave","shortcutElement","shortcut","s","selectDate","type","selectedDate","endDate","getDateCellClass","confirmSelection","resetSelection","startCalendarDays","endCalendarDays","displayText","formatDate","startStr","endStr","dropdownClasses","hasValue","canConfirm","newValue","startDate","handleClearClick","changeMonth","direction","newDate","_hoisted_15","_hoisted_17","week","weekIndex","dayIndex","_hoisted_23","_hoisted_25","_hoisted_26","_hoisted_27","_hoisted_28","_hoisted_30","_hoisted_31","_hoisted_32","rootEl","isChecked","switchStyle","onToggle","containerRef","imageRef","previewImageRef","isLoaded","isLoading","hasError","isInView","showPreview","imgSrc","previewSrc","zoomLevel","isMounted","originalBodyStyle","RADIUS_TOKEN_MAP","containerClass","radiusValue","radiusStyle","imageClass","imageStyle","resolvedPreviewSrc","getScrollbarWidth","scrollDiv","lockBodyScroll","unlockBodyScroll","observer","setupIntersectionObserver","entries","entry","handleLoad","handleError","retryLoad","getPreviewUrl","handleErrorClick","handlePreview","previewUrl","img","timeoutId","isHandled","showPreviewModal","closePreview","handleWheel","zoomDirection","newZoom","nv","_vShow","dropdownRef","hideTimer","menuClass","menuStyle","showDropdown","hideDropdown","menu","menuRect","absoluteTop","absoluteLeft","menuWidth","menuHeight","transitionName","roundedClass","DEPT_ICON_URL","PERSON_ICON_URL","treeData","store","effectiveRestrictLevel","getNodeKey","node","getNodeLabel","isEmployeeNode","getNodeIcon","rootNode","dept","person","button","childStyleIcon","isChildStyleNode","hasChildren","children","getNodeChildren","getNodeDepth","targetNode","currentDepth","child","depth","isNodeExpanded","nodeKey","isNodeChecked","checkedChildren","indeterminateChildren","isNodeIndeterminate","isNodeCurrent","isNodeHighlighted","handleCheckClick","newCheckedState","currentExpandedKeys","cascadeChildren","check","childKey","preventAutoExpandFourthLevel","updateAllParentNodes","_node","handleExpandClick","allNodes","collectAllNodes","nodes","updateNodeParents","handleNodeClick","data","nodeComponent","isChildStyle","handleNodeContextMenu","keys","restrictLevel","getDepthByKey","targetKey","level","n","d","collectKeysToDepth","maxDepth","newExpandedKeys","filtered","expandAllNodes","collectExpandableKeys","allExpandableKeys","expandNodesWithCheckedPermissions","findPathsToCheckedNodes","parentPath","currentPath","checkedKeys","expandableKeys","highlightAndExpandByIds","ids","findPathToKey","nk","newPath","p","targetIds","keysToExpand","targetId","clearHighlights","clearCurrentNode","grandChild","greatGrandChild","_hoisted_33","_hoisted_34","_hoisted_36","_hoisted_37","greatGreatGrandChild","_hoisted_40","_hoisted_42","_hoisted_43","_hoisted_45","isExpanded","searchForm","reactive","autoTriggerTypes","autoSearchTimer","visibleFields","displayedFields","hasHiddenFields","getFieldComponent","YSelect","YTime","YSwitch","YInput","updateFieldValue","f","handleFieldChange","scheduleAutoSearch","handleSwitchChange","handleSearch","searchParams","filterEmptyParams","formattedParams","formatSearchParams","rawParams","handleReset","toggleExpanded","getFieldListeners","handleInputQuickSearch","params","rawValue","formatted","startKey","endKey","initFormData","_c","_d","_e","onBeforeUnmount","_TransitionGroup","_resolveDynamicComponent","_mergeProps","_toHandlers","YButton","timer","remainingTime","startTimer","clearTimer","duration","elapsed","onAfterLeave","seed","GAP","instances","calcOffset","offset","inst","id","computedTop","updatePositions","render","rmIndex","options","vm","createVNode","YMessageToast","cid","initialHeight","realHeight","YMessage","message","durationOrOpts","targetTop","currentHeight","toggle","collapse","expand","inject","components","YTable","YPagination","YBadge","YDialog","YPopover","YImage","YDropdown","YDrawer","YTree","QueryEncapsulation","HintTag","app"],"mappings":"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"}
|