@rft-rc/recycle-ui 0.0.2-rc.1 → 0.0.2-rc.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.
@@ -1 +1 @@
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/search-area/index.vue","../src/components/search-area/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: 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","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","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","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","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":"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"}
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/search-area/index.vue","../src/components/search-area/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: 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","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?.slot && $slots[currentFilter.key]\">\r\n <slot \r\n :name=\"currentFilter.key\" \r\n :value=\"getSlotValue(currentFilter)\"\r\n :update:value=\"(val: any) => updateSlotValue(currentFilter, val)\"\r\n />\r\n </template>\r\n\r\n <!-- 输入框模式 -->\r\n <template v-else-if=\"currentFilter?.type === 'input'\">\r\n <div class=\"rc-search-area__input-wrapper\">\r\n <input\r\n v-model=\"tempInputValue\"\r\n type=\"text\"\r\n class=\"rc-search-area__input\"\r\n :placeholder=\"currentFilter.placeholder || '请输入'\"\r\n @input=\"handleInputChange\"\r\n />\r\n </div>\r\n </template>\r\n\r\n <!-- 树形单选模式 -->\r\n <template v-else-if=\"currentFilter?.type === 'tree-single'\">\r\n <div class=\"rc-search-area__tree-container\">\r\n <div\r\n v-for=\"(group, groupIdx) in getTreeGroups(currentFilter)\"\r\n :key=\"groupIdx\"\r\n class=\"rc-search-area__tree-group\"\r\n >\r\n <div class=\"rc-search-area__tree-group-title\">\r\n {{ getOptionLabel(group, currentFilter || undefined) }}\r\n </div>\r\n <div class=\"rc-search-area__tree-group-options\">\r\n <div\r\n v-for=\"(option, optIdx) in getTreeGroupChildren(group, currentFilter)\"\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, currentFilter || undefined) }}</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 </div>\r\n </div>\r\n </template>\r\n\r\n <!-- 树形多选模式 -->\r\n <template v-else-if=\"currentFilter?.type === 'tree-multiple'\">\r\n <div class=\"rc-search-area__tree-container\">\r\n <div\r\n v-for=\"(group, groupIdx) in getTreeGroups(currentFilter)\"\r\n :key=\"groupIdx\"\r\n class=\"rc-search-area__tree-group\"\r\n >\r\n <div class=\"rc-search-area__tree-group-title\">\r\n {{ getOptionLabel(group, currentFilter || undefined) }}\r\n </div>\r\n <div class=\"rc-search-area__tree-group-options\">\r\n <div\r\n v-for=\"(option, optIdx) in getTreeGroupChildren(group, currentFilter)\"\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, currentFilter || undefined) }}</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 </div>\r\n </div>\r\n </template>\r\n\r\n <!-- 普通单选模式 -->\r\n <template v-else-if=\"currentFilter?.type === 'single'\">\r\n <div class=\"rc-search-area__options-grid\">\r\n <div\r\n v-for=\"(option, optIdx) in getDisplayOptions(currentFilter)\"\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, currentFilter || undefined) }}</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 getDisplayOptions(currentFilter)\"\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, currentFilter || undefined) }}</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?.type !== 'input' && !currentFilter?.slot && currentFilter?.options?.length === 0\" class=\"rc-search-area__empty\">\r\n <p>暂无选项</p>\r\n </div>\r\n </div>\r\n\r\n <div v-if=\"!props.autoConfirm && currentFilter?.type !== 'single' && currentFilter?.type !== 'tree-single'\" 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 多选,tree-single 树形单选,tree-multiple 树形多选,input 输入框(默认 multiple) */\r\n type?: 'single' | 'multiple' | 'tree-single' | 'tree-multiple' | 'input';\r\n /** 多选时的列数(默认 2) */\r\n column?: number;\r\n /** 格式化 value,默认返回原始数据。为 string 时,会作为 key 从原始数据中获取值,相当于 (d) => d[format]。为函数时,以函数返回结果作为 value */\r\n format?: ((data: FilterOption) => any) | string;\r\n /** 渲染选项内容。为 string 时,返回 d[string]。为 function 时,返回函数结果 */\r\n renderItem?: ((data: FilterOption) => any) | string;\r\n /** 选中后在结果中显示的内容,默认和 renderItem 相同 */\r\n renderResult?: ((data: FilterOption) => any) | string;\r\n /** 树形数据下,指定子数据的属性名,有值时可以展示树形结构 */\r\n childrenKey?: string;\r\n /** 输入框类型的占位符(仅 type='input' 时有效) */\r\n placeholder?: string;\r\n /** 是否使用插槽自定义渲染,为 true 时使用名为 key 的插槽 */\r\n slot?: boolean;\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 /** 是否自动确认:为 true 时,每次修改立即触发 change 事件并关闭弹窗,不显示确定和重置按钮 */\r\n autoConfirm?: boolean;\r\n}>(), {\r\n items: () => [],\r\n modelValue: () => ({}),\r\n showMask: true,\r\n autoConfirm: false,\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\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\n * 处理点击外部区域关闭面板\r\n * @param event 鼠标事件\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 tempInputValue = ref<string>('');\r\n\r\n/** 插槽的临时值 */\r\nconst tempSlotValues = 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\n * 获取筛选项的显示文本\r\n * @param item 筛选项配置\r\n * @returns 显示文本\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.slot) {\r\n // 插槽类型:显示标签,具体显示内容由插槽决定\r\n return item.label;\r\n } else if (item.type === 'input') {\r\n // 输入框类型\r\n if (value && String(value).trim()) {\r\n return `${item.label}: ${value}`;\r\n }\r\n } else if (item.type === 'single' || item.type === 'tree-single') {\r\n // 单选类型\r\n const option = findOption(item, value);\r\n if (option) {\r\n return `${item.label}: ${getResultLabel(option, item)}`;\r\n }\r\n } else {\r\n // 多选类型(包括 tree-multiple)\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 ? getResultLabel(opt, item) : 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\n * 打开筛选模态窗\r\n * @param index 筛选项索引\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.slot) {\r\n // 插槽类型:初始化插槽值\r\n tempSlotValues.value[item.key] = currentValue !== undefined ? (typeof currentValue === 'object' && currentValue !== null ? { ...currentValue } : currentValue) : undefined;\r\n } else if (item.type === 'input') {\r\n // 输入框类型\r\n tempInputValue.value = currentValue !== undefined && currentValue !== null ? String(currentValue) : '';\r\n } else if (item.type === 'single' || item.type === 'tree-single') {\r\n // 单选类型\r\n tempSelectedValues.value[item.key] = currentValue !== undefined ? currentValue : null;\r\n } else {\r\n // 多选类型(包括 tree-multiple)\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\n * 获取选项的显示文本\r\n * @param option 选项数据\r\n * @param item 筛选项配置(可选)\r\n * @returns 显示文本\r\n */\r\nconst getOptionLabel = (option: FilterOption | string, item?: FilterItem): string => {\r\n if (!item) {\r\n if (typeof option === 'string') return option;\r\n return option.label || String(option.value);\r\n }\r\n\r\n const data: any = typeof option === 'string' ? option : option;\r\n \r\n // 使用 renderItem\r\n if (item.renderItem) {\r\n if (typeof item.renderItem === 'string') {\r\n // 字符串模式:从数据中获取属性\r\n if (typeof data === 'object' && data !== null) {\r\n return String(data[item.renderItem] ?? '');\r\n }\r\n return String(data);\r\n } else {\r\n // 函数模式\r\n const result = item.renderItem(data);\r\n return result !== undefined && result !== null ? String(result) : '';\r\n }\r\n }\r\n \r\n // 默认行为\r\n if (typeof option === 'string') return option;\r\n return option.label || String(option.value);\r\n};\r\n\r\n/**\r\n * 获取选项的值\r\n * @param option 选项数据\r\n * @param item 筛选项配置(可选)\r\n * @returns 选项的值\r\n */\r\nconst getOptionValue = (option: FilterOption | string, item?: FilterItem): any => {\r\n if (!item) {\r\n if (typeof option === 'string') return option;\r\n return option.value !== undefined ? option.value : option;\r\n }\r\n\r\n const data: any = typeof option === 'string' ? option : option;\r\n \r\n // 使用 format\r\n if (item.format) {\r\n if (typeof item.format === 'string') {\r\n // 字符串模式:从数据中获取属性\r\n if (typeof data === 'object' && data !== null) {\r\n return data[item.format];\r\n }\r\n return data;\r\n } else {\r\n // 函数模式\r\n return item.format(data);\r\n }\r\n }\r\n \r\n // 默认行为\r\n if (typeof option === 'string') return option;\r\n return option.value !== undefined ? option.value : option;\r\n};\r\n\r\n/**\r\n * 获取结果中显示的文本\r\n * @param option 选项数据\r\n * @param item 筛选项配置\r\n * @returns 结果文本\r\n */\r\nconst getResultLabel = (option: FilterOption | string, item: FilterItem): string => {\r\n const data: any = typeof option === 'string' ? option : option;\r\n \r\n // 使用 renderResult,如果没有则使用 renderItem\r\n const render = item.renderResult || item.renderItem;\r\n \r\n if (render) {\r\n if (typeof render === 'string') {\r\n // 字符串模式:从数据中获取属性\r\n if (typeof data === 'object' && data !== null) {\r\n return String(data[render] ?? '');\r\n }\r\n return String(data);\r\n } else {\r\n // 函数模式\r\n const result = render(data);\r\n return result !== undefined && result !== null ? String(result) : '';\r\n }\r\n }\r\n \r\n // 默认行为\r\n return getOptionLabel(option, item);\r\n};\r\n\r\n/**\r\n * 查找选项(支持树形结构)\r\n * @param item 筛选项配置\r\n * @param value 要查找的值\r\n * @param options 选项列表(可选,用于递归查找)\r\n * @returns 找到的选项或 null\r\n */\r\nconst findOption = (item: FilterItem, value: any, options?: FilterOption[] | string[]): FilterOption | string | null => {\r\n const opts = options || item.options;\r\n const childrenKey = item.childrenKey || 'children';\r\n \r\n for (const opt of opts) {\r\n const optValue = getOptionValue(opt, item);\r\n if (optValue === value || String(optValue) === String(value)) {\r\n return opt;\r\n }\r\n \r\n // 如果是树形结构,递归查找子节点\r\n if (item.childrenKey && typeof opt === 'object' && opt !== null) {\r\n const children = (opt as any)[childrenKey];\r\n if (Array.isArray(children) && children.length > 0) {\r\n const found = findOption(item, value, children);\r\n if (found) return found;\r\n }\r\n }\r\n }\r\n \r\n return null;\r\n};\r\n\r\n/**\r\n * 扁平化选项列表(用于树形结构)\r\n * @param item 筛选项配置\r\n * @param options 选项列表(可选,用于递归)\r\n * @returns 扁平化后的选项列表\r\n */\r\nconst flattenOptions = (item: FilterItem, options?: FilterOption[] | string[]): (FilterOption | string)[] => {\r\n const opts = options || item.options;\r\n const childrenKey = item.childrenKey || 'children';\r\n const result: (FilterOption | string)[] = [];\r\n \r\n for (const opt of opts) {\r\n result.push(opt);\r\n \r\n // 如果有子节点,递归添加\r\n if (item.childrenKey && typeof opt === 'object' && opt !== null) {\r\n const children = (opt as any)[childrenKey];\r\n if (Array.isArray(children) && children.length > 0) {\r\n result.push(...flattenOptions(item, children));\r\n }\r\n }\r\n }\r\n \r\n return result;\r\n};\r\n\r\n/**\r\n * 判断选项是否被选中(临时状态)\r\n * @param option 选项数据\r\n * @returns 是否选中\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, currentFilter.value);\r\n \r\n if (currentFilter.value.type === 'single' || currentFilter.value.type === 'tree-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\n * 获取显示的选项列表(普通模式)\r\n * @param item 筛选项配置\r\n * @returns 选项列表\r\n */\r\nconst getDisplayOptions = (item: FilterItem | null): (FilterOption | string)[] => {\r\n if (!item) return [];\r\n // 如果有 childrenKey,扁平化选项;否则直接返回\r\n return item.childrenKey ? flattenOptions(item) : item.options;\r\n};\r\n\r\n/**\r\n * 获取树形结构的一级分组(仅返回一级选项,作为分组标题)\r\n * @param item 筛选项配置\r\n * @returns 一级选项列表\r\n */\r\nconst getTreeGroups = (item: FilterItem | null): (FilterOption | string)[] => {\r\n if (!item) return [];\r\n const childrenKey = item.childrenKey || 'children';\r\n // 只返回一级选项(有子节点的选项)\r\n return (item.options || []).filter((opt) => {\r\n if (typeof opt === 'string') return false;\r\n const children = (opt as any)[childrenKey];\r\n return Array.isArray(children) && children.length > 0;\r\n });\r\n};\r\n\r\n/**\r\n * 获取树形结构分组下的子选项\r\n * @param group 分组选项\r\n * @param item 筛选项配置\r\n * @returns 子选项列表\r\n */\r\nconst getTreeGroupChildren = (group: FilterOption | string, item: FilterItem | null): (FilterOption | string)[] => {\r\n if (!item || typeof group === 'string') return [];\r\n const childrenKey = item.childrenKey || 'children';\r\n const children = (group as any)[childrenKey];\r\n return Array.isArray(children) ? children : [];\r\n};\r\n\r\n/**\r\n * 获取插槽的当前值\r\n * @param item 筛选项配置\r\n * @returns 插槽的当前值\r\n */\r\nconst getSlotValue = (item: FilterItem | null): any => {\r\n if (!item) return undefined;\r\n return tempSlotValues.value[item.key] !== undefined ? tempSlotValues.value[item.key] : confirmedValues.value[item.key];\r\n};\r\n\r\n/**\r\n * 更新插槽的值\r\n * @param item 筛选项配置\r\n * @param value 新值\r\n */\r\nconst updateSlotValue = (item: FilterItem | null, value: any) => {\r\n if (!item) return;\r\n tempSlotValues.value[item.key] = value;\r\n \r\n // 如果启用了自动确认,立即确认并关闭\r\n if (props.autoConfirm) {\r\n const key = item.key;\r\n confirmedValues.value[key] = value;\r\n emit('update:modelValue', { ...confirmedValues.value });\r\n emit('change', { ...confirmedValues.value }, item);\r\n closeFilter();\r\n }\r\n};\r\n\r\n/**\r\n * 判断选项是否有子节点\r\n * @param option 选项数据\r\n * @param item 筛选项配置\r\n * @returns 是否有子节点\r\n */\r\nconst hasChildren = (option: FilterOption | string, item: FilterItem | null): boolean => {\r\n if (!item || !item.childrenKey) return false;\r\n if (typeof option === 'string') return false;\r\n const children = (option as any)[item.childrenKey];\r\n return Array.isArray(children) && children.length > 0;\r\n};\r\n\r\n/**\r\n * 单选(支持树形结构)- 点击后直接确认并关闭\r\n * @param option 选项数据\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, currentFilter.value);\r\n const oldValue = confirmedValues.value[key];\r\n \r\n // 如果已选中,则取消选中;否则选中\r\n let newValue: any;\r\n if (tempSelectedValues.value[key] === optValue) {\r\n newValue = undefined;\r\n } else {\r\n newValue = optValue;\r\n }\r\n \r\n // 直接更新已确认的值\r\n confirmedValues.value[key] = newValue;\r\n \r\n // 更新 v-model\r\n emit('update:modelValue', { ...confirmedValues.value });\r\n \r\n // 触发 change 事件\r\n emit('change', { ...confirmedValues.value }, currentFilter.value);\r\n \r\n // 直接关闭面板\r\n closeFilter();\r\n};\r\n\r\n/**\r\n * 多选切换\r\n * @param option 选项数据\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, currentFilter.value);\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 if (props.autoConfirm) {\r\n const newValue = tempArray.length > 0 ? tempArray : undefined;\r\n confirmedValues.value[key] = newValue;\r\n emit('update:modelValue', { ...confirmedValues.value });\r\n emit('change', { ...confirmedValues.value }, currentFilter.value);\r\n closeFilter();\r\n }\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.slot) {\r\n tempSlotValues.value[key] = undefined;\r\n } else if (currentFilter.value.type === 'input') {\r\n tempInputValue.value = '';\r\n } else if (currentFilter.value.type === 'single' || currentFilter.value.type === 'tree-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 handleInputChange = () => {\r\n // 如果启用了自动确认,立即确认并关闭\r\n if (props.autoConfirm && currentFilter.value) {\r\n const key = currentFilter.value.key;\r\n const newValue = tempInputValue.value.trim() || undefined;\r\n confirmedValues.value[key] = newValue;\r\n emit('update:modelValue', { ...confirmedValues.value });\r\n emit('change', { ...confirmedValues.value }, currentFilter.value);\r\n closeFilter();\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 oldValue = confirmedValues.value[key];\r\n \r\n // 更新已确认的值\r\n let newValue: any;\r\n if (currentFilter.value.slot) {\r\n // 插槽类型\r\n newValue = tempSlotValues.value[key];\r\n confirmedValues.value[key] = newValue;\r\n } else if (currentFilter.value.type === 'input') {\r\n // 输入框类型\r\n newValue = tempInputValue.value.trim() || undefined;\r\n confirmedValues.value[key] = newValue;\r\n } else if (currentFilter.value.type === 'single' || currentFilter.value.type === 'tree-single') {\r\n // 单选类型\r\n const tempValue = tempSelectedValues.value[key];\r\n newValue = tempValue !== null && tempValue !== undefined ? tempValue : undefined;\r\n confirmedValues.value[key] = newValue;\r\n } else {\r\n // 多选类型(包括 tree-multiple)\r\n const tempValue = tempSelectedValues.value[key];\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 // 触发 change 事件\r\n emit('change', { ...confirmedValues.value }, currentFilter.value);\r\n \r\n closeFilter();\r\n};\r\n\r\n/**\r\n * 获取已选中的数量(已确认的)\r\n * @param item 筛选项配置\r\n * @returns 选中数量\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.slot) {\r\n // 插槽类型:有值就返回1\r\n return 1;\r\n } else if (item.type === 'input') {\r\n return String(value).trim() ? 1 : 0;\r\n } else if (item.type === 'single' || item.type === 'tree-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\n * 获取临时选中的数量\r\n * @param item 筛选项配置\r\n * @returns 临时选中数量\r\n */\r\nconst getTempSelectedCount = (item: FilterItem): number => {\r\n if (item.slot) {\r\n // 插槽类型:有值就返回1\r\n const slotValue = tempSlotValues.value[item.key];\r\n return slotValue !== undefined && slotValue !== null && slotValue !== '' ? 1 : 0;\r\n } else if (item.type === 'input') {\r\n return tempInputValue.value.trim() ? 1 : 0;\r\n }\r\n \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' || item.type === 'tree-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 tempSlotValues.value = {};\r\n emit('update:modelValue', {});\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: #F9F9F9;\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: #F9F9F9;\r\n border-color: transparent;\r\n color: #323233;\r\n\r\n &::after {\r\n content: '';\r\n border: 1px solid #F9F9F9;\r\n position: absolute;\r\n bottom: -8px;\r\n width: 100%;\r\n height: 8px;\r\n background: #F9F9F9;\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: #F9F9F9;\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 &__tree-container {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n }\r\n\r\n &__tree-group {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 8px;\r\n }\r\n\r\n &__tree-group-title {\r\n padding: 8px 12px;\r\n font-size: 14px;\r\n font-weight: 500;\r\n color: #323233;\r\n background: #f7f8fa;\r\n border-radius: 6px;\r\n user-select: none;\r\n cursor: default;\r\n }\r\n\r\n &__tree-group-options {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 12px;\r\n padding-left: 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 &__input-wrapper {\r\n padding: 8px;\r\n }\r\n\r\n &__input {\r\n width: 100%;\r\n height: 40px;\r\n padding: 0 12px;\r\n font-size: 14px;\r\n color: #323233;\r\n background: #fff;\r\n border: 1px solid #dcdee0;\r\n border-radius: 8px;\r\n outline: none;\r\n box-sizing: border-box;\r\n transition: border-color 0.2s;\r\n\r\n &:focus {\r\n border-color: #1677ff;\r\n }\r\n\r\n &::placeholder {\r\n color: #969799;\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","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","activeIndex","panelRef","maskRef","maskStyle","updateMaskPosition","nextTick","panelTop","handleClickOutside","event","target","searchAreaEl","barEl","closeFilter","watch","newVal","tempSelectedValues","tempInputValue","tempSlotValues","confirmedValues","newValue","currentFilter","selectedCountText","count","getTempSelectedCount","getItemDisplayText","item","value","option","findOption","getResultLabel","values","labels","val","label","openFilter","index","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","confirmFilter","getSelectedCount","slotValue","$event","_unref","_hoisted_8","groupIdx","_hoisted_9","_hoisted_10","optIdx","_hoisted_12","_d","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_17","_e","_hoisted_18","_hoisted_20","_hoisted_21","_hoisted_23","_f","_g","_i","_h","_hoisted_24","_cache","_j","_k","_hoisted_25","RcButton","_createTextVNode","RcSearchArea","doAutoRegister","installButton","installDescriptions","installCard","installToast","installIcon","installMessage","installSearchArea","plugin","createRecycleUI"],"mappings":"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"}