vue3-smart-table 2.1.2 → 2.1.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.
- package/dist/vue3-smart-table.cjs.js +1 -1
- package/dist/vue3-smart-table.cjs.js.map +1 -1
- package/dist/vue3-smart-table.es.js +144 -144
- package/dist/vue3-smart-table.es.js.map +1 -1
- package/dist/vue3-smart-table.umd.js +2 -2
- package/dist/vue3-smart-table.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/SmartTable/renderers/index.ts +21 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue3-smart-table.umd.js","sources":["../src/components/SmartTable/types.ts","../src/components/SmartTable/hooks/useTableColumns.ts","../src/components/SmartTable/hooks/useOperationColumn.ts","../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/config.ts","../src/components/SmartTable/index.vue","../src/types/enhanced.ts"],"sourcesContent":["import type { ButtonProps, TableColumnCtx } from 'element-plus'\r\nimport { DefaultRow } from 'element-plus/es/components/table/src/table/defaults'\r\nimport type { Component } from 'vue'\r\n\r\n// 导出验证函数类型\r\nexport type { validateRendererProps } from './renderer'\r\n\r\n/* ======================= 基础工具类型 ======================= */\r\n\r\n/** 支持额外参数(Element Plus 透传 props) */\r\nexport type WithRestProps<T> = T & {\r\n [key: string]: any\r\n}\r\n\r\n/* ======================= 渲染器系统 ======================= */\r\n\r\n/** Renderer 组件类型 */\r\nexport type Renderer = Component\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\nexport interface SmartTableConfig {\r\n /** 自定义渲染器 */\r\n renderers?: Record<string, Renderer>\r\n /** 默认分页配置 */\r\n defaultPagination?: {\r\n page?: number\r\n size?: number\r\n total?: number\r\n }\r\n /** 默认表格属性 */\r\n defaultTableProps?: Record<string, any>\r\n /** 默认列属性 */\r\n defaultColumnProps?: Record<string, any>\r\n}\r\n\r\n/* ======================= 分页配置 ======================= */\r\n\r\n/** 分页配置接口 */\r\nexport interface PaginationConfig {\r\n /** 当前页码 */\r\n page?: number\r\n /** 每页条数 */\r\n size?: number\r\n /** 总条数 */\r\n total?: number\r\n}\r\n\r\n/* ======================= 操作列按钮 ======================= */\r\n\r\nexport interface ButtonConfig<R = any> {\r\n permission?: string | string[]\r\n label: string\r\n type?: 'primary' | 'success' | 'warning' | 'danger' | 'info'\r\n action: (row: R) => void\r\n visible?: (row: R) => boolean\r\n width?: number\r\n}\r\n\r\n/* ======================= 列类型 ======================= */\r\n\r\n/**\r\n * 列类型枚举\r\n * 包含特殊列类型和渲染器类型\r\n */\r\nexport type ColumnType =\r\n // 特殊列\r\n | 'selection'\r\n | 'index'\r\n | 'operation'\r\n // 内置渲染器\r\n | 'input'\r\n | 'input-number'\r\n | 'select'\r\n | 'dict'\r\n | 'map'\r\n | 'img'\r\n | 'link'\r\n | 'button'\r\n | 'copy'\r\n | 'html'\r\n | 'formatter'\r\n | 'icon'\r\n | 'slot'\r\n\r\n/* ======================= Props 类型映射 ======================= */\r\n\r\n/** 各类型对应的 props */\r\nexport interface ColumnPropsMap {\r\n // 特殊列\r\n selection: {}\r\n index: {}\r\n operation: {}\r\n\r\n // 渲染器\r\n html: WithRestProps<{\r\n style?: string | Record<string, any>\r\n class?: string\r\n }>\r\n\r\n copy: WithRestProps<{\r\n iconColor?: string\r\n copyTitle?: string\r\n successText?: string\r\n errorText?: string\r\n lineClamp?: number\r\n textStyles?: Record<string, any>\r\n textClass?: string\r\n }>\r\n\r\n img: WithRestProps<{\r\n width?: string | number\r\n height?: string | number\r\n fit?: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down'\r\n previewSrcList?: string[]\r\n placeholder?: string\r\n style?: string | Record<string, any>\r\n }>\r\n\r\n dict: WithRestProps<{\r\n options: Array<{\r\n label: string\r\n value: string | number\r\n listClass?: string\r\n cssClass?: string\r\n tagProps?: Record<string, any>\r\n }>\r\n showValue?: boolean\r\n }>\r\n\r\n map: WithRestProps<{\r\n options: Record<string | number, any>\r\n }>\r\n\r\n formatter: WithRestProps<{}>\r\n\r\n icon: WithRestProps<{\r\n style?: string | Record<string, any>\r\n size?: number\r\n class?: string\r\n }>\r\n\r\n input: WithRestProps<{\r\n placeholder?: string\r\n size?: 'small' | 'default' | 'large'\r\n clearable?: boolean\r\n maxlength?: number\r\n showWordLimit?: boolean\r\n disabled?: boolean\r\n // 事件\r\n onChange?: (val: string, row: any, col: any) => void\r\n onBlur?: (e: FocusEvent, row: any, col: any) => void\r\n onFocus?: (e: FocusEvent, row: any, col: any) => void\r\n onInput?: (val: string, row: any, col: any) => void\r\n onClear?: (row: any, col: any) => void\r\n onEnter?: (e: KeyboardEvent, row: any, col: any) => void\r\n }>\r\n\r\n 'input-number': WithRestProps<{\r\n min?: number\r\n max?: number\r\n step?: number\r\n precision?: number\r\n size?: 'small' | 'default' | 'large'\r\n controls?: boolean\r\n disabled?: boolean\r\n // 事件\r\n onChange?: (val: number | undefined, oldVal: number | undefined, row: any, col: any) => void\r\n onBlur?: (e: FocusEvent, row: any, col: any) => void\r\n onFocus?: (e: FocusEvent, row: any, col: any) => void\r\n onEnter?: (e: KeyboardEvent, row: any, col: any) => void\r\n }>\r\n\r\n select: WithRestProps<{\r\n options: Array<{\r\n label: string\r\n value: string | number\r\n disabled?: boolean\r\n }>\r\n placeholder?: string\r\n size?: 'small' | 'default' | 'large'\r\n clearable?: boolean\r\n filterable?: boolean\r\n multiple?: boolean\r\n disabled?: boolean\r\n // 事件\r\n onChange?: (val: any, row: any, col: any) => void\r\n onBlur?: (e: FocusEvent, row: any, col: any) => void\r\n onFocus?: (e: FocusEvent, row: any, col: any) => void\r\n onVisibleChange?: (visible: boolean, row: any, col: any) => void\r\n onClear?: (row: any, col: any) => void\r\n }>\r\n\r\n button: WithRestProps<ButtonProps & {\r\n label?: string\r\n style?: string | Record<string, any>\r\n class?: string\r\n onClick?: (e: Event, row: any, col: any) => void\r\n }>\r\n\r\n link: WithRestProps<{\r\n label?: string\r\n href?: string\r\n blank?: boolean\r\n style?: string | Record<string, any>\r\n class?: string\r\n }>\r\n\r\n slot: {}\r\n}\r\n\r\n/* ======================= ColumnConfig ======================= */\r\n\r\n/** 列配置基础接口 */\r\nexport interface BaseColumnConfig<R extends DefaultRow = any> {\r\n /** 字段名 */\r\n key: string\r\n /** 列类型 */\r\n type?: ColumnType | string\r\n /** 列标题 */\r\n label?: string\r\n /** 是否显示 */\r\n visible?: boolean\r\n /** 是否在列控制中显示 */\r\n inControl?: boolean\r\n /** el-table-column 原生属性 */\r\n columnProps?: Partial<TableColumnCtx<R>>\r\n /** 插槽名称(type 为 slot 时使用,默认用 key) */\r\n slot?: string\r\n /** 渲染器/组件属性 */\r\n props?: Record<string, any>\r\n}\r\n\r\n/** Selection 列 */\r\nexport interface SelectionColumn<R extends DefaultRow = any> extends BaseColumnConfig<R> {\r\n type: 'selection'\r\n}\r\n\r\n/** Index 列 */\r\nexport interface IndexColumn<R extends DefaultRow = any> extends BaseColumnConfig<R> {\r\n type: 'index'\r\n}\r\n\r\n/** Operation 列 */\r\nexport interface OperationColumn<R extends DefaultRow = any> extends BaseColumnConfig<R> {\r\n type: 'operation'\r\n buttons: ButtonConfig<R>[]\r\n /** 最大显示按钮数 */\r\n maxbtn?: number\r\n}\r\n\r\n/** 数据列 */\r\nexport interface DataColumn<R extends DefaultRow = any> extends BaseColumnConfig<R> {\r\n type?: Exclude<ColumnType, 'selection' | 'index' | 'operation'> | string\r\n /**\r\n * 格式化函数(type 为 formatter 时使用)\r\n */\r\n formatter?: (value: any, row: R, index: number) => any\r\n}\r\n\r\n/** 列配置联合类型 */\r\nexport type ColumnConfig<R extends DefaultRow = any> =\r\n | SelectionColumn<R>\r\n | IndexColumn<R>\r\n | OperationColumn<R>\r\n | DataColumn<R>\r\n\r\n/* ======================= 组件 Props ======================= */\r\n\r\n/**\r\n * SmartTable 组件 Props 接口\r\n */\r\nexport interface SmartTableProps<R extends DefaultRow = any> {\r\n /** 表格数据 */\r\n data: R[]\r\n /** 列配置 */\r\n columns: ColumnConfig<R>[]\r\n /** 行数据的唯一标识字段,默认 'id' */\r\n rowKey?: string\r\n /** 是否显示加载状态 */\r\n loading?: boolean\r\n /** 权限列表,用于操作列按钮权限控制 */\r\n permissions?: string[]\r\n /** 列配置缓存 key,用于持久化列显隐配置 */\r\n cacheKey?: string\r\n /** 分页配置,用于序号列计算 */\r\n pagination?: PaginationConfig\r\n}\r\n\r\n/**\r\n * SmartTable 组件 Emits 接口\r\n */\r\nexport interface SmartTableEmits<R extends DefaultRow = any> {\r\n /** 列配置更新(v-model:columns) */\r\n (e: 'update:columns', columns: ColumnConfig<R>[]): void\r\n /** 单元格值变更 */\r\n (e: 'cellChange', row: R, col: ColumnConfig<R>): void\r\n /** 单元格失焦 */\r\n (e: 'cellBlur', row: R, col: ColumnConfig<R>): void\r\n /** 单元格回车 */\r\n (e: 'cellEnter', row: R, col: ColumnConfig<R>): void\r\n /** 单元格点击(button 类型) */\r\n (e: 'cellClick', row: R, col: ColumnConfig<R>): void\r\n}\r\n\r\n/* ======================= 辅助类型 ======================= */\r\n\r\n/** 特殊列类型 */\r\nexport type SpecialColumnType = 'selection' | 'index' | 'operation'\r\n\r\n/** 判断是否为特殊列 */\r\nexport function isSpecialColumn(type?: string): type is SpecialColumnType {\r\n return type === 'selection' || type === 'index' || type === 'operation'\r\n}\r\n\r\n/** 判断是否为渲染器类型 */\r\nexport function isRendererType(type?: string): boolean {\r\n if (!type) return false\r\n return !isSpecialColumn(type)\r\n}\r\n\r\n/** 判断是否为 operation 列 */\r\nexport function isOperationColumn<R extends DefaultRow = any>(col: ColumnConfig<R>): col is OperationColumn<R> {\r\n return col.type === 'operation'\r\n}\r\n","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","import { computed } from 'vue'\r\n\r\nimport { ButtonConfig } from \"../types\"\r\n\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 = 55\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 * 注意:这里不考虑 visible,因为没有 row 数据无法执行 visible 函数\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","/**\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', 'index', '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 index: number\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', 'index', '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>\r\n <el-input\r\n v-model=\"value\"\r\n v-bind=\"inputProps\"\r\n @blur=\"onBlur\"\r\n @focus=\"onFocus\"\r\n @change=\"onChange\"\r\n @input=\"onInput\"\r\n @keyup.enter=\"onEnter\"\r\n @clear=\"onClear\"\r\n />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch, computed } from 'vue'\r\nimport type { ColumnConfig } from '../types'\r\nimport { getValueByPath, setValueByPath } from '../utils/path'\r\n\r\ninterface Props {\r\n readonly row: any\r\n readonly col: ColumnConfig\r\n readonly index: number\r\n onCellChange?: (row: any, col: ColumnConfig) => void\r\n onCellBlur?: (row: any, col: ColumnConfig) => void\r\n onCellEnter?: (row: any, col: ColumnConfig) => void\r\n}\r\n\r\nconst props = defineProps<Props>()\r\nconst value = ref(getValueByPath(props.row, props.col.key))\r\n\r\n// 合并默认属性和用户自定义属性\r\nconst inputProps = computed(() => {\r\n const rp = props.col.props || {}\r\n const { onBlur, onFocus, onChange, onInput, onClear, onEnter, ...rest } = rp\r\n return {\r\n placeholder: '',\r\n size: 'small' as const,\r\n clearable: true,\r\n ...rest\r\n }\r\n})\r\n\r\nwatch(value, (v) => {\r\n setValueByPath(props.row, props.col.key, v)\r\n})\r\n\r\nconst onChange = (val: string) => {\r\n props.onCellChange?.(props.row, props.col)\r\n props.col.props?.onChange?.(val, props.row, props.col)\r\n}\r\n\r\nconst onBlur = (e: FocusEvent) => {\r\n props.onCellBlur?.(props.row, props.col)\r\n props.col.props?.onBlur?.(e, props.row, props.col)\r\n}\r\n\r\nconst onFocus = (e: FocusEvent) => {\r\n props.col.props?.onFocus?.(e, props.row, props.col)\r\n}\r\n\r\nconst onInput = (val: string) => {\r\n props.col.props?.onInput?.(val, props.row, props.col)\r\n}\r\n\r\nconst onEnter = (e: KeyboardEvent) => {\r\n props.onCellEnter?.(props.row, props.col)\r\n props.col.props?.onEnter?.(e, props.row, props.col)\r\n}\r\n\r\nconst onClear = () => {\r\n props.col.props?.onClear?.(props.row, props.col)\r\n}\r\n</script>\r\n","<template>\r\n <el-input-number\r\n v-model=\"value\"\r\n v-bind=\"inputProps\"\r\n @blur=\"onBlur\"\r\n @focus=\"onFocus\"\r\n @change=\"onChange\"\r\n @keyup.enter=\"onEnter\"\r\n />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch, computed } from 'vue'\r\nimport type { ColumnConfig } from '../types'\r\nimport { getValueByPath, setValueByPath } from '../utils/path'\r\n\r\ninterface Props {\r\n readonly row: any\r\n readonly col: ColumnConfig\r\n readonly index: number\r\n onCellChange?: (row: any, col: ColumnConfig) => void\r\n onCellBlur?: (row: any, col: ColumnConfig) => void\r\n onCellEnter?: (row: any, col: ColumnConfig) => void\r\n}\r\n\r\nconst props = defineProps<Props>()\r\nconst value = ref(getValueByPath(props.row, props.col.key))\r\n\r\n// 合并默认属性和用户自定义属性\r\nconst inputProps = computed(() => {\r\n const rp = props.col.props || {}\r\n const { onBlur, onFocus, onChange, onEnter, ...rest } = rp\r\n return {\r\n min: 0,\r\n max: 99999,\r\n controls: false,\r\n size: 'small' as const,\r\n ...rest\r\n }\r\n})\r\n\r\nwatch(value, (v) => {\r\n setValueByPath(props.row, props.col.key, v)\r\n})\r\n\r\nconst onChange = (val: number | undefined, oldVal: number | undefined) => {\r\n props.onCellChange?.(props.row, props.col)\r\n props.col.props?.onChange?.(val, oldVal, props.row, props.col)\r\n}\r\n\r\nconst onBlur = (e: FocusEvent) => {\r\n props.onCellBlur?.(props.row, props.col)\r\n props.col.props?.onBlur?.(e, props.row, props.col)\r\n}\r\n\r\nconst onFocus = (e: FocusEvent) => {\r\n props.col.props?.onFocus?.(e, props.row, props.col)\r\n}\r\n\r\nconst onEnter = (e: KeyboardEvent) => {\r\n props.onCellEnter?.(props.row, props.col)\r\n props.col.props?.onEnter?.(e, props.row, props.col)\r\n}\r\n</script>\r\n","<template>\r\n <el-select\r\n v-model=\"value\"\r\n v-bind=\"selectProps\"\r\n @change=\"onChange\"\r\n @blur=\"onBlur\"\r\n @focus=\"onFocus\"\r\n @visible-change=\"onVisibleChange\"\r\n @clear=\"onClear\"\r\n @keyup.enter=\"onEnter\"\r\n >\r\n <el-option\r\n v-for=\"opt in options\"\r\n :key=\"opt.value\"\r\n :label=\"opt.label\"\r\n :value=\"opt.value\"\r\n :disabled=\"opt.disabled\"\r\n />\r\n </el-select>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch, computed } from 'vue'\r\nimport type { ColumnConfig } from '../types'\r\nimport { getValueByPath, setValueByPath } from '../utils/path'\r\n\r\ninterface Props {\r\n readonly row: any\r\n readonly col: ColumnConfig\r\n readonly index: number\r\n onCellChange?: (row: any, col: ColumnConfig) => void\r\n onCellBlur?: (row: any, col: ColumnConfig) => void\r\n onCellEnter?: (row: any, col: ColumnConfig) => void\r\n}\r\n\r\nconst props = defineProps<Props>()\r\nconst value = ref(getValueByPath(props.row, props.col.key))\r\n\r\n// 合并默认属性和用户自定义属性\r\nconst selectProps = computed(() => {\r\n const rp = props.col.props || {}\r\n const { options, onChange, onBlur, onFocus, onVisibleChange, onClear, onEnter, ...rest } = rp\r\n return {\r\n placeholder: '请选择',\r\n size: 'small' as const,\r\n clearable: true,\r\n ...rest\r\n }\r\n})\r\n\r\n// 选项列表\r\nconst options = computed(() => {\r\n const rp = props.col.props || {}\r\n return rp.options || []\r\n})\r\n\r\nwatch(value, (v) => {\r\n setValueByPath(props.row, props.col.key, v)\r\n})\r\n\r\nconst onChange = (val: any) => {\r\n props.onCellChange?.(props.row, props.col)\r\n props.col.props?.onChange?.(val, props.row, props.col)\r\n}\r\n\r\nconst onBlur = (e: FocusEvent) => {\r\n props.onCellBlur?.(props.row, props.col)\r\n props.col.props?.onBlur?.(e, props.row, props.col)\r\n}\r\n\r\nconst onFocus = (e: FocusEvent) => {\r\n props.col.props?.onFocus?.(e, props.row, props.col)\r\n}\r\n\r\nconst onVisibleChange = (visible: boolean) => {\r\n props.col.props?.onVisibleChange?.(visible, props.row, props.col)\r\n}\r\n\r\nconst onClear = () => {\r\n props.col.props?.onClear?.(props.row, props.col)\r\n}\r\n\r\nconst onEnter = (e: KeyboardEvent) => {\r\n props.onCellEnter?.(props.row, props.col)\r\n props.col.props?.onEnter?.(e, props.row, props.col)\r\n}\r\n</script>\r\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 * 提取 props 中的事件(on 开头的属性)\r\n */\r\nconst extractEvents = (rp: Record<string, any>) => {\r\n const events: Record<string, any> = {}\r\n const props: Record<string, any> = {}\r\n \r\n Object.keys(rp).forEach(key => {\r\n if (key.startsWith('on') && typeof rp[key] === 'function') {\r\n events[key] = rp[key]\r\n } else {\r\n props[key] = rp[key]\r\n }\r\n })\r\n \r\n return { events, props }\r\n}\r\n\r\n/**\r\n * button 渲染�?\r\n */\r\nconst button = createFunctionalRenderer((props) => {\r\n const rp = props.col.props || {}\r\n const val = getValueByPath(props.row, props.col.key)\r\n const { events, props: restProps } = extractEvents(rp)\r\n \r\n return h(ElButton as any, {\r\n type: 'primary',\r\n ...restProps,\r\n ...events,\r\n onClick: (e: Event) => {\r\n props.onClick?.(props.row, props.col)\r\n // 支持用户自定�?onClick\r\n rp.onClick?.(e, props.row, props.col)\r\n }\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.props || {}\r\n const val = getValueByPath(props.row, props.col.key)\r\n const { href, blank, label, ...restProps } = rp\r\n \r\n return h('a', {\r\n href: href || val || '#',\r\n target: blank ? '_blank' : '_self',\r\n rel: blank ? 'noopener noreferrer' : undefined,\r\n style: 'color:#409EFF;cursor:pointer;text-decoration:none;',\r\n ...restProps,\r\n }, 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 const rp = props.col?.props || {}\r\n const { style, class: className, ...restProps } = rp\r\n \r\n return h('div', {\r\n class: className || 'line-clamp-2',\r\n style,\r\n innerHTML: val ?? '',\r\n ...restProps\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.props ?? {}\r\n const { iconColor, copyTitle, successText, errorText, lineClamp, textStyles, textClass, ...restProps } = rp\r\n \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': iconColor || '#409EFF',\r\n 'user-select': 'none'\r\n }\r\n const textStyleObj = {\r\n 'padding-right': '10px',\r\n 'display': '-webkit-box',\r\n '-webkit-box-orient': 'vertical',\r\n '-webkit-line-clamp': lineClamp ?? 2,\r\n 'overflow': 'hidden',\r\n ...textStyles\r\n }\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 ...restProps\r\n },\r\n [\r\n h('span', {\r\n class: `st_copy_text ${textClass ?? ''}`,\r\n style: textStyleObj,\r\n title: val\r\n }, val),\r\n val && h('span', {\r\n class: 'st_copy_btn',\r\n style: butStyle,\r\n title: 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(successText ?? '复制成功')\r\n }).catch(() => {\r\n ElMessage.error(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(successText ?? '复制成功')\r\n } else {\r\n ElMessage.error(errorText ?? '复制失败')\r\n }\r\n }\r\n } catch (err) {\r\n ElMessage.error(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?.props || {}\r\n const { width, height, fit, previewSrcList, placeholder, style, ...restProps } = rp\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 placeholder || ''\r\n }\r\n\r\n const defaultStyle = {\r\n width: width || '80px',\r\n height: height || '80px',\r\n marginRight: imageList.length > 1 ? '4px' : '0',\r\n ...(typeof style === 'object' ? style : {})\r\n }\r\n\r\n const imageProps = {\r\n previewSrcList: previewSrcList || imageList,\r\n previewTeleported: true, \r\n fit: fit || 'contain',\r\n style: defaultStyle,\r\n ...restProps\r\n }\r\n\r\n if (imageList.length === 1) {\r\n return h(ElImage, {\r\n src: imageList[0],\r\n ...imageProps\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 ...imageProps\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.props || {}\r\n const { options = [], showValue = false, ...restProps } = rp\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: string) => !options.some((opt: any) => String(opt.value) === v))\r\n\r\n const children = matchedOptions.map((item: any) => {\r\n const { listClass, cssClass, tagProps, ...itemRest } = item\r\n return h(\r\n ElTag,\r\n { \r\n key: item.value, \r\n type: listClass, \r\n class: cssClass, \r\n disableTransitions: true,\r\n ...restProps,\r\n ...tagProps\r\n },\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', { style: 'display: inline-flex; gap: 4px; flex-wrap: wrap;' }, 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 rp = props.col.props || {}\r\n const { options = {}, ...restProps } = rp\r\n const mappedVal = val != null ? options[val] ?? '' : ''\r\n \r\n return h('span', { ...restProps }, mappedVal)\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, index } = props\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const rp = props.col.props || {}\r\n \r\n let content = val\r\n if (isDataColumn(col)) {\r\n content = col.formatter?.(val, row, index) ?? val\r\n }\r\n \r\n return h('span', { ...rp }, content)\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.props || {}\r\n const { style, size, class: className, ...restProps } = rp\r\n \r\n if (!val) return ''\r\n \r\n const iconSize = size ? `${size}px` : '20px'\r\n \r\n // 判断网络图片\r\n if (/^https?:\\/\\//.test(val)) {\r\n return h(ElImage, {\r\n src: val,\r\n previewSrcList: [val],\r\n previewTeleported: true, \r\n fit: 'contain',\r\n style: { width: '40px', height: '40px', ...(typeof style === 'object' ? style : {}) },\r\n ...restProps\r\n })\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 class: className,\r\n style: { \r\n width: '40px', \r\n height: '40px', \r\n display: 'inline-block',\r\n ...(typeof style === 'object' ? style : {})\r\n },\r\n ...restProps\r\n })\r\n }\r\n \r\n // 默认当作 iconfont\r\n return h('i', {\r\n class: [val, className].filter(Boolean).join(' '),\r\n style: { \r\n fontSize: iconSize,\r\n ...(typeof style === 'object' ? style : {})\r\n },\r\n ...restProps\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","/**\r\n * 全局配置管理\r\n */\r\nimport type { SmartTableConfig } from './types'\r\nimport { getRendererManager } from './renderer'\r\nimport { registerBuiltInRenderers } from './renderers'\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 private _initialized = false\r\n\r\n /**\r\n * 是否已初始化\r\n */\r\n get initialized(): boolean {\r\n return this._initialized\r\n }\r\n\r\n /**\r\n * 初始化(注册内置渲染器)\r\n */\r\n init(): void {\r\n if (this._initialized) return\r\n registerBuiltInRenderers(getRendererManager())\r\n this._initialized = true\r\n }\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 // 初始化内置渲染器\r\n manager.init()\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","<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\r\n <template v-for=\"(col, idx) in visibleColumns\" :key=\"getColumnKey(col, idx)\">\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'\"\r\n :label=\"col.label || '操作'\"\r\n align=\"center\"\r\n v-bind=\"{\r\n ...col.columnProps,\r\n width: getOperationWidth(col)\r\n }\"\r\n >\r\n <template #default=\"{ row }\">\r\n <el-button\r\n v-for=\"btn in getVisibleButtons(col, 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 <!-- ========== 数据列 ========== -->\r\n <el-table-column\r\n v-else\r\n :prop=\"col.key\"\r\n :label=\"col.label\"\r\n align=\"center\"\r\n v-bind=\"col.columnProps || {}\"\r\n >\r\n <template #default=\"scope\">\r\n <!-- slot 类型 -->\r\n <template v-if=\"col.type === 'slot'\">\r\n <slot v-if=\"scope.$index >= 0\" :name=\"col.slot || col.key\" v-bind=\"scope\" />\r\n </template>\r\n\r\n <!-- 渲染器类型 -->\r\n <component\r\n v-else-if=\"col.type && renderer[col.type]\"\r\n :is=\"renderer[col.type]\"\r\n :row=\"scope.row\"\r\n :col=\"col\"\r\n :index=\"scope.$index\"\r\n :onCellChange=\"handleCellChange\"\r\n :onCellBlur=\"handleCellBlur\"\r\n :onCellEnter=\"handleCellEnter\"\r\n :onClick=\"handleCellClick\"\r\n />\r\n\r\n <!-- 默认文本 -->\r\n <span v-else\r\n :style=\"col.props?.style || ''\"\r\n :class=\"col.props?.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 </template>\r\n </el-table>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"SmartTable\">\r\n import { ref, watch, computed } from 'vue'\r\n import type { ColumnConfig, SmartTableProps, SmartTableEmits, OperationColumn } from './types'\r\n import { isSpecialColumn, isOperationColumn } from './types'\r\n import { useTableColumns } from \"./hooks/useTableColumns\"\r\n import { useOperationColumn } from './hooks/useOperationColumn'\r\n import { getRendererManager } from './renderer'\r\n import { getConfigManager } from './config'\r\n import { getValueByPath } from './utils/path'\r\n\r\n // Props 定义\r\n const props = withDefaults(defineProps<SmartTableProps>(), {\r\n data: () => [],\r\n columns: () => [],\r\n rowKey: 'id',\r\n loading: false,\r\n permissions: () => [],\r\n pagination: () => ({}),\r\n })\r\n\r\n // Emits 定义\r\n const emit = defineEmits<SmartTableEmits>()\r\n\r\n // ------------------ 初始化渲染器(仅首次) ------------------\r\n getConfigManager().init()\r\n\r\n // ------------------ columns 处理 ------------------\r\n const { columns: cachedColumns } = useTableColumns(props.columns, {\r\n cacheKey: props.cacheKey ?? '',\r\n })\r\n \r\n // 标记是否已初始化,避免初始化时触发不必要的更新\r\n const isInitialized = ref(false)\r\n watch(\r\n cachedColumns,\r\n (val: ColumnConfig[]) => {\r\n if (isInitialized.value) {\r\n emit(\"update:columns\", val)\r\n }\r\n isInitialized.value = true\r\n },\r\n { deep: true, immediate: true },\r\n )\r\n\r\n // ------------------ operation 列逻辑(需要在 visibleColumns 之前定义) ------------------\r\n // operation 列集合\r\n const operationColumns = computed(() =>\r\n cachedColumns.value.filter(col => col.type === 'operation')\r\n )\r\n\r\n // 为每个 operation 列创建 useOperationColumn 实例\r\n const operationColumnMap = computed(() => {\r\n const map = new Map<string, ReturnType<typeof useOperationColumn>>()\r\n\r\n operationColumns.value.forEach(col => {\r\n const hook = useOperationColumn(\r\n col.buttons || [],\r\n col.maxbtn ?? 10,\r\n props.permissions || []\r\n )\r\n map.set(col.key, hook)\r\n })\r\n\r\n return map\r\n })\r\n\r\n const getOperationColumnHook = (col: ColumnConfig) => {\r\n return operationColumnMap.value.get(col.key)\r\n }\r\n\r\n // 判断 operation 列是否应该显示\r\n const isOperationVisible = (col: ColumnConfig) => {\r\n if (!isOperationColumn(col)) return false\r\n \r\n const hook = getOperationColumnHook(col)\r\n if (!hook) return false\r\n\r\n const buttons = col.buttons || []\r\n if (!buttons.length) return false\r\n\r\n // 无数据时,只要有权限的按钮就显示\r\n if (!props.data?.length) return hook.hasAnyButton.value\r\n\r\n // 有数据时,检查是否至少有一行有可见按钮\r\n return hook.hasAnyVisibleButton(props.data)\r\n }\r\n\r\n const getOperationWidth = (col: ColumnConfig) => {\r\n const hook = getOperationColumnHook(col)\r\n if (!hook) return 0\r\n\r\n // 无行数据,用静态宽度\r\n if (!props.data?.length) return hook.optWidth.value\r\n // 有行数据,取最大宽度\r\n return hook.getMaxOptWidth(props.data)\r\n }\r\n\r\n const getVisibleButtons = (col: OperationColumn, row: any) => {\r\n const hook = getOperationColumnHook(col)\r\n if (!hook) return []\r\n\r\n const buttons = col.buttons || []\r\n if (!buttons.length) return []\r\n\r\n return hook.getVisibleButtons(row)\r\n }\r\n\r\n // ------------------ 列处理 ------------------\r\n \r\n // 可见列(按用户配置顺序)\r\n const visibleColumns = computed(() =>\r\n cachedColumns.value.filter(col => {\r\n // operation 列需要判断是否有可见按钮\r\n if (col.type === 'operation') {\r\n return isOperationVisible(col)\r\n }\r\n // selection/index 始终显示\r\n if (isSpecialColumn(col.type)) return true\r\n // 数据列根据 visible 控制\r\n return col.visible !== false\r\n })\r\n )\r\n\r\n // 生成列的唯一 key\r\n const getColumnKey = (col: ColumnConfig, idx: number) => {\r\n if (col.type === 'selection') return `selection-${idx}`\r\n if (col.type === 'index') return `index-${idx}`\r\n if (col.type === 'operation') return `operation-${col.key}-${idx}`\r\n return `${col.key}-${idx}`\r\n }\r\n\r\n // ------------------ index 列序号计算 ------------------\r\n const 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 // ------------------ renderer 获取 ------------------\r\n const renderer = computed(() => {\r\n const manager = getRendererManager()\r\n const allRenderers: Record<string, any> = {}\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 // ------------------ 事件封装 ------------------\r\n const handleCellChange = (row: any, col: ColumnConfig) => {\r\n emit('cellChange', row, col)\r\n }\r\n const handleCellBlur = (row: any, col: ColumnConfig) => {\r\n emit('cellBlur', row, col)\r\n }\r\n const handleCellEnter = (row: any, col: ColumnConfig) => {\r\n emit('cellEnter', row, col)\r\n }\r\n const handleCellClick = (row: any, col: ColumnConfig) => {\r\n if (!col) return\r\n emit('cellClick', 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 { ColumnConfig, ColumnType } 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 ColumnType> =\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":["isSpecialColumn","type","isRendererType","isOperationColumn","col","mergeColumns","defaultColumns","cacheColumns","cacheMap","c","cacheCol","useTableColumns","options","cacheKey","storage","cache","columns","ref","watch","newVal","lightColumns","newColumns","useOperationColumn","buttonConfigs","maxbtn","userPermissions","all_permission","hasPermi","value","permArray","p","hasAnyButton","computed","btn","optWidth","sum","isButtonVisible","row","optRowWidth","rows","max","RendererManager","__publicField","name","renderer","renderers","globalRendererManager","getRendererManager","wrapSFCComponent","comp","defineComponent","props","h","createFunctionalRenderer","render","validateRendererProps","rendererName","renderProps","getValueByPath","obj","path","acc","key","setValueByPath","keys","lastKey","target","__props","inputProps","rp","onBlur","onFocus","onChange","onInput","onClear","onEnter","rest","v","val","_a","_c","_b","e","_openBlock","_createBlock","_component_el_input","_mergeProps","$event","oldVal","_component_el_input_number","selectProps","onVisibleChange","visible","_component_el_select","_createElementBlock","_Fragment","_renderList","opt","_component_el_option","input","EditableInput","inputNumber","EditableNumber","select","EditableSelect","extractEvents","events","button","restProps","ElButton","link","href","blank","label","html","style","className","copy","iconColor","copyTitle","successText","errorText","lineClamp","textStyles","textClass","butStyle","textStyleObj","ElMessage","textarea","successful","DocumentCopy","img","width","height","fit","previewSrcList","placeholder","imageList","item","defaultStyle","imageProps","ElImage","CopyDocument","dict","showValue","values","matchedOptions","unmatched","children","listClass","cssClass","tagProps","itemRest","ElTag","map","mappedVal","isDataColumn","formatter","index","content","icon","size","iconSize","builtInRenderers","registerBuiltInRenderers","registry","createRenderer","defaultConfig","ConfigManager","config","source","result","globalConfigManager","getConfigManager","setSmartTableConfig","getSmartTableConfig","emit","__emit","cachedColumns","isInitialized","operationColumns","operationColumnMap","hook","getOperationColumnHook","isOperationVisible","getOperationWidth","getVisibleButtons","visibleColumns","getColumnKey","idx","computeIndex","page","manager","allRenderers","r","handleCellChange","handleCellBlur","handleCellEnter","handleCellClick","tableRef","__expose","_withDirectives","_component_el_table","$attrs","_component_el_table_column","_withCtx","$index","_createTextVNode","_toDisplayString","_component_el_button","scope","_renderSlot","_ctx","_resolveDynamicComponent","_normalizeStyle","_normalizeClass","_unref","_hoisted_1","defineColumn"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"vue3-smart-table.umd.js","sources":["../src/components/SmartTable/types.ts","../src/components/SmartTable/hooks/useTableColumns.ts","../src/components/SmartTable/hooks/useOperationColumn.ts","../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/config.ts","../src/components/SmartTable/index.vue","../src/types/enhanced.ts"],"sourcesContent":["import type { ButtonProps, TableColumnCtx } from 'element-plus'\r\nimport { DefaultRow } from 'element-plus/es/components/table/src/table/defaults'\r\nimport type { Component } from 'vue'\r\n\r\n// 导出验证函数类型\r\nexport type { validateRendererProps } from './renderer'\r\n\r\n/* ======================= 基础工具类型 ======================= */\r\n\r\n/** 支持额外参数(Element Plus 透传 props) */\r\nexport type WithRestProps<T> = T & {\r\n [key: string]: any\r\n}\r\n\r\n/* ======================= 渲染器系统 ======================= */\r\n\r\n/** Renderer 组件类型 */\r\nexport type Renderer = Component\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\nexport interface SmartTableConfig {\r\n /** 自定义渲染器 */\r\n renderers?: Record<string, Renderer>\r\n /** 默认分页配置 */\r\n defaultPagination?: {\r\n page?: number\r\n size?: number\r\n total?: number\r\n }\r\n /** 默认表格属性 */\r\n defaultTableProps?: Record<string, any>\r\n /** 默认列属性 */\r\n defaultColumnProps?: Record<string, any>\r\n}\r\n\r\n/* ======================= 分页配置 ======================= */\r\n\r\n/** 分页配置接口 */\r\nexport interface PaginationConfig {\r\n /** 当前页码 */\r\n page?: number\r\n /** 每页条数 */\r\n size?: number\r\n /** 总条数 */\r\n total?: number\r\n}\r\n\r\n/* ======================= 操作列按钮 ======================= */\r\n\r\nexport interface ButtonConfig<R = any> {\r\n permission?: string | string[]\r\n label: string\r\n type?: 'primary' | 'success' | 'warning' | 'danger' | 'info'\r\n action: (row: R) => void\r\n visible?: (row: R) => boolean\r\n width?: number\r\n}\r\n\r\n/* ======================= 列类型 ======================= */\r\n\r\n/**\r\n * 列类型枚举\r\n * 包含特殊列类型和渲染器类型\r\n */\r\nexport type ColumnType =\r\n // 特殊列\r\n | 'selection'\r\n | 'index'\r\n | 'operation'\r\n // 内置渲染器\r\n | 'input'\r\n | 'input-number'\r\n | 'select'\r\n | 'dict'\r\n | 'map'\r\n | 'img'\r\n | 'link'\r\n | 'button'\r\n | 'copy'\r\n | 'html'\r\n | 'formatter'\r\n | 'icon'\r\n | 'slot'\r\n\r\n/* ======================= Props 类型映射 ======================= */\r\n\r\n/** 各类型对应的 props */\r\nexport interface ColumnPropsMap {\r\n // 特殊列\r\n selection: {}\r\n index: {}\r\n operation: {}\r\n\r\n // 渲染器\r\n html: WithRestProps<{\r\n style?: string | Record<string, any>\r\n class?: string\r\n }>\r\n\r\n copy: WithRestProps<{\r\n iconColor?: string\r\n copyTitle?: string\r\n successText?: string\r\n errorText?: string\r\n lineClamp?: number\r\n textStyles?: Record<string, any>\r\n textClass?: string\r\n }>\r\n\r\n img: WithRestProps<{\r\n width?: string | number\r\n height?: string | number\r\n fit?: 'contain' | 'cover' | 'fill' | 'none' | 'scale-down'\r\n previewSrcList?: string[]\r\n placeholder?: string\r\n style?: string | Record<string, any>\r\n }>\r\n\r\n dict: WithRestProps<{\r\n options: Array<{\r\n label: string\r\n value: string | number\r\n listClass?: string\r\n cssClass?: string\r\n tagProps?: Record<string, any>\r\n }>\r\n showValue?: boolean\r\n }>\r\n\r\n map: WithRestProps<{\r\n options: Record<string | number, any>\r\n }>\r\n\r\n formatter: WithRestProps<{}>\r\n\r\n icon: WithRestProps<{\r\n style?: string | Record<string, any>\r\n size?: number\r\n class?: string\r\n }>\r\n\r\n input: WithRestProps<{\r\n placeholder?: string\r\n size?: 'small' | 'default' | 'large'\r\n clearable?: boolean\r\n maxlength?: number\r\n showWordLimit?: boolean\r\n disabled?: boolean\r\n // 事件\r\n onChange?: (val: string, row: any, col: any) => void\r\n onBlur?: (e: FocusEvent, row: any, col: any) => void\r\n onFocus?: (e: FocusEvent, row: any, col: any) => void\r\n onInput?: (val: string, row: any, col: any) => void\r\n onClear?: (row: any, col: any) => void\r\n onEnter?: (e: KeyboardEvent, row: any, col: any) => void\r\n }>\r\n\r\n 'input-number': WithRestProps<{\r\n min?: number\r\n max?: number\r\n step?: number\r\n precision?: number\r\n size?: 'small' | 'default' | 'large'\r\n controls?: boolean\r\n disabled?: boolean\r\n // 事件\r\n onChange?: (val: number | undefined, oldVal: number | undefined, row: any, col: any) => void\r\n onBlur?: (e: FocusEvent, row: any, col: any) => void\r\n onFocus?: (e: FocusEvent, row: any, col: any) => void\r\n onEnter?: (e: KeyboardEvent, row: any, col: any) => void\r\n }>\r\n\r\n select: WithRestProps<{\r\n options: Array<{\r\n label: string\r\n value: string | number\r\n disabled?: boolean\r\n }>\r\n placeholder?: string\r\n size?: 'small' | 'default' | 'large'\r\n clearable?: boolean\r\n filterable?: boolean\r\n multiple?: boolean\r\n disabled?: boolean\r\n // 事件\r\n onChange?: (val: any, row: any, col: any) => void\r\n onBlur?: (e: FocusEvent, row: any, col: any) => void\r\n onFocus?: (e: FocusEvent, row: any, col: any) => void\r\n onVisibleChange?: (visible: boolean, row: any, col: any) => void\r\n onClear?: (row: any, col: any) => void\r\n }>\r\n\r\n button: WithRestProps<ButtonProps & {\r\n label?: string\r\n style?: string | Record<string, any>\r\n class?: string\r\n onClick?: (e: Event, row: any, col: any) => void\r\n }>\r\n\r\n link: WithRestProps<{\r\n label?: string\r\n href?: string\r\n blank?: boolean\r\n style?: string | Record<string, any>\r\n class?: string\r\n }>\r\n\r\n slot: {}\r\n}\r\n\r\n/* ======================= ColumnConfig ======================= */\r\n\r\n/** 列配置基础接口 */\r\nexport interface BaseColumnConfig<R extends DefaultRow = any> {\r\n /** 字段名 */\r\n key: string\r\n /** 列类型 */\r\n type?: ColumnType | string\r\n /** 列标题 */\r\n label?: string\r\n /** 是否显示 */\r\n visible?: boolean\r\n /** 是否在列控制中显示 */\r\n inControl?: boolean\r\n /** el-table-column 原生属性 */\r\n columnProps?: Partial<TableColumnCtx<R>>\r\n /** 插槽名称(type 为 slot 时使用,默认用 key) */\r\n slot?: string\r\n /** 渲染器/组件属性 */\r\n props?: Record<string, any>\r\n}\r\n\r\n/** Selection 列 */\r\nexport interface SelectionColumn<R extends DefaultRow = any> extends BaseColumnConfig<R> {\r\n type: 'selection'\r\n}\r\n\r\n/** Index 列 */\r\nexport interface IndexColumn<R extends DefaultRow = any> extends BaseColumnConfig<R> {\r\n type: 'index'\r\n}\r\n\r\n/** Operation 列 */\r\nexport interface OperationColumn<R extends DefaultRow = any> extends BaseColumnConfig<R> {\r\n type: 'operation'\r\n buttons: ButtonConfig<R>[]\r\n /** 最大显示按钮数 */\r\n maxbtn?: number\r\n}\r\n\r\n/** 数据列 */\r\nexport interface DataColumn<R extends DefaultRow = any> extends BaseColumnConfig<R> {\r\n type?: Exclude<ColumnType, 'selection' | 'index' | 'operation'> | string\r\n /**\r\n * 格式化函数(type 为 formatter 时使用)\r\n */\r\n formatter?: (value: any, row: R, index: number) => any\r\n}\r\n\r\n/** 列配置联合类型 */\r\nexport type ColumnConfig<R extends DefaultRow = any> =\r\n | SelectionColumn<R>\r\n | IndexColumn<R>\r\n | OperationColumn<R>\r\n | DataColumn<R>\r\n\r\n/* ======================= 组件 Props ======================= */\r\n\r\n/**\r\n * SmartTable 组件 Props 接口\r\n */\r\nexport interface SmartTableProps<R extends DefaultRow = any> {\r\n /** 表格数据 */\r\n data: R[]\r\n /** 列配置 */\r\n columns: ColumnConfig<R>[]\r\n /** 行数据的唯一标识字段,默认 'id' */\r\n rowKey?: string\r\n /** 是否显示加载状态 */\r\n loading?: boolean\r\n /** 权限列表,用于操作列按钮权限控制 */\r\n permissions?: string[]\r\n /** 列配置缓存 key,用于持久化列显隐配置 */\r\n cacheKey?: string\r\n /** 分页配置,用于序号列计算 */\r\n pagination?: PaginationConfig\r\n}\r\n\r\n/**\r\n * SmartTable 组件 Emits 接口\r\n */\r\nexport interface SmartTableEmits<R extends DefaultRow = any> {\r\n /** 列配置更新(v-model:columns) */\r\n (e: 'update:columns', columns: ColumnConfig<R>[]): void\r\n /** 单元格值变更 */\r\n (e: 'cellChange', row: R, col: ColumnConfig<R>): void\r\n /** 单元格失焦 */\r\n (e: 'cellBlur', row: R, col: ColumnConfig<R>): void\r\n /** 单元格回车 */\r\n (e: 'cellEnter', row: R, col: ColumnConfig<R>): void\r\n /** 单元格点击(button 类型) */\r\n (e: 'cellClick', row: R, col: ColumnConfig<R>): void\r\n}\r\n\r\n/* ======================= 辅助类型 ======================= */\r\n\r\n/** 特殊列类型 */\r\nexport type SpecialColumnType = 'selection' | 'index' | 'operation'\r\n\r\n/** 判断是否为特殊列 */\r\nexport function isSpecialColumn(type?: string): type is SpecialColumnType {\r\n return type === 'selection' || type === 'index' || type === 'operation'\r\n}\r\n\r\n/** 判断是否为渲染器类型 */\r\nexport function isRendererType(type?: string): boolean {\r\n if (!type) return false\r\n return !isSpecialColumn(type)\r\n}\r\n\r\n/** 判断是否为 operation 列 */\r\nexport function isOperationColumn<R extends DefaultRow = any>(col: ColumnConfig<R>): col is OperationColumn<R> {\r\n return col.type === 'operation'\r\n}\r\n","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","import { computed } from 'vue'\r\n\r\nimport { ButtonConfig } from \"../types\"\r\n\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 = 55\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 * 注意:这里不考虑 visible,因为没有 row 数据无法执行 visible 函数\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","/**\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', 'index', '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 index: number\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', 'index', '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>\r\n <el-input\r\n v-model=\"value\"\r\n v-bind=\"inputProps\"\r\n @blur=\"onBlur\"\r\n @focus=\"onFocus\"\r\n @change=\"onChange\"\r\n @input=\"onInput\"\r\n @keyup.enter=\"onEnter\"\r\n @clear=\"onClear\"\r\n />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch, computed } from 'vue'\r\nimport type { ColumnConfig } from '../types'\r\nimport { getValueByPath, setValueByPath } from '../utils/path'\r\n\r\ninterface Props {\r\n readonly row: any\r\n readonly col: ColumnConfig\r\n readonly index: number\r\n onCellChange?: (row: any, col: ColumnConfig) => void\r\n onCellBlur?: (row: any, col: ColumnConfig) => void\r\n onCellEnter?: (row: any, col: ColumnConfig) => void\r\n}\r\n\r\nconst props = defineProps<Props>()\r\nconst value = ref(getValueByPath(props.row, props.col.key))\r\n\r\n// 合并默认属性和用户自定义属性\r\nconst inputProps = computed(() => {\r\n const rp = props.col.props || {}\r\n const { onBlur, onFocus, onChange, onInput, onClear, onEnter, ...rest } = rp\r\n return {\r\n placeholder: '',\r\n size: 'small' as const,\r\n clearable: true,\r\n ...rest\r\n }\r\n})\r\n\r\nwatch(value, (v) => {\r\n setValueByPath(props.row, props.col.key, v)\r\n})\r\n\r\nconst onChange = (val: string) => {\r\n props.onCellChange?.(props.row, props.col)\r\n props.col.props?.onChange?.(val, props.row, props.col)\r\n}\r\n\r\nconst onBlur = (e: FocusEvent) => {\r\n props.onCellBlur?.(props.row, props.col)\r\n props.col.props?.onBlur?.(e, props.row, props.col)\r\n}\r\n\r\nconst onFocus = (e: FocusEvent) => {\r\n props.col.props?.onFocus?.(e, props.row, props.col)\r\n}\r\n\r\nconst onInput = (val: string) => {\r\n props.col.props?.onInput?.(val, props.row, props.col)\r\n}\r\n\r\nconst onEnter = (e: KeyboardEvent) => {\r\n props.onCellEnter?.(props.row, props.col)\r\n props.col.props?.onEnter?.(e, props.row, props.col)\r\n}\r\n\r\nconst onClear = () => {\r\n props.col.props?.onClear?.(props.row, props.col)\r\n}\r\n</script>\r\n","<template>\r\n <el-input-number\r\n v-model=\"value\"\r\n v-bind=\"inputProps\"\r\n @blur=\"onBlur\"\r\n @focus=\"onFocus\"\r\n @change=\"onChange\"\r\n @keyup.enter=\"onEnter\"\r\n />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch, computed } from 'vue'\r\nimport type { ColumnConfig } from '../types'\r\nimport { getValueByPath, setValueByPath } from '../utils/path'\r\n\r\ninterface Props {\r\n readonly row: any\r\n readonly col: ColumnConfig\r\n readonly index: number\r\n onCellChange?: (row: any, col: ColumnConfig) => void\r\n onCellBlur?: (row: any, col: ColumnConfig) => void\r\n onCellEnter?: (row: any, col: ColumnConfig) => void\r\n}\r\n\r\nconst props = defineProps<Props>()\r\nconst value = ref(getValueByPath(props.row, props.col.key))\r\n\r\n// 合并默认属性和用户自定义属性\r\nconst inputProps = computed(() => {\r\n const rp = props.col.props || {}\r\n const { onBlur, onFocus, onChange, onEnter, ...rest } = rp\r\n return {\r\n min: 0,\r\n max: 99999,\r\n controls: false,\r\n size: 'small' as const,\r\n ...rest\r\n }\r\n})\r\n\r\nwatch(value, (v) => {\r\n setValueByPath(props.row, props.col.key, v)\r\n})\r\n\r\nconst onChange = (val: number | undefined, oldVal: number | undefined) => {\r\n props.onCellChange?.(props.row, props.col)\r\n props.col.props?.onChange?.(val, oldVal, props.row, props.col)\r\n}\r\n\r\nconst onBlur = (e: FocusEvent) => {\r\n props.onCellBlur?.(props.row, props.col)\r\n props.col.props?.onBlur?.(e, props.row, props.col)\r\n}\r\n\r\nconst onFocus = (e: FocusEvent) => {\r\n props.col.props?.onFocus?.(e, props.row, props.col)\r\n}\r\n\r\nconst onEnter = (e: KeyboardEvent) => {\r\n props.onCellEnter?.(props.row, props.col)\r\n props.col.props?.onEnter?.(e, props.row, props.col)\r\n}\r\n</script>\r\n","<template>\r\n <el-select\r\n v-model=\"value\"\r\n v-bind=\"selectProps\"\r\n @change=\"onChange\"\r\n @blur=\"onBlur\"\r\n @focus=\"onFocus\"\r\n @visible-change=\"onVisibleChange\"\r\n @clear=\"onClear\"\r\n @keyup.enter=\"onEnter\"\r\n >\r\n <el-option\r\n v-for=\"opt in options\"\r\n :key=\"opt.value\"\r\n :label=\"opt.label\"\r\n :value=\"opt.value\"\r\n :disabled=\"opt.disabled\"\r\n />\r\n </el-select>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch, computed } from 'vue'\r\nimport type { ColumnConfig } from '../types'\r\nimport { getValueByPath, setValueByPath } from '../utils/path'\r\n\r\ninterface Props {\r\n readonly row: any\r\n readonly col: ColumnConfig\r\n readonly index: number\r\n onCellChange?: (row: any, col: ColumnConfig) => void\r\n onCellBlur?: (row: any, col: ColumnConfig) => void\r\n onCellEnter?: (row: any, col: ColumnConfig) => void\r\n}\r\n\r\nconst props = defineProps<Props>()\r\nconst value = ref(getValueByPath(props.row, props.col.key))\r\n\r\n// 合并默认属性和用户自定义属性\r\nconst selectProps = computed(() => {\r\n const rp = props.col.props || {}\r\n const { options, onChange, onBlur, onFocus, onVisibleChange, onClear, onEnter, ...rest } = rp\r\n return {\r\n placeholder: '请选择',\r\n size: 'small' as const,\r\n clearable: true,\r\n ...rest\r\n }\r\n})\r\n\r\n// 选项列表\r\nconst options = computed(() => {\r\n const rp = props.col.props || {}\r\n return rp.options || []\r\n})\r\n\r\nwatch(value, (v) => {\r\n setValueByPath(props.row, props.col.key, v)\r\n})\r\n\r\nconst onChange = (val: any) => {\r\n props.onCellChange?.(props.row, props.col)\r\n props.col.props?.onChange?.(val, props.row, props.col)\r\n}\r\n\r\nconst onBlur = (e: FocusEvent) => {\r\n props.onCellBlur?.(props.row, props.col)\r\n props.col.props?.onBlur?.(e, props.row, props.col)\r\n}\r\n\r\nconst onFocus = (e: FocusEvent) => {\r\n props.col.props?.onFocus?.(e, props.row, props.col)\r\n}\r\n\r\nconst onVisibleChange = (visible: boolean) => {\r\n props.col.props?.onVisibleChange?.(visible, props.row, props.col)\r\n}\r\n\r\nconst onClear = () => {\r\n props.col.props?.onClear?.(props.row, props.col)\r\n}\r\n\r\nconst onEnter = (e: KeyboardEvent) => {\r\n props.onCellEnter?.(props.row, props.col)\r\n props.col.props?.onEnter?.(e, props.row, props.col)\r\n}\r\n</script>\r\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\nconst normalizeCssSize = (size: string | number | undefined, fallback: string) => {\r\n if (size === undefined || size === null || size === '') return fallback\r\n return typeof size === 'number' ? size + 'px' : size\r\n}\r\n\r\n\r\n/**\r\n * 提取 props 中的事件(on 开头的属性)\r\n */\r\nconst extractEvents = (rp: Record<string, any>) => {\r\n const events: Record<string, any> = {}\r\n const props: Record<string, any> = {}\r\n \r\n Object.keys(rp).forEach(key => {\r\n if (key.startsWith('on') && typeof rp[key] === 'function') {\r\n events[key] = rp[key]\r\n } else {\r\n props[key] = rp[key]\r\n }\r\n })\r\n \r\n return { events, props }\r\n}\r\n\r\n/**\r\n * button 渲染�?\r\n */\r\nconst button = createFunctionalRenderer((props) => {\r\n const rp = props.col.props || {}\r\n const val = getValueByPath(props.row, props.col.key)\r\n const { events, props: restProps } = extractEvents(rp)\r\n \r\n return h(ElButton as any, {\r\n type: 'primary',\r\n ...restProps,\r\n ...events,\r\n onClick: (e: Event) => {\r\n props.onClick?.(props.row, props.col)\r\n // 支持用户自定�?onClick\r\n rp.onClick?.(e, props.row, props.col)\r\n }\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.props || {}\r\n const val = getValueByPath(props.row, props.col.key)\r\n const { href, blank, label, ...restProps } = rp\r\n \r\n return h('a', {\r\n href: href || val || '#',\r\n target: blank ? '_blank' : '_self',\r\n rel: blank ? 'noopener noreferrer' : undefined,\r\n style: 'color:#409EFF;cursor:pointer;text-decoration:none;',\r\n ...restProps,\r\n }, 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 const rp = props.col?.props || {}\r\n const { style, class: className, ...restProps } = rp\r\n \r\n return h('div', {\r\n class: className || 'line-clamp-2',\r\n style,\r\n innerHTML: val ?? '',\r\n ...restProps\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.props ?? {}\r\n const { iconColor, copyTitle, successText, errorText, lineClamp, textStyles, textClass, ...restProps } = rp\r\n \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': iconColor || '#409EFF',\r\n 'user-select': 'none'\r\n }\r\n const textStyleObj = {\r\n 'padding-right': '10px',\r\n 'display': '-webkit-box',\r\n '-webkit-box-orient': 'vertical',\r\n '-webkit-line-clamp': lineClamp ?? 2,\r\n 'overflow': 'hidden',\r\n ...textStyles\r\n }\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 ...restProps\r\n },\r\n [\r\n h('span', {\r\n class: `st_copy_text ${textClass ?? ''}`,\r\n style: textStyleObj,\r\n title: val\r\n }, val),\r\n val && h('span', {\r\n class: 'st_copy_btn',\r\n style: butStyle,\r\n title: 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(successText ?? '复制成功')\r\n }).catch(() => {\r\n ElMessage.error(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(successText ?? '复制成功')\r\n } else {\r\n ElMessage.error(errorText ?? '复制失败')\r\n }\r\n }\r\n } catch (err) {\r\n ElMessage.error(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?.props || {}\r\n const { width, height, fit, previewSrcList, placeholder, style, ...restProps } = rp\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 placeholder || ''\r\n }\r\n\r\n const defaultStyle = {\r\n width: normalizeCssSize(width, '80px'),\r\n height: normalizeCssSize(height, '80px'),\r\n marginRight: imageList.length > 1 ? '4px' : '0',\r\n ...(typeof style === 'object' ? style : {})\r\n }\r\n\r\n const imageProps = {\r\n previewSrcList: previewSrcList || imageList,\r\n previewTeleported: true, \r\n fit: fit || 'contain',\r\n style: defaultStyle,\r\n ...restProps\r\n }\r\n\r\n if (imageList.length === 1) {\r\n return h(ElImage, {\r\n src: imageList[0],\r\n ...imageProps\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 ...imageProps\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.props || {}\r\n const { options = [], showValue = false, ...restProps } = rp\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: string) => !options.some((opt: any) => String(opt.value) === v))\r\n\r\n const children = matchedOptions.map((item: any) => {\r\n const { listClass, cssClass, tagProps, ...itemRest } = item\r\n return h(\r\n ElTag,\r\n { \r\n key: item.value, \r\n type: listClass, \r\n class: cssClass, \r\n disableTransitions: true,\r\n ...restProps,\r\n ...tagProps\r\n },\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', { style: 'display: inline-flex; gap: 4px; flex-wrap: wrap;' }, 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 rp = props.col.props || {}\r\n const { options = {}, ...restProps } = rp\r\n const mappedVal = val != null ? options[val] ?? '' : ''\r\n \r\n return h('span', { ...restProps }, mappedVal)\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, index } = props\r\n const val = getValueByPath(props.row, props.col.key) ?? ''\r\n const rp = props.col.props || {}\r\n \r\n let content = val\r\n if (isDataColumn(col)) {\r\n content = col.formatter?.(val, row, index) ?? val\r\n }\r\n \r\n return h('span', { ...rp }, content)\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.props || {}\r\n const { style, size, class: className, ...restProps } = rp\r\n \r\n if (!val) return ''\r\n \r\n const iconSize = size ? `${size}px` : '20px'\r\n \r\n // 判断网络图片\r\n if (/^https?:\\/\\//.test(val)) {\r\n return h(ElImage, {\r\n src: val,\r\n previewSrcList: [val],\r\n previewTeleported: true, \r\n fit: 'contain',\r\n style: { width: '40px', height: '40px', ...(typeof style === 'object' ? style : {}) },\r\n ...restProps\r\n })\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 class: className,\r\n style: { \r\n width: '40px', \r\n height: '40px', \r\n display: 'inline-block',\r\n ...(typeof style === 'object' ? style : {})\r\n },\r\n ...restProps\r\n })\r\n }\r\n \r\n // 默认当作 iconfont\r\n return h('i', {\r\n class: [val, className].filter(Boolean).join(' '),\r\n style: { \r\n fontSize: iconSize,\r\n ...(typeof style === 'object' ? style : {})\r\n },\r\n ...restProps\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","/**\r\n * 全局配置管理\r\n */\r\nimport type { SmartTableConfig } from './types'\r\nimport { getRendererManager } from './renderer'\r\nimport { registerBuiltInRenderers } from './renderers'\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 private _initialized = false\r\n\r\n /**\r\n * 是否已初始化\r\n */\r\n get initialized(): boolean {\r\n return this._initialized\r\n }\r\n\r\n /**\r\n * 初始化(注册内置渲染器)\r\n */\r\n init(): void {\r\n if (this._initialized) return\r\n registerBuiltInRenderers(getRendererManager())\r\n this._initialized = true\r\n }\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 // 初始化内置渲染器\r\n manager.init()\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","<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\r\n <template v-for=\"(col, idx) in visibleColumns\" :key=\"getColumnKey(col, idx)\">\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'\"\r\n :label=\"col.label || '操作'\"\r\n align=\"center\"\r\n v-bind=\"{\r\n ...col.columnProps,\r\n width: getOperationWidth(col)\r\n }\"\r\n >\r\n <template #default=\"{ row }\">\r\n <el-button\r\n v-for=\"btn in getVisibleButtons(col, 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 <!-- ========== 数据列 ========== -->\r\n <el-table-column\r\n v-else\r\n :prop=\"col.key\"\r\n :label=\"col.label\"\r\n align=\"center\"\r\n v-bind=\"col.columnProps || {}\"\r\n >\r\n <template #default=\"scope\">\r\n <!-- slot 类型 -->\r\n <template v-if=\"col.type === 'slot'\">\r\n <slot v-if=\"scope.$index >= 0\" :name=\"col.slot || col.key\" v-bind=\"scope\" />\r\n </template>\r\n\r\n <!-- 渲染器类型 -->\r\n <component\r\n v-else-if=\"col.type && renderer[col.type]\"\r\n :is=\"renderer[col.type]\"\r\n :row=\"scope.row\"\r\n :col=\"col\"\r\n :index=\"scope.$index\"\r\n :onCellChange=\"handleCellChange\"\r\n :onCellBlur=\"handleCellBlur\"\r\n :onCellEnter=\"handleCellEnter\"\r\n :onClick=\"handleCellClick\"\r\n />\r\n\r\n <!-- 默认文本 -->\r\n <span v-else\r\n :style=\"col.props?.style || ''\"\r\n :class=\"col.props?.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 </template>\r\n </el-table>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"SmartTable\">\r\n import { ref, watch, computed } from 'vue'\r\n import type { ColumnConfig, SmartTableProps, SmartTableEmits, OperationColumn } from './types'\r\n import { isSpecialColumn, isOperationColumn } from './types'\r\n import { useTableColumns } from \"./hooks/useTableColumns\"\r\n import { useOperationColumn } from './hooks/useOperationColumn'\r\n import { getRendererManager } from './renderer'\r\n import { getConfigManager } from './config'\r\n import { getValueByPath } from './utils/path'\r\n\r\n // Props 定义\r\n const props = withDefaults(defineProps<SmartTableProps>(), {\r\n data: () => [],\r\n columns: () => [],\r\n rowKey: 'id',\r\n loading: false,\r\n permissions: () => [],\r\n pagination: () => ({}),\r\n })\r\n\r\n // Emits 定义\r\n const emit = defineEmits<SmartTableEmits>()\r\n\r\n // ------------------ 初始化渲染器(仅首次) ------------------\r\n getConfigManager().init()\r\n\r\n // ------------------ columns 处理 ------------------\r\n const { columns: cachedColumns } = useTableColumns(props.columns, {\r\n cacheKey: props.cacheKey ?? '',\r\n })\r\n \r\n // 标记是否已初始化,避免初始化时触发不必要的更新\r\n const isInitialized = ref(false)\r\n watch(\r\n cachedColumns,\r\n (val: ColumnConfig[]) => {\r\n if (isInitialized.value) {\r\n emit(\"update:columns\", val)\r\n }\r\n isInitialized.value = true\r\n },\r\n { deep: true, immediate: true },\r\n )\r\n\r\n // ------------------ operation 列逻辑(需要在 visibleColumns 之前定义) ------------------\r\n // operation 列集合\r\n const operationColumns = computed(() =>\r\n cachedColumns.value.filter(col => col.type === 'operation')\r\n )\r\n\r\n // 为每个 operation 列创建 useOperationColumn 实例\r\n const operationColumnMap = computed(() => {\r\n const map = new Map<string, ReturnType<typeof useOperationColumn>>()\r\n\r\n operationColumns.value.forEach(col => {\r\n const hook = useOperationColumn(\r\n col.buttons || [],\r\n col.maxbtn ?? 10,\r\n props.permissions || []\r\n )\r\n map.set(col.key, hook)\r\n })\r\n\r\n return map\r\n })\r\n\r\n const getOperationColumnHook = (col: ColumnConfig) => {\r\n return operationColumnMap.value.get(col.key)\r\n }\r\n\r\n // 判断 operation 列是否应该显示\r\n const isOperationVisible = (col: ColumnConfig) => {\r\n if (!isOperationColumn(col)) return false\r\n \r\n const hook = getOperationColumnHook(col)\r\n if (!hook) return false\r\n\r\n const buttons = col.buttons || []\r\n if (!buttons.length) return false\r\n\r\n // 无数据时,只要有权限的按钮就显示\r\n if (!props.data?.length) return hook.hasAnyButton.value\r\n\r\n // 有数据时,检查是否至少有一行有可见按钮\r\n return hook.hasAnyVisibleButton(props.data)\r\n }\r\n\r\n const getOperationWidth = (col: ColumnConfig) => {\r\n const hook = getOperationColumnHook(col)\r\n if (!hook) return 0\r\n\r\n // 无行数据,用静态宽度\r\n if (!props.data?.length) return hook.optWidth.value\r\n // 有行数据,取最大宽度\r\n return hook.getMaxOptWidth(props.data)\r\n }\r\n\r\n const getVisibleButtons = (col: OperationColumn, row: any) => {\r\n const hook = getOperationColumnHook(col)\r\n if (!hook) return []\r\n\r\n const buttons = col.buttons || []\r\n if (!buttons.length) return []\r\n\r\n return hook.getVisibleButtons(row)\r\n }\r\n\r\n // ------------------ 列处理 ------------------\r\n \r\n // 可见列(按用户配置顺序)\r\n const visibleColumns = computed(() =>\r\n cachedColumns.value.filter(col => {\r\n // operation 列需要判断是否有可见按钮\r\n if (col.type === 'operation') {\r\n return isOperationVisible(col)\r\n }\r\n // selection/index 始终显示\r\n if (isSpecialColumn(col.type)) return true\r\n // 数据列根据 visible 控制\r\n return col.visible !== false\r\n })\r\n )\r\n\r\n // 生成列的唯一 key\r\n const getColumnKey = (col: ColumnConfig, idx: number) => {\r\n if (col.type === 'selection') return `selection-${idx}`\r\n if (col.type === 'index') return `index-${idx}`\r\n if (col.type === 'operation') return `operation-${col.key}-${idx}`\r\n return `${col.key}-${idx}`\r\n }\r\n\r\n // ------------------ index 列序号计算 ------------------\r\n const 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 // ------------------ renderer 获取 ------------------\r\n const renderer = computed(() => {\r\n const manager = getRendererManager()\r\n const allRenderers: Record<string, any> = {}\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 // ------------------ 事件封装 ------------------\r\n const handleCellChange = (row: any, col: ColumnConfig) => {\r\n emit('cellChange', row, col)\r\n }\r\n const handleCellBlur = (row: any, col: ColumnConfig) => {\r\n emit('cellBlur', row, col)\r\n }\r\n const handleCellEnter = (row: any, col: ColumnConfig) => {\r\n emit('cellEnter', row, col)\r\n }\r\n const handleCellClick = (row: any, col: ColumnConfig) => {\r\n if (!col) return\r\n emit('cellClick', 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 { ColumnConfig, ColumnType } 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 ColumnType> =\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":["isSpecialColumn","type","isRendererType","isOperationColumn","col","mergeColumns","defaultColumns","cacheColumns","cacheMap","c","cacheCol","useTableColumns","options","cacheKey","storage","cache","columns","ref","watch","newVal","lightColumns","newColumns","useOperationColumn","buttonConfigs","maxbtn","userPermissions","all_permission","hasPermi","value","permArray","p","hasAnyButton","computed","btn","optWidth","sum","isButtonVisible","row","optRowWidth","rows","max","RendererManager","__publicField","name","renderer","renderers","globalRendererManager","getRendererManager","wrapSFCComponent","comp","defineComponent","props","h","createFunctionalRenderer","render","validateRendererProps","rendererName","renderProps","getValueByPath","obj","path","acc","key","setValueByPath","keys","lastKey","target","__props","inputProps","rp","onBlur","onFocus","onChange","onInput","onClear","onEnter","rest","v","val","_a","_c","_b","e","_openBlock","_createBlock","_component_el_input","_mergeProps","$event","oldVal","_component_el_input_number","selectProps","onVisibleChange","visible","_component_el_select","_createElementBlock","_Fragment","_renderList","opt","_component_el_option","input","EditableInput","inputNumber","EditableNumber","select","EditableSelect","normalizeCssSize","size","fallback","extractEvents","events","button","restProps","ElButton","link","href","blank","label","html","style","className","copy","iconColor","copyTitle","successText","errorText","lineClamp","textStyles","textClass","butStyle","textStyleObj","ElMessage","textarea","successful","DocumentCopy","img","width","height","fit","previewSrcList","placeholder","imageList","item","defaultStyle","imageProps","ElImage","CopyDocument","dict","showValue","values","matchedOptions","unmatched","children","listClass","cssClass","tagProps","itemRest","ElTag","map","mappedVal","isDataColumn","formatter","index","content","icon","iconSize","builtInRenderers","registerBuiltInRenderers","registry","createRenderer","defaultConfig","ConfigManager","config","source","result","globalConfigManager","getConfigManager","setSmartTableConfig","getSmartTableConfig","emit","__emit","cachedColumns","isInitialized","operationColumns","operationColumnMap","hook","getOperationColumnHook","isOperationVisible","getOperationWidth","getVisibleButtons","visibleColumns","getColumnKey","idx","computeIndex","page","manager","allRenderers","r","handleCellChange","handleCellBlur","handleCellEnter","handleCellClick","tableRef","__expose","_withDirectives","_component_el_table","$attrs","_component_el_table_column","_withCtx","$index","_createTextVNode","_toDisplayString","_component_el_button","scope","_renderSlot","_ctx","_resolveDynamicComponent","_normalizeStyle","_normalizeClass","_unref","_hoisted_1","defineColumn"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 内置渲染器集�?
|
|
3
|
-
* 可以按需引入或批量注�?
|
|
2
|
+
* 内置渲染器集�?
|
|
3
|
+
* 可以按需引入或批量注�?
|
|
4
4
|
*/
|
|
5
5
|
import { h } from 'vue'
|
|
6
6
|
import { ElButton, ElTag, ElImage, ElMessage } from 'element-plus'
|
|
@@ -18,6 +18,11 @@ import EditableSelect from './select.vue'
|
|
|
18
18
|
const input = wrapSFCComponent(EditableInput)
|
|
19
19
|
const inputNumber = wrapSFCComponent(EditableNumber)
|
|
20
20
|
const select = wrapSFCComponent(EditableSelect)
|
|
21
|
+
const normalizeCssSize = (size: string | number | undefined, fallback: string) => {
|
|
22
|
+
if (size === undefined || size === null || size === '') return fallback
|
|
23
|
+
return typeof size === 'number' ? size + 'px' : size
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
|
|
22
27
|
/**
|
|
23
28
|
* 提取 props 中的事件(on 开头的属性)
|
|
@@ -38,7 +43,7 @@ const extractEvents = (rp: Record<string, any>) => {
|
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
/**
|
|
41
|
-
* button 渲染�?
|
|
46
|
+
* button 渲染�?
|
|
42
47
|
*/
|
|
43
48
|
const button = createFunctionalRenderer((props) => {
|
|
44
49
|
const rp = props.col.props || {}
|
|
@@ -51,14 +56,14 @@ const button = createFunctionalRenderer((props) => {
|
|
|
51
56
|
...events,
|
|
52
57
|
onClick: (e: Event) => {
|
|
53
58
|
props.onClick?.(props.row, props.col)
|
|
54
|
-
// 支持用户自定�?onClick
|
|
59
|
+
// 支持用户自定�?onClick
|
|
55
60
|
rp.onClick?.(e, props.row, props.col)
|
|
56
61
|
}
|
|
57
62
|
}, () => rp.label || val)
|
|
58
63
|
})
|
|
59
64
|
|
|
60
65
|
/**
|
|
61
|
-
* link 渲染�?
|
|
66
|
+
* link 渲染�?
|
|
62
67
|
*/
|
|
63
68
|
const link = createFunctionalRenderer((props) => {
|
|
64
69
|
const rp = props.col.props || {}
|
|
@@ -75,7 +80,7 @@ const link = createFunctionalRenderer((props) => {
|
|
|
75
80
|
})
|
|
76
81
|
|
|
77
82
|
/**
|
|
78
|
-
* html 渲染�?
|
|
83
|
+
* html 渲染�?
|
|
79
84
|
*/
|
|
80
85
|
const html = createFunctionalRenderer((props) => {
|
|
81
86
|
const val = getValueByPath(props.row, props.col.key)
|
|
@@ -91,7 +96,7 @@ const html = createFunctionalRenderer((props) => {
|
|
|
91
96
|
})
|
|
92
97
|
|
|
93
98
|
/**
|
|
94
|
-
* copy 渲染�?
|
|
99
|
+
* copy 渲染�?
|
|
95
100
|
*/
|
|
96
101
|
const copy = createFunctionalRenderer((props) => {
|
|
97
102
|
const val = getValueByPath(props.row, props.col.key) ?? ''
|
|
@@ -170,7 +175,7 @@ const copy = createFunctionalRenderer((props) => {
|
|
|
170
175
|
})
|
|
171
176
|
|
|
172
177
|
/**
|
|
173
|
-
* img 渲染�?
|
|
178
|
+
* img 渲染�?
|
|
174
179
|
*/
|
|
175
180
|
const img = createFunctionalRenderer((props) => {
|
|
176
181
|
const val = getValueByPath(props.row, props.col.key) ?? ''
|
|
@@ -192,8 +197,8 @@ const img = createFunctionalRenderer((props) => {
|
|
|
192
197
|
}
|
|
193
198
|
|
|
194
199
|
const defaultStyle = {
|
|
195
|
-
width: width
|
|
196
|
-
height: height
|
|
200
|
+
width: normalizeCssSize(width, '80px'),
|
|
201
|
+
height: normalizeCssSize(height, '80px'),
|
|
197
202
|
marginRight: imageList.length > 1 ? '4px' : '0',
|
|
198
203
|
...(typeof style === 'object' ? style : {})
|
|
199
204
|
}
|
|
@@ -233,7 +238,7 @@ const img = createFunctionalRenderer((props) => {
|
|
|
233
238
|
})
|
|
234
239
|
|
|
235
240
|
/**
|
|
236
|
-
* dict 渲染�?
|
|
241
|
+
* dict 渲染�?
|
|
237
242
|
*/
|
|
238
243
|
const dict = createFunctionalRenderer((props) => {
|
|
239
244
|
const val = getValueByPath(props.row, props.col.key) ?? ''
|
|
@@ -270,7 +275,7 @@ const dict = createFunctionalRenderer((props) => {
|
|
|
270
275
|
})
|
|
271
276
|
|
|
272
277
|
/**
|
|
273
|
-
* map 渲染�?
|
|
278
|
+
* map 渲染�?
|
|
274
279
|
*/
|
|
275
280
|
const map = createFunctionalRenderer((props) => {
|
|
276
281
|
const val = getValueByPath(props.row, props.col.key) ?? ''
|
|
@@ -282,7 +287,7 @@ const map = createFunctionalRenderer((props) => {
|
|
|
282
287
|
})
|
|
283
288
|
|
|
284
289
|
/**
|
|
285
|
-
* formatter 渲染�?
|
|
290
|
+
* formatter 渲染�?
|
|
286
291
|
*/
|
|
287
292
|
export function isDataColumn(
|
|
288
293
|
col: ColumnConfig
|
|
@@ -304,7 +309,7 @@ const formatter = createFunctionalRenderer((props) => {
|
|
|
304
309
|
})
|
|
305
310
|
|
|
306
311
|
/**
|
|
307
|
-
* icon 渲染�?
|
|
312
|
+
* icon 渲染�?
|
|
308
313
|
*/
|
|
309
314
|
const icon = createFunctionalRenderer((props) => {
|
|
310
315
|
const val = getValueByPath(props.row, props.col.key) ?? ''
|
|
@@ -379,8 +384,8 @@ export function registerBuiltInRenderers(registry: { registerMultiple: (renderer
|
|
|
379
384
|
}
|
|
380
385
|
|
|
381
386
|
/**
|
|
382
|
-
* 创建默认渲染器集合(兼容�?API�?
|
|
383
|
-
* @deprecated 建议使用插件化架�?
|
|
387
|
+
* 创建默认渲染器集合(兼容�?API�?
|
|
388
|
+
* @deprecated 建议使用插件化架�?
|
|
384
389
|
*/
|
|
385
390
|
export function createRenderer() {
|
|
386
391
|
return builtInRenderers
|