vue3-smart-table 1.0.0 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"vue3-smart-table.umd.js","sources":["../src/components/SmartTable/renderer.ts","../src/components/SmartTable/utils/path.ts","../src/components/SmartTable/renderers/input.vue","../src/components/SmartTable/renderers/inputNumber.vue","../src/components/SmartTable/renderers/select.vue","../src/components/SmartTable/renderers/index.ts","../src/components/SmartTable/hooks/useOperationColumn.ts","../src/components/SmartTable/column/index.vue","../src/components/SmartTable/hooks/useTableColumns.ts","../src/components/SmartTable/index.vue","../src/components/SmartTable/config.ts","../src/types/enhanced.ts"],"sourcesContent":["/**\r\n * SmartTable 内部渲染器管理系统\r\n * 移动到组件内部,保证组件的自包含性\r\n */\r\nimport { defineComponent, h, Component } from 'vue'\r\nimport type { Renderer } from './types'\r\n\r\n/**\r\n * 渲染器注册表接口\r\n */\r\nexport interface RendererRegistry {\r\n register(name: string, renderer: Renderer): void\r\n registerMultiple(renderers: Record<string, Renderer>): void\r\n get(name: string): Renderer | undefined\r\n has(name: string): boolean\r\n unregister(name: string): boolean\r\n clear(): void\r\n names(): string[]\r\n}\r\n\r\n/**\r\n * 渲染器管理器类\r\n */\r\nclass RendererManager implements RendererRegistry {\r\n private renderers: Map<string, Renderer> = new Map()\r\n\r\n register(name: string, renderer: Renderer): void {\r\n if (this.renderers.has(name)) {\r\n // 批量注册时不警告,只在单独注册时警告\r\n if (process.env.NODE_ENV === 'development') {\r\n console.debug(`[SmartTable] Renderer \"${name}\" already registered, skipping.`)\r\n }\r\n }\r\n this.renderers.set(name, renderer)\r\n }\r\n\r\n registerMultiple(renderers: Record<string, Renderer>): void {\r\n Object.entries(renderers).forEach(([name, renderer]) => {\r\n if (!this.renderers.has(name)) {\r\n this.renderers.set(name, renderer)\r\n }\r\n })\r\n }\r\n\r\n get(name: string): Renderer | undefined {\r\n return this.renderers.get(name)\r\n }\r\n\r\n has(name: string): boolean {\r\n return this.renderers.has(name)\r\n }\r\n\r\n unregister(name: string): boolean {\r\n return this.renderers.delete(name)\r\n }\r\n\r\n clear(): void {\r\n this.renderers.clear()\r\n }\r\n\r\n names(): string[] {\r\n return Array.from(this.renderers.keys())\r\n }\r\n}\r\n\r\n/**\r\n * 全局渲染器管理器单例\r\n */\r\nlet globalRendererManager: RendererManager | null = null\r\n\r\n/**\r\n * 获取渲染器管理器\r\n */\r\nexport function getRendererManager(): RendererManager {\r\n if (!globalRendererManager) {\r\n globalRendererManager = new RendererManager()\r\n }\r\n return globalRendererManager\r\n}\r\n\r\n/**\r\n * 包装 SFC 组件为渲染器\r\n */\r\nexport function wrapSFCComponent(comp: Component): Renderer {\r\n return defineComponent({\r\n props: ['row', 'col', 'onCellChange', 'onCellBlur', 'onCellEnter', 'onClick'],\r\n setup(props) {\r\n return () => h(comp, props)\r\n }\r\n })\r\n}\r\n\r\n/**\r\n * 创建函数式渲染器\r\n */\r\nexport function createFunctionalRenderer(\r\n render: (props: {\r\n row: any\r\n col: any\r\n onCellChange?: (row: any, col: any) => void\r\n onCellBlur?: (row: any, col: any) => void\r\n onCellEnter?: (row: any, col: any) => void\r\n onClick?: (row: any, col: any) => void\r\n }) => any\r\n): Renderer {\r\n return defineComponent({\r\n props: ['row', 'col', 'onCellChange', 'onCellBlur', 'onCellEnter', 'onClick'],\r\n setup(props) {\r\n return () => render(props)\r\n }\r\n })\r\n}\r\n\r\n/**\r\n * 验证渲染器配置\r\n * 在开发环境下验证 renderProps 的正确性\r\n */\r\nexport function validateRendererProps(\r\n rendererName: string,\r\n renderProps: Record<string, any> | undefined\r\n): void {\r\n if (process.env.NODE_ENV !== 'production' && renderProps) {\r\n switch (rendererName) {\r\n case 'dict':\r\n if (!renderProps.options || !Array.isArray(renderProps.options)) {\r\n console.warn(\r\n `[SmartTable] 'dict' renderer requires 'options' array, received:`,\r\n renderProps.options\r\n )\r\n }\r\n break\r\n\r\n case 'select':\r\n if (!renderProps.options || !Array.isArray(renderProps.options)) {\r\n console.warn(\r\n `[SmartTable] 'select' renderer requires 'options' array, received:`,\r\n renderProps.options\r\n )\r\n } else if (renderProps.options.length === 0) {\r\n console.warn(`[SmartTable] 'select' renderer 'options' array is empty`)\r\n }\r\n break\r\n\r\n case 'map':\r\n if (!renderProps.options || typeof renderProps.options !== 'object') {\r\n console.warn(\r\n `[SmartTable] 'map' renderer requires 'options' object, received:`,\r\n renderProps.options\r\n )\r\n }\r\n break\r\n\r\n case 'link':\r\n if (!renderProps.href || typeof renderProps.href !== 'string') {\r\n console.warn(\r\n `[SmartTable] 'link' renderer requires 'href' string, received:`,\r\n renderProps.href\r\n )\r\n }\r\n break\r\n\r\n case 'input-number':\r\n if (renderProps.min !== undefined && renderProps.max !== undefined) {\r\n if (renderProps.min > renderProps.max) {\r\n console.warn(\r\n `[SmartTable] 'input-number' renderer: min (${renderProps.min}) should not be greater than max (${renderProps.max})`\r\n )\r\n }\r\n }\r\n break\r\n }\r\n }\r\n}\r\n","/**\r\n * 安全获取对象深层属性\r\n * 支持 a.b.c / a.0.b\r\n */\r\nexport function getValueByPath(obj: any, path?: string) {\r\n if (!obj || !path) return undefined\r\n return path.split('.').reduce((acc, key) => acc?.[key], obj)\r\n }\r\n \r\n /**\r\n * 安全设置对象深层属性(用于可编辑表格)\r\n */\r\n export function setValueByPath(\r\n obj: any,\r\n path: string,\r\n value: any\r\n ) {\r\n if (!obj || !path) return\r\n const keys = path.split('.')\r\n const lastKey = keys.pop()!\r\n \r\n const target = keys.reduce((acc, key) => {\r\n if (!acc[key]) acc[key] = {}\r\n return acc[key]\r\n }, obj)\r\n \r\n target[lastKey] = value\r\n }\r\n ","<template>\n <el-input\n v-model=\"value\"\n v-bind=\"{ placeholder: '', size: 'small', clearable: true, ...col.renderProps }\"\n @blur=\"onBlur\"\n @keyup.enter=\"onEnter\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport type { ColumnConfig } from '../types'\nimport { getValueByPath, setValueByPath } from '../utils/path'\n\ninterface Props {\n readonly row: any\n readonly col: ColumnConfig\n onCellBlur?: (row: any, col: ColumnConfig) => void\n onCellEnter?: (row: any, col: ColumnConfig) => void\n}\n\nconst props = defineProps<Props>()\nconst value = ref(getValueByPath(props.row, props.col.key))\n\nwatch(value, (v) => {\n setValueByPath(props.row, props.col.key, v)\n})\n\nconst onBlur = () => props.onCellBlur?.(props.row, props.col)\nconst onEnter = () => props.onCellEnter?.(props.row, props.col)\n</script>\n","<template>\n <el-input-number\n v-model=\"value\"\n v-bind=\"{ min: 0, max: 99999, controls: false, size: 'small', ...col.renderProps }\"\n @blur=\"onBlur\"\n @keyup.enter=\"onEnter\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport type { ColumnConfig } from '../types'\nimport { getValueByPath, setValueByPath } from '../utils/path'\n\ninterface Props {\n readonly row: any\n readonly col: ColumnConfig\n onCellChange?: (row: any, col: ColumnConfig) => void\n onCellBlur?: (row: any, col: ColumnConfig) => void\n onCellEnter?: (row: any, col: ColumnConfig) => void\n}\n\nconst props = defineProps<Props>()\nconst value = ref(getValueByPath(props.row, props.col.key))\n\nwatch(value, (v) => {\n setValueByPath(props.row, props.col.key, v)\n props.onCellChange?.(props.row, props.col)\n})\n\nconst onBlur = () => props.onCellBlur?.(props.row, props.col)\nconst onEnter = () => props.onCellEnter?.(props.row, props.col)\n</script>\n","<template>\n <el-select\n v-model=\"value\"\n v-bind=\"{ placeholder: '请选择', size: 'small', clearable: true, ...col.renderProps }\"\n @change=\"onChange\"\n @blur=\"onBlur\"\n @keyup.enter=\"onEnter\"\n >\n <el-option\n v-for=\"opt in col.renderProps?.options || []\"\n :key=\"opt.value\"\n :label=\"opt.label\"\n :value=\"opt.value\"\n />\n </el-select>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport type { ColumnConfig } from '../types'\nimport { getValueByPath, setValueByPath } from '../utils/path'\n\ninterface Props {\n readonly row: any\n readonly col: ColumnConfig\n onCellChange?: (row: any, col: ColumnConfig) => void\n onCellBlur?: (row: any, col: ColumnConfig) => void\n onCellEnter?: (row: any, col: ColumnConfig) => void\n}\n\nconst props = defineProps<Props>()\nconst value = ref(getValueByPath(props.row, props.col.key))\n\nwatch(value, (v) => {\n setValueByPath(props.row, props.col.key, v)\n})\n\nconst onChange = () => props.onCellChange?.(props.row, props.col)\nconst onBlur = () => props.onCellBlur?.(props.row, props.col)\nconst onEnter = () => props.onCellEnter?.(props.row, props.col)\n</script>\n","/**\r\n * 内置渲染器集合\r\n * 可以按需引入或批量注册\r\n */\r\nimport { h } from 'vue'\r\nimport { ElButton, ElTag, ElImage, ElMessage } from 'element-plus'\r\nimport { DocumentCopy, CopyDocument } from '@element-plus/icons-vue'\r\nimport type { ColumnConfig } from '../types'\r\nimport { getValueByPath } from '../utils/path'\r\nimport { wrapSFCComponent, createFunctionalRenderer } from '../renderer'\r\nimport EditableInput from './input.vue'\r\nimport EditableNumber from './inputNumber.vue'\r\nimport EditableSelect from './select.vue'\r\n\r\n/**\r\n * 包装 SFC 组件\r\n */\r\nconst input = wrapSFCComponent(EditableInput)\r\nconst inputNumber = wrapSFCComponent(EditableNumber)\r\nconst select = wrapSFCComponent(EditableSelect)\r\n\r\n/**\r\n * button 渲染器\r\n */\r\nconst button = createFunctionalRenderer((props) => {\r\n const rp = props.col.renderProps || {}\r\n const val = getValueByPath(props.row, props.col.key)\r\n return h(ElButton as any, {\r\n type: rp.type || 'primary',\r\n ...rp,\r\n onClick: () => props.onClick?.(props.row, props.col)\r\n }, () => rp.label || val)\r\n})\r\n\r\n/**\r\n * link 渲染器\r\n */\r\nconst link = createFunctionalRenderer((props) => {\r\n const rp = props.col.renderProps || {}\r\n const val = getValueByPath(props.row, props.col.key)\r\n return h('a', {\r\n href: rp.href || '#',\r\n target: rp.blank ? '_blank' : '_self',\r\n style: rp.style || 'color:#409EFF;cursor:pointer;',\r\n }, rp.label || val)\r\n})\r\n\r\n/**\r\n * html 渲染器\r\n */\r\nconst html = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key)\r\n return h('div', {\r\n class: 'line-clamp-2',\r\n innerHTML: val ?? '',\r\n ...(props.col?.renderProps || {})\r\n })\r\n})\r\n\r\n/**\r\n * copy 渲染器\r\n */\r\nconst copy = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const rp = props.col.renderProps ?? {}\r\n const butStyle = {\r\n 'position': 'absolute',\r\n 'right': '-5px',\r\n 'top': '50%',\r\n 'transform': 'translateY(-50%)',\r\n 'cursor': 'pointer',\r\n 'display': 'none',\r\n 'font-size': '12px',\r\n 'color': rp.iconColor || '#409EFF',\r\n 'user-select': 'none'\r\n }\r\n return h('div', {\r\n class: 'st_copy_wrapper',\r\n style: 'width: 100%; position: relative; display: inline-block;'\r\n },\r\n [\r\n h('span', {\r\n class: 'st_copy_text line-clamp-1',\r\n style: 'padding-right: 10px; display: block;',\r\n }, val),\r\n val && h('span', {\r\n class: 'st_copy_btn',\r\n style: butStyle,\r\n title: rp.copyTitle || '复制',\r\n onClick: () => {\r\n if (!val) return\r\n try {\r\n if (navigator.clipboard && navigator.clipboard.writeText) {\r\n navigator.clipboard.writeText(val).then(() => {\r\n ElMessage.success(rp.successText ?? '复制成功')\r\n }).catch(() => {\r\n ElMessage.error(rp.errorText ?? '复制失败')\r\n })\r\n } else {\r\n const textarea = document.createElement('textarea')\r\n textarea.value = val\r\n textarea.style.position = 'fixed'\r\n textarea.style.opacity = '0'\r\n document.body.appendChild(textarea)\r\n textarea.select()\r\n const successful = document.execCommand('copy')\r\n document.body.removeChild(textarea)\r\n\r\n if (successful) {\r\n ElMessage.success(rp.successText ?? '复制成功')\r\n } else {\r\n ElMessage.error(rp.errorText ?? '复制失败')\r\n }\r\n }\r\n } catch (err) {\r\n ElMessage.error(rp.errorText ?? '复制失败')\r\n }\r\n }\r\n }, [h(DocumentCopy, {\r\n style: 'width: 1em; height: 1em;'\r\n })])\r\n ].filter(Boolean)\r\n )\r\n})\r\n\r\n/**\r\n * img 渲染器\r\n */\r\nconst img = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const rp = props.col?.renderProps || {}\r\n\r\n const getImageList = () => {\r\n if (!val) return []\r\n if (Array.isArray(val)) {\r\n return val.filter(item => item && typeof item === 'string')\r\n }\r\n return [val]\r\n }\r\n\r\n const imageList = getImageList()\r\n\r\n if (imageList.length === 0) {\r\n return rp.placeholder || ''\r\n }\r\n\r\n const defaultStyle = {\r\n width: rp.width || '80px',\r\n height: rp.height || '80px',\r\n marginRight: imageList.length > 1 ? '4px' : '0',\r\n ...(rp.style || {})\r\n }\r\n\r\n if (imageList.length === 1) {\r\n return h(ElImage, {\r\n src: imageList[0],\r\n previewSrcList: rp.previewSrcList || imageList,\r\n fit: rp.fit || 'contain',\r\n style: defaultStyle,\r\n ...rp\r\n })\r\n }\r\n\r\n return h('div',\r\n {\r\n class: 'st_img_wrapper',\r\n style: 'display: flex; align-items: center; position: relative'\r\n },\r\n [\r\n h(ElImage, {\r\n src: imageList[0],\r\n previewSrcList: rp.previewSrcList || imageList,\r\n fit: rp.fit || 'contain',\r\n style: defaultStyle,\r\n ...rp\r\n }),\r\n imageList.length > 1 && h('span', {\r\n class: 'st_img_total',\r\n style: `position: absolute; top: 0; right: 0; `,\r\n title: `${imageList.length}`\r\n }, [h(CopyDocument, { style: `width: 1em; height: 1em; ` })])\r\n ]\r\n )\r\n})\r\n\r\n/**\r\n * dict 渲染器\r\n */\r\nconst dict = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const rp = props.col.renderProps || {}\r\n const options = rp.options ?? []\r\n const showValue = rp.showValue ?? false\r\n\r\n if (val === null || val === undefined || val === '') return ''\r\n\r\n const values = Array.isArray(val) ? val.map(String) : [String(val)]\r\n const matchedOptions = options.filter((opt: any) => values.includes(String(opt.value)))\r\n const unmatched = values.filter(v => !options.some((opt: any) => String(opt.value) === v))\r\n\r\n const children = matchedOptions.map((item: any, _index: number) => {\r\n return h(\r\n ElTag,\r\n { key: item.value, type: item.listClass, class: item.cssClass, disableTransitions: true },\r\n { default: () => item.label + ' ' }\r\n )\r\n })\r\n\r\n if (showValue && unmatched.length > 0) {\r\n children.push(h('span', {}, unmatched.join(' ')))\r\n }\r\n\r\n return h('div', {}, children)\r\n})\r\n\r\n/**\r\n * map 渲染器\r\n */\r\nconst map = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const options = (props.col.renderProps?.options ?? {}) as Record<string, any>\r\n return val != null ? options[val] ?? '' : ''\r\n})\r\n\r\n/**\r\n * formatter 渲染器\r\n */\r\nexport function isDataColumn(\r\n col: ColumnConfig\r\n): col is any {\r\n return typeof (col as any).formatter === 'function'\r\n}\r\n\r\nconst formatter = createFunctionalRenderer((props) => {\r\n const { col, row } = props\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n if (isDataColumn(col)) {\r\n return col.formatter?.(val, row)\r\n }\r\n return val ?? ''\r\n})\r\n\r\n/**\r\n * icon 渲染器\r\n */\r\nconst icon = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const rp = props.col.renderProps || {}\r\n if (!val) return ''\r\n // 判断网络图片\r\n if (/^https?:\\/\\//.test(val)) {\r\n return h(ElImage, {\r\n src: val,\r\n previewSrcList: [val],\r\n fit: 'contain',\r\n style: 'width:40px;height:40px',\r\n ...rp\r\n })\r\n }\r\n // 判断 svg 源码\r\n if (/^\\s*<svg[\\s\\S]*<\\/svg>\\s*$/.test(val)) {\r\n return h('div', {\r\n innerHTML: val,\r\n style: `width:40px;height:40px;display:inline-block;${rp.style || ''}`,\r\n ...rp\r\n })\r\n }\r\n // 默认当作 iconfont\r\n return h('i', {\r\n class: val,\r\n style: `font-size:20px;${rp.style || ''}`,\r\n ...rp\r\n })\r\n})\r\n\r\n/**\r\n * 所有内置渲染器\r\n */\r\nexport const builtInRenderers = {\r\n input,\r\n 'input-number': inputNumber,\r\n select,\r\n button,\r\n link,\r\n html,\r\n copy,\r\n img,\r\n dict,\r\n map,\r\n formatter,\r\n icon,\r\n}\r\n\r\n/**\r\n * 安装所有内置渲染器\r\n */\r\nexport function registerBuiltInRenderers(registry: { registerMultiple: (renderers: Record<string, any>) => void }) {\r\n registry.registerMultiple(builtInRenderers)\r\n}\r\n\r\n/**\r\n * 创建默认渲染器集合(兼容旧 API)\r\n * @deprecated 建议使用插件化架构\r\n */\r\nexport function createRenderer() {\r\n return builtInRenderers\r\n}\r\n","import { computed } from 'vue'\r\n\r\nimport { ButtonConfig } from \"../types\"\r\n/**\r\n * useOperationColumn\r\n *\r\n * 操作列专用逻辑 Hook,负责:\r\n * 1. 根据权限判断操作列是否需要显示\r\n * 2. 计算操作列宽度(支持按钮自定义宽度)\r\n * 3. 支持行级 visible 配置\r\n * @param buttonConfigs 操作列按钮配置\r\n * @param maxbtn 操作列最多显示按钮数量(超过的不参与宽度计算)\r\n * @param userPermissions 当前用户权限列表\r\n */\r\nexport function useOperationColumn(\r\n buttonConfigs: ButtonConfig[],\r\n maxbtn = 10,\r\n userPermissions: string[] = []\r\n) {\r\n /** 默认按钮宽度 */\r\n const defaultWidth = 60\r\n\r\n /** 超级权限标识 */\r\n const all_permission = '*:*:*'\r\n\r\n /** --------------------------\r\n * 权限判断\r\n * -------------------------- */\r\n\r\n /**\r\n * 判断是否具备按钮权限\r\n *\r\n * 规则:\r\n * - permission 未配置 ⇒ 永远有权限\r\n * - permission 为 string | string[] ⇒ 与用户权限匹配\r\n */\r\n const hasPermi = (value?: string | string[]) => {\r\n if (!value) return true\r\n\r\n const permArray = Array.isArray(value) ? value : [value]\r\n return userPermissions.some(\r\n p => p === all_permission || permArray.includes(p)\r\n )\r\n }\r\n\r\n /** --------------------------\r\n * 仅基于权限(不考虑行级 visible)\r\n * 适用于:表格未加载数据时的判断\r\n * -------------------------- */\r\n\r\n /**\r\n * 是否至少存在一个有权限的按钮\r\n * 用于判断操作列是否需要渲染\r\n */\r\n const hasAnyButton = computed(() => {\r\n return buttonConfigs.some(btn => hasPermi(btn.permission))\r\n })\r\n\r\n /**\r\n * 操作列宽度(仅基于权限)\r\n * 用于无行数据时的兜底宽度计算\r\n */\r\n const optWidth = computed(() => {\r\n const permittedBtns = buttonConfigs\r\n .filter(btn => hasPermi(btn.permission))\r\n .slice(0, maxbtn)\r\n\r\n return permittedBtns.reduce(\r\n (sum, btn) => sum + (btn.width ?? defaultWidth),\r\n 0\r\n )\r\n })\r\n\r\n /** --------------------------\r\n * 权限 + 行级 visible\r\n * -------------------------- */\r\n\r\n /**\r\n * 判断某个按钮在某一行是否可见\r\n */\r\n const isButtonVisible = (btn: ButtonConfig, row: any) => {\r\n return (\r\n hasPermi(btn.permission) &&\r\n (btn.visible ? btn.visible(row) : true)\r\n )\r\n }\r\n\r\n /**\r\n * 单行操作列宽度\r\n */\r\n const optRowWidth = (row: any) => {\r\n const visibleBtns = buttonConfigs\r\n .filter(btn => isButtonVisible(btn, row))\r\n .slice(0, maxbtn)\r\n\r\n return visibleBtns.reduce(\r\n (sum, btn) => sum + (btn.width ?? defaultWidth),\r\n 0\r\n )\r\n }\r\n\r\n /**\r\n * 遍历所有行,获取最大操作列宽度\r\n */\r\n const getMaxOptWidth = (rows: any[]) => {\r\n if (!rows?.length) return optWidth.value\r\n return rows.reduce(\r\n (max, row) => Math.max(max, optRowWidth(row)),\r\n 0\r\n )\r\n }\r\n\r\n /**\r\n * 判断是否至少有一行存在可见按钮\r\n */\r\n const hasAnyVisibleButton = (rows: any[]) => {\r\n if (!rows?.length) return false\r\n return rows.some(row =>\r\n buttonConfigs.some(btn => isButtonVisible(btn, row))\r\n )\r\n }\r\n\r\n const getVisibleButtons = (row: any) => {\r\n return buttonConfigs\r\n .filter(btn => isButtonVisible(btn, row))\r\n .slice(0, maxbtn)\r\n }\r\n\r\n return {\r\n hasAnyButton,\r\n optWidth,\r\n hasAnyVisibleButton,\r\n getMaxOptWidth,\r\n getVisibleButtons\r\n }\r\n}\r\n","<template>\r\n <!-- ========== selection 列 ========== -->\r\n <el-table-column\r\n v-if=\"col.type === 'selection'\"\r\n type=\"selection\"\r\n v-bind=\"col.columnProps\"\r\n />\r\n\r\n <!-- ========== index 列 ========== -->\r\n <el-table-column\r\n v-else-if=\"col.type === 'index'\"\r\n type=\"index\"\r\n :label=\"col.label || '#'\"\r\n align=\"center\"\r\n v-bind=\"col.columnProps\"\r\n >\r\n <template #default=\"{ $index }\">\r\n {{ computeIndex($index) }}\r\n </template>\r\n </el-table-column>\r\n\r\n <!-- ========== operation 列 ========== -->\r\n <el-table-column\r\n v-else-if=\"col.type === 'operation' && showOperationColumn\"\r\n :label=\"col.label || '操作'\"\r\n align=\"center\"\r\n v-bind=\"{\r\n ...col.columnProps,\r\n width: operationWidth\r\n }\"\r\n >\r\n <template #default=\"{ row }\">\r\n <el-button\r\n v-for=\"btn in getVisibleButtons(row)\"\r\n :key=\"btn.label\"\r\n :type=\"btn.type || 'primary'\"\r\n link\r\n @click=\"btn.action(row)\"\r\n >\r\n {{ btn.label }}\r\n </el-button>\r\n </template>\r\n </el-table-column>\r\n\r\n <!-- ========== 普通列 / renderer / editable ========== -->\r\n <el-table-column\r\n v-else-if=\"isDataOrOperationColumn(col)\"\r\n :label=\"col.label\"\r\n align=\"center\"\r\n v-bind=\"col.columnProps || {}\"\r\n >\r\n \r\n <template #default=\"scope\">\r\n <!-- 父组件插槽优先 -->\r\n <template v-if=\"col.render === 'slot' && $slots[col?.slot || col.key]\">\r\n <slot :name=\"col?.slot || col.key\" v-bind=\"scope\" />\r\n </template>\r\n\r\n <!-- renderer -->\r\n <component\r\n v-else-if=\"col.render && renderer[col.render]\"\r\n :is=\"renderer[col.render]\"\r\n :row=\"scope.row\"\r\n :col=\"col\"\r\n :onCellChange=\"handleCellChange\"\r\n :onCellBlur=\"handleCellBlur\"\r\n :onCellEnter=\"handleCellEnter\"\r\n :onClick=\"handleCellClick\"\r\n />\r\n <!-- 默认文本 -->\r\n <span v-else\r\n :style=\"col.renderProps?.style || ''\"\r\n :class=\"col.renderProps?.class || ''\"\r\n :title=\"getValueByPath(scope.row, col.key)\">\r\n {{ getValueByPath(scope.row, col.key) }}\r\n </span>\r\n </template>\r\n </el-table-column>\r\n \r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, toRefs } from 'vue'\r\nimport type { PropType } from 'vue'\r\nimport type { ColumnConfig } from '../types'\r\nimport { getRendererManager } from '../renderer'\r\nimport { registerBuiltInRenderers } from '../renderers'\r\nimport { useOperationColumn } from '../hooks/useOperationColumn'\r\nimport { getValueByPath } from '../utils/path'\r\n\r\nconst props = defineProps({\r\n col: { type: Object as PropType<ColumnConfig>, required: true },\r\n permissions: { type: Array as PropType<string[]>, default: () => [] },\r\n pagination: { type: Object, default: () => ({}) },\r\n})\r\n\r\nconst emit = defineEmits(['cellBlur', 'cellEnter', 'cellChange', 'cellClick'])\r\n\r\nconst computeIndex = (index: number) => {\r\n const page = props.pagination?.page\r\n const size = props.pagination?.size\r\n return page && size ? (page - 1) * size + index + 1 : index + 1\r\n}\r\n\r\n/** 解构 col 响应式引用 */\r\nconst { col } = toRefs(props)\r\n\r\n/** ========== 事件统一上抛 ========== */\r\nconst handleCellChange = (row: any, key: string) => emit('cellChange', row, key)\r\nconst handleCellBlur = (row: any, key: string) => emit('cellBlur', row, key)\r\nconst handleCellEnter = (row: any, key: string) => emit('cellEnter', row, key)\r\nconst handleCellClick = (row: any, col: any) => emit('cellClick', row, col)\r\n\r\n/** ========== renderer 注册 ========== */\r\n// 注册内置渲染器(重复调用会自动跳过已存在的)\r\nregisterBuiltInRenderers(getRendererManager())\r\n\r\n// 获取所有渲染器(内置 + 自定义)\r\nconst renderer = computed(() => {\r\n const manager = getRendererManager()\r\n const allRenderers: Record<string, any> = {}\r\n\r\n // 合并内置渲染器和自定义渲染器\r\n manager.names().forEach((name: string) => {\r\n const r = manager.get(name)\r\n if (r) allRenderers[name] = r\r\n })\r\n\r\n return allRenderers\r\n})\r\n\r\n/** ========== operation 列逻辑 ========== */\r\nconst {\r\n hasAnyButton,\r\n hasAnyVisibleButton,\r\n optWidth,\r\n getMaxOptWidth,\r\n getVisibleButtons\r\n} = useOperationColumn(\r\n col.value.buttons || [],\r\n col.value.maxbtn ?? 10,\r\n props.permissions || []\r\n)\r\n\r\n/** 是否显示操作列 */\r\nconst showOperationColumn = computed(() => {\r\n const buttons = col.value.buttons || []\r\n if (!buttons.length) return false // 没有配置按钮直接隐藏\r\n const rows = col.value.__rows || []\r\n // 无行数据时,至少有一个按钮有权限就显示\r\n if (!rows.length) return hasAnyButton.value\r\n // 有行数据时,至少一行有可见按钮才显示\r\n return hasAnyVisibleButton(col.value.__rows || [])\r\n})\r\n\r\n/** 操作列宽度 */\r\nconst operationWidth = computed(() => {\r\n // 无行数据,用静态宽度\r\n if (!col.value.__rows) return optWidth.value\r\n // 有行数据,取最大宽度\r\n return getMaxOptWidth(col.value.__rows)\r\n})\r\n\r\nfunction isDataOrOperationColumn(c: ColumnConfig) {\r\n if (c.type === 'selection' || c.type === 'index') return false\r\n if (c.type === 'operation' && !showOperationColumn.value) return false\r\n if (c.visible === false) return false\r\n return true\r\n}\r\n</script>\r\n<style>\r\n .st_copy_wrapper:hover .st_copy_btn {\r\n display: inline-block !important;\r\n }\r\n</style>","import { ref, watch } from 'vue'\r\n\r\n\r\n/**\r\n * 合并默认列配置和缓存配置\r\n *\r\n * 设计原则:\r\n * 1️⃣ 列顺序:以 defaultColumns 为准\r\n * 2️⃣ 列增减:以 defaultColumns 为准\r\n * 3️⃣ 缓存只覆盖用户可配置字段(如 visible)\r\n */\r\nfunction mergeColumns(\r\n defaultColumns: any[],\r\n cacheColumns: Array<{ key: string; visible?: boolean }>\r\n) {\r\n if (!cacheColumns?.length) return defaultColumns\r\n\r\n // 建立 key => cache 映射表,提升查找效率\r\n const cacheMap = new Map(\r\n cacheColumns.map(c => [c.key, c])\r\n )\r\n\r\n return defaultColumns.map(col => {\r\n const cacheCol = cacheMap.get(col.key)\r\n\r\n // 只允许缓存覆盖「可配置字段」\r\n if (!cacheCol) return col\r\n\r\n return {\r\n ...col,\r\n visible:\r\n typeof cacheCol.visible === 'boolean'\r\n ? cacheCol.visible\r\n : col.visible\r\n }\r\n })\r\n}\r\n\r\n\r\n/**\r\n * useTableColumns\r\n *\r\n * 表格列管理 Hook\r\n *\r\n * 职责:\r\n * - 管理表格列顺序\r\n * - 管理列显示 / 隐藏\r\n * - 持久化用户配置\r\n */\r\nexport function useTableColumns(\r\n defaultColumns: any[],\r\n options?: {\r\n /** 缓存唯一标识 */\r\n cacheKey?: string\r\n /** 存储介质,默认 localStorage */\r\n storage?: Storage\r\n }\r\n) {\r\n\r\n /** 解构参数并设置默认值 */\r\n const { cacheKey, storage = localStorage } = options || {}\r\n\r\n /**\r\n * 如果没有 cacheKey,则不启用缓存\r\n * (例如公共页面、未登录页面)\r\n * 从缓存中读取列配置\r\n */\r\n const cache = cacheKey ? storage.getItem(cacheKey) : null\r\n\r\n /**\r\n * 响应式列配置\r\n * 初始化时合并默认列和缓存列\r\n */\r\n const columns = ref(\r\n mergeColumns(\r\n defaultColumns,\r\n cache ? JSON.parse(cache) : []\r\n )\r\n )\r\n\r\n /**\r\n * 监听列变化,自动写入缓存\r\n */\r\n watch(\r\n columns,\r\n (newVal: any) => {\r\n if (!cacheKey) return\r\n\r\n /**\r\n * ⚠️ 只保存“轻量配置”\r\n * 避免把 render / action / 函数序列化进 localStorage\r\n */\r\n const lightColumns = newVal.map((col: any) => ({\r\n key: col.key,\r\n visible: col.visible,\r\n columnOpts: col.columnOpts\r\n }))\r\n\r\n storage.setItem(\r\n cacheKey,\r\n JSON.stringify(lightColumns)\r\n )\r\n },\r\n { deep: true }\r\n )\r\n\r\n /**\r\n * 对外暴露的 API\r\n */\r\n return {\r\n /** 当前列配置(响应式) */\r\n columns,\r\n\r\n /**\r\n * 主动设置列配置\r\n * 常用于:列设置弹窗 / 拖拽排序完成\r\n */\r\n setColumns(newColumns: any[]) {\r\n columns.value = mergeColumns(\r\n defaultColumns,\r\n newColumns\r\n )\r\n\r\n if (cacheKey) {\r\n storage.setItem(\r\n cacheKey,\r\n JSON.stringify(newColumns)\r\n )\r\n }\r\n },\r\n\r\n /**\r\n * 重置为默认列配置\r\n */\r\n resetColumns() {\r\n columns.value = defaultColumns\r\n\r\n if (cacheKey) {\r\n storage.removeItem(cacheKey)\r\n }\r\n }\r\n }\r\n}\r\n","<template>\r\n <el-table ref=\"tableRef\"\r\n v-bind=\"$attrs\"\r\n :data=\"data\"\r\n :row-key=\"rowKey\"\r\n class=\"smart-table\"\r\n v-loading=\"loading\">\r\n <TableColumn \r\n v-for=\"col in cachedColumns\" \r\n :key=\"col.key\" \r\n :col=\"col\" \r\n :permissions=\"permissions\"\r\n :pagination=\"pagination\"\r\n @cell-change=\"handleCellChange\"\r\n @cell-blur=\"handleCellBlur\"\r\n @cell-enter=\"handleCellEnter\"\r\n @cell-click=\"handleCellClick\">\r\n <template v-for=\"col in cachedColumns\" #[col.key]=\"slotProps\">\r\n <slot :name=\"col.key\" v-bind=\"slotProps\" />\r\n </template>\r\n </TableColumn>\r\n </el-table>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"SmartTable\">\r\n import { PropType, ref, watch } from 'vue'\r\n import TableColumn from './column/index.vue'\r\n import type { BaseColumn, ColumnConfig } from './types'\r\n import { useTableColumns } from \"./hooks/useTableColumns\"\r\n\r\n const props = defineProps({\r\n data: { type: Array, default: () => [] },\r\n columns: { type: Array, default: () => [] },\r\n rowKey: { type: String, default: 'id' },\r\n loading: { type: Boolean, default: false },\r\n permissions: {\r\n type: Array as PropType<string[]>,\r\n default: () => []\r\n },\r\n cacheKey: String,\r\n pagination: { type: Object, default: () => ({}) },\r\n\r\n })\r\n \r\n const emit = defineEmits([\r\n 'update:columns',\r\n 'cellChange',\r\n 'cellBlur',\r\n 'cellEnter',\r\n 'cell-click',\r\n ])\r\n\r\n // ------------------ columns 处理 ------------------\r\n const { columns: cachedColumns } = useTableColumns(props.columns, {\r\n cacheKey: props.cacheKey ?? '',\r\n })\r\n watch(\r\n cachedColumns,\r\n (val: ColumnConfig[]) => emit(\"update:columns\", val),\r\n { deep: true, immediate: true },\r\n )\r\n\r\n // ----------------事件封装 ------------------\r\n const handleCellChange = (row: any, key: string) => emit('cellChange', row, key)\r\n const handleCellBlur = (row: any, key: string) => {\r\n emit('cellBlur', row, key)\r\n }\r\n const handleCellEnter = (row: any, key: string) => {\r\n console.log('enter')\r\n emit('cellEnter', row, key)\r\n }\r\n \r\n // SmartTable\r\n const handleCellClick = (row: any, col: any) => {\r\n if(!col) return\r\n emit('cell-click', row, col)\r\n }\r\n\r\n // el-table\r\n const tableRef = ref();\r\n defineExpose({\r\n tableRef,\r\n });\r\n\r\n</script>\r\n\r\n<style scoped>\r\n .smart-table {\r\n width: 100%;\r\n }\r\n</style>\r\n","/**\r\n * 全局配置管理\r\n */\r\nimport type { SmartTableConfig } from './types'\r\nimport { getRendererManager } from './renderer'\r\n\r\n/**\r\n * 默认配置\r\n */\r\nconst defaultConfig: SmartTableConfig = {\r\n defaultPagination: {\r\n page: 1,\r\n size: 10,\r\n total: 0\r\n },\r\n defaultTableProps: {},\r\n defaultColumnProps: {},\r\n theme: {\r\n primaryColor: '#409EFF',\r\n successColor: '#67C23A',\r\n warningColor: '#E6A23C',\r\n dangerColor: '#F56C6C',\r\n infoColor: '#909399'\r\n }\r\n}\r\n\r\n/**\r\n * 全局配置类\r\n */\r\nclass ConfigManager {\r\n private config: SmartTableConfig = { ...defaultConfig }\r\n\r\n /**\r\n * 获取所有配置\r\n */\r\n getConfig(): SmartTableConfig {\r\n return { ...this.config }\r\n }\r\n\r\n /**\r\n * 设置配置\r\n */\r\n setConfig(config: Partial<SmartTableConfig>): void {\r\n this.config = this.mergeConfig(this.config, config)\r\n\r\n // 如果有自定义渲染器,自动注册\r\n if (config.renderers) {\r\n const manager = getRendererManager()\r\n manager.registerMultiple(config.renderers)\r\n }\r\n }\r\n\r\n /**\r\n * 获取特定配置项\r\n */\r\n get<K extends keyof SmartTableConfig>(key: K): SmartTableConfig[K] {\r\n return this.config[key]\r\n }\r\n\r\n /**\r\n * 重置为默认配置\r\n */\r\n reset(): void {\r\n this.config = { ...defaultConfig }\r\n }\r\n\r\n /**\r\n * 深度合并配置\r\n */\r\n private mergeConfig(target: any, source: any): any {\r\n const result = { ...target }\r\n\r\n for (const key in source) {\r\n if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {\r\n result[key] = this.mergeConfig(target[key] || {}, source[key])\r\n } else {\r\n result[key] = source[key]\r\n }\r\n }\r\n\r\n return result\r\n }\r\n}\r\n\r\n/**\r\n * 全局配置管理器单例\r\n */\r\nlet globalConfigManager: ConfigManager | null = null\r\n\r\n/**\r\n * 获取全局配置管理器\r\n */\r\nexport function getConfigManager(): ConfigManager {\r\n if (!globalConfigManager) {\r\n globalConfigManager = new ConfigManager()\r\n }\r\n return globalConfigManager\r\n}\r\n\r\n/**\r\n * 安装插件(用于 Vue.use())\r\n */\r\nexport interface SmartTablePlugin {\r\n install: (options?: SmartTableConfig) => void\r\n}\r\n\r\n/**\r\n * 创建插件实例\r\n */\r\nexport function createSmartTablePlugin(defaultOptions?: SmartTableConfig): SmartTablePlugin {\r\n return {\r\n install(options?: SmartTableConfig) {\r\n const manager = getConfigManager()\r\n const config = { ...defaultOptions, ...options }\r\n if (config) {\r\n manager.setConfig(config)\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 全局配置快捷方法\r\n */\r\nexport function setSmartTableConfig(config: Partial<SmartTableConfig>): void {\r\n getConfigManager().setConfig(config)\r\n}\r\n\r\nexport function getSmartTableConfig(): SmartTableConfig {\r\n return getConfigManager().getConfig()\r\n}\r\n","/**\r\n * 增强类型系统 - 提供更好的类型推断\r\n */\r\nimport type { ColumnConfig, RendererName } from '../components/SmartTable/types'\r\n\r\n/**\r\n * 提取行数据的类型\r\n */\r\nexport type ExtractRowType<T> = T extends ColumnConfig<infer R> ? R : never\r\n\r\n/**\r\n * 根据列配置提取表格数据类型\r\n */\r\nexport type TableDataFromColumns<T extends ColumnConfig[]> = T extends (infer C)[]\r\n ? C extends ColumnConfig<infer R>\r\n ? R\r\n : any\r\n : any\r\n\r\n/**\r\n * 渲染器 Props 类型推断\r\n */\r\nexport type InferRendererProps<T extends RendererName> =\r\n T extends 'html'\r\n ? { style?: string; class?: string; [key: string]: any }\r\n : T extends 'copy'\r\n ? { successText?: string; errorText?: string; iconColor?: string; [key: string]: any }\r\n : T extends 'img'\r\n ? { width?: string | number; height?: string | number; fit?: string; previewSrcList?: string[]; [key: string]: any }\r\n : T extends 'dict'\r\n ? { options: Array<{ label: string; value: string | number; listClass?: string; cssClass?: string }>; showValue?: boolean }\r\n : T extends 'map'\r\n ? { options: Record<string | number, any> }\r\n : T extends 'input'\r\n ? { placeholder?: string; size?: 'small' | 'default' | 'large'; clearable?: boolean }\r\n : T extends 'select'\r\n ? { options: Array<{ label: string; value: string | number }>; placeholder?: string; clearable?: boolean }\r\n : { [key: string]: any }\r\n\r\n/**\r\n * 快捷创建列的辅助函数(类型安全简化版)\r\n */\r\nexport function defineColumn(\r\n key: string,\r\n config?: Partial<Omit<ColumnConfig, 'key'>>\r\n): ColumnConfig {\r\n return {\r\n key,\r\n ...config\r\n } as ColumnConfig\r\n}\r\n"],"names":["RendererManager","__publicField","name","renderer","renderers","globalRendererManager","getRendererManager","wrapSFCComponent","comp","defineComponent","props","h","createFunctionalRenderer","render","validateRendererProps","rendererName","renderProps","getValueByPath","obj","path","acc","key","setValueByPath","value","keys","lastKey","target","__props","ref","watch","v","onBlur","_a","onEnter","_openBlock","_createBlock","_component_el_input","_mergeProps","$event","_component_el_input_number","onChange","_component_el_select","_createElementBlock","_Fragment","opt","_component_el_option","input","EditableInput","inputNumber","EditableNumber","select","EditableSelect","button","rp","val","ElButton","link","html","copy","butStyle","ElMessage","textarea","successful","DocumentCopy","img","imageList","item","defaultStyle","ElImage","CopyDocument","dict","options","showValue","values","matchedOptions","unmatched","children","_index","ElTag","map","isDataColumn","col","formatter","row","icon","builtInRenderers","registerBuiltInRenderers","registry","createRenderer","useOperationColumn","buttonConfigs","maxbtn","userPermissions","all_permission","hasPermi","permArray","p","hasAnyButton","computed","btn","optWidth","sum","isButtonVisible","optRowWidth","rows","max","emit","__emit","computeIndex","index","page","size","_b","toRefs","handleCellChange","handleCellBlur","handleCellEnter","handleCellClick","manager","allRenderers","r","hasAnyVisibleButton","getMaxOptWidth","getVisibleButtons","showOperationColumn","operationWidth","isDataOrOperationColumn","c","_unref","_component_el_table_column","_withCtx","$index","_createTextVNode","_toDisplayString","_renderList","_component_el_button","scope","$slots","_renderSlot","_ctx","_normalizeProps","_resolveDynamicComponent","_normalizeStyle","_normalizeClass","_hoisted_1","mergeColumns","defaultColumns","cacheColumns","cacheMap","cacheCol","useTableColumns","cacheKey","storage","cache","columns","newVal","lightColumns","newColumns","cachedColumns","tableRef","__expose","_withDirectives","_component_el_table","$attrs","TableColumn","slotProps","defaultConfig","ConfigManager","config","source","result","globalConfigManager","getConfigManager","setSmartTableConfig","getSmartTableConfig","defineColumn"],"mappings":"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"}
1
+ {"version":3,"file":"vue3-smart-table.umd.js","sources":["../src/components/SmartTable/renderer.ts","../src/components/SmartTable/utils/path.ts","../src/components/SmartTable/renderers/input.vue","../src/components/SmartTable/renderers/inputNumber.vue","../src/components/SmartTable/renderers/select.vue","../src/components/SmartTable/renderers/index.ts","../src/components/SmartTable/hooks/useOperationColumn.ts","../src/components/SmartTable/column/index.vue","../src/components/SmartTable/hooks/useTableColumns.ts","../src/components/SmartTable/index.vue","../src/components/SmartTable/config.ts","../src/types/enhanced.ts"],"sourcesContent":["/**\r\n * SmartTable 内部渲染器管理系统\r\n * 移动到组件内部,保证组件的自包含性\r\n */\r\nimport { defineComponent, h, Component } from 'vue'\r\nimport type { Renderer } from './types'\r\n\r\n/**\r\n * 渲染器注册表接口\r\n */\r\nexport interface RendererRegistry {\r\n register(name: string, renderer: Renderer): void\r\n registerMultiple(renderers: Record<string, Renderer>): void\r\n get(name: string): Renderer | undefined\r\n has(name: string): boolean\r\n unregister(name: string): boolean\r\n clear(): void\r\n names(): string[]\r\n}\r\n\r\n/**\r\n * 渲染器管理器类\r\n */\r\nclass RendererManager implements RendererRegistry {\r\n private renderers: Map<string, Renderer> = new Map()\r\n\r\n register(name: string, renderer: Renderer): void {\r\n if (this.renderers.has(name)) {\r\n // 批量注册时不警告,只在单独注册时警告\r\n if (process.env.NODE_ENV === 'development') {\r\n console.debug(`[SmartTable] Renderer \"${name}\" already registered, skipping.`)\r\n }\r\n }\r\n this.renderers.set(name, renderer)\r\n }\r\n\r\n registerMultiple(renderers: Record<string, Renderer>): void {\r\n Object.entries(renderers).forEach(([name, renderer]) => {\r\n if (!this.renderers.has(name)) {\r\n this.renderers.set(name, renderer)\r\n }\r\n })\r\n }\r\n\r\n get(name: string): Renderer | undefined {\r\n return this.renderers.get(name)\r\n }\r\n\r\n has(name: string): boolean {\r\n return this.renderers.has(name)\r\n }\r\n\r\n unregister(name: string): boolean {\r\n return this.renderers.delete(name)\r\n }\r\n\r\n clear(): void {\r\n this.renderers.clear()\r\n }\r\n\r\n names(): string[] {\r\n return Array.from(this.renderers.keys())\r\n }\r\n}\r\n\r\n/**\r\n * 全局渲染器管理器单例\r\n */\r\nlet globalRendererManager: RendererManager | null = null\r\n\r\n/**\r\n * 获取渲染器管理器\r\n */\r\nexport function getRendererManager(): RendererManager {\r\n if (!globalRendererManager) {\r\n globalRendererManager = new RendererManager()\r\n }\r\n return globalRendererManager\r\n}\r\n\r\n/**\r\n * 包装 SFC 组件为渲染器\r\n */\r\nexport function wrapSFCComponent(comp: Component): Renderer {\r\n return defineComponent({\r\n props: ['row', 'col', 'onCellChange', 'onCellBlur', 'onCellEnter', 'onClick'],\r\n setup(props) {\r\n return () => h(comp, props)\r\n }\r\n })\r\n}\r\n\r\n/**\r\n * 创建函数式渲染器\r\n */\r\nexport function createFunctionalRenderer(\r\n render: (props: {\r\n row: any\r\n col: any\r\n onCellChange?: (row: any, col: any) => void\r\n onCellBlur?: (row: any, col: any) => void\r\n onCellEnter?: (row: any, col: any) => void\r\n onClick?: (row: any, col: any) => void\r\n }) => any\r\n): Renderer {\r\n return defineComponent({\r\n props: ['row', 'col', 'onCellChange', 'onCellBlur', 'onCellEnter', 'onClick'],\r\n setup(props) {\r\n return () => render(props)\r\n }\r\n })\r\n}\r\n\r\n/**\r\n * 验证渲染器配置\r\n * 在开发环境下验证 renderProps 的正确性\r\n */\r\nexport function validateRendererProps(\r\n rendererName: string,\r\n renderProps: Record<string, any> | undefined\r\n): void {\r\n if (process.env.NODE_ENV !== 'production' && renderProps) {\r\n switch (rendererName) {\r\n case 'dict':\r\n if (!renderProps.options || !Array.isArray(renderProps.options)) {\r\n console.warn(\r\n `[SmartTable] 'dict' renderer requires 'options' array, received:`,\r\n renderProps.options\r\n )\r\n }\r\n break\r\n\r\n case 'select':\r\n if (!renderProps.options || !Array.isArray(renderProps.options)) {\r\n console.warn(\r\n `[SmartTable] 'select' renderer requires 'options' array, received:`,\r\n renderProps.options\r\n )\r\n } else if (renderProps.options.length === 0) {\r\n console.warn(`[SmartTable] 'select' renderer 'options' array is empty`)\r\n }\r\n break\r\n\r\n case 'map':\r\n if (!renderProps.options || typeof renderProps.options !== 'object') {\r\n console.warn(\r\n `[SmartTable] 'map' renderer requires 'options' object, received:`,\r\n renderProps.options\r\n )\r\n }\r\n break\r\n\r\n case 'link':\r\n if (!renderProps.href || typeof renderProps.href !== 'string') {\r\n console.warn(\r\n `[SmartTable] 'link' renderer requires 'href' string, received:`,\r\n renderProps.href\r\n )\r\n }\r\n break\r\n\r\n case 'input-number':\r\n if (renderProps.min !== undefined && renderProps.max !== undefined) {\r\n if (renderProps.min > renderProps.max) {\r\n console.warn(\r\n `[SmartTable] 'input-number' renderer: min (${renderProps.min}) should not be greater than max (${renderProps.max})`\r\n )\r\n }\r\n }\r\n break\r\n }\r\n }\r\n}\r\n","/**\r\n * 安全获取对象深层属性\r\n * 支持 a.b.c / a.0.b\r\n */\r\nexport function getValueByPath(obj: any, path?: string) {\r\n if (!obj || !path) return undefined\r\n return path.split('.').reduce((acc, key) => acc?.[key], obj)\r\n }\r\n \r\n /**\r\n * 安全设置对象深层属性(用于可编辑表格)\r\n */\r\n export function setValueByPath(\r\n obj: any,\r\n path: string,\r\n value: any\r\n ) {\r\n if (!obj || !path) return\r\n const keys = path.split('.')\r\n const lastKey = keys.pop()!\r\n \r\n const target = keys.reduce((acc, key) => {\r\n if (!acc[key]) acc[key] = {}\r\n return acc[key]\r\n }, obj)\r\n \r\n target[lastKey] = value\r\n }\r\n ","<template>\n <el-input\n v-model=\"value\"\n v-bind=\"{ placeholder: '', size: 'small', clearable: true, ...col.renderProps }\"\n @blur=\"onBlur\"\n @keyup.enter=\"onEnter\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport type { ColumnConfig } from '../types'\nimport { getValueByPath, setValueByPath } from '../utils/path'\n\ninterface Props {\n readonly row: any\n readonly col: ColumnConfig\n onCellBlur?: (row: any, col: ColumnConfig) => void\n onCellEnter?: (row: any, col: ColumnConfig) => void\n}\n\nconst props = defineProps<Props>()\nconst value = ref(getValueByPath(props.row, props.col.key))\n\nwatch(value, (v) => {\n setValueByPath(props.row, props.col.key, v)\n})\n\nconst onBlur = () => props.onCellBlur?.(props.row, props.col)\nconst onEnter = () => props.onCellEnter?.(props.row, props.col)\n</script>\n","<template>\n <el-input-number\n v-model=\"value\"\n v-bind=\"{ min: 0, max: 99999, controls: false, size: 'small', ...col.renderProps }\"\n @blur=\"onBlur\"\n @keyup.enter=\"onEnter\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport type { ColumnConfig } from '../types'\nimport { getValueByPath, setValueByPath } from '../utils/path'\n\ninterface Props {\n readonly row: any\n readonly col: ColumnConfig\n onCellChange?: (row: any, col: ColumnConfig) => void\n onCellBlur?: (row: any, col: ColumnConfig) => void\n onCellEnter?: (row: any, col: ColumnConfig) => void\n}\n\nconst props = defineProps<Props>()\nconst value = ref(getValueByPath(props.row, props.col.key))\n\nwatch(value, (v) => {\n setValueByPath(props.row, props.col.key, v)\n props.onCellChange?.(props.row, props.col)\n})\n\nconst onBlur = () => props.onCellBlur?.(props.row, props.col)\nconst onEnter = () => props.onCellEnter?.(props.row, props.col)\n</script>\n","<template>\n <el-select\n v-model=\"value\"\n v-bind=\"{ placeholder: '请选择', size: 'small', clearable: true, ...col.renderProps }\"\n @change=\"onChange\"\n @blur=\"onBlur\"\n @keyup.enter=\"onEnter\"\n >\n <el-option\n v-for=\"opt in col.renderProps?.options || []\"\n :key=\"opt.value\"\n :label=\"opt.label\"\n :value=\"opt.value\"\n />\n </el-select>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport type { ColumnConfig } from '../types'\nimport { getValueByPath, setValueByPath } from '../utils/path'\n\ninterface Props {\n readonly row: any\n readonly col: ColumnConfig\n onCellChange?: (row: any, col: ColumnConfig) => void\n onCellBlur?: (row: any, col: ColumnConfig) => void\n onCellEnter?: (row: any, col: ColumnConfig) => void\n}\n\nconst props = defineProps<Props>()\nconst value = ref(getValueByPath(props.row, props.col.key))\n\nwatch(value, (v) => {\n setValueByPath(props.row, props.col.key, v)\n})\n\nconst onChange = () => props.onCellChange?.(props.row, props.col)\nconst onBlur = () => props.onCellBlur?.(props.row, props.col)\nconst onEnter = () => props.onCellEnter?.(props.row, props.col)\n</script>\n","/**\r\n * 内置渲染器集合\r\n * 可以按需引入或批量注册\r\n */\r\nimport { h } from 'vue'\r\nimport { ElButton, ElTag, ElImage, ElMessage } from 'element-plus'\r\nimport { DocumentCopy, CopyDocument } from '@element-plus/icons-vue'\r\nimport type { ColumnConfig } from '../types'\r\nimport { getValueByPath } from '../utils/path'\r\nimport { wrapSFCComponent, createFunctionalRenderer } from '../renderer'\r\nimport EditableInput from './input.vue'\r\nimport EditableNumber from './inputNumber.vue'\r\nimport EditableSelect from './select.vue'\r\n\r\n/**\r\n * 包装 SFC 组件\r\n */\r\nconst input = wrapSFCComponent(EditableInput)\r\nconst inputNumber = wrapSFCComponent(EditableNumber)\r\nconst select = wrapSFCComponent(EditableSelect)\r\n\r\n/**\r\n * button 渲染器\r\n */\r\nconst button = createFunctionalRenderer((props) => {\r\n const rp = props.col.renderProps || {}\r\n const val = getValueByPath(props.row, props.col.key)\r\n return h(ElButton as any, {\r\n type: rp.type || 'primary',\r\n ...rp,\r\n onClick: () => props.onClick?.(props.row, props.col)\r\n }, () => rp.label || val)\r\n})\r\n\r\n/**\r\n * link 渲染器\r\n */\r\nconst link = createFunctionalRenderer((props) => {\r\n const rp = props.col.renderProps || {}\r\n const val = getValueByPath(props.row, props.col.key)\r\n return h('a', {\r\n href: rp.href || '#',\r\n target: rp.blank ? '_blank' : '_self',\r\n style: rp.style || 'color:#409EFF;cursor:pointer;',\r\n }, rp.label || val)\r\n})\r\n\r\n/**\r\n * html 渲染器\r\n */\r\nconst html = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key)\r\n return h('div', {\r\n class: 'line-clamp-2',\r\n innerHTML: val ?? '',\r\n ...(props.col?.renderProps || {})\r\n })\r\n})\r\n\r\n/**\r\n * copy 渲染器\r\n */\r\nconst copy = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const rp = props.col.renderProps ?? {}\r\n const butStyle = {\r\n 'position': 'absolute',\r\n 'right': '-5px',\r\n 'top': '50%',\r\n 'transform': 'translateY(-50%)',\r\n 'cursor': 'pointer',\r\n 'display': 'none',\r\n 'font-size': '12px',\r\n 'color': rp.iconColor || '#409EFF',\r\n 'user-select': 'none'\r\n }\r\n return h('div', {\r\n class: 'st_copy_wrapper',\r\n style: 'width: 100%; position: relative; display: inline-block;'\r\n },\r\n [\r\n h('span', {\r\n class: 'st_copy_text line-clamp-1',\r\n style: 'padding-right: 10px; display: block;',\r\n }, val),\r\n val && h('span', {\r\n class: 'st_copy_btn',\r\n style: butStyle,\r\n title: rp.copyTitle || '复制',\r\n onClick: () => {\r\n if (!val) return\r\n try {\r\n if (navigator.clipboard && navigator.clipboard.writeText) {\r\n navigator.clipboard.writeText(val).then(() => {\r\n ElMessage.success(rp.successText ?? '复制成功')\r\n }).catch(() => {\r\n ElMessage.error(rp.errorText ?? '复制失败')\r\n })\r\n } else {\r\n const textarea = document.createElement('textarea')\r\n textarea.value = val\r\n textarea.style.position = 'fixed'\r\n textarea.style.opacity = '0'\r\n document.body.appendChild(textarea)\r\n textarea.select()\r\n const successful = document.execCommand('copy')\r\n document.body.removeChild(textarea)\r\n\r\n if (successful) {\r\n ElMessage.success(rp.successText ?? '复制成功')\r\n } else {\r\n ElMessage.error(rp.errorText ?? '复制失败')\r\n }\r\n }\r\n } catch (err) {\r\n ElMessage.error(rp.errorText ?? '复制失败')\r\n }\r\n }\r\n }, [h(DocumentCopy, {\r\n style: 'width: 1em; height: 1em;'\r\n })])\r\n ].filter(Boolean)\r\n )\r\n})\r\n\r\n/**\r\n * img 渲染器\r\n */\r\nconst img = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const rp = props.col?.renderProps || {}\r\n\r\n const getImageList = () => {\r\n if (!val) return []\r\n if (Array.isArray(val)) {\r\n return val.filter(item => item && typeof item === 'string')\r\n }\r\n return [val]\r\n }\r\n\r\n const imageList = getImageList()\r\n\r\n if (imageList.length === 0) {\r\n return rp.placeholder || ''\r\n }\r\n\r\n const defaultStyle = {\r\n width: rp.width || '80px',\r\n height: rp.height || '80px',\r\n marginRight: imageList.length > 1 ? '4px' : '0',\r\n ...(rp.style || {})\r\n }\r\n\r\n if (imageList.length === 1) {\r\n return h(ElImage, {\r\n src: imageList[0],\r\n previewSrcList: rp.previewSrcList || imageList,\r\n fit: rp.fit || 'contain',\r\n style: defaultStyle,\r\n ...rp\r\n })\r\n }\r\n\r\n return h('div',\r\n {\r\n class: 'st_img_wrapper',\r\n style: 'display: flex; align-items: center; position: relative'\r\n },\r\n [\r\n h(ElImage, {\r\n src: imageList[0],\r\n previewSrcList: rp.previewSrcList || imageList,\r\n fit: rp.fit || 'contain',\r\n style: defaultStyle,\r\n ...rp\r\n }),\r\n imageList.length > 1 && h('span', {\r\n class: 'st_img_total',\r\n style: `position: absolute; top: 0; right: 0; `,\r\n title: `${imageList.length}`\r\n }, [h(CopyDocument, { style: `width: 1em; height: 1em; ` })])\r\n ]\r\n )\r\n})\r\n\r\n/**\r\n * dict 渲染器\r\n */\r\nconst dict = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const rp = props.col.renderProps || {}\r\n const options = rp.options ?? []\r\n const showValue = rp.showValue ?? false\r\n\r\n if (val === null || val === undefined || val === '') return ''\r\n\r\n const values = Array.isArray(val) ? val.map(String) : [String(val)]\r\n const matchedOptions = options.filter((opt: any) => values.includes(String(opt.value)))\r\n const unmatched = values.filter(v => !options.some((opt: any) => String(opt.value) === v))\r\n\r\n const children = matchedOptions.map((item: any, _index: number) => {\r\n return h(\r\n ElTag,\r\n { key: item.value, type: item.listClass, class: item.cssClass, disableTransitions: true },\r\n { default: () => item.label + ' ' }\r\n )\r\n })\r\n\r\n if (showValue && unmatched.length > 0) {\r\n children.push(h('span', {}, unmatched.join(' ')))\r\n }\r\n\r\n return h('div', {}, children)\r\n})\r\n\r\n/**\r\n * map 渲染器\r\n */\r\nconst map = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const options = (props.col.renderProps?.options ?? {}) as Record<string, any>\r\n return val != null ? options[val] ?? '' : ''\r\n})\r\n\r\n/**\r\n * formatter 渲染器\r\n */\r\nexport function isDataColumn(\r\n col: ColumnConfig\r\n): col is any {\r\n return typeof (col as any).formatter === 'function'\r\n}\r\n\r\nconst formatter = createFunctionalRenderer((props) => {\r\n const { col, row } = props\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n if (isDataColumn(col)) {\r\n return col.formatter?.(val, row)\r\n }\r\n return val ?? ''\r\n})\r\n\r\n/**\r\n * icon 渲染器\r\n */\r\nconst icon = createFunctionalRenderer((props) => {\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const rp = props.col.renderProps || {}\r\n if (!val) return ''\r\n // 判断网络图片\r\n if (/^https?:\\/\\//.test(val)) {\r\n return h(ElImage, {\r\n src: val,\r\n previewSrcList: [val],\r\n fit: 'contain',\r\n style: 'width:40px;height:40px',\r\n ...rp\r\n })\r\n }\r\n // 判断 svg 源码\r\n if (/^\\s*<svg[\\s\\S]*<\\/svg>\\s*$/.test(val)) {\r\n return h('div', {\r\n innerHTML: val,\r\n style: `width:40px;height:40px;display:inline-block;${rp.style || ''}`,\r\n ...rp\r\n })\r\n }\r\n // 默认当作 iconfont\r\n return h('i', {\r\n class: val,\r\n style: `font-size:20px;${rp.style || ''}`,\r\n ...rp\r\n })\r\n})\r\n\r\n/**\r\n * 所有内置渲染器\r\n */\r\nexport const builtInRenderers = {\r\n input,\r\n 'input-number': inputNumber,\r\n select,\r\n button,\r\n link,\r\n html,\r\n copy,\r\n img,\r\n dict,\r\n map,\r\n formatter,\r\n icon,\r\n}\r\n\r\n/**\r\n * 安装所有内置渲染器\r\n */\r\nexport function registerBuiltInRenderers(registry: { registerMultiple: (renderers: Record<string, any>) => void }) {\r\n registry.registerMultiple(builtInRenderers)\r\n}\r\n\r\n/**\r\n * 创建默认渲染器集合(兼容旧 API)\r\n * @deprecated 建议使用插件化架构\r\n */\r\nexport function createRenderer() {\r\n return builtInRenderers\r\n}\r\n","import { computed } from 'vue'\r\n\r\nimport { ButtonConfig } from \"../types\"\r\n/**\r\n * useOperationColumn\r\n *\r\n * 操作列专用逻辑 Hook,负责:\r\n * 1. 根据权限判断操作列是否需要显示\r\n * 2. 计算操作列宽度(支持按钮自定义宽度)\r\n * 3. 支持行级 visible 配置\r\n * @param buttonConfigs 操作列按钮配置\r\n * @param maxbtn 操作列最多显示按钮数量(超过的不参与宽度计算)\r\n * @param userPermissions 当前用户权限列表\r\n */\r\nexport function useOperationColumn(\r\n buttonConfigs: ButtonConfig[],\r\n maxbtn = 10,\r\n userPermissions: string[] = []\r\n) {\r\n /** 默认按钮宽度 */\r\n const defaultWidth = 60\r\n\r\n /** 超级权限标识 */\r\n const all_permission = '*:*:*'\r\n\r\n /** --------------------------\r\n * 权限判断\r\n * -------------------------- */\r\n\r\n /**\r\n * 判断是否具备按钮权限\r\n *\r\n * 规则:\r\n * - permission 未配置 ⇒ 永远有权限\r\n * - permission 为 string | string[] ⇒ 与用户权限匹配\r\n */\r\n const hasPermi = (value?: string | string[]) => {\r\n if (!value) return true\r\n\r\n const permArray = Array.isArray(value) ? value : [value]\r\n return userPermissions.some(\r\n p => p === all_permission || permArray.includes(p)\r\n )\r\n }\r\n\r\n /** --------------------------\r\n * 仅基于权限(不考虑行级 visible)\r\n * 适用于:表格未加载数据时的判断\r\n * -------------------------- */\r\n\r\n /**\r\n * 是否至少存在一个有权限的按钮\r\n * 用于判断操作列是否需要渲染\r\n */\r\n const hasAnyButton = computed(() => {\r\n return buttonConfigs.some(btn => hasPermi(btn.permission))\r\n })\r\n\r\n /**\r\n * 操作列宽度(仅基于权限)\r\n * 用于无行数据时的兜底宽度计算\r\n */\r\n const optWidth = computed(() => {\r\n const permittedBtns = buttonConfigs\r\n .filter(btn => hasPermi(btn.permission))\r\n .slice(0, maxbtn)\r\n\r\n return permittedBtns.reduce(\r\n (sum, btn) => sum + (btn.width ?? defaultWidth),\r\n 0\r\n )\r\n })\r\n\r\n /** --------------------------\r\n * 权限 + 行级 visible\r\n * -------------------------- */\r\n\r\n /**\r\n * 判断某个按钮在某一行是否可见\r\n */\r\n const isButtonVisible = (btn: ButtonConfig, row: any) => {\r\n return (\r\n hasPermi(btn.permission) &&\r\n (btn.visible ? btn.visible(row) : true)\r\n )\r\n }\r\n\r\n /**\r\n * 单行操作列宽度\r\n */\r\n const optRowWidth = (row: any) => {\r\n const visibleBtns = buttonConfigs\r\n .filter(btn => isButtonVisible(btn, row))\r\n .slice(0, maxbtn)\r\n\r\n return visibleBtns.reduce(\r\n (sum, btn) => sum + (btn.width ?? defaultWidth),\r\n 0\r\n )\r\n }\r\n\r\n /**\r\n * 遍历所有行,获取最大操作列宽度\r\n */\r\n const getMaxOptWidth = (rows: any[]) => {\r\n if (!rows?.length) return optWidth.value\r\n return rows.reduce(\r\n (max, row) => Math.max(max, optRowWidth(row)),\r\n 0\r\n )\r\n }\r\n\r\n /**\r\n * 判断是否至少有一行存在可见按钮\r\n */\r\n const hasAnyVisibleButton = (rows: any[]) => {\r\n if (!rows?.length) return false\r\n return rows.some(row =>\r\n buttonConfigs.some(btn => isButtonVisible(btn, row))\r\n )\r\n }\r\n\r\n const getVisibleButtons = (row: any) => {\r\n return buttonConfigs\r\n .filter(btn => isButtonVisible(btn, row))\r\n .slice(0, maxbtn)\r\n }\r\n\r\n return {\r\n hasAnyButton,\r\n optWidth,\r\n hasAnyVisibleButton,\r\n getMaxOptWidth,\r\n getVisibleButtons\r\n }\r\n}\r\n","<template>\r\n <!-- ========== selection 列 ========== -->\r\n <el-table-column\r\n v-if=\"col.type === 'selection'\"\r\n type=\"selection\"\r\n v-bind=\"col.columnProps\"\r\n />\r\n\r\n <!-- ========== index 列 ========== -->\r\n <el-table-column\r\n v-else-if=\"col.type === 'index'\"\r\n type=\"index\"\r\n :label=\"col.label || '#'\"\r\n align=\"center\"\r\n v-bind=\"col.columnProps\"\r\n >\r\n <template #default=\"{ $index }\">\r\n {{ computeIndex($index) }}\r\n </template>\r\n </el-table-column>\r\n\r\n <!-- ========== operation 列 ========== -->\r\n <el-table-column\r\n v-else-if=\"col.type === 'operation' && showOperationColumn\"\r\n :label=\"col.label || '操作'\"\r\n align=\"center\"\r\n v-bind=\"{\r\n ...col.columnProps,\r\n width: operationWidth\r\n }\"\r\n >\r\n <template #default=\"{ row }\">\r\n <el-button\r\n v-for=\"btn in getVisibleButtons(row)\"\r\n :key=\"btn.label\"\r\n :type=\"btn.type || 'primary'\"\r\n link\r\n @click=\"btn.action(row)\"\r\n >\r\n {{ btn.label }}\r\n </el-button>\r\n </template>\r\n </el-table-column>\r\n\r\n <!-- ========== 普通列 / renderer / editable ========== -->\r\n <el-table-column\r\n v-else-if=\"isDataOrOperationColumn(col)\"\r\n :label=\"col.label\"\r\n align=\"center\"\r\n v-bind=\"col.columnProps || {}\"\r\n >\r\n \r\n <template #default=\"scope\">\r\n <!-- 父组件插槽优先 -->\r\n <template v-if=\"col.render === 'slot' && $slots[col?.slot || col.key]\">\r\n <slot :name=\"col?.slot || col.key\" v-bind=\"scope\" />\r\n </template>\r\n\r\n <!-- renderer -->\r\n <component\r\n v-else-if=\"col.render && renderer[col.render]\"\r\n :is=\"renderer[col.render]\"\r\n :row=\"scope.row\"\r\n :col=\"col\"\r\n :onCellChange=\"handleCellChange\"\r\n :onCellBlur=\"handleCellBlur\"\r\n :onCellEnter=\"handleCellEnter\"\r\n :onClick=\"handleCellClick\"\r\n />\r\n <!-- 默认文本 -->\r\n <span v-else\r\n :style=\"col.renderProps?.style || ''\"\r\n :class=\"col.renderProps?.class || ''\"\r\n :title=\"getValueByPath(scope.row, col.key)\">\r\n {{ getValueByPath(scope.row, col.key) }}\r\n </span>\r\n </template>\r\n </el-table-column>\r\n \r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed, toRefs } from 'vue'\r\nimport type { PropType } from 'vue'\r\nimport type { ColumnConfig } from '../types'\r\nimport { getRendererManager } from '../renderer'\r\nimport { registerBuiltInRenderers } from '../renderers'\r\nimport { useOperationColumn } from '../hooks/useOperationColumn'\r\nimport { getValueByPath } from '../utils/path'\r\n\r\nconst props = defineProps({\r\n col: { type: Object as PropType<ColumnConfig>, required: true },\r\n permissions: { type: Array as PropType<string[]>, default: () => [] },\r\n pagination: { type: Object, default: () => ({}) },\r\n})\r\n\r\nconst emit = defineEmits(['cellBlur', 'cellEnter', 'cellChange', 'cellClick'])\r\n\r\nconst computeIndex = (index: number) => {\r\n const page = props.pagination?.page\r\n const size = props.pagination?.size\r\n return page && size ? (page - 1) * size + index + 1 : index + 1\r\n}\r\n\r\n/** 解构 col 响应式引用 */\r\nconst { col } = toRefs(props)\r\n\r\n/** ========== 事件统一上抛 ========== */\r\nconst handleCellChange = (row: any, key: string) => emit('cellChange', row, key)\r\nconst handleCellBlur = (row: any, key: string) => emit('cellBlur', row, key)\r\nconst handleCellEnter = (row: any, key: string) => emit('cellEnter', row, key)\r\nconst handleCellClick = (row: any, col: any) => emit('cellClick', row, col)\r\n\r\n/** ========== renderer 注册 ========== */\r\n// 注册内置渲染器(重复调用会自动跳过已存在的)\r\nregisterBuiltInRenderers(getRendererManager())\r\n\r\n// 获取所有渲染器(内置 + 自定义)\r\nconst renderer = computed(() => {\r\n const manager = getRendererManager()\r\n const allRenderers: Record<string, any> = {}\r\n\r\n // 合并内置渲染器和自定义渲染器\r\n manager.names().forEach((name: string) => {\r\n const r = manager.get(name)\r\n if (r) allRenderers[name] = r\r\n })\r\n\r\n return allRenderers\r\n})\r\n\r\n/** ========== operation 列逻辑 ========== */\r\nconst {\r\n hasAnyButton,\r\n hasAnyVisibleButton,\r\n optWidth,\r\n getMaxOptWidth,\r\n getVisibleButtons\r\n} = useOperationColumn(\r\n col.value.buttons || [],\r\n col.value.maxbtn ?? 10,\r\n props.permissions || []\r\n)\r\n\r\n/** 是否显示操作列 */\r\nconst showOperationColumn = computed(() => {\r\n const buttons = col.value.buttons || []\r\n if (!buttons.length) return false // 没有配置按钮直接隐藏\r\n const rows = col.value.__rows || []\r\n // 无行数据时,至少有一个按钮有权限就显示\r\n if (!rows.length) return hasAnyButton.value\r\n // 有行数据时,至少一行有可见按钮才显示\r\n return hasAnyVisibleButton(col.value.__rows || [])\r\n})\r\n\r\n/** 操作列宽度 */\r\nconst operationWidth = computed(() => {\r\n // 无行数据,用静态宽度\r\n if (!col.value.__rows) return optWidth.value\r\n // 有行数据,取最大宽度\r\n return getMaxOptWidth(col.value.__rows)\r\n})\r\n\r\nfunction isDataOrOperationColumn(c: ColumnConfig) {\r\n if (c.type === 'selection' || c.type === 'index') return false\r\n if (c.type === 'operation' && !showOperationColumn.value) return false\r\n if (c.visible === false) return false\r\n return true\r\n}\r\n</script>","import { ref, watch } from 'vue'\r\n\r\n\r\n/**\r\n * 合并默认列配置和缓存配置\r\n *\r\n * 设计原则:\r\n * 1️⃣ 列顺序:以 defaultColumns 为准\r\n * 2️⃣ 列增减:以 defaultColumns 为准\r\n * 3️⃣ 缓存只覆盖用户可配置字段(如 visible)\r\n */\r\nfunction mergeColumns(\r\n defaultColumns: any[],\r\n cacheColumns: Array<{ key: string; visible?: boolean }>\r\n) {\r\n if (!cacheColumns?.length) return defaultColumns\r\n\r\n // 建立 key => cache 映射表,提升查找效率\r\n const cacheMap = new Map(\r\n cacheColumns.map(c => [c.key, c])\r\n )\r\n\r\n return defaultColumns.map(col => {\r\n const cacheCol = cacheMap.get(col.key)\r\n\r\n // 只允许缓存覆盖「可配置字段」\r\n if (!cacheCol) return col\r\n\r\n return {\r\n ...col,\r\n visible:\r\n typeof cacheCol.visible === 'boolean'\r\n ? cacheCol.visible\r\n : col.visible\r\n }\r\n })\r\n}\r\n\r\n\r\n/**\r\n * useTableColumns\r\n *\r\n * 表格列管理 Hook\r\n *\r\n * 职责:\r\n * - 管理表格列顺序\r\n * - 管理列显示 / 隐藏\r\n * - 持久化用户配置\r\n */\r\nexport function useTableColumns(\r\n defaultColumns: any[],\r\n options?: {\r\n /** 缓存唯一标识 */\r\n cacheKey?: string\r\n /** 存储介质,默认 localStorage */\r\n storage?: Storage\r\n }\r\n) {\r\n\r\n /** 解构参数并设置默认值 */\r\n const { cacheKey, storage = localStorage } = options || {}\r\n\r\n /**\r\n * 如果没有 cacheKey,则不启用缓存\r\n * (例如公共页面、未登录页面)\r\n * 从缓存中读取列配置\r\n */\r\n const cache = cacheKey ? storage.getItem(cacheKey) : null\r\n\r\n /**\r\n * 响应式列配置\r\n * 初始化时合并默认列和缓存列\r\n */\r\n const columns = ref(\r\n mergeColumns(\r\n defaultColumns,\r\n cache ? JSON.parse(cache) : []\r\n )\r\n )\r\n\r\n /**\r\n * 监听列变化,自动写入缓存\r\n */\r\n watch(\r\n columns,\r\n (newVal: any) => {\r\n if (!cacheKey) return\r\n\r\n /**\r\n * ⚠️ 只保存“轻量配置”\r\n * 避免把 render / action / 函数序列化进 localStorage\r\n */\r\n const lightColumns = newVal.map((col: any) => ({\r\n key: col.key,\r\n visible: col.visible,\r\n columnOpts: col.columnOpts\r\n }))\r\n\r\n storage.setItem(\r\n cacheKey,\r\n JSON.stringify(lightColumns)\r\n )\r\n },\r\n { deep: true }\r\n )\r\n\r\n /**\r\n * 对外暴露的 API\r\n */\r\n return {\r\n /** 当前列配置(响应式) */\r\n columns,\r\n\r\n /**\r\n * 主动设置列配置\r\n * 常用于:列设置弹窗 / 拖拽排序完成\r\n */\r\n setColumns(newColumns: any[]) {\r\n columns.value = mergeColumns(\r\n defaultColumns,\r\n newColumns\r\n )\r\n\r\n if (cacheKey) {\r\n storage.setItem(\r\n cacheKey,\r\n JSON.stringify(newColumns)\r\n )\r\n }\r\n },\r\n\r\n /**\r\n * 重置为默认列配置\r\n */\r\n resetColumns() {\r\n columns.value = defaultColumns\r\n\r\n if (cacheKey) {\r\n storage.removeItem(cacheKey)\r\n }\r\n }\r\n }\r\n}\r\n","<template>\r\n <el-table ref=\"tableRef\"\r\n v-bind=\"$attrs\"\r\n :data=\"data\"\r\n :row-key=\"rowKey\"\r\n class=\"smart_table\"\r\n v-loading=\"loading\">\r\n <TableColumn \r\n v-for=\"col in cachedColumns\" \r\n :key=\"col.key\" \r\n :col=\"col\" \r\n :permissions=\"permissions\"\r\n :pagination=\"pagination\"\r\n @cell-change=\"handleCellChange\"\r\n @cell-blur=\"handleCellBlur\"\r\n @cell-enter=\"handleCellEnter\"\r\n @cell-click=\"handleCellClick\">\r\n <template v-for=\"col in cachedColumns\" #[col.key]=\"slotProps\">\r\n <slot :name=\"col.key\" v-bind=\"slotProps\" />\r\n </template>\r\n </TableColumn>\r\n </el-table>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"SmartTable\">\r\n import { PropType, ref, watch } from 'vue'\r\n import TableColumn from './column/index.vue'\r\n import type { BaseColumn, ColumnConfig } from './types'\r\n import { useTableColumns } from \"./hooks/useTableColumns\"\r\n\r\n const props = defineProps({\r\n data: { type: Array, default: () => [] },\r\n columns: { type: Array, default: () => [] },\r\n rowKey: { type: String, default: 'id' },\r\n loading: { type: Boolean, default: false },\r\n permissions: {\r\n type: Array as PropType<string[]>,\r\n default: () => []\r\n },\r\n cacheKey: String,\r\n pagination: { type: Object, default: () => ({}) },\r\n\r\n })\r\n \r\n const emit = defineEmits([\r\n 'update:columns',\r\n 'cellChange',\r\n 'cellBlur',\r\n 'cellEnter',\r\n 'cell-click',\r\n ])\r\n\r\n // ------------------ columns 处理 ------------------\r\n const { columns: cachedColumns } = useTableColumns(props.columns, {\r\n cacheKey: props.cacheKey ?? '',\r\n })\r\n watch(\r\n cachedColumns,\r\n (val: ColumnConfig[]) => emit(\"update:columns\", val),\r\n { deep: true, immediate: true },\r\n )\r\n\r\n // ----------------事件封装 ------------------\r\n const handleCellChange = (row: any, key: string) => emit('cellChange', row, key)\r\n const handleCellBlur = (row: any, key: string) => {\r\n emit('cellBlur', row, key)\r\n }\r\n const handleCellEnter = (row: any, key: string) => {\r\n console.log('enter')\r\n emit('cellEnter', row, key)\r\n }\r\n \r\n // SmartTable\r\n const handleCellClick = (row: any, col: any) => {\r\n if(!col) return\r\n emit('cell-click', row, col)\r\n }\r\n\r\n // el-table\r\n const tableRef = ref();\r\n defineExpose({\r\n tableRef,\r\n });\r\n\r\n</script>\r\n\r\n<style>\r\n .smart_table {\r\n width: 100%;\r\n }\r\n \r\n .st_copy_wrapper:hover .st_copy_btn {\r\n display: inline-block !important;\r\n }\r\n\r\n .st_copy_btn:hover {\r\n transform: translateY(-50%) scale(1.1);\r\n }\r\n</style>\r\n","/**\r\n * 全局配置管理\r\n */\r\nimport type { SmartTableConfig } from './types'\r\nimport { getRendererManager } from './renderer'\r\n\r\n/**\r\n * 默认配置\r\n */\r\nconst defaultConfig: SmartTableConfig = {\r\n defaultPagination: {\r\n page: 1,\r\n size: 10,\r\n total: 0\r\n },\r\n defaultTableProps: {},\r\n defaultColumnProps: {}\r\n}\r\n\r\n/**\r\n * 全局配置类\r\n */\r\nclass ConfigManager {\r\n private config: SmartTableConfig = { ...defaultConfig }\r\n\r\n /**\r\n * 获取所有配置\r\n */\r\n getConfig(): SmartTableConfig {\r\n return { ...this.config }\r\n }\r\n\r\n /**\r\n * 设置配置\r\n */\r\n setConfig(config: Partial<SmartTableConfig>): void {\r\n this.config = this.mergeConfig(this.config, config)\r\n\r\n // 如果有自定义渲染器,自动注册\r\n if (config.renderers) {\r\n const manager = getRendererManager()\r\n manager.registerMultiple(config.renderers)\r\n }\r\n }\r\n\r\n /**\r\n * 获取特定配置项\r\n */\r\n get<K extends keyof SmartTableConfig>(key: K): SmartTableConfig[K] {\r\n return this.config[key]\r\n }\r\n\r\n /**\r\n * 重置为默认配置\r\n */\r\n reset(): void {\r\n this.config = { ...defaultConfig }\r\n }\r\n\r\n /**\r\n * 深度合并配置\r\n */\r\n private mergeConfig(target: any, source: any): any {\r\n const result = { ...target }\r\n\r\n for (const key in source) {\r\n if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {\r\n result[key] = this.mergeConfig(target[key] || {}, source[key])\r\n } else {\r\n result[key] = source[key]\r\n }\r\n }\r\n\r\n return result\r\n }\r\n}\r\n\r\n/**\r\n * 全局配置管理器单例\r\n */\r\nlet globalConfigManager: ConfigManager | null = null\r\n\r\n/**\r\n * 获取全局配置管理器\r\n */\r\nexport function getConfigManager(): ConfigManager {\r\n if (!globalConfigManager) {\r\n globalConfigManager = new ConfigManager()\r\n }\r\n return globalConfigManager\r\n}\r\n\r\n/**\r\n * 安装插件(用于 Vue.use())\r\n */\r\nexport interface SmartTablePlugin {\r\n install: (options?: SmartTableConfig) => void\r\n}\r\n\r\n/**\r\n * 创建插件实例\r\n */\r\nexport function createSmartTablePlugin(defaultOptions?: SmartTableConfig): SmartTablePlugin {\r\n return {\r\n install(options?: SmartTableConfig) {\r\n const manager = getConfigManager()\r\n const config = { ...defaultOptions, ...options }\r\n if (config) {\r\n manager.setConfig(config)\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 全局配置快捷方法\r\n */\r\nexport function setSmartTableConfig(config: Partial<SmartTableConfig>): void {\r\n getConfigManager().setConfig(config)\r\n}\r\n\r\nexport function getSmartTableConfig(): SmartTableConfig {\r\n return getConfigManager().getConfig()\r\n}\r\n","/**\r\n * 增强类型系统 - 提供更好的类型推断\r\n */\r\nimport type { ColumnConfig, RendererName } from '../components/SmartTable/types'\r\n\r\n/**\r\n * 提取行数据的类型\r\n */\r\nexport type ExtractRowType<T> = T extends ColumnConfig<infer R> ? R : never\r\n\r\n/**\r\n * 根据列配置提取表格数据类型\r\n */\r\nexport type TableDataFromColumns<T extends ColumnConfig[]> = T extends (infer C)[]\r\n ? C extends ColumnConfig<infer R>\r\n ? R\r\n : any\r\n : any\r\n\r\n/**\r\n * 渲染器 Props 类型推断\r\n */\r\nexport type InferRendererProps<T extends RendererName> =\r\n T extends 'html'\r\n ? { style?: string; class?: string; [key: string]: any }\r\n : T extends 'copy'\r\n ? { successText?: string; errorText?: string; iconColor?: string; [key: string]: any }\r\n : T extends 'img'\r\n ? { width?: string | number; height?: string | number; fit?: string; previewSrcList?: string[]; [key: string]: any }\r\n : T extends 'dict'\r\n ? { options: Array<{ label: string; value: string | number; listClass?: string; cssClass?: string }>; showValue?: boolean }\r\n : T extends 'map'\r\n ? { options: Record<string | number, any> }\r\n : T extends 'input'\r\n ? { placeholder?: string; size?: 'small' | 'default' | 'large'; clearable?: boolean }\r\n : T extends 'select'\r\n ? { options: Array<{ label: string; value: string | number }>; placeholder?: string; clearable?: boolean }\r\n : { [key: string]: any }\r\n\r\n/**\r\n * 快捷创建列的辅助函数(类型安全简化版)\r\n */\r\nexport function defineColumn(\r\n key: string,\r\n config?: Partial<Omit<ColumnConfig, 'key'>>\r\n): ColumnConfig {\r\n return {\r\n key,\r\n ...config\r\n } as ColumnConfig\r\n}\r\n"],"names":["RendererManager","__publicField","name","renderer","renderers","globalRendererManager","getRendererManager","wrapSFCComponent","comp","defineComponent","props","h","createFunctionalRenderer","render","validateRendererProps","rendererName","renderProps","getValueByPath","obj","path","acc","key","setValueByPath","value","keys","lastKey","target","__props","ref","watch","v","onBlur","_a","onEnter","_openBlock","_createBlock","_component_el_input","_mergeProps","$event","_component_el_input_number","onChange","_component_el_select","_createElementBlock","_Fragment","opt","_component_el_option","input","EditableInput","inputNumber","EditableNumber","select","EditableSelect","button","rp","val","ElButton","link","html","copy","butStyle","ElMessage","textarea","successful","DocumentCopy","img","imageList","item","defaultStyle","ElImage","CopyDocument","dict","options","showValue","values","matchedOptions","unmatched","children","_index","ElTag","map","isDataColumn","col","formatter","row","icon","builtInRenderers","registerBuiltInRenderers","registry","createRenderer","useOperationColumn","buttonConfigs","maxbtn","userPermissions","all_permission","hasPermi","permArray","p","hasAnyButton","computed","btn","optWidth","sum","isButtonVisible","optRowWidth","rows","max","emit","__emit","computeIndex","index","page","size","_b","toRefs","handleCellChange","handleCellBlur","handleCellEnter","handleCellClick","manager","allRenderers","r","hasAnyVisibleButton","getMaxOptWidth","getVisibleButtons","showOperationColumn","operationWidth","isDataOrOperationColumn","c","_unref","_component_el_table_column","_withCtx","$index","_createTextVNode","_toDisplayString","_renderList","_component_el_button","scope","$slots","_renderSlot","_ctx","_normalizeProps","_resolveDynamicComponent","_normalizeStyle","_normalizeClass","_hoisted_1","mergeColumns","defaultColumns","cacheColumns","cacheMap","cacheCol","useTableColumns","cacheKey","storage","cache","columns","newVal","lightColumns","newColumns","cachedColumns","tableRef","__expose","_withDirectives","_component_el_table","$attrs","TableColumn","slotProps","defaultConfig","ConfigManager","config","source","result","globalConfigManager","getConfigManager","setSmartTableConfig","getSmartTableConfig","defineColumn"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue3-smart-table",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "基于 Vue 3 + Element Plus 的高可复用表格组件库 - 插件化架构,支持自定义渲染器",
5
5
  "main": "dist/vue3-smart-table.cjs.js",
6
6
  "module": "dist/vue3-smart-table.es.js",
@@ -167,9 +167,4 @@ function isDataOrOperationColumn(c: ColumnConfig) {
167
167
  if (c.visible === false) return false
168
168
  return true
169
169
  }
170
- </script>
171
- <style>
172
- .st_copy_wrapper:hover .st_copy_btn {
173
- display: inline-block !important;
174
- }
175
- </style>
170
+ </script>
@@ -14,14 +14,7 @@ const defaultConfig: SmartTableConfig = {
14
14
  total: 0
15
15
  },
16
16
  defaultTableProps: {},
17
- defaultColumnProps: {},
18
- theme: {
19
- primaryColor: '#409EFF',
20
- successColor: '#67C23A',
21
- warningColor: '#E6A23C',
22
- dangerColor: '#F56C6C',
23
- infoColor: '#909399'
24
- }
17
+ defaultColumnProps: {}
25
18
  }
26
19
 
27
20
  /**
@@ -3,7 +3,7 @@
3
3
  v-bind="$attrs"
4
4
  :data="data"
5
5
  :row-key="rowKey"
6
- class="smart-table"
6
+ class="smart_table"
7
7
  v-loading="loading">
8
8
  <TableColumn
9
9
  v-for="col in cachedColumns"
@@ -84,8 +84,16 @@
84
84
 
85
85
  </script>
86
86
 
87
- <style scoped>
88
- .smart-table {
87
+ <style>
88
+ .smart_table {
89
89
  width: 100%;
90
90
  }
91
+
92
+ .st_copy_wrapper:hover .st_copy_btn {
93
+ display: inline-block !important;
94
+ }
95
+
96
+ .st_copy_btn:hover {
97
+ transform: translateY(-50%) scale(1.1);
98
+ }
91
99
  </style>
@@ -42,14 +42,6 @@ export interface SmartTableConfig {
42
42
  defaultTableProps?: Record<string, any>
43
43
  /** 默认列属性 */
44
44
  defaultColumnProps?: Record<string, any>
45
- /** 主题配置 */
46
- theme?: {
47
- primaryColor?: string
48
- successColor?: string
49
- warningColor?: string
50
- dangerColor?: string
51
- infoColor?: string
52
- }
53
45
  }
