@rft-rc/recycle-ui 0.0.2 → 0.0.3

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.
Files changed (42) hide show
  1. package/README.md +38 -34
  2. package/dist/components/button/index.vue.d.ts +18 -6
  3. package/dist/components/button/index.vue.d.ts.map +1 -1
  4. package/dist/components/calendar/index.d.ts +5 -0
  5. package/dist/components/calendar/index.d.ts.map +1 -0
  6. package/dist/components/calendar/index.vue.d.ts +64 -0
  7. package/dist/components/calendar/index.vue.d.ts.map +1 -0
  8. package/dist/components/calendar/panel-content.vue.d.ts +38 -0
  9. package/dist/components/calendar/panel-content.vue.d.ts.map +1 -0
  10. package/dist/components/card/index.vue.d.ts +2 -2
  11. package/dist/components/card/index.vue.d.ts.map +1 -1
  12. package/dist/components/dropdown/index.d.ts +8 -0
  13. package/dist/components/dropdown/index.d.ts.map +1 -0
  14. package/dist/components/dropdown/index.vue.d.ts +49 -0
  15. package/dist/components/dropdown/index.vue.d.ts.map +1 -0
  16. package/dist/components/dropdown/item.vue.d.ts +24 -0
  17. package/dist/components/dropdown/item.vue.d.ts.map +1 -0
  18. package/dist/components/dropdown/menu.vue.d.ts +32 -0
  19. package/dist/components/dropdown/menu.vue.d.ts.map +1 -0
  20. package/dist/components/dropdown/types.d.ts +2 -0
  21. package/dist/components/dropdown/types.d.ts.map +1 -0
  22. package/dist/components/icon/index.d.ts +1 -1
  23. package/dist/components/icon/index.vue.d.ts +1 -1
  24. package/dist/components/icon/index.vue.d.ts.map +1 -1
  25. package/dist/components/input/index.d.ts +5 -0
  26. package/dist/components/input/index.d.ts.map +1 -0
  27. package/dist/components/input/index.vue.d.ts +135 -0
  28. package/dist/components/input/index.vue.d.ts.map +1 -0
  29. package/dist/components/popup/index.d.ts +5 -0
  30. package/dist/components/popup/index.d.ts.map +1 -0
  31. package/dist/components/popup/index.vue.d.ts +70 -0
  32. package/dist/components/popup/index.vue.d.ts.map +1 -0
  33. package/dist/components/search-area/index.vue.d.ts +51 -11
  34. package/dist/components/search-area/index.vue.d.ts.map +1 -1
  35. package/dist/index.cjs +1 -1
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.ts +9 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.mjs +2105 -483
  40. package/dist/index.mjs.map +1 -1
  41. package/dist/style.css +1 -1
  42. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/components/button/index.vue","../src/components/button/index.ts","../src/components/descriptions/item.vue","../src/components/descriptions/index.vue","../src/components/descriptions/index.ts","../src/components/card/index.vue","../src/components/card/index.ts","../src/components/toast/index.vue","../src/components/toast/index.ts","../src/components/message/index.vue","../src/components/message/index.ts","../src/components/icon/index.vue","../src/components/icon/index.ts","../src/components/search-area/index.vue","../src/components/search-area/index.ts","../src/index.ts"],"sourcesContent":["<template>\r\n <button\r\n class=\"rc-button\"\r\n :class=\"[`rc-button--${type}`, `rc-button--${size}`, { 'is-plain': plain, 'is-block': block, 'is-disabled': disabled, 'is-loading': loading }]\"\r\n :style=\"{ borderRadius: radius }\"\r\n :disabled=\"disabled || loading\"\r\n @click=\"onClick\"\r\n >\r\n <span v-if=\"loading\" class=\"rc-button__spinner\" />\r\n <slot>{{ label }}</slot>\r\n </button>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from 'vue';\r\ntype ButtonType = 'default' | 'primary' | 'success' | 'warning' | 'danger';\r\ntype ButtonSize = 'mini' | 'small' | 'medium' | 'large';\r\n\r\ninterface Props {\r\n type?: ButtonType;\r\n size?: ButtonSize;\r\n plain?: boolean;\r\n block?: boolean;\r\n /** 按钮文本,提供时可不写默认插槽 */\r\n label?: string;\r\n /** 圆角;number 代表 px,string 支持百分比等写法(如 '50%')。也兼容 boolean,true 表示大圆角。 */\r\n round?: number | string | boolean;\r\n disabled?: boolean;\r\n loading?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n type: 'default',\r\n size: 'medium',\r\n plain: false,\r\n block: false,\r\n label: '',\r\n round: 6,\r\n disabled: false,\r\n loading: false,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n (e: 'click', ev: MouseEvent): void\r\n}>();\r\n\r\nconst onClick = (ev: MouseEvent) => {\r\n if (!props.disabled && !props.loading) emit('click', ev);\r\n};\r\n\r\nconst radius = computed(() => {\r\n const v = props.round;\r\n if (typeof v === 'boolean') return v ? '999px' : '6px';\r\n if (typeof v === 'number') return `${v}px`;\r\n return String(v);\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.rc-button {\r\n --rc-primary: #1677ff;\r\n --rc-success: #00b578;\r\n --rc-warning: #ff8f1f;\r\n --rc-danger: #ff3141;\r\n --rc-text: #323233;\r\n --rc-border: #dcdee0;\r\n --rc-white: #ffffff;\r\n\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 36px;\r\n padding: 0 16px;\r\n border: 1px solid var(--rc-border);\r\n border-radius: 6px;\r\n background: var(--rc-white);\r\n color: var(--rc-text);\r\n cursor: pointer;\r\n user-select: none;\r\n transition: all .2s ease;\r\n\r\n &.is-disabled { cursor: not-allowed; opacity: .6; }\r\n &.is-block { display: flex; width: 100%; }\r\n &.is-plain { background: var(--rc-white); }\r\n &.is-loading { opacity: .85; }\r\n\r\n &__spinner {\r\n width: 14px;\r\n height: 14px;\r\n margin-right: 6px;\r\n border: 2px solid currentColor;\r\n border-top-color: transparent;\r\n border-radius: 50%;\r\n animation: rc-spin 0.8s linear infinite;\r\n }\r\n\r\n &--primary { background: var(--rc-primary); color: var(--rc-white); border-color: var(--rc-primary); }\r\n &--success { background: var(--rc-success); color: var(--rc-white); border-color: var(--rc-success); }\r\n &--warning { background: var(--rc-warning); color: var(--rc-white); border-color: var(--rc-warning); }\r\n &--danger { background: var(--rc-danger); color: var(--rc-white); border-color: var(--rc-danger); }\r\n\r\n &--mini { height: 24px; padding: 0 8px; font-size: 12px; }\r\n &--small { height: 28px; padding: 0 10px; font-size: 13px; }\r\n &--medium { height: 36px; padding: 0 16px; font-size: 14px; }\r\n &--large { height: 44px; padding: 0 20px; font-size: 16px; }\r\n}\r\n\r\n@keyframes rc-spin { to { transform: rotate(360deg) } }\r\n</style>\r\n\r\n\r\n\r\n","import type { App } from 'vue';\r\nimport Button from './index.vue';\r\n\r\n// 组件名使用全小写,以 <rc-button> 形式在模板中使用\r\n(Button as any).name = 'rc-button';\r\n\r\nexport function install(app: App) {\r\n app.component((Button as any).name, Button);\r\n return app;\r\n}\r\n\r\n\r\nexport default Button;\r\n","<template>\n <div class=\"rc-desc-item\" :style=\"{ width: computedWidth, flex: `0 0 ${computedWidth}` }\">\n <div class=\"rc-desc-item__label\" :style=\"labelStyle\">\n <slot name=\"label\">\n {{ label }}\n </slot>\n </div>\n <div class=\"rc-desc-item__value\">\n <slot>\n {{ value }}\n </slot>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, inject, Ref } from 'vue';\n\ndefineOptions({ name: 'rc-descriptions-item' });\n\nconst props = withDefaults(defineProps<{\n label?: string | number;\n value?: any;\n labelWidth?: string | number;\n /** 跨越的列数,默认 1,可传字符串数字 */\n span?: number | string;\n}>(), {\n label: '',\n value: '',\n labelWidth: '',\n span: 1,\n});\n\nconst providedWidth = inject<Ref<string>>('rcDescItemWidth', undefined as unknown as Ref<string>);\nconst providedSingleWidth = inject<Ref<string> | string>('rcDescSingleWidth', '' as unknown as Ref<string>);\nconst providedGap = inject<string>('rcDescGap', '0px');\nconst providedGapPx = inject<Ref<number> | number>('rcDescGapPx', 0 as unknown as Ref<number>);\nconst providedColCount = inject<Ref<number> | number>('rcDescColCount', 1 as unknown as Ref<number>);\nconst providedLabelWidth = inject<Ref<string> | string>('rcDescLabelWidth', '' as unknown as Ref<string>);\n\nconst spanNum = computed(() => {\n const n = typeof props.span === 'string' ? parseInt(props.span, 10) : props.span;\n const max = typeof (providedColCount as any)?.value === 'number' ? (providedColCount as any).value : (providedColCount as any);\n const safe = !Number.isNaN(n as number) && (n as number) > 0 ? (n as number) : 1;\n return Math.min(safe, max || 1);\n});\n\nconst computedWidth = computed(() => {\n const n = typeof (providedColCount as any)?.value === 'number' ? (providedColCount as any).value : (providedColCount as any);\n const gapPx = typeof (providedGapPx as any)?.value === 'number' ? (providedGapPx as any).value : (providedGapPx as any);\n const k = spanNum.value;\n if (!n || n <= 1) return '100%';\n if (k >= n) return '100%';\n // 展开为单层 calc:((100% - (n-1)*gap) * k / n + (k-1)*gap)\n const totalGap = (n - 1) * gapPx;\n const interGap = (k - 1) * gapPx;\n return `calc((100% - ${totalGap}px) * ${k} / ${n} + ${interGap}px)`;\n});\n\nconst labelStyle = computed(() => {\n const injected = typeof (providedLabelWidth as any)?.value === 'string'\n ? (providedLabelWidth as any).value\n : (providedLabelWidth as any);\n const w = props.labelWidth !== '' ? props.labelWidth : (injected || '');\n return w ? { width: typeof w === 'number' ? `${w}px` : String(w), flex: '0 0 auto' } : {};\n});\n</script>\n\n<style scoped>\n.rc-desc-item {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 6px 0;\n flex: 0 0 auto;\n}\n.rc-desc-item__label {\n color: #666;\n font-size: 14px;\n line-height: 22px;\n /* 不强制最小宽度,交由 label-width 控制 */\n min-width: 0;\n}\n.rc-desc-item__value {\n flex: 1 1 auto;\n font-size: 14px;\n line-height: 22px;\n}\n\n</style>\n\n\n","<template>\n <div class=\"rc-descriptions\">\n <div v-if=\"$slots.title || title\" class=\"rc-descriptions__title\">\n <slot name=\"title\">\n {{ title }}\n </slot>\n </div>\n <div class=\"rc-descriptions__body\" :style=\"{ gap: gapStyle }\" ref=\"wrapEl\">\n <template v-if=\"normalizedData.length\">\n <rcDescriptionsItem\n v-for=\"(it, idx) in normalizedData\"\n :key=\"idx\"\n :label=\"it.label\"\n :value=\"it.value\"\n :label-width=\"labelWidth\"\n />\n </template>\n <slot v-else />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, provide, ref, watchEffect } from 'vue';\nimport rcDescriptionsItem from './item.vue';\n\ndefineOptions({ name: 'rc-descriptions' });\n\ntype KeyMap = { key: string; value: string };\n\nconst props = withDefaults(defineProps<{\n title?: string;\n /** 每行展示的列数,支持数字或字符串数字 */\n column?: number | string;\n /** 列间距,支持数字(px)或字符串值,例如 '12px' */\n gap?: number | string;\n /** label 固定宽度,数字代表 px,也可直接传入 '120px' */\n labelWidth?: number | string | '';\n /** 直接通过数据渲染 */\n data?: Array<Record<string, any>>;\n /** data 的字段映射,如 { key: 'label', value: 'value' } */\n keyMap?: KeyMap;\n}>(), {\n column: 2,\n gap: 4,\n labelWidth: '',\n data: () => [],\n});\n\nconst wrapEl = ref<HTMLElement | null>(null);\nconst gapStyle = computed(() => (typeof props.gap === 'number' ? `${props.gap}px` : String(props.gap)));\nconst colCount = computed(() => {\n const n = typeof props.column === 'string' ? Number.parseInt(props.column as string, 10) : (props.column ?? 1);\n return !Number.isNaN(n) && n > 0 ? n : 1;\n});\n\n// compute child item width as percentage string or 'auto'\nconst itemWidth = ref<string>('100%');\nconst singleWidth = ref<string>('100%');\nwatchEffect(() => {\n const n = colCount.value;\n if (n <= 1) {\n itemWidth.value = '100%';\n singleWidth.value = '100%';\n } else {\n // subtract total horizontal gaps from 100%\n const gapPx = typeof props.gap === 'number' ? props.gap : parseFloat(String(props.gap)) || 0;\n const totalGap = (n - 1) * gapPx;\n const base = `calc((100% - ${totalGap}px) / ${n})`;\n singleWidth.value = base;\n itemWidth.value = base;\n }\n});\n\nprovide('rcDescItemWidth', itemWidth);\nprovide('rcDescSingleWidth', singleWidth);\nprovide('rcDescColCount', colCount);\nprovide('rcDescGapPx', computed(() => (typeof props.gap === 'number' ? props.gap : parseFloat(String(props.gap)) || 0)));\nconst labelWidthCss = computed(() => {\n if (props.labelWidth === '' || props.labelWidth === undefined) return '';\n return typeof props.labelWidth === 'number' ? `${props.labelWidth}px` : String(props.labelWidth);\n});\nprovide('rcDescLabelWidth', labelWidthCss);\nprovide('rcDescGap', computed(() => (typeof props.gap === 'number' ? `${props.gap}px` : String(props.gap))));\n\nconst normalizedData = computed(() => {\n const keyK = (props.keyMap?.key ?? 'label') as string;\n const keyV = (props.keyMap?.value ?? 'value') as string;\n if (!props.data?.length) return [];\n return props.data.map((it) => ({\n label: it?.[keyK],\n value: it?.[keyV],\n }));\n});\n\n</script>\n\n<style scoped>\n.rc-descriptions {\n width: 100%;\n}\n.rc-descriptions__title {\n font-weight: 600;\n font-size: 16px;\n margin: 0 0 12px 0;\n}\n.rc-description__row {\n display: contents;\n}\n.rc-descriptions__body {\n display: flex;\n flex-wrap: wrap;\n}\n\n</style>\n\n\n","import type { App } from 'vue';\r\nimport Descriptions from './index.vue';\r\nimport DescriptionsItem from './item.vue';\r\n\r\n(Descriptions as any).name = 'rc-descriptions';\r\n(DescriptionsItem as any).name = 'rc-descriptions-item';\r\n\r\nexport function install(app: App) {\r\n // 同时注册 kebab 与 PascalCase 名称,便于 <rc-descriptions>/<RcDescriptions> 使用\r\n app.component((Descriptions as any).name, Descriptions);\r\n app.component('RcDescriptions', Descriptions);\r\n app.component((DescriptionsItem as any).name, DescriptionsItem);\r\n app.component('RcDescriptionsItem', DescriptionsItem);\r\n return app;\r\n}\r\n\r\nexport const RcDescriptions = Descriptions;\r\nexport const RcDescriptionsItem = DescriptionsItem;\r\n\r\nexport default Descriptions;\r\n\r\n\r\n\r\n","<template>\n <div\n class=\"rc-card\"\n :class=\"[{ 'rc-card--bordered': bordered }]\"\n :style=\"wrapperStyle\"\n >\n <div\n v-if=\"$slots.title || title || $slots.status || status\"\n class=\"rc-card__top\"\n :style=\"{ backgroundColor: topBgColor || 'rgba(29, 133, 252, 0.05)' }\"\n >\n <div class=\"rc-card__title\">\n <slot name=\"title\">\n <span class=\"rc-card__title-text\">{{ title }}</span>\n </slot>\n </div>\n <div class=\"rc-card__status\" v-if=\"$slots.status || status\">\n <slot name=\"status\">\n <span class=\"rc-card__status-text\" :style=\"{ color: statusColor || 'var(--rc-primary)' }\">\n {{ status }}\n </span>\n </slot>\n </div>\n </div>\n\n <div class=\"rc-card__body\" :style=\"{ padding: bodyPadding, gap: bodyGap }\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div v-if=\"$slots.action\" class=\"rc-card__divider\" />\n\n <div v-if=\"$slots.action\" class=\"rc-card__action\">\n <slot name=\"action\" />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\ndefineOptions({ name: 'rc-card' });\n\ninterface Props {\n /** 卡片整体背景色,默认白色 */\n color?: string;\n /** 顶部色块背景色 */\n topBgColor?: string;\n /** 标题文本(可用 slot=\"title\" 自定义) */\n title?: string;\n /** 右侧状态文案(可用 slot=\"status\" 自定义) */\n status?: string;\n /** 状态文本颜色 */\n statusColor?: string;\n /** 圆角:数值代表 px,字符串可用百分比 */\n round?: number | string;\n /** 是否描边 */\n bordered?: boolean;\n /** 阴影强度:0/1/2/3... -> 转换为不同阴影强度 */\n elevation?: number;\n /** 内边距(CSS 值,如 '16px 12px') */\n padding?: string;\n /** 主体内容的垂直间距(px 或 CSS 字符串) */\n gap?: number | string;\n /** 宽度(px/百分比) */\n width?: string | number;\n /** 高度(px/百分比) */\n height?: string | number;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n color: 'var(--rc-white)',\n topBgColor: 'rgba(29, 133, 252, 0.05)',\n title: '',\n status: '',\n statusColor: 'var(--rc-primary)',\n round: 8,\n bordered: false,\n elevation: 2,\n padding: '16px',\n gap: 12,\n width: '100%',\n height: '',\n});\n\nconst wrapperStyle = computed(() => {\n const radius =\n typeof props.round === 'boolean'\n ? props.round\n ? '12px'\n : '0'\n : typeof props.round === 'number'\n ? `${props.round}px`\n : String(props.round);\n\n return {\n backgroundColor: props.color || 'var(--rc-white)',\n borderRadius: radius,\n boxShadow: shadowByLevel(props.elevation),\n width: toCssSize(props.width),\n height: toCssSize(props.height),\n } as Record<string, string>;\n});\n\nconst bodyPadding = computed(() => props.padding || '16px');\nconst bodyGap = computed(() =>\n typeof props.gap === 'number' ? `${props.gap}px` : String(props.gap)\n);\n\nfunction toCssSize(v?: string | number) {\n if (v === undefined || v === null || v === '') return '';\n return typeof v === 'number' ? `${v}px` : String(v);\n}\n\nfunction shadowByLevel(level: number) {\n if (!level || level <= 0) return 'none';\n // 简单的多层阴影(可按需微调)\n const base = 4 * level;\n return `0 ${Math.round(base / 2)}px ${base}px rgba(0,0,0,0.06), 0 ${Math.round(\n base / 4\n )}px ${Math.round(base / 2)}px rgba(0,0,0,0.04)`;\n}\n</script>\n\n<style scoped>\n.rc-card {\n --rc-white: #ffffff;\n --rc-border: #e5e6eb;\n --rc-primary: #1677ff;\n\n display: flex;\n flex-direction: column;\n width: 100%;\n border: 1px solid transparent;\n background: var(.rc-white);\n}\n.rc-card--bordered {\n border-color: var(--rc-border);\n}\n\n.rc-card__top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n}\n.rc-card__title {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.rc-card__title-text {\n font-weight: 600;\n font-size: 16px;\n color: #1d2129;\n}\n.rc-card__status-text {\n font-size: 14px;\n}\n.rc-card__body {\n display: flex;\n flex-direction: column;\n}\n.rc-card__divider {\n height: 1px;\n background: var(--rc-border);\n}\n.rc-card__action {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n}\n</style>\n\n\n","import type { App } from 'vue';\r\nimport Card from './index.vue';\r\n\r\n// 同时注册小写与驼峰,便于 <rc-card> / <RcCard> 两种写法\r\n(Card as any).name = 'rc-card';\r\nconst PascalName = 'RcCard';\r\n\r\nexport function install(app: App) {\r\n app.component((Card as any).name, Card);\r\n app.component(PascalName, Card);\r\n return app;\r\n}\r\n\r\nexport default Card;\r\n\r\n\r\n","<template>\r\n <teleport to=\"body\">\r\n <transition name=\"rc-toast-fade\" @after-leave=\"onAfterLeave\">\r\n <div v-if=\"visible\" class=\"rc-toast\" :class=\"[`rc-toast--${type}`]\">\r\n <div v-if=\"mask\" class=\"rc-toast__mask\" />\r\n <div class=\"rc-toast__content\">\r\n <div v-if=\"type === 'loading'\" class=\"rc-toast__spinner\" />\r\n <div v-else-if=\"type === 'success'\" class=\"rc-toast__icon rc-toast__icon--success\" />\r\n <div v-else-if=\"type === 'fail'\" class=\"rc-toast__icon rc-toast__icon--fail\" />\r\n <div class=\"rc-toast__text\">{{ message }}</div>\r\n </div>\r\n </div>\r\n </transition>\r\n </teleport>\r\n <slot />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { onMounted, onUnmounted, ref, watch, defineExpose } from 'vue';\r\n\r\nexport type ToastType = 'text' | 'success' | 'fail' | 'loading';\r\nexport interface ToastProps {\r\n message?: string;\r\n type?: ToastType;\r\n duration?: number;\r\n mask?: boolean;\r\n /** 服务端关闭回调,用于卸载容器 */\r\n onAfterLeave?: () => void;\r\n}\r\n\r\nconst props = withDefaults(defineProps<ToastProps>(), {\r\n message: '',\r\n type: 'text',\r\n duration: 2000,\r\n mask: false,\r\n});\r\n\r\nconst visible = ref(true);\r\nlet timer: any;\r\n\r\nfunction clearTimer() {\r\n if (timer) {\r\n clearTimeout(timer);\r\n timer = null;\r\n }\r\n}\r\n\r\nfunction close() {\r\n clearTimer();\r\n visible.value = false;\r\n}\r\n\r\ndefineExpose({ close });\r\n\r\nonMounted(() => {\r\n if (props.duration && props.duration > 0) {\r\n timer = setTimeout(() => {\r\n close();\r\n }, props.duration);\r\n }\r\n});\r\n\r\nonUnmounted(() => {\r\n clearTimer();\r\n});\r\n</script>\r\n\r\n<style scoped>\r\n.rc-toast {\r\n position: fixed;\r\n inset: 0;\r\n z-index: 9999;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n.rc-toast__mask {\r\n position: absolute;\r\n inset: 0;\r\n background: rgba(0, 0, 0, 0.35);\r\n pointer-events: auto;\r\n backdrop-filter: blur(1px);\r\n}\r\n.rc-toast__content {\r\n position: relative;\r\n max-width: 80%;\r\n background: rgba(0, 0, 0, 0.75);\r\n color: #fff;\r\n border-radius: 12px;\r\n padding: 12px 14px;\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 8px;\r\n box-shadow: 0 6px 16px rgba(0,0,0,0.2);\r\n}\r\n.rc-toast__text {\r\n font-size: 14px;\r\n line-height: 1.4;\r\n}\r\n.rc-toast__spinner {\r\n width: 18px;\r\n height: 18px;\r\n border: 2px solid rgba(255,255,255,0.35);\r\n border-top-color: #fff;\r\n border-radius: 50%;\r\n animation: rc-toast-spin 0.8s linear infinite;\r\n}\r\n.rc-toast__icon {\r\n width: 18px;\r\n height: 18px;\r\n border-radius: 50%;\r\n position: relative;\r\n flex: 0 0 18px;\r\n}\r\n.rc-toast__icon--success::before {\r\n content: '';\r\n position: absolute;\r\n left: 3px;\r\n top: 3px;\r\n width: 10px;\r\n height: 10px;\r\n border-right: 2px solid #fff;\r\n border-bottom: 2px solid #fff;\r\n transform: rotate(45deg);\r\n}\r\n.rc-toast__icon--fail::before,\r\n.rc-toast__icon--fail::after {\r\n content: '';\r\n position: absolute;\r\n left: 3px;\r\n right: 3px;\r\n top: 8px;\r\n height: 2px;\r\n background: #fff;\r\n}\r\n.rc-toast__icon--fail::before {\r\n transform: rotate(45deg);\r\n}\r\n.rc-toast__icon--fail::after {\r\n transform: rotate(-45deg);\r\n}\r\n\r\n.rc-toast-fade-enter-active,\r\n.rc-toast-fade-leave-active {\r\n transition: opacity .2s ease;\r\n}\r\n.rc-toast-fade-enter-from,\r\n.rc-toast-fade-leave-to {\r\n opacity: 0;\r\n}\r\n@keyframes rc-toast-spin {\r\n to { transform: rotate(360deg); }\r\n}\r\n</style>\r\n\r\n\r\n","import { App, createApp } from 'vue';\r\nimport Toast, { type ToastProps } from './index.vue';\r\n\r\nexport type { ToastProps };\r\nexport interface ShowToastOptions {\r\n message?: string;\r\n type?: 'text' | 'success' | 'fail' | 'loading';\r\n duration?: number;\r\n mask?: boolean;\r\n /** 关闭时回调(仅服务方式有效) */\r\n onClose?: () => void;\r\n}\r\n\r\nlet app: App<Element> | null = null;\r\nlet host: HTMLDivElement | null = null;\r\n\r\nfunction unmount() {\r\n if (app) {\r\n app.unmount();\r\n app = null;\r\n }\r\n if (host) {\r\n document.body.removeChild(host);\r\n host = null;\r\n }\r\n}\r\n\r\nexport function showToast(options: string | ShowToastOptions) {\r\n const opt: ShowToastOptions =\r\n typeof options === 'string' ? { message: options } : (options || {});\r\n unmount();\r\n host = document.createElement('div');\r\n document.body.appendChild(host);\r\n const toastProps: ToastProps = {\r\n message: opt.message,\r\n type: (opt as any).type ?? 'text',\r\n duration: (opt as any).duration ?? 2000,\r\n mask: (opt as any).mask ?? false,\r\n onAfterLeave: () => {\r\n unmount();\r\n opt.onClose?.();\r\n },\r\n };\r\n app = createApp(Toast, toastProps as any);\r\n app.mount(host);\r\n return {\r\n close: hideToast,\r\n };\r\n}\r\n\r\nexport function hideToast() {\r\n if (!app) return;\r\n // 调用暴露的 close 方法\r\n // @ts-ignore\r\n app._instance?.exposed?.close?.();\r\n}\r\n\r\n// 组件注册(可选,提供 rc-toast 用于手动放置 Portal)\r\n(Toast as any).name = 'rc-toast';\r\nexport function install(app: App) {\r\n app.component((Toast as any).name, Toast);\r\n return app;\r\n}\r\n\r\nexport default Toast;\r\n\r\n\r\n","<template>\r\n <div class=\"rc-message\" role=\"alert\" aria-live=\"polite\">\r\n <transition-group name=\"rc-message-fade\" tag=\"div\">\r\n <div\r\n v-for=\"m in messages\"\r\n :key=\"m.id\"\r\n class=\"rc-message__item\"\r\n :class=\"`rc-message--${m.type}`\"\r\n >\r\n <span class=\"rc-message__content\">{{ m.content }}</span>\r\n </div>\r\n </transition-group>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { reactive } from 'vue';\r\n\r\nexport type MessageType = 'info' | 'success' | 'warning' | 'error' | 'loading';\r\nexport interface MessageItem {\r\n id: number;\r\n type: MessageType;\r\n content: string;\r\n duration: number; // ms; 0 = persistent (except loading default)\r\n}\r\n\r\nconst messages = reactive<MessageItem[]>([]);\r\nlet uid = 1;\r\n\r\nfunction remove(id: number) {\r\n const idx = messages.findIndex((x) => x.id === id);\r\n if (idx >= 0) messages.splice(idx, 1);\r\n}\r\n\r\nfunction add(type: MessageType, content: string, duration: number) {\r\n const id = uid++;\r\n messages.push({ id, type, content, duration });\r\n if (duration > 0) {\r\n window.setTimeout(() => remove(id), duration);\r\n }\r\n return id;\r\n}\r\n\r\ndefineExpose({ add, remove });\r\n</script>\r\n\r\n<style scoped>\r\n.rc-message {\r\n position: fixed;\r\n top: 16px;\r\n left: 0;\r\n right: 0;\r\n z-index: 10000;\r\n pointer-events: none;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n.rc-message__item {\r\n pointer-events: auto;\r\n min-width: 120px;\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 6px;\r\n color: #fff;\r\n background: rgba(0, 0, 0, 0.78);\r\n box-shadow: 0 6px 16px rgba(0,0,0,0.2);\r\n font-size: 14px;\r\n}\r\n.rc-message--success { background: rgba(22,119,255,0.9); }\r\n.rc-message--warning { background: rgba(250,173,20,0.95); }\r\n.rc-message--error { background: rgba(245,63,63,0.95); }\r\n.rc-message--info { background: rgba(0,0,0,0.78); }\r\n.rc-message--loading { background: rgba(0,0,0,0.78); }\r\n\r\n.rc-message-fade-enter-active,\r\n.rc-message-fade-leave-active {\r\n transition: all .2s ease;\r\n}\r\n.rc-message-fade-enter-from,\r\n.rc-message-fade-leave-to {\r\n opacity: 0;\r\n transform: translateY(-6px);\r\n}\r\n</style>\r\n\r\n\r\n","import { createVNode, render, type App } from 'vue';\r\nimport MessageHost from './index.vue';\r\n\r\ntype MessageType = 'info' | 'success' | 'warning' | 'error' | 'loading';\r\n\r\nexport interface MessageOptions {\r\n content: string;\r\n duration?: number; // ms; default 2000, loading 默认 0\r\n type?: MessageType;\r\n}\r\n\r\nlet container: HTMLElement | null = null;\r\nlet hostExposed: any = null;\r\n\r\nfunction ensureHost() {\r\n if (container && hostExposed) return;\r\n container = document.createElement('div');\r\n document.body.appendChild(container);\r\n const vnode = createVNode(MessageHost, {});\r\n render(vnode, container);\r\n hostExposed = (vnode.component as any)?.exposed;\r\n}\r\n\r\nfunction open(type: MessageType, content: string, duration?: number) {\r\n ensureHost();\r\n const d = typeof duration === 'number'\r\n ? duration\r\n : (type === 'loading' ? 0 : 2000);\r\n return hostExposed?.add?.(type, content, d);\r\n}\r\n\r\nexport const message = {\r\n open(opts: MessageOptions) {\r\n return open(opts.type || 'info', opts.content, opts.duration);\r\n },\r\n info(content: string, duration?: number) {\r\n return open('info', content, duration);\r\n },\r\n success(content: string, duration?: number) {\r\n return open('success', content, duration);\r\n },\r\n warning(content: string, duration?: number) {\r\n return open('warning', content, duration);\r\n },\r\n error(content: string, duration?: number) {\r\n return open('error', content, duration);\r\n },\r\n loading(content: string, duration?: number) {\r\n return open('loading', content, duration);\r\n },\r\n destroy() {\r\n if (container) {\r\n render(null, container);\r\n container.remove();\r\n container = null;\r\n hostExposed = null;\r\n }\r\n },\r\n};\r\n\r\nexport default message;\r\n\r\n// 可选:提供 install,注入到 app.config.globalProperties 以便 this.$message 使用\r\nexport function install(app: App) {\r\n (app.config.globalProperties as any).$message = message;\r\n return app;\r\n}\r\n\r\n\r\n","<template>\r\n <i\r\n class=\"rc-icon\"\r\n :class=\"[baseClass, iconClassName, { 'rc-icon--spin': spin }]\"\r\n :style=\"iconStyle\"\r\n aria-hidden=\"true\"\r\n >\r\n <span v-if=\"char\" class=\"rc-icon__unicode\">{{ char }}</span>\r\n </i>\r\n </template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, inject, onMounted } from 'vue';\r\nimport type { RecycleUIOptions } from '../../types';\r\nimport { RECYCLE_UI_SYMBOL, defaultRecycleUIConfig } from '../../index';\r\n\r\ndefineOptions({ name: 'rc-icon' });\r\n\r\nconst props = withDefaults(defineProps<{\r\n /** 图标名,例如 'icon_a_in_store',也可直接传完整类名 */\r\n name: string;\r\n /** 尺寸,数字按 px 处理,也可传 '1.2em' 等 */\r\n size?: number | string;\r\n /** 颜色 */\r\n color?: string;\r\n /** 是否旋转(用于 loading 类图标) */\r\n spin?: boolean;\r\n /** Unicode 码点(不带 \\\\u,十六进制,如 'e609' 或 0xe609),用于无类名时渲染 */\r\n code?: string | number;\r\n}>(), {\r\n size: 16,\r\n color: '',\r\n spin: false,\r\n code: '',\r\n});\r\n\r\nconst cfg = inject<RecycleUIOptions>(RECYCLE_UI_SYMBOL, {} as RecycleUIOptions);\r\n\r\nconst baseClass = computed(() => cfg?.iconClass || 'iconfont');\r\nconst iconClassName = computed(() => props.name || '');\r\n\r\nconst sizeCss = computed(() => (typeof props.size === 'number' ? `${props.size}px` : (props.size || '16px')));\r\nconst iconStyle = computed(() => ({\r\n fontSize: sizeCss.value,\r\n color: props.color || undefined,\r\n lineHeight: 1,\r\n fontFamily: cfg?.iconClass || 'iconfont',\r\n}));\r\n\r\n// 将 code 转为字符\r\nconst char = computed(() => {\r\n const c = props.code as any;\r\n if (c === undefined || c === null || c === '' || c === 0) return '';\r\n if (typeof c === 'number') {\r\n return String.fromCharCode(c);\r\n }\r\n const hex = String(c).replace(/^0x/i, '');\r\n const num = parseInt(hex, 16);\r\n if (Number.isNaN(num)) return '';\r\n return String.fromCharCode(num);\r\n});\r\n\r\n// 兜底:若未通过 app.use 安装插件,则在组件挂载时尝试注入默认的 iconfont 样式\r\nonMounted(() => {\r\n if (typeof window === 'undefined') return;\r\n const url = (cfg && cfg.iconCssUrl) || defaultRecycleUIConfig.iconCssUrl;\r\n if (!url) return;\r\n const selector = `link[rel=\"stylesheet\"][data-rcui-icon=\"true\"][href=\"${url}\"]`;\r\n const exists = document.head.querySelector(selector);\r\n if (!exists) {\r\n const link = document.createElement('link');\r\n link.rel = 'stylesheet';\r\n link.href = url as string;\r\n link.setAttribute('data-rcui-icon', 'true');\r\n document.head.appendChild(link);\r\n }\r\n});\r\n</script>\r\n\r\n<style scoped>\r\n.rc-icon {\r\n display: inline-block;\r\n vertical-align: -0.125em;\r\n}\r\n.rc-icon__unicode {\r\n /* 让 Unicode 文本走同一字体,确保显示 */\r\n font-family: inherit;\r\n line-height: 1;\r\n}\r\n.rc-icon--spin {\r\n animation: rc-icon-rot 1s linear infinite;\r\n}\r\n@keyframes rc-icon-rot {\r\n to { transform: rotate(360deg); }\r\n}\r\n</style>\r\n\r\n\r\n","import type { App } from 'vue';\r\nimport Icon from './index.vue';\r\n\r\n(Icon as any).name = 'rc-icon';\r\n\r\nexport function install(app: App) {\r\n app.component((Icon as any).name, Icon);\r\n app.component('RcIcon', Icon);\r\n return app;\r\n}\r\n\r\nexport const RcIcon = Icon;\r\nexport default Icon;\r\n\r\n\r\n","<template>\r\n <div class=\"rc-search-area\">\r\n <!-- 筛选项按钮行 -->\r\n <div class=\"rc-search-area__bar\">\r\n <div\r\n v-for=\"(item, index) in props.items\"\r\n :key=\"index\"\r\n class=\"rc-search-area__item\"\r\n :class=\"{ \r\n 'is-active': activeIndex === index,\r\n 'has-value': getSelectedCount(item) > 0\r\n }\"\r\n @click=\"openFilter(index)\"\r\n >\r\n <span class=\"rc-search-area__item-label\">{{ getItemDisplayText(item) }}</span>\r\n <rc-icon \r\n name=\"icon_a-xiala2\" \r\n :color=\"(activeIndex !== index && getSelectedCount(item) > 0) ? '#1677ff' : '#969799'\"\r\n class=\"rc-search-area__item-arrow\" \r\n :class=\"{ 'is-up': activeIndex === index }\"\r\n />\r\n </div>\r\n </div>\r\n\r\n <!-- 蒙层 -->\r\n <transition name=\"rc-search-area-fade\">\r\n <div \r\n v-if=\"activeIndex !== null && props.showMask\" \r\n ref=\"maskRef\"\r\n class=\"rc-search-area__mask\"\r\n :style=\"maskStyle\"\r\n @click=\"closeFilter\"\r\n ></div>\r\n </transition>\r\n\r\n <!-- 筛选面板 -->\r\n <transition name=\"rc-search-area-slide\">\r\n <div v-if=\"activeIndex !== null\" ref=\"panelRef\" class=\"rc-search-area__panel\">\r\n <div class=\"rc-search-area__panel-content\">\r\n <!-- 单选模式 -->\r\n <template v-if=\"currentFilter?.type === 'single'\">\r\n <div class=\"rc-search-area__options-grid\">\r\n <div\r\n v-for=\"(option, optIdx) in currentFilter.options\"\r\n :key=\"optIdx\"\r\n class=\"rc-search-area__option\"\r\n :class=\"{ 'is-selected': isSelected(option) }\"\r\n @click=\"selectSingle(option)\"\r\n >\r\n <span class=\"rc-search-area__option-label\">{{ getOptionLabel(option) }}</span>\r\n <rc-icon v-if=\"isSelected(option)\" name=\"icon_select\" class=\"rc-search-area__option-check\" />\r\n </div>\r\n </div>\r\n </template>\r\n\r\n <!-- 多选模式 -->\r\n <template v-else>\r\n <div class=\"rc-search-area__options-grid\">\r\n <div\r\n v-for=\"(option, optIdx) in currentFilter?.options || []\"\r\n :key=\"optIdx\"\r\n class=\"rc-search-area__option\"\r\n :class=\"{ 'is-selected': isSelected(option) }\"\r\n @click=\"toggleOption(option)\"\r\n >\r\n <span class=\"rc-search-area__option-label\">{{ getOptionLabel(option) }}</span>\r\n <rc-icon v-if=\"isSelected(option)\" name=\"icon_select\" class=\"rc-search-area__option-check\" />\r\n </div>\r\n </div>\r\n </template>\r\n\r\n <!-- 无结果提示 -->\r\n <div v-if=\"currentFilter?.options?.length === 0\" class=\"rc-search-area__empty\">\r\n <p>暂无选项</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"rc-search-area__panel-footer\">\r\n <rc-button \r\n block \r\n @click=\"resetCurrentFilter\"\r\n >\r\n 重置\r\n </rc-button>\r\n <rc-button \r\n type=\"primary\"\r\n block \r\n @click=\"confirmFilter\"\r\n >\r\n 确定{{ selectedCountText }}\r\n </rc-button>\r\n </div>\r\n </div>\r\n </transition>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, ref, watch, nextTick, onUnmounted } from 'vue';\r\nimport RcIcon from '../icon';\r\nimport RcButton from '../button';\r\n\r\ndefineOptions({ name: 'rc-search-area' });\r\n\r\nexport interface FilterOption {\r\n label: string;\r\n value: any;\r\n [key: string]: any;\r\n}\r\n\r\nexport interface FilterItem {\r\n /** 筛选项标签 */\r\n label: string;\r\n /** 筛选项唯一标识 */\r\n key: string;\r\n /** 选项列表 */\r\n options: FilterOption[] | string[];\r\n /** 筛选类型:single 单选,multiple 多选(默认) */\r\n type?: 'single' | 'multiple';\r\n /** 多选时的列数(默认 2) */\r\n column?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<{\r\n /** 筛选项配置 */\r\n items: FilterItem[];\r\n /** 当前筛选值(支持 v-model) */\r\n modelValue?: Record<string, any>;\r\n /** 是否显示蒙层 */\r\n showMask?: boolean;\r\n}>(), {\r\n items: () => [],\r\n modelValue: () => ({}),\r\n showMask: true,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n /** v-model 更新事件 */\r\n (e: 'update:modelValue', values: Record<string, any>): void;\r\n /** 筛选条件变化时触发 */\r\n (e: 'change', values: Record<string, any>, item: FilterItem): void;\r\n /** 确认筛选时触发 */\r\n (e: 'confirm', values: Record<string, any>, item: FilterItem): void;\r\n /** 重置筛选时触发 */\r\n (e: 'reset', key?: string): void;\r\n /** 某个筛选项的值被修改并确认时触发 */\r\n (e: 'item-change', key: string, value: any): void;\r\n}>();\r\n\r\n// 当前打开的筛选项索引\r\nconst activeIndex = ref<number | null>(null);\r\n\r\n// 面板和蒙层的 ref\r\nconst panelRef = ref<HTMLElement | null>(null);\r\nconst maskRef = ref<HTMLElement | null>(null);\r\n\r\n// 蒙层样式 - 从面板底部开始\r\nconst maskStyle = ref<{ top: string }>({ top: '0px' });\r\n\r\n// 计算蒙层位置\r\nconst updateMaskPosition = async () => {\r\n if (activeIndex.value === null || !panelRef.value) {\r\n return;\r\n }\r\n await nextTick();\r\n const panelRect = panelRef.value.getBoundingClientRect();\r\n const panelTop = panelRect.top;\r\n maskStyle.value = { top: `${panelTop}px` };\r\n};\r\n\r\n// 处理点击外部区域关闭面板\r\nconst handleClickOutside = (event: MouseEvent) => {\r\n if (activeIndex.value === null || !panelRef.value) {\r\n return;\r\n }\r\n \r\n const target = event.target as HTMLElement;\r\n \r\n // 检查点击的目标是否在面板内部\r\n if (panelRef.value.contains(target)) {\r\n return;\r\n }\r\n \r\n // 检查是否点击的是筛选项按钮(避免点击按钮时关闭)\r\n const searchAreaEl = panelRef.value.closest('.rc-search-area');\r\n if (searchAreaEl) {\r\n const barEl = searchAreaEl.querySelector('.rc-search-area__bar');\r\n if (barEl && barEl.contains(target)) {\r\n // 点击的是筛选项按钮,不关闭面板(由按钮的点击事件处理)\r\n return;\r\n }\r\n }\r\n \r\n // 点击的是外部区域,关闭面板\r\n closeFilter();\r\n};\r\n\r\n// 监听面板打开,更新蒙层位置和添加外部点击监听\r\nwatch(activeIndex, async (newVal) => {\r\n if (newVal !== null) {\r\n await nextTick();\r\n updateMaskPosition();\r\n // 监听窗口大小变化和滚动,更新蒙层位置\r\n window.addEventListener('resize', updateMaskPosition);\r\n window.addEventListener('scroll', updateMaskPosition, true);\r\n // 添加点击外部区域关闭面板的监听\r\n document.addEventListener('click', handleClickOutside, true);\r\n } else {\r\n window.removeEventListener('resize', updateMaskPosition);\r\n window.removeEventListener('scroll', updateMaskPosition, true);\r\n document.removeEventListener('click', handleClickOutside, true);\r\n }\r\n});\r\n\r\n// 组件卸载时清理事件监听器\r\nonUnmounted(() => {\r\n window.removeEventListener('resize', updateMaskPosition);\r\n window.removeEventListener('scroll', updateMaskPosition, true);\r\n document.removeEventListener('click', handleClickOutside, true);\r\n});\r\n\r\n// 每个筛选项的选中值(临时状态,用于模态窗内选择)\r\nconst tempSelectedValues = ref<Record<string, any>>({});\r\n\r\n// 已确认的筛选值\r\nconst confirmedValues = ref<Record<string, any>>({ ...props.modelValue });\r\n\r\n// 监听外部传入的 modelValue 变化\r\nwatch(() => props.modelValue, (newValue) => {\r\n confirmedValues.value = { ...(newValue || {}) };\r\n}, { deep: true, immediate: true });\r\n\r\n// 当前打开的筛选项\r\nconst currentFilter = computed(() => {\r\n if (activeIndex.value === null) return null;\r\n return props.items[activeIndex.value];\r\n});\r\n\r\n// 确定按钮文本\r\nconst selectedCountText = computed(() => {\r\n if (!currentFilter.value) return '';\r\n const count = getTempSelectedCount(currentFilter.value);\r\n return count > 0 ? `(${count}项)` : '';\r\n});\r\n\r\n// 获取筛选项的显示文本\r\nconst getItemDisplayText = (item: FilterItem): string => {\r\n const value = confirmedValues.value[item.key];\r\n if (value === undefined || value === null || value === '') {\r\n return item.label;\r\n }\r\n \r\n if (item.type === 'single') {\r\n const option = findOption(item, value);\r\n if (option) {\r\n return `${item.label}: ${getOptionLabel(option)}`;\r\n }\r\n } else {\r\n // 多选\r\n const values = Array.isArray(value) ? value : [value];\r\n if (values.length > 0) {\r\n const labels = values\r\n .map((val) => {\r\n const opt = findOption(item, val);\r\n return opt ? getOptionLabel(opt) : null;\r\n })\r\n .filter((label) => label !== null);\r\n \r\n if (labels.length > 0) {\r\n return `${item.label}: ${labels.join('、')}`;\r\n }\r\n }\r\n }\r\n \r\n return item.label;\r\n};\r\n\r\n// 打开筛选模态窗\r\nconst openFilter = (index: number) => {\r\n const item = props.items[index];\r\n if (!item) return;\r\n \r\n // 如果点击的是当前已打开的筛选项,则收起\r\n if (activeIndex.value === index) {\r\n activeIndex.value = null;\r\n return;\r\n }\r\n \r\n // 初始化临时选中值\r\n const currentValue = confirmedValues.value[item.key];\r\n if (item.type === 'single') {\r\n tempSelectedValues.value[item.key] = currentValue !== undefined ? currentValue : null;\r\n } else {\r\n tempSelectedValues.value[item.key] = currentValue !== undefined \r\n ? (Array.isArray(currentValue) ? [...currentValue] : [currentValue])\r\n : [];\r\n }\r\n \r\n activeIndex.value = index;\r\n};\r\n\r\n// 关闭筛选模态窗\r\nconst closeFilter = () => {\r\n activeIndex.value = null;\r\n};\r\n\r\n// 获取选项的显示文本\r\nconst getOptionLabel = (option: FilterOption | string): string => {\r\n if (typeof option === 'string') return option;\r\n return option.label || String(option.value);\r\n};\r\n\r\n// 获取选项的值\r\nconst getOptionValue = (option: FilterOption | string): any => {\r\n if (typeof option === 'string') return option;\r\n return option.value !== undefined ? option.value : option;\r\n};\r\n\r\n// 查找选项\r\nconst findOption = (item: FilterItem, value: any): FilterOption | string | null => {\r\n return item.options.find((opt) => {\r\n const optValue = getOptionValue(opt);\r\n return optValue === value || String(optValue) === String(value);\r\n }) || null;\r\n};\r\n\r\n// 判断选项是否被选中(临时状态)\r\nconst isSelected = (option: FilterOption | string): boolean => {\r\n if (!currentFilter.value) return false;\r\n const key = currentFilter.value.key;\r\n const tempValue = tempSelectedValues.value[key];\r\n const optValue = getOptionValue(option);\r\n \r\n if (currentFilter.value.type === 'single') {\r\n return tempValue !== null && tempValue !== undefined && tempValue === optValue;\r\n } else {\r\n const tempArray = Array.isArray(tempValue) ? tempValue : [];\r\n return tempArray.some((v) => v === optValue || String(v) === String(optValue));\r\n }\r\n};\r\n\r\n// 单选\r\nconst selectSingle = (option: FilterOption | string) => {\r\n if (!currentFilter.value) return;\r\n const key = currentFilter.value.key;\r\n const optValue = getOptionValue(option);\r\n \r\n // 如果已选中,则取消选中\r\n if (tempSelectedValues.value[key] === optValue) {\r\n tempSelectedValues.value[key] = null;\r\n } else {\r\n tempSelectedValues.value[key] = optValue;\r\n }\r\n};\r\n\r\n// 多选切换\r\nconst toggleOption = (option: FilterOption | string) => {\r\n if (!currentFilter.value) return;\r\n const key = currentFilter.value.key;\r\n const optValue = getOptionValue(option);\r\n const tempArray = Array.isArray(tempSelectedValues.value[key]) \r\n ? [...tempSelectedValues.value[key]] \r\n : [];\r\n \r\n const existingIndex = tempArray.findIndex(\r\n (v) => v === optValue || String(v) === String(optValue)\r\n );\r\n \r\n if (existingIndex >= 0) {\r\n tempArray.splice(existingIndex, 1);\r\n } else {\r\n tempArray.push(optValue);\r\n }\r\n \r\n tempSelectedValues.value[key] = tempArray;\r\n};\r\n\r\n// 重置当前筛选项\r\nconst resetCurrentFilter = () => {\r\n if (!currentFilter.value) return;\r\n const key = currentFilter.value.key;\r\n if (currentFilter.value.type === 'single') {\r\n tempSelectedValues.value[key] = null;\r\n } else {\r\n tempSelectedValues.value[key] = [];\r\n }\r\n};\r\n\r\n// 确认筛选\r\nconst confirmFilter = () => {\r\n if (!currentFilter.value) return;\r\n const key = currentFilter.value.key;\r\n const tempValue = tempSelectedValues.value[key];\r\n const oldValue = confirmedValues.value[key];\r\n \r\n // 更新已确认的值\r\n let newValue: any;\r\n if (currentFilter.value.type === 'single') {\r\n newValue = tempValue !== null && tempValue !== undefined ? tempValue : undefined;\r\n confirmedValues.value[key] = newValue;\r\n } else {\r\n newValue = Array.isArray(tempValue) && tempValue.length > 0 ? tempValue : undefined;\r\n confirmedValues.value[key] = newValue;\r\n }\r\n \r\n // 更新 v-model\r\n emit('update:modelValue', { ...confirmedValues.value });\r\n \r\n // 触发事件\r\n emit('change', { ...confirmedValues.value }, currentFilter.value);\r\n emit('confirm', { ...confirmedValues.value }, currentFilter.value);\r\n \r\n // 如果值发生变化,触发 item-change 事件\r\n const valueChanged = JSON.stringify(oldValue) !== JSON.stringify(newValue);\r\n if (valueChanged) {\r\n emit('item-change', key, newValue);\r\n }\r\n \r\n closeFilter();\r\n};\r\n\r\n// 获取已选中的数量(已确认的)\r\nconst getSelectedCount = (item: FilterItem): number => {\r\n const value = confirmedValues.value[item.key];\r\n if (value === undefined || value === null || value === '') return 0;\r\n \r\n if (item.type === 'single') {\r\n return 1;\r\n } else {\r\n return Array.isArray(value) ? value.length : (value ? 1 : 0);\r\n }\r\n};\r\n\r\n// 获取临时选中的数量\r\nconst getTempSelectedCount = (item: FilterItem): number => {\r\n const tempValue = tempSelectedValues.value[item.key];\r\n if (tempValue === undefined || tempValue === null || tempValue === '') return 0;\r\n \r\n if (item.type === 'single') {\r\n return 1;\r\n } else {\r\n return Array.isArray(tempValue) ? tempValue.length : 0;\r\n }\r\n};\r\n\r\n// 暴露方法供外部调用\r\ndefineExpose({\r\n /** 获取当前筛选值 */\r\n getValues: () => ({ ...confirmedValues.value }),\r\n /** 重置所有筛选 */\r\n reset: () => {\r\n confirmedValues.value = {};\r\n tempSelectedValues.value = {};\r\n emit('update:modelValue', {});\r\n emit('change', {}, null as any);\r\n emit('reset');\r\n },\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.rc-search-area {\r\n position: relative;\r\n width: 100%;\r\n\r\n &__bar {\r\n display: flex;\r\n align-items: center;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n -webkit-overflow-scrolling: touch;\r\n scrollbar-width: none;\r\n -ms-overflow-style: none;\r\n touch-action: pan-x;\r\n padding: 4px 8px;\r\n box-sizing: border-box;\r\n\r\n &::-webkit-scrollbar {\r\n display: none;\r\n }\r\n }\r\n\r\n &__item {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n padding: 4px 6px;\r\n font-size: 14px;\r\n color: #323233;\r\n cursor: pointer;\r\n user-select: none;\r\n -webkit-user-select: none;\r\n -webkit-tap-highlight-color: transparent;\r\n transition: all 0.2s;\r\n white-space: nowrap;\r\n flex-shrink: 0;\r\n flex-grow: 0;\r\n background: #f0f0f0;\r\n border: 1px solid transparent;\r\n border-radius: 4px;\r\n margin-right: 8px;\r\n max-width: calc(100% - 16px);\r\n min-width: 0;\r\n\r\n &:last-child {\r\n margin-right: 0;\r\n }\r\n\r\n &.has-value {\r\n border-color: #1677ff;\r\n color: #1677ff;\r\n background: #fff;\r\n }\r\n\r\n &.is-active {\r\n background: #f0f0f0;\r\n border-color: transparent;\r\n color: #323233;\r\n\r\n &::after {\r\n content: '';\r\n border: 1px solid #f0f0f0;\r\n position: absolute;\r\n bottom: -8px;\r\n width: 100%;\r\n height: 8px;\r\n background: #f0f0f0;\r\n }\r\n }\r\n\r\n &-label {\r\n margin-right: 4px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n min-width: 0;\r\n flex: 1;\r\n max-width: 100%;\r\n }\r\n\r\n &-count {\r\n min-width: 16px;\r\n height: 16px;\r\n padding: 0 4px;\r\n margin-right: 4px;\r\n background: #1677ff;\r\n color: #fff;\r\n border-radius: 8px;\r\n font-size: 11px;\r\n line-height: 16px;\r\n text-align: center;\r\n }\r\n\r\n &-arrow {\r\n font-size: 10px;\r\n color: #969799;\r\n transition: transform 0.2s;\r\n transform: rotate(0deg);\r\n flex-shrink: 0;\r\n\r\n &.is-up {\r\n transform: rotate(180deg);\r\n }\r\n }\r\n }\r\n\r\n &__mask {\r\n position: fixed;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background: rgba(0, 0, 0, 0.5);\r\n z-index: 999;\r\n }\r\n\r\n &__panel {\r\n position: absolute;\r\n top: 100%;\r\n left: 0;\r\n right: 0;\r\n max-height: 70vh;\r\n background: #f0f0f0;\r\n z-index: 1000;\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n border-bottom-right-radius: 8px;\r\n border-bottom-left-radius: 8px;\r\n }\r\n\r\n &__panel-content {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 8px;\r\n }\r\n\r\n &__options-grid {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 12px;\r\n }\r\n\r\n &__option {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 4px 6px;\r\n background: #f7f8fa;\r\n border: 1px solid #dcdee0;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n white-space: nowrap;\r\n flex-shrink: 0;\r\n\r\n &:hover {\r\n border-color: #1677ff;\r\n }\r\n\r\n &.is-selected {\r\n background: #e6f4ff;\r\n border-color: #1677ff;\r\n color: #1677ff;\r\n }\r\n\r\n &-label {\r\n font-size: 14px;\r\n }\r\n\r\n &-check {\r\n color: #1677ff;\r\n }\r\n }\r\n\r\n &__empty {\r\n padding: 40px 0;\r\n text-align: center;\r\n color: #969799;\r\n font-size: 14px;\r\n }\r\n\r\n &__panel-footer {\r\n display: flex;\r\n gap: 12px;\r\n padding: 8px;\r\n border-top: 1px solid #eee;\r\n flex-shrink: 0;\r\n }\r\n}\r\n\r\n// 过渡动画\r\n.rc-search-area-fade-enter-active,\r\n.rc-search-area-fade-leave-active {\r\n transition: opacity 0.3s ease-out;\r\n}\r\n\r\n.rc-search-area-fade-enter-from,\r\n.rc-search-area-fade-leave-to {\r\n opacity: 0;\r\n}\r\n\r\n.rc-search-area-fade-enter-to,\r\n.rc-search-area-fade-leave-from {\r\n opacity: 1;\r\n}\r\n\r\n.rc-search-area-slide-enter-active,\r\n.rc-search-area-slide-leave-active {\r\n transition: max-height 0.3s ease-out, opacity 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n.rc-search-area-slide-enter-from,\r\n.rc-search-area-slide-leave-to {\r\n max-height: 0;\r\n opacity: 0;\r\n}\r\n\r\n.rc-search-area-slide-enter-to,\r\n.rc-search-area-slide-leave-from {\r\n max-height: 70vh;\r\n opacity: 1;\r\n}\r\n</style>\r\n\r\n","/**\r\n * @description 基础用法\r\n */\r\nimport type { App } from 'vue';\r\nimport RcSearchArea from './index.vue';\r\n\r\nexport { RcSearchArea };\r\nexport type { FilterItem, FilterOption } from './index.vue';\r\n\r\nexport const install = (app: App) => {\r\n app.component('RcSearchArea', RcSearchArea);\r\n app.component('rc-search-area', RcSearchArea);\r\n};\r\n\r\nexport default RcSearchArea;\r\n\r\n","// library entry\r\nimport type { App, Plugin } from 'vue';\r\nimport { install as installButton } from './components/button';\r\nimport { install as installDescriptions } from './components/descriptions';\r\nimport { install as installCard } from './components/card';\r\nimport { install as installToast } from './components/toast';\r\nimport { install as installMessage } from './components/message';\r\nimport { install as installIcon } from './components/icon/index';\r\nimport { install as installSearchArea } from './components/search-area';\r\nimport type { RecycleUIOptions } from './types';\r\n\r\nexport const RECYCLE_UI_SYMBOL = Symbol('RECYCLE_UI_CONFIG');\r\n\r\nexport const defaultRecycleUIConfig: RecycleUIOptions = {\r\n prefix: 'rc',\r\n autoRegister: true,\r\n provideKey: RECYCLE_UI_SYMBOL,\r\n // 预留主题/其他全局配置\r\n theme: {},\r\n // IconFont 默认配置(可在 app.use 时覆盖)\r\n iconCssUrl: '//at.alicdn.com/t/c/font_4252799_9vcnw0pnmkh.css',\r\n iconClass: 'iconfont',\r\n};\r\n\r\n// 统一导出所有类型的命名空间\r\nexport namespace RecycleUiTypes {\r\n // 核心配置类型\r\n export type Options = RecycleUIOptions;\r\n export type DefaultConfig = typeof defaultRecycleUIConfig;\r\n \r\n // Message 相关类型\r\n export type MessageOptions = import('./components/message').MessageOptions;\r\n export type MessageType = import('./components/message/index.vue').MessageType;\r\n export type MessageItem = import('./components/message/index.vue').MessageItem;\r\n \r\n // Toast 相关类型\r\n export type ToastProps = import('./components/toast/index.vue').ToastProps;\r\n export type ToastType = import('./components/toast/index.vue').ToastType;\r\n export type ShowToastOptions = import('./components/toast').ShowToastOptions;\r\n}\r\n\r\nfunction doAutoRegister(app: App, opts: RecycleUIOptions) {\r\n if (opts.autoRegister === false) return;\r\n if (typeof installButton === 'function') installButton(app);\r\n if (typeof installDescriptions === 'function') installDescriptions(app);\r\n if (typeof installCard === 'function') installCard(app);\r\n if (typeof installToast === 'function') installToast(app);\r\n if (typeof installIcon === 'function') installIcon(app);\r\n if (typeof installMessage === 'function') installMessage(app);\r\n if (typeof installSearchArea === 'function') installSearchArea(app);\r\n}\r\n\r\nexport const install = (app: App, options?: RecycleUIOptions) => {\r\n const cfg: RecycleUIOptions = { ...defaultRecycleUIConfig, ...(options || {}) };\r\n // 提供全局配置\r\n app.provide(cfg.provideKey ?? RECYCLE_UI_SYMBOL, cfg);\r\n // 供模板/实例访问:this.$recycleUI\r\n (app.config.globalProperties as any).$recycleUI = cfg;\r\n // 注入 IconFont 样式链接(浏览器环境)\r\n if (typeof window !== 'undefined' && cfg.iconCssUrl) {\r\n const selector = `link[rel=\"stylesheet\"][data-rcui-icon=\"true\"][href=\"${cfg.iconCssUrl}\"]`;\r\n const exists = document.head.querySelector(selector);\r\n if (!exists) {\r\n const link = document.createElement('link');\r\n link.rel = 'stylesheet';\r\n link.href = cfg.iconCssUrl;\r\n link.setAttribute('data-rcui-icon', 'true');\r\n document.head.appendChild(link);\r\n }\r\n }\r\n // 自动注册内置组件(可通过 autoRegister 关闭)\r\n doAutoRegister(app, cfg);\r\n return app;\r\n};\r\n\r\n// 默认导出为插件,支持 app.use(recycleUi, options)\r\nconst plugin: Plugin = { install };\r\nexport default plugin;\r\n\r\n// 也导出命名组件安装器与默认配置(defaultRecycleUIConfig 已在上方以常量形式导出)\r\n\r\n// 可选:工厂方法,便于创建带预设配置的插件\r\nexport function createRecycleUI(options?: RecycleUIOptions): Plugin {\r\n return {\r\n install(app: App) {\r\n install(app, options);\r\n },\r\n };\r\n}\r\n\r\n// 按需导出组件与其安装器(供文档与业务直接使用)\r\nexport { default as RcButton } from './components/button';\r\nexport { RcDescriptions, RcDescriptionsItem } from './components/descriptions';\r\nexport { install as installButton } from './components/button';\r\nexport { install as installDescriptions } from './components/descriptions';\r\nexport { default as RcCard } from './components/card';\r\nexport { install as installCard } from './components/card';\r\n// 兼容别名导出(文档示例中的 rcXxx)\r\nexport { RcDescriptions as rcDescriptions, RcDescriptionsItem as rcDescriptionsItem } from './components/descriptions';\r\n// Toast 服务导出\r\nexport { default as RcToast, showToast, hideToast } from './components/toast';\r\n// Icon 组件导出\r\nexport { default as RcIcon } from './components/icon/index';\r\nexport { install as installIcon } from './components/icon/index';\r\n// Message 服务(对标 antd 的 message)\r\nexport { default as message } from './components/message';\r\nexport { install as installMessage } from './components/message';\r\n// SearchArea 组件导出\r\nexport { default as RcSearchArea } from './components/search-area';\r\nexport { install as installSearchArea } from './components/search-area';\r\nexport type { FilterItem, FilterOption } from './components/search-area';\r\n"],"names":["props","__props","emit","__emit","onClick","ev","radius","computed","v","_createElementBlock","_normalizeClass","_openBlock","_hoisted_2","_renderSlot","_ctx","Button","install","app","inject","providedGapPx","providedColCount","providedLabelWidth","spanNum","n","max","safe","computedWidth","gapPx","k","totalGap","interGap","labelStyle","injected","w","_normalizeStyle","_createElementVNode","_hoisted_1","wrapEl","ref","gapStyle","colCount","itemWidth","singleWidth","watchEffect","base","provide","labelWidthCss","normalizedData","keyK","_a","keyV","_b","_c","it","$slots","_Fragment","_renderList","idx","_createBlock","rcDescriptionsItem","Descriptions","DescriptionsItem","RcDescriptions","RcDescriptionsItem","wrapperStyle","shadowByLevel","toCssSize","bodyPadding","bodyGap","level","_toDisplayString","_hoisted_3","_hoisted_4","_hoisted_5","Card","PascalName","visible","timer","clearTimer","close","__expose","onMounted","onUnmounted","_Teleport","_createVNode","_Transition","_hoisted_6","host","unmount","showToast","options","opt","toastProps","createApp","Toast","hideToast","messages","reactive","uid","remove","id","x","add","type","content","duration","_TransitionGroup","m","container","hostExposed","ensureHost","vnode","createVNode","MessageHost","render","open","d","message","opts","cfg","RECYCLE_UI_SYMBOL","baseClass","iconClassName","sizeCss","iconStyle","char","c","hex","num","url","defaultRecycleUIConfig","selector","link","Icon","activeIndex","panelRef","maskRef","maskStyle","updateMaskPosition","nextTick","panelTop","handleClickOutside","event","target","searchAreaEl","barEl","closeFilter","watch","newVal","tempSelectedValues","confirmedValues","newValue","currentFilter","selectedCountText","count","getTempSelectedCount","getItemDisplayText","item","value","option","findOption","getOptionLabel","values","labels","val","label","openFilter","index","currentValue","getOptionValue","optValue","isSelected","key","tempValue","selectSingle","toggleOption","tempArray","existingIndex","resetCurrentFilter","confirmFilter","oldValue","getSelectedCount","$event","_unref","RcIcon","optIdx","_hoisted_8","_hoisted_9","_hoisted_11","_d","_hoisted_12","_cache","_hoisted_13","RcButton","_createTextVNode","RcSearchArea","doAutoRegister","installButton","installDescriptions","installCard","installToast","installIcon","installMessage","installSearchArea","plugin","createRecycleUI"],"mappings":"ggBA+BA,MAAMA,EAAQC,EAWRC,EAAOC,EAIPC,EAAWC,GAAmB,CAC9B,CAACL,EAAM,UAAY,CAACA,EAAM,SAASE,EAAK,QAASG,CAAE,CACzD,EAEMC,EAASC,EAAAA,SAAS,IAAM,CAC5B,MAAMC,EAAIR,EAAM,MAChB,OAAI,OAAOQ,GAAM,UAAkBA,EAAI,QAAU,MAC7C,OAAOA,GAAM,SAAiB,GAAGA,CAAC,KAC/B,OAAOA,CAAC,CACjB,CAAC,8BAtDCC,EAAAA,mBASS,SAAA,CARP,MAAKC,EAAAA,eAAA,CAAC,YAAW,CAAA,cACMT,EAAA,IAAI,GAAA,cAAkBA,EAAA,IAAI,GAAA,CAAA,WAAkBA,EAAA,MAAK,WAAcA,EAAA,MAAK,cAAiBA,EAAA,sBAAwBA,EAAA,OAAA,CAAO,CAAA,CAAA,EAC1I,qCAAuBK,EAAA,MAAM,EAC7B,SAAUL,EAAA,UAAYA,EAAA,QACtB,QAAAG,CAAA,GAEWH,EAAA,SAAZU,EAAAA,UAAA,EAAAF,EAAAA,mBAAkD,OAAlDG,EAAkD,+BAClDC,EAAAA,WAAwBC,sBAAxB,IAAwB,qCAAfb,EAAA,KAAK,EAAA,CAAA,CAAA,iICLjBc,EAAe,KAAO,YAEhB,SAASC,EAAQC,EAAU,CAChC,OAAAA,EAAI,UAAWF,EAAe,KAAMA,CAAM,EACnCE,CACT,wMCWA,MAAMjB,EAAQC,EAaQiB,EAAAA,OAAoB,kBAAmB,MAAmC,EACpEA,EAAAA,OAA6B,oBAAqB,EAA4B,EACtFA,EAAAA,OAAe,YAAa,KAAK,EACrD,MAAMC,EAAgBD,EAAAA,OAA6B,cAAe,CAA2B,EACvFE,EAAmBF,EAAAA,OAA6B,iBAAkB,CAA2B,EAC7FG,EAAqBH,EAAAA,OAA6B,mBAAoB,EAA4B,EAElGI,EAAUf,EAAAA,SAAS,IAAM,CAC7B,MAAMgB,EAAI,OAAOvB,EAAM,MAAS,SAAW,SAASA,EAAM,KAAM,EAAE,EAAIA,EAAM,KACtEwB,EAAM,OAAQJ,GAAA,YAAAA,EAA0B,QAAU,SAAYA,EAAyB,MAASA,EAChGK,EAAO,CAAC,OAAO,MAAMF,CAAW,GAAMA,EAAe,EAAKA,EAAe,EAC/E,OAAO,KAAK,IAAIE,EAAMD,GAAO,CAAC,CAChC,CAAC,EAEKE,EAAgBnB,EAAAA,SAAS,IAAM,CACnC,MAAMgB,EAAI,OAAQH,GAAA,YAAAA,EAA0B,QAAU,SAAYA,EAAyB,MAASA,EAC9FO,EAAQ,OAAQR,GAAA,YAAAA,EAAuB,QAAU,SAAYA,EAAsB,MAASA,EAC5FS,EAAIN,EAAQ,MAElB,GADI,CAACC,GAAKA,GAAK,GACXK,GAAKL,EAAG,MAAO,OAEnB,MAAMM,GAAYN,EAAI,GAAKI,EACrBG,GAAYF,EAAI,GAAKD,EAC3B,MAAO,gBAAgBE,CAAQ,SAASD,CAAC,MAAML,CAAC,MAAMO,CAAQ,KAChE,CAAC,EAEKC,EAAaxB,EAAAA,SAAS,IAAM,CAChC,MAAMyB,EAAW,OAAQX,GAAA,YAAAA,EAA4B,QAAU,SAC1DA,EAA2B,MAC3BA,EACCY,EAAIjC,EAAM,aAAe,GAAKA,EAAM,WAAcgC,GAAY,GACpE,OAAOC,EAAI,CAAE,MAAO,OAAOA,GAAM,SAAW,GAAGA,CAAC,KAAO,OAAOA,CAAC,EAAG,KAAM,UAAA,EAAe,CAAA,CACzF,CAAC,8BAhECxB,EAAAA,mBAWM,MAAA,CAXD,MAAM,eAAgB,MAAKyB,EAAAA,eAAA,CAAA,MAAWR,EAAA,MAAa,KAAA,OAAeA,EAAA,KAAa,EAAA,CAAA,CAAA,GAClFS,EAAAA,mBAIM,MAAA,CAJD,MAAM,sBAAuB,uBAAOJ,EAAA,KAAU,CAAA,GACjDlB,EAAAA,WAEOC,oBAFP,IAEO,qCADFb,EAAA,KAAK,EAAA,CAAA,CAAA,UAGZkC,EAAAA,mBAIM,MAJNC,GAIM,CAHJvB,EAAAA,WAEOC,sBAFP,IAEO,qCADFb,EAAA,KAAK,EAAA,CAAA,CAAA,kTCqBhB,MAAMD,EAAQC,EAmBRoC,EAASC,EAAAA,IAAwB,IAAI,EACrCC,EAAWhC,EAAAA,SAAS,IAAO,OAAOP,EAAM,KAAQ,SAAW,GAAGA,EAAM,GAAG,KAAO,OAAOA,EAAM,GAAG,CAAE,EAChGwC,EAAWjC,EAAAA,SAAS,IAAM,CAC9B,MAAMgB,EAAI,OAAOvB,EAAM,QAAW,SAAW,OAAO,SAASA,EAAM,OAAkB,EAAE,EAAKA,EAAM,QAAU,EAC5G,MAAO,CAAC,OAAO,MAAMuB,CAAC,GAAKA,EAAI,EAAIA,EAAI,CACzC,CAAC,EAGKkB,EAAYH,EAAAA,IAAY,MAAM,EAC9BI,EAAcJ,EAAAA,IAAY,MAAM,EACtCK,EAAAA,YAAY,IAAM,CAChB,MAAMpB,EAAIiB,EAAS,MACnB,GAAIjB,GAAK,EACPkB,EAAU,MAAQ,OAClBC,EAAY,MAAQ,WACf,CAEL,MAAMf,EAAQ,OAAO3B,EAAM,KAAQ,SAAWA,EAAM,IAAM,WAAW,OAAOA,EAAM,GAAG,CAAC,GAAK,EAErF4C,EAAO,iBADKrB,EAAI,GAAKI,CACU,SAASJ,CAAC,IAC/CmB,EAAY,MAAQE,EACpBH,EAAU,MAAQG,CACpB,CACF,CAAC,EAEDC,EAAAA,QAAQ,kBAAmBJ,CAAS,EACpCI,EAAAA,QAAQ,oBAAqBH,CAAW,EACxCG,EAAAA,QAAQ,iBAAkBL,CAAQ,EAClCK,EAAAA,QAAQ,cAAetC,EAAAA,SAAS,IAAO,OAAOP,EAAM,KAAQ,SAAWA,EAAM,IAAM,WAAW,OAAOA,EAAM,GAAG,CAAC,GAAK,CAAE,CAAC,EACvH,MAAM8C,EAAgBvC,EAAAA,SAAS,IACzBP,EAAM,aAAe,IAAMA,EAAM,aAAe,OAAkB,GAC/D,OAAOA,EAAM,YAAe,SAAW,GAAGA,EAAM,UAAU,KAAO,OAAOA,EAAM,UAAU,CAChG,EACD6C,EAAAA,QAAQ,mBAAoBC,CAAa,EACzCD,EAAAA,QAAQ,YAAatC,EAAAA,SAAS,IAAO,OAAOP,EAAM,KAAQ,SAAW,GAAGA,EAAM,GAAG,KAAO,OAAOA,EAAM,GAAG,CAAE,CAAC,EAE3G,MAAM+C,EAAiBxC,EAAAA,SAAS,IAAM,WACpC,MAAMyC,IAAQC,EAAAjD,EAAM,SAAN,YAAAiD,EAAc,MAAO,QAC7BC,IAAQC,EAAAnD,EAAM,SAAN,YAAAmD,EAAc,QAAS,QACrC,OAAKC,EAAApD,EAAM,OAAN,MAAAoD,EAAY,OACVpD,EAAM,KAAK,IAAKqD,IAAQ,CAC7B,MAAOA,GAAA,YAAAA,EAAKL,GACZ,MAAOK,GAAA,YAAAA,EAAKH,EAAI,EAChB,EAJ8B,CAAA,CAKlC,CAAC,gBA5FCvC,YAAA,EAAAF,qBAkBM,MAlBN2B,GAkBM,CAjBOkB,EAAAA,OAAO,OAASrD,EAAA,OAA3BU,EAAAA,YAAAF,EAAAA,mBAIM,MAJNG,GAIM,CAHJC,EAAAA,WAEOC,oBAFP,IAEO,qCADFb,EAAA,KAAK,EAAA,CAAA,CAAA,qCAGZkC,EAAAA,mBAWM,MAAA,CAXD,MAAM,wBAAyB,4BAAcI,EAAA,MAAQ,UAAQ,SAAJ,IAAIF,CAAA,GAChDU,EAAA,MAAe,QAC7BpC,EAAAA,UAAA,EAAA,EAAAF,EAAAA,mBAME8C,EAAAA,SAAA,CAAA,IAAA,GAAAC,aALoBT,EAAA,MAAc,CAA1BM,EAAII,mBADdC,EAAAA,YAMEC,EAAA,CAJC,IAAKF,EACL,MAAOJ,EAAG,MACV,MAAOA,EAAG,MACV,cAAapD,EAAA,UAAA,kDAGlBY,EAAAA,WAAeC,EAAA,OAAA,UAAA,CAAA,IAAA,CAAA,EAAA,OAAA,EAAA,CAAA,qDCbpB8C,EAAqB,KAAO,kBAC5BC,EAAyB,KAAO,uBAE1B,SAAS7C,EAAQC,EAAU,CAEhC,OAAAA,EAAI,UAAW2C,EAAqB,KAAMA,CAAY,EACtD3C,EAAI,UAAU,iBAAkB2C,CAAY,EAC5C3C,EAAI,UAAW4C,EAAyB,KAAMA,CAAgB,EAC9D5C,EAAI,UAAU,qBAAsB4C,CAAgB,EAC7C5C,CACT,CAEO,MAAM6C,GAAiBF,EACjBG,GAAqBF,ijBCsDlC,MAAM7D,EAAQC,EAeR+D,EAAezD,EAAAA,SAAS,IAAM,CAClC,MAAMD,EACJ,OAAON,EAAM,OAAU,UACnBA,EAAM,MACJ,OACA,IACF,OAAOA,EAAM,OAAU,SACrB,GAAGA,EAAM,KAAK,KACd,OAAOA,EAAM,KAAK,EAE1B,MAAO,CACL,gBAAiBA,EAAM,OAAS,kBAChC,aAAcM,EACd,UAAW2D,EAAcjE,EAAM,SAAS,EACxC,MAAOkE,EAAUlE,EAAM,KAAK,EAC5B,OAAQkE,EAAUlE,EAAM,MAAM,CAAA,CAElC,CAAC,EAEKmE,EAAc5D,EAAAA,SAAS,IAAMP,EAAM,SAAW,MAAM,EACpDoE,EAAU7D,EAAAA,SAAS,IACvB,OAAOP,EAAM,KAAQ,SAAW,GAAGA,EAAM,GAAG,KAAO,OAAOA,EAAM,GAAG,CAAA,EAGrE,SAASkE,EAAU1D,EAAqB,CACtC,OAAuBA,GAAM,MAAQA,IAAM,GAAW,GAC/C,OAAOA,GAAM,SAAW,GAAGA,CAAC,KAAO,OAAOA,CAAC,CACpD,CAEA,SAASyD,EAAcI,EAAe,CACpC,GAAI,CAACA,GAASA,GAAS,EAAG,MAAO,OAEjC,MAAMzB,EAAO,EAAIyB,EACjB,MAAO,KAAK,KAAK,MAAMzB,EAAO,CAAC,CAAC,MAAMA,CAAI,0BAA0B,KAAK,MACvEA,EAAO,CAAA,CACR,MAAM,KAAK,MAAMA,EAAO,CAAC,CAAC,qBAC7B,6BAzHEnC,EAAAA,mBAmCM,MAAA,CAlCJ,MAAKC,EAAAA,eAAA,CAAC,UAAS,CAAA,CAAA,oBACiBT,EAAA,QAAA,CAAQ,CAAA,CAAA,EACvC,uBAAO+D,EAAA,KAAY,CAAA,GAGZV,EAAAA,OAAO,OAASrD,EAAA,OAASqD,EAAAA,OAAO,QAAUrD,EAAA,sBADlDQ,EAAAA,mBAiBM,MAAA,OAfJ,MAAM,eACL,wCAA0BR,EAAA,YAAU,2BAAA,CAAA,GAErCkC,EAAAA,mBAIM,MAJNC,GAIM,CAHJvB,EAAAA,WAEOC,oBAFP,IAEO,CADLqB,EAAAA,mBAAoD,OAApDvB,GAAoD0D,EAAAA,gBAAfrE,EAAA,KAAK,EAAA,CAAA,CAAA,QAGXqD,EAAAA,OAAO,QAAUrD,EAAA,QAApDU,EAAAA,YAAAF,EAAAA,mBAMM,MANN8D,GAMM,CALJ1D,EAAAA,WAIOC,qBAJP,IAIO,CAHLqB,EAAAA,mBAEO,OAAA,CAFD,MAAM,uBAAwB,8BAAgBlC,EAAA,aAAW,oBAAA,CAAA,oBAC1DA,EAAA,MAAM,EAAA,CAAA,CAAA,sEAMjBkC,EAAAA,mBAIM,MAAA,CAJD,MAAM,gBAAiB,MAAKD,EAAAA,eAAA,CAAA,QAAaiC,EAAA,MAAW,IAAOC,EAAA,KAAA,CAAO,CAAA,GACrEvD,EAAAA,WAEOC,sBAFP,IAEO,CADLD,EAAAA,WAAQC,EAAA,OAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAIDwC,EAAAA,OAAO,QAAlB3C,EAAAA,YAAAF,EAAAA,mBAAqD,MAArD+D,EAAqD,+BAE1ClB,EAAAA,OAAO,QAAlB3C,EAAAA,YAAAF,EAAAA,mBAEM,MAFNgE,GAEM,CADJ5D,EAAAA,WAAsBC,EAAA,OAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,kFC9B3B4D,EAAa,KAAO,UACrB,MAAMC,GAAa,SAEZ,SAAS3D,EAAQC,EAAU,CAChC,OAAAA,EAAI,UAAWyD,EAAa,KAAMA,CAAI,EACtCzD,EAAI,UAAU0D,GAAYD,CAAI,EACvBzD,CACT,4aCmBA,MAAMjB,EAAQC,EAOR2E,EAAUtC,EAAAA,IAAI,EAAI,EACxB,IAAIuC,EAEJ,SAASC,GAAa,CAChBD,IACF,aAAaA,CAAK,EAClBA,EAAQ,KAEZ,CAEA,SAASE,GAAQ,CACfD,EAAA,EACAF,EAAQ,MAAQ,EAClB,CAEA,OAAAI,EAAa,CAAE,MAAAD,EAAO,EAEtBE,EAAAA,UAAU,IAAM,CACVjF,EAAM,UAAYA,EAAM,SAAW,IACrC6E,EAAQ,WAAW,IAAM,CACvBE,EAAA,CACF,EAAG/E,EAAM,QAAQ,EAErB,CAAC,EAEDkF,EAAAA,YAAY,IAAM,CAChBJ,EAAA,CACF,CAAC,6EA/DCpB,EAAAA,YAYWyB,EAAAA,SAAA,CAZD,GAAG,QAAM,CACjBC,EAAAA,YAUaC,EAAAA,WAAA,CAVD,KAAK,gBAAiB,aAAapF,EAAA,YAAA,qBAC7C,IAQM,CARK2E,EAAA,qBAAXnE,EAAAA,mBAQM,MAAA,OARc,MAAKC,EAAAA,eAAA,CAAC,WAAU,CAAA,aAAuBT,EAAA,IAAI,EAAA,CAAA,CAAA,CAAA,GAClDA,EAAA,MAAXU,EAAAA,UAAA,EAAAF,EAAAA,mBAA0C,MAA1C2B,EAA0C,+BAC1CD,EAAAA,mBAKM,MALNvB,GAKM,CAJOX,EAAA,OAAI,WAAfU,EAAAA,UAAA,EAAAF,EAAAA,mBAA2D,MAA3D8D,EAA2D,GAC3CtE,EAAA,OAAI,WAApBU,EAAAA,UAAA,EAAAF,EAAAA,mBAAqF,MAArF+D,EAAqF,GACrEvE,EAAA,OAAI,QAApBU,EAAAA,UAAA,EAAAF,EAAAA,mBAA+E,MAA/EgE,EAA+E,+BAC/EtC,EAAAA,mBAA+C,MAA/CmD,GAA+ChB,EAAAA,gBAAhBrE,EAAA,OAAO,EAAA,CAAA,CAAA,kEAK9CY,EAAAA,WAAQC,EAAA,OAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,oDCDV,IAAIG,EAA2B,KAC3BsE,EAA8B,KAElC,SAASC,GAAU,CACbvE,IACFA,EAAI,QAAA,EACJA,EAAM,MAEJsE,IACF,SAAS,KAAK,YAAYA,CAAI,EAC9BA,EAAO,KAEX,CAEO,SAASE,GAAUC,EAAoC,CAC5D,MAAMC,EACJ,OAAOD,GAAY,SAAW,CAAE,QAASA,CAAA,EAAaA,GAAW,CAAA,EACnEF,EAAA,EACAD,EAAO,SAAS,cAAc,KAAK,EACnC,SAAS,KAAK,YAAYA,CAAI,EAC9B,MAAMK,EAAyB,CAC7B,QAASD,EAAI,QACb,KAAOA,EAAY,MAAQ,OAC3B,SAAWA,EAAY,UAAY,IACnC,KAAOA,EAAY,MAAQ,GAC3B,aAAc,IAAM,OAClBH,EAAA,GACAvC,EAAA0C,EAAI,UAAJ,MAAA1C,EAAA,KAAA0C,EACF,CAAA,EAEF,OAAA1E,EAAM4E,EAAAA,UAAUC,EAAOF,CAAiB,EACxC3E,EAAI,MAAMsE,CAAI,EACP,CACL,MAAOQ,EAAA,CAEX,CAEO,SAASA,IAAY,WACrB9E,KAGLmC,GAAAD,GAAAF,EAAAhC,EAAI,YAAJ,YAAAgC,EAAe,UAAf,YAAAE,EAAwB,QAAxB,MAAAC,EAAA,KAAAD,GACF,CAGC2C,EAAc,KAAO,WACf,SAAS9E,EAAQC,EAAU,CAChCA,OAAAA,EAAI,UAAW6E,EAAc,KAAMA,CAAK,EACjC7E,CACT,2JCpCA,MAAM+E,EAAWC,EAAAA,SAAwB,EAAE,EAC3C,IAAIC,EAAM,EAEV,SAASC,EAAOC,EAAY,CAC1B,MAAM3C,EAAMuC,EAAS,UAAWK,GAAMA,EAAE,KAAOD,CAAE,EAC7C3C,GAAO,GAAGuC,EAAS,OAAOvC,EAAK,CAAC,CACtC,CAEA,SAAS6C,EAAIC,EAAmBC,EAAiBC,EAAkB,CACjE,MAAML,EAAKF,IACX,OAAAF,EAAS,KAAK,CAAE,GAAAI,EAAI,KAAAG,EAAM,QAAAC,EAAS,SAAAC,EAAU,EACzCA,EAAW,GACb,OAAO,WAAW,IAAMN,EAAOC,CAAE,EAAGK,CAAQ,EAEvCL,CACT,CAEA,OAAApB,EAAa,CAAE,IAAAsB,EAAK,OAAAH,EAAQ,UA1C1BxF,YAAA,EAAAF,qBAWM,MAXN2B,GAWM,CAVJgD,EAAAA,YASmBsB,EAAAA,gBAAA,CATD,KAAK,kBAAkB,IAAI,KAAA,qBAEzC,IAAqB,kBADvBjG,qBAOM8C,EAAAA,SAAA,KAAAC,EAAAA,WANQwC,EAALW,kBADTlG,EAAAA,mBAOM,MAAA,CALH,IAAKkG,EAAE,GACR,MAAKjG,EAAAA,eAAA,CAAC,mBAAkB,eACDiG,EAAE,IAAI,EAAA,CAAA,CAAA,GAE7BxE,EAAAA,mBAAwD,OAAxDvB,GAAwD0D,EAAAA,gBAAnBqC,EAAE,OAAO,EAAA,CAAA,CAAA,sECEtD,IAAIC,EAAgC,KAChCC,EAAmB,KAEvB,SAASC,IAAa,OACpB,GAAIF,GAAaC,EAAa,OAC9BD,EAAY,SAAS,cAAc,KAAK,EACxC,SAAS,KAAK,YAAYA,CAAS,EACnC,MAAMG,EAAQC,EAAAA,YAAYC,GAAa,EAAE,EACzCC,EAAAA,OAAOH,EAAOH,CAAS,EACvBC,GAAe5D,EAAA8D,EAAM,YAAN,YAAA9D,EAAyB,OAC1C,CAEA,SAASkE,EAAKZ,EAAmBC,EAAiBC,EAAmB,OACnEK,GAAA,EACA,MAAMM,EAAI,OAAOX,GAAa,SAC1BA,EACCF,IAAS,UAAY,EAAI,IAC9B,OAAOtD,EAAA4D,GAAA,YAAAA,EAAa,MAAb,YAAA5D,EAAA,KAAA4D,EAAmBN,EAAMC,EAASY,EAC3C,CAEO,MAAMC,GAAU,CACrB,KAAKC,EAAsB,CACzB,OAAOH,EAAKG,EAAK,MAAQ,OAAQA,EAAK,QAASA,EAAK,QAAQ,CAC9D,EACA,KAAKd,EAAiBC,EAAmB,CACvC,OAAOU,EAAK,OAAQX,EAASC,CAAQ,CACvC,EACA,QAAQD,EAAiBC,EAAmB,CAC1C,OAAOU,EAAK,UAAWX,EAASC,CAAQ,CAC1C,EACA,QAAQD,EAAiBC,EAAmB,CAC1C,OAAOU,EAAK,UAAWX,EAASC,CAAQ,CAC1C,EACA,MAAMD,EAAiBC,EAAmB,CACxC,OAAOU,EAAK,QAASX,EAASC,CAAQ,CACxC,EACA,QAAQD,EAAiBC,EAAmB,CAC1C,OAAOU,EAAK,UAAWX,EAASC,CAAQ,CAC1C,EACA,SAAU,CACJG,IACFM,EAAAA,OAAO,KAAMN,CAAS,EACtBA,EAAU,OAAA,EACVA,EAAY,KACZC,EAAc,KAElB,CACF,EAKO,SAAS7F,EAAQC,EAAU,CAC/B,OAAAA,EAAI,OAAO,iBAAyB,SAAWoG,GACzCpG,CACT,8MChDA,MAAMjB,EAAQC,EAkBRsH,EAAMrG,EAAAA,OAAyBsG,EAAmB,EAAsB,EAExEC,EAAYlH,EAAAA,SAAS,KAAMgH,GAAA,YAAAA,EAAK,YAAa,UAAU,EACvDG,EAAgBnH,EAAAA,SAAS,IAAMP,EAAM,MAAQ,EAAE,EAE/C2H,EAAUpH,EAAAA,SAAS,IAAO,OAAOP,EAAM,MAAS,SAAW,GAAGA,EAAM,IAAI,KAAQA,EAAM,MAAQ,MAAQ,EACtG4H,EAAYrH,EAAAA,SAAS,KAAO,CAChC,SAAUoH,EAAQ,MAClB,MAAO3H,EAAM,OAAS,OACtB,WAAY,EACZ,YAAYuH,GAAA,YAAAA,EAAK,YAAa,UAAA,EAC9B,EAGIM,EAAOtH,EAAAA,SAAS,IAAM,CAC1B,MAAMuH,EAAI9H,EAAM,KAChB,GAAuB8H,GAAM,MAAQA,IAAM,IAAMA,IAAM,EAAG,MAAO,GACjE,GAAI,OAAOA,GAAM,SACf,OAAO,OAAO,aAAaA,CAAC,EAE9B,MAAMC,EAAM,OAAOD,CAAC,EAAE,QAAQ,OAAQ,EAAE,EAClCE,EAAM,SAASD,EAAK,EAAE,EAC5B,OAAI,OAAO,MAAMC,CAAG,EAAU,GACvB,OAAO,aAAaA,CAAG,CAChC,CAAC,EAGD/C,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAI,OAAO,OAAW,IAAa,OACnC,MAAMgD,EAAOV,GAAOA,EAAI,YAAeW,EAAuB,WAC9D,GAAI,CAACD,EAAK,OACV,MAAME,EAAW,uDAAuDF,CAAG,KAE3E,GAAI,CADW,SAAS,KAAK,cAAcE,CAAQ,EACtC,CACX,MAAMC,EAAO,SAAS,cAAc,MAAM,EAC1CA,EAAK,IAAM,aACXA,EAAK,KAAOH,EACZG,EAAK,aAAa,iBAAkB,MAAM,EAC1C,SAAS,KAAK,YAAYA,CAAI,CAChC,CACF,CAAC,wBA3EC3H,EAAAA,mBAOI,IAAA,CANF,wBAAM,UAAS,CACNgH,QAAWC,EAAA,uBAAkCzH,EAAA,IAAA,CAAI,CAAA,CAAA,EACzD,uBAAO2H,EAAA,KAAS,EACjB,cAAY,MAAA,GAEAC,EAAA,qBAAZpH,EAAAA,mBAA4D,OAA5D2B,GAA4DkC,EAAAA,gBAAduD,EAAA,KAAI,EAAA,CAAA,iFCJrDQ,EAAa,KAAO,UAEd,SAASrH,EAAQC,EAAU,CAChC,OAAAA,EAAI,UAAWoH,EAAa,KAAMA,CAAI,EACtCpH,EAAI,UAAU,SAAUoH,CAAI,EACrBpH,CACT,ssBCkHA,MAAMjB,EAAQC,EAaRC,EAAOC,EAcPmI,EAAchG,EAAAA,IAAmB,IAAI,EAGrCiG,EAAWjG,EAAAA,IAAwB,IAAI,EACvCkG,EAAUlG,EAAAA,IAAwB,IAAI,EAGtCmG,EAAYnG,EAAAA,IAAqB,CAAE,IAAK,MAAO,EAG/CoG,EAAqB,SAAY,CACrC,GAAIJ,EAAY,QAAU,MAAQ,CAACC,EAAS,MAC1C,OAEF,MAAMI,WAAA,EAEN,MAAMC,EADYL,EAAS,MAAM,sBAAA,EACN,IAC3BE,EAAU,MAAQ,CAAE,IAAK,GAAGG,CAAQ,IAAA,CACtC,EAGMC,EAAsBC,GAAsB,CAChD,GAAIR,EAAY,QAAU,MAAQ,CAACC,EAAS,MAC1C,OAGF,MAAMQ,EAASD,EAAM,OAGrB,GAAIP,EAAS,MAAM,SAASQ,CAAM,EAChC,OAIF,MAAMC,EAAeT,EAAS,MAAM,QAAQ,iBAAiB,EAC7D,GAAIS,EAAc,CAChB,MAAMC,EAAQD,EAAa,cAAc,sBAAsB,EAC/D,GAAIC,GAASA,EAAM,SAASF,CAAM,EAEhC,MAEJ,CAGAG,EAAA,CACF,EAGAC,QAAMb,EAAa,MAAOc,GAAW,CAC/BA,IAAW,MACb,MAAMT,WAAA,EACND,EAAA,EAEA,OAAO,iBAAiB,SAAUA,CAAkB,EACpD,OAAO,iBAAiB,SAAUA,EAAoB,EAAI,EAE1D,SAAS,iBAAiB,QAASG,EAAoB,EAAI,IAE3D,OAAO,oBAAoB,SAAUH,CAAkB,EACvD,OAAO,oBAAoB,SAAUA,EAAoB,EAAI,EAC7D,SAAS,oBAAoB,QAASG,EAAoB,EAAI,EAElE,CAAC,EAGD3D,EAAAA,YAAY,IAAM,CAChB,OAAO,oBAAoB,SAAUwD,CAAkB,EACvD,OAAO,oBAAoB,SAAUA,EAAoB,EAAI,EAC7D,SAAS,oBAAoB,QAASG,EAAoB,EAAI,CAChE,CAAC,EAGD,MAAMQ,EAAqB/G,EAAAA,IAAyB,EAAE,EAGhDgH,EAAkBhH,EAAAA,IAAyB,CAAE,GAAGtC,EAAM,WAAY,EAGxEmJ,EAAAA,MAAM,IAAMnJ,EAAM,WAAauJ,GAAa,CAC1CD,EAAgB,MAAQ,CAAE,GAAIC,GAAY,CAAA,CAAC,CAC7C,EAAG,CAAE,KAAM,GAAM,UAAW,GAAM,EAGlC,MAAMC,EAAgBjJ,EAAAA,SAAS,IACzB+H,EAAY,QAAU,KAAa,KAChCtI,EAAM,MAAMsI,EAAY,KAAK,CACrC,EAGKmB,EAAoBlJ,EAAAA,SAAS,IAAM,CACvC,GAAI,CAACiJ,EAAc,MAAO,MAAO,GACjC,MAAME,EAAQC,GAAqBH,EAAc,KAAK,EACtD,OAAOE,EAAQ,EAAI,IAAIA,CAAK,KAAO,EACrC,CAAC,EAGKE,GAAsBC,GAA6B,CACvD,MAAMC,EAAQR,EAAgB,MAAMO,EAAK,GAAG,EAC5C,GAA2BC,GAAU,MAAQA,IAAU,GACrD,OAAOD,EAAK,MAGd,GAAIA,EAAK,OAAS,SAAU,CAC1B,MAAME,EAASC,EAAWH,EAAMC,CAAK,EACrC,GAAIC,EACF,MAAO,GAAGF,EAAK,KAAK,KAAKI,EAAeF,CAAM,CAAC,EAEnD,KAAO,CAEL,MAAMG,EAAS,MAAM,QAAQJ,CAAK,EAAIA,EAAQ,CAACA,CAAK,EACpD,GAAII,EAAO,OAAS,EAAG,CACrB,MAAMC,EAASD,EACZ,IAAKE,GAAQ,CACZ,MAAMzE,EAAMqE,EAAWH,EAAMO,CAAG,EAChC,OAAOzE,EAAMsE,EAAetE,CAAG,EAAI,IACrC,CAAC,EACA,OAAQ0E,GAAUA,IAAU,IAAI,EAEnC,GAAIF,EAAO,OAAS,EAClB,MAAO,GAAGN,EAAK,KAAK,KAAKM,EAAO,KAAK,GAAG,CAAC,EAE7C,CACF,CAEA,OAAON,EAAK,KACd,EAGMS,GAAcC,GAAkB,CACpC,MAAMV,EAAO7J,EAAM,MAAMuK,CAAK,EAC9B,GAAI,CAACV,EAAM,OAGX,GAAIvB,EAAY,QAAUiC,EAAO,CAC/BjC,EAAY,MAAQ,KACpB,MACF,CAGA,MAAMkC,EAAelB,EAAgB,MAAMO,EAAK,GAAG,EAC/CA,EAAK,OAAS,SAChBR,EAAmB,MAAMQ,EAAK,GAAG,EAAIW,IAAiB,OAAYA,EAAe,KAEjFnB,EAAmB,MAAMQ,EAAK,GAAG,EAAIW,IAAiB,OACjD,MAAM,QAAQA,CAAY,EAAI,CAAC,GAAGA,CAAY,EAAI,CAACA,CAAY,EAChE,CAAA,EAGNlC,EAAY,MAAQiC,CACtB,EAGMrB,EAAc,IAAM,CACxBZ,EAAY,MAAQ,IACtB,EAGM2B,EAAkBF,GAClB,OAAOA,GAAW,SAAiBA,EAChCA,EAAO,OAAS,OAAOA,EAAO,KAAK,EAItCU,EAAkBV,GAClB,OAAOA,GAAW,SAAiBA,EAChCA,EAAO,QAAU,OAAYA,EAAO,MAAQA,EAI/CC,EAAa,CAACH,EAAkBC,IAC7BD,EAAK,QAAQ,KAAMlE,GAAQ,CAChC,MAAM+E,EAAWD,EAAe9E,CAAG,EACnC,OAAO+E,IAAaZ,GAAS,OAAOY,CAAQ,IAAM,OAAOZ,CAAK,CAChE,CAAC,GAAK,KAIFa,EAAcZ,GAA2C,CAC7D,GAAI,CAACP,EAAc,MAAO,MAAO,GACjC,MAAMoB,EAAMpB,EAAc,MAAM,IAC1BqB,EAAYxB,EAAmB,MAAMuB,CAAG,EACxCF,EAAWD,EAAeV,CAAM,EAEtC,OAAIP,EAAc,MAAM,OAAS,SACxBqB,GAAc,MAAmCA,IAAcH,GAEpD,MAAM,QAAQG,CAAS,EAAIA,EAAY,CAAA,GACxC,KAAMrK,GAAMA,IAAMkK,GAAY,OAAOlK,CAAC,IAAM,OAAOkK,CAAQ,CAAC,CAEjF,EAGMI,GAAgBf,GAAkC,CACtD,GAAI,CAACP,EAAc,MAAO,OAC1B,MAAMoB,EAAMpB,EAAc,MAAM,IAC1BkB,EAAWD,EAAeV,CAAM,EAGlCV,EAAmB,MAAMuB,CAAG,IAAMF,EACpCrB,EAAmB,MAAMuB,CAAG,EAAI,KAEhCvB,EAAmB,MAAMuB,CAAG,EAAIF,CAEpC,EAGMK,GAAgBhB,GAAkC,CACtD,GAAI,CAACP,EAAc,MAAO,OAC1B,MAAMoB,EAAMpB,EAAc,MAAM,IAC1BkB,EAAWD,EAAeV,CAAM,EAChCiB,EAAY,MAAM,QAAQ3B,EAAmB,MAAMuB,CAAG,CAAC,EACzD,CAAC,GAAGvB,EAAmB,MAAMuB,CAAG,CAAC,EACjC,CAAA,EAEEK,EAAgBD,EAAU,UAC7BxK,GAAMA,IAAMkK,GAAY,OAAOlK,CAAC,IAAM,OAAOkK,CAAQ,CAAA,EAGpDO,GAAiB,EACnBD,EAAU,OAAOC,EAAe,CAAC,EAEjCD,EAAU,KAAKN,CAAQ,EAGzBrB,EAAmB,MAAMuB,CAAG,EAAII,CAClC,EAGME,GAAqB,IAAM,CAC/B,GAAI,CAAC1B,EAAc,MAAO,OAC1B,MAAMoB,EAAMpB,EAAc,MAAM,IAC5BA,EAAc,MAAM,OAAS,SAC/BH,EAAmB,MAAMuB,CAAG,EAAI,KAEhCvB,EAAmB,MAAMuB,CAAG,EAAI,CAAA,CAEpC,EAGMO,GAAgB,IAAM,CAC1B,GAAI,CAAC3B,EAAc,MAAO,OAC1B,MAAMoB,EAAMpB,EAAc,MAAM,IAC1BqB,EAAYxB,EAAmB,MAAMuB,CAAG,EACxCQ,EAAW9B,EAAgB,MAAMsB,CAAG,EAG1C,IAAIrB,EACAC,EAAc,MAAM,OAAS,UAC/BD,EAAWsB,GAA4D,OACvEvB,EAAgB,MAAMsB,CAAG,EAAIrB,IAE7BA,EAAW,MAAM,QAAQsB,CAAS,GAAKA,EAAU,OAAS,EAAIA,EAAY,OAC1EvB,EAAgB,MAAMsB,CAAG,EAAIrB,GAI/BrJ,EAAK,oBAAqB,CAAE,GAAGoJ,EAAgB,MAAO,EAGtDpJ,EAAK,SAAU,CAAE,GAAGoJ,EAAgB,KAAA,EAASE,EAAc,KAAK,EAChEtJ,EAAK,UAAW,CAAE,GAAGoJ,EAAgB,KAAA,EAASE,EAAc,KAAK,EAG5C,KAAK,UAAU4B,CAAQ,IAAM,KAAK,UAAU7B,CAAQ,GAEvErJ,EAAK,cAAe0K,EAAKrB,CAAQ,EAGnCL,EAAA,CACF,EAGMmC,EAAoBxB,GAA6B,CACrD,MAAMC,EAAQR,EAAgB,MAAMO,EAAK,GAAG,EAC5C,OAA2BC,GAAU,MAAQA,IAAU,GAAW,EAE9DD,EAAK,OAAS,SACT,EAEA,MAAM,QAAQC,CAAK,EAAIA,EAAM,OAAUA,EAAQ,EAAI,CAE9D,EAGMH,GAAwBE,GAA6B,CACzD,MAAMgB,EAAYxB,EAAmB,MAAMQ,EAAK,GAAG,EACnD,OAA+BgB,GAAc,MAAQA,IAAc,GAAW,EAE1EhB,EAAK,OAAS,SACT,EAEA,MAAM,QAAQgB,CAAS,EAAIA,EAAU,OAAS,CAEzD,EAGA,OAAA7F,EAAa,CAEX,UAAW,KAAO,CAAE,GAAGsE,EAAgB,KAAA,GAEvC,MAAO,IAAM,CACXA,EAAgB,MAAQ,CAAA,EACxBD,EAAmB,MAAQ,CAAA,EAC3BnJ,EAAK,oBAAqB,EAAE,EAC5BA,EAAK,SAAU,CAAA,EAAI,IAAW,EAC9BA,EAAK,OAAO,CACd,CAAA,CACD,UAxcCS,YAAA,EAAAF,qBA6FM,MA7FN2B,GA6FM,CA3FJD,EAAAA,mBAmBM,MAnBNvB,GAmBM,EAlBJD,EAAAA,UAAA,EAAA,EAAAF,EAAAA,mBAiBM8C,6BAhBoBvD,EAAM,MAAK,CAA3B6J,EAAMU,mBADhB9J,EAAAA,mBAiBM,MAAA,CAfH,IAAK8J,EACN,wBAAM,uBAAsB,CACO,YAAAjC,EAAA,QAAgBiC,EAA+B,YAAAc,EAAiBxB,CAAI,EAAA,CAAA,IAItG,QAAKyB,GAAEhB,GAAWC,CAAK,CAAA,GAExBpI,EAAAA,mBAA8E,OAA9EqC,GAA8EF,EAAAA,gBAAlCsF,GAAmBC,CAAI,CAAA,EAAA,CAAA,EACnEzE,cAKEmG,EAAAA,MAAAC,CAAA,EAAA,CAJA,KAAK,gBACJ,MAAQlD,EAAA,QAAgBiC,GAASc,EAAiBxB,CAAI,EAAA,EAAA,UAAA,UACvD,MAAKnJ,EAAAA,eAAA,CAAC,6BAA4B,CAAA,QACf4H,EAAA,QAAgBiC,EAAK,CAAA,CAAA,8CAM9CnF,EAAAA,YAQaC,EAAAA,WAAA,CARD,KAAK,uBAAqB,mBACpC,IAMO,CALCiD,EAAA,QAAW,MAAatI,EAAM,wBADtCS,EAAAA,mBAMO,MAAA,eAJD,UAAJ,IAAI+H,EACJ,MAAM,uBACL,uBAAOC,EAAA,KAAS,EAChB,QAAOS,CAAA,+CAKZ9D,EAAAA,YAyDaC,EAAAA,WAAA,CAzDD,KAAK,wBAAsB,mBACrC,IAAA,aAuDM,OAvDKiD,EAAA,QAAW,oBAAtB7H,EAAAA,mBAuDM,MAAA,eAvD+B,WAAJ,IAAI8H,EAAW,MAAM,uBAAA,GACpDpG,EAAAA,mBAqCM,MArCNsC,GAqCM,GAnCYxB,EAAAuG,EAAA,QAAA,YAAAvG,EAAe,QAAI,UACjCtC,EAAAA,YAAAF,EAAAA,mBAWM,MAXN6E,GAWM,EAVJ3E,EAAAA,UAAA,EAAA,EAAAF,EAAAA,mBASM8C,EAAAA,2BARuBiG,EAAA,MAAc,QAAO,CAAxCO,EAAQ0B,mBADlBhL,EAAAA,mBASM,MAAA,CAPH,IAAKgL,EACN,MAAK/K,EAAAA,eAAA,CAAC,yBAAwB,CAAA,cACLiK,EAAWZ,CAAM,CAAA,CAAA,CAAA,EACzC,QAAKuB,IAAER,GAAaf,CAAM,CAAA,GAE3B5H,EAAAA,mBAA8E,OAA9EuJ,GAA8EpH,EAAAA,gBAAhC2F,EAAeF,CAAM,CAAA,EAAA,CAAA,EACpDY,EAAWZ,CAAM,iBAAhCrG,EAAAA,YAA6F6H,EAAAA,MAAAC,CAAA,EAAA,OAA1D,KAAK,cAAc,MAAM,8BAAA,oDAOhE7K,EAAAA,UAAA,EAAAF,qBAWM,MAXNkL,GAWM,EAVJhL,EAAAA,UAAA,EAAA,EAAAF,qBASM8C,EAAAA,6BARuBJ,EAAAqG,EAAA,QAAA,YAAArG,EAAe,UAAO,CAAA,EAAA,CAAzC4G,EAAQ0B,mBADlBhL,EAAAA,mBASM,MAAA,CAPH,IAAKgL,EACN,MAAK/K,EAAAA,eAAA,CAAC,yBAAwB,CAAA,cACLiK,EAAWZ,CAAM,CAAA,CAAA,CAAA,EACzC,QAAKuB,IAAEP,GAAahB,CAAM,CAAA,GAE3B5H,EAAAA,mBAA8E,OAA9EyJ,GAA8EtH,EAAAA,gBAAhC2F,EAAeF,CAAM,CAAA,EAAA,CAAA,EACpDY,EAAWZ,CAAM,iBAAhCrG,EAAAA,YAA6F6H,EAAAA,MAAAC,CAAA,EAAA,OAA1D,KAAK,cAAc,MAAM,8BAAA,qDAMvDK,GAAAzI,EAAAoG,EAAA,QAAA,YAAApG,EAAe,UAAf,YAAAyI,EAAwB,UAAM,GAAzClL,EAAAA,YAAAF,EAAAA,mBAEM,MAFNqL,GAEM,CAAA,GAAAC,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAA,CADJ5J,EAAAA,mBAAW,SAAR,OAAI,EAAA,CAAA,oCAIXA,EAAAA,mBAcM,MAdN6J,GAcM,CAbJ5G,cAKYmG,EAAAA,MAAAU,CAAA,EAAA,CAJV,MAAA,GACC,QAAOf,EAAA,qBACT,IAED,CAAA,GAAAa,EAAA,CAAA,IAAAA,EAAA,CAAA,EAAA,mBAFC,OAED,EAAA,CAAA,WACA3G,cAMYmG,EAAAA,MAAAU,CAAA,EAAA,CALV,KAAK,UACL,MAAA,GACC,QAAOd,EAAA,qBACT,IACG,CADHe,EAAAA,gBAAA,wBACMzC,EAAA,KAAiB,EAAA,CAAA,CAAA,uGChFrBzI,EAAWC,GAAa,CACnCA,EAAI,UAAU,eAAgBkL,CAAY,EAC1ClL,EAAI,UAAU,iBAAkBkL,CAAY,CAC9C,ECDa3E,EAAoB,OAAO,mBAAmB,EAE9CU,EAA2C,CACtD,OAAQ,KACR,aAAc,GACd,WAAYV,EAEZ,MAAO,CAAA,EAEP,WAAY,mDACZ,UAAW,UACb,EAmBA,SAAS4E,GAAenL,EAAUqG,EAAwB,CACpDA,EAAK,eAAiB,KACtB,OAAO+E,GAAkB,YAAYA,EAAcpL,CAAG,EACtD,OAAOqL,GAAwB,YAAYA,EAAoBrL,CAAG,EAClE,OAAOsL,GAAgB,YAAYA,EAAYtL,CAAG,EAClD,OAAOuL,GAAiB,YAAYA,EAAavL,CAAG,EACpD,OAAOwL,GAAgB,YAAYA,EAAYxL,CAAG,EAClD,OAAOyL,GAAmB,YAAYA,EAAezL,CAAG,EACxD,OAAO0L,GAAsB,YAAYA,EAAkB1L,CAAG,EACpE,CAEO,MAAMD,EAAU,CAACC,EAAUyE,IAA+B,CAC/D,MAAM6B,EAAwB,CAAE,GAAGW,EAAwB,GAAIxC,GAAW,CAAA,CAAC,EAM3E,GAJAzE,EAAI,QAAQsG,EAAI,YAAcC,EAAmBD,CAAG,EAEnDtG,EAAI,OAAO,iBAAyB,WAAasG,EAE9C,OAAO,OAAW,KAAeA,EAAI,WAAY,CACnD,MAAMY,EAAW,uDAAuDZ,EAAI,UAAU,KAEtF,GAAI,CADW,SAAS,KAAK,cAAcY,CAAQ,EACtC,CACX,MAAMC,EAAO,SAAS,cAAc,MAAM,EAC1CA,EAAK,IAAM,aACXA,EAAK,KAAOb,EAAI,WAChBa,EAAK,aAAa,iBAAkB,MAAM,EAC1C,SAAS,KAAK,YAAYA,CAAI,CAChC,CACF,CAEA,OAAAgE,GAAenL,EAAKsG,CAAG,EAChBtG,CACT,EAGM2L,GAAiB,CAAE,QAAA5L,CAAA,EAMlB,SAAS6L,GAAgBnH,EAAoC,CAClE,MAAO,CACL,QAAQzE,EAAU,CAChBD,EAAQC,EAAKyE,CAAO,CACtB,CAAA,CAEJ"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/components/icon/index.vue","../src/components/button/index.vue","../src/components/button/index.ts","../src/components/descriptions/item.vue","../src/components/descriptions/index.vue","../src/components/descriptions/index.ts","../src/components/card/index.vue","../src/components/card/index.ts","../src/components/toast/index.vue","../src/components/toast/index.ts","../src/components/message/index.vue","../src/components/message/index.ts","../src/components/icon/index.ts","../src/components/popup/index.vue","../src/components/popup/index.ts","../src/components/calendar/panel-content.vue","../src/components/calendar/index.vue","../src/components/calendar/index.ts","../src/components/search-area/index.vue","../src/components/search-area/index.ts","../src/components/input/index.vue","../src/components/input/index.ts","../src/components/dropdown/menu.vue","../src/components/dropdown/index.vue","../src/components/dropdown/item.vue","../src/components/dropdown/index.ts","../src/index.ts"],"sourcesContent":["<template>\r\n <i\r\n class=\"rc-icon\"\r\n :class=\"[baseClass, iconClassName, { 'rc-icon--spin': spin }]\"\r\n :style=\"iconStyle\"\r\n aria-hidden=\"true\"\r\n >\r\n <span v-if=\"char\" class=\"rc-icon__unicode\">{{ char }}</span>\r\n </i>\r\n </template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, inject, onMounted } from 'vue';\r\nimport type { RecycleUIOptions } from '../../types';\r\nimport { RECYCLE_UI_SYMBOL, defaultRecycleUIConfig } from '../../index';\r\n\r\ndefineOptions({ name: 'rc-icon' });\r\n\r\nconst props = withDefaults(defineProps<{\r\n /** 图标名,例如 'icon_a_in_store',也可直接传完整类名 */\r\n name: string;\r\n /** 尺寸,数字按 px 处理,也可传 '1.2em' 等 */\r\n size?: number | string;\r\n /** 颜色 */\r\n color?: string;\r\n /** 是否旋转(用于 loading 类图标) */\r\n spin?: boolean;\r\n /** Unicode 码点(不带 \\\\u,十六进制,如 'e609' 或 0xe609),用于无类名时渲染 */\r\n code?: string | number;\r\n}>(), {\r\n size: 16,\r\n color: '',\r\n spin: false,\r\n code: '',\r\n});\r\n\r\nconst cfg = inject<RecycleUIOptions>(RECYCLE_UI_SYMBOL, {} as RecycleUIOptions);\r\n\r\nconst baseClass = computed(() => cfg?.iconClass || 'iconfont');\r\nconst iconClassName = computed(() => props.name || '');\r\n\r\nconst sizeCss = computed(() => (typeof props.size === 'number' ? `${props.size}px` : (props.size || '16px')));\r\nconst iconStyle = computed(() => ({\r\n fontSize: sizeCss.value,\r\n color: props.color || undefined,\r\n lineHeight: 1,\r\n fontFamily: cfg?.iconClass || 'iconfont',\r\n}));\r\n\r\n// 将 code 转为字符\r\nconst char = computed(() => {\r\n const c = props.code as any;\r\n if (c === undefined || c === null || c === '' || c === 0) return '';\r\n if (typeof c === 'number') {\r\n return String.fromCharCode(c);\r\n }\r\n const hex = String(c).replace(/^0x/i, '');\r\n const num = parseInt(hex, 16);\r\n if (Number.isNaN(num)) return '';\r\n return String.fromCharCode(num);\r\n});\r\n\r\n// 兜底:若未通过 app.use 安装插件,则在组件挂载时尝试注入默认的 iconfont 样式\r\nonMounted(() => {\r\n if (typeof window === 'undefined') return;\r\n const url = (cfg && cfg.iconCssUrl) || defaultRecycleUIConfig.iconCssUrl;\r\n if (!url) return;\r\n const selector = `link[rel=\"stylesheet\"][data-rcui-icon=\"true\"][href=\"${url}\"]`;\r\n const exists = document.head.querySelector(selector);\r\n if (!exists) {\r\n const link = document.createElement('link');\r\n link.rel = 'stylesheet';\r\n link.href = url as string;\r\n link.setAttribute('data-rcui-icon', 'true');\r\n document.head.appendChild(link);\r\n }\r\n});\r\n</script>\r\n\r\n<style scoped>\r\n.rc-icon {\r\n display: inline-block;\r\n vertical-align: -0.125em;\r\n}\r\n.rc-icon__unicode {\r\n /* 让 Unicode 文本走同一字体,确保显示 */\r\n font-family: inherit;\r\n line-height: 1;\r\n}\r\n.rc-icon--spin {\r\n animation: rc-icon-rot 1s linear infinite;\r\n}\r\n@keyframes rc-icon-rot {\r\n to { transform: rotate(360deg); }\r\n}\r\n</style>\r\n\r\n\r\n","<template>\r\n <button\r\n class=\"rc-button\"\r\n :class=\"[`rc-button--${type}`, `rc-button--${size}`, mode ? `rc-button--${mode}` : '', { 'is-block': block, 'is-disabled': disabled, 'is-loading': loading }]\"\r\n :style=\"{ borderRadius: radius }\"\r\n :disabled=\"disabled || loading\"\r\n @click=\"onClick\"\r\n >\r\n <span v-if=\"loading\" class=\"rc-button__spinner\" />\r\n <template v-else>\r\n <span v-if=\"preIcon || $slots.preIcon\" class=\"rc-button__icon rc-button__icon--prefix\">\r\n <slot name=\"preIcon\">\r\n <rc-icon v-if=\"preIcon\" :name=\"preIcon\" />\r\n </slot>\r\n </span>\r\n </template>\r\n <slot>{{ label }}</slot>\r\n <span v-if=\"!loading && (suffixIcon || $slots.suffixIcon)\" class=\"rc-button__icon rc-button__icon--suffix\">\r\n <slot name=\"suffixIcon\">\r\n <rc-icon v-if=\"suffixIcon\" :name=\"suffixIcon\" />\r\n </slot>\r\n </span>\r\n </button>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from 'vue';\r\nimport RcIcon from '../icon/index.vue';\r\ntype ButtonType = 'default' | 'primary' | 'success' | 'warning' | 'danger';\r\ntype ButtonSize = 'mini' | 'small' | 'medium' | 'large';\r\ntype ButtonMode = 'outline' | 'text';\r\n\r\ninterface Props {\r\n type?: ButtonType;\r\n size?: ButtonSize;\r\n /** 按钮模式:outline 中空模式,text 文本模式 */\r\n mode?: ButtonMode;\r\n block?: boolean;\r\n /** 按钮文本,提供时可不写默认插槽 */\r\n label?: string;\r\n /** 圆角;number 代表 px,string 支持百分比等写法(如 '50%')。也兼容 boolean,true 表示大圆角。 */\r\n round?: number | string | boolean;\r\n disabled?: boolean;\r\n loading?: boolean;\r\n /** 前置图标名称 */\r\n preIcon?: string;\r\n /** 后置图标名称 */\r\n suffixIcon?: string;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n type: 'default',\r\n size: 'medium',\r\n mode: undefined,\r\n block: false,\r\n label: '',\r\n round: 6,\r\n disabled: false,\r\n loading: false,\r\n preIcon: '',\r\n suffixIcon: '',\r\n});\r\n\r\nconst emit = defineEmits<{\r\n (e: 'click', ev: MouseEvent): void\r\n}>();\r\n\r\nconst onClick = (ev: MouseEvent) => {\r\n if (!props.disabled && !props.loading) emit('click', ev);\r\n};\r\n\r\nconst radius = computed(() => {\r\n const v = props.round;\r\n if (typeof v === 'boolean') return v ? '999px' : '6px';\r\n if (typeof v === 'number') return `${v}px`;\r\n return String(v);\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.rc-button {\r\n --rc-primary: #1677ff;\r\n --rc-success: #00b578;\r\n --rc-warning: #ff8f1f;\r\n --rc-danger: #ff3141;\r\n --rc-text: #323233;\r\n --rc-border: #dcdee0;\r\n --rc-white: #ffffff;\r\n\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 36px;\r\n padding: 0 16px;\r\n border: 1px solid var(--rc-border);\r\n border-radius: 6px;\r\n background: var(--rc-white);\r\n color: var(--rc-text);\r\n cursor: pointer;\r\n user-select: none;\r\n transition: all .2s ease;\r\n\r\n &.is-disabled { cursor: not-allowed; opacity: .6; }\r\n &.is-block { display: flex; width: 100%; }\r\n &.is-loading { opacity: .85; }\r\n\r\n &__spinner {\r\n width: 14px;\r\n height: 14px;\r\n margin-right: 6px;\r\n border: 2px solid currentColor;\r\n border-top-color: transparent;\r\n border-radius: 50%;\r\n animation: rc-spin 0.8s linear infinite;\r\n }\r\n\r\n &__icon {\r\n display: inline-flex;\r\n align-items: center;\r\n line-height: 1;\r\n color: currentColor;\r\n\r\n &--prefix {\r\n margin-right: 6px;\r\n }\r\n\r\n &--suffix {\r\n margin-left: 6px;\r\n }\r\n }\r\n\r\n &--primary { background: var(--rc-primary); color: var(--rc-white); border-color: var(--rc-primary); }\r\n &--success { background: var(--rc-success); color: var(--rc-white); border-color: var(--rc-success); }\r\n &--warning { background: var(--rc-warning); color: var(--rc-white); border-color: var(--rc-warning); }\r\n &--danger { background: var(--rc-danger); color: var(--rc-white); border-color: var(--rc-danger); }\r\n\r\n // outline 模式:中空,有边框,文字和边框颜色为 type 颜色\r\n &--outline {\r\n background: transparent;\r\n\r\n &.rc-button--default { color: var(--rc-text); border-color: var(--rc-border); }\r\n &.rc-button--primary { color: var(--rc-primary); border-color: var(--rc-primary); }\r\n &.rc-button--success { color: var(--rc-success); border-color: var(--rc-success); }\r\n &.rc-button--warning { color: var(--rc-warning); border-color: var(--rc-warning); }\r\n &.rc-button--danger { color: var(--rc-danger); border-color: var(--rc-danger); }\r\n }\r\n\r\n // text 模式:无边框,无背景,文字颜色为 type 颜色\r\n &--text {\r\n background: transparent;\r\n border-color: transparent;\r\n\r\n &.rc-button--default { color: var(--rc-text); }\r\n &.rc-button--primary { color: var(--rc-primary); }\r\n &.rc-button--success { color: var(--rc-success); }\r\n &.rc-button--warning { color: var(--rc-warning); }\r\n &.rc-button--danger { color: var(--rc-danger); }\r\n }\r\n\r\n &--mini { height: auto; padding: 2px 3px; font-size: 12px; }\r\n &--small { height: auto; padding: 3px 5px; font-size: 13px; }\r\n &--medium { height: auto; padding: 4px 8px; font-size: 14px; }\r\n &--large { height: auto; padding: 6px 14px; font-size: 16px; }\r\n}\r\n\r\n@keyframes rc-spin { to { transform: rotate(360deg) } }\r\n</style>\r\n\r\n\r\n\r\n","import type { App } from 'vue';\r\nimport Button from './index.vue';\r\n\r\n// 组件名使用全小写,以 <rc-button> 形式在模板中使用\r\n(Button as any).name = 'rc-button';\r\n\r\nexport function install(app: App) {\r\n app.component((Button as any).name, Button);\r\n return app;\r\n}\r\n\r\n\r\nexport default Button;\r\n","<template>\n <div class=\"rc-desc-item\" :style=\"{ width: computedWidth, flex: `0 0 ${computedWidth}` }\">\n <div class=\"rc-desc-item__label\" :style=\"labelStyle\">\n <slot name=\"label\">\n {{ label }}\n </slot>\n </div>\n <div class=\"rc-desc-item__value\">\n <slot>\n {{ value }}\n </slot>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, inject, Ref } from 'vue';\n\ndefineOptions({ name: 'rc-descriptions-item' });\n\nconst props = withDefaults(defineProps<{\n label?: string | number;\n value?: any;\n labelWidth?: string | number;\n /** 跨越的列数,默认 1,可传字符串数字 */\n span?: number | string;\n}>(), {\n label: '',\n value: '',\n labelWidth: '',\n span: 1,\n});\n\nconst providedWidth = inject<Ref<string>>('rcDescItemWidth', undefined as unknown as Ref<string>);\nconst providedSingleWidth = inject<Ref<string> | string>('rcDescSingleWidth', '' as unknown as Ref<string>);\nconst providedGap = inject<string>('rcDescGap', '0px');\nconst providedGapPx = inject<Ref<number> | number>('rcDescGapPx', 0 as unknown as Ref<number>);\nconst providedColCount = inject<Ref<number> | number>('rcDescColCount', 1 as unknown as Ref<number>);\nconst providedLabelWidth = inject<Ref<string> | string>('rcDescLabelWidth', '' as unknown as Ref<string>);\n\nconst spanNum = computed(() => {\n const n = typeof props.span === 'string' ? parseInt(props.span, 10) : props.span;\n const max = typeof (providedColCount as any)?.value === 'number' ? (providedColCount as any).value : (providedColCount as any);\n const safe = !Number.isNaN(n as number) && (n as number) > 0 ? (n as number) : 1;\n return Math.min(safe, max || 1);\n});\n\nconst computedWidth = computed(() => {\n const n = typeof (providedColCount as any)?.value === 'number' ? (providedColCount as any).value : (providedColCount as any);\n const gapPx = typeof (providedGapPx as any)?.value === 'number' ? (providedGapPx as any).value : (providedGapPx as any);\n const k = spanNum.value;\n if (!n || n <= 1) return '100%';\n if (k >= n) return '100%';\n // 展开为单层 calc:((100% - (n-1)*gap) * k / n + (k-1)*gap)\n const totalGap = (n - 1) * gapPx;\n const interGap = (k - 1) * gapPx;\n return `calc((100% - ${totalGap}px) * ${k} / ${n} + ${interGap}px)`;\n});\n\nconst labelStyle = computed(() => {\n const injected = typeof (providedLabelWidth as any)?.value === 'string'\n ? (providedLabelWidth as any).value\n : (providedLabelWidth as any);\n const w = props.labelWidth !== '' ? props.labelWidth : (injected || '');\n return w ? { width: typeof w === 'number' ? `${w}px` : String(w), flex: '0 0 auto' } : {};\n});\n</script>\n\n<style scoped>\n.rc-desc-item {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 6px 0;\n flex: 0 0 auto;\n}\n.rc-desc-item__label {\n color: #666;\n font-size: 14px;\n line-height: 22px;\n /* 不强制最小宽度,交由 label-width 控制 */\n min-width: 0;\n}\n.rc-desc-item__value {\n flex: 1 1 auto;\n font-size: 14px;\n line-height: 22px;\n}\n\n</style>\n\n\n","<template>\n <div class=\"rc-descriptions\">\n <div v-if=\"$slots.title || title\" class=\"rc-descriptions__title\">\n <slot name=\"title\">\n {{ title }}\n </slot>\n </div>\n <div class=\"rc-descriptions__body\" :style=\"{ gap: gapStyle }\" ref=\"wrapEl\">\n <template v-if=\"normalizedData.length\">\n <rcDescriptionsItem\n v-for=\"(it, idx) in normalizedData\"\n :key=\"idx\"\n :label=\"it.label\"\n :value=\"it.value\"\n :label-width=\"labelWidth\"\n />\n </template>\n <slot v-else />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, provide, ref, watchEffect } from 'vue';\nimport rcDescriptionsItem from './item.vue';\n\ndefineOptions({ name: 'rc-descriptions' });\n\ntype KeyMap = { key: string; value: string };\n\nconst props = withDefaults(defineProps<{\n title?: string;\n /** 每行展示的列数,支持数字或字符串数字 */\n column?: number | string;\n /** 列间距,支持数字(px)或字符串值,例如 '12px' */\n gap?: number | string;\n /** label 固定宽度,数字代表 px,也可直接传入 '120px' */\n labelWidth?: number | string | '';\n /** 直接通过数据渲染 */\n data?: Array<Record<string, any>>;\n /** data 的字段映射,如 { key: 'label', value: 'value' } */\n keyMap?: KeyMap;\n}>(), {\n column: 2,\n gap: 4,\n labelWidth: '',\n data: () => [],\n});\n\nconst wrapEl = ref<HTMLElement | null>(null);\nconst gapStyle = computed(() => (typeof props.gap === 'number' ? `${props.gap}px` : String(props.gap)));\nconst colCount = computed(() => {\n const n = typeof props.column === 'string' ? Number.parseInt(props.column as string, 10) : (props.column ?? 1);\n return !Number.isNaN(n) && n > 0 ? n : 1;\n});\n\n// compute child item width as percentage string or 'auto'\nconst itemWidth = ref<string>('100%');\nconst singleWidth = ref<string>('100%');\nwatchEffect(() => {\n const n = colCount.value;\n if (n <= 1) {\n itemWidth.value = '100%';\n singleWidth.value = '100%';\n } else {\n // subtract total horizontal gaps from 100%\n const gapPx = typeof props.gap === 'number' ? props.gap : parseFloat(String(props.gap)) || 0;\n const totalGap = (n - 1) * gapPx;\n const base = `calc((100% - ${totalGap}px) / ${n})`;\n singleWidth.value = base;\n itemWidth.value = base;\n }\n});\n\nprovide('rcDescItemWidth', itemWidth);\nprovide('rcDescSingleWidth', singleWidth);\nprovide('rcDescColCount', colCount);\nprovide('rcDescGapPx', computed(() => (typeof props.gap === 'number' ? props.gap : parseFloat(String(props.gap)) || 0)));\nconst labelWidthCss = computed(() => {\n if (props.labelWidth === '' || props.labelWidth === undefined) return '';\n return typeof props.labelWidth === 'number' ? `${props.labelWidth}px` : String(props.labelWidth);\n});\nprovide('rcDescLabelWidth', labelWidthCss);\nprovide('rcDescGap', computed(() => (typeof props.gap === 'number' ? `${props.gap}px` : String(props.gap))));\n\nconst normalizedData = computed(() => {\n const keyK = (props.keyMap?.key ?? 'label') as string;\n const keyV = (props.keyMap?.value ?? 'value') as string;\n if (!props.data?.length) return [];\n return props.data.map((it) => ({\n label: it?.[keyK],\n value: it?.[keyV],\n }));\n});\n\n</script>\n\n<style scoped>\n.rc-descriptions {\n width: 100%;\n}\n.rc-descriptions__title {\n font-weight: 600;\n font-size: 16px;\n margin: 0 0 12px 0;\n}\n.rc-description__row {\n display: contents;\n}\n.rc-descriptions__body {\n display: flex;\n flex-wrap: wrap;\n}\n\n</style>\n\n\n","import type { App } from 'vue';\r\nimport Descriptions from './index.vue';\r\nimport DescriptionsItem from './item.vue';\r\n\r\n(Descriptions as any).name = 'rc-descriptions';\r\n(DescriptionsItem as any).name = 'rc-descriptions-item';\r\n\r\nexport function install(app: App) {\r\n // 同时注册 kebab 与 PascalCase 名称,便于 <rc-descriptions>/<RcDescriptions> 使用\r\n app.component((Descriptions as any).name, Descriptions);\r\n app.component('RcDescriptions', Descriptions);\r\n app.component((DescriptionsItem as any).name, DescriptionsItem);\r\n app.component('RcDescriptionsItem', DescriptionsItem);\r\n return app;\r\n}\r\n\r\nexport const RcDescriptions = Descriptions;\r\nexport const RcDescriptionsItem = DescriptionsItem;\r\n\r\nexport default Descriptions;\r\n\r\n\r\n\r\n","<template>\n <div\n class=\"rc-card\"\n :class=\"[{ 'rc-card--bordered': bordered }]\"\n :style=\"wrapperStyle\"\n >\n <div\n v-if=\"$slots.title || title || $slots.status || status\"\n class=\"rc-card__top\"\n :style=\"{ backgroundColor: topBgColor || 'rgba(29, 133, 252, 0.05)' }\"\n >\n <div class=\"rc-card__title\">\n <slot name=\"title\">\n <span class=\"rc-card__title-text\">{{ title }}</span>\n </slot>\n </div>\n <div class=\"rc-card__status\" v-if=\"$slots.status || status\">\n <slot name=\"status\">\n <span class=\"rc-card__status-text\" :style=\"{ color: statusColor || 'var(--rc-primary)' }\">\n {{ status }}\n </span>\n </slot>\n </div>\n </div>\n\n <div class=\"rc-card__body\" :style=\"{ padding: bodyPadding, gap: bodyGap }\">\n <slot name=\"content\">\n <slot />\n </slot>\n </div>\n\n <div v-if=\"$slots.action\" class=\"rc-card__divider\" />\n\n <div v-if=\"$slots.action\" class=\"rc-card__action\">\n <slot name=\"action\" />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\ndefineOptions({ name: 'rc-card' });\n\ninterface Props {\n /** 卡片整体背景色,默认白色 */\n color?: string;\n /** 顶部色块背景色 */\n topBgColor?: string;\n /** 标题文本(可用 slot=\"title\" 自定义) */\n title?: string;\n /** 右侧状态文案(可用 slot=\"status\" 自定义) */\n status?: string;\n /** 状态文本颜色 */\n statusColor?: string;\n /** 圆角:数值代表 px,字符串可用百分比 */\n round?: number | string;\n /** 是否描边 */\n bordered?: boolean;\n /** 阴影强度:0/1/2/3... -> 转换为不同阴影强度 */\n elevation?: number;\n /** 内边距(CSS 值,如 '16px 12px') */\n padding?: string;\n /** 主体内容的垂直间距(px 或 CSS 字符串) */\n gap?: number | string;\n /** 宽度(px/百分比) */\n width?: string | number;\n /** 高度(px/百分比) */\n height?: string | number;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n color: 'var(--rc-white)',\n topBgColor: 'rgba(29, 133, 252, 0.05)',\n title: '',\n status: '',\n statusColor: 'var(--rc-primary)',\n round: 8,\n bordered: false,\n elevation: 2,\n padding: '16px',\n gap: 12,\n width: '100%',\n height: '',\n});\n\nconst wrapperStyle = computed(() => {\n const radius =\n typeof props.round === 'boolean'\n ? props.round\n ? '12px'\n : '0'\n : typeof props.round === 'number'\n ? `${props.round}px`\n : String(props.round);\n\n return {\n backgroundColor: props.color || 'var(--rc-white)',\n borderRadius: radius,\n boxShadow: shadowByLevel(props.elevation),\n width: toCssSize(props.width),\n height: toCssSize(props.height),\n } as Record<string, string>;\n});\n\nconst bodyPadding = computed(() => props.padding || '16px');\nconst bodyGap = computed(() =>\n typeof props.gap === 'number' ? `${props.gap}px` : String(props.gap)\n);\n\nfunction toCssSize(v?: string | number) {\n if (v === undefined || v === null || v === '') return '';\n return typeof v === 'number' ? `${v}px` : String(v);\n}\n\nfunction shadowByLevel(level: number) {\n if (!level || level <= 0) return 'none';\n // 简单的多层阴影(可按需微调)\n const base = 4 * level;\n return `0 ${Math.round(base / 2)}px ${base}px rgba(0,0,0,0.06), 0 ${Math.round(\n base / 4\n )}px ${Math.round(base / 2)}px rgba(0,0,0,0.04)`;\n}\n</script>\n\n<style scoped>\n.rc-card {\n --rc-white: #ffffff;\n --rc-border: #e5e6eb;\n --rc-primary: #1677ff;\n\n display: flex;\n flex-direction: column;\n width: 100%;\n border: 1px solid transparent;\n background: var(.rc-white);\n}\n.rc-card--bordered {\n border-color: var(--rc-border);\n}\n\n.rc-card__top {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px;\n border-top-left-radius: inherit;\n border-top-right-radius: inherit;\n}\n.rc-card__title {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.rc-card__title-text {\n font-weight: 600;\n font-size: 16px;\n color: #1d2129;\n}\n.rc-card__status-text {\n font-size: 14px;\n}\n.rc-card__body {\n display: flex;\n flex-direction: column;\n}\n.rc-card__divider {\n height: 1px;\n background: var(--rc-border);\n}\n.rc-card__action {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n}\n</style>\n\n\n","import type { App } from 'vue';\r\nimport Card from './index.vue';\r\n\r\n// 同时注册小写与驼峰,便于 <rc-card> / <RcCard> 两种写法\r\n(Card as any).name = 'rc-card';\r\nconst PascalName = 'RcCard';\r\n\r\nexport function install(app: App) {\r\n app.component((Card as any).name, Card);\r\n app.component(PascalName, Card);\r\n return app;\r\n}\r\n\r\nexport default Card;\r\n\r\n\r\n","<template>\r\n <teleport to=\"body\">\r\n <transition name=\"rc-toast-fade\" @after-leave=\"onAfterLeave\">\r\n <div v-if=\"visible\" class=\"rc-toast\" :class=\"[`rc-toast--${type}`]\">\r\n <div v-if=\"mask\" class=\"rc-toast__mask\" />\r\n <div class=\"rc-toast__content\">\r\n <div v-if=\"type === 'loading'\" class=\"rc-toast__spinner\" />\r\n <div v-else-if=\"type === 'success'\" class=\"rc-toast__icon rc-toast__icon--success\" />\r\n <div v-else-if=\"type === 'fail'\" class=\"rc-toast__icon rc-toast__icon--fail\" />\r\n <div class=\"rc-toast__text\">{{ message }}</div>\r\n </div>\r\n </div>\r\n </transition>\r\n </teleport>\r\n <slot />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { onMounted, onUnmounted, ref, watch, defineExpose } from 'vue';\r\n\r\nexport type ToastType = 'text' | 'success' | 'fail' | 'loading';\r\nexport interface ToastProps {\r\n message?: string;\r\n type?: ToastType;\r\n duration?: number;\r\n mask?: boolean;\r\n /** 服务端关闭回调,用于卸载容器 */\r\n onAfterLeave?: () => void;\r\n}\r\n\r\nconst props = withDefaults(defineProps<ToastProps>(), {\r\n message: '',\r\n type: 'text',\r\n duration: 2000,\r\n mask: false,\r\n});\r\n\r\nconst visible = ref(true);\r\nlet timer: any;\r\n\r\nfunction clearTimer() {\r\n if (timer) {\r\n clearTimeout(timer);\r\n timer = null;\r\n }\r\n}\r\n\r\nfunction close() {\r\n clearTimer();\r\n visible.value = false;\r\n}\r\n\r\ndefineExpose({ close });\r\n\r\nonMounted(() => {\r\n if (props.duration && props.duration > 0) {\r\n timer = setTimeout(() => {\r\n close();\r\n }, props.duration);\r\n }\r\n});\r\n\r\nonUnmounted(() => {\r\n clearTimer();\r\n});\r\n</script>\r\n\r\n<style scoped>\r\n.rc-toast {\r\n position: fixed;\r\n inset: 0;\r\n z-index: 9999;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n.rc-toast__mask {\r\n position: absolute;\r\n inset: 0;\r\n background: rgba(0, 0, 0, 0.35);\r\n pointer-events: auto;\r\n backdrop-filter: blur(1px);\r\n}\r\n.rc-toast__content {\r\n position: relative;\r\n max-width: 80%;\r\n background: rgba(0, 0, 0, 0.75);\r\n color: #fff;\r\n border-radius: 12px;\r\n padding: 12px 14px;\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 8px;\r\n box-shadow: 0 6px 16px rgba(0,0,0,0.2);\r\n}\r\n.rc-toast__text {\r\n font-size: 14px;\r\n line-height: 1.4;\r\n}\r\n.rc-toast__spinner {\r\n width: 18px;\r\n height: 18px;\r\n border: 2px solid rgba(255,255,255,0.35);\r\n border-top-color: #fff;\r\n border-radius: 50%;\r\n animation: rc-toast-spin 0.8s linear infinite;\r\n}\r\n.rc-toast__icon {\r\n width: 18px;\r\n height: 18px;\r\n border-radius: 50%;\r\n position: relative;\r\n flex: 0 0 18px;\r\n}\r\n.rc-toast__icon--success::before {\r\n content: '';\r\n position: absolute;\r\n left: 3px;\r\n top: 3px;\r\n width: 10px;\r\n height: 10px;\r\n border-right: 2px solid #fff;\r\n border-bottom: 2px solid #fff;\r\n transform: rotate(45deg);\r\n}\r\n.rc-toast__icon--fail::before,\r\n.rc-toast__icon--fail::after {\r\n content: '';\r\n position: absolute;\r\n left: 3px;\r\n right: 3px;\r\n top: 8px;\r\n height: 2px;\r\n background: #fff;\r\n}\r\n.rc-toast__icon--fail::before {\r\n transform: rotate(45deg);\r\n}\r\n.rc-toast__icon--fail::after {\r\n transform: rotate(-45deg);\r\n}\r\n\r\n.rc-toast-fade-enter-active,\r\n.rc-toast-fade-leave-active {\r\n transition: opacity .2s ease;\r\n}\r\n.rc-toast-fade-enter-from,\r\n.rc-toast-fade-leave-to {\r\n opacity: 0;\r\n}\r\n@keyframes rc-toast-spin {\r\n to { transform: rotate(360deg); }\r\n}\r\n</style>\r\n\r\n\r\n","import { App, createApp } from 'vue';\r\nimport Toast, { type ToastProps } from './index.vue';\r\n\r\nexport type { ToastProps };\r\nexport interface ShowToastOptions {\r\n message?: string;\r\n type?: 'text' | 'success' | 'fail' | 'loading';\r\n duration?: number;\r\n mask?: boolean;\r\n /** 关闭时回调(仅服务方式有效) */\r\n onClose?: () => void;\r\n}\r\n\r\nlet app: App<Element> | null = null;\r\nlet host: HTMLDivElement | null = null;\r\n\r\nfunction unmount() {\r\n if (app) {\r\n app.unmount();\r\n app = null;\r\n }\r\n if (host) {\r\n document.body.removeChild(host);\r\n host = null;\r\n }\r\n}\r\n\r\nexport function showToast(options: string | ShowToastOptions) {\r\n const opt: ShowToastOptions =\r\n typeof options === 'string' ? { message: options } : (options || {});\r\n unmount();\r\n host = document.createElement('div');\r\n document.body.appendChild(host);\r\n const toastProps: ToastProps = {\r\n message: opt.message,\r\n type: (opt as any).type ?? 'text',\r\n duration: (opt as any).duration ?? 2000,\r\n mask: (opt as any).mask ?? false,\r\n onAfterLeave: () => {\r\n unmount();\r\n opt.onClose?.();\r\n },\r\n };\r\n app = createApp(Toast, toastProps as any);\r\n app.mount(host);\r\n return {\r\n close: hideToast,\r\n };\r\n}\r\n\r\nexport function hideToast() {\r\n if (!app) return;\r\n // 调用暴露的 close 方法\r\n // @ts-ignore\r\n app._instance?.exposed?.close?.();\r\n}\r\n\r\n// 组件注册(可选,提供 rc-toast 用于手动放置 Portal)\r\n(Toast as any).name = 'rc-toast';\r\nexport function install(app: App) {\r\n app.component((Toast as any).name, Toast);\r\n return app;\r\n}\r\n\r\nexport default Toast;\r\n\r\n\r\n","<template>\r\n <div class=\"rc-message\" role=\"alert\" aria-live=\"polite\">\r\n <transition-group name=\"rc-message-fade\" tag=\"div\">\r\n <div\r\n v-for=\"m in messages\"\r\n :key=\"m.id\"\r\n class=\"rc-message__item\"\r\n :class=\"`rc-message--${m.type}`\"\r\n >\r\n <span class=\"rc-message__content\">{{ m.content }}</span>\r\n </div>\r\n </transition-group>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { reactive } from 'vue';\r\n\r\nexport type MessageType = 'info' | 'success' | 'warning' | 'error' | 'loading';\r\nexport interface MessageItem {\r\n id: number;\r\n type: MessageType;\r\n content: string;\r\n duration: number; // ms; 0 = persistent (except loading default)\r\n}\r\n\r\nconst messages = reactive<MessageItem[]>([]);\r\nlet uid = 1;\r\n\r\nfunction remove(id: number) {\r\n const idx = messages.findIndex((x) => x.id === id);\r\n if (idx >= 0) messages.splice(idx, 1);\r\n}\r\n\r\nfunction add(type: MessageType, content: string, duration: number) {\r\n const id = uid++;\r\n messages.push({ id, type, content, duration });\r\n if (duration > 0) {\r\n window.setTimeout(() => remove(id), duration);\r\n }\r\n return id;\r\n}\r\n\r\ndefineExpose({ add, remove });\r\n</script>\r\n\r\n<style scoped>\r\n.rc-message {\r\n position: fixed;\r\n top: 16px;\r\n left: 0;\r\n right: 0;\r\n z-index: 10000;\r\n pointer-events: none;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: 8px;\r\n}\r\n.rc-message__item {\r\n pointer-events: auto;\r\n min-width: 120px;\r\n max-width: 80%;\r\n padding: 8px 12px;\r\n border-radius: 6px;\r\n color: #fff;\r\n background: rgba(0, 0, 0, 0.78);\r\n box-shadow: 0 6px 16px rgba(0,0,0,0.2);\r\n font-size: 14px;\r\n}\r\n.rc-message--success { background: rgba(22,119,255,0.9); }\r\n.rc-message--warning { background: rgba(250,173,20,0.95); }\r\n.rc-message--error { background: rgba(245,63,63,0.95); }\r\n.rc-message--info { background: rgba(0,0,0,0.78); }\r\n.rc-message--loading { background: rgba(0,0,0,0.78); }\r\n\r\n.rc-message-fade-enter-active,\r\n.rc-message-fade-leave-active {\r\n transition: all .2s ease;\r\n}\r\n.rc-message-fade-enter-from,\r\n.rc-message-fade-leave-to {\r\n opacity: 0;\r\n transform: translateY(-6px);\r\n}\r\n</style>\r\n\r\n\r\n","import { createVNode, render, type App } from 'vue';\r\nimport MessageHost from './index.vue';\r\n\r\ntype MessageType = 'info' | 'success' | 'warning' | 'error' | 'loading';\r\n\r\nexport interface MessageOptions {\r\n content: string;\r\n duration?: number; // ms; default 2000, loading 默认 0\r\n type?: MessageType;\r\n}\r\n\r\nlet container: HTMLElement | null = null;\r\nlet hostExposed: any = null;\r\n\r\nfunction ensureHost() {\r\n if (container && hostExposed) return;\r\n container = document.createElement('div');\r\n document.body.appendChild(container);\r\n const vnode = createVNode(MessageHost, {});\r\n render(vnode, container);\r\n hostExposed = (vnode.component as any)?.exposed;\r\n}\r\n\r\nfunction open(type: MessageType, content: string, duration?: number) {\r\n ensureHost();\r\n const d = typeof duration === 'number'\r\n ? duration\r\n : (type === 'loading' ? 0 : 2000);\r\n return hostExposed?.add?.(type, content, d);\r\n}\r\n\r\nexport const message = {\r\n open(opts: MessageOptions) {\r\n return open(opts.type || 'info', opts.content, opts.duration);\r\n },\r\n info(content: string, duration?: number) {\r\n return open('info', content, duration);\r\n },\r\n success(content: string, duration?: number) {\r\n return open('success', content, duration);\r\n },\r\n warning(content: string, duration?: number) {\r\n return open('warning', content, duration);\r\n },\r\n error(content: string, duration?: number) {\r\n return open('error', content, duration);\r\n },\r\n loading(content: string, duration?: number) {\r\n return open('loading', content, duration);\r\n },\r\n destroy() {\r\n if (container) {\r\n render(null, container);\r\n container.remove();\r\n container = null;\r\n hostExposed = null;\r\n }\r\n },\r\n};\r\n\r\nexport default message;\r\n\r\n// 可选:提供 install,注入到 app.config.globalProperties 以便 this.$message 使用\r\nexport function install(app: App) {\r\n (app.config.globalProperties as any).$message = message;\r\n return app;\r\n}\r\n\r\n\r\n","import type { App } from 'vue';\r\nimport Icon from './index.vue';\r\n\r\n(Icon as any).name = 'rc-icon';\r\n\r\nexport function install(app: App) {\r\n app.component((Icon as any).name, Icon);\r\n app.component('RcIcon', Icon);\r\n return app;\r\n}\r\n\r\nexport const RcIcon = Icon;\r\nexport default Icon;\r\n\r\n\r\n","<template>\r\n <teleport to=\"body\">\r\n <transition name=\"rc-popup-fade\">\r\n <div\r\n v-if=\"visible && props.overlay\"\r\n class=\"rc-popup__overlay\"\r\n :class=\"{ 'rc-popup__overlay--transparent': props.overlayClass === 'transparent' }\"\r\n :style=\"props.overlayStyle\"\r\n @click=\"handleOverlayClick\"\r\n ></div>\r\n </transition>\r\n\r\n <transition :name=\"transitionName\">\r\n <div\r\n v-if=\"visible\"\r\n ref=\"popupRef\"\r\n class=\"rc-popup\"\r\n :class=\"[\r\n `rc-popup--${position}`,\r\n { 'rc-popup--round': round }\r\n ]\"\r\n :style=\"popupStyle\"\r\n @click.stop\r\n >\r\n <div v-if=\"closeable\" class=\"rc-popup__close\" :class=\"`rc-popup__close--${closeIconPosition}`\" @click=\"handleClose\">\r\n <rc-icon :name=\"closeIcon\" class=\"rc-popup__close-icon\" />\r\n </div>\r\n\r\n <div class=\"rc-popup__content\">\r\n <slot />\r\n </div>\r\n </div>\r\n </transition>\r\n </teleport>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, watch, onUnmounted } from 'vue';\r\nimport RcIcon from '../icon/index.vue';\r\n\r\ndefineOptions({ name: 'rc-popup' });\r\n\r\ntype PopupPosition = 'top' | 'bottom' | 'left' | 'right' | 'center';\r\ntype CloseIconPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\r\n\r\ninterface Props {\r\n /** 是否显示弹出层 */\r\n modelValue?: boolean;\r\n /** 弹出位置 */\r\n position?: PopupPosition;\r\n /** 是否显示遮罩层 */\r\n overlay?: boolean;\r\n /** 遮罩层样式类名 */\r\n overlayClass?: string;\r\n /** 遮罩层样式 */\r\n overlayStyle?: Record<string, string>;\r\n /** 是否显示关闭图标 */\r\n closeable?: boolean;\r\n /** 关闭图标位置 */\r\n closeIconPosition?: CloseIconPosition;\r\n /** 自定义关闭图标 */\r\n closeIcon?: string;\r\n /** 是否显示圆角 */\r\n round?: boolean;\r\n /** 弹出层样式 */\r\n popupStyle?: Record<string, string>;\r\n /** 是否点击遮罩层关闭 */\r\n closeOnClickOverlay?: boolean;\r\n /** 是否锁定背景滚动 */\r\n lockScroll?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n modelValue: false,\r\n position: 'center',\r\n overlay: true,\r\n overlayClass: '',\r\n overlayStyle: undefined,\r\n closeable: false,\r\n closeIconPosition: 'top-right',\r\n closeIcon: 'icon_close',\r\n round: false,\r\n popupStyle: undefined,\r\n closeOnClickOverlay: true,\r\n lockScroll: 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 (e: 'click-overlay'): void;\r\n}>();\r\n\r\nconst popupRef = ref<HTMLElement>();\r\nconst visible = ref(props.modelValue);\r\n\r\n// 监听 modelValue 变化\r\nwatch(\r\n () => props.modelValue,\r\n (val) => {\r\n visible.value = val;\r\n if (val) {\r\n emit('open');\r\n if (props.lockScroll) {\r\n lockBodyScroll();\r\n }\r\n } else {\r\n emit('close');\r\n if (props.lockScroll) {\r\n unlockBodyScroll();\r\n }\r\n }\r\n },\r\n { immediate: true }\r\n);\r\n\r\n\r\n// 监听 visible 变化,同步到 modelValue\r\nwatch(visible, (val) => {\r\n if (val !== props.modelValue) {\r\n emit('update:modelValue', val);\r\n }\r\n});\r\n\r\n// 计算过渡动画名称\r\nconst transitionName = computed(() => {\r\n return `rc-popup-slide-${props.position}`;\r\n});\r\n\r\n// 计算弹出层样式\r\nconst popupStyle = computed(() => {\r\n return { ...(props.popupStyle || {}) };\r\n});\r\n\r\n\r\n// 锁定背景滚动\r\nlet scrollLocked = false;\r\nfunction lockBodyScroll() {\r\n if (scrollLocked) return;\r\n scrollLocked = true;\r\n document.body.style.overflow = 'hidden';\r\n}\r\n\r\n// 解锁背景滚动\r\nfunction unlockBodyScroll() {\r\n if (!scrollLocked) return;\r\n scrollLocked = false;\r\n document.body.style.overflow = '';\r\n}\r\n\r\n// 处理遮罩层点击\r\nfunction handleOverlayClick() {\r\n emit('click-overlay');\r\n if (props.closeOnClickOverlay) {\r\n close();\r\n }\r\n}\r\n\r\n// 处理关闭\r\nfunction handleClose() {\r\n close();\r\n}\r\n\r\n// 关闭弹出层\r\nfunction close() {\r\n visible.value = false;\r\n}\r\n\r\n// 打开弹出层\r\nfunction open() {\r\n visible.value = true;\r\n}\r\n\r\nonUnmounted(() => {\r\n unlockBodyScroll();\r\n});\r\n\r\n// 暴露方法(供函数式调用使用)\r\ndefineExpose({\r\n open,\r\n close,\r\n visible,\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.rc-popup {\r\n --rc-primary: #1677ff;\r\n --rc-text: #323233;\r\n --rc-border: #dcdee0;\r\n --rc-white: #ffffff;\r\n --rc-overlay: rgba(0, 0, 0, 0.7);\r\n\r\n position: fixed;\r\n z-index: 2000;\r\n max-height: 100%;\r\n max-width: 100%;\r\n background: var(--rc-white);\r\n overflow: auto;\r\n\r\n &--round {\r\n border-radius: 8px 8px 0 0;\r\n }\r\n\r\n &--top {\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n width: 100%;\r\n }\r\n\r\n &--bottom {\r\n bottom: 0;\r\n left: 0;\r\n right: 0;\r\n width: 100%;\r\n }\r\n\r\n &--left {\r\n top: 0;\r\n bottom: 0;\r\n left: 0;\r\n height: 100%;\r\n }\r\n\r\n &--right {\r\n top: 0;\r\n bottom: 0;\r\n right: 0;\r\n height: 100%;\r\n }\r\n\r\n &--center {\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n max-width: 90vw;\r\n max-height: 90vh;\r\n border-radius: 8px;\r\n }\r\n\r\n &__overlay {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n z-index: 1999;\r\n background: rgba(0, 0, 0, 0.7);\r\n\r\n &--transparent {\r\n background: transparent;\r\n }\r\n }\r\n\r\n &__close {\r\n position: absolute;\r\n z-index: 1;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n cursor: pointer;\r\n transition: opacity 0.2s;\r\n\r\n &:hover {\r\n opacity: 0.8;\r\n }\r\n\r\n &--top-left {\r\n top: 8px;\r\n left: 8px;\r\n }\r\n\r\n &--top-right {\r\n top: 8px;\r\n right: 8px;\r\n }\r\n\r\n &--bottom-left {\r\n bottom: 8px;\r\n left: 8px;\r\n }\r\n\r\n &--bottom-right {\r\n bottom: 8px;\r\n right: 8px;\r\n }\r\n }\r\n\r\n &__close-icon {\r\n font-size: 18px;\r\n color: var(--rc-text);\r\n }\r\n\r\n &__content {\r\n width: 100%;\r\n height: 100%;\r\n }\r\n}\r\n\r\n// 过渡动画\r\n.rc-popup-fade-enter-active,\r\n.rc-popup-fade-leave-active {\r\n transition: opacity 0.3s;\r\n}\r\n\r\n.rc-popup-fade-enter-from,\r\n.rc-popup-fade-leave-to {\r\n opacity: 0;\r\n}\r\n\r\n.rc-popup-slide-top-enter-active,\r\n.rc-popup-slide-top-leave-active {\r\n transition: transform 0.3s;\r\n}\r\n\r\n.rc-popup-slide-top-enter-from,\r\n.rc-popup-slide-top-leave-to {\r\n transform: translateY(-100%);\r\n}\r\n\r\n.rc-popup-slide-bottom-enter-active,\r\n.rc-popup-slide-bottom-leave-active {\r\n transition: transform 0.3s;\r\n}\r\n\r\n.rc-popup-slide-bottom-enter-from,\r\n.rc-popup-slide-bottom-leave-to {\r\n transform: translateY(100%);\r\n}\r\n\r\n.rc-popup-slide-left-enter-active,\r\n.rc-popup-slide-left-leave-active {\r\n transition: transform 0.3s;\r\n}\r\n\r\n.rc-popup-slide-left-enter-from,\r\n.rc-popup-slide-left-leave-to {\r\n transform: translateX(-100%);\r\n}\r\n\r\n.rc-popup-slide-right-enter-active,\r\n.rc-popup-slide-right-leave-active {\r\n transition: transform 0.3s;\r\n}\r\n\r\n.rc-popup-slide-right-enter-from,\r\n.rc-popup-slide-right-leave-to {\r\n transform: translateX(100%);\r\n}\r\n</style>\r\n\r\n","import type { App } from 'vue';\r\nimport Popup from './index.vue';\r\n\r\n// 组件名使用全小写,以 <rc-popup> 形式在模板中使用\r\n(Popup as any).name = 'rc-popup';\r\nconst PascalName = 'RcPopup';\r\n\r\nexport function install(app: App) {\r\n app.component((Popup as any).name, Popup);\r\n app.component(PascalName, Popup);\r\n return app;\r\n}\r\n\r\nexport default Popup;\r\n\r\n","<template>\r\n <div>\r\n <!-- 标题栏 -->\r\n <div v-if=\"showTitle\" class=\"rc-calendar__header\">\r\n <div class=\"rc-calendar__header-title\">{{ title }}</div>\r\n <span\r\n class=\"rc-calendar__header-clear\"\r\n :class=\"{ 'is-disabled': !hasValue }\"\r\n @click=\"handleHeaderClear\"\r\n >\r\n 清空\r\n </span>\r\n </div>\r\n\r\n <!-- 快捷选择 -->\r\n <div v-if=\"range\" class=\"rc-calendar__shortcuts\">\r\n <div class=\"rc-calendar__shortcuts-scroll\">\r\n <div\r\n v-for=\"option in availableShortcuts\"\r\n :key=\"option.key\"\r\n class=\"rc-calendar__shortcut-item\"\r\n @click=\"handleShortcutClick(option)\"\r\n >\r\n {{ option.label }}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 月份导航 -->\r\n <div class=\"rc-calendar__month-title\">\r\n <div class=\"rc-calendar__nav-button\" @click=\"prevMonth\">\r\n <rc-icon name=\"icon_caret-left\" class=\"rc-calendar__nav-icon\" />\r\n </div>\r\n <div class=\"rc-calendar__month-text\" @click=\"openMonthPicker\">\r\n {{ monthTitle }}\r\n </div>\r\n <div class=\"rc-calendar__nav-button\" @click=\"nextMonth\">\r\n <rc-icon name=\"icon_caret-right\" class=\"rc-calendar__nav-icon\" />\r\n </div>\r\n </div>\r\n\r\n <!-- 星期标题 -->\r\n <div class=\"rc-calendar__weekdays\">\r\n <div v-for=\"day in weekdays\" :key=\"day\" class=\"rc-calendar__weekday\">\r\n {{ day }}\r\n </div>\r\n </div>\r\n\r\n <!-- 日期网格 -->\r\n <div class=\"rc-calendar__days\">\r\n <div\r\n v-for=\"(day, index) in monthDays\"\r\n :key=\"index\"\r\n class=\"rc-calendar__day\"\r\n :class=\"getDayClass(day)\"\r\n @click=\"onSelectDay(day)\"\r\n >\r\n <div class=\"rc-calendar__day-content\">\r\n <span class=\"rc-calendar__day-text\">{{ day.text }}</span>\r\n <span v-if=\"day.bottomInfo\" class=\"rc-calendar__day-bottom\">{{ day.bottomInfo }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 底部操作栏(区间模式) -->\r\n <div v-if=\"range && showFooter\" class=\"rc-calendar__footer\">\r\n <rc-button type=\"default\" class=\"rc-calendar__footer-reset\" @click=\"onClear\">取消</rc-button>\r\n <rc-button\r\n type=\"primary\"\r\n class=\"rc-calendar__footer-confirm\"\r\n :disabled=\"!isRangeComplete\"\r\n @click=\"onConfirm\"\r\n >\r\n {{ isRangeComplete ? `确定(${selectedRangeCount}项)` : '确定' }}\r\n </rc-button>\r\n </div>\r\n \r\n <!-- 年月选择器 - 覆盖在日历面板上 -->\r\n <transition name=\"rc-calendar-fade\">\r\n <div v-if=\"showMonthPicker\" class=\"rc-calendar__month-picker-overlay\">\r\n <div class=\"rc-calendar__month-picker\">\r\n <div class=\"rc-calendar__month-picker-header\">\r\n <rc-button type=\"default\" mode=\"text\" size=\"small\" @click=\"onCloseMonthPicker\">取消</rc-button>\r\n <div class=\"rc-calendar__month-picker-title\">\r\n <span @click=\"onPickerModeChange('year')\">{{ tempYear }}年</span>\r\n <span v-if=\"pickerMode === 'month'\"> - </span>\r\n <span v-if=\"pickerMode === 'month'\" @click=\"onPickerModeChange('month')\">{{ tempMonth }}月</span>\r\n </div>\r\n <rc-button \r\n v-if=\"pickerMode === 'year'\"\r\n type=\"primary\" \r\n mode=\"text\" \r\n size=\"small\" \r\n @click=\"selectCurrentYear\"\r\n >\r\n 本年\r\n </rc-button>\r\n <rc-button \r\n v-if=\"pickerMode === 'month'\"\r\n type=\"primary\" \r\n mode=\"text\" \r\n size=\"small\" \r\n @click=\"selectCurrentMonth\"\r\n >\r\n 本月\r\n </rc-button>\r\n </div>\r\n \r\n <!-- 年份选择 -->\r\n <div v-if=\"pickerMode === 'year'\" class=\"rc-calendar__year-picker-content\">\r\n <div \r\n class=\"rc-calendar__year-picker-scroll\" \r\n ref=\"yearScrollRef\" \r\n @scroll=\"handleYearScroll\"\r\n >\r\n <div class=\"rc-calendar__year-picker-spacer\" :style=\"{ height: `${Math.floor((visibleYearStart - dynamicMinYear) / itemsPerRow) * itemHeight}px` }\"></div>\r\n <div class=\"rc-calendar__year-picker-grid\">\r\n <div\r\n v-for=\"year in visibleYearList\"\r\n :key=\"year\"\r\n class=\"rc-calendar__year-picker-item\"\r\n :class=\"{\r\n 'is-selected': tempYear === year,\r\n 'is-disabled': isYearDisabled(year)\r\n }\"\r\n @click=\"selectYear(year)\"\r\n >\r\n {{ year }}\r\n </div>\r\n </div>\r\n <div class=\"rc-calendar__year-picker-spacer\" :style=\"{ height: `${Math.ceil((dynamicMaxYear - visibleYearEnd) / itemsPerRow) * itemHeight}px` }\"></div>\r\n </div>\r\n </div>\r\n \r\n <!-- 月份选择 -->\r\n <div v-if=\"pickerMode === 'month'\" class=\"rc-calendar__month-picker-content\">\r\n <div\r\n v-for=\"month in 12\"\r\n :key=\"month\"\r\n class=\"rc-calendar__month-picker-item\"\r\n :class=\"{\r\n 'is-selected': tempMonth === month,\r\n 'is-disabled': isMonthDisabled(tempYear, month)\r\n }\"\r\n @click=\"selectMonth(month)\"\r\n >\r\n {{ month }}月\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </transition>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, watch, nextTick } from 'vue';\r\nimport RcIcon from '../icon';\r\nimport RcButton from '../button';\r\n\r\ninterface DayItem {\r\n date: Date;\r\n type: string;\r\n text: string;\r\n bottomInfo?: string;\r\n}\r\n\r\ninterface Props {\r\n showTitle?: boolean;\r\n title?: string;\r\n range?: boolean;\r\n selectedDate: string | null;\r\n rangeStart: string | null;\r\n rangeEnd: string | null;\r\n minDate?: string;\r\n maxDate?: string;\r\n disabledDate?: (date: Date) => boolean;\r\n formatter?: (day: DayItem) => { text?: string; bottomInfo?: string };\r\n showFooter?: boolean;\r\n maxRangeDays?: number;\r\n}\r\n\r\nconst props = defineProps<Props>();\r\n\r\nconst emit = defineEmits<{\r\n (e: 'select-day', day: DayItem): void;\r\n (e: 'clear'): void;\r\n (e: 'confirm'): void;\r\n (e: 'shortcut-select', range: [string, string]): void;\r\n}>();\r\n\r\n// 常量\r\nconst weekdays = ['日', '一', '二', '三', '四', '五', '六'];\r\nconst itemHeight = 48; // 每个年份项的高度(包括 margin)\r\nconst itemsPerRow = 3; // 每行显示的年份数\r\nconst visibleRows = 7; // 可见的行数\r\n\r\n// 解析日期字符串\r\nfunction parseDate(dateStr: string | null | undefined): Date | null {\r\n if (!dateStr) return null;\r\n const date = new Date(dateStr);\r\n return isNaN(date.getTime()) ? null : date;\r\n}\r\n\r\n// 格式化日期为 YYYY-MM-DD\r\nfunction formatDate(date: Date): string {\r\n const year = date.getFullYear();\r\n const month = String(date.getMonth() + 1).padStart(2, '0');\r\n const day = String(date.getDate()).padStart(2, '0');\r\n return `${year}-${month}-${day}`;\r\n}\r\n\r\n// 当前显示的月份\r\nconst currentDate = ref(new Date());\r\n\r\n// 根据选中的日期初始化 currentDate\r\nwatch(\r\n () => [props.selectedDate, props.rangeStart],\r\n () => {\r\n if (props.range && props.rangeStart) {\r\n const date = parseDate(props.rangeStart);\r\n if (date) {\r\n currentDate.value = date;\r\n }\r\n } else if (!props.range && props.selectedDate) {\r\n const date = parseDate(props.selectedDate);\r\n if (date) {\r\n currentDate.value = date;\r\n }\r\n }\r\n },\r\n { immediate: true }\r\n);\r\n\r\n// 判断是否是今天\r\nfunction isToday(date: Date): boolean {\r\n const today = new Date();\r\n return (\r\n date.getFullYear() === today.getFullYear() &&\r\n date.getMonth() === today.getMonth() &&\r\n date.getDate() === today.getDate()\r\n );\r\n}\r\n\r\n// 判断日期是否在区间内\r\nfunction isInRange(date: Date): boolean {\r\n if (!props.rangeStart || !props.rangeEnd) return false;\r\n const dateStr = formatDate(date);\r\n const start = props.rangeStart;\r\n const end = props.rangeEnd;\r\n return dateStr > start && dateStr < end;\r\n}\r\n\r\n// 判断日期是否被禁用\r\nfunction isDisabled(date: Date): boolean {\r\n if (props.disabledDate && props.disabledDate(date)) {\r\n return true;\r\n }\r\n \r\n const dateStr = formatDate(date);\r\n \r\n if (props.minDate && dateStr < props.minDate) {\r\n return true;\r\n }\r\n if (props.maxDate && dateStr > props.maxDate) {\r\n return true;\r\n }\r\n \r\n return false;\r\n}\r\n\r\n// 计算指定月份的日期\r\nfunction getMonthDays(year: number, month: number): DayItem[] {\r\n const firstDay = new Date(year, month, 1);\r\n const lastDay = new Date(year, month + 1, 0);\r\n const firstDayWeek = firstDay.getDay();\r\n const daysInMonth = lastDay.getDate();\r\n \r\n const days: DayItem[] = [];\r\n \r\n // 上个月的日期\r\n const prevMonthLastDay = new Date(year, month, 0).getDate();\r\n for (let i = firstDayWeek - 1; i >= 0; i--) {\r\n const date = new Date(year, month - 1, prevMonthLastDay - i);\r\n const dayItem: DayItem = {\r\n date,\r\n type: 'prev-month',\r\n text: String(prevMonthLastDay - i),\r\n };\r\n \r\n if (props.formatter) {\r\n const formatted = props.formatter(dayItem);\r\n if (formatted.text) dayItem.text = formatted.text;\r\n if (formatted.bottomInfo) dayItem.bottomInfo = formatted.bottomInfo;\r\n }\r\n \r\n days.push(dayItem);\r\n }\r\n \r\n // 当前月的日期\r\n for (let i = 1; i <= daysInMonth; i++) {\r\n const date = new Date(year, month, i);\r\n const dayItem: DayItem = {\r\n date,\r\n type: 'current-month',\r\n text: String(i),\r\n };\r\n \r\n if (props.formatter) {\r\n const formatted = props.formatter(dayItem);\r\n if (formatted.text) dayItem.text = formatted.text;\r\n if (formatted.bottomInfo) dayItem.bottomInfo = formatted.bottomInfo;\r\n }\r\n \r\n days.push(dayItem);\r\n }\r\n \r\n // 下个月的日期(补齐6行)\r\n const remaining = 42 - days.length;\r\n for (let i = 1; i <= remaining; i++) {\r\n const date = new Date(year, month + 1, i);\r\n const dayItem: DayItem = {\r\n date,\r\n type: 'next-month',\r\n text: String(i),\r\n };\r\n \r\n if (props.formatter) {\r\n const formatted = props.formatter(dayItem);\r\n if (formatted.text) dayItem.text = formatted.text;\r\n if (formatted.bottomInfo) dayItem.bottomInfo = formatted.bottomInfo;\r\n }\r\n \r\n days.push(dayItem);\r\n }\r\n \r\n return days;\r\n}\r\n\r\n// 计算当前月份的所有日期\r\nconst monthDays = computed(() => {\r\n const year = currentDate.value.getFullYear();\r\n const month = currentDate.value.getMonth();\r\n return getMonthDays(year, month);\r\n});\r\n\r\n// 月份标题\r\nconst monthTitle = computed(() => {\r\n const year = currentDate.value.getFullYear();\r\n const month = currentDate.value.getMonth() + 1;\r\n return `${year}年${month}月`;\r\n});\r\n\r\n// 获取日期单元格的类名\r\nfunction getDayClass(day: DayItem) {\r\n const classes: string[] = [];\r\n \r\n if (day.type !== 'current-month') {\r\n classes.push('is-other-month');\r\n }\r\n \r\n if (isToday(day.date)) {\r\n classes.push('is-today');\r\n }\r\n \r\n if (isDisabled(day.date)) {\r\n classes.push('is-disabled');\r\n return classes;\r\n }\r\n \r\n const dateStr = formatDate(day.date);\r\n \r\n if (props.range) {\r\n if (props.rangeStart === dateStr) {\r\n classes.push('is-start');\r\n }\r\n if (props.rangeEnd === dateStr) {\r\n classes.push('is-end');\r\n }\r\n if (isInRange(day.date)) {\r\n classes.push('is-in-range');\r\n }\r\n } else {\r\n if (props.selectedDate === dateStr) {\r\n classes.push('is-selected');\r\n }\r\n }\r\n \r\n return classes;\r\n}\r\n\r\n// 区间是否完整\r\nconst isRangeComplete = computed(() => {\r\n return !!(props.rangeStart && props.rangeEnd);\r\n});\r\n\r\n// 已选中的日期范围项数\r\nconst selectedRangeCount = computed(() => {\r\n if (props.rangeStart && props.rangeEnd) {\r\n return 2;\r\n } else if (props.rangeStart || props.rangeEnd) {\r\n return 1;\r\n }\r\n return 0;\r\n});\r\n\r\n// 判断年份是否被禁用\r\nfunction isYearDisabled(year: number): boolean {\r\n if (!props.minDate && !props.maxDate) {\r\n return false;\r\n }\r\n \r\n const min = props.minDate ? parseDate(props.minDate) : null;\r\n const max = props.maxDate ? parseDate(props.maxDate) : null;\r\n \r\n if (min && year < min.getFullYear()) {\r\n return true;\r\n }\r\n if (max && year > max.getFullYear()) {\r\n return true;\r\n }\r\n \r\n return false;\r\n}\r\n\r\n// 判断月份是否被禁用\r\nfunction isMonthDisabled(year: number, month: number): boolean {\r\n const min = props.minDate ? parseDate(props.minDate) : null;\r\n const max = props.maxDate ? parseDate(props.maxDate) : null;\r\n \r\n if (min) {\r\n const minYear = min.getFullYear();\r\n const minMonth = min.getMonth() + 1;\r\n if (year < minYear || (year === minYear && month < minMonth)) {\r\n return true;\r\n }\r\n }\r\n \r\n if (max) {\r\n const maxYear = max.getFullYear();\r\n const maxMonth = max.getMonth() + 1;\r\n if (year > maxYear || (year === maxYear && month > maxMonth)) {\r\n return true;\r\n }\r\n }\r\n \r\n return false;\r\n}\r\n\r\n// 年月选择器状态\r\nconst showMonthPicker = ref(false);\r\nconst pickerMode = ref<'year' | 'month'>('year');\r\nconst tempYear = ref(currentDate.value.getFullYear());\r\nconst tempMonth = ref(currentDate.value.getMonth() + 1);\r\n\r\n// 年份选择器虚拟滚动\r\nconst yearScrollRef = ref<HTMLElement>();\r\nconst visibleYearStart = ref(1900);\r\nconst visibleYearEnd = ref(1920);\r\nconst dynamicMinYear = ref(1900);\r\nconst dynamicMaxYear = ref(2100);\r\n\r\n// 计算可见年份列表\r\nconst visibleYearList = computed(() => {\r\n const years: number[] = [];\r\n const bufferRows = 3;\r\n const startRow = Math.floor((visibleYearStart.value - dynamicMinYear.value) / itemsPerRow) - bufferRows;\r\n const endRow = Math.ceil((visibleYearEnd.value - dynamicMinYear.value) / itemsPerRow) + bufferRows;\r\n const start = dynamicMinYear.value + Math.max(0, startRow) * itemsPerRow;\r\n const end = dynamicMinYear.value + endRow * itemsPerRow - 1;\r\n \r\n for (let i = start; i <= end; i++) {\r\n years.push(i);\r\n }\r\n return years;\r\n});\r\n\r\n// 监听currentDate变化,同步tempYear和tempMonth\r\nwatch(() => currentDate.value, (date) => {\r\n tempYear.value = date.getFullYear();\r\n tempMonth.value = date.getMonth() + 1;\r\n}, { immediate: true });\r\n\r\n// 处理年份滚动\r\nfunction handleYearScroll() {\r\n if (!yearScrollRef.value) return;\r\n const scrollTop = yearScrollRef.value.scrollTop;\r\n const rowHeight = itemHeight;\r\n const startRow = Math.max(0, Math.floor(scrollTop / rowHeight));\r\n const newStart = dynamicMinYear.value + startRow * itemsPerRow;\r\n const newEnd = newStart + visibleRows * itemsPerRow - 1;\r\n \r\n // 动态扩展年份范围\r\n if (newStart < dynamicMinYear.value) {\r\n dynamicMinYear.value = newStart - 100;\r\n } else if (newEnd > dynamicMaxYear.value) {\r\n dynamicMaxYear.value = newEnd + 100;\r\n }\r\n \r\n if (newStart !== visibleYearStart.value || newEnd !== visibleYearEnd.value) {\r\n visibleYearStart.value = newStart;\r\n visibleYearEnd.value = newEnd;\r\n }\r\n}\r\n\r\n// 打开年月选择器\r\nfunction openMonthPicker() {\r\n tempYear.value = currentDate.value.getFullYear();\r\n tempMonth.value = currentDate.value.getMonth() + 1;\r\n pickerMode.value = 'year';\r\n showMonthPicker.value = true;\r\n \r\n // 动态调整年份范围\r\n const currentYear = tempYear.value;\r\n if (currentYear < dynamicMinYear.value) {\r\n dynamicMinYear.value = Math.floor(currentYear / 100) * 100;\r\n } else if (currentYear > dynamicMaxYear.value) {\r\n dynamicMaxYear.value = Math.ceil(currentYear / 100) * 100 + 99;\r\n }\r\n \r\n // 初始化可见年份范围\r\n nextTick(() => {\r\n if (yearScrollRef.value) {\r\n const rowIndex = Math.floor((currentYear - dynamicMinYear.value) / itemsPerRow);\r\n const startRow = Math.max(0, rowIndex - 2);\r\n visibleYearStart.value = dynamicMinYear.value + startRow * itemsPerRow;\r\n visibleYearEnd.value = visibleYearStart.value + visibleRows * itemsPerRow - 1;\r\n scrollToYear(currentYear);\r\n }\r\n });\r\n}\r\n\r\n// 滚动到指定年份\r\nfunction scrollToYear(year: number) {\r\n if (!yearScrollRef.value) return;\r\n \r\n if (year < dynamicMinYear.value) {\r\n dynamicMinYear.value = Math.floor(year / 100) * 100;\r\n } else if (year > dynamicMaxYear.value) {\r\n dynamicMaxYear.value = Math.ceil(year / 100) * 100 + 99;\r\n }\r\n \r\n const rowIndex = Math.floor((year - dynamicMinYear.value) / itemsPerRow);\r\n const scrollTop = rowIndex * itemHeight;\r\n yearScrollRef.value.scrollTop = scrollTop;\r\n const startRow = Math.max(0, rowIndex - 2);\r\n visibleYearStart.value = dynamicMinYear.value + startRow * itemsPerRow;\r\n visibleYearEnd.value = visibleYearStart.value + visibleRows * itemsPerRow - 1;\r\n}\r\n\r\n// 上一个月\r\nfunction prevMonth() {\r\n const date = new Date(currentDate.value);\r\n date.setMonth(date.getMonth() - 1);\r\n currentDate.value = date;\r\n}\r\n\r\n// 下一个月\r\nfunction nextMonth() {\r\n const date = new Date(currentDate.value);\r\n date.setMonth(date.getMonth() + 1);\r\n currentDate.value = date;\r\n}\r\n\r\n// 选择年份\r\nfunction selectYear(year: number) {\r\n if (isYearDisabled(year)) return;\r\n tempYear.value = year;\r\n pickerMode.value = 'month';\r\n}\r\n\r\n// 选择月份\r\nfunction selectMonth(month: number) {\r\n if (isMonthDisabled(tempYear.value, month)) return;\r\n tempMonth.value = month;\r\n // 直接确认并关闭\r\n confirmMonth();\r\n}\r\n\r\n// 确认年月选择\r\nfunction confirmMonth() {\r\n const date = new Date(currentDate.value);\r\n date.setFullYear(tempYear.value);\r\n date.setMonth(tempMonth.value - 1);\r\n currentDate.value = date;\r\n showMonthPicker.value = false;\r\n pickerMode.value = 'year';\r\n}\r\n\r\nfunction onSelectDay(day: DayItem) {\r\n emit('select-day', day);\r\n}\r\n\r\nfunction onClear() {\r\n emit('clear');\r\n}\r\n\r\n// 处理标题栏清空按钮点击\r\nfunction handleHeaderClear() {\r\n if (!hasValue.value) return;\r\n onClear();\r\n}\r\n\r\nfunction onConfirm() {\r\n emit('confirm');\r\n}\r\n\r\nfunction onCloseMonthPicker() {\r\n showMonthPicker.value = false;\r\n}\r\n\r\nfunction onPickerModeChange(mode: 'year' | 'month') {\r\n pickerMode.value = mode;\r\n}\r\n\r\n// 选择本年(年份选择模式下)\r\nfunction selectCurrentYear() {\r\n const today = new Date();\r\n const currentYear = today.getFullYear();\r\n if (isYearDisabled(currentYear)) return;\r\n tempYear.value = currentYear;\r\n // 选择年后切换到月份选择\r\n pickerMode.value = 'month';\r\n}\r\n\r\n// 选择本月(月份选择模式下)\r\nfunction selectCurrentMonth() {\r\n const today = new Date();\r\n const currentMonth = today.getMonth() + 1;\r\n if (isMonthDisabled(tempYear.value, currentMonth)) return;\r\n tempMonth.value = currentMonth;\r\n // 选择月后直接确认并关闭\r\n confirmMonth();\r\n}\r\n\r\n// 是否有值(用于显示清空按钮)\r\nconst hasValue = computed(() => {\r\n if (props.range) {\r\n return !!(props.rangeStart || props.rangeEnd);\r\n } else {\r\n return !!props.selectedDate;\r\n }\r\n});\r\n\r\n// 快捷选项定义\r\ninterface ShortcutOption {\r\n key: string;\r\n label: string;\r\n getRange: () => [string, string] | null;\r\n days?: number; // 该选项对应的天数\r\n disabled?: boolean;\r\n}\r\n\r\n// 计算两个日期之间的天数差\r\nfunction getDaysBetween(start: string, end: string): number {\r\n const startDate = parseDate(start);\r\n const endDate = parseDate(end);\r\n if (!startDate || !endDate) return 0;\r\n const diffTime = Math.abs(endDate.getTime() - startDate.getTime());\r\n return Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1; // +1 因为包含开始和结束日期\r\n}\r\n\r\n// 获取今天的日期字符串\r\nfunction getTodayStr(): string {\r\n return formatDate(new Date());\r\n}\r\n\r\n// 获取本周的开始日期(周一)\r\nfunction getWeekStart(): Date {\r\n const today = new Date();\r\n const day = today.getDay();\r\n const diff = today.getDate() - day + (day === 0 ? -6 : 1); // 调整为周一\r\n return new Date(today.getFullYear(), today.getMonth(), diff);\r\n}\r\n\r\n// 获取本周的结束日期(周日)\r\nfunction getWeekEnd(): Date {\r\n const weekStart = getWeekStart();\r\n const weekEnd = new Date(weekStart);\r\n weekEnd.setDate(weekStart.getDate() + 6); // 周日是周一+6天\r\n return weekEnd;\r\n}\r\n\r\n// 获取本月的开始日期\r\nfunction getMonthStart(): Date {\r\n const today = new Date();\r\n return new Date(today.getFullYear(), today.getMonth(), 1);\r\n}\r\n\r\n// 获取本月的结束日期\r\nfunction getMonthEnd(): Date {\r\n const today = new Date();\r\n return new Date(today.getFullYear(), today.getMonth() + 1, 0); // 下个月的第0天就是本月的最后一天\r\n}\r\n\r\n// 获取近三个月的开始日期\r\nfunction getThreeMonthsAgo(): Date {\r\n const today = new Date();\r\n return new Date(today.getFullYear(), today.getMonth() - 2, 1);\r\n}\r\n\r\n// 获取本年的开始日期\r\nfunction getYearStart(): Date {\r\n const today = new Date();\r\n return new Date(today.getFullYear(), 0, 1);\r\n}\r\n\r\n// 获取本年的结束日期\r\nfunction getYearEnd(): Date {\r\n const today = new Date();\r\n return new Date(today.getFullYear(), 11, 31); // 12月的第31天\r\n}\r\n\r\n// 所有快捷选项\r\nconst allShortcuts: ShortcutOption[] = [\r\n {\r\n key: 'today',\r\n label: '本日',\r\n days: 1,\r\n getRange: () => {\r\n const today = getTodayStr();\r\n return [today, today];\r\n },\r\n },\r\n {\r\n key: 'week',\r\n label: '本周',\r\n days: 7,\r\n getRange: () => {\r\n const start = formatDate(getWeekStart());\r\n const end = formatDate(getWeekEnd());\r\n return [start, end];\r\n },\r\n },\r\n {\r\n key: 'month',\r\n label: '本月',\r\n getRange: () => {\r\n const start = formatDate(getMonthStart());\r\n const end = formatDate(getMonthEnd());\r\n return [start, end];\r\n },\r\n },\r\n {\r\n key: 'threeMonths',\r\n label: '近三月',\r\n getRange: () => {\r\n const start = formatDate(getThreeMonthsAgo());\r\n const end = formatDate(getMonthEnd()); // 到本月结束\r\n return [start, end];\r\n },\r\n },\r\n {\r\n key: 'year',\r\n label: '本年',\r\n getRange: () => {\r\n const start = formatDate(getYearStart());\r\n const end = formatDate(getYearEnd());\r\n return [start, end];\r\n },\r\n },\r\n {\r\n key: 'last7Days',\r\n label: '近7天',\r\n days: 7,\r\n getRange: () => {\r\n const today = new Date();\r\n const startDate = new Date(today);\r\n startDate.setDate(today.getDate() - 6); // 包含今天,所以是 -6\r\n return [formatDate(startDate), getTodayStr()];\r\n },\r\n },\r\n {\r\n key: 'last30Days',\r\n label: '近30天',\r\n days: 30,\r\n getRange: () => {\r\n const today = new Date();\r\n const startDate = new Date(today);\r\n startDate.setDate(today.getDate() - 29); // 包含今天,所以是 -29\r\n return [formatDate(startDate), getTodayStr()];\r\n },\r\n },\r\n];\r\n\r\n// 根据 range 过滤可用的快捷选项(不可选的直接隐藏)\r\nconst availableShortcuts = computed(() => {\r\n return allShortcuts.filter(option => {\r\n // 如果设置了最大天数限制,检查该选项是否符合\r\n if (props.maxRangeDays !== undefined) {\r\n if (option.days !== undefined) {\r\n // 如果选项有明确的天数,直接比较\r\n return option.days <= props.maxRangeDays;\r\n } else {\r\n // 如果选项没有明确的天数,计算实际天数\r\n const range = option.getRange();\r\n if (range) {\r\n const days = getDaysBetween(range[0], range[1]);\r\n return days <= props.maxRangeDays;\r\n }\r\n }\r\n }\r\n \r\n // 没有限制时,所有选项都可用\r\n return true;\r\n });\r\n});\r\n\r\n// 处理快捷选项点击\r\nfunction handleShortcutClick(option: ShortcutOption) {\r\n const range = option.getRange();\r\n if (range) {\r\n // 检查日期范围是否在 minDate 和 maxDate 范围内\r\n if (props.minDate && range[0] < props.minDate) {\r\n return;\r\n }\r\n if (props.maxDate && range[1] > props.maxDate) {\r\n return;\r\n }\r\n \r\n // 触发选择日期事件(通过模拟点击日期来实现)\r\n // 这里需要直接设置 rangeStart 和 rangeEnd,但它们是 props,不能直接修改\r\n // 所以需要通过 emit 来通知父组件\r\n emit('shortcut-select', range);\r\n }\r\n}\r\n\r\ndefineExpose({\r\n yearScrollRef\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.rc-calendar {\r\n &__header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n margin-bottom: 16px;\r\n padding-bottom: 12px;\r\n border-bottom: 1px solid var(--rc-border);\r\n }\r\n\r\n &__header-title {\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: var(--rc-text);\r\n }\r\n\r\n &__header-clear {\r\n color: var(--rc-primary);\r\n font-size: 14px;\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n\r\n &:hover:not(.is-disabled) {\r\n opacity: 0.8;\r\n }\r\n\r\n &.is-disabled {\r\n color: var(--rc-disabled);\r\n cursor: not-allowed;\r\n }\r\n }\r\n\r\n &__shortcuts {\r\n margin-bottom: 16px;\r\n overflow: hidden;\r\n }\r\n\r\n &__shortcuts-scroll {\r\n display: flex;\r\n gap: 8px;\r\n overflow-x: auto;\r\n overflow-y: hidden;\r\n -webkit-overflow-scrolling: touch;\r\n scrollbar-width: none; /* Firefox */\r\n -ms-overflow-style: none; /* IE and Edge */\r\n \r\n &::-webkit-scrollbar {\r\n display: none; /* Chrome, Safari, Opera */\r\n }\r\n }\r\n\r\n &__shortcut-item {\r\n flex-shrink: 0;\r\n padding: 6px 16px;\r\n border: 1px solid var(--rc-border);\r\n border-radius: 16px;\r\n background: var(--rc-white);\r\n font-size: 14px;\r\n color: var(--rc-text);\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n white-space: nowrap;\r\n\r\n &:hover {\r\n border-color: var(--rc-primary);\r\n color: var(--rc-primary);\r\n }\r\n }\r\n\r\n &__month-title {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n margin-bottom: 16px;\r\n }\r\n\r\n &__month-text {\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: var(--rc-text);\r\n cursor: pointer;\r\n user-select: none;\r\n }\r\n\r\n &__nav-button {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n border-radius: 50%;\r\n background: rgba(22, 119, 255, 0.1);\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n\r\n &:hover {\r\n background: rgba(22, 119, 255, 0.2);\r\n }\r\n\r\n &:active {\r\n background: rgba(22, 119, 255, 0.3);\r\n }\r\n }\r\n\r\n &__nav-icon {\r\n color: var(--rc-primary);\r\n font-size: 16px;\r\n }\r\n\r\n &__weekdays {\r\n display: grid;\r\n grid-template-columns: repeat(7, 1fr);\r\n margin-bottom: 8px;\r\n }\r\n\r\n &__weekday {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 32px;\r\n font-size: 14px;\r\n font-weight: 500;\r\n color: var(--rc-text);\r\n }\r\n\r\n &__days {\r\n display: grid;\r\n grid-template-columns: repeat(7, 1fr);\r\n gap: 4px;\r\n }\r\n\r\n &__day {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-height: 30px;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n\r\n &.is-other-month {\r\n opacity: 0.3;\r\n cursor: default;\r\n }\r\n\r\n &.is-disabled {\r\n opacity: 0.3;\r\n cursor: not-allowed;\r\n }\r\n\r\n &.is-in-range:not(.is-start):not(.is-end) {\r\n background: rgba(22, 119, 255, 0.1);\r\n }\r\n\r\n &.is-today {\r\n .rc-calendar__day-text {\r\n color: var(--rc-primary);\r\n font-weight: 600;\r\n }\r\n }\r\n\r\n &.is-start,\r\n &.is-end {\r\n background: var(--rc-primary);\r\n color: var(--rc-white);\r\n\r\n .rc-calendar__day-text {\r\n color: var(--rc-white);\r\n font-weight: 600;\r\n }\r\n }\r\n\r\n &.is-selected {\r\n background: var(--rc-primary);\r\n color: var(--rc-white);\r\n\r\n .rc-calendar__day-text {\r\n color: var(--rc-white);\r\n font-weight: 600;\r\n }\r\n }\r\n\r\n &:hover:not(.is-disabled):not(.is-other-month):not(.is-start):not(.is-end):not(.is-selected) {\r\n background: var(--rc-bg);\r\n }\r\n }\r\n\r\n &__day-content {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: 2px;\r\n }\r\n\r\n &__day-text {\r\n font-size: 14px;\r\n color: var(--rc-text);\r\n }\r\n\r\n &__day-bottom {\r\n font-size: 10px;\r\n color: var(--rc-text);\r\n opacity: 0.7;\r\n }\r\n\r\n &__footer {\r\n display: flex;\r\n justify-content: space-between;\r\n gap: 12px;\r\n margin-top: 16px;\r\n padding-top: 16px;\r\n border-top: 1px solid var(--rc-border);\r\n\r\n &-reset {\r\n flex: 1;\r\n background: var(--rc-white);\r\n color: var(--rc-text);\r\n border-color: var(--rc-border);\r\n }\r\n\r\n &-confirm {\r\n flex: 1;\r\n }\r\n }\r\n\r\n &__month-picker-overlay {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n z-index: 10;\r\n background: var(--rc-white);\r\n border-radius: 8px;\r\n }\r\n\r\n &__month-picker {\r\n position: relative;\r\n height: 100%;\r\n background: var(--rc-white);\r\n border-radius: 8px;\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n\r\n &__month-picker-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 0 16px 16px;\r\n flex-shrink: 0;\r\n }\r\n\r\n &__month-picker-title {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n font-size: 16px;\r\n font-weight: 600;\r\n color: var(--rc-text);\r\n \r\n span {\r\n cursor: pointer;\r\n transition: color 0.2s;\r\n \r\n &:hover {\r\n color: var(--rc-primary);\r\n }\r\n }\r\n }\r\n\r\n &__year-picker-content {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n min-height: 0;\r\n }\r\n\r\n &__year-picker-scroll {\r\n flex: 1;\r\n overflow-y: auto;\r\n -webkit-overflow-scrolling: touch;\r\n min-height: 0;\r\n }\r\n\r\n &__year-picker-spacer {\r\n width: 100%;\r\n }\r\n\r\n &__year-picker-grid {\r\n display: grid;\r\n grid-template-columns: repeat(3, 1fr);\r\n gap: 8px;\r\n padding: 8px 16px;\r\n }\r\n\r\n &__year-picker-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 40px;\r\n border: 1px solid var(--rc-border);\r\n border-radius: 6px;\r\n background: var(--rc-bg);\r\n font-size: 14px;\r\n color: var(--rc-text);\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n\r\n &:hover:not(.is-selected):not(.is-disabled) {\r\n border-color: var(--rc-primary);\r\n color: var(--rc-primary);\r\n }\r\n\r\n &.is-selected {\r\n background: var(--rc-primary);\r\n border-color: var(--rc-primary);\r\n color: var(--rc-white);\r\n }\r\n\r\n &.is-disabled {\r\n opacity: 0.3;\r\n cursor: not-allowed;\r\n }\r\n }\r\n\r\n &__month-picker-content {\r\n display: grid;\r\n grid-template-columns: repeat(3, 1fr);\r\n gap: 8px;\r\n padding: 0 16px 16px;\r\n }\r\n\r\n &__month-picker-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n height: 40px;\r\n border: 1px solid var(--rc-border);\r\n border-radius: 6px;\r\n background: var(--rc-white);\r\n font-size: 14px;\r\n color: var(--rc-text);\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n\r\n &:hover:not(.is-selected):not(.is-disabled) {\r\n border-color: var(--rc-primary);\r\n color: var(--rc-primary);\r\n }\r\n\r\n &.is-selected {\r\n background: var(--rc-primary);\r\n border-color: var(--rc-primary);\r\n color: var(--rc-white);\r\n }\r\n\r\n &.is-disabled {\r\n opacity: 0.3;\r\n cursor: not-allowed;\r\n }\r\n }\r\n}\r\n\r\n// 过渡动画\r\n.rc-calendar-fade-enter-active,\r\n.rc-calendar-fade-leave-active {\r\n transition: opacity 0.3s;\r\n}\r\n\r\n.rc-calendar-fade-enter-from,\r\n.rc-calendar-fade-leave-to {\r\n opacity: 0;\r\n}\r\n</style>\r\n\r\n","<template>\r\n <div class=\"rc-calendar\">\r\n <!-- 输入框模式 -->\r\n <div v-if=\"mode === 'popup'\" class=\"rc-calendar__input\" @click=\"open\">\r\n <input\r\n ref=\"inputRef\"\r\n v-model=\"inputText\"\r\n type=\"text\"\r\n class=\"rc-calendar__input-field\"\r\n :placeholder=\"placeholder\"\r\n readonly\r\n @focus=\"handleInputFocus\"\r\n @blur=\"handleInputBlur\"\r\n @input=\"handleInput\"\r\n />\r\n <div class=\"rc-calendar__input-actions\">\r\n <rc-icon name=\"icon_a-rili\" class=\"rc-calendar__input-icon\" />\r\n </div>\r\n </div>\r\n\r\n <!-- 日历面板 - 直接展示模式 -->\r\n <div \r\n v-if=\"mode === 'default'\"\r\n class=\"rc-calendar__panel\"\r\n >\r\n <CalendarPanelContent\r\n :show-title=\"showTitle\"\r\n :title=\"title\"\r\n :range=\"isRangeMode\"\r\n :selected-date=\"selectedDate\"\r\n :range-start=\"rangeStart\"\r\n :range-end=\"rangeEnd\"\r\n :min-date=\"minDate\"\r\n :max-date=\"maxDate\"\r\n :disabled-date=\"mergedDisabledDate\"\r\n :formatter=\"formatter\"\r\n :show-footer=\"false\"\r\n :max-range-days=\"maxRangeDays\"\r\n @select-day=\"onSelectDay\"\r\n @clear=\"onClear\"\r\n @confirm=\"onConfirm\"\r\n @shortcut-select=\"onShortcutSelect\"\r\n />\r\n </div>\r\n\r\n <!-- 日历面板 - Popup 模式 -->\r\n <rc-popup\r\n v-if=\"mode === 'popup'\"\r\n v-model=\"visible\"\r\n position=\"bottom\"\r\n :overlay=\"true\"\r\n :round=\"true\"\r\n :close-on-click-overlay=\"true\"\r\n :lock-scroll=\"true\"\r\n @update:modelValue=\"handlePopupClose\"\r\n >\r\n <div \r\n ref=\"popupPanelRef\"\r\n class=\"rc-calendar__panel\"\r\n >\r\n <CalendarPanelContent\r\n :show-title=\"showTitle\"\r\n :title=\"title\"\r\n :range=\"isRangeMode\"\r\n :selected-date=\"selectedDate\"\r\n :range-start=\"rangeStart\"\r\n :range-end=\"rangeEnd\"\r\n :min-date=\"minDate\"\r\n :max-date=\"maxDate\"\r\n :disabled-date=\"mergedDisabledDate\"\r\n :formatter=\"formatter\"\r\n :show-footer=\"showFooter\"\r\n :max-range-days=\"maxRangeDays\"\r\n @select-day=\"onSelectDay\"\r\n @clear=\"onClear\"\r\n @confirm=\"onConfirm\"\r\n @shortcut-select=\"onShortcutSelect\"\r\n />\r\n </div>\r\n </rc-popup>\r\n \r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue';\r\nimport RcIcon from '../icon';\r\nimport RcButton from '../button';\r\nimport RcPopup from '../popup';\r\nimport CalendarPanelContent from './panel-content.vue';\r\n\r\ndefineOptions({ name: 'rc-calendar' });\r\n\r\ntype CalendarValue = string | [string, string] | null;\r\n\r\ninterface DayItem {\r\n date: Date;\r\n type: string;\r\n text: string;\r\n bottomInfo?: string;\r\n}\r\n\r\ntype CalendarMode = 'default' | 'popup';\r\n\r\ninterface Props {\r\n /** 当前选中的日期,格式为 YYYY-MM-DD */\r\n modelValue?: CalendarValue;\r\n /** 是否支持区间选择:true/false 或数字(表示区间可选的最大天数) */\r\n range?: boolean | number;\r\n /** 显示模式:default 直接展示,popup 输入框模式(点击后弹出日历) */\r\n mode?: CalendarMode;\r\n /** 输入框占位符 */\r\n placeholder?: string;\r\n /** 是否显示标题栏 */\r\n showTitle?: boolean;\r\n /** 标题栏文字 */\r\n title?: string;\r\n /** 最小可选日期 */\r\n minDate?: string;\r\n /** 最大可选日期 */\r\n maxDate?: string;\r\n /** 禁用日期函数 */\r\n disabledDate?: (date: Date) => boolean;\r\n /** 日期格式化函数 */\r\n formatter?: (day: DayItem) => { text?: string; bottomInfo?: string };\r\n /** 区间模式下是否显示底部按钮(确定/取消),为 false 时区间完整后自动确认 */\r\n showFooter?: boolean;\r\n /** 区间模式下,结束日期是否自动加一天(选中日期为结束日期时,实际返回的结束日期会加一天) */\r\n endDateOffset?: boolean;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n modelValue: null,\r\n range: false,\r\n mode: 'default',\r\n placeholder: '请选择日期',\r\n showTitle: true,\r\n title: '选择日期',\r\n minDate: undefined,\r\n maxDate: undefined,\r\n disabledDate: undefined,\r\n formatter: undefined,\r\n showFooter: true,\r\n endDateOffset: false,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n (e: 'update:modelValue', value: CalendarValue): void;\r\n (e: 'change', value: CalendarValue): void;\r\n (e: 'confirm', value: CalendarValue): void;\r\n}>();\r\n\r\nconst inputRef = ref<HTMLInputElement>();\r\nconst popupPanelRef = ref<HTMLElement>();\r\nconst visible = ref(false);\r\nconst inputText = ref('');\r\n\r\n// 判断是否是区间模式\r\nconst isRangeMode = computed(() => {\r\n return props.range === true || typeof props.range === 'number';\r\n});\r\n\r\n// 最大区间天数(如果是数字模式)\r\nconst maxRangeDays = computed(() => {\r\n return typeof props.range === 'number' ? props.range : undefined;\r\n});\r\n\r\n// 合并禁用日期函数(包括天数限制)\r\nconst mergedDisabledDate = computed(() => {\r\n return (date: Date): boolean => {\r\n // 先检查用户自定义的禁用函数\r\n if (props.disabledDate && props.disabledDate(date)) {\r\n return true;\r\n }\r\n \r\n // 如果设置了最大天数限制且已选择开始日期,禁用超出范围的日期\r\n if (maxRangeDays.value !== undefined && rangeStart.value && !rangeEnd.value) {\r\n const dateStr = formatDate(date);\r\n const startDate = parseDate(rangeStart.value);\r\n if (startDate) {\r\n const days = getDaysBetween(rangeStart.value, dateStr);\r\n // 如果日期超出最大天数范围(包括开始日期之前的日期),则禁用\r\n if (days > maxRangeDays.value) {\r\n return true;\r\n }\r\n }\r\n }\r\n \r\n return false;\r\n };\r\n});\r\n\r\n// 单日期模式:选中的日期\r\nconst selectedDate = ref<string | null>(null);\r\n// 区间模式:选中的开始和结束日期\r\nconst rangeStart = ref<string | null>(null);\r\nconst rangeEnd = ref<string | null>(null);\r\n\r\n// 初始化选中值\r\nwatch(\r\n () => props.modelValue,\r\n (val) => {\r\n if (isRangeMode.value) {\r\n if (Array.isArray(val) && val.length === 2) {\r\n rangeStart.value = val[0];\r\n // 如果启用了 endDateOffset,从外部传入的结束日期需要减一天来显示\r\n rangeEnd.value = getDisplayEndDate(val[1]);\r\n } else {\r\n rangeStart.value = null;\r\n rangeEnd.value = null;\r\n }\r\n } else {\r\n selectedDate.value = typeof val === 'string' ? val : null;\r\n }\r\n updateInputText();\r\n },\r\n { immediate: true }\r\n);\r\n\r\n// 更新输入框文本\r\nfunction updateInputText() {\r\n if (props.mode !== 'popup') return;\r\n \r\n if (isRangeMode.value) {\r\n if (rangeStart.value && rangeEnd.value) {\r\n // 显示时使用用户实际选择的日期(rangeEnd 存储的就是用户选择的日期)\r\n inputText.value = `${rangeStart.value} ~ ${rangeEnd.value}`;\r\n } else if (rangeStart.value) {\r\n inputText.value = `${rangeStart.value} ~ `;\r\n } else {\r\n inputText.value = '';\r\n }\r\n } else {\r\n inputText.value = selectedDate.value || '';\r\n }\r\n}\r\n\r\n\r\n// 解析日期字符串\r\nfunction parseDate(dateStr: string | null | undefined): Date | null {\r\n if (!dateStr) return null;\r\n const date = new Date(dateStr);\r\n return isNaN(date.getTime()) ? null : date;\r\n}\r\n\r\n// 格式化日期为 YYYY-MM-DD\r\nfunction formatDate(date: Date): string {\r\n const year = date.getFullYear();\r\n const month = String(date.getMonth() + 1).padStart(2, '0');\r\n const day = String(date.getDate()).padStart(2, '0');\r\n return `${year}-${month}-${day}`;\r\n}\r\n\r\n\r\n\r\n// 计算两个日期之间的天数差\r\nfunction getDaysBetween(start: string, end: string): number {\r\n const startDate = parseDate(start);\r\n const endDate = parseDate(end);\r\n if (!startDate || !endDate) return 0;\r\n const diffTime = Math.abs(endDate.getTime() - startDate.getTime());\r\n return Math.ceil(diffTime / (1000 * 60 * 60 * 24));\r\n}\r\n\r\n// 给日期加一天\r\nfunction addOneDay(dateStr: string): string {\r\n const date = parseDate(dateStr);\r\n if (!date) return dateStr;\r\n date.setDate(date.getDate() + 1);\r\n return formatDate(date);\r\n}\r\n\r\n// 给日期减一天\r\nfunction subtractOneDay(dateStr: string): string {\r\n const date = parseDate(dateStr);\r\n if (!date) return dateStr;\r\n date.setDate(date.getDate() - 1);\r\n return formatDate(date);\r\n}\r\n\r\n// 获取实际的结束日期(如果启用了 endDateOffset,则加一天)\r\nfunction getActualEndDate(endDate: string): string {\r\n if (props.endDateOffset && isRangeMode.value) {\r\n return addOneDay(endDate);\r\n }\r\n return endDate;\r\n}\r\n\r\n// 获取显示的结束日期(如果启用了 endDateOffset,从外部传入的值需要减一天来显示)\r\nfunction getDisplayEndDate(endDate: string): string {\r\n if (props.endDateOffset && isRangeMode.value) {\r\n return subtractOneDay(endDate);\r\n }\r\n return endDate;\r\n}\r\n\r\n// 选择日期\r\nfunction onSelectDay(day: DayItem) {\r\n if (day.type !== 'current-month') {\r\n return;\r\n }\r\n \r\n // 检查是否被禁用\r\n if (props.disabledDate && props.disabledDate(day.date)) {\r\n return;\r\n }\r\n \r\n const dateStr = formatDate(day.date);\r\n if (props.minDate && dateStr < props.minDate) {\r\n return;\r\n }\r\n if (props.maxDate && dateStr > props.maxDate) {\r\n return;\r\n }\r\n \r\n if (isRangeMode.value) {\r\n if (!rangeStart.value || (rangeStart.value && rangeEnd.value)) {\r\n // 重新开始选择\r\n rangeStart.value = dateStr;\r\n rangeEnd.value = null;\r\n } else {\r\n // 选择结束日期\r\n let start = rangeStart.value;\r\n let end = dateStr;\r\n \r\n if (dateStr < rangeStart.value!) {\r\n // 如果结束日期早于开始日期,交换\r\n end = rangeStart.value;\r\n start = dateStr;\r\n }\r\n \r\n rangeStart.value = start;\r\n rangeEnd.value = end;\r\n \r\n // 区间模式下,选择完成后立即触发 change\r\n if (rangeStart.value && rangeEnd.value) {\r\n const actualEnd = getActualEndDate(rangeEnd.value);\r\n const value: [string, string] = [rangeStart.value, actualEnd];\r\n emit('update:modelValue', value);\r\n emit('change', value);\r\n \r\n // 如果隐藏了底部按钮,区间完整后自动确认\r\n if (!props.showFooter) {\r\n onConfirm();\r\n }\r\n }\r\n }\r\n } else {\r\n selectedDate.value = dateStr;\r\n const value = dateStr;\r\n emit('update:modelValue', value);\r\n emit('change', value);\r\n \r\n // 单日期模式下,选择后自动关闭(输入框模式或弹窗模式)\r\n if (props.mode) {\r\n close();\r\n }\r\n }\r\n \r\n updateInputText();\r\n}\r\n\r\n// 确认选择(区间模式)\r\nfunction onConfirm() {\r\n if (rangeStart.value && rangeEnd.value) {\r\n const actualEnd = getActualEndDate(rangeEnd.value);\r\n const value: [string, string] = [rangeStart.value, actualEnd];\r\n emit('update:modelValue', value);\r\n emit('change', value);\r\n emit('confirm', value);\r\n close();\r\n }\r\n}\r\n\r\n// 清除选择\r\nfunction onClear() {\r\n if (isRangeMode.value) {\r\n rangeStart.value = null;\r\n rangeEnd.value = null;\r\n } else {\r\n selectedDate.value = null;\r\n }\r\n const value = null;\r\n emit('update:modelValue', value);\r\n emit('change', value);\r\n updateInputText();\r\n}\r\n\r\n// 处理快捷选项选择\r\nfunction onShortcutSelect(range: [string, string]) {\r\n rangeStart.value = range[0];\r\n rangeEnd.value = range[1];\r\n const actualEnd = getActualEndDate(range[1]);\r\n const value: [string, string] = [range[0], actualEnd];\r\n emit('update:modelValue', value);\r\n emit('change', value);\r\n \r\n // 如果隐藏了底部按钮,区间完整后自动确认\r\n if (!props.showFooter) {\r\n onConfirm();\r\n } else {\r\n updateInputText();\r\n }\r\n}\r\n\r\n\r\n\r\n\r\n// 打开日历\r\nfunction open() {\r\n visible.value = true;\r\n}\r\n\r\n// 关闭日历\r\nfunction close() {\r\n visible.value = false;\r\n}\r\n\r\n// Popup 关闭处理\r\nfunction handlePopupClose(value: boolean) {\r\n visible.value = value;\r\n}\r\n\r\n// 处理输入框焦点\r\nfunction handleInputFocus() {\r\n open();\r\n}\r\n\r\n// 处理输入框失焦\r\nfunction handleInputBlur() {\r\n if (props.mode === 'popup') {\r\n parseInputText();\r\n }\r\n}\r\n\r\n// 处理输入框输入\r\nfunction handleInput() {\r\n if (!visible.value) {\r\n open();\r\n }\r\n}\r\n\r\n// 解析输入文本\r\nfunction parseInputText() {\r\n const text = inputText.value.trim();\r\n \r\n if (isRangeMode.value) {\r\n // 区间模式:支持 \"YYYY-MM-DD ~ YYYY-MM-DD\" 格式\r\n const parts = text.split('~').map(s => s.trim());\r\n if (parts.length === 2 && parts[0] && parts[1]) {\r\n const start = parseDate(parts[0]);\r\n const end = parseDate(parts[1]);\r\n if (start && end && !isNaN(start.getTime()) && !isNaN(end.getTime())) {\r\n rangeStart.value = formatDate(start);\r\n // 解析输入文本时,如果启用了 endDateOffset,需要将输入的结束日期减一天来存储\r\n const endStr = formatDate(end);\r\n rangeEnd.value = getDisplayEndDate(endStr);\r\n const actualEnd = getActualEndDate(rangeEnd.value);\r\n const value: [string, string] = [rangeStart.value, actualEnd];\r\n emit('update:modelValue', value);\r\n emit('change', value);\r\n return;\r\n }\r\n }\r\n } else {\r\n // 单日期模式\r\n const date = parseDate(text);\r\n if (date && !isNaN(date.getTime())) {\r\n selectedDate.value = formatDate(date);\r\n emit('update:modelValue', selectedDate.value);\r\n emit('change', selectedDate.value);\r\n return;\r\n }\r\n }\r\n \r\n // 解析失败,恢复显示值\r\n updateInputText();\r\n}\r\n\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.rc-calendar {\r\n --rc-primary: #1677ff;\r\n --rc-text: #323233;\r\n --rc-border: #dcdee0;\r\n --rc-white: #ffffff;\r\n --rc-bg: #f7f8fa;\r\n --rc-disabled: #c8c9cc;\r\n\r\n position: relative;\r\n width: 100%;\r\n\r\n &__input {\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n width: 100%;\r\n padding: 8px 12px;\r\n border: 1px solid var(--rc-border);\r\n border-radius: 6px;\r\n background: var(--rc-white);\r\n cursor: pointer;\r\n }\r\n\r\n &__input-field {\r\n flex: 1;\r\n border: none;\r\n outline: none;\r\n background: transparent;\r\n font-size: 14px;\r\n color: var(--rc-text);\r\n\r\n &::placeholder {\r\n color: var(--rc-disabled);\r\n }\r\n }\r\n\r\n &__input-actions {\r\n display: flex;\r\n align-items: center;\r\n }\r\n\r\n &__input-icon {\r\n color: var(--rc-disabled);\r\n font-size: 18px;\r\n }\r\n\r\n &__panel {\r\n position: relative;\r\n padding: 16px;\r\n background: var(--rc-white);\r\n border-radius: 8px;\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n}\r\n</style>\r\n","import type { App } from 'vue';\r\nimport Calendar from './index.vue';\r\n\r\n// 组件名使用全小写,以 <rc-calendar> 形式在模板中使用\r\n(Calendar as any).name = 'rc-calendar';\r\nconst PascalName = 'RcCalendar';\r\n\r\nexport function install(app: App) {\r\n app.component((Calendar as any).name, Calendar);\r\n app.component(PascalName, Calendar);\r\n return app;\r\n}\r\n\r\nexport default Calendar;\r\n\r\n","<template>\n <div class=\"rc-search-area\">\n <!-- 筛选项按钮行 -->\n <div class=\"rc-search-area__bar\">\n <div\n v-for=\"(item, index) in props.items\"\n :key=\"index\"\n class=\"rc-search-area__item\"\n :class=\"{ \n 'is-active': activeIndex === index,\n 'has-value': getSelectedCount(item) > 0\n }\"\n @click=\"openFilter(index)\"\n >\n <span class=\"rc-search-area__item-label\">{{ getItemDisplayText(item) }}</span>\n <rc-icon \n name=\"icon_a-xiala2\" \n :color=\"(activeIndex !== index && getSelectedCount(item) > 0) ? '#1677ff' : '#969799'\"\n class=\"rc-search-area__item-arrow\" \n :class=\"{ 'is-up': activeIndex === index }\"\n />\n </div>\n </div>\n\n <!-- 蒙层 -->\n <transition name=\"rc-search-area-fade\">\n <div \n v-if=\"activeIndex !== null && props.showMask\" \n ref=\"maskRef\"\n class=\"rc-search-area__mask\"\n :style=\"maskStyle\"\n @click=\"closeFilter\"\n ></div>\n </transition>\n\n <!-- 筛选面板 -->\n <transition name=\"rc-search-area-slide\">\n <div v-if=\"activeIndex !== null\" ref=\"panelRef\" class=\"rc-search-area__panel\">\n <div class=\"rc-search-area__panel-content\">\n <!-- 插槽模式 -->\n <template v-if=\"currentFilter?.slot && $slots[currentFilter.key]\">\n <slot \n :name=\"currentFilter.key\" \n :value=\"getSlotValue(currentFilter)\"\n :update:value=\"(val: any) => updateSlotValue(currentFilter, val)\"\n />\n </template>\n\n <!-- 输入框模式 -->\n <template v-else-if=\"currentFilter?.type === 'input'\">\n <div class=\"rc-search-area__input-wrapper\">\n <input\n v-model=\"tempInputValue\"\n type=\"text\"\n class=\"rc-search-area__input\"\n :placeholder=\"currentFilter.placeholder || '请输入'\"\n @input=\"handleInputChange\"\n />\n </div>\n </template>\n\n <!-- 日期选择器模式 -->\n <template v-else-if=\"currentFilter?.type === 'calendar'\">\n <div class=\"rc-search-area__calendar-wrapper\">\n <rc-calendar\n v-model=\"tempCalendarValue\"\n :range=\"currentFilter.calendarConfig?.range || false\"\n mode=\"default\"\n :min-date=\"currentFilter.calendarConfig?.minDate\"\n :max-date=\"currentFilter.calendarConfig?.maxDate\"\n :disabled-date=\"currentFilter.calendarConfig?.disabledDate\"\n :formatter=\"currentFilter.calendarConfig?.formatter\"\n :end-date-offset=\"currentFilter.calendarConfig?.endDateOffset || false\"\n @change=\"handleCalendarChange\"\n />\n </div>\n </template>\n\n <!-- 树形单选模式 -->\n <template v-else-if=\"currentFilter?.type === 'tree-single'\">\n <div class=\"rc-search-area__tree-container\">\n <div\n v-for=\"(group, groupIdx) in getTreeGroups(currentFilter)\"\n :key=\"groupIdx\"\n class=\"rc-search-area__tree-group\"\n >\n <div class=\"rc-search-area__tree-group-title\">\n {{ getOptionLabel(group, currentFilter || undefined) }}\n </div>\n <div class=\"rc-search-area__tree-group-options\">\n <div\n v-for=\"(option, optIdx) in getTreeGroupChildren(group, currentFilter)\"\n :key=\"optIdx\"\n class=\"rc-search-area__option\"\n :class=\"{ 'is-selected': isSelected(option) }\"\n @click=\"selectSingle(option)\"\n >\n <span class=\"rc-search-area__option-label\">{{ getOptionLabel(option, currentFilter || undefined) }}</span>\n <rc-icon v-if=\"isSelected(option)\" name=\"icon_check\" class=\"rc-search-area__option-check\" />\n </div>\n </div>\n </div>\n </div>\n </template>\n\n <!-- 树形多选模式 -->\n <template v-else-if=\"currentFilter?.type === 'tree-multiple'\">\n <div class=\"rc-search-area__tree-container\">\n <div\n v-for=\"(group, groupIdx) in getTreeGroups(currentFilter)\"\n :key=\"groupIdx\"\n class=\"rc-search-area__tree-group\"\n >\n <div class=\"rc-search-area__tree-group-title\">\n {{ getOptionLabel(group, currentFilter || undefined) }}\n </div>\n <div class=\"rc-search-area__tree-group-options\">\n <div\n v-for=\"(option, optIdx) in getTreeGroupChildren(group, currentFilter)\"\n :key=\"optIdx\"\n class=\"rc-search-area__option\"\n :class=\"{ 'is-selected': isSelected(option) }\"\n @click=\"toggleOption(option)\"\n >\n <span class=\"rc-search-area__option-label\">{{ getOptionLabel(option, currentFilter || undefined) }}</span>\n <rc-icon v-if=\"isSelected(option)\" name=\"icon_check\" class=\"rc-search-area__option-check\" />\n </div>\n </div>\n </div>\n </div>\n </template>\n\n <!-- 普通单选模式 -->\n <template v-else-if=\"currentFilter?.type === 'single'\">\n <div class=\"rc-search-area__options-grid\">\n <div\n v-for=\"(option, optIdx) in getDisplayOptions(currentFilter)\"\n :key=\"optIdx\"\n class=\"rc-search-area__option\"\n :class=\"{ 'is-selected': isSelected(option) }\"\n @click=\"selectSingle(option)\"\n >\n <span class=\"rc-search-area__option-label\">{{ getOptionLabel(option, currentFilter || undefined) }}</span>\n <rc-icon v-if=\"isSelected(option)\" name=\"icon_check\" class=\"rc-search-area__option-check\" />\n </div>\n </div>\n </template>\n\n <!-- 普通多选模式 -->\n <template v-else>\n <div class=\"rc-search-area__options-grid\">\n <div\n v-for=\"(option, optIdx) in getDisplayOptions(currentFilter)\"\n :key=\"optIdx\"\n class=\"rc-search-area__option\"\n :class=\"{ 'is-selected': isSelected(option) }\"\n @click=\"toggleOption(option)\"\n >\n <span class=\"rc-search-area__option-label\">{{ getOptionLabel(option, currentFilter || undefined) }}</span>\n <rc-icon v-if=\"isSelected(option)\" name=\"icon_check\" class=\"rc-search-area__option-check\" />\n </div>\n </div>\n </template>\n\n <!-- 无结果提示 -->\n <div v-if=\"currentFilter?.type !== 'input' && currentFilter?.type !== 'calendar' && !currentFilter?.slot && currentFilter?.options?.length === 0\" class=\"rc-search-area__empty\">\n <p>暂无选项</p>\n </div>\n </div>\n\n <div v-if=\"!props.autoConfirm && currentFilter?.type !== 'single' && currentFilter?.type !== 'tree-single'\" class=\"rc-search-area__panel-footer\">\n <rc-button \n block \n @click=\"resetCurrentFilter\"\n >\n 重置\n </rc-button>\n <rc-button \n type=\"primary\"\n block \n @click=\"confirmFilter\"\n >\n 确定{{ selectedCountText }}\n </rc-button>\n </div>\n </div>\n </transition>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, watch, nextTick, onUnmounted } from 'vue';\nimport RcIcon from '../icon';\nimport RcButton from '../button';\nimport RcCalendar from '../calendar';\n\ndefineOptions({ name: 'rc-search-area' });\n\nexport interface FilterOption {\n label: string;\n value: any;\n [key: string]: any;\n}\n\nexport interface FilterItem {\n /** 筛选项标签 */\n label: string;\n /** 筛选项唯一标识 */\n key: string;\n /** 筛选类型:single 单选,multiple 多选,tree-single 树形单选,tree-multiple 树形多选,input 输入框,calendar 日期选择器(默认 multiple) */\n type: 'single' | 'multiple' | 'tree-single' | 'tree-multiple' | 'input' | 'calendar';\n /** 选项列表 */\n options?: FilterOption[] | string[];\n /** 多选时的列数(默认 2) */\n column?: number;\n /** 格式化 value,默认返回原始数据。为 string 时,会作为 key 从原始数据中获取值,相当于 (d) => d[format]。为函数时,以函数返回结果作为 value */\n format?: ((data: FilterOption) => any) | string;\n /** 渲染选项内容。为 string 时,返回 d[string]。为 function 时,返回函数结果 */\n renderItem?: ((data: FilterOption) => any) | string;\n /** 选中后在结果中显示的内容,默认和 renderItem 相同 */\n renderResult?: ((data: FilterOption) => any) | string;\n /** 树形数据下,指定子数据的属性名,有值时可以展示树形结构 */\n childrenKey?: string;\n /** 输入框类型的占位符(仅 type='input' 时有效) */\n placeholder?: string;\n /** 是否使用插槽自定义渲染,为 true 时使用名为 key 的插槽 */\n slot?: boolean;\n /** 日期选择器相关配置(仅 type='calendar' 时有效) */\n calendarConfig?: {\n /** 是否支持区间选择:true/false 或数字(表示区间可选的最大天数) */\n range?: boolean | number;\n /** 最小可选日期,格式为 YYYY-MM-DD */\n minDate?: string;\n /** 最大可选日期,格式为 YYYY-MM-DD */\n maxDate?: string;\n /** 禁用日期函数 */\n disabledDate?: (date: Date) => boolean;\n /** 日期格式化函数 */\n formatter?: (day: any) => { text?: string; bottomInfo?: string };\n /** 区间模式下,结束日期是否自动加一天(选中日期为结束日期时,实际返回的结束日期会加一天) */\n endDateOffset?: boolean;\n };\n}\n\nconst props = withDefaults(defineProps<{\n /** 筛选项配置 */\n items: FilterItem[];\n /** 当前筛选值(支持 v-model) */\n modelValue?: Record<string, any>;\n /** 是否显示蒙层 */\n showMask?: boolean;\n /** 是否自动确认:为 true 时,每次修改立即触发 change 事件并关闭弹窗,不显示确定和重置按钮 */\n autoConfirm?: boolean;\n}>(), {\n items: () => [],\n modelValue: () => ({}),\n showMask: true,\n autoConfirm: false,\n});\n\nconst emit = defineEmits<{\n /** v-model 更新事件 */\n (e: 'update:modelValue', values: Record<string, any>): void;\n /** 筛选条件变化时触发 */\n (e: 'change', values: Record<string, any>, item: FilterItem): void;\n}>();\n\n/** 当前打开的筛选项索引 */\nconst activeIndex = ref<number | null>(null);\n\n/** 面板和蒙层的 ref */\nconst panelRef = ref<HTMLElement | null>(null);\nconst maskRef = ref<HTMLElement | null>(null);\n\n/** 蒙层样式 - 从面板底部开始 */\nconst maskStyle = ref<{ top: string }>({ top: '0px' });\n\n/** 计算蒙层位置 */\nconst updateMaskPosition = async () => {\n if (activeIndex.value === null || !panelRef.value) {\n return;\n }\n await nextTick();\n const panelRect = panelRef.value.getBoundingClientRect();\n const panelTop = panelRect.top;\n maskStyle.value = { top: `${panelTop}px` };\n};\n\n/**\n * 处理点击外部区域关闭面板\n * @param event 鼠标事件\n */\nconst handleClickOutside = (event: MouseEvent) => {\n if (activeIndex.value === null || !panelRef.value) {\n return;\n }\n \n const target = event.target as HTMLElement;\n \n // 检查点击的目标是否在面板内部\n if (panelRef.value.contains(target)) {\n return;\n }\n \n // 检查是否点击的是筛选项按钮(避免点击按钮时关闭)\n const searchAreaEl = panelRef.value.closest('.rc-search-area');\n if (searchAreaEl) {\n const barEl = searchAreaEl.querySelector('.rc-search-area__bar');\n if (barEl && barEl.contains(target)) {\n // 点击的是筛选项按钮,不关闭面板(由按钮的点击事件处理)\n return;\n }\n }\n \n // 点击的是外部区域,关闭面板\n closeFilter();\n};\n\n/** 监听面板打开,更新蒙层位置和添加外部点击监听 */\nwatch(activeIndex, async (newVal) => {\n if (newVal !== null) {\n await nextTick();\n updateMaskPosition();\n // 监听窗口大小变化和滚动,更新蒙层位置\n window.addEventListener('resize', updateMaskPosition);\n window.addEventListener('scroll', updateMaskPosition, true);\n // 添加点击外部区域关闭面板的监听\n document.addEventListener('click', handleClickOutside, true);\n } else {\n window.removeEventListener('resize', updateMaskPosition);\n window.removeEventListener('scroll', updateMaskPosition, true);\n document.removeEventListener('click', handleClickOutside, true);\n }\n});\n\n/** 组件卸载时清理事件监听器 */\nonUnmounted(() => {\n window.removeEventListener('resize', updateMaskPosition);\n window.removeEventListener('scroll', updateMaskPosition, true);\n document.removeEventListener('click', handleClickOutside, true);\n});\n\n/** 每个筛选项的选中值(临时状态,用于模态窗内选择) */\nconst tempSelectedValues = ref<Record<string, any>>({});\n\n/** 输入框的临时值 */\nconst tempInputValue = ref<string>('');\n\n/** 日历的临时值 */\nconst tempCalendarValue = ref<string | [string, string] | null>(null);\n\n/** 插槽的临时值 */\nconst tempSlotValues = ref<Record<string, any>>({});\n\n/** 已确认的筛选值 */\nconst confirmedValues = ref<Record<string, any>>({ ...props.modelValue });\n\n/** 监听外部传入的 modelValue 变化 */\nwatch(() => props.modelValue, (newValue) => {\n confirmedValues.value = { ...(newValue || {}) };\n}, { deep: true, immediate: true });\n\n/** 当前打开的筛选项 */\nconst currentFilter = computed(() => {\n if (activeIndex.value === null) return null;\n return props.items[activeIndex.value];\n});\n\n/** 确定按钮文本 */\nconst selectedCountText = computed(() => {\n if (!currentFilter.value) return '';\n const count = getTempSelectedCount(currentFilter.value);\n return count > 0 ? `(${count}项)` : '';\n});\n\n/**\n * 获取筛选项的显示文本\n * @param item 筛选项配置\n * @returns 显示文本\n */\nconst getItemDisplayText = (item: FilterItem): string => {\n const value = confirmedValues.value[item.key];\n if (value === undefined || value === null || value === '') {\n return item.label;\n }\n \n if (item.slot) {\n // 插槽类型:显示标签,具体显示内容由插槽决定\n return item.label;\n } else if (item.type === 'input') {\n // 输入框类型\n if (value && String(value).trim()) {\n return `${item.label}: ${value}`;\n }\n } else if (item.type === 'calendar') {\n // 日历类型\n if (value) {\n if (Array.isArray(value) && value.length === 2) {\n return `${item.label}: ${value[0]} ~ ${value[1]}`;\n } else if (typeof value === 'string') {\n return `${item.label}: ${value}`;\n }\n }\n } else if (item.type === 'single' || item.type === 'tree-single') {\n // 单选类型\n const option = findOption(item, value);\n if (option) {\n return `${item.label}: ${getResultLabel(option, item)}`;\n }\n } else {\n // 多选类型(包括 tree-multiple)\n const values = Array.isArray(value) ? value : [value];\n if (values.length > 0) {\n const labels = values\n .map((val) => {\n const opt = findOption(item, val);\n return opt ? getResultLabel(opt, item) : null;\n })\n .filter((label) => label !== null);\n \n if (labels.length > 0) {\n return `${item.label}: ${labels.join('、')}`;\n }\n }\n }\n \n return item.label;\n};\n\n/**\n * 打开筛选模态窗\n * @param index 筛选项索引\n */\nconst openFilter = (index: number) => {\n const item = props.items[index];\n if (!item) return;\n \n // 如果点击的是当前已打开的筛选项,则收起\n if (activeIndex.value === index) {\n activeIndex.value = null;\n return;\n }\n \n // 初始化临时选中值\n const currentValue = confirmedValues.value[item.key];\n if (item.slot) {\n // 插槽类型:初始化插槽值(保持原始数据类型,不做转换)\n if (currentValue !== undefined && currentValue !== null) {\n if (Array.isArray(currentValue)) {\n // 数组类型:使用数组复制\n tempSlotValues.value[item.key] = [...currentValue];\n } else if (typeof currentValue === 'object') {\n // 对象类型:使用对象展开\n tempSlotValues.value[item.key] = { ...currentValue };\n } else {\n // 其他类型:直接赋值\n tempSlotValues.value[item.key] = currentValue;\n }\n } else {\n tempSlotValues.value[item.key] = undefined;\n }\n } else if (item.type === 'input') {\n // 输入框类型\n tempInputValue.value = currentValue !== undefined && currentValue !== null ? String(currentValue) : '';\n } else if (item.type === 'calendar') {\n // 日历类型\n tempCalendarValue.value = currentValue !== undefined && currentValue !== null ? currentValue : null;\n } else if (item.type === 'single' || item.type === 'tree-single') {\n // 单选类型\n tempSelectedValues.value[item.key] = currentValue !== undefined ? currentValue : null;\n } else {\n // 多选类型(包括 tree-multiple)\n tempSelectedValues.value[item.key] = currentValue !== undefined \n ? (Array.isArray(currentValue) ? [...currentValue] : [currentValue])\n : [];\n }\n \n activeIndex.value = index;\n};\n\n/** 关闭筛选模态窗 */\nconst closeFilter = () => {\n activeIndex.value = null;\n};\n\n/**\n * 获取选项的显示文本\n * @param option 选项数据\n * @param item 筛选项配置(可选)\n * @returns 显示文本\n */\nconst getOptionLabel = (option: FilterOption | string, item?: FilterItem): string => {\n if (!item) {\n if (typeof option === 'string') return option;\n return option.label || String(option.value);\n }\n\n const data: any = typeof option === 'string' ? option : option;\n \n // 使用 renderItem\n if (item.renderItem) {\n if (typeof item.renderItem === 'string') {\n // 字符串模式:从数据中获取属性\n if (typeof data === 'object' && data !== null) {\n return String(data[item.renderItem] ?? '');\n }\n return String(data);\n } else {\n // 函数模式\n const result = item.renderItem(data);\n return result !== undefined && result !== null ? String(result) : '';\n }\n }\n \n // 默认行为\n if (typeof option === 'string') return option;\n return option.label || String(option.value);\n};\n\n/**\n * 获取选项的值\n * @param option 选项数据\n * @param item 筛选项配置(可选)\n * @returns 选项的值\n */\nconst getOptionValue = (option: FilterOption | string, item?: FilterItem): any => {\n if (!item) {\n if (typeof option === 'string') return option;\n return option.value !== undefined ? option.value : option;\n }\n\n const data: any = typeof option === 'string' ? option : option;\n \n // 使用 format\n if (item.format) {\n if (typeof item.format === 'string') {\n // 字符串模式:从数据中获取属性\n if (typeof data === 'object' && data !== null) {\n return data[item.format];\n }\n return data;\n } else {\n // 函数模式\n return item.format(data);\n }\n }\n \n // 默认行为\n if (typeof option === 'string') return option;\n return option.value !== undefined ? option.value : option;\n};\n\n/**\n * 获取结果中显示的文本\n * @param option 选项数据\n * @param item 筛选项配置\n * @returns 结果文本\n */\nconst getResultLabel = (option: FilterOption | string, item: FilterItem): string => {\n const data: any = typeof option === 'string' ? option : option;\n \n // 使用 renderResult,如果没有则使用 renderItem\n const render = item.renderResult || item.renderItem;\n \n if (render) {\n if (typeof render === 'string') {\n // 字符串模式:从数据中获取属性\n if (typeof data === 'object' && data !== null) {\n return String(data[render] ?? '');\n }\n return String(data);\n } else {\n // 函数模式\n const result = render(data);\n return result !== undefined && result !== null ? String(result) : '';\n }\n }\n \n // 默认行为\n return getOptionLabel(option, item);\n};\n\n/**\n * 查找选项(支持树形结构)\n * @param item 筛选项配置\n * @param value 要查找的值\n * @param options 选项列表(可选,用于递归查找)\n * @returns 找到的选项或 null\n */\nconst findOption = (item: FilterItem, value: any, options?: FilterOption[] | string[]): FilterOption | string | null => {\n const opts = options || item.options;\n if (!opts) return null;\n const childrenKey = item.childrenKey || 'children';\n \n for (const opt of opts) {\n const optValue = getOptionValue(opt, item);\n if (optValue === value || String(optValue) === String(value)) {\n return opt;\n }\n \n // 如果是树形结构,递归查找子节点\n if (typeof opt === 'object' && opt !== null) {\n const children = (opt as any)[childrenKey];\n if (Array.isArray(children) && children.length > 0) {\n const found = findOption(item, value, children);\n if (found) return found;\n }\n }\n }\n \n return null;\n};\n\n/**\n * 扁平化选项列表(用于树形结构)\n * @param item 筛选项配置\n * @param options 选项列表(可选,用于递归)\n * @returns 扁平化后的选项列表\n */\nconst flattenOptions = (item: FilterItem, options?: FilterOption[] | string[]): (FilterOption | string)[] => {\n const opts = options || item.options;\n if (!opts) return [];\n const childrenKey = item.childrenKey || 'children';\n const result: (FilterOption | string)[] = [];\n \n for (const opt of opts) {\n result.push(opt);\n \n // 如果有子节点,递归添加\n if (typeof opt === 'object' && opt !== null) {\n const children = (opt as any)[childrenKey];\n if (Array.isArray(children) && children.length > 0) {\n result.push(...flattenOptions(item, children));\n }\n }\n }\n \n return result;\n};\n\n/**\n * 判断选项是否被选中(临时状态)\n * @param option 选项数据\n * @returns 是否选中\n */\nconst isSelected = (option: FilterOption | string): boolean => {\n if (!currentFilter.value) return false;\n const key = currentFilter.value.key;\n const tempValue = tempSelectedValues.value[key];\n const optValue = getOptionValue(option, currentFilter.value);\n \n if (currentFilter.value.type === 'single' || currentFilter.value.type === 'tree-single') {\n return tempValue !== null && tempValue !== undefined && tempValue === optValue;\n } else {\n const tempArray = Array.isArray(tempValue) ? tempValue : [];\n return tempArray.some((v) => v === optValue || String(v) === String(optValue));\n }\n};\n\n/**\n * 获取显示的选项列表(普通模式)\n * @param item 筛选项配置\n * @returns 选项列表\n */\nconst getDisplayOptions = (item: FilterItem | null): (FilterOption | string)[] => {\n if (!item) return [];\n // 如果有 childrenKey,扁平化选项;否则直接返回\n return item.childrenKey ? flattenOptions(item) : (item.options || []);\n};\n\n/**\n * 获取树形结构的一级分组(仅返回一级选项,作为分组标题)\n * @param item 筛选项配置\n * @returns 一级选项列表\n */\nconst getTreeGroups = (item: FilterItem | null): (FilterOption | string)[] => {\n if (!item) return [];\n const childrenKey = item.childrenKey || 'children';\n // 只返回一级选项(有子节点的选项)\n return (item.options || []).filter((opt) => {\n if (typeof opt === 'string') return false;\n const children = (opt as any)[childrenKey];\n return Array.isArray(children) && children.length > 0;\n });\n};\n\n/**\n * 获取树形结构分组下的子选项\n * @param group 分组选项\n * @param item 筛选项配置\n * @returns 子选项列表\n */\nconst getTreeGroupChildren = (group: FilterOption | string, item: FilterItem | null): (FilterOption | string)[] => {\n if (!item || typeof group === 'string') return [];\n const childrenKey = item.childrenKey || 'children';\n const children = (group as any)[childrenKey];\n return Array.isArray(children) ? children : [];\n};\n\n/**\n * 获取插槽的当前值\n * @param item 筛选项配置\n * @returns 插槽的当前值\n */\nconst getSlotValue = (item: FilterItem | null): any => {\n if (!item) return undefined;\n return tempSlotValues.value[item.key] !== undefined ? tempSlotValues.value[item.key] : confirmedValues.value[item.key];\n};\n\n/**\n * 更新插槽的值\n * @param item 筛选项配置\n * @param value 新值\n */\nconst updateSlotValue = (item: FilterItem | null, value: any) => {\n if (!item) return;\n tempSlotValues.value[item.key] = value;\n \n // 如果启用了自动确认,立即确认并关闭\n if (props.autoConfirm) {\n const key = item.key;\n confirmedValues.value[key] = value;\n emit('update:modelValue', { ...confirmedValues.value });\n emit('change', { ...confirmedValues.value }, item);\n closeFilter();\n }\n};\n\n/**\n * 判断选项是否有子节点\n * @param option 选项数据\n * @param item 筛选项配置\n * @returns 是否有子节点\n */\nconst hasChildren = (option: FilterOption | string, item: FilterItem | null): boolean => {\n if (!item || !item.childrenKey) return false;\n if (typeof option === 'string') return false;\n const children = (option as any)[item.childrenKey];\n return Array.isArray(children) && children.length > 0;\n};\n\n/**\n * 单选(支持树形结构)- 点击后直接确认并关闭\n * @param option 选项数据\n */\nconst selectSingle = (option: FilterOption | string) => {\n if (!currentFilter.value) return;\n const key = currentFilter.value.key;\n const optValue = getOptionValue(option, currentFilter.value);\n const oldValue = confirmedValues.value[key];\n \n // 如果已选中,则取消选中;否则选中\n let newValue: any;\n if (tempSelectedValues.value[key] === optValue) {\n newValue = undefined;\n } else {\n newValue = optValue;\n }\n \n // 直接更新已确认的值\n confirmedValues.value[key] = newValue;\n \n // 更新 v-model\n emit('update:modelValue', { ...confirmedValues.value });\n \n // 触发 change 事件\n emit('change', { ...confirmedValues.value }, currentFilter.value);\n \n // 直接关闭面板\n closeFilter();\n};\n\n/**\n * 多选切换\n * @param option 选项数据\n */\nconst toggleOption = (option: FilterOption | string) => {\n if (!currentFilter.value) return;\n const key = currentFilter.value.key;\n const optValue = getOptionValue(option, currentFilter.value);\n const tempArray = Array.isArray(tempSelectedValues.value[key]) \n ? [...tempSelectedValues.value[key]] \n : [];\n \n const existingIndex = tempArray.findIndex(\n (v) => v === optValue || String(v) === String(optValue)\n );\n \n if (existingIndex >= 0) {\n tempArray.splice(existingIndex, 1);\n } else {\n tempArray.push(optValue);\n }\n \n tempSelectedValues.value[key] = tempArray;\n \n // 如果启用了自动确认,立即确认并关闭\n if (props.autoConfirm) {\n const newValue = tempArray.length > 0 ? tempArray : undefined;\n confirmedValues.value[key] = newValue;\n emit('update:modelValue', { ...confirmedValues.value });\n emit('change', { ...confirmedValues.value }, currentFilter.value);\n closeFilter();\n }\n};\n\n/** 重置当前筛选项 */\nconst resetCurrentFilter = () => {\n if (!currentFilter.value) return;\n const key = currentFilter.value.key;\n if (currentFilter.value.slot) {\n tempSlotValues.value[key] = undefined;\n } else if (currentFilter.value.type === 'input') {\n tempInputValue.value = '';\n } else if (currentFilter.value.type === 'calendar') {\n tempCalendarValue.value = null;\n } else if (currentFilter.value.type === 'single' || currentFilter.value.type === 'tree-single') {\n tempSelectedValues.value[key] = null;\n } else {\n tempSelectedValues.value[key] = [];\n }\n};\n\n/** 处理输入框变化 */\nconst handleInputChange = () => {\n // 如果启用了自动确认,立即确认并关闭\n if (props.autoConfirm && currentFilter.value) {\n const key = currentFilter.value.key;\n const newValue = tempInputValue.value.trim() || undefined;\n confirmedValues.value[key] = newValue;\n emit('update:modelValue', { ...confirmedValues.value });\n emit('change', { ...confirmedValues.value }, currentFilter.value);\n closeFilter();\n }\n};\n\n/** 处理日历变化 */\nconst handleCalendarChange = (value: string | [string, string] | null) => {\n tempCalendarValue.value = value;\n \n // 如果启用了自动确认,立即确认并关闭\n if (props.autoConfirm && currentFilter.value) {\n const key = currentFilter.value.key;\n const newValue = value !== null && value !== undefined ? value : undefined;\n confirmedValues.value[key] = newValue;\n emit('update:modelValue', { ...confirmedValues.value });\n emit('change', { ...confirmedValues.value }, currentFilter.value);\n closeFilter();\n }\n};\n\n/** 确认筛选 */\nconst confirmFilter = () => {\n if (!currentFilter.value) return;\n const key = currentFilter.value.key;\n const oldValue = confirmedValues.value[key];\n \n // 更新已确认的值\n let newValue: any;\n if (currentFilter.value.slot) {\n // 插槽类型\n newValue = tempSlotValues.value[key];\n confirmedValues.value[key] = newValue;\n } else if (currentFilter.value.type === 'input') {\n // 输入框类型\n newValue = tempInputValue.value.trim() || undefined;\n confirmedValues.value[key] = newValue;\n } else if (currentFilter.value.type === 'calendar') {\n // 日历类型\n newValue = tempCalendarValue.value !== null && tempCalendarValue.value !== undefined ? tempCalendarValue.value : undefined;\n confirmedValues.value[key] = newValue;\n } else if (currentFilter.value.type === 'single' || currentFilter.value.type === 'tree-single') {\n // 单选类型\n const tempValue = tempSelectedValues.value[key];\n newValue = tempValue !== null && tempValue !== undefined ? tempValue : undefined;\n confirmedValues.value[key] = newValue;\n } else {\n // 多选类型(包括 tree-multiple)\n const tempValue = tempSelectedValues.value[key];\n newValue = Array.isArray(tempValue) && tempValue.length > 0 ? tempValue : undefined;\n confirmedValues.value[key] = newValue;\n }\n \n // 更新 v-model\n emit('update:modelValue', { ...confirmedValues.value });\n \n // 触发 change 事件\n emit('change', { ...confirmedValues.value }, currentFilter.value);\n \n closeFilter();\n};\n\n/**\n * 获取已选中的数量(已确认的)\n * @param item 筛选项配置\n * @returns 选中数量\n */\nconst getSelectedCount = (item: FilterItem): number => {\n const value = confirmedValues.value[item.key];\n if (value === undefined || value === null || value === '') return 0;\n \n if (item.slot) {\n // 插槽类型:有值就返回1\n return 1;\n } else if (item.type === 'input') {\n return String(value).trim() ? 1 : 0;\n } else if (item.type === 'single' || item.type === 'tree-single') {\n return 1;\n } else {\n return Array.isArray(value) ? value.length : (value ? 1 : 0);\n }\n};\n\n/**\n * 获取临时选中的数量\n * @param item 筛选项配置\n * @returns 临时选中数量\n */\nconst getTempSelectedCount = (item: FilterItem): number => {\n if (item.slot) {\n // 插槽类型:有值就返回1\n const slotValue = tempSlotValues.value[item.key];\n return slotValue !== undefined && slotValue !== null && slotValue !== '' ? 1 : 0;\n } else if (item.type === 'input') {\n return tempInputValue.value.trim() ? 1 : 0;\n } else if (item.type === 'calendar') {\n return tempCalendarValue.value !== null && tempCalendarValue.value !== undefined ? 1 : 0;\n }\n \n const tempValue = tempSelectedValues.value[item.key];\n if (tempValue === undefined || tempValue === null || tempValue === '') return 0;\n \n if (item.type === 'single' || item.type === 'tree-single') {\n return 1;\n } else {\n return Array.isArray(tempValue) ? tempValue.length : 0;\n }\n};\n\n// 暴露方法供外部调用\ndefineExpose({\n /** 获取当前筛选值 */\n getValues: () => ({ ...confirmedValues.value }),\n /** 重置所有筛选 */\n reset: () => {\n confirmedValues.value = {};\n tempSelectedValues.value = {};\n tempSlotValues.value = {};\n emit('update:modelValue', {});\n },\n});\n</script>\n\n<style scoped lang=\"scss\">\n.rc-search-area {\n position: relative;\n width: 100%;\n\n &__bar {\n display: flex;\n align-items: center;\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n scrollbar-width: none;\n -ms-overflow-style: none;\n touch-action: pan-x;\n padding: 4px 8px;\n box-sizing: border-box;\n\n &::-webkit-scrollbar {\n display: none;\n }\n }\n\n &__item {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 4px 6px;\n font-size: 14px;\n color: #323233;\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n -webkit-tap-highlight-color: transparent;\n transition: all 0.2s;\n white-space: nowrap;\n flex-shrink: 0;\n flex-grow: 0;\n background: #F9F9F9;\n border: 1px solid transparent;\n border-radius: 4px;\n margin-right: 8px;\n max-width: calc(100% - 16px);\n min-width: 0;\n\n &:last-child {\n margin-right: 0;\n }\n\n &.has-value {\n border-color: #1677ff;\n color: #1677ff;\n background: #fff;\n }\n\n &.is-active {\n background: #F9F9F9;\n border-color: transparent;\n color: #323233;\n\n &::after {\n content: '';\n border: 1px solid #F9F9F9;\n position: absolute;\n bottom: -8px;\n width: 100%;\n height: 8px;\n background: #F9F9F9;\n }\n }\n\n &-label {\n margin-right: 4px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n flex: 1;\n max-width: 100%;\n }\n\n &-count {\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n margin-right: 4px;\n background: #1677ff;\n color: #fff;\n border-radius: 8px;\n font-size: 11px;\n line-height: 16px;\n text-align: center;\n }\n\n &-arrow {\n font-size: 10px;\n color: #969799;\n transition: transform 0.2s;\n transform: rotate(0deg);\n flex-shrink: 0;\n\n &.is-up {\n transform: rotate(180deg);\n }\n }\n }\n\n &__mask {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n z-index: 999;\n }\n\n &__panel {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n max-height: 70vh;\n background: #F9F9F9;\n z-index: 1000;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n border-bottom-right-radius: 8px;\n border-bottom-left-radius: 8px;\n }\n\n &__panel-content {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n }\n\n &__options-grid {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n }\n\n &__tree-container {\n display: flex;\n flex-direction: column;\n gap: 16px;\n }\n\n &__tree-group {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n &__tree-group-title {\n padding: 8px 12px;\n font-size: 14px;\n font-weight: 500;\n color: #323233;\n background: #f7f8fa;\n border-radius: 6px;\n user-select: none;\n cursor: default;\n }\n\n &__tree-group-options {\n display: flex;\n flex-wrap: wrap;\n gap: 12px;\n padding-left: 12px;\n }\n\n &__option {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 4px 6px;\n background: #f7f8fa;\n border: 1px solid #dcdee0;\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n flex-shrink: 0;\n\n &:hover {\n border-color: #1677ff;\n }\n\n &.is-selected {\n background: #e6f4ff;\n border-color: #1677ff;\n color: #1677ff;\n }\n\n &-label {\n font-size: 14px;\n }\n\n &-check {\n color: #1677ff;\n }\n }\n\n &__input-wrapper {\n padding: 8px;\n }\n\n &__calendar-wrapper {\n padding: 8px;\n }\n\n &__input {\n width: 100%;\n height: 40px;\n padding: 0 12px;\n font-size: 14px;\n color: #323233;\n background: #fff;\n border: 1px solid #dcdee0;\n border-radius: 8px;\n outline: none;\n box-sizing: border-box;\n transition: border-color 0.2s;\n\n &:focus {\n border-color: #1677ff;\n }\n\n &::placeholder {\n color: #969799;\n }\n }\n\n &__empty {\n padding: 40px 0;\n text-align: center;\n color: #969799;\n font-size: 14px;\n }\n\n &__panel-footer {\n display: flex;\n gap: 12px;\n padding: 8px;\n border-top: 1px solid #eee;\n flex-shrink: 0;\n }\n}\n\n// 过渡动画\n.rc-search-area-fade-enter-active,\n.rc-search-area-fade-leave-active {\n transition: opacity 0.3s ease-out;\n}\n\n.rc-search-area-fade-enter-from,\n.rc-search-area-fade-leave-to {\n opacity: 0;\n}\n\n.rc-search-area-fade-enter-to,\n.rc-search-area-fade-leave-from {\n opacity: 1;\n}\n\n.rc-search-area-slide-enter-active,\n.rc-search-area-slide-leave-active {\n transition: max-height 0.3s ease-out, opacity 0.3s ease-out;\n overflow: hidden;\n}\n\n.rc-search-area-slide-enter-from,\n.rc-search-area-slide-leave-to {\n max-height: 0;\n opacity: 0;\n}\n\n.rc-search-area-slide-enter-to,\n.rc-search-area-slide-leave-from {\n max-height: 70vh;\n opacity: 1;\n}\n</style>\n\n","/**\r\n * @description 基础用法\r\n */\r\nimport type { App } from 'vue';\r\nimport RcSearchArea from './index.vue';\r\n\r\nexport { RcSearchArea };\r\nexport type { FilterItem, FilterOption } from './index.vue';\r\n\r\nexport const install = (app: App) => {\r\n app.component('RcSearchArea', RcSearchArea);\r\n app.component('rc-search-area', RcSearchArea);\r\n};\r\n\r\nexport default RcSearchArea;\r\n\r\n","<template>\r\n <div class=\"rc-input\" :class=\"[\r\n `rc-input--${size}`,\r\n {\r\n 'is-disabled': disabled,\r\n 'is-focused': focused,\r\n 'is-readonly': readonly,\r\n 'rc-input--textarea': type === 'textarea',\r\n 'has-prepend': $slots.prepend,\r\n 'has-append': $slots.append,\r\n }\r\n ]\" @click=\"handleWrapperClick\">\r\n <!-- 前置元素 -->\r\n <div v-if=\"$slots.prepend\" class=\"rc-input__prepend\">\r\n <slot name=\"prepend\" />\r\n </div>\r\n\r\n <div class=\"rc-input__wrapper\">\r\n <!-- 前缀图标或插槽 -->\r\n <div v-if=\"prefixIcon || $slots.prefix\" class=\"rc-input__prefix\">\r\n <slot name=\"prefix\">\r\n <rc-icon v-if=\"prefixIcon\" :name=\"prefixIcon\" class=\"rc-input__prefix-icon\" />\r\n </slot>\r\n </div>\r\n\r\n <!-- 输入框或文本域 -->\r\n <component :is=\"type === 'textarea' ? 'textarea' : 'input'\" ref=\"inputRef\" :value=\"displayValue\"\r\n :type=\"actualType\" class=\"rc-input__field\" :class=\"{ 'rc-input__field--textarea': type === 'textarea' }\"\r\n :placeholder=\"placeholder\" :disabled=\"disabled\" :readonly=\"readonly\" :maxlength=\"maxlength\"\r\n :minlength=\"minlength\" :rows=\"rows\" :autocomplete=\"autocomplete\" :name=\"name\" :autofocus=\"autofocus\"\r\n :form=\"form\" :tabindex=\"tabindex\" :style=\"textareaStyle\" @input=\"onInput\" @focus=\"onFocus\" @blur=\"onBlur\"\r\n @keydown=\"onKeydown\" @mouseenter=\"onMouseEnter\" @mouseleave=\"onMouseLeave\"\r\n @compositionstart=\"onCompositionStart\" @compositionupdate=\"onCompositionUpdate\"\r\n @compositionend=\"onCompositionEnd\" />\r\n\r\n <!-- 后缀操作区 -->\r\n <div v-if=\"hasSuffix\" class=\"rc-input__suffix\">\r\n <div v-if=\"$slots.suffix\" class=\"rc-input__suffix-inner\">\r\n <slot name=\"suffix\" />\r\n </div>\r\n <!-- 密码显示/隐藏切换 -->\r\n <button v-if=\"showPassword && type === 'password' && hasValue\" type=\"button\" class=\"rc-input__password-toggle\"\r\n @click.stop=\"togglePassword\">\r\n <rc-icon :color=\"passwordVisible ? '#1677ff' : '#999'\"\r\n :name=\"passwordVisible ? 'icon_view' : 'icon_view-off'\" />\r\n </button>\r\n <!-- 清空按钮 -->\r\n <button v-if=\"clearable && hasValue && !disabled && !readonly\" type=\"button\" class=\"rc-input__clear\"\r\n @click.stop=\"onClear\">\r\n <rc-icon name=\"icon_close\" class=\"rc-input__clear-icon\" />\r\n </button>\r\n <!-- 后缀图标 -->\r\n <rc-icon v-if=\"suffixIcon && !clearable && !showPassword\" :name=\"suffixIcon\" class=\"rc-input__suffix-icon\" />\r\n </div>\r\n\r\n <!-- 字符计数 -->\r\n <span v-if=\"showWordLimit && maxlength\" class=\"rc-input__count\">\r\n {{ wordCount }} / {{ maxlength }}\r\n </span>\r\n </div>\r\n\r\n <!-- 后置元素 -->\r\n <div v-if=\"$slots.append\" class=\"rc-input__append\">\r\n <slot name=\"append\" />\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch, computed, nextTick, onMounted, useSlots } from 'vue';\r\nimport RcIcon from '../icon';\r\n\r\ntype InputValue = string | number | null | undefined;\r\ntype InputSize = 'large' | 'default' | 'small';\r\ntype AutosizeConfig = boolean | { minRows?: number; maxRows?: number };\r\n\r\ninterface Props {\r\n /** 双向绑定值 */\r\n modelValue?: InputValue;\r\n /** 输入框类型 */\r\n type?: string;\r\n /** 尺寸 */\r\n size?: InputSize;\r\n /** 占位符 */\r\n placeholder?: string;\r\n /** 是否禁用 */\r\n disabled?: boolean;\r\n /** 是否显示清空按钮 */\r\n clearable?: boolean;\r\n /** 是否显示密码切换按钮 */\r\n showPassword?: boolean;\r\n /** 是否只读 */\r\n readonly?: boolean;\r\n /** 最大输入长度 */\r\n maxlength?: number;\r\n /** 最小输入长度 */\r\n minlength?: number;\r\n /** 是否显示字数统计,只在 type 为 'text' 或 'textarea' 时生效 */\r\n showWordLimit?: boolean;\r\n /** 文本域行数 */\r\n rows?: number;\r\n /** 文本域自适应内容高度 */\r\n autosize?: AutosizeConfig;\r\n /** 文本域是否可以缩放 */\r\n resize?: 'none' | 'both' | 'horizontal' | 'vertical';\r\n /** 前缀图标 */\r\n prefixIcon?: string;\r\n /** 后缀图标 */\r\n suffixIcon?: string;\r\n /** 原生 autocomplete 属性 */\r\n autocomplete?: string;\r\n /** 原生 name 属性 */\r\n name?: string;\r\n /** 原生 autofocus 属性 */\r\n autofocus?: boolean;\r\n /** 原生 form 属性 */\r\n form?: string;\r\n /** tabindex */\r\n tabindex?: string | number;\r\n /** 格式化函数 */\r\n formatter?: (value: string) => string;\r\n /** 解析函数 */\r\n parser?: (value: string) => string;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n modelValue: '',\r\n type: 'text',\r\n size: 'default',\r\n placeholder: '请输入',\r\n disabled: false,\r\n clearable: false,\r\n showPassword: false,\r\n readonly: false,\r\n maxlength: undefined,\r\n minlength: undefined,\r\n showWordLimit: false,\r\n rows: 2,\r\n autosize: false,\r\n resize: undefined,\r\n prefixIcon: '',\r\n suffixIcon: '',\r\n autocomplete: 'off',\r\n name: undefined,\r\n autofocus: false,\r\n form: undefined,\r\n tabindex: undefined,\r\n formatter: undefined,\r\n parser: undefined,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n (e: 'update:modelValue', value: InputValue): void;\r\n (e: 'input', value: InputValue): void;\r\n (e: 'change', value: InputValue): void;\r\n (e: 'focus', event: FocusEvent): void;\r\n (e: 'blur', event: FocusEvent): void;\r\n (e: 'clear'): void;\r\n (e: 'keydown', event: KeyboardEvent): void;\r\n (e: 'mouseenter', event: MouseEvent): void;\r\n (e: 'mouseleave', event: MouseEvent): void;\r\n (e: 'compositionstart', event: CompositionEvent): void;\r\n (e: 'compositionupdate', event: CompositionEvent): void;\r\n (e: 'compositionend', event: CompositionEvent): void;\r\n}>();\r\n\r\nconst inputRef = ref<HTMLInputElement | HTMLTextAreaElement>();\r\nconst innerValue = ref<InputValue>(props.modelValue ?? '');\r\nconst focused = ref(false);\r\nconst passwordVisible = ref(false);\r\nconst isComposing = ref(false);\r\n\r\nwatch(\r\n () => props.modelValue,\r\n (val) => {\r\n innerValue.value = val ?? '';\r\n }\r\n);\r\n\r\n// 实际输入类型(密码框切换时)\r\nconst actualType = computed(() => {\r\n if (props.type === 'password') {\r\n return passwordVisible.value ? 'text' : 'password';\r\n }\r\n return props.type;\r\n});\r\n\r\n// 显示值(格式化后)\r\nconst displayValue = computed(() => {\r\n const value = String(innerValue.value ?? '');\r\n if (props.formatter && !isComposing.value) {\r\n return props.formatter(value);\r\n }\r\n return value;\r\n});\r\n\r\n// 是否有值\r\nconst hasValue = computed(() => {\r\n const value = innerValue.value;\r\n return value !== '' && value !== null && value !== undefined;\r\n});\r\n\r\n// 字符计数\r\nconst wordCount = computed(() => {\r\n return String(innerValue.value ?? '').length;\r\n});\r\n\r\n// 是否有后缀内容\r\nconst slots = useSlots();\r\nconst hasSuffix = computed(() => {\r\n return !!(\r\n props.suffixIcon ||\r\n (props.showPassword && props.type === 'password') ||\r\n (props.clearable && hasValue.value && !props.disabled && !props.readonly) ||\r\n slots.suffix\r\n );\r\n});\r\n\r\n// 文本域样式\r\nconst textareaStyle = computed(() => {\r\n if (props.type !== 'textarea') return {};\r\n const style: Record<string, string> = {};\r\n\r\n // 如果设置了 autosize,禁止 resize\r\n if (props.autosize) {\r\n style.resize = 'none';\r\n } else if (props.resize !== undefined) {\r\n // 如果明确设置了 resize,使用设置的值\r\n style.resize = props.resize;\r\n } else {\r\n // 默认允许垂直方向调整大小\r\n style.resize = 'vertical';\r\n }\r\n\r\n return style;\r\n});\r\n\r\n// 输入处理\r\nfunction onInput(event: Event) {\r\n const target = event.target as HTMLInputElement | HTMLTextAreaElement;\r\n let value = target.value;\r\n\r\n // 解析函数\r\n if (props.parser && !isComposing.value) {\r\n value = props.parser(value);\r\n }\r\n\r\n innerValue.value = value;\r\n emit('update:modelValue', value);\r\n emit('input', value);\r\n\r\n // change 事件在失焦或回车时触发\r\n if (props.type === 'textarea' && props.autosize) {\r\n nextTick(() => {\r\n resizeTextarea();\r\n });\r\n }\r\n}\r\n\r\n// 聚焦\r\nfunction onFocus(event: FocusEvent) {\r\n focused.value = true;\r\n emit('focus', event);\r\n}\r\n\r\n// 失焦\r\nfunction onBlur(event: FocusEvent) {\r\n focused.value = false;\r\n const value = innerValue.value;\r\n emit('blur', event);\r\n emit('change', value);\r\n}\r\n\r\n// 清空\r\nfunction onClear() {\r\n innerValue.value = '';\r\n emit('update:modelValue', '');\r\n emit('input', '');\r\n emit('change', '');\r\n emit('clear');\r\n nextTick(() => {\r\n inputRef.value?.focus();\r\n });\r\n}\r\n\r\n// 切换密码显示\r\nfunction togglePassword() {\r\n passwordVisible.value = !passwordVisible.value;\r\n}\r\n\r\n// 键盘按下\r\nfunction onKeydown(event: KeyboardEvent) {\r\n emit('keydown', event);\r\n if (event.key === 'Enter' && props.type !== 'textarea') {\r\n emit('change', innerValue.value);\r\n }\r\n}\r\n\r\n// 鼠标进入\r\nfunction onMouseEnter(event: MouseEvent) {\r\n emit('mouseenter', event);\r\n}\r\n\r\n// 鼠标离开\r\nfunction onMouseLeave(event: MouseEvent) {\r\n emit('mouseleave', event);\r\n}\r\n\r\n// 输入法开始\r\nfunction onCompositionStart(event: CompositionEvent) {\r\n isComposing.value = true;\r\n emit('compositionstart', event);\r\n}\r\n\r\n// 输入法更新\r\nfunction onCompositionUpdate(event: CompositionEvent) {\r\n emit('compositionupdate', event);\r\n}\r\n\r\n// 输入法结束\r\nfunction onCompositionEnd(event: CompositionEvent) {\r\n isComposing.value = false;\r\n emit('compositionend', event);\r\n // 输入法结束后触发 input\r\n const target = event.target as HTMLInputElement | HTMLTextAreaElement;\r\n if (target) {\r\n onInput(event as any);\r\n }\r\n}\r\n\r\n// 包装器点击\r\nfunction handleWrapperClick() {\r\n if (props.disabled || props.readonly) return;\r\n inputRef.value?.focus();\r\n}\r\n\r\n// 调整文本域高度\r\nfunction resizeTextarea() {\r\n if (props.type !== 'textarea' || !inputRef.value) return;\r\n\r\n const textarea = inputRef.value as HTMLTextAreaElement;\r\n\r\n if (props.autosize) {\r\n textarea.style.height = 'auto';\r\n const scrollHeight = textarea.scrollHeight;\r\n\r\n if (typeof props.autosize === 'object') {\r\n const { minRows = 2, maxRows } = props.autosize;\r\n const lineHeight = parseInt(getComputedStyle(textarea).lineHeight) || 20;\r\n const minHeight = minRows * lineHeight;\r\n const maxHeight = maxRows ? maxRows * lineHeight : Infinity;\r\n\r\n textarea.style.height = `${Math.min(Math.max(scrollHeight, minHeight), maxHeight)}px`;\r\n } else {\r\n textarea.style.height = `${scrollHeight}px`;\r\n }\r\n }\r\n}\r\n\r\n// 暴露方法\r\nfunction focus() {\r\n inputRef.value?.focus();\r\n}\r\n\r\nfunction blur() {\r\n inputRef.value?.blur();\r\n}\r\n\r\nfunction select() {\r\n if (inputRef.value && 'select' in inputRef.value) {\r\n (inputRef.value as HTMLInputElement).select();\r\n }\r\n}\r\n\r\nfunction clear() {\r\n onClear();\r\n}\r\n\r\nonMounted(() => {\r\n if (props.type === 'textarea' && props.autosize) {\r\n resizeTextarea();\r\n }\r\n});\r\n\r\ndefineExpose({\r\n focus,\r\n blur,\r\n select,\r\n clear,\r\n resizeTextarea,\r\n inputRef,\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.rc-input {\r\n --rc-primary: #1677ff;\r\n --rc-text: #323233;\r\n --rc-border: #dcdee0;\r\n --rc-white: #ffffff;\r\n --rc-bg: #f7f8fa;\r\n --rc-disabled: #c8c9cc;\r\n\r\n position: relative;\r\n display: inline-flex;\r\n width: 100%;\r\n font-size: 14px;\r\n line-height: 1.5;\r\n\r\n &--small {\r\n font-size: 12px;\r\n }\r\n\r\n &--large {\r\n font-size: 16px;\r\n }\r\n\r\n &--textarea {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n\r\n &__prepend,\r\n &__append {\r\n display: flex;\r\n align-items: center;\r\n padding: 0 12px;\r\n background: var(--rc-bg);\r\n border: 1px solid var(--rc-border);\r\n white-space: nowrap;\r\n }\r\n\r\n &__prepend {\r\n border-right: none;\r\n border-top-left-radius: 6px;\r\n border-bottom-left-radius: 6px;\r\n border-top-right-radius: 0;\r\n border-bottom-right-radius: 0;\r\n }\r\n\r\n &__append {\r\n border-left: none;\r\n border-top-right-radius: 6px;\r\n border-bottom-right-radius: 6px;\r\n border-top-left-radius: 0;\r\n border-bottom-left-radius: 0;\r\n }\r\n\r\n &__wrapper {\r\n position: relative;\r\n display: inline-flex;\r\n align-items: center;\r\n width: 100%;\r\n padding: 8px 12px;\r\n border: 1px solid var(--rc-border);\r\n border-radius: 6px;\r\n background: var(--rc-white);\r\n transition: border-color 0.2s, box-shadow 0.2s;\r\n\r\n .rc-input--small & {\r\n padding: 4px 8px;\r\n }\r\n\r\n .rc-input--large & {\r\n padding: 12px 16px;\r\n }\r\n\r\n .rc-input--textarea & {\r\n padding: 0;\r\n align-items: stretch;\r\n }\r\n\r\n .rc-input.has-prepend & {\r\n border-top-left-radius: 0;\r\n border-bottom-left-radius: 0;\r\n }\r\n\r\n .rc-input.has-append & {\r\n border-top-right-radius: 0;\r\n border-bottom-right-radius: 0;\r\n }\r\n }\r\n\r\n &.is-focused &__wrapper {\r\n border-color: var(--rc-primary);\r\n box-shadow: 0 0 0 2px rgba(22, 119, 255, 0.12);\r\n }\r\n\r\n &.is-disabled &__wrapper {\r\n background: var(--rc-bg);\r\n cursor: not-allowed;\r\n }\r\n\r\n &.is-readonly &__wrapper {\r\n background: var(--rc-bg);\r\n }\r\n\r\n &__prefix {\r\n display: flex;\r\n align-items: center;\r\n margin-right: 8px;\r\n color: var(--rc-text);\r\n }\r\n\r\n &__prefix-icon {\r\n font-size: 16px;\r\n }\r\n\r\n &__field {\r\n flex: 1;\r\n border: none;\r\n outline: none;\r\n background: transparent;\r\n font-size: inherit;\r\n color: var(--rc-text);\r\n min-width: 0;\r\n padding: 0;\r\n\r\n &::placeholder {\r\n color: var(--rc-disabled);\r\n }\r\n\r\n &--textarea {\r\n min-height: 32px;\r\n line-height: 1.5;\r\n padding: 8px 12px;\r\n width: 100%;\r\n }\r\n }\r\n\r\n &--small &__field--textarea {\r\n padding: 4px 8px;\r\n }\r\n\r\n &--large &__field--textarea {\r\n padding: 12px 16px;\r\n }\r\n\r\n &__suffix {\r\n display: flex;\r\n align-items: center;\r\n margin-left: 8px;\r\n gap: 4px;\r\n\r\n &:empty {\r\n display: none;\r\n }\r\n }\r\n\r\n &__suffix-inner {\r\n display: flex;\r\n align-items: center;\r\n color: var(--rc-text);\r\n }\r\n\r\n &__suffix-icon {\r\n font-size: 16px;\r\n color: var(--rc-text);\r\n }\r\n\r\n &__clear {\r\n border: none;\r\n background: transparent;\r\n cursor: pointer;\r\n padding: 0;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n opacity: 0;\r\n transition: opacity 0.2s;\r\n color: var(--rc-disabled);\r\n font-size: 16px;\r\n\r\n &:hover {\r\n color: var(--rc-text);\r\n }\r\n }\r\n\r\n &__password-toggle {\r\n border: none;\r\n background: transparent;\r\n cursor: pointer;\r\n padding: 0;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n color: var(--rc-disabled);\r\n font-size: 16px;\r\n opacity: 1;\r\n\r\n &:hover {\r\n color: var(--rc-text);\r\n }\r\n }\r\n\r\n &:hover &__clear:not(:disabled) {\r\n opacity: 1;\r\n }\r\n\r\n &__count {\r\n position: absolute;\r\n right: 8px;\r\n bottom: 4px;\r\n font-size: 12px;\r\n color: var(--rc-disabled);\r\n line-height: 1;\r\n }\r\n\r\n &--textarea &__count {\r\n bottom: 8px;\r\n right: 12px;\r\n }\r\n\r\n &.is-disabled {\r\n .rc-input__field {\r\n color: var(--rc-disabled);\r\n cursor: not-allowed;\r\n }\r\n }\r\n}\r\n</style>\r\n\r\n\r\n\r\n","import type { App } from 'vue';\r\nimport Input from './index.vue';\r\n\r\n(Input as any).name = 'rc-input';\r\n\r\nexport function install(app: App) {\r\n app.component((Input as any).name, Input);\r\n return app;\r\n}\r\n\r\nexport default Input;\r\n\r\n","<template>\r\n <teleport v-if=\"hasTeleport\" to=\"body\">\r\n <transition name=\"rc-dropdown-fade\">\r\n <ul\r\n v-if=\"shouldShow\"\r\n ref=\"menuRef\"\r\n class=\"rc-dropdown-menu\"\r\n :class=\"[`rc-dropdown-menu--${effect}`]\"\r\n :style=\"menuStyle\"\r\n @click.stop\r\n @mouseenter=\"$emit('mouseenter', $event)\"\r\n @mouseleave=\"$emit('mouseleave', $event)\"\r\n >\r\n <slot />\r\n </ul>\r\n </transition>\r\n </teleport>\r\n <ul\r\n v-else\r\n ref=\"menuRef\"\r\n class=\"rc-dropdown-menu rc-dropdown-menu--nested\"\r\n :class=\"[`rc-dropdown-menu--${effect}`]\"\r\n :style=\"menuStyle\"\r\n @click.stop\r\n @mouseenter=\"$emit('mouseenter', $event)\"\r\n @mouseleave=\"$emit('mouseleave', $event)\"\r\n >\r\n <slot />\r\n </ul>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, computed } from 'vue';\r\n\r\ndefineOptions({ name: 'rc-dropdown-menu' });\r\n\r\ninterface Props {\r\n visible?: boolean;\r\n effect?: 'dark' | 'light';\r\n maxHeight?: string | number;\r\n}\r\n\r\nconst emit = defineEmits<{\r\n (e: 'mouseenter', event: MouseEvent): void;\r\n (e: 'mouseleave', event: MouseEvent): void;\r\n}>();\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n visible: undefined,\r\n effect: 'light',\r\n maxHeight: '',\r\n});\r\n\r\nconst menuRef = ref<HTMLElement>();\r\n\r\n// 如果 visible 未定义,说明是嵌套使用的内层菜单,应该始终显示\r\n// 如果 visible 已定义,则根据其值决定是否显示\r\nconst shouldShow = computed(() => {\r\n return props.visible === undefined ? true : props.visible;\r\n});\r\n\r\n// 只有外层菜单(有 visible prop)才使用 teleport\r\nconst hasTeleport = computed(() => {\r\n return props.visible !== undefined;\r\n});\r\n\r\nconst menuStyle = computed(() => {\r\n const style: Record<string, string> = {};\r\n if (props.maxHeight) {\r\n style.maxHeight = typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight;\r\n style.overflowY = 'auto';\r\n }\r\n return style;\r\n});\r\n\r\ndefineExpose({\r\n menuRef,\r\n});\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.rc-dropdown-menu {\r\n --rc-primary: #1677ff;\r\n --rc-text: #323233;\r\n --rc-border: #dcdee0;\r\n --rc-white: #ffffff;\r\n --rc-bg: #f7f8fa;\r\n\r\n position: fixed;\r\n z-index: 2000;\r\n min-width: 120px;\r\n padding: 4px 0;\r\n margin: 0;\r\n background: var(--rc-white);\r\n border: 1px solid var(--rc-border);\r\n border-radius: 6px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n list-style: none;\r\n\r\n &--dark {\r\n background: #1d1e1f;\r\n border-color: #1d1e1f;\r\n color: var(--rc-white);\r\n }\r\n\r\n &--light {\r\n background: var(--rc-white);\r\n border-color: var(--rc-border);\r\n color: var(--rc-text);\r\n }\r\n\r\n &--nested {\r\n position: static;\r\n top: auto;\r\n left: auto;\r\n box-shadow: none;\r\n border: none;\r\n padding: 0;\r\n }\r\n}\r\n\r\n.rc-dropdown-fade-enter-active,\r\n.rc-dropdown-fade-leave-active {\r\n transition: opacity 0.15s, transform 0.15s;\r\n}\r\n\r\n.rc-dropdown-fade-enter-from,\r\n.rc-dropdown-fade-leave-to {\r\n opacity: 0;\r\n transform: scale(0.95);\r\n}\r\n</style>\r\n\r\n\r\n\r\n","<template>\r\n <div\r\n ref=\"dropdownRef\"\r\n class=\"rc-dropdown\"\r\n :class=\"{ 'is-disabled': disabled }\"\r\n @mouseenter=\"handleMouseEnter\"\r\n @mouseleave=\"handleMouseLeave\"\r\n @click=\"handleClick\"\r\n >\r\n <slot />\r\n\r\n <rc-dropdown-menu\r\n ref=\"menuRef\"\r\n :visible=\"visible\"\r\n :effect=\"effect\"\r\n :max-height=\"maxHeight\"\r\n @mouseenter=\"handleMenuMouseEnter\"\r\n @mouseleave=\"handleMenuMouseLeave\"\r\n >\r\n <slot name=\"dropdown\" />\r\n </rc-dropdown-menu>\r\n </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, provide, watch, computed, onMounted, onUnmounted, nextTick } from 'vue';\r\nimport RcDropdownMenu from './menu.vue';\r\nimport type { DropdownPlacement } from './types';\r\n\r\ndefineOptions({ name: 'rc-dropdown' });\r\n\r\ninterface Props {\r\n placement?: DropdownPlacement;\r\n trigger?: 'hover' | 'click';\r\n disabled?: boolean;\r\n effect?: 'dark' | 'light';\r\n maxHeight?: string | number;\r\n hideOnClick?: boolean;\r\n showTimeout?: number;\r\n hideTimeout?: number;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n placement: 'bottom',\r\n trigger: 'hover',\r\n disabled: false,\r\n effect: 'light',\r\n maxHeight: '',\r\n hideOnClick: true,\r\n showTimeout: 150,\r\n hideTimeout: 150,\r\n});\r\n\r\nconst emit = defineEmits<{\r\n (e: 'command', command: string | number | object): void;\r\n (e: 'visible-change', visible: boolean): void;\r\n}>();\r\n\r\nconst dropdownRef = ref<HTMLElement>();\r\nconst menuRef = ref<InstanceType<typeof RcDropdownMenu>>();\r\nconst visible = ref(false);\r\nlet showTimer: ReturnType<typeof setTimeout> | null = null;\r\nlet hideTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n// 处理菜单项点击\r\nfunction handleItemClick(command?: string | number | object) {\r\n if (props.hideOnClick) {\r\n visible.value = false;\r\n }\r\n if (command !== undefined) {\r\n emit('command', command);\r\n }\r\n}\r\n\r\nprovide('handleItemClick', handleItemClick);\r\n\r\n// 显示菜单\r\nfunction show() {\r\n if (props.disabled) return;\r\n if (showTimer) {\r\n clearTimeout(showTimer);\r\n showTimer = null;\r\n }\r\n if (hideTimer) {\r\n clearTimeout(hideTimer);\r\n hideTimer = null;\r\n }\r\n showTimer = setTimeout(() => {\r\n visible.value = true;\r\n // 使用 requestAnimationFrame 确保 DOM 已更新\r\n requestAnimationFrame(() => {\r\n nextTick(() => {\r\n updatePosition();\r\n });\r\n });\r\n }, props.showTimeout);\r\n}\r\n\r\n// 隐藏菜单\r\nfunction hide() {\r\n if (props.trigger === 'hover' && isMenuHovered.value) {\r\n return;\r\n }\r\n if (hideTimer) {\r\n clearTimeout(hideTimer);\r\n hideTimer = null;\r\n }\r\n if (showTimer) {\r\n clearTimeout(showTimer);\r\n showTimer = null;\r\n }\r\n hideTimer = setTimeout(() => {\r\n visible.value = false;\r\n isMenuHovered.value = false;\r\n }, props.hideTimeout);\r\n}\r\n\r\n// 切换菜单显示状态\r\nfunction toggle() {\r\n if (props.disabled) return;\r\n if (visible.value) {\r\n hide();\r\n } else {\r\n show();\r\n }\r\n}\r\n\r\n// 鼠标进入\r\nfunction handleMouseEnter() {\r\n if (props.trigger === 'hover' && !props.disabled) {\r\n show();\r\n }\r\n}\r\n\r\n// 鼠标离开\r\nfunction handleMouseLeave() {\r\n if (props.trigger === 'hover') {\r\n // 延迟隐藏,给菜单鼠标进入的时间\r\n setTimeout(() => {\r\n if (!isMenuHovered.value) {\r\n hide();\r\n }\r\n }, 50);\r\n }\r\n}\r\n\r\nconst isMenuHovered = ref(false);\r\n\r\n// 菜单鼠标进入\r\nfunction handleMenuMouseEnter() {\r\n if (props.trigger === 'hover') {\r\n isMenuHovered.value = true;\r\n if (showTimer) {\r\n clearTimeout(showTimer);\r\n showTimer = null;\r\n }\r\n if (hideTimer) {\r\n clearTimeout(hideTimer);\r\n hideTimer = null;\r\n }\r\n }\r\n}\r\n\r\n// 菜单鼠标离开\r\nfunction handleMenuMouseLeave() {\r\n if (props.trigger === 'hover') {\r\n isMenuHovered.value = false;\r\n hide();\r\n }\r\n}\r\n\r\n// 点击\r\nfunction handleClick(event: MouseEvent) {\r\n if (props.trigger === 'click' && !props.disabled) {\r\n event.stopPropagation();\r\n toggle();\r\n }\r\n}\r\n\r\n// 更新菜单位置\r\nfunction updatePosition() {\r\n if (!dropdownRef.value || !menuRef.value?.menuRef) return;\r\n \r\n const triggerEl = dropdownRef.value;\r\n const menuEl = menuRef.value.menuRef as HTMLElement;\r\n \r\n if (!triggerEl || !menuEl) return;\r\n\r\n const triggerRect = triggerEl.getBoundingClientRect();\r\n \r\n // 确保菜单已经渲染完成,如果尺寸为0则等待\r\n const menuRect = menuEl.getBoundingClientRect();\r\n if (menuRect.width === 0 || menuRect.height === 0) {\r\n // 如果菜单还没有尺寸,延迟重试\r\n setTimeout(() => {\r\n if (visible.value) {\r\n updatePosition();\r\n }\r\n }, 10);\r\n return;\r\n }\r\n \r\n // 使用 fixed 定位,直接使用 getBoundingClientRect 的坐标(相对于视口)\r\n let top = 0;\r\n let left = 0;\r\n\r\n switch (props.placement) {\r\n case 'top':\r\n top = triggerRect.top - menuRect.height;\r\n left = triggerRect.left;\r\n break;\r\n case 'top-start':\r\n top = triggerRect.top - menuRect.height;\r\n left = triggerRect.left;\r\n break;\r\n case 'top-end':\r\n top = triggerRect.top - menuRect.height;\r\n left = triggerRect.left + triggerRect.width - menuRect.width;\r\n break;\r\n case 'bottom':\r\n top = triggerRect.bottom;\r\n left = triggerRect.left + (triggerRect.width - menuRect.width) / 2;\r\n break;\r\n case 'bottom-start':\r\n top = triggerRect.bottom;\r\n left = triggerRect.left;\r\n break;\r\n case 'bottom-end':\r\n top = triggerRect.bottom;\r\n left = triggerRect.left + triggerRect.width - menuRect.width;\r\n break;\r\n case 'left':\r\n top = triggerRect.top + (triggerRect.height - menuRect.height) / 2;\r\n left = triggerRect.left - menuRect.width;\r\n break;\r\n case 'left-start':\r\n top = triggerRect.top;\r\n left = triggerRect.left - menuRect.width;\r\n break;\r\n case 'left-end':\r\n top = triggerRect.top + triggerRect.height - menuRect.height;\r\n left = triggerRect.left - menuRect.width;\r\n break;\r\n case 'right':\r\n top = triggerRect.top + (triggerRect.height - menuRect.height) / 2;\r\n left = triggerRect.right;\r\n break;\r\n case 'right-start':\r\n top = triggerRect.top;\r\n left = triggerRect.right;\r\n break;\r\n case 'right-end':\r\n top = triggerRect.top + triggerRect.height - menuRect.height;\r\n left = triggerRect.right;\r\n break;\r\n }\r\n\r\n // 边界检测和调整(fixed 定位相对于视口)\r\n const viewportWidth = window.innerWidth;\r\n const viewportHeight = window.innerHeight;\r\n\r\n if (left < 0) left = 8;\r\n if (left + menuRect.width > viewportWidth) {\r\n left = viewportWidth - menuRect.width - 8;\r\n }\r\n if (top < 0) top = 8;\r\n if (top + menuRect.height > viewportHeight) {\r\n top = viewportHeight - menuRect.height - 8;\r\n }\r\n\r\n menuEl.style.top = `${top}px`;\r\n menuEl.style.left = `${left}px`;\r\n menuEl.style.position = 'fixed';\r\n menuEl.style.visibility = 'visible';\r\n menuEl.style.display = 'block';\r\n}\r\n\r\n// 监听 visible 变化\r\nwatch(visible, (val) => {\r\n emit('visible-change', val);\r\n if (val) {\r\n // 使用 requestAnimationFrame 确保 DOM 已更新\r\n requestAnimationFrame(() => {\r\n nextTick(() => {\r\n updatePosition();\r\n });\r\n });\r\n document.addEventListener('click', handleDocumentClick);\r\n } else {\r\n document.removeEventListener('click', handleDocumentClick);\r\n }\r\n});\r\n\r\n// 处理文档点击\r\nfunction handleDocumentClick(event: MouseEvent) {\r\n if (props.trigger === 'click' && !props.disabled) {\r\n const target = event.target as HTMLElement;\r\n if (dropdownRef.value && !dropdownRef.value.contains(target)) {\r\n hide();\r\n }\r\n }\r\n}\r\n\r\n// 监听窗口大小变化\r\nfunction handleResize() {\r\n if (visible.value) {\r\n updatePosition();\r\n }\r\n}\r\n\r\nonMounted(() => {\r\n window.addEventListener('resize', handleResize);\r\n window.addEventListener('scroll', handleResize, true);\r\n});\r\n\r\nonUnmounted(() => {\r\n if (showTimer) clearTimeout(showTimer);\r\n if (hideTimer) clearTimeout(hideTimer);\r\n document.removeEventListener('click', handleDocumentClick);\r\n window.removeEventListener('resize', handleResize);\r\n window.removeEventListener('scroll', handleResize, true);\r\n});\r\n\r\n// 暴露方法\r\ndefineExpose({\r\n show,\r\n hide,\r\n toggle,\r\n visible,\r\n});\r\n</script>\r\n\r\n\r\n<style scoped lang=\"scss\">\r\n.rc-dropdown {\r\n position: relative;\r\n display: inline-block;\r\n\r\n &.is-disabled {\r\n cursor: not-allowed;\r\n opacity: 0.6;\r\n }\r\n}\r\n</style>\r\n\r\n\r\n\r\n\r\n","<template>\r\n <li\r\n class=\"rc-dropdown-item\"\r\n :class=\"{\r\n 'is-disabled': disabled,\r\n 'is-divided': divided,\r\n }\"\r\n @click=\"handleClick\"\r\n >\r\n <rc-icon v-if=\"icon\" :name=\"icon\" class=\"rc-dropdown-item__icon\" />\r\n <span class=\"rc-dropdown-item__text\">\r\n <slot />\r\n </span>\r\n </li>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { inject } from 'vue';\r\nimport RcIcon from '../icon/index.vue';\r\n\r\ndefineOptions({ name: 'rc-dropdown-item' });\r\n\r\ninterface Props {\r\n command?: string | number | object;\r\n disabled?: boolean;\r\n divided?: boolean;\r\n icon?: string;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n command: undefined,\r\n disabled: false,\r\n divided: false,\r\n icon: '',\r\n});\r\n\r\nconst handleItemClick = inject<(command?: string | number | object) => void>('handleItemClick', () => {});\r\n\r\nfunction handleClick(event: MouseEvent) {\r\n if (props.disabled) {\r\n event.stopPropagation();\r\n return;\r\n }\r\n handleItemClick(props.command);\r\n}\r\n</script>\r\n\r\n<style scoped lang=\"scss\">\r\n.rc-dropdown-item {\r\n --rc-primary: #1677ff;\r\n --rc-text: #323233;\r\n --rc-disabled: #c8c9cc;\r\n --rc-hover: #f5f5f5;\r\n --rc-border: #dcdee0;\r\n\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n padding: 8px 16px;\r\n margin: 0;\r\n font-size: 14px;\r\n line-height: 22px;\r\n color: var(--rc-text);\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n list-style: none;\r\n\r\n &:hover:not(.is-disabled) {\r\n background-color: var(--rc-hover);\r\n }\r\n\r\n &.is-disabled {\r\n color: var(--rc-disabled);\r\n cursor: not-allowed;\r\n }\r\n\r\n &.is-divided {\r\n border-top: 1px solid #dcdee0;\r\n margin-top: 4px;\r\n padding-top: 8px;\r\n }\r\n\r\n &__icon {\r\n margin-right: 8px;\r\n font-size: 14px;\r\n }\r\n\r\n &__text {\r\n flex: 1;\r\n }\r\n}\r\n\r\n:deep(.rc-dropdown-menu--dark) .rc-dropdown-item {\r\n color: rgba(255, 255, 255, 0.9);\r\n\r\n &:hover:not(.is-disabled) {\r\n background-color: rgba(255, 255, 255, 0.1);\r\n }\r\n\r\n &.is-disabled {\r\n color: rgba(255, 255, 255, 0.4);\r\n }\r\n\r\n &.is-divided {\r\n border-top-color: rgba(255, 255, 255, 0.1);\r\n }\r\n}\r\n</style>\r\n\r\n\r\n\r\n","import type { App } from 'vue';\r\nimport Dropdown from './index.vue';\r\nimport DropdownMenu from './menu.vue';\r\nimport DropdownItem from './item.vue';\r\n\r\n(Dropdown as any).name = 'rc-dropdown';\r\n(DropdownMenu as any).name = 'rc-dropdown-menu';\r\n(DropdownItem as any).name = 'rc-dropdown-item';\r\n\r\nexport function install(app: App) {\r\n app.component((Dropdown as any).name, Dropdown);\r\n app.component((DropdownMenu as any).name, DropdownMenu);\r\n app.component((DropdownItem as any).name, DropdownItem);\r\n return app;\r\n}\r\n\r\nexport { DropdownMenu, DropdownItem };\r\nexport default Dropdown;\r\n\r\n\r\n\r\n\r\n","// library entry\nimport type { App, Plugin } from 'vue';\nimport { install as installButton } from './components/button';\nimport { install as installDescriptions } from './components/descriptions';\nimport { install as installCard } from './components/card';\nimport { install as installToast } from './components/toast';\nimport { install as installMessage } from './components/message';\nimport { install as installIcon } from './components/icon/index';\nimport { install as installSearchArea } from './components/search-area';\nimport { install as installCalendar } from './components/calendar';\nimport { install as installPopup } from './components/popup';\nimport { install as installInput } from './components/input';\nimport { install as installDropdown } from './components/dropdown';\nimport type { RecycleUIOptions } from './types';\n\nexport const RECYCLE_UI_SYMBOL = Symbol('RECYCLE_UI_CONFIG');\n\nexport const defaultRecycleUIConfig: RecycleUIOptions = {\n prefix: 'rc',\n autoRegister: true,\n provideKey: RECYCLE_UI_SYMBOL,\n // 预留主题/其他全局配置\n theme: {},\n // IconFont 默认配置(可在 app.use 时覆盖)\n iconCssUrl: '//at.alicdn.com/t/c/font_4252799_2vm5jrrzfvq.css',\n iconClass: 'iconfont',\n};\n\n// 统一导出所有类型的命名空间\nexport namespace RecycleUiTypes {\n // 核心配置类型\n export type Options = RecycleUIOptions;\n export type DefaultConfig = typeof defaultRecycleUIConfig;\n \n // Message 相关类型\n export type MessageOptions = import('./components/message').MessageOptions;\n export type MessageType = import('./components/message/index.vue').MessageType;\n export type MessageItem = import('./components/message/index.vue').MessageItem;\n \n // Toast 相关类型\n export type ToastProps = import('./components/toast/index.vue').ToastProps;\n export type ToastType = import('./components/toast/index.vue').ToastType;\n export type ShowToastOptions = import('./components/toast').ShowToastOptions;\n}\n\nfunction doAutoRegister(app: App, opts: RecycleUIOptions) {\n if (opts.autoRegister === false) return;\n if (typeof installButton === 'function') installButton(app);\n if (typeof installDescriptions === 'function') installDescriptions(app);\n if (typeof installCard === 'function') installCard(app);\n if (typeof installToast === 'function') installToast(app);\n if (typeof installIcon === 'function') installIcon(app);\n if (typeof installMessage === 'function') installMessage(app);\n if (typeof installSearchArea === 'function') installSearchArea(app);\n if (typeof installCalendar === 'function') installCalendar(app);\n if (typeof installPopup === 'function') installPopup(app);\n if (typeof installInput === 'function') installInput(app);\n if (typeof installDropdown === 'function') installDropdown(app);\n}\n\nexport const install = (app: App, options?: RecycleUIOptions) => {\n const cfg: RecycleUIOptions = { ...defaultRecycleUIConfig, ...(options || {}) };\n // 提供全局配置\n app.provide(cfg.provideKey ?? RECYCLE_UI_SYMBOL, cfg);\n // 供模板/实例访问:this.$recycleUI\n (app.config.globalProperties as any).$recycleUI = cfg;\n // 注入 IconFont 样式链接(浏览器环境)\n if (typeof window !== 'undefined' && cfg.iconCssUrl) {\n const selector = `link[rel=\"stylesheet\"][data-rcui-icon=\"true\"][href=\"${cfg.iconCssUrl}\"]`;\n const exists = document.head.querySelector(selector);\n if (!exists) {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = cfg.iconCssUrl;\n link.setAttribute('data-rcui-icon', 'true');\n document.head.appendChild(link);\n }\n }\n // 自动注册内置组件(可通过 autoRegister 关闭)\n doAutoRegister(app, cfg);\n return app;\n};\n\n// 默认导出为插件,支持 app.use(recycleUi, options)\nconst plugin: Plugin = { install };\nexport default plugin;\n\n// 也导出命名组件安装器与默认配置(defaultRecycleUIConfig 已在上方以常量形式导出)\n\n// 可选:工厂方法,便于创建带预设配置的插件\nexport function createRecycleUI(options?: RecycleUIOptions): Plugin {\n return {\n install(app: App) {\n install(app, options);\n },\n };\n}\n\n// 按需导出组件与其安装器(供文档与业务直接使用)\nexport { default as RcButton } from './components/button';\nexport { RcDescriptions, RcDescriptionsItem } from './components/descriptions';\nexport { install as installButton } from './components/button';\nexport { install as installDescriptions } from './components/descriptions';\nexport { default as RcCard } from './components/card';\nexport { install as installCard } from './components/card';\n// 兼容别名导出(文档示例中的 rcXxx)\nexport { RcDescriptions as rcDescriptions, RcDescriptionsItem as rcDescriptionsItem } from './components/descriptions';\n// Toast 服务导出\nexport { default as RcToast, showToast, hideToast } from './components/toast';\n// Icon 组件导出\nexport { default as RcIcon } from './components/icon/index';\nexport { install as installIcon } from './components/icon/index';\n// Message 服务(对标 antd 的 message)\nexport { default as message } from './components/message';\nexport { install as installMessage } from './components/message';\n// SearchArea 组件导出\nexport { default as RcSearchArea } from './components/search-area';\nexport { install as installSearchArea } from './components/search-area';\nexport type { FilterItem, FilterOption } from './components/search-area';\n// Calendar 组件导出\nexport { default as RcCalendar } from './components/calendar';\nexport { install as installCalendar } from './components/calendar';\n// Popup 组件导出\nexport { default as RcPopup } from './components/popup';\nexport { install as installPopup } from './components/popup';\n// Input 组件导出\nexport { default as RcInput } from './components/input';\nexport { install as installInput } from './components/input';\n// Dropdown 组件导出\nexport { default as RcDropdown, DropdownMenu as RcDropdownMenu, DropdownItem as RcDropdownItem } from './components/dropdown';\nexport { install as installDropdown } from './components/dropdown';\nexport type { DropdownPlacement } from './components/dropdown/types';\n"],"names":["props","__props","cfg","inject","RECYCLE_UI_SYMBOL","baseClass","computed","iconClassName","sizeCss","iconStyle","char","c","hex","num","onMounted","url","defaultRecycleUIConfig","selector","link","_createElementBlock","_hoisted_1","_toDisplayString","emit","__emit","onClick","ev","radius","v","_normalizeClass","_openBlock","_hoisted_2","_Fragment","$slots","_hoisted_3","_renderSlot","_ctx","_createBlock","RcIcon","_hoisted_4","Button","install","app","providedGapPx","providedColCount","providedLabelWidth","spanNum","n","max","safe","computedWidth","gapPx","k","totalGap","interGap","labelStyle","injected","w","_normalizeStyle","_createElementVNode","wrapEl","ref","gapStyle","colCount","itemWidth","singleWidth","watchEffect","base","provide","labelWidthCss","normalizedData","keyK","_a","keyV","_b","_c","it","_renderList","idx","rcDescriptionsItem","Descriptions","DescriptionsItem","RcDescriptions","RcDescriptionsItem","wrapperStyle","shadowByLevel","toCssSize","bodyPadding","bodyGap","level","_hoisted_5","Card","PascalName","visible","timer","clearTimer","close","__expose","onUnmounted","_Teleport","_createVNode","_Transition","_hoisted_6","host","unmount","showToast","options","opt","toastProps","createApp","Toast","hideToast","messages","reactive","uid","remove","id","x","add","type","content","duration","_TransitionGroup","m","container","hostExposed","ensureHost","vnode","createVNode","MessageHost","render","open","d","message","opts","Icon","popupRef","watch","val","lockBodyScroll","unlockBodyScroll","transitionName","popupStyle","scrollLocked","handleOverlayClick","handleClose","Popup","itemHeight","itemsPerRow","visibleRows","weekdays","parseDate","dateStr","date","formatDate","year","month","day","currentDate","isToday","today","isInRange","start","end","isDisabled","getMonthDays","firstDay","lastDay","firstDayWeek","daysInMonth","days","prevMonthLastDay","i","dayItem","formatted","remaining","monthDays","monthTitle","getDayClass","classes","isRangeComplete","selectedRangeCount","isYearDisabled","min","isMonthDisabled","minYear","minMonth","maxYear","maxMonth","showMonthPicker","pickerMode","tempYear","tempMonth","yearScrollRef","visibleYearStart","visibleYearEnd","dynamicMinYear","dynamicMaxYear","visibleYearList","years","startRow","endRow","handleYearScroll","scrollTop","newStart","newEnd","openMonthPicker","currentYear","nextTick","rowIndex","scrollToYear","prevMonth","nextMonth","selectYear","selectMonth","confirmMonth","onSelectDay","onClear","handleHeaderClear","hasValue","onConfirm","onCloseMonthPicker","onPickerModeChange","mode","selectCurrentYear","selectCurrentMonth","currentMonth","getDaysBetween","startDate","endDate","diffTime","getTodayStr","getWeekStart","diff","getWeekEnd","weekStart","weekEnd","getMonthStart","getMonthEnd","getThreeMonthsAgo","getYearStart","getYearEnd","allShortcuts","availableShortcuts","option","range","handleShortcutClick","$event","_unref","_hoisted_7","_hoisted_8","index","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","RcButton","_cache","_createTextVNode","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","_hoisted_19","_hoisted_20","_hoisted_21","_hoisted_22","_hoisted_23","inputRef","popupPanelRef","inputText","isRangeMode","maxRangeDays","mergedDisabledDate","rangeStart","rangeEnd","selectedDate","getDisplayEndDate","updateInputText","addOneDay","subtractOneDay","getActualEndDate","actualEnd","value","onShortcutSelect","handlePopupClose","handleInputFocus","handleInputBlur","parseInputText","handleInput","text","parts","s","endStr","CalendarPanelContent","RcPopup","Calendar","activeIndex","panelRef","maskRef","maskStyle","updateMaskPosition","panelTop","handleClickOutside","event","target","searchAreaEl","barEl","closeFilter","newVal","tempSelectedValues","tempInputValue","tempCalendarValue","tempSlotValues","confirmedValues","newValue","currentFilter","selectedCountText","count","getTempSelectedCount","getItemDisplayText","item","findOption","getResultLabel","values","labels","label","openFilter","currentValue","getOptionLabel","data","result","getOptionValue","childrenKey","optValue","children","found","flattenOptions","isSelected","key","tempValue","getDisplayOptions","getTreeGroups","getTreeGroupChildren","group","getSlotValue","updateSlotValue","selectSingle","toggleOption","tempArray","existingIndex","resetCurrentFilter","handleInputChange","handleCalendarChange","confirmFilter","getSelectedCount","slotValue","RcCalendar","_d","_e","_f","_g","_h","_i","_j","_hoisted_9","groupIdx","optIdx","_k","_hoisted_18","_l","_hoisted_24","_m","_n","_o","_q","_p","_hoisted_25","_r","_s","_hoisted_26","RcSearchArea","innerValue","focused","passwordVisible","isComposing","actualType","displayValue","wordCount","slots","useSlots","hasSuffix","textareaStyle","style","onInput","resizeTextarea","onFocus","onBlur","togglePassword","onKeydown","onMouseEnter","onMouseLeave","onCompositionStart","onCompositionUpdate","onCompositionEnd","handleWrapperClick","textarea","scrollHeight","minRows","maxRows","lineHeight","minHeight","maxHeight","focus","blur","select","clear","_resolveDynamicComponent","Input","menuRef","shouldShow","hasTeleport","menuStyle","$emit","dropdownRef","showTimer","hideTimer","handleItemClick","command","show","updatePosition","hide","isMenuHovered","toggle","handleMouseEnter","handleMouseLeave","handleMenuMouseEnter","handleMenuMouseLeave","handleClick","triggerEl","menuEl","triggerRect","menuRect","top","left","viewportWidth","viewportHeight","handleDocumentClick","handleResize","RcDropdownMenu","Dropdown","DropdownMenu","DropdownItem","doAutoRegister","installButton","installDescriptions","installCard","installToast","installIcon","installMessage","installSearchArea","installCalendar","installPopup","installInput","installDropdown","plugin","createRecycleUI"],"mappings":"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"}