54
46
 
55
47
  /* ======================= 操作列按钮 ======================= */
@@ -1,206 +0,0 @@
1
- /**
2
- * SmartTable 主题样式
3
- * 使用 CSS 变量实现主题定制
4
- */
5
-
6
- :root {
7
- /* 默认主题色 - 可通过 CSS 变量覆盖 */
8
- --st-primary-color: #409EFF;
9
- --st-success-color: #67C23A;
10
- --st-warning-color: #E6A23C;
11
- --st-danger-color: #F56C6C;
12
- --st-info-color: #909399;
13
-
14
- /* 文本颜色 */
15
- --st-text-primary: #303133;
16
- --st-text-regular: #606266;
17
- --st-text-secondary: #909399;
18
- --st-text-placeholder: #C0C4CC;
19
-
20
- /* 边框颜色 */
21
- --st-border-color: #DCDFE6;
22
- --st-border-color-light: #E4E7ED;
23
- --st-border-color-lighter: #EBEEF5;
24
- --st-border-color-extra-light: #F2F6FC;
25
-
26
- /* 背景颜色 */
27
- --st-bg-color: #FFFFFF;
28
- --st-bg-color-page: #F2F3F5;
29
-
30
- /* 间距 */
31
- --st-spacing-xs: 4px;
32
- --st-spacing-sm: 8px;
33
- --st-spacing-md: 16px;
34
- --st-spacing-lg: 24px;
35
- --st-spacing-xl: 32px;
36
-
37
- /* 圆角 */
38
- --st-border-radius-sm: 2px;
39
- --st-border-radius-md: 4px;
40
- --st-border-radius-lg: 8px;
41
-
42
- /* 字体 */
43
- --st-font-size-xs: 12px;
44
- --st-font-size-sm: 14px;
45
- --st-font-size-md: 16px;
46
- --st-font-size-lg: 18px;
47
-
48
- /* 阴影 */
49
- --st-box-shadow-light: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
50
- --st-box-shadow-base: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
51
- --st-box-shadow-dark: 0 2px 8px rgba(0, 0, 0, .15);
52
- }
53
-
54
- /* ========== 表格样式 ========== */
55
- .smart-table {
56
- --st-table-border-color: var(--st-border-color-lighter);
57
- --st-table-header-bg: var(--st-bg-color);
58
- --st-table-row-hover-bg: var(--st-border-color-extra-light);
59
- --st-table-cell-padding: var(--st-spacing-md);
60
- }
61
-
62
- /* ========== 操作列样式 ========== */
63
- .st-operation-buttons {
64
- display: flex;
65
- gap: var(--st-spacing-sm);
66
- align-items: center;
67
- justify-content: center;
68
- }
69
-
70
- /* ========== 复制按钮样式 ========== */
71
- .st_copy_wrapper {
72
- position: relative;
73
- display: inline-block;
74
- width: 100%;
75
- }
76
-
77
- .st_copy_text {
78
- padding-right: 10px;
79
- display: block;
80
- overflow: hidden;
81
- text-overflow: ellipsis;
82
- white-space: nowrap;
83
- }
84
-
85
- .st_copy_btn {
86
- position: absolute;
87
- right: -5px;
88
- top: 50%;
89
- transform: translateY(-50%);
90
- cursor: pointer;
91
- display: none;
92
- font-size: 12px;
93
- color: var(--st-primary-color);
94
- user-select: none;
95
- transition: all 0.2s;
96
- }
97
-
98
- .st_copy_wrapper:hover .st_copy_btn {
99
- display: inline-block !important;
100
- }
101
-
102
- .st_copy_btn:hover {
103
- transform: translateY(-50%) scale(1.1);
104
- }
105
-
106
- /* ========== 图片样式 ========== */
107
- .st_img_wrapper {
108
- display: flex;
109
- align-items: center;
110
- position: relative;
111
- }
112
-
113
- .st_img_total {
114
- position: absolute;
115
- top: 0;
116
- right: 0;
117
- background: rgba(0, 0, 0, 0.5);
118
- color: white;
119
- padding: 2px 6px;
120
- border-radius: 10px;
121
- font-size: 12px;
122
- }
123
-
124
- /* ========== 文本截断 ========== */
125
- .line-clamp-1 {
126
- overflow: hidden;
127
- text-overflow: ellipsis;
128
- white-space: nowrap;
129
- }
130
-
131
- .line-clamp-2 {
132
- display: -webkit-box;
133
- -webkit-line-clamp: 2;
134
- -webkit-box-orient: vertical;
135
- overflow: hidden;
136
- text-overflow: ellipsis;
137
- }
138
-
139
- /* ========== 可编辑单元格样式 ========== */
140
- .st-editable-cell {
141
- padding: 0;
142
- }
143
-
144
- .st-editable-cell .el-input,
145
- .st-editable-cell .el-input-number,
146
- .st-editable-cell .el-select {
147
- width: 100%;
148
- }
149
-
150
- /* ========== 加载状态 ========== */
151
- .st-loading-overlay {
152
- position: absolute;
153
- top: 0;
154
- left: 0;
155
- right: 0;
156
- bottom: 0;
157
- background: rgba(255, 255, 255, 0.8);
158
- display: flex;
159
- align-items: center;
160
- justify-content: center;
161
- z-index: 1000;
162
- }
163
-
164
- /* ========== 空状态 ========== */
165
- .st-empty-state {
166
- padding: var(--st-spacing-xl);
167
- text-align: center;
168
- color: var(--st-text-secondary);
169
- }
170
-
171
- .st-empty-state__icon {
172
- font-size: 48px;
173
- margin-bottom: var(--st-spacing-md);
174
- opacity: 0.5;
175
- }
176
-
177
- .st-empty-state__text {
178
- font-size: var(--st-font-size-sm);
179
- }
180
-
181
- /* ========== 响应式 ========== */
182
- @media (max-width: 768px) {
183
- .smart-table {
184
- font-size: var(--st-font-size-xs);
185
- }
186
-
187
- .st-operation-buttons {
188
- flex-direction: column;
189
- gap: var(--st-spacing-xs);
190
- }
191
- }
192
-
193
- /* ========== 深色主题支持 ========== */
194
- @media (prefers-color-scheme: dark) {
195
- :root {
196
- --st-text-primary: #E5EAF3;
197
- --st-text-regular: #CFD3DC;
198
- --st-text-secondary: #A3A6AD;
199
- --st-border-color: #4C4D4F;
200
- --st-border-color-light: #414243;
201
- --st-border-color-lighter: #363637;
202
- --st-border-color-extra-light: #2B2B2C;
203
- --st-bg-color: #1D1E1F;
204
- --st-bg-color-page: #141414;
205
- }
206
- }