@es-plus/vue2 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"es-plus-vue2.js","sources":["../src/composables/use-form-inputs.ts","../src/composables/use-form-layout.ts","../src/composables/use-form-request.ts","../src/utils/size.ts","../src/components/es-form/es-form.vue","../src/components/es-form/index.ts","../src/components/es-table/column-item.vue","../src/utils/icon.ts","../src/components/es-table/table-btns.vue","../src/composables/use-table-resize.ts","../src/composables/use-table-selection.ts","../src/components/es-table/component.vue","../src/components/es-table/index.ts","../src/components/es-dialog/render-jsx.vue","../src/components/es-dialog/component.vue","../src/components/es-dialog/use-dialog.ts","../src/components/es-dialog/index.ts","../src/components/es-crud-page/es-crud-page.vue","../src/components/es-crud-page/index.ts","../src/index.ts"],"sourcesContent":["/**\r\n * Vue 2 + Element UI 表单输入适配器\r\n *\r\n * 与 Vue 3 + Element Plus 版本(packages/vue3/src/composables/use-form-inputs.ts)的核心差异:\r\n *\r\n * 1. h() 签名:\r\n * - Vue 3:h(Comp, { modelValue, 'onUpdate:modelValue': fn, ...props })\r\n * - Vue 2:h(Comp, { props: { value, ... }, on: { input, ... }, attrs: {...} })\r\n *\r\n * 2. v-model 实现:\r\n * - Vue 3 默认 v-model 等价于 :modelValue + @update:modelValue\r\n * - Vue 2 默认 v-model 等价于 :value + @input(原生输入框是 :value + @input;\r\n * el-* 控件大多遵循该规范,少数有特殊 model 配置如 el-checkbox 用 checked/change)\r\n *\r\n * 3. 组件名:el-input / el-select / el-date-picker ...(kebab-case 字符串注册)\r\n * - Element UI 通过 Vue.use(ElementUI) 全局注册了所有组件,可直接用字符串引用\r\n *\r\n * 4. 图标系统:Element UI 用 class(el-icon-xxx),不再使用图标组件\r\n *\r\n * 5. 嵌套属性 path:复用核心层的 getNestedValue / setNestedValue(Vue 2 中 setNestedValue\r\n * 需要配合 Vue.set 才能触发响应式 —— 由 EsForm 组件的 currentModel 经 reactive 包装解决)\r\n *\r\n * 用户保持一致的写法:\r\n * {\r\n * formtype: 'Input',\r\n * prop: 'name',\r\n * label: '姓名',\r\n * attrs: { placeholder: '请输入', clearable: true },\r\n * on: { input: (val) => console.log(val) }\r\n * }\r\n *\r\n * 这样无论是 Vue 2 还是 Vue 3 项目,配置 schema 完全一致 —— 只有内部渲染层做差异化处理。\r\n */\r\n\r\nimport { getNestedValue, setNestedValue } from '@es-plus/core'\r\nimport type { FormItemOption, ModelData } from '@es-plus/core'\r\n\r\n/**\r\n * Vue 2 createElement 函数类型\r\n * 来自 Vue 实例的 $createElement 或 render 函数的第一参数\r\n */\r\nexport type CreateElement = (tag: string | object, dataOrChildren?: unknown, children?: unknown) => unknown\r\n\r\n/**\r\n * 表单输入渲染函数签名\r\n * - h:createElement 函数(Vue 2)\r\n * - model:当前 model 数据(响应式对象,需通过 setNestedValue 写入以触发响应式)\r\n * - ctx:包含 row(当前 FormItemOption)的上下文\r\n */\r\nexport type FormInputRenderer = (\r\n h: CreateElement,\r\n model: ModelData,\r\n ctx: { row: FormItemOption; index?: number }\r\n) => unknown\r\n\r\n/**\r\n * 解析 dataOptions:支持 Array 或 () => Array 两种形式\r\n */\r\nfunction resolveDataOptions(dataOptions: FormItemOption['dataOptions'] | (() => unknown[])): Array<{\r\n label: string\r\n value: unknown\r\n disabled?: boolean\r\n children?: unknown[]\r\n}> {\r\n if (Array.isArray(dataOptions)) return dataOptions\r\n if (typeof dataOptions === 'function') {\r\n const result = (dataOptions as () => unknown)()\r\n return Array.isArray(result) ? (result as Array<{ label: string; value: unknown }>) : []\r\n }\r\n return []\r\n}\r\n\r\n/**\r\n * 解析 attrs,特别处理 disabled 函数形式(与 es-eui 保持一致)\r\n */\r\nfunction resolveAttrs(row: FormItemOption): Record<string, unknown> {\r\n const attrs: Record<string, unknown> = { ...(row.attrs || {}) }\r\n if (typeof attrs.disabled === 'function') {\r\n attrs.disabled = (attrs.disabled as () => boolean)()\r\n }\r\n return attrs\r\n}\r\n\r\n/**\r\n * 构造统一的事件监听器对象:\r\n * - 默认 input 事件用于 v-model 同步(写回 model)\r\n * - 用户配置的 input 优先(可拦截/转换值)\r\n * - 其它事件(focus/blur/change...)原样透传\r\n */\r\nfunction buildEventHandlers(\r\n row: FormItemOption,\r\n defaultInputHandler: (val: unknown) => void\r\n): Record<string, unknown> {\r\n const userOn = (row.on || {}) as Record<string, unknown>\r\n const handlers: Record<string, unknown> = {}\r\n\r\n for (const [key, handler] of Object.entries(userOn)) {\r\n if (typeof handler === 'function') {\r\n handlers[key] = handler\r\n }\r\n }\r\n\r\n // 用户没显式配置 input 时,绑定默认写回逻辑\r\n if (typeof handlers.input !== 'function') {\r\n handlers.input = defaultInputHandler\r\n }\r\n\r\n return handlers\r\n}\r\n\r\n/**\r\n * 创建一个表单输入渲染器映射\r\n *\r\n * 与 Vue 3 版本通过 useFormInputs() composable 调用一致;\r\n * Vue 2 中也提供同名函数以保证 API 一致性,方便未来共享代码。\r\n */\r\nexport function useFormInputs() {\r\n const formInputComponents = (item: FormItemOption): FormInputRenderer => {\r\n const formPutList = new Map<string, FormInputRenderer>([\r\n // ─────────────────────────────────────────────────────────────────\r\n // Input - 文本输入\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Input',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-input', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // InputNumber - 数字输入(保留兼容 es-eui 的扩展类型)\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'InputNumber',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-input-number', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Select - 下拉选择\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Select',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const dataOptions = resolveDataOptions(row.dataOptions as never)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h(\r\n 'el-select',\r\n {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n },\r\n dataOptions.map((opt, idx) =>\r\n h('el-option', {\r\n key: idx,\r\n props: { value: opt.value, label: opt.label, disabled: opt.disabled },\r\n })\r\n )\r\n )\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // datePicker - 日期选择(注意 Vue 3 用大写 DatePicker,Vue 2 用 datePicker;\r\n // 这里 Map key 跟 Vue 3 版本对齐,使用 'datePicker')\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'datePicker',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-date-picker', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // timePicker - 时间选择\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'timePicker',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-time-picker', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Slider - 滑块\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Slider',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-slider', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // ColorPicker - 颜色选择\r\n // Element UI 的 el-color-picker 使用 v-model 默认 prop 为 'value',事件 'change'/'active-change'\r\n // 但同时支持 input 事件透传,这里保持 input 用作默认写回\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'ColorPicker',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n // ColorPicker 没有 input 事件,使用 change 作为默认写回\r\n const userOn = (row.on || {}) as Record<string, unknown>\r\n const handlers: Record<string, unknown> = {}\r\n for (const [key, handler] of Object.entries(userOn)) {\r\n if (typeof handler === 'function') handlers[key] = handler\r\n }\r\n if (typeof handlers.change !== 'function') {\r\n handlers.change = (val: unknown) => setNestedValue(model, row.prop, val)\r\n }\r\n return h('el-color-picker', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Transfer - 穿梭框\r\n // Element UI 中 el-transfer 默认 v-model 为 :value + @input,data 通过 props 传入\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Transfer',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const dataOptions = resolveDataOptions(row.dataOptions as never)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-transfer', {\r\n attrs,\r\n props: {\r\n value,\r\n data: dataOptions.map((opt) => ({ key: opt.value, label: opt.label, disabled: opt.disabled })),\r\n ...row.props,\r\n },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Cascader - 级联选择\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Cascader',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const dataOptions = resolveDataOptions(row.dataOptions as never)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-cascader', {\r\n // key 强制 dataOptions 变化时重渲染,Element UI 内部 cache 否则不刷新\r\n key: JSON.stringify(dataOptions),\r\n attrs,\r\n props: {\r\n value,\r\n options: dataOptions,\r\n ...row.props,\r\n },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Radio - 单选组\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Radio',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const dataOptions = resolveDataOptions(row.dataOptions as never)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h(\r\n 'el-radio-group',\r\n {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n },\r\n dataOptions.map((opt, idx) =>\r\n h(\r\n 'el-radio',\r\n {\r\n key: idx,\r\n // Element UI 中 el-radio 使用 :label 作为值\r\n props: { label: opt.value, disabled: opt.disabled || (attrs.disabled as boolean) },\r\n },\r\n [opt.label]\r\n )\r\n )\r\n )\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Checkbox - 复选组\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Checkbox',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const dataOptions = resolveDataOptions(row.dataOptions as never)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h(\r\n 'el-checkbox-group',\r\n {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n },\r\n dataOptions.map((opt, idx) =>\r\n h(\r\n 'el-checkbox',\r\n {\r\n key: idx,\r\n props: { label: opt.value, disabled: opt.disabled || (attrs.disabled as boolean) },\r\n },\r\n [opt.label]\r\n )\r\n )\r\n )\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Switch - 开关\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Switch',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n // Element UI 的 el-switch 默认 v-model 用 :value + @input\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-switch', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Rate - 评分\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Rate',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-rate', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Upload - 上传(最复杂的一个,需处理 fileList、httpRequest、自定义 trigger 等)\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Upload',\r\n (h, model, { row }) => {\r\n const prop = row.prop\r\n const attrs = resolveAttrs(row)\r\n const userProps = (row.props || {}) as Record<string, unknown>\r\n const userOn = (row.on || {}) as Record<string, unknown>\r\n const fileList = (getNestedValue(model, prop) as unknown[]) || []\r\n\r\n const isCustomUpload = typeof row.httpRequest === 'function'\r\n\r\n // 用户配置 trigger 渲染(picture-card 模式 / 普通模式 都用 default slot 占位)\r\n const triggerRender = (row as FormItemOption & {\r\n triggerRender?: (h: CreateElement) => unknown\r\n }).triggerRender\r\n const fileRender = (row as FormItemOption & {\r\n fileRender?: (h: CreateElement, file: unknown, onRemove: () => void) => unknown\r\n }).fileRender\r\n\r\n // 默认 trigger 按钮(size 与 EsForm 默认 mini 对齐,避免视觉割裂)\r\n const triggerVnode = triggerRender\r\n ? triggerRender(h)\r\n : h('el-button', { props: { size: 'mini', type: 'primary' } }, ['选择文件'])\r\n\r\n // ── 上传成功处理(与 es-eui 保持一致的字段抽取规则) ──\r\n const processSuccess = (response: Record<string, unknown> | undefined, file: Record<string, unknown>, list: unknown[]) => {\r\n const url =\r\n (response?.link as string) ||\r\n (response?.url as string) ||\r\n ((response?.data as Record<string, unknown> | undefined)?.link as string) ||\r\n ((response?.data as Record<string, unknown> | undefined)?.url as string)\r\n\r\n if (url) file.url = url\r\n file.status = 'success'\r\n file.response = response\r\n\r\n if (typeof userOn.success === 'function') {\r\n ;(userOn.success as (...a: unknown[]) => void)(response, file, list)\r\n }\r\n // 触发响应式更新(替换为新数组引用以让 Vue 2 检测变化)\r\n setNestedValue(model, prop, [...list])\r\n }\r\n\r\n const processError = (err: unknown, file: Record<string, unknown>, list: unknown[]) => {\r\n file.status = 'fail'\r\n file.error = err\r\n if (typeof userOn.error === 'function') {\r\n ;(userOn.error as (...a: unknown[]) => void)(err, file, list)\r\n }\r\n setNestedValue(model, prop, [...list])\r\n }\r\n\r\n // ── 自定义 httpRequest 包装:el-upload 的 http-request 接收 { file, onSuccess, onError, onProgress } ──\r\n const httpRequestProp = isCustomUpload\r\n ? (options: { file: File; onSuccess: (res: unknown) => void; onError: (err: unknown) => void; onProgress?: (e: { percent: number }) => void }) => {\r\n const customRequest = row.httpRequest as (params: Record<string, unknown>) => Promise<unknown>\r\n customRequest({\r\n file: options.file,\r\n filename: options.file.name,\r\n onProgress: options.onProgress,\r\n })\r\n .then((res) => {\r\n const resp = (res as Record<string, unknown>)?.data || res\r\n options.onSuccess(resp)\r\n })\r\n .catch((err) => options.onError(err))\r\n }\r\n : undefined\r\n\r\n /**\r\n * Element UI 的 <el-upload> 把所有上传生命周期回调都暴露为 Function 类型 prop\r\n * (onPreview / onSuccess / onChange / onRemove / onError / onProgress / onExceed),\r\n * 而非通过 $emit 派发事件 —— 因此用户写 `on: { preview }` 在 Vue 2 render 函数里\r\n * 等价于 `v-on:preview`,永远不会触发(el-upload 不会 $emit('preview'))。\r\n *\r\n * 关键点:onPreview 在 Element UI 中**没有 noop 默认值**,\r\n * 当 prop 缺失时 upload-list 的 `v-if=\"handlePreview\"` 为 false,\r\n * picture-card 模式下的\"预览(放大镜)\"图标会被隐藏 —— 这就是用户报的 bug。\r\n *\r\n * 修复:把 row.on 中的回调按 camelCase 转为 prop(key → onKey)。\r\n */\r\n const eventToProp: Record<string, string> = {\r\n preview: 'onPreview',\r\n change: 'onChange',\r\n success: 'onSuccess',\r\n error: 'onError',\r\n progress: 'onProgress',\r\n remove: 'onRemove',\r\n exceed: 'onExceed',\r\n }\r\n const uploadCallbackProps: Record<string, unknown> = {}\r\n for (const [key, handler] of Object.entries(userOn)) {\r\n if (typeof handler !== 'function') continue\r\n // success / error / remove 由我们包装后再写入,跳过原始用户函数\r\n if (key === 'success' || key === 'error' || key === 'remove') continue\r\n const propName = eventToProp[key]\r\n if (propName) uploadCallbackProps[propName] = handler\r\n }\r\n // 始终接管 success / error / remove —— 既调用用户回调,也同步 fileList 到 model\r\n uploadCallbackProps.onSuccess = processSuccess\r\n uploadCallbackProps.onError = processError\r\n uploadCallbackProps.onRemove = (file: Record<string, unknown>, list: unknown[]) => {\r\n if (typeof userOn.remove === 'function') {\r\n ;(userOn.remove as (...a: unknown[]) => void)(file, list)\r\n }\r\n setNestedValue(model, prop, [...list])\r\n }\r\n\r\n // 主体\r\n return h(\r\n 'el-upload',\r\n {\r\n attrs: {\r\n ...attrs,\r\n action: (userProps.action as string) || (attrs.action as string) || '#',\r\n 'file-list': fileList,\r\n },\r\n props: {\r\n ...userProps,\r\n fileList,\r\n // 自定义上传时禁用 auto-upload,由 httpRequest 接管\r\n autoUpload: isCustomUpload ? false : (userProps.autoUpload !== false),\r\n httpRequest: httpRequestProp,\r\n // 把 row.on.* 转换为 onXxx prop(覆盖在 userProps 之上:\r\n // 若用户已直接在 props 里给了 onPreview,这里仍以 row.on 为优先权来源)\r\n ...uploadCallbackProps,\r\n },\r\n // Vue 2 的 scopedSlots 用于自定义文件项渲染\r\n scopedSlots: fileRender\r\n ? {\r\n file: ({ file }: { file: Record<string, unknown> }) =>\r\n fileRender(h, file, () => {\r\n const newList = fileList.filter((f) => f !== file)\r\n setNestedValue(model, prop, newList)\r\n }),\r\n }\r\n : undefined,\r\n },\r\n [triggerVnode]\r\n )\r\n },\r\n ],\r\n ])\r\n\r\n /**\r\n * formtype 大小写兼容查找:\r\n * - Vue 3 版本约定 `datePicker` / `timePicker` 用 camelCase,其它用 PascalCase\r\n * - 原 es-eui 历史上一律使用 PascalCase(`DatePicker` / `TimePicker`)\r\n * 为了让旧 es-eui 案例无修改即可使用 @es-plus/vue2,这里做大小写兼容:\r\n * 1) 精确匹配(保持 Vue 3 习惯)\r\n * 2) 首字母翻转再试一次(覆盖 'DatePicker' ↔ 'datePicker' 这类差异)\r\n * 3) 全表 case-insensitive 兜底\r\n * 都未命中则返回空渲染器。\r\n */\r\n const formtype = (item.formtype ?? '') as string\r\n if (!formtype) return (): unknown => null\r\n\r\n const direct = formPutList.get(formtype)\r\n if (direct) return direct\r\n\r\n const flipped = formtype[0]\r\n ? (formtype[0] === formtype[0].toLowerCase()\r\n ? formtype[0].toUpperCase() + formtype.slice(1)\r\n : formtype[0].toLowerCase() + formtype.slice(1))\r\n : formtype\r\n const flippedHit = formPutList.get(flipped)\r\n if (flippedHit) return flippedHit\r\n\r\n const lower = formtype.toLowerCase()\r\n for (const [key, val] of formPutList) {\r\n if (key.toLowerCase() === lower) return val\r\n }\r\n return (): unknown => null\r\n }\r\n\r\n return { formInputComponents }\r\n}\r\n","/**\r\n * EsForm 布局 composable —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - 仅 import 路径不同:从 'vue' 替换为 './vue-compat',从本地 utils 替换为 '@es-plus/core'\r\n * - 24 栅格行列分组算法 100% 复用 @es-plus/core 提供的 getRowColsAlgorithm\r\n *\r\n * 该 composable 不依赖任何 Element UI 组件,是纯逻辑层。\r\n */\r\n\r\nimport { computed, ref, watch } from '../vue-compat'\r\nimport {\r\n getRowColsAlgorithm as coreGetRowColsAlgorithm,\r\n resolveFormLayProps,\r\n type FormLayoutResult,\r\n} from '@es-plus/core'\r\nimport type { FormItemOption, LayoutFormProps } from '@es-plus/core'\r\n\r\nexport interface UseFormLayoutProps {\r\n layoutFormProps?: LayoutFormProps\r\n /** 注意:调用方需保证此处是响应式来源(或用 getter 形式:`get formItemList() { ... }`) */\r\n formItemList: FormItemOption[]\r\n}\r\n\r\nexport function useFormLayout(props: UseFormLayoutProps) {\r\n const folded = ref(false)\r\n\r\n /**\r\n * 隐藏按钮区字段名兼容:原 es-eui 使用 `isBtnHiden`(少一个 d,原始拼写错误),\r\n * 后续 schema/类型规范化为 `isBtnHidden`。两者都接受,原始拼写优先。\r\n */\r\n const isBtnHidden = computed(() => {\r\n const fromLay = resolveFormLayProps(props.layoutFormProps) as Record<string, unknown> | undefined\r\n if (!fromLay || !Object.keys(fromLay).length) return false\r\n const legacy = fromLay.isBtnHiden\r\n const fixed = fromLay.isBtnHidden\r\n return Boolean(legacy ?? fixed ?? false)\r\n })\r\n /**\r\n * el-row 布局参数。\r\n *\r\n * 注意:Element UI v2 的 `el-row` 默认是 **浮动布局**(float-based),\r\n * 而 Element Plus 的 `el-row` 默认是 **flex 布局**。\r\n *\r\n * 浮动布局的问题:当不同 el-col 的高度不一致时(比如 Checkbox 组在窄屏下换成两行、\r\n * DatePicker 高度比 Switch 略高),后面的 el-col 会卡进高的列下方留白处,\r\n * 而不是干净地换行 —— 表现为「布局错乱」。\r\n *\r\n * 修复策略:默认使用 `type=\"flex\"`,并通过 SFC 样式给 `.es-form .el-row--flex`\r\n * 加上 `flex-wrap: wrap`,让换行行为与 Element Plus 一致。用户若显式传入\r\n * `rowLayProps: { type: '' }` 仍可回退为浮动布局。\r\n */\r\n const rowLayout = computed(() => {\r\n const userProps = (props.layoutFormProps?.rowLayProps as Record<string, unknown>) || {}\r\n return {\r\n type: 'flex',\r\n gutter: 20,\r\n ...userProps,\r\n }\r\n })\r\n const formLayout = computed(() => resolveFormLayProps(props.layoutFormProps))\r\n const getSetOptionsStatus = computed(() => props.layoutFormProps?.setOptions)\r\n\r\n const getRowColsAlgorithm = computed<FormLayoutResult>(() =>\r\n coreGetRowColsAlgorithm(props.formItemList || [])\r\n )\r\n\r\n /**\r\n * 折叠行阈值字段名兼容:\r\n * - 原 es-eui 使用小写 `minfoldRows`(fold 全小写)\r\n * - 后续部分文档示例与 EsCrudPage schema 使用驼峰 `minFoldRows`\r\n * 这里两个都接受,原始小写优先(保持旧文档案例不改字面量即可工作)。\r\n */\r\n const getMinFoldRow = (): number => {\r\n const fromLay = resolveFormLayProps(props.layoutFormProps) as Record<string, unknown> | undefined\r\n if (!fromLay || !Object.keys(fromLay).length) return 0\r\n const legacy = fromLay.minfoldRows\r\n const camel = fromLay.minFoldRows\r\n return Number(legacy ?? camel ?? 0) || 0\r\n }\r\n\r\n const isFold = computed(() => {\r\n const minFoldRow = getMinFoldRow()\r\n return minFoldRow > 0 && minFoldRow < getRowColsAlgorithm.value.rowNum\r\n })\r\n\r\n const getBtnColSpan = computed(() => {\r\n const { rowNum, columnRow } = getRowColsAlgorithm.value\r\n const lastColumn = columnRow[rowNum - 1] || []\r\n const btnColSpan = Number((resolveFormLayProps(props.layoutFormProps) as Record<string, unknown>)?.btnColSpan) || 0\r\n const totalSpan = lastColumn.reduce(\r\n (sum: number, idx: number) => sum + (props.formItemList[idx]?.span || 24),\r\n 0\r\n )\r\n const hasSpan = 24 - totalSpan\r\n return !folded.value && btnColSpan <= hasSpan ? hasSpan : 24\r\n })\r\n\r\n const formItem = computed(() => {\r\n const minFoldRow = getMinFoldRow()\r\n const { columnNodeIndex } = getRowColsAlgorithm.value\r\n\r\n if (folded.value) {\r\n const lastFoldIndex =\r\n columnNodeIndex[minFoldRow - 1] ?? columnNodeIndex[columnNodeIndex.length - 1] ?? 9999\r\n return (props.formItemList || []).map((it: FormItemOption, index: number) => ({\r\n ...it,\r\n isFold: index > lastFoldIndex,\r\n }))\r\n }\r\n return (props.formItemList || []).map((it: FormItemOption) => ({ ...it, isFold: false }))\r\n })\r\n\r\n watch(\r\n isFold,\r\n (val: boolean) => {\r\n folded.value = val\r\n },\r\n { immediate: true }\r\n )\r\n\r\n const changeFolded = () => {\r\n folded.value = !folded.value\r\n }\r\n\r\n return {\r\n folded,\r\n isBtnHidden,\r\n rowLayout,\r\n formLayout,\r\n getSetOptionsStatus,\r\n getRowColsAlgorithm,\r\n isFold,\r\n getBtnColSpan,\r\n formItem,\r\n changeFolded,\r\n }\r\n}\r\n","/**\r\n * EsForm 请求 composable —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - nextTick 来源从 'vue' 改为 './vue-compat'\r\n * - toRaw/unref 不再需要:Vue 2 的响应式对象天然是 plain object(仅在 setter 处被 wrapped),\r\n * 而我们在请求时只读取值,无需 unwrap\r\n * - 核心格式化逻辑 100% 复用 @es-plus/core/request\r\n *\r\n * 该 composable 仅做 Vue 包装,所有数据转换都委托给 @es-plus/core。\r\n */\r\n\r\nimport { nextTick } from '../vue-compat'\r\nimport {\r\n queryTableListMethod as coreQueryTableListMethod,\r\n configFormField as coreConfigFormField,\r\n formatConfigOut as coreFormatConfigOut,\r\n httpRequestFormInstance as coreHttpRequestFormInstance,\r\n getEveryFormQueryField as coreGetEveryFormQueryField,\r\n type RequestConfig,\r\n type ConfigFormFieldOut,\r\n} from '@es-plus/core'\r\nimport type { FormItemOption } from '@es-plus/core'\r\n\r\nexport type { RequestConfig, ConfigFormFieldOut }\r\n\r\nexport function useFormRequest(\r\n httpRequestGlobal?: (params: Record<string, unknown>) => Promise<unknown>\r\n) {\r\n const queryTableListMethod = (\r\n params: Record<string, unknown>,\r\n options: RequestConfig = {}\r\n ) => coreQueryTableListMethod(params, options, httpRequestGlobal)\r\n\r\n const configFormField = (\r\n options: Record<string, unknown> = {},\r\n fieldFieldOutput?: (defaults: ConfigFormFieldOut) => ConfigFormFieldOut\r\n ) => coreConfigFormField(options, fieldFieldOutput)\r\n\r\n const formatConfigOut = (\r\n row: Record<string, unknown> | unknown[],\r\n keyList: string[],\r\n options: Record<string, unknown> = {},\r\n fieldFieldOutput?: (defaults: ConfigFormFieldOut) => ConfigFormFieldOut\r\n ) => coreFormatConfigOut(row, keyList, options, fieldFieldOutput)\r\n\r\n const httpRequestFormInstance = (\r\n model: Record<string, unknown>,\r\n options: RequestConfig,\r\n rows: FormItemOption,\r\n fieldFieldOutput?: (defaults: ConfigFormFieldOut) => ConfigFormFieldOut\r\n ) =>\r\n // 与原 es-eui httpRquestFormInstace 一致:data 字段已剥一层 res.data,\r\n // 因此类型是 unknown(可能是数组、对象或 undefined)。\r\n new Promise<{ data: unknown; configRows: Record<string, unknown> }>((resolve, reject) => {\r\n nextTick(() => {\r\n coreHttpRequestFormInstance(model, options, rows, httpRequestGlobal, fieldFieldOutput)\r\n .then(resolve)\r\n .catch(reject)\r\n })\r\n })\r\n\r\n const getEveryFormQueryField = (\r\n rowsList: FormItemOption[],\r\n fieldFieldOutput?: (defaults: ConfigFormFieldOut) => ConfigFormFieldOut\r\n ) => coreGetEveryFormQueryField(rowsList, httpRequestGlobal, fieldFieldOutput)\r\n\r\n return {\r\n queryTableListMethod,\r\n getEveryFormQueryField,\r\n formatConfigOut,\r\n configFormField,\r\n }\r\n}\r\n","/**\r\n * Element UI v2 与 Element Plus 尺寸语义映射\r\n *\r\n * 背景:用户在两套版本之间复用同一份配置(如 size: 'small'),但两个组件库的尺寸系统并不一致:\r\n * Element Plus: large(40px) / default(32px) / small(24px)\r\n * Element UI v2: medium(36px) / small(32px) / mini(28px)\r\n *\r\n * 直接透传会导致同样的字符串渲染出截然不同的物理高度(small 在 EP 是 24px,在 EUI 是 32px),\r\n * 视觉上 Vue 2 版本明显比 Vue 3 版本\"大一圈\"。\r\n *\r\n * 本工具按\"接近视觉高度\"做语义映射:\r\n * large → medium (40 → 36)\r\n * default → small (32 → 32) — 高度本身一致\r\n * small → mini (24 → 28) — EUI 没有更小的,mini 已是最贴近\r\n * mini → mini (透传 — EUI 原生支持)\r\n * medium → medium (透传 — EUI 原生支持)\r\n *\r\n * 这样一来,在 Vue 3 版本里使用 size: 'small' 的紧凑表单,迁到 Vue 2 版本会自动落到 mini,\r\n * 整体视觉密度保持一致。用户若显式希望使用 EUI 原生尺寸(如 medium),原样透传即可。\r\n */\r\n\r\nexport type ElPlusSize = 'large' | 'default' | 'small' | ''\r\nexport type ElUiSize = 'medium' | 'small' | 'mini' | ''\r\n\r\nconst SIZE_MAP: Record<string, ElUiSize> = {\r\n large: 'medium',\r\n default: 'small',\r\n small: 'mini',\r\n // EUI 原生值透传\r\n medium: 'medium',\r\n mini: 'mini',\r\n}\r\n\r\n/**\r\n * 将任意尺寸字符串映射为 Element UI v2 支持的尺寸。\r\n * - 未识别的值返回 undefined,让组件回退到自身默认值\r\n * - 空字符串/空值同样返回 undefined\r\n */\r\nexport function mapSize(size: unknown): ElUiSize | undefined {\r\n if (size === undefined || size === null || size === '') return undefined\r\n const key = String(size).trim()\r\n if (!key) return undefined\r\n return SIZE_MAP[key]\r\n}\r\n","<template>\r\n <el-form ref=\"formRef\" v-bind=\"formProps\" class=\"es-form\">\r\n <div class=\"flex-center\">\r\n <el-row v-bind=\"rowLayout\">\r\n <template v-for=\"(item, index) in formItem\">\r\n <el-col\r\n v-show=\"!item.isFold\"\r\n :key=\"item.prop || index\"\r\n :span=\"item.span\"\r\n >\r\n <el-form-item\r\n :label=\"translateLabel(item)\"\r\n v-bind=\"initFormItemOptions(item.formItemOptions || {})\"\r\n :prop=\"item.prop\"\r\n @click.native.stop=\"noop\"\r\n >\r\n <template v-if=\"item.formtype\">\r\n <render-dom-form\r\n :row=\"item\"\r\n :render=\"formInputComponents(item)\"\r\n :index=\"index\"\r\n :model=\"model\"\r\n />\r\n </template>\r\n <template v-else-if=\"item.render\">\r\n <render-dom-form\r\n :row=\"item\"\r\n :render=\"item.render\"\r\n :index=\"index\"\r\n :model=\"model\"\r\n />\r\n </template>\r\n </el-form-item>\r\n </el-col>\r\n </template>\r\n\r\n <template v-if=\"!isBtnHidden\">\r\n <render-btn\r\n v-if=\"isRenderBtn\"\r\n :row=\"{ isFold, folded, getBtnColSpan, getRowColsAlgorithm, changeFolded, refsForm: formInstance }\"\r\n :form-model=\"model\"\r\n :form-item-list=\"formItem\"\r\n :render=\"renderBtn\"\r\n />\r\n <el-col v-else :span=\"btnColSpanRow ? 24 : getBtnColSpan\">\r\n <!-- btnColSpanRow=true 时左右分布 -->\r\n <div\r\n v-if=\"btnColSpanRow && configBtn.length\"\r\n class=\"buttonOperate leftRightBtn\"\r\n >\r\n <div class=\"btn-left\">\r\n <el-form-item label-width=\"0px\" class=\"btn-formItem\">\r\n <template v-for=\"(it, inx) in colRightLeftList.colLeftBtn\">\r\n <el-button\r\n v-if=\"checkPermission(it.permissionValue)\"\r\n :key=\"it.key || inx\"\r\n v-bind=\"filterOptions(it)\"\r\n :icon=\"getCompIcon(it.icon)\"\r\n :disabled=\"resolveDisabled(it)\"\r\n @click=\"handleBtnClick(it)\"\r\n >\r\n {{ it.name }}\r\n </el-button>\r\n </template>\r\n </el-form-item>\r\n </div>\r\n <div class=\"btn-right\">\r\n <el-form-item label-width=\"0px\" class=\"btn-formItem\">\r\n <template v-for=\"(it, inx) in colRightLeftList.colRightBtn\">\r\n <el-button\r\n v-if=\"checkPermission(it.permissionValue)\"\r\n :key=\"it.key || inx\"\r\n v-bind=\"filterOptions(it)\"\r\n :icon=\"getCompIcon(it.icon)\"\r\n :disabled=\"resolveDisabled(it)\"\r\n @click=\"clickBtn(it)\"\r\n >\r\n {{ it.name }}\r\n </el-button>\r\n </template>\r\n <el-button\r\n v-if=\"isFold\"\r\n type=\"text\"\r\n :icon=\"folded ? 'el-icon-arrow-down' : 'el-icon-arrow-up'\"\r\n style=\"padding-left: 0; border: none\"\r\n @click=\"changeFolded\"\r\n >\r\n {{ folded ? '展开' : '收起' }}\r\n </el-button>\r\n </el-form-item>\r\n </div>\r\n </div>\r\n <!-- btnColSpanRow=false 时单行布局 -->\r\n <el-form-item\r\n v-if=\"!btnColSpanRow && configBtn.length\"\r\n :label=\"' '\"\r\n :label-width=\"formProps.labelBtnWidth ? formProps.labelBtnWidth : formProps.labelWidth\"\r\n :class=\"{ formItemCols: btnColSpanRow ? true : getBtnColSpan === 24 }\"\r\n class=\"btn-formItem\"\r\n >\r\n <div\r\n class=\"buttonOperate\"\r\n :style=\"{ 'text-align': getBtnColSpan === 24 ? 'right' : 'left' }\"\r\n >\r\n <template v-for=\"(it, inx) in configBtn\">\r\n <el-button\r\n v-if=\"checkPermission(it.permissionValue)\"\r\n :key=\"it.key || inx\"\r\n v-bind=\"filterOptions(it)\"\r\n :icon=\"getCompIcon(it.icon)\"\r\n :disabled=\"resolveDisabled(it)\"\r\n @click=\"handleBtnClick(it)\"\r\n >\r\n {{ it.name }}\r\n </el-button>\r\n </template>\r\n <el-button\r\n v-if=\"isFold\"\r\n type=\"text\"\r\n :icon=\"folded ? 'el-icon-arrow-down' : 'el-icon-arrow-up'\"\r\n style=\"padding-left: 0; border: none\"\r\n @click=\"changeFolded\"\r\n >\r\n {{ folded ? '展开' : '收起' }}\r\n </el-button>\r\n </div>\r\n </el-form-item>\r\n </el-col>\r\n </template>\r\n </el-row>\r\n </div>\r\n </el-form>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsForm —— Vue 2 + Element UI 配置化表单\r\n *\r\n * 与 Vue 3 + Element Plus 版本(packages/vue3/.../es-form.vue)的功能等价点:\r\n * - 24 栅格自动布局 / 折叠展开\r\n * - 13 种内置 formtype\r\n * - 远端 dataOptions 加载(apiParams + httpRequest)\r\n * - 工具栏按钮(左右分布、权限过滤、内置 query/rest 行为)\r\n * - 与 EsTable 联动(通过 inject getTableInstantce)\r\n * - exposed 方法:validate / resetFields / clearValidate / scrollToField\r\n *\r\n * Vue 2 关键差异点:\r\n * - 使用 defineComponent + setup() 替代 <script setup>\r\n * - 取 formRef 用 templateRefs().formRef(而非 Vue 3 的 ref())\r\n * - 图标改为字符串 class(el-icon-xxx)替代 Element Plus 图标组件\r\n * - 工具栏 dropdown 暂未实现自定义查询/自定义表格 → 后续 phase 5 验证后再补\r\n */\r\n\r\nimport { defineComponent, ref, computed, watch, inject, getCurrentInstance, nextTick, h, type PropType } from '../../vue-compat'\r\nimport { useFormInputs } from '../../composables/use-form-inputs'\r\nimport { useFormLayout } from '../../composables/use-form-layout'\r\nimport { useFormRequest } from '../../composables/use-form-request'\r\nimport { mapSize } from '../../utils/size'\r\nimport { getGlobalConfig, resolveFormLayProps } from '@es-plus/core'\r\nimport type { FormItemOption, BtnConfig, LayoutFormProps, ModelData } from '@es-plus/core'\r\n\r\n/**\r\n * 内联子组件:渲染 form-input 函数返回的 VNode\r\n *\r\n * 与 Vue 3 版本不同,Vue 2 中 render 函数签名为 (createElement, ctx),\r\n * 因此这里把传入的 render(已是 useFormInputs 暴露的 (h, model, ctx) 风格)\r\n * 桥接为 functional 组件。\r\n */\r\nconst RenderDomForm = defineComponent({\r\n name: 'RenderDomForm',\r\n functional: true,\r\n props: {\r\n row: { type: Object as PropType<FormItemOption>, default: () => ({}) },\r\n index: { type: Number, default: 0 },\r\n render: { type: Function, default: undefined },\r\n model: { type: Object as PropType<ModelData>, default: () => ({}) },\r\n },\r\n render(createElement, ctx) {\r\n const { row, index, model, render } = ctx.props\r\n if (typeof render !== 'function') return null\r\n const safeRow = row || {}\r\n const renderContent = render(createElement, model || {}, { row: safeRow, index })\r\n return typeof renderContent === 'string' ? createElement('span', renderContent) : renderContent\r\n },\r\n})\r\n\r\n/**\r\n * 自定义按钮区渲染(用户传 renderBtn 时使用)\r\n */\r\nconst RenderBtn = defineComponent({\r\n name: 'RenderBtn',\r\n functional: true,\r\n props: {\r\n row: { type: Object, default: () => ({}) },\r\n formItemList: { type: Array, default: () => [] },\r\n formModel: { type: Object, default: () => ({}) },\r\n render: { type: Function, default: undefined },\r\n },\r\n render(createElement, ctx) {\r\n const { formItemList, formModel, row, render } = ctx.props\r\n if (typeof render !== 'function') return null\r\n const renderContent = render(row, formModel, formItemList, createElement) || ''\r\n return typeof renderContent === 'string' ? createElement('span', renderContent) : renderContent\r\n },\r\n})\r\n\r\nexport default defineComponent({\r\n name: 'EsForm',\r\n components: { RenderDomForm, RenderBtn },\r\n props: {\r\n /** 表单 model 数据 */\r\n model: { type: Object as PropType<ModelData>, default: () => ({}) },\r\n /** 表单字段配置 */\r\n formItemList: { type: Array as PropType<FormItemOption[]>, default: () => [] },\r\n /** 布局配置 */\r\n layoutFormProps: { type: Object as PropType<LayoutFormProps>, default: () => ({}) },\r\n /** 工具栏按钮 */\r\n configBtn: { type: Array as PropType<BtnConfig[]>, default: () => [] },\r\n /** 自定义按钮区渲染函数 */\r\n renderBtn: { type: [Function, Boolean] as PropType<((row: object, model: ModelData, list: FormItemOption[], h: Function) => unknown) | boolean>, default: false },\r\n /** 是否一行内左右分布按钮 */\r\n btnColSpanRow: { type: Boolean, default: true },\r\n /** 校验规则 */\r\n rules: { type: Object as PropType<Record<string, unknown>>, default: () => ({}) },\r\n /** 字段映射注入函数 */\r\n fieldFieldOutput: { type: Function as PropType<(defaults: Record<string, string>) => Record<string, string>>, default: undefined },\r\n },\r\n setup(props, ctx) {\r\n const instance = getCurrentInstance()\r\n /**\r\n * Vue 2.7 的 setup(props, ctx) 中 ctx 仅有 attrs/listeners/slots/emit/expose,\r\n * 并不存在 ctx.refs。模板里 ref=\"formRef\" 拿到的实例只能从组件代理 vm.$refs 上读取。\r\n * 这里包一层 proxy 访问器,所有需要拿 formRef 的地方统一走 templateRefs.formRef。\r\n */\r\n const templateRefs = (): Record<string, unknown> => {\r\n const proxy = (instance as unknown as { proxy?: Record<string, unknown> } | null)?.proxy\r\n return ((proxy?.$refs as Record<string, unknown>) || {})\r\n }\r\n\r\n /**\r\n * 解析真实的 form data model —— 统一从两个来源回退:\r\n *\r\n * 1. `$vnode.data.model` —— 兼容 JSX `<es-form model={data} />`。\r\n * 背景:@vue/babel-preset-jsx@1.4.0 把 `model` 列为 rootAttribute,所以 JSX\r\n * `<es-form model={x} />` 编译产物是 `h(EsForm, { attrs: {...}, model: x })`,\r\n * `model` 落在 data 根级而非 attrs。Vue 2 运行时随后调用 transformModel,\r\n * 期待 v-model 形状 `{ value, callback }`,把 data.attrs.value = data.model.value\r\n * 写回;但用户传入的是普通数据对象,既无 .value 也无 .callback,结果\r\n * props.model 收到默认 `{}`。判定:若值为非空对象且 .callback 不是函数,则视为\r\n * 用户数据对象。\r\n *\r\n * 2. `props.model`(兜底)—— template `:model=\"x\"` 或真正的 v-model 走这里。\r\n */\r\n const resolvedModel = computed<ModelData>(() => {\r\n const proxy = (instance as unknown as { proxy?: { $vnode?: { data?: { model?: unknown } } } } | null)?.proxy\r\n const rawJsxModel = proxy?.$vnode?.data?.model\r\n if (\r\n rawJsxModel &&\r\n typeof rawJsxModel === 'object' &&\r\n typeof (rawJsxModel as { callback?: unknown }).callback !== 'function'\r\n ) {\r\n return rawJsxModel as ModelData\r\n }\r\n return props.model\r\n })\r\n const $esPlusForm = (inject('$esPlusForm', null) as Record<string, unknown> | null) ?? getGlobalConfig().EsForm ?? {}\r\n const esPlus = (inject('$EsPlus', null) as Record<string, unknown> | null) ?? getGlobalConfig() ?? {}\r\n\r\n // ─── 权限 / i18n ──\r\n const checkPermission = (pvalue?: string): boolean => {\r\n if (!pvalue) return true\r\n const fn = esPlus.permission as ((v: string) => boolean) | undefined\r\n return typeof fn === 'function' ? fn(pvalue) : true\r\n }\r\n const translateLabel = (item: FormItemOption): string => {\r\n if (item.labelKey && typeof esPlus.t === 'function') {\r\n return (esPlus.t as (k: string) => string)(item.labelKey)\r\n }\r\n return item.label\r\n }\r\n\r\n // ─── 与 EsTable 联动 ──\r\n const injectedTableInstant = inject<(() => unknown) | null>('getTableInstantce', null)\r\n const getTableInstant = computed(() => {\r\n if (injectedTableInstant) {\r\n return typeof injectedTableInstant === 'function'\r\n ? injectedTableInstant()\r\n : injectedTableInstant\r\n }\r\n const proxy = (instance as unknown as { proxy?: Record<string, unknown> })?.proxy\r\n const fn = proxy?.getTableInstantce\r\n if (typeof fn === 'function') return (fn as () => unknown)()\r\n return fn\r\n })\r\n const isParentTable = computed(() => {\r\n const t = getTableInstant.value as Record<string, unknown> | null | undefined\r\n return !!(t && Object.keys(t).length)\r\n })\r\n\r\n // ─── 图标处理(Element UI 用 class 字符串) ──\r\n const getCompIcon = (key?: string): string | undefined => {\r\n if (!key) return undefined\r\n // 兼容 Element Plus 图标名(如 'Plus')→ 'el-icon-plus'\r\n // 已经是 el-icon-xxx 的直接返回\r\n if (key.startsWith('el-icon-')) return key\r\n // PascalCase → kebab-case\r\n const kebab = key.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/[\\s_]+/g, '-').toLowerCase()\r\n return `el-icon-${kebab}`\r\n }\r\n const filterOptions = (it: BtnConfig) => {\r\n const { icon: _icon, ...opt } = it as unknown as Record<string, unknown>\r\n // 把用户传入的 size 经 mapSize 翻译到 Element UI v2 语义;缺省时与表单默认尺寸\r\n // (mini) 对齐,避免按钮比表单输入大一截。详见 packages/vue2/src/utils/size.ts。\r\n if (opt.size !== undefined) {\r\n const mapped = mapSize(opt.size)\r\n if (mapped !== undefined) opt.size = mapped\r\n } else {\r\n opt.size = 'mini'\r\n }\r\n return opt\r\n }\r\n const resolveDisabled = (it: BtnConfig): boolean => {\r\n const d = it.disabled\r\n if (typeof d === 'function') return Boolean((d as () => boolean | undefined)())\r\n return Boolean(d)\r\n }\r\n\r\n // ─── refs ──\r\n const formInstance = ref<Record<string, unknown>>({})\r\n const formItemRowsList = ref<FormItemOption[]>(props.formItemList || [])\r\n\r\n // ─── composables ──\r\n const { formInputComponents } = useFormInputs()\r\n const httpRequestGlobal = ($esPlusForm?.$httpRequest as ((p: Record<string, unknown>) => Promise<unknown>) | undefined) || undefined\r\n const fieldFieldOutputGlobal = (props.fieldFieldOutput || $esPlusForm?.fieldFieldOutput) as\r\n | ((defaults: Record<string, string>) => Record<string, string>)\r\n | undefined\r\n const { getEveryFormQueryField } = useFormRequest(httpRequestGlobal)\r\n\r\n // ─── formProps (供 el-form 使用) ──\r\n const formLayoutRef = ref<Record<string, unknown>>(resolveFormLayProps(props.layoutFormProps) as Record<string, unknown>)\r\n /**\r\n * Element UI v2 的 el-form 在 `labelWidth` 缺省时会让 label 浮动在自然位置,\r\n * 当外层是 flex/wrap 布局且 label 较长时会被挤到 input 上方(label 与 content 分行),\r\n * 严重破坏栅格视觉。原 es-eui 的 esForm 对此做了缺省 `labelWidth: 'auto'` 的兜底\r\n * (详见 es-eui/src/components/es-eui/esForm/src/esForm.vue 的 fromProps 计算属性)。\r\n *\r\n * 这里保持同样的兜底策略,确保未显式传 labelWidth 时 label 与 content 同行展示。\r\n *\r\n * 默认 size 与原 es-eui 对齐为 `mini`(el-form size=mini 时表单控件高度 ≈ 28px),\r\n * 同时通过 mapSize 把用户从 Vue 3 / Element Plus 习惯传来的 `large/default/small`\r\n * 自动转译为 Element UI v2 语义,避免两个版本\"同一份配置渲染出明显不同尺寸\"。\r\n */\r\n const formProps = computed<Record<string, unknown>>(() => {\r\n const userLayout = formLayoutRef.value || {}\r\n const merged: Record<string, unknown> = {\r\n size: 'mini',\r\n ...userLayout,\r\n model: resolvedModel.value,\r\n rules: props.rules,\r\n validateOnRuleChange: false,\r\n }\r\n const mapped = mapSize(merged.size)\r\n if (mapped !== undefined) merged.size = mapped\r\n if (merged.labelWidth === undefined || merged.labelWidth === '' || merged.labelWidth === null) {\r\n merged.labelWidth = 'auto'\r\n }\r\n return merged\r\n })\r\n\r\n // ─── 远端选项加载(仅对未加载过的字段执行) ──\r\n const loadedApiProps = ref<Set<string>>(new Set<string>())\r\n\r\n watch(\r\n () => props.formItemList,\r\n async (val) => {\r\n const list = Array.isArray(val) ? val : []\r\n const needLoadList = list.filter(\r\n (it) => it && it.isInitRun !== false && !loadedApiProps.value.has(it.prop)\r\n )\r\n if (!needLoadList.length) {\r\n formItemRowsList.value = list\r\n .map((it) => {\r\n if (!it) return null\r\n const existing = formItemRowsList.value.find((old) => old && old.prop === it.prop)\r\n return existing?.dataOptions?.length ? { ...it, dataOptions: existing.dataOptions } : it\r\n })\r\n .filter((it): it is FormItemOption => !!it)\r\n return\r\n }\r\n const rows = await getEveryFormQueryField(needLoadList, fieldFieldOutputGlobal)\r\n needLoadList.forEach((it) => loadedApiProps.value.add(it.prop))\r\n formItemRowsList.value = list\r\n .map((it) => {\r\n if (!it) return null\r\n const fromApi = rows.find((r) => r && r.prop === it.prop)\r\n const existing = formItemRowsList.value.find((old) => old && old.prop === it.prop)\r\n if (fromApi) {\r\n return {\r\n ...it,\r\n dataOptions: fromApi.listData as Array<{ label: string; value: unknown }>,\r\n }\r\n }\r\n if (existing?.dataOptions?.length) return { ...it, dataOptions: existing.dataOptions }\r\n return it\r\n })\r\n .filter((it): it is FormItemOption => !!it)\r\n },\r\n { immediate: true, deep: true }\r\n )\r\n\r\n // ─── 可见 + auto-span 计算 ──\r\n const formItemListFilter = computed(() => {\r\n const list = formItemRowsList.value || []\r\n const visible = list\r\n .map((it) => (it ? { ...it, dataOptions: it.dataOptions || [] } : null))\r\n .filter((it): it is FormItemOption & { dataOptions: Array<{ label: string; value: unknown }> } => {\r\n if (!it) return false\r\n // 字段名兼容:原 es-eui 用 `isHiden`(少一个 d,原始拼写错误),\r\n // 后续规范化为 `isHidden`。两者都接受,原始拼写优先(保持旧文档案例可直接运行)。\r\n const legacyHide = (it as unknown as { isHiden?: unknown }).isHiden\r\n const fixedHide = it.isHidden\r\n const hideFn = typeof legacyHide === 'function'\r\n ? (legacyHide as (m: ModelData, item: FormItemOption, props: Record<string, unknown>) => boolean)\r\n : typeof fixedHide === 'function'\r\n ? fixedHide\r\n : null\r\n if (hideFn) {\r\n return !hideFn(resolvedModel.value, it, formProps.value)\r\n }\r\n return true\r\n })\r\n\r\n const itemsWithoutSpan = visible.filter((it) => !it.span)\r\n const autoCount = itemsWithoutSpan.length\r\n let autoSpan = 6\r\n if (autoCount > 0) {\r\n const fixedTotal = visible.reduce((sum, it) => sum + (it.span || 0), 0)\r\n const remaining = 24 - (fixedTotal % 24 || (fixedTotal ? 24 : 0))\r\n if (fixedTotal === 0) {\r\n if (autoCount === 1) autoSpan = 24\r\n else if (autoCount === 2) autoSpan = 12\r\n else if (autoCount === 3) autoSpan = 8\r\n else autoSpan = 6\r\n } else {\r\n autoSpan = remaining >= autoCount ? Math.floor(remaining / autoCount) : 6\r\n if (autoSpan > 12) autoSpan = 12\r\n if (autoSpan < 4) autoSpan = 6\r\n }\r\n }\r\n return visible.map((it) => ({ ...it, span: it.span || autoSpan }))\r\n })\r\n\r\n const layoutResult = useFormLayout({\r\n layoutFormProps: props.layoutFormProps,\r\n get formItemList() {\r\n return formItemListFilter.value\r\n },\r\n } as never)\r\n\r\n const {\r\n folded,\r\n isBtnHidden,\r\n rowLayout,\r\n formLayout,\r\n getRowColsAlgorithm,\r\n isFold,\r\n getBtnColSpan,\r\n formItem,\r\n changeFolded,\r\n } = layoutResult\r\n\r\n watch(\r\n formLayout,\r\n (val: Record<string, unknown>) => {\r\n formLayoutRef.value = val\r\n },\r\n { immediate: true }\r\n )\r\n\r\n // ─── 按钮分组(左右) ──\r\n const colRightLeftList = computed(() => ({\r\n colRightBtn: props.configBtn.filter((it) => it.direction === 'right' || !it.direction),\r\n colLeftBtn: props.configBtn.filter((it) => it.direction === 'left'),\r\n }))\r\n\r\n const isRenderBtn = computed(() => typeof props.renderBtn === 'function')\r\n\r\n // ─── 按钮点击逻辑 ──\r\n const handleBtnClick = (it: BtnConfig) => {\r\n const formRef = (templateRefs().formRef as unknown) as Record<string, unknown> | null\r\n const httpFn = (getTableInstant.value as { httpRequestInstance?: (p: unknown) => void } | null)?.httpRequestInstance\r\n it.click?.(resolvedModel.value, formRef as unknown, httpFn)\r\n }\r\n\r\n const queryTableRequest = (model: ModelData, formRef: { resetFields?: () => void } | null, key?: string) => {\r\n const t = getTableInstant.value as { httpRequestInstance?: (p: unknown) => void } | null\r\n if (key === 'query') {\r\n if (isParentTable.value) {\r\n t?.httpRequestInstance?.(model)\r\n }\r\n } else if (key === 'rest' && formRef) {\r\n if (isParentTable.value) {\r\n t?.httpRequestInstance?.(model)\r\n }\r\n formRef.resetFields?.()\r\n }\r\n }\r\n\r\n const clickBtn = (it: BtnConfig) => {\r\n const formRef = (templateRefs().formRef as unknown) as { resetFields?: () => void } | null\r\n if (it.triggerEvent && ['query', 'rest'].includes(it.key || '')) {\r\n queryTableRequest(resolvedModel.value, formRef, it.key)\r\n } else {\r\n if (it.key === 'rest' && formRef) {\r\n formRef.resetFields?.()\r\n }\r\n const httpFn = (getTableInstant.value as { httpRequestInstance?: (p: unknown) => void } | null)?.httpRequestInstance\r\n it.click?.(resolvedModel.value, formRef as unknown, httpFn)\r\n }\r\n }\r\n\r\n const initFormItemOptions = (opts: Record<string, unknown>) => {\r\n if (isParentTable.value) {\r\n const { style, ...rest } = opts\r\n return { style: { marginBottom: '10px', ...((style as Record<string, unknown>) || {}) }, ...rest }\r\n }\r\n return opts\r\n }\r\n\r\n // ─── 暴露给外部的方法 ──\r\n const getFormRef = () => templateRefs().formRef as unknown as {\r\n validate: (cb?: (valid: boolean) => void) => Promise<boolean>\r\n resetFields: () => void\r\n clearValidate: (props?: string | string[]) => void\r\n validateField: (props: string | string[], cb?: (msg: string) => void) => void\r\n }\r\n\r\n const validate = (): Promise<boolean> => {\r\n const ref = getFormRef()\r\n if (!ref) return Promise.resolve(false)\r\n // Element UI el-form.validate 接受 callback;若返回 Promise 我们以 callback 形式包装\r\n return new Promise<boolean>((resolve) => {\r\n try {\r\n const maybePromise = (ref as unknown as { validate: (cb: (valid: boolean) => void) => void | Promise<boolean> }).validate((valid: boolean) => {\r\n resolve(!!valid)\r\n })\r\n if (maybePromise && typeof (maybePromise as Promise<boolean>).then === 'function') {\r\n ;(maybePromise as Promise<boolean>).then(resolve).catch(() => resolve(false))\r\n }\r\n } catch (e) {\r\n resolve(false)\r\n }\r\n })\r\n }\r\n const resetFields = () => getFormRef()?.resetFields()\r\n const clearValidate = (p?: string | string[]) => getFormRef()?.clearValidate(p)\r\n const validateField = (p: string | string[]) => getFormRef()?.validateField(p)\r\n\r\n const formItmeRequestInstance = async (propsList: string[]) => {\r\n const list = formItemListFilter.value\r\n const targetItems = list.filter((it) => it && propsList.includes(it.prop))\r\n if (!targetItems.length) return\r\n const rows = await getEveryFormQueryField(targetItems, fieldFieldOutputGlobal)\r\n rows.forEach((apiOption) => {\r\n if (!apiOption) return\r\n const itemIndex = formItemRowsList.value.findIndex((it) => it && it.prop === apiOption.prop)\r\n if (itemIndex !== -1) {\r\n formItemRowsList.value[itemIndex] = {\r\n ...formItemRowsList.value[itemIndex],\r\n dataOptions: apiOption.listData as Array<{ label: string; value: unknown }>,\r\n }\r\n }\r\n })\r\n }\r\n\r\n nextTick(() => {\r\n formInstance.value = templateRefs().formRef as unknown as Record<string, unknown>\r\n const proxy = (instance as unknown as { proxy?: Record<string, unknown> })?.proxy\r\n const bodyFormFn = proxy?.bodyFormInstance as ((inst: Record<string, unknown>) => void) | undefined\r\n bodyFormFn?.(formInstance.value)\r\n })\r\n\r\n // 暴露给 ref 拿到的 expose(Vue 2 + composition-api 用 expose;Vue 2.7 setupContext 也支持)\r\n if (typeof (ctx as unknown as { expose?: (e: Record<string, unknown>) => void }).expose === 'function') {\r\n ;(ctx as unknown as { expose: (e: Record<string, unknown>) => void }).expose({\r\n formItmeRequestInstance,\r\n getFormRef,\r\n validate,\r\n resetFields,\r\n clearValidate,\r\n validateField,\r\n })\r\n }\r\n\r\n return {\r\n // 模板使用\r\n formProps,\r\n rowLayout,\r\n formItem,\r\n isBtnHidden,\r\n isFold,\r\n folded,\r\n getBtnColSpan,\r\n isRenderBtn,\r\n colRightLeftList,\r\n configBtn: computed(() => props.configBtn),\r\n formInputComponents,\r\n formInstance,\r\n model: resolvedModel,\r\n btnColSpanRow: computed(() => props.btnColSpanRow),\r\n renderBtn: computed(() => props.renderBtn),\r\n getRowColsAlgorithm,\r\n changeFolded,\r\n // 方法\r\n checkPermission,\r\n translateLabel,\r\n getCompIcon,\r\n filterOptions,\r\n resolveDisabled,\r\n handleBtnClick,\r\n clickBtn,\r\n initFormItemOptions,\r\n noop: () => {},\r\n // expose 公开方法(供 $refs.<esForm>.validate() 直接调用,不经过 ctx.expose)\r\n formItmeRequestInstance,\r\n getFormRef,\r\n validate,\r\n resetFields,\r\n clearValidate,\r\n validateField,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.es-form {\r\n /**\r\n * 修复 Element UI v2 的栅格布局错乱问题。\r\n *\r\n * 默认的 el-row 是 float 布局,子 el-col 高度不一致时会出现「卡进上一列尾部留白」\r\n * 的换行错乱。我们在 use-form-layout 中默认给 el-row 加了 type=\"flex\",\r\n * 但 Element UI 的 .el-row--flex 没有自带 flex-wrap,需要这里补上。\r\n *\r\n * 这个写法只影响 .es-form 内部的 el-row,不污染外部的栅格布局。\r\n */\r\n ::v-deep(.el-row--flex) {\r\n flex-wrap: wrap;\r\n }\r\n ::v-deep(.el-form-item) {\r\n margin-bottom: 18px;\r\n }\r\n ::v-deep(.el-form-item__label) {\r\n font-weight: 500;\r\n }\r\n .buttonOperate {\r\n display: flex;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n }\r\n .leftRightBtn {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n width: 100%;\r\n .btn-left,\r\n .btn-right {\r\n display: flex;\r\n align-items: center;\r\n }\r\n }\r\n .btn-formItem {\r\n margin-bottom: 0;\r\n }\r\n .formItemCols {\r\n width: 100%;\r\n }\r\n}\r\n</style>\r\n","/**\r\n * EsForm 组件入口\r\n *\r\n * 提供两种导入方式:\r\n * 1. 默认导入:import EsForm from '@es-plus/vue2/es-form'\r\n * 2. install 安装:通过 Vue.use(EsPlus) 全局注册\r\n */\r\n\r\nimport EsForm from './es-form.vue'\r\nimport type { Vue } from '../../vue-compat'\r\n\r\n// Element UI 组件作为 EsForm 的依赖,由用户在 main.js 中通过 Vue.use(ElementUI) 全局注册。\r\n// 这里不重复注册,但提供 install 函数让 Vue.use(EsForm) 也能局部使用。\r\n;(EsForm as unknown as { install: (V: typeof Vue) => void }).install = function (Vue) {\r\n Vue.component((EsForm as unknown as { name: string }).name || 'EsForm', EsForm)\r\n}\r\n\r\nexport default EsForm\r\nexport { EsForm }\r\n","<template>\r\n <!-- 分组列处理 -->\r\n <el-table-column\r\n v-if=\"cols.groups && Array.isArray(cols.groups)\"\r\n v-bind=\"columnBindAttr(cols)\"\r\n >\r\n <el-table-column\r\n v-for=\"(item, index) in cols.groups\"\r\n :key=\"item.prop || item.key || index\"\r\n v-bind=\"columnBindAttr(Object.assign({}, item, { columnIndex: index }))\"\r\n >\r\n <template v-if=\"item.render && typeof item.render === 'function'\" #default=\"scope\">\r\n <render-dom-tb\r\n v-if=\"scope && scope.row\"\r\n :row=\"scope.row\"\r\n :index=\"scope.$index\"\r\n :data-key=\"item.key\"\r\n :render=\"item.render\"\r\n />\r\n <span v-else>-</span>\r\n </template>\r\n <template v-else-if=\"item.scopedSlots && item.scopedSlots.customRender\" #default=\"scope\">\r\n <slot\r\n v-if=\"scope && scope.row\"\r\n v-bind=\"Object.assign({}, item, { row: scope.row, column: scope.column, scope: scope })\"\r\n :name=\"item.scopedSlots.customRender\"\r\n />\r\n <span v-else>-</span>\r\n </template>\r\n </el-table-column>\r\n </el-table-column>\r\n\r\n <!-- 自定义渲染函数列 -->\r\n <el-table-column\r\n v-else-if=\"cols.render && typeof cols.render === 'function'\"\r\n v-bind=\"columnBindAttr(cols)\"\r\n >\r\n <template #default=\"scope\">\r\n <render-dom-tb\r\n v-if=\"scope && scope.row\"\r\n :row=\"scope.row\"\r\n :index=\"scope.$index\"\r\n :data-key=\"cols.key\"\r\n :render=\"cols.render\"\r\n />\r\n <span v-else>-</span>\r\n </template>\r\n </el-table-column>\r\n\r\n <!-- 作用域插槽列 -->\r\n <el-table-column\r\n v-else-if=\"cols.scopedSlots && cols.scopedSlots.customRender\"\r\n v-bind=\"columnBindAttr(cols)\"\r\n >\r\n <template #default=\"scope\">\r\n <slot\r\n v-if=\"scope && scope.row\"\r\n v-bind=\"Object.assign({}, cols, { row: scope.row, column: scope.column, scope: scope })\"\r\n :name=\"cols.scopedSlots.customRender\"\r\n />\r\n <span v-else>-</span>\r\n </template>\r\n </el-table-column>\r\n\r\n <!-- 省略号工具提示列 -->\r\n <el-table-column\r\n v-else-if=\"cols.ellipsis && typeof cols.ellipsis === 'boolean'\"\r\n show-overflow-tooltip\r\n v-bind=\"columnBindAttr(cols)\"\r\n />\r\n\r\n <!-- 普通列 -->\r\n <el-table-column v-else v-bind=\"columnBindAttr(cols)\" />\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsTable 列递归渲染组件 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - 不使用 <script setup>,改为 defineComponent + setup()\r\n * - h 来自 './vue-compat'(实际是 Vue 2 的 createElement)\r\n * - inject 来自 @vue/composition-api,签名一致\r\n * - el-table-column 在 Element UI 与 Element Plus 中 API 基本一致\r\n *\r\n * 列配置约定:\r\n * - cols.groups: 嵌套表头(多级表头)\r\n * - cols.render: 自定义渲染函数 (h, { value, row, index }) => VNode\r\n * - cols.scopedSlots.customRender: 作用域插槽名称\r\n * - cols.ellipsis: 文字超出时显示 tooltip\r\n * - cols.key: 数据字段(自动映射为 prop)\r\n * - cols.labelKey: 国际化 label 键\r\n */\r\n\r\nimport { h, defineComponent, inject } from '../../vue-compat'\r\nimport { getGlobalConfig } from '@es-plus/core'\r\nimport type { TableColumn } from '../../types'\r\n\r\n// 函数式 render 包装组件 —— 把用户传入的 render(h, ctx) 渲染为 VNode\r\nconst RenderDomTb = defineComponent({\r\n name: 'RenderDomTb',\r\n props: {\r\n row: { type: Object, default: () => ({}) },\r\n index: { type: Number, default: 0 },\r\n dataKey: String,\r\n render: { type: Function, required: true },\r\n },\r\n setup(props: any) {\r\n return () => {\r\n const { row, index, dataKey, render } = props\r\n if (!row) return h('span', '-')\r\n const value = dataKey ? row[dataKey] : null\r\n try {\r\n const renderResult = render(h, { value, row, index })\r\n if (typeof renderResult === 'string') return h('span', renderResult)\r\n return renderResult\r\n } catch (error) {\r\n return h('span', '-')\r\n }\r\n }\r\n },\r\n})\r\n\r\nconst firstWordUpperCase = (str: string): string => {\r\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'EsTableColumnItem',\r\n components: { RenderDomTb },\r\n props: {\r\n cols: {\r\n type: Object as () => TableColumn,\r\n required: true,\r\n },\r\n },\r\n setup() {\r\n // 注入全局 EsPlus 配置(含 i18n t 函数)\r\n const esPlus =\r\n inject<Record<string, unknown>>('$EsPlus', null as unknown as Record<string, unknown>) ??\r\n (getGlobalConfig() as Record<string, unknown>) ??\r\n {}\r\n\r\n /**\r\n * 把用户写的列配置规范化为 el-table-column 的 props\r\n * - 跳过 groups/scopedSlots/render(它们走单独的渲染路径)\r\n * - 中划线属性自动转驼峰(如 'show-overflow-tooltip' → 'showOverflowTooltip')\r\n * - key → prop 双向映射\r\n * - labelKey + 全局 t 函数 → 国际化 label\r\n * - 默认 align: center(与 Vue 3 版本保持一致)\r\n */\r\n const columnBindAttr = (cols: TableColumn) => {\r\n const options: Record<string, unknown> = {}\r\n\r\n for (const t in cols) {\r\n if (t === 'groups' || t === 'scopedSlots' || t === 'render') continue\r\n\r\n if (t.includes('-')) {\r\n const parts = t.split('-')\r\n let camelKey = parts[0]\r\n for (let i = 1; i < parts.length; i++) {\r\n camelKey += firstWordUpperCase(parts[i])\r\n }\r\n options[camelKey] = (cols as Record<string, unknown>)[t]\r\n } else if (t === 'key') {\r\n options.prop = (cols as Record<string, unknown>)[t]\r\n options[t] = (cols as Record<string, unknown>)[t]\r\n } else if (t === 'label' && cols.labelKey && typeof esPlus.t === 'function') {\r\n options.label = (esPlus.t as (k: string) => string)(cols.labelKey as string)\r\n } else {\r\n options[t] = (cols as Record<string, unknown>)[t]\r\n }\r\n }\r\n\r\n if (!options.align) {\r\n options.align = 'center'\r\n }\r\n\r\n return options\r\n }\r\n\r\n return {\r\n columnBindAttr,\r\n }\r\n },\r\n})\r\n</script>\r\n","/**\r\n * Element UI 图标适配工具\r\n *\r\n * Element Plus 使用图标组件(如 `<Plus />`),Element UI 使用 class 字符串(如 `el-icon-plus`)。\r\n * 用户配置可能传入:\r\n * - 'Plus' (Element Plus 风格 PascalCase)\r\n * - 'el-icon-plus' (Element UI 原生 class)\r\n * - 'plus' (短名)\r\n *\r\n * 本函数统一规范化为 Element UI 的 class 字符串。\r\n */\r\nexport const getCompIcon = (key?: string): string | undefined => {\r\n if (!key) return undefined\r\n // 已经是 el-icon-xxx 的直接返回\r\n if (key.startsWith('el-icon-')) return key\r\n // PascalCase / camelCase → kebab-case,并加 el-icon- 前缀\r\n const kebab = key\r\n .replace(/([a-z])([A-Z])/g, '$1-$2')\r\n .replace(/[\\s_]+/g, '-')\r\n .toLowerCase()\r\n return `el-icon-${kebab}`\r\n}\r\n","<template>\r\n <div v-if=\"showContainer\" class=\"flex-float btns\">\r\n <div class=\"left-text\">\r\n {{ leftText }}\r\n </div>\r\n\r\n <div class=\"btn-container_block\">\r\n <!-- 左侧按钮组 -->\r\n <div class=\"btn-left\">\r\n <template v-for=\"(item, index) in processedBtnLeft\">\r\n <div v-if=\"!item.isHide\" :key=\"item.name || index\" :style=\"buttonContainerStyle(index)\">\r\n <render-dom\r\n v-if=\"item.render && typeof item.render === 'function'\"\r\n :render=\"item.render\"\r\n />\r\n <el-button\r\n v-else\r\n :type=\"item.type || ''\"\r\n :size=\"resolveBtnSize(item)\"\r\n :icon=\"getCompIcon(item.icon)\"\r\n :loading=\"item.loading || false\"\r\n v-bind=\"filterOptions(item)\"\r\n :disabled=\"getDisabledState(item)\"\r\n @click=\"() => item.click && item.click(instance)\"\r\n >\r\n {{ item.name }}\r\n </el-button>\r\n </div>\r\n </template>\r\n </div>\r\n\r\n <!-- 右侧按钮组 -->\r\n <div class=\"btn-right\">\r\n <template v-for=\"(item, index) in processedBtnRight\">\r\n <div v-if=\"!item.isHide\" :key=\"item.name || index\" :style=\"buttonContainerStyle(index)\">\r\n <render-dom\r\n v-if=\"item.render && typeof item.render === 'function'\"\r\n :render=\"item.render\"\r\n />\r\n <el-button\r\n v-else\r\n :type=\"item.type || ''\"\r\n :size=\"resolveBtnSize(item)\"\r\n :icon=\"getCompIcon(item.icon)\"\r\n :loading=\"item.loading || false\"\r\n v-bind=\"filterOptions(item)\"\r\n :disabled=\"getDisabledState(item)\"\r\n @click=\"() => item.click && item.click(instance)\"\r\n >\r\n {{ item.name }}\r\n </el-button>\r\n </div>\r\n </template>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsTable 工具栏按钮组件 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - 不使用 <script setup>\r\n * - 图标用 el-icon-* class 字符串(getCompIcon 转换 Element Plus 风格)\r\n * - 按钮 v-bind 时排除 icon/render/click/permissionValue 等已单独处理或非 DOM 属性\r\n *\r\n * 按钮配置约定:\r\n * - code === 1: 渲染到左侧\r\n * - code === 2: 渲染到右侧\r\n * - permissionValue: 配合全局 esPlus.permission(value) 做权限过滤\r\n * - isHide: boolean | () => boolean,函数形式会被解析\r\n * - render: 用户自定义渲染函数\r\n * - click(instance): 点击回调,注入 EsTable 实例\r\n */\r\n\r\nimport { defineComponent, computed, inject, h } from '../../vue-compat'\r\nimport { getGlobalConfig, getButtonPosition, type BtnConfig } from '@es-plus/core'\r\nimport { getCompIcon } from '../../utils/icon'\r\nimport { mapSize } from '../../utils/size'\r\n\r\n/**\r\n * 工具栏按钮的运行时形状(在 BtnConfig 基础上加 isHide)\r\n *\r\n * BtnConfig 上的 `[key: string]: unknown` 索引签名会让 vue-tsc 在模板里\r\n * 把 item.name / item.icon / item.click 全部窄化成 unknown。这里显式\r\n * 用一个最小契约(只覆盖模板真正会用到的字段)来阻断那条索引签名,\r\n * 让 :key / :icon / @click 在生成 .d.ts 时通过类型校验。\r\n */\r\ntype RenderableBtn = {\r\n name?: string\r\n icon?: string\r\n click?: (...args: unknown[]) => void\r\n type?: string\r\n size?: string\r\n loading?: boolean\r\n disabled?: boolean | ((...args: unknown[]) => boolean)\r\n render?: (...args: unknown[]) => unknown\r\n isHide?: boolean\r\n permissionValue?: string\r\n code?: 1 | 2\r\n}\r\n\r\n// 函数式 render 包装组件\r\nconst RenderDom = defineComponent({\r\n name: 'RenderDomTbBtn',\r\n props: {\r\n render: { type: Function, required: true },\r\n },\r\n setup(props: any) {\r\n return () => {\r\n if (!props.render || typeof props.render !== 'function') return null\r\n try {\r\n return props.render()\r\n } catch {\r\n return null\r\n }\r\n }\r\n },\r\n})\r\n\r\nexport default defineComponent({\r\n name: 'EsTableBtns',\r\n components: { RenderDom },\r\n props: {\r\n leftText: { type: String, default: '' },\r\n btnConfig: {\r\n type: Array as () => BtnConfig[],\r\n default: () => [],\r\n },\r\n instance: {\r\n type: Object as () => Record<string, unknown>,\r\n default: () => ({}),\r\n },\r\n },\r\n setup(props) {\r\n const esPlus =\r\n inject<Record<string, unknown>>('$EsPlus', null as unknown as Record<string, unknown>) ??\r\n (getGlobalConfig() as Record<string, unknown>) ??\r\n {}\r\n\r\n const hasPermission = (_btnList: unknown[], pvalue?: string) => {\r\n if (!pvalue) return true\r\n const permFn = esPlus.permission\r\n if (typeof permFn === 'function') return (permFn as (v: string) => boolean)(pvalue)\r\n return true\r\n }\r\n\r\n const processButtonConfig = (config: Array<Record<string, unknown>>) => {\r\n return config.map((item) => {\r\n const processed = { ...item }\r\n const hasPerm = hasPermission([], item.permissionValue as string)\r\n\r\n if (!hasPerm) {\r\n processed.isHide = true\r\n } else if (typeof item.isHide === 'function') {\r\n processed.isHide = (item.isHide as () => boolean)()\r\n } else {\r\n processed.isHide = item.isHide || false\r\n }\r\n\r\n return processed\r\n })\r\n }\r\n\r\n const processedBtnLeft = computed<RenderableBtn[]>(() => {\r\n return processButtonConfig(\r\n (props.btnConfig || []).filter((item) => getButtonPosition(item as BtnConfig) === 'left') as Array<Record<string, unknown>>\r\n ).filter((item) => !item.isHide) as RenderableBtn[]\r\n })\r\n\r\n const processedBtnRight = computed<RenderableBtn[]>(() => {\r\n return processButtonConfig(\r\n (props.btnConfig || []).filter((item) => getButtonPosition(item as BtnConfig) === 'right') as Array<Record<string, unknown>>\r\n ).filter((item) => !item.isHide) as RenderableBtn[]\r\n })\r\n\r\n const showContainer = computed(() => {\r\n return (\r\n !!props.leftText ||\r\n processedBtnLeft.value.length > 0 ||\r\n processedBtnRight.value.length > 0\r\n )\r\n })\r\n\r\n const getDisabledState = (item: Record<string, unknown>): boolean => {\r\n if (typeof item.disabled === 'function') {\r\n return (item.disabled as () => boolean)()\r\n }\r\n return (item.disabled as boolean) || false\r\n }\r\n\r\n const buttonContainerStyle = (index: number) => {\r\n return {\r\n display: 'inline-block',\r\n marginLeft: index !== 0 ? '8px' : '0px',\r\n }\r\n }\r\n\r\n /**\r\n * 过滤掉非 el-button 原生 props 的字段,避免 v-bind 透传出错\r\n */\r\n const filterOptions = (item: Record<string, unknown>) => {\r\n const {\r\n render: _r,\r\n click: _c,\r\n icon: _i,\r\n permissionValue: _p,\r\n code: _co,\r\n isHide: _ih,\r\n name: _n,\r\n size: _s,\r\n ...rest\r\n } = item\r\n return rest\r\n }\r\n\r\n /**\r\n * 解析按钮尺寸:先按用户传入值经 mapSize 翻译为 Element UI v2 语义;\r\n * 用户未传时默认 mini,与 EsForm 的默认值保持一致,避免 EsTable 工具栏按钮\r\n * 比表单控件视觉上\"大一截\"。\r\n */\r\n const resolveBtnSize = (item: { size?: string }): string => {\r\n const mapped = mapSize(item.size)\r\n return mapped || 'mini'\r\n }\r\n\r\n return {\r\n processedBtnLeft,\r\n processedBtnRight,\r\n showContainer,\r\n getDisabledState,\r\n buttonContainerStyle,\r\n getCompIcon,\r\n filterOptions,\r\n resolveBtnSize,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.btns {\r\n padding: 0;\r\n padding-bottom: 5px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.left-text {\r\n color: rgb(125, 125, 125);\r\n font-size: 14px;\r\n}\r\n\r\n.btn-container_block {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n flex: 1;\r\n\r\n .btn-left {\r\n display: flex;\r\n justify-content: flex-start;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n }\r\n\r\n .btn-right {\r\n display: flex;\r\n justify-content: flex-end;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n }\r\n}\r\n\r\n@media (max-width: 768px) {\r\n .btns {\r\n flex-direction: column;\r\n align-items: flex-start;\r\n }\r\n\r\n .btn-container_block {\r\n flex-direction: column;\r\n align-items: flex-start;\r\n gap: 10px;\r\n\r\n .btn-left,\r\n .btn-right {\r\n width: 100%;\r\n justify-content: flex-start;\r\n }\r\n }\r\n}\r\n</style>\r\n","/**\r\n * EsTable 容器尺寸自适应 composable —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - ref/nextTick/onMounted/onBeforeUnmount 来自 './vue-compat'\r\n * - 业务逻辑 100% 一致(只是 Vue API 来源不同)\r\n *\r\n * 核心思路:通过 ResizeObserver 监听表格容器及表头按钮区高度,动态计算 el-table 的 height/maxHeight,\r\n * 让表格在 height 模式下分页固定贴底、在 auto 模式下随内容自适应。\r\n */\r\n\r\nimport { ref, nextTick, onMounted, onBeforeUnmount } from '../vue-compat'\r\n\r\nexport function useTableResize(\r\n tableContainerRef: { value: HTMLElement | null },\r\n headBarRef: { value: HTMLElement | null },\r\n tbBtnRef: { value: { $el?: HTMLElement } | null },\r\n paginationRef: { value: HTMLElement | null },\r\n options: { heightType?: 'auto' | 'height'; tabHeight?: number | string }\r\n) {\r\n const tableHeight = ref(400)\r\n const observer = ref<ResizeObserver | null>(null)\r\n\r\n const isNegative = (num: number) => Math.sign(num) === -1\r\n\r\n const totalContainerNum = () => {\r\n const headBarHeight = headBarRef.value?.offsetHeight || 0\r\n const tbBtnHeight = tbBtnRef.value?.$el?.offsetHeight || 0\r\n const paginationHeight = paginationRef.value?.offsetHeight || 0\r\n return Math.round(paginationHeight + headBarHeight + tbBtnHeight)\r\n }\r\n\r\n const resizeObservers = () => {\r\n const element = tableContainerRef.value\r\n if (!element) return\r\n\r\n const containerHeight =\r\n typeof options.tabHeight === 'number'\r\n ? options.tabHeight\r\n : options.heightType === 'height'\r\n ? element.parentElement?.offsetHeight || element.offsetHeight\r\n : parseInt(options.tabHeight as string, 10) || 450\r\n\r\n const maxContainer = !isNaN(containerHeight) ? containerHeight : 450\r\n const minTableNum = maxContainer - totalContainerNum()\r\n const tabContainer = isNegative(minTableNum) ? totalContainerNum() + 300 : maxContainer\r\n\r\n const paginationHeight = paginationRef.value?.offsetHeight || 0\r\n const headBarHeight = headBarRef.value?.offsetHeight || 0\r\n const tbBtnHeight = tbBtnRef.value?.$el?.offsetHeight || 0\r\n\r\n const newHeight =\r\n Math.floor(tabContainer) - Math.round(paginationHeight + headBarHeight + tbBtnHeight)\r\n if (tableHeight.value !== newHeight) {\r\n tableHeight.value = newHeight\r\n }\r\n }\r\n\r\n const startObserver = () => {\r\n nextTick(() => {\r\n if (!tableContainerRef.value || typeof ResizeObserver === 'undefined') return\r\n\r\n observer.value = new ResizeObserver(() => {\r\n requestAnimationFrame(() => {\r\n if (tableContainerRef.value) resizeObservers()\r\n })\r\n })\r\n\r\n const target =\r\n options.heightType === 'height'\r\n ? tableContainerRef.value.parentElement || tableContainerRef.value\r\n : tableContainerRef.value\r\n observer.value.observe(target)\r\n\r\n if (headBarRef.value) {\r\n observer.value.observe(headBarRef.value)\r\n }\r\n })\r\n }\r\n\r\n const stopObserver = () => {\r\n if (observer.value) {\r\n observer.value.disconnect()\r\n observer.value = null\r\n }\r\n }\r\n\r\n onMounted(() => startObserver())\r\n onBeforeUnmount(() => stopObserver())\r\n\r\n return { tableHeight, resizeObservers, startObserver, stopObserver }\r\n}\r\n","/**\r\n * EsTable 跨页选择状态 composable —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - ref/nextTick 来自 './vue-compat'\r\n * - 选择集合算法 100% 复用 @es-plus/core/table-selection\r\n *\r\n * 实现说明:\r\n * - core 层的 SelectionState 是普通对象,直接 mutate 不会触发响应式\r\n * - 因此本 wrapper 在每次状态变更后调用 sync(),把字段同步到 ref,触发视图更新\r\n * - rowkey 由 wrapper 在闭包中持有,转发给 core 函数\r\n */\r\n\r\nimport { ref, nextTick } from '../vue-compat'\r\nimport {\r\n createSelectionState,\r\n applySelectionChange,\r\n restoreSelectionForPage,\r\n clearAllSelection as coreClearAll,\r\n type TableRefLike,\r\n} from '@es-plus/core'\r\n\r\nexport function useTableSelection(rowkey?: string) {\r\n const state = createSelectionState()\r\n const multipleSelection = ref<Record<string, unknown>[]>([])\r\n const selectionsByPage = ref<Record<number, Record<string, unknown>[]>>({})\r\n const isInitChange = ref(false)\r\n\r\n // 把 core state 的字段同步到 ref —— Vue 2 通过浅拷贝触发响应式\r\n const sync = () => {\r\n multipleSelection.value = [...state.multipleSelection]\r\n selectionsByPage.value = { ...state.selectionsByPage }\r\n isInitChange.value = state.isInitChange\r\n }\r\n\r\n const handleSelectionChange = (val: Record<string, unknown>[], currentPage: number) => {\r\n if (state.isInitChange && rowkey) return\r\n applySelectionChange(state, val, currentPage, rowkey)\r\n sync()\r\n }\r\n\r\n const clearAllSelection = (tableRef: TableRefLike | null) => {\r\n if (!tableRef) {\r\n // 没有 tableRef 时手工重置 state(core 要求 tableRef 非空)\r\n state.multipleSelection = []\r\n state.selectionsByPage = {}\r\n } else {\r\n coreClearAll(state, tableRef)\r\n }\r\n sync()\r\n }\r\n\r\n const initSelection = (dataList: Record<string, unknown>[], tableRef: TableRefLike | null) => {\r\n state.isInitChange = true\r\n sync()\r\n if (!tableRef) {\r\n state.isInitChange = false\r\n sync()\r\n return\r\n }\r\n if (rowkey) {\r\n nextTick(() => {\r\n restoreSelectionForPage(state, dataList, tableRef, rowkey)\r\n state.isInitChange = false\r\n sync()\r\n })\r\n } else {\r\n nextTick(() => {\r\n tableRef.clearSelection?.()\r\n state.isInitChange = false\r\n sync()\r\n })\r\n }\r\n }\r\n\r\n return {\r\n multipleSelection,\r\n selectionsByPage,\r\n isInitChange,\r\n handleSelectionChange,\r\n clearAllSelection,\r\n initSelection,\r\n }\r\n}\r\n","<template>\r\n <div :ref=\"setTableContainer\" class=\"table_component\" :style=\"containerStyle\">\r\n <div class=\"table_containers\">\r\n <div\r\n v-if=\"showHeaderBar\"\r\n ref=\"headBarRef\"\r\n class=\"btn-slot\"\r\n :style=\"slotStyles.type === 'object' ? slotStyles.value : null\"\r\n :class=\"slotStyles.type === 'string' ? slotStyles.value : null\"\r\n >\r\n <div\r\n v-if=\"hasDefaultSlot\"\r\n class=\"headerBar\"\r\n :style=\"{ paddingBottom: hasDefaultSlot ? '10px' : '0px' }\"\r\n >\r\n <slot />\r\n </div>\r\n </div>\r\n\r\n <div\r\n v-loading=\"loadStatus\"\r\n element-loading-background=\"rgba(0, 0, 0, 0.03)\"\r\n element-loading-text=\"努力加载中...\"\r\n class=\"page-loading-con tableContainer\"\r\n >\r\n <div class=\"table_inner_containers\">\r\n <table-btns\r\n v-if=\"(options.configBtn && options.configBtn.length) || options.leftText\"\r\n ref=\"tbBtnRef\"\r\n :instance=\"{ tableRef: instance, formInstance: formInstance }\"\r\n :btn-config=\"options.configBtn\"\r\n :left-text=\"options.leftText\"\r\n />\r\n\r\n <!--\r\n Vue 2 / Element UI 版本不支持虚拟滚动 (Element UI 无 el-table-v2)\r\n 当用户配置 options.virtual === true 时,控制台会警告,仍按普通 el-table 渲染\r\n -->\r\n <el-table\r\n class=\"el-dp_tables\"\r\n :id=\"tableId\"\r\n :key=\"tableId\"\r\n ref=\"tableRef\"\r\n style=\"width: 100%\"\r\n v-bind=\"tableBindAttrs\"\r\n :data=\"dataSource\"\r\n @sort-change=\"changeTableSort\"\r\n @selection-change=\"handleTableSelectionChange\"\r\n >\r\n <template #empty>\r\n <div class=\"ant-empty ant-empty-normal\">\r\n <div class=\"ant-empty-image\">\r\n <svg\r\n class=\"ant-empty-img-simple\"\r\n width=\"64\"\r\n height=\"41\"\r\n viewBox=\"0 0 64 41\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <g transform=\"translate(0 1)\" fill=\"none\" fill-rule=\"evenodd\">\r\n <ellipse\r\n class=\"ant-empty-img-simple-ellipse\"\r\n cx=\"32\"\r\n cy=\"33\"\r\n rx=\"32\"\r\n ry=\"7\"\r\n />\r\n <g class=\"ant-empty-img-simple-g\" fill-rule=\"nonzero\">\r\n <path\r\n d=\"M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z\"\r\n />\r\n <path\r\n d=\"M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z\"\r\n class=\"ant-empty-img-simple-path\"\r\n />\r\n </g>\r\n </g>\r\n </svg>\r\n </div>\r\n <div class=\"ant-empty-description\">暂无数据</div>\r\n </div>\r\n </template>\r\n\r\n <column-item\r\n v-for=\"(cols, index) in filteredColumns\"\r\n :key=\"cols.prop || cols.key || index\"\r\n :cols=\"Object.assign({}, cols, { columnIndex: index })\"\r\n >\r\n <template\r\n v-if=\"cols.scopedSlots && cols.scopedSlots.customRender\"\r\n #[cols.scopedSlots.customRender]=\"{ scope }\"\r\n >\r\n <slot\r\n :name=\"cols.scopedSlots.customRender\"\r\n v-bind=\"\r\n Object.assign({}, cols, {\r\n columnIndex: index,\r\n row: scope.row,\r\n column: scope.column,\r\n })\r\n \"\r\n :scope=\"scope\"\r\n />\r\n </template>\r\n </column-item>\r\n </el-table>\r\n </div>\r\n\r\n <div\r\n v-if=\"showPagination\"\r\n ref=\"paginationRef\"\r\n class=\"pagination_page\"\r\n :style=\"paginationStyle\"\r\n >\r\n <!--\r\n Element UI 与 Element Plus 分页组件 API 差异:\r\n - current-page: .sync 双向绑定 (vs Vue 3 v-model:current-page)\r\n - page-size: .sync 双向绑定\r\n -->\r\n <el-pagination\r\n :background=\"paginationBackground\"\r\n :size=\"paginationIsSmall ? 'small' : paginationConfig.size\"\r\n :total=\"paginationConfig.total\"\r\n :page-size.sync=\"paginationConfig.pageSize\"\r\n :page-sizes=\"paginationPageSizes\"\r\n :current-page.sync=\"paginationConfig.current\"\r\n :layout=\"layout\"\r\n style=\"padding: 0; margin: 10px 0; text-align: center\"\r\n @size-change=\"handleSizeChange\"\r\n @current-change=\"handleIndexChange\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsTable 表格组件 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的核心差异:\r\n * 1. <script setup> → defineComponent + setup(),props/emits/expose 通过返回值与 setup 第二参数实现\r\n * 2. el-pagination 双向绑定从 v-model:current-page → :current-page.sync\r\n * 3. ElConfigProvider 在 Element UI 中不存在 —— 国际化 locale 由用户在 main.js 中\r\n * 通过 Vue.use(ElementUI, { locale }) 全局配置\r\n * 4. 虚拟滚动 (virtual: true) Element UI 无对应 el-table-v2,本版本不支持,\r\n * 仅控制台警告并降级为普通 el-table 渲染\r\n * 5. ElButton 用于操作列时,Element UI 的 type='text' 取代 Element Plus 的 text 属性\r\n * 6. v-loading 指令在 Element UI 中由 Vue.use(ElementUI) 自动注册,无需 ./vLoading 导入\r\n *\r\n * 业务逻辑(请求/分页/选择/列规范化)100% 与 Vue 3 版本保持一致。\r\n */\r\nimport {\r\n defineComponent,\r\n ref,\r\n computed,\r\n watch,\r\n inject,\r\n provide,\r\n getCurrentInstance,\r\n onMounted,\r\n h,\r\n nextTick,\r\n} from '../../vue-compat'\r\nimport {\r\n getGlobalConfig,\r\n isObject,\r\n findValueByKey,\r\n getCallback,\r\n type TableColumn,\r\n type PaginationConfig,\r\n type TableOptions,\r\n} from '@es-plus/core'\r\nimport ColumnItem from './column-item.vue'\r\nimport TableBtns from './table-btns.vue'\r\nimport { useTableResize } from '../../composables/use-table-resize'\r\nimport { useTableSelection } from '../../composables/use-table-selection'\r\nimport { mapSize } from '../../utils/size'\r\n\r\nconst defaultOptions: TableOptions = {\r\n multiSelect: false,\r\n expand: false,\r\n snIndex: false,\r\n loading: false,\r\n border: false,\r\n size: 'small',\r\n headerCellStyle: { background: '#f5f7fa' },\r\n highlightCurrentRow: true,\r\n cachePageSelection: true,\r\n}\r\n\r\n// es-table 内部选项键,不应透传给 el-table\r\nconst TABLE_INTERNAL_KEYS = new Set([\r\n 'multiSelect',\r\n 'expand',\r\n 'snIndex',\r\n 'loading',\r\n 'cachePageSelection',\r\n 'httpRequest',\r\n 'configTableOut',\r\n 'listenToCallBack',\r\n 'apiParams',\r\n 'actionUrl',\r\n 'heightType',\r\n 'tabHeight',\r\n 'isInitRun',\r\n 'entryQuery',\r\n 'configBtn',\r\n 'leftText',\r\n 'rowkey',\r\n 'virtual',\r\n 'engine',\r\n 'rowHeight',\r\n 'estimatedRowHeight',\r\n 'overscanCount',\r\n 'rowClassName',\r\n])\r\n\r\nconst firstWordUpperCase = (str: string): string => {\r\n return str.toLowerCase().replace(/(\\s|^)[a-z]/g, (char) => char.toUpperCase())\r\n}\r\n\r\n/**\r\n * 把 options 中的中划线属性、key/prop 双向映射等规范化为 el-table 可接受的 props\r\n */\r\nconst columnBindAttr = (cols: Record<string, unknown>) => {\r\n const options: Record<string, unknown> = {}\r\n for (const t in cols) {\r\n if (t === 'groups' || t === 'scopedSlots' || t === 'render') continue\r\n\r\n if (t.includes('-')) {\r\n const parts = t.split('-')\r\n let newkey = parts[0]\r\n for (let j = 1; j < parts.length; j++) {\r\n newkey += firstWordUpperCase(parts[j])\r\n }\r\n options[newkey] = cols[t]\r\n } else if (t === 'key') {\r\n options.prop = cols[t]\r\n options[t] = cols[t]\r\n } else {\r\n options[t] = cols[t]\r\n }\r\n }\r\n if (!options.align) {\r\n options.align = 'center'\r\n }\r\n return options\r\n}\r\n\r\nconst checkQueryFields = (obj: Record<string, unknown>): boolean => {\r\n const checkListKey = ['total', 'pageSize', 'current', 'tableData']\r\n if (isObject(obj)) {\r\n return Object.keys(obj).every((it) => {\r\n return checkListKey.find((its) => its === it) && obj[it] && typeof obj[it] === 'string'\r\n })\r\n }\r\n return false\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'EsTable',\r\n components: { ColumnItem, TableBtns },\r\n // 关闭自动 attrs 继承,避免 fallthrough 重复绑定\r\n inheritAttrs: false,\r\n props: {\r\n initTabHeight: { type: Number, default: 400 },\r\n headBarClass: {\r\n type: [String, Object] as unknown as () => string | Record<string, unknown>,\r\n default: '',\r\n },\r\n showHeaderBar: { type: Boolean, default: true },\r\n dataSource: {\r\n type: Array as () => Record<string, unknown>[],\r\n default: () => [],\r\n },\r\n columns: {\r\n type: Array as () => TableColumn[],\r\n default: () => [],\r\n },\r\n options: {\r\n type: Object as () => TableOptions,\r\n default: () => ({ ...defaultOptions }),\r\n },\r\n pagination: {\r\n type: Object as () => PaginationConfig,\r\n default: () => ({}),\r\n },\r\n },\r\n emits: [\r\n 'update:dataSource',\r\n 'update:pagination',\r\n 'pagination-current-change',\r\n 'size-change',\r\n 'change-table-sort',\r\n ],\r\n setup(props, { emit, slots, attrs, expose }) {\r\n // ─── 注入全局配置 ─────────────────────────\r\n const instance = getCurrentInstance() as unknown as Record<string, unknown>\r\n const $esPlusTable =\r\n inject<Record<string, unknown>>(\r\n '$esPlusTable',\r\n null as unknown as Record<string, unknown>\r\n ) ??\r\n ((getGlobalConfig() as Record<string, unknown>).EsTable as Record<string, unknown>) ??\r\n {}\r\n const esPlus =\r\n inject<Record<string, unknown>>('$EsPlus', null as unknown as Record<string, unknown>) ??\r\n (getGlobalConfig() as Record<string, unknown>) ??\r\n {}\r\n\r\n const checkPermission = (pvalue?: string): boolean => {\r\n if (!pvalue) return true\r\n const fn = esPlus.permission\r\n return typeof fn === 'function' ? (fn as (v: string) => boolean)(pvalue) : true\r\n }\r\n\r\n // ─── 虚拟滚动降级 ─────────────────────────\r\n if (props.options.virtual === true || props.options.engine === 'virtual') {\r\n // eslint-disable-next-line no-console\r\n console.warn(\r\n '[@es-plus/vue2] 虚拟滚动 (virtual: true) 在 Vue 2 + Element UI 下不可用,已降级为普通 el-table 渲染。如需虚拟滚动请使用 Vue 3 + Element Plus 版本(@es-plus/vue3)。'\r\n )\r\n }\r\n\r\n // ─── Refs ─────────────────────────────────\r\n const tableRef = ref<any>(null)\r\n const tbBtnRef = ref<any>(null)\r\n const headBarRef = ref<HTMLElement | null>(null)\r\n const paginationRef = ref<HTMLElement | null>(null)\r\n const tableContainerRef = ref<HTMLElement | null>(null)\r\n const tableId = ref(`table_${Math.random().toString(36).substring(2, 12)}`)\r\n const tableData = ref<Record<string, unknown>[]>([])\r\n const columnRowList = ref<TableColumn[]>([...props.columns])\r\n\r\n watch(\r\n () => props.columns,\r\n (val) => {\r\n columnRowList.value = [...val]\r\n },\r\n { deep: true }\r\n )\r\n\r\n const loadingStatus = ref(false)\r\n const slotState = ref(false)\r\n const showPagination = ref(false)\r\n\r\n // Vue 2 函数式 ref:用 :ref=\"setTableContainer\" 避免 ref 被赋值为 string\r\n const setTableContainer = (el: HTMLElement | null) => {\r\n if (el) tableContainerRef.value = el\r\n }\r\n\r\n // ─── 与 EsForm 的耦合 ─────────────────────\r\n const bodyFormInstance = inject<(inst: unknown) => void>('bodyFormInstance', () => {})\r\n const getVisibleShow = inject<(() => boolean) | boolean>('getVisibleShow', false)\r\n\r\n const visibleShow = computed(() =>\r\n typeof getVisibleShow === 'function' ? getVisibleShow() : getVisibleShow\r\n )\r\n\r\n const paginationConfig = ref<PaginationConfig>({\r\n pageSize: 10,\r\n current: 1,\r\n total: 0,\r\n pageSizes: [],\r\n size: 'small',\r\n isSmall: true,\r\n ...props.pagination,\r\n })\r\n\r\n const formInstance = ref<unknown>(null)\r\n\r\n // ─── 计算属性 ──────────────────────────────\r\n const getListEntry = computed(() => {\r\n const eq = props.options.entryQuery\r\n if (eq && isObject(eq) && Object.keys(eq).length) {\r\n return eq\r\n }\r\n return {}\r\n })\r\n\r\n const configTableField = computed(() => {\r\n if (\r\n props.options.configTableOut &&\r\n isObject(props.options.configTableOut) &&\r\n Object.keys(props.options.configTableOut).length &&\r\n checkQueryFields(props.options.configTableOut)\r\n ) {\r\n return props.options.configTableOut\r\n }\r\n\r\n if (\r\n $esPlusTable?.configQueryFieldOutput &&\r\n typeof $esPlusTable.configQueryFieldOutput === 'function'\r\n ) {\r\n const configFields = ($esPlusTable.configQueryFieldOutput as Function)({\r\n total: 'records',\r\n pageSize: 'pageSize',\r\n current: 'pageNo',\r\n tableData: 'rows',\r\n })\r\n if (checkQueryFields(configFields)) return configFields\r\n }\r\n\r\n return {\r\n total: 'records',\r\n pageSize: 'pageSize',\r\n current: 'pageNo',\r\n tableData: 'rows',\r\n }\r\n })\r\n\r\n /**\r\n * 探测 default slot 中是否含 EsForm 实例 —— Vue 2 的 $children 模式\r\n *\r\n * 与 Vue 3 不同:Vue 2 中 vnode 没有 ctx,需要通过 $children 遍历查找。\r\n * 这里采用:等待挂载后,在 instance.$children 中找 name === 'EsForm' 的子组件。\r\n */\r\n const isFormInstance = computed(() => {\r\n const proxy = (instance as any)?.proxy\r\n if (!proxy || !proxy.$children) return {}\r\n const formChild = proxy.$children.find((child: any) => {\r\n const n = child?.$options?.name\r\n return n === 'EsForm'\r\n })\r\n if (formChild) {\r\n formInstance.value = formChild\r\n bodyFormInstance(formChild)\r\n // 返回的对象至少要保证 .props.model 可用\r\n return formChild\r\n }\r\n return {}\r\n })\r\n\r\n const hasDefaultSlot = computed(() => {\r\n // Vue 2 的 slots 是函数集合,调用后取得 vnode 数组\r\n const fn = (slots as any).default\r\n if (typeof fn === 'function') {\r\n const result = fn()\r\n return Array.isArray(result) ? result.length > 0 : !!result\r\n }\r\n // 兼容老式:$slots 是 vnode 数组\r\n const vnodes = (slots as any).default\r\n return Array.isArray(vnodes) && vnodes.length > 0\r\n })\r\n\r\n const heightType = computed(\r\n () => (props.options.heightType || 'auto') as 'auto' | 'height' | 'maxHeight'\r\n )\r\n\r\n const tabHeight = computed(() => {\r\n if (typeof props.options.tabHeight === 'number') {\r\n return `${props.options.tabHeight}px`\r\n }\r\n if (heightType.value === 'height' && typeof props.options.height === 'number') {\r\n return `${props.options.height}px`\r\n }\r\n return '100%'\r\n })\r\n\r\n const containerStyle = computed(() => ({\r\n [heightType.value]: tabHeight.value,\r\n }))\r\n\r\n const slotStyles = computed(() => {\r\n if (props.headBarClass) {\r\n return {\r\n type: typeof props.headBarClass === 'string' ? 'string' : 'object',\r\n value: props.headBarClass,\r\n }\r\n }\r\n return { type: 'string', value: '' }\r\n })\r\n\r\n // ─── 分页布局配置(来自全局 EsTable 配置) ──\r\n const paginationLayoutConfig = computed(() => {\r\n const cfg = $esPlusTable?.paginationLayout\r\n if (!cfg) return null\r\n return typeof cfg === 'function' ? (cfg as Function)() : cfg\r\n })\r\n\r\n const layout = computed(\r\n () =>\r\n (paginationLayoutConfig.value as any)?.layout ||\r\n 'prev, pager, next, jumper, sizes, ->, total'\r\n )\r\n const paginationPageSizes = computed(\r\n () =>\r\n (paginationLayoutConfig.value as any)?.pageSizes ||\r\n paginationConfig.value.pageSizes\r\n )\r\n const paginationIsSmall = computed(\r\n () => (paginationLayoutConfig.value as any)?.isSmall ?? paginationConfig.value.isSmall\r\n )\r\n const paginationBackground = computed(\r\n () => (paginationLayoutConfig.value as any)?.background ?? true\r\n )\r\n\r\n const paginationStyle = computed(() => ({\r\n position: heightType.value === 'height' ? 'absolute' : 'static',\r\n bottom: '0px',\r\n left: '0px',\r\n zIndex: 5,\r\n background: '#fff',\r\n }))\r\n\r\n const loadStatus = computed(() => props.options.loading || loadingStatus.value)\r\n const isRequestConf = computed(\r\n () =>\r\n !!props.options.actionUrl ||\r\n (props.options.apiParams &&\r\n isObject(props.options.apiParams) &&\r\n Object.keys(props.options.apiParams).length > 0)\r\n )\r\n\r\n // ─── 列处理 ────────────────────────────────\r\n const filteredColumns = computed(() => {\r\n const list = columnRowList.value.filter((item) => !item.hidCol)\r\n list.forEach((el) => {\r\n if (\r\n el.prop !== 'operate' &&\r\n el.key !== 'operate' &&\r\n (el.prop || el.key) &&\r\n !el.formatter\r\n ) {\r\n el.formatter = (row: Record<string, unknown>) => {\r\n const value = row[el.prop as string] || row[el.key as string]\r\n if (value == null || value === '') {\r\n return (el.emptyPlaceholder as string) || '-'\r\n }\r\n return value as string\r\n }\r\n }\r\n\r\n if ((el.prop === 'operate' || el.key === 'operate') && el.btns && !el.render) {\r\n el.render = (_h: any, { row }: { row: Record<string, unknown> }) => {\r\n return h('div', [\r\n el.btns\r\n ?.filter((btn: any) => checkPermission(btn.permissionValue))\r\n .map((btn: any) =>\r\n // Element UI text 按钮:type=\"text\" 而非 text 属性\r\n h(\r\n 'el-button',\r\n {\r\n props: {\r\n type: 'text',\r\n },\r\n attrs: {\r\n ...(btn.type ? { 'data-btn-type': btn.type } : {}),\r\n },\r\n on: {\r\n click: () => btn.clickEvent?.(row),\r\n },\r\n },\r\n btn.name\r\n )\r\n ),\r\n ])\r\n }\r\n }\r\n })\r\n\r\n // 当所有列都设置了固定 width 且没有 minWidth 时,把最后一个非固定列的 width 转为 minWidth\r\n const allFixedWidth = list.length > 0 && list.every((col) => col.width && !col.minWidth)\r\n if (allFixedWidth) {\r\n let flexIdx = -1\r\n for (let i = list.length - 1; i >= 0; i--) {\r\n const col = list[i]\r\n if (!col.fixed && col.prop !== 'operate' && col.key !== 'operate') {\r\n flexIdx = i\r\n break\r\n }\r\n }\r\n if (flexIdx === -1) flexIdx = list.length - 1\r\n if (flexIdx >= 0) {\r\n const col = list[flexIdx]\r\n col.minWidth = col.width\r\n delete col.width\r\n }\r\n }\r\n\r\n return list\r\n })\r\n\r\n const tableAttrs = computed(() => {\r\n const merged = columnBindAttr({ ...defaultOptions, ...props.options })\r\n const { align: _align, ...rest } = merged\r\n const result: Record<string, unknown> = {}\r\n for (const key in rest) {\r\n if (!TABLE_INTERNAL_KEYS.has(key)) {\r\n result[key] = rest[key]\r\n }\r\n }\r\n // 把 Element Plus 语义的 size(large/default/small)映射到 Element UI v2 语义\r\n // (medium/small/mini),让两套版本同一份 options 渲染出一致的视觉密度。\r\n // 详见 packages/vue2/src/utils/size.ts。\r\n if (result.size !== undefined) {\r\n const mapped = mapSize(result.size)\r\n if (mapped !== undefined) {\r\n result.size = mapped\r\n }\r\n }\r\n return result\r\n })\r\n\r\n // ─── ResizeObserver 自适应高度 ─────────────\r\n const { tableHeight, resizeObservers } = useTableResize(\r\n tableContainerRef,\r\n headBarRef,\r\n tbBtnRef,\r\n paginationRef,\r\n {\r\n heightType: heightType.value as 'auto' | 'height',\r\n tabHeight: props.options.tabHeight,\r\n }\r\n )\r\n\r\n // 合并 options + fallthrough attrs,供 el-table 使用\r\n const tableBindAttrs = computed(() => {\r\n const result: Record<string, unknown> = { ...tableAttrs.value, ...(attrs as any) }\r\n if (props.options.rowkey) {\r\n result.rowKey = props.options.rowkey\r\n }\r\n if (heightType.value === 'height') {\r\n result.height = tableHeight.value\r\n } else if (heightType.value === 'maxHeight') {\r\n result.maxHeight = tableHeight.value\r\n }\r\n return result\r\n })\r\n\r\n // ─── 选择逻辑 ──────────────────────────────\r\n const {\r\n multipleSelection,\r\n handleSelectionChange,\r\n initSelection,\r\n clearAllSelection: clearAllSelectionInternal,\r\n } = useTableSelection(props.options.rowkey)\r\n\r\n const handleTableSelectionChange = (val: Record<string, unknown>[]) => {\r\n handleSelectionChange(val, paginationConfig.value.current || 1)\r\n }\r\n\r\n // ─── Watchers ─────────────────────────────\r\n watch(visibleShow, async (val, oldVal) => {\r\n if (val && val !== oldVal) {\r\n if (props.options.actionUrl) {\r\n await httpRequestInstance()\r\n }\r\n ;(tableRef.value as any)?.doLayout?.()\r\n }\r\n })\r\n\r\n watch(\r\n () => props.pagination,\r\n (val) => {\r\n paginationConfig.value = { ...paginationConfig.value, ...val }\r\n showPagination.value = val.total !== undefined\r\n },\r\n { deep: true, immediate: true }\r\n )\r\n\r\n watch(\r\n () => props.dataSource,\r\n (val) => {\r\n initSelection(val, tableRef.value)\r\n },\r\n { deep: true }\r\n )\r\n\r\n watch(\r\n tableData,\r\n (val) => {\r\n if (Array.isArray(val)) {\r\n emit('update:dataSource', val)\r\n }\r\n },\r\n { deep: true }\r\n )\r\n\r\n onMounted(() => {\r\n if (isRequestConf.value && props.options.isInitRun !== false) {\r\n httpRequestInstance()\r\n }\r\n // 等待 EsForm 子组件挂载后再触发一次依赖收集\r\n nextTick(() => {\r\n // eslint-disable-next-line no-unused-expressions\r\n isFormInstance.value\r\n })\r\n })\r\n\r\n // ─── 请求逻辑 ──────────────────────────────\r\n const getListenToCallBack = (eventName: string, params: unknown) => {\r\n const cb = props.options.listenToCallBack\r\n if (!cb) return undefined\r\n const fn = getCallback(cb as any, eventName)\r\n if (typeof fn === 'function') {\r\n return fn(params)\r\n }\r\n return undefined\r\n }\r\n\r\n const formatConfigOut = (row: Record<string, unknown>, keyList: string[]) => {\r\n const cf = configTableField.value as Record<string, unknown>\r\n if (isObject(cf) && Object.keys(cf).length) {\r\n Object.entries(cf).forEach(([key, value]) => {\r\n const isKeyUsed = keyList.includes(key)\r\n if (!isKeyUsed) return\r\n\r\n const rowData = row[value as string] ?? findValueByKey(row, value as string)\r\n if (key === 'tableData') {\r\n tableData.value = Array.isArray(rowData) ? rowData : []\r\n } else {\r\n ;(paginationConfig.value as any)[key] =\r\n typeof rowData === 'number' ? rowData : parseInt(rowData as string, 10) || 0\r\n }\r\n })\r\n }\r\n }\r\n\r\n const queryTableListMethod = (\r\n params: Record<string, unknown>,\r\n options: {\r\n success?: (res: Record<string, unknown>) => void\r\n fail?: (err: unknown) => void\r\n } = {}\r\n ) => {\r\n const { success, fail } = options\r\n const apiParams = (props.options?.apiParams || {}) as Record<string, any>\r\n const url = props.options?.actionUrl || apiParams.url || ''\r\n\r\n if (!url || !Object.keys(apiParams).length) return\r\n\r\n // Vue 2 中响应式对象天然是 plain object,无需 toRaw / unref\r\n const formObj = isFormInstance.value as any\r\n const formData =\r\n formObj && formObj.props && formObj.props.model\r\n ? { ...formObj.props.model }\r\n : getListEntry.value || {}\r\n\r\n const fnParams = getListenToCallBack('beforeRequest', {\r\n ...formData,\r\n ...params,\r\n ...(apiParams.model || {}),\r\n })\r\n const finalParams = isObject(fnParams)\r\n ? fnParams\r\n : { ...formData, ...(apiParams.model || {}), ...params }\r\n const requestOption = { ...(apiParams.options || {}) }\r\n if (apiParams?.method) {\r\n requestOption.method = apiParams?.method\r\n }\r\n\r\n const requestHandler = async (requestFn: Function) => {\r\n if (loadingStatus.value) return\r\n loadingStatus.value = true\r\n try {\r\n const res = await requestFn({\r\n url,\r\n formParams: finalParams,\r\n headers: apiParams.headers || {},\r\n ...requestOption,\r\n ...params,\r\n })\r\n const responseData = getListenToCallBack('afterResponse', res) || res\r\n if (\r\n isObject(res) &&\r\n Object.keys(res as object).length &&\r\n typeof success === 'function'\r\n ) {\r\n success(responseData as Record<string, unknown>)\r\n }\r\n } catch (e) {\r\n if (typeof fail === 'function') {\r\n fail(e)\r\n }\r\n } finally {\r\n loadingStatus.value = false\r\n }\r\n }\r\n\r\n if (props.options.httpRequest) {\r\n requestHandler(props.options.httpRequest as Function)\r\n } else if ($esPlusTable.$httpRequest) {\r\n requestHandler($esPlusTable.$httpRequest as Function)\r\n }\r\n }\r\n\r\n const httpRequestInstance = (model?: Record<string, unknown>) => {\r\n return new Promise((resolve, reject) => {\r\n paginationConfig.value.current = 1\r\n queryTableListMethod(\r\n {\r\n ...(model || {}),\r\n pageIndex: paginationConfig.value.current,\r\n pageSize: paginationConfig.value.pageSize,\r\n },\r\n {\r\n success: (res) => {\r\n formatConfigOut(res, ['total', 'tableData'])\r\n if (Object.keys(props.pagination).length) {\r\n emit('update:pagination', paginationConfig.value)\r\n }\r\n resolve(res)\r\n },\r\n fail: (err) => {\r\n reject(err)\r\n },\r\n }\r\n )\r\n })\r\n }\r\n\r\n const changePageIndexRequest = () => {\r\n queryTableListMethod(\r\n {\r\n pageIndex: paginationConfig.value.current,\r\n pageSize: paginationConfig.value.pageSize,\r\n },\r\n {\r\n success: (res) => {\r\n formatConfigOut(res, ['total', 'tableData'])\r\n emit('update:pagination', paginationConfig.value)\r\n emit('pagination-current-change', paginationConfig.value)\r\n },\r\n }\r\n )\r\n }\r\n\r\n const changePageSizeRequest = () => {\r\n queryTableListMethod(\r\n {\r\n pageIndex: paginationConfig.value.current,\r\n pageSize: paginationConfig.value.pageSize,\r\n },\r\n {\r\n success: (res) => {\r\n formatConfigOut(res, ['total', 'tableData'])\r\n emit('update:pagination', paginationConfig.value)\r\n },\r\n }\r\n )\r\n }\r\n\r\n const handleSizeChange = (size: number) => {\r\n paginationConfig.value.pageSize = size\r\n paginationConfig.value.current = 1\r\n if (isRequestConf.value) {\r\n changePageSizeRequest()\r\n } else {\r\n emit('update:pagination', paginationConfig.value)\r\n emit('size-change', paginationConfig.value, size)\r\n }\r\n }\r\n\r\n const handleIndexChange = (val: number) => {\r\n paginationConfig.value.current = val\r\n if (isRequestConf.value) {\r\n changePageIndexRequest()\r\n } else {\r\n emit('update:pagination', paginationConfig.value)\r\n emit('pagination-current-change', paginationConfig.value)\r\n }\r\n }\r\n\r\n const changeTableSort = (column: Record<string, unknown>) => {\r\n emit('change-table-sort', column)\r\n }\r\n\r\n // ─── 提供给子组件的实例 ────────────────────\r\n provide('getTableInstantce', () => ({\r\n tableRef,\r\n toggleSelection: (rows: Record<string, unknown>[]) => {\r\n if (rows) {\r\n rows.forEach((row) => {\r\n ;(tableRef.value as any)?.toggleRowSelection?.(row)\r\n })\r\n } else {\r\n ;(tableRef.value as any)?.clearSelection?.()\r\n }\r\n },\r\n clearAllSelection: () => clearAllSelectionInternal(tableRef.value),\r\n refsInstance: () => tableRef.value,\r\n httpRequestInstance,\r\n }))\r\n\r\n // ─── 暴露方法(Vue 2 通过 expose 或 return) ──\r\n const exposed = {\r\n httpRequestInstance,\r\n getSelectionRows: () => multipleSelection.value,\r\n clearSelection: () => (tableRef.value as any)?.clearSelection?.(),\r\n clearAllSelection: () => clearAllSelectionInternal(tableRef.value),\r\n refresh: () => (tableRef.value as any)?.doLayout?.(),\r\n // virtual 滚动占位(保持 API 一致,Vue 2 版本无效)\r\n scrollToRow: (_row: number) => {\r\n // noop in Vue 2 + Element UI\r\n },\r\n }\r\n\r\n if (typeof expose === 'function') {\r\n expose(exposed)\r\n }\r\n\r\n return {\r\n // refs\r\n tableRef,\r\n tbBtnRef,\r\n headBarRef,\r\n paginationRef,\r\n tableId,\r\n tableData,\r\n // state\r\n loadStatus,\r\n paginationConfig,\r\n formInstance,\r\n // computeds\r\n filteredColumns,\r\n tableBindAttrs,\r\n hasDefaultSlot,\r\n heightType,\r\n tabHeight,\r\n slotStyles,\r\n slotState,\r\n showPagination,\r\n containerStyle,\r\n paginationStyle,\r\n layout,\r\n paginationPageSizes,\r\n paginationIsSmall,\r\n paginationBackground,\r\n // handlers\r\n setTableContainer,\r\n handleTableSelectionChange,\r\n changeTableSort,\r\n handleSizeChange,\r\n handleIndexChange,\r\n // exposed methods (also accessible via $refs.tableRef.xxx in Vue 2)\r\n ...exposed,\r\n instance,\r\n resizeObservers,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.el-dp_tables {\r\n height: auto;\r\n ::v-deep(.el-table__body-wrapper) {\r\n height: auto;\r\n }\r\n}\r\n\r\n.table_component {\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: space-between;\r\n align-items: flex-start;\r\n overflow: hidden;\r\n}\r\n\r\n.table_containers {\r\n flex: 1;\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n justify-content: space-between;\r\n flex-direction: column;\r\n align-items: flex-start;\r\n position: relative;\r\n}\r\n\r\n.pagination_page {\r\n width: 100%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.btn-slot {\r\n width: 100%;\r\n\r\n .headerBar {\r\n box-sizing: border-box;\r\n background-color: #fff;\r\n border-radius: 6px;\r\n\r\n ::v-deep(.el-form-item--small .el-form-item__label) {\r\n box-sizing: border-box;\r\n }\r\n }\r\n}\r\n\r\n.tableContainer {\r\n border-radius: 0px;\r\n transition: all 1.5s;\r\n flex: 1;\r\n width: 100%;\r\n display: flex;\r\n justify-content: space-between;\r\n flex-direction: column;\r\n align-items: flex-start;\r\n\r\n .table_inner_containers {\r\n width: 100%;\r\n }\r\n\r\n ::v-deep(.el-table__empty-block) {\r\n width: 100% !important;\r\n margin: 32px 0;\r\n font-size: 14px;\r\n line-height: 1.5715;\r\n\r\n .el-table__empty-text {\r\n width: auto !important;\r\n }\r\n\r\n .ant-empty-image {\r\n height: 40px;\r\n margin-bottom: 8px;\r\n\r\n .ant-empty-img-simple-ellipse {\r\n fill: #f5f5f5;\r\n }\r\n\r\n .ant-empty-img-simple-g {\r\n stroke: #d9d9d9;\r\n }\r\n\r\n .ant-empty-img-simple-path {\r\n fill: #fafafa;\r\n }\r\n }\r\n\r\n .ant-empty-description {\r\n line-height: 1.5715;\r\n color: rgba(0, 0, 0, 0.25);\r\n }\r\n }\r\n\r\n ::v-deep(.el-tag) {\r\n height: 20px;\r\n padding: 0 7px;\r\n line-height: 20px;\r\n background: #fafafa;\r\n border: none;\r\n border-radius: 4px;\r\n\r\n &.el-tag--info {\r\n color: rgba(0, 0, 0, 0.85);\r\n }\r\n\r\n &.el-tag--success {\r\n color: #52c41a;\r\n background: #f6ffed;\r\n border-color: #b7eb8f;\r\n }\r\n }\r\n}\r\n</style>\r\n","/**\r\n * EsTable 组件入口\r\n *\r\n * 使用方式:\r\n * 1. 默认导入:import EsTable from '@es-plus/vue2/es-table'\r\n * 2. install 安装:通过 Vue.use(EsPlus) 全局注册\r\n *\r\n * Element UI 组件(el-table / el-pagination 等)作为 EsTable 的依赖,\r\n * 由用户在 main.js 中通过 Vue.use(ElementUI) 全局注册。\r\n */\r\n\r\nimport EsTable from './component.vue'\r\nimport type { Vue } from '../../vue-compat'\r\n\r\n;(EsTable as unknown as { install: (V: typeof Vue) => void }).install = function (Vue) {\r\n Vue.component((EsTable as unknown as { name: string }).name || 'EsTable', EsTable)\r\n}\r\n\r\nexport default EsTable\r\nexport { EsTable }\r\n","<script lang=\"ts\">\r\n/**\r\n * EsDialog 内部内容渲染器 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的核心差异:\r\n * - h(...) 是 createElement,签名 `h(tag, data, children)`,data 中区分 props/attrs/on/ref\r\n * - vnode.componentInstance 取代 Vue 3 的 vnode.component(用于回填 currentRef)\r\n * - Element UI 没有 ElConfigProvider,国际化由 Vue.use(ElementUI, { locale }) 全局配置\r\n *\r\n * 职责:\r\n * - 调用用户传入的 render(h, instance, components) → VNode/字符串/组件\r\n * - 把渲染结果挂到 refsObject.currentRef,供 EsDialog 工具栏按钮 click 回调取到\r\n */\r\nimport {\r\n defineComponent,\r\n h,\r\n reactive,\r\n onMounted,\r\n onUpdated,\r\n} from '../../vue-compat'\r\n\r\nexport default defineComponent({\r\n name: 'RenderJsx',\r\n props: {\r\n refs: { type: [Function, Object] as unknown as () => Function | Record<string, unknown>, default: null },\r\n row: { type: Object, default: () => ({}) },\r\n render: { type: Function, default: () => undefined },\r\n model: { type: Object, default: () => ({}) },\r\n instance: { type: Object, default: () => ({}) },\r\n components: { type: Object, default: () => ({}) },\r\n },\r\n setup(props) {\r\n const refsObject =\r\n props.refs && typeof props.refs === 'object'\r\n ? (props.refs as Record<string, unknown>)\r\n : reactive<Record<string, unknown>>({})\r\n\r\n let componentVNode: any = null\r\n\r\n /**\r\n * Vue 2 vnode 结构:\r\n * - 组件 vnode: vnode.componentInstance 是组件实例(即 vm)\r\n * - 普通元素: vnode.elm 是 DOM\r\n */\r\n function flushRef() {\r\n if (!componentVNode) return\r\n const inst = componentVNode.componentInstance\r\n if (!inst) return\r\n ;(refsObject as Record<string, unknown>).currentRef = inst\r\n }\r\n\r\n onMounted(() => flushRef())\r\n onUpdated(() => flushRef())\r\n\r\n return () => {\r\n const { instance } = props as { instance: Record<string, unknown> }\r\n const enhancedInstance = {\r\n ...instance,\r\n registerRef: (name: string, el: unknown) => {\r\n if (el !== null && el !== undefined) {\r\n ;(refsObject as Record<string, unknown>)[name] = el\r\n }\r\n },\r\n getRefs: () => refsObject,\r\n }\r\n\r\n // 调用用户的 render(h, instance, components)\r\n const renderFn = props.render as Function\r\n const renderContent =\r\n renderFn && typeof renderFn === 'function'\r\n ? renderFn(h, enhancedInstance, props.components || {})\r\n : ''\r\n\r\n // 字符串/数字 → 包成 span\r\n if (typeof renderContent === 'string' || typeof renderContent === 'number') {\r\n componentVNode = null\r\n return h(\r\n 'span',\r\n {\r\n ref: 'currentRef',\r\n // Vue 2 的函数式 ref 通过 v-bind 不可直接传,用以下方式赋值\r\n },\r\n [String(renderContent)]\r\n )\r\n }\r\n\r\n // VNode:判断是否为组件(type 不是 string 即视为组件 vnode)\r\n if (renderContent && typeof renderContent === 'object' && 'tag' in renderContent) {\r\n // Vue 2 的组件 vnode tag 形如 'vue-component-1-EsForm',只要存在 componentOptions 就视为组件\r\n const isComponent = !!renderContent.componentOptions\r\n if (isComponent) {\r\n componentVNode = renderContent\r\n return renderContent\r\n }\r\n componentVNode = null\r\n return h('div', [renderContent])\r\n }\r\n\r\n componentVNode = null\r\n // 退化兜底\r\n return h('div', [String(renderContent || '')])\r\n }\r\n },\r\n})\r\n</script>\r\n","<template>\r\n <div class=\"dp-dialog_wrapper\">\r\n <!--\r\n Element UI dialog 与 Element Plus 关键差异:\r\n - 双向绑定::visible.sync (Vue 3 是 v-model)\r\n - 不支持 draggable 属性(Element UI 2.x 无此特性,已去掉传透)\r\n - 全屏:fullscreen 同名属性\r\n - header/footer 槽位写法相同,但不能用 #header (Vue 2.6+ 支持新语法,2.5 及以下需 slot=\"header\")\r\n - 图标改用 i.el-icon-* class 字符串\r\n -->\r\n <el-dialog\r\n :class=\"['dg-dialog', initDialogCls]\"\r\n v-bind=\"filteredAttrs\"\r\n :visible.sync=\"dialogVisible\"\r\n :width=\"typeof width === 'number' ? width + 'px' : width\"\r\n :show-close=\"false\"\r\n :fullscreen=\"filteredAttrs && filteredAttrs.fullscreen != null ? filteredAttrs.fullscreen : isFullscreen\"\r\n :append-to-body=\"appendToBody\"\r\n :modal-append-to-body=\"modalAppendToBody\"\r\n :close-on-click-modal=\"closeOnClickModal\"\r\n :close-on-press-escape=\"closeOnPressEscape\"\r\n :destroy-on-close=\"destroyOnClose\"\r\n :before-close=\"beforeCloseHandler\"\r\n @close=\"onDialogClose\"\r\n @closed=\"onDialogClosed\"\r\n >\r\n <template #title>\r\n <render-jsx\r\n v-if=\"renderHeader && typeof renderHeader === 'function'\"\r\n :render=\"renderHeader\"\r\n :instance=\"getCurrentInstanceModel\"\r\n />\r\n <template v-else>\r\n <div class=\"dialog-header\">\r\n <span class=\"dialog-title\">{{ title }}</span>\r\n <div class=\"btns\">\r\n <i\r\n v-show=\"!hiddenFullBtn\"\r\n :class=\"isFullscreen ? 'el-icon-copy-document' : 'el-icon-full-screen'\"\r\n @click=\"handleFullscreen\"\r\n />\r\n <i class=\"el-icon-close\" @click=\"handleClose\" />\r\n </div>\r\n </div>\r\n </template>\r\n </template>\r\n\r\n <div class=\"dialog_body_layouts\" :style=\"initDialogHeight\">\r\n <render-jsx\r\n v-if=\"render && typeof render === 'function'\"\r\n :refs=\"renderBodyRefsObject\"\r\n :instance=\"getCurrentInstanceModel\"\r\n :render=\"render\"\r\n :components=\"dialogComponents\"\r\n />\r\n </div>\r\n\r\n <template v-if=\"!isHiddenFooter\" #footer>\r\n <span v-if=\"!$slots.footer\" class=\"dialog-footer\">\r\n <render-jsx\r\n v-if=\"renderFooter && typeof renderFooter === 'function'\"\r\n :render=\"renderFooter\"\r\n :instance=\"getCurrentInstanceModel\"\r\n />\r\n <template v-else-if=\"configBtn && configBtn.length\">\r\n <template v-for=\"(it, inx) in configBtn\">\r\n <el-button\r\n v-if=\"checkPermission(it.permissionValue)\"\r\n :key=\"it.key || inx\"\r\n size=\"small\"\r\n v-bind=\"filterOptions(it)\"\r\n :icon=\"getCompIcon(it.icon)\"\r\n :disabled=\"getDisabled(it)\"\r\n @click=\"() => handleBtnClick(it)\"\r\n >\r\n {{ it.name }}\r\n </el-button>\r\n </template>\r\n </template>\r\n </span>\r\n <slot v-else name=\"footer\" />\r\n </template>\r\n </el-dialog>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsDialog 弹窗组件 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异(详细列举):\r\n * 1. <script setup> → defineComponent + setup()\r\n * 2. dialog 双向绑定::visible.sync 替代 v-model\r\n * 3. 图标系统:el-icon-* class 字符串替代 Element Plus 图标组件\r\n * 4. ElConfigProvider 不存在 —— 国际化由 Vue.use(ElementUI, { locale }) 全局完成\r\n * 5. draggable 属性在 Element UI 2.x 中不存在,本组件不再支持 isDraggable\r\n * (prop 仍保留兼容,仅传递给底层用户使用,但 el-dialog 会忽略)\r\n * 6. exposed 方法:通过 expose() 或挂到 vm 上(Vue 2 中通过 setup 返回值即可)\r\n *\r\n * 业务能力(render slot/configBtn/全屏/maxHeight/事件)100% 与 Vue 3 版本一致。\r\n */\r\nimport {\r\n defineComponent,\r\n ref,\r\n reactive,\r\n computed,\r\n inject,\r\n provide,\r\n getCurrentInstance,\r\n} from '../../vue-compat'\r\nimport { getGlobalConfig, type BtnConfig } from '@es-plus/core'\r\nimport RenderJsx from './render-jsx.vue'\r\nimport { getCompIcon } from '../../utils/icon'\r\n\r\nexport default defineComponent({\r\n name: 'EsDialog',\r\n components: { RenderJsx },\r\n inheritAttrs: false,\r\n props: {\r\n title: { type: String, default: '' },\r\n visible: { type: Boolean, default: false },\r\n appendTo: { type: [Object, String], default: undefined },\r\n appendToBody: { type: Boolean, default: false },\r\n modalAppendToBody: { type: Boolean, default: true },\r\n closeOnClickModal: { type: Boolean, default: true },\r\n closeOnPressEscape: { type: Boolean, default: true },\r\n destroyOnClose: { type: Boolean, default: false },\r\n hiddenFullBtn: { type: Boolean, default: false },\r\n width: { type: [String, Number], default: '50%' },\r\n // Element UI 不支持 draggable,保留 prop 兼容用户配置但实际不生效\r\n isDraggable: { type: Boolean, default: false },\r\n confirmText: { type: String, default: '' },\r\n cancelText: { type: String, default: '' },\r\n configBtn: { type: Array as () => BtnConfig[], default: () => [] },\r\n maxHeight: { type: [String, Number], default: undefined },\r\n isHiddenFooter: { type: Boolean, default: false },\r\n renderHeader: { type: Function, default: undefined },\r\n renderFooter: { type: Function, default: undefined },\r\n render: { type: Function, default: undefined },\r\n fullscreen: { type: Boolean, default: false },\r\n // 用户透传给 RenderJsx 的额外组件映射(如 EsTable / EsForm 引用)\r\n components: { type: Object, default: () => ({}) },\r\n },\r\n emits: ['update:visible', 'closed', 'submit'],\r\n setup(props, { emit, attrs, slots, expose }) {\r\n const instance = getCurrentInstance() as unknown as Record<string, unknown>\r\n const lyFormInstance = ref<unknown>(null)\r\n const renderBodyRefsObject = reactive<Record<string, unknown>>({})\r\n const isFullscreen = ref(false)\r\n const dialogInstance = instance\r\n\r\n const esPlus =\r\n inject<Record<string, unknown>>('$EsPlus', null as unknown as Record<string, unknown>) ??\r\n (getGlobalConfig() as Record<string, unknown>) ??\r\n {}\r\n\r\n const checkPermission = (pvalue?: string): boolean => {\r\n if (!pvalue) return true\r\n const fn = esPlus.permission\r\n return typeof fn === 'function' ? (fn as (v: string) => boolean)(pvalue) : true\r\n }\r\n\r\n const filterOptions = (it: BtnConfig) => {\r\n const {\r\n icon: _icon,\r\n click: _c,\r\n permissionValue: _p,\r\n name: _n,\r\n disabled: _d,\r\n key: _k,\r\n ...opt\r\n } = it as unknown as Record<string, unknown>\r\n return opt\r\n }\r\n\r\n const getDisabled = (it: BtnConfig): boolean => {\r\n const d = (it as Record<string, unknown>).disabled\r\n if (typeof d === 'function') return (d as () => boolean)()\r\n return !!d\r\n }\r\n\r\n const closeFullscreen = () => {\r\n setTimeout(() => {\r\n if (isFullscreen.value) {\r\n isFullscreen.value = false\r\n }\r\n }, 500)\r\n }\r\n\r\n const handleFullscreen = () => {\r\n if ((attrs as Record<string, unknown>)?.fullscreen) return\r\n isFullscreen.value = !isFullscreen.value\r\n }\r\n\r\n const dialogVisible = computed({\r\n get: () => props.visible || false,\r\n set: (val: boolean) => {\r\n emit('update:visible', val)\r\n if (!val) {\r\n emit('closed', val)\r\n closeFullscreen()\r\n }\r\n },\r\n })\r\n\r\n const handleClose = () => {\r\n // 通过 set dialogVisible 触发 :visible.sync → emit('update:visible', false)\r\n ;(dialogVisible as unknown as { value: boolean }).value = false\r\n emit('closed', false)\r\n closeFullscreen()\r\n }\r\n\r\n const onDialogClose = () => {\r\n // el-dialog @close 触发,与 handleClose 等价\r\n emit('closed', false)\r\n closeFullscreen()\r\n }\r\n\r\n const onDialogClosed = () => {\r\n // 动画结束后触发\r\n }\r\n\r\n /**\r\n * el-dialog 的 before-close 钩子:返回 false 可阻止关闭\r\n * 此处保持开放(done() 调用即关闭)\r\n */\r\n const beforeCloseHandler = (done: () => void) => {\r\n done()\r\n }\r\n\r\n const filteredAttrs = computed(() => ({ ...(attrs as Record<string, unknown>) }))\r\n\r\n const initDialogCls = computed(() => {\r\n if (!isFullscreen.value) {\r\n if (props.maxHeight) return 'dialogShadow'\r\n return 'dialogAuto'\r\n }\r\n return 'dialogFull'\r\n })\r\n\r\n const getMaxContentHeight = () => {\r\n const viewH = typeof window !== 'undefined' ? window.innerHeight : 800\r\n return Math.max(viewH - 135, 200)\r\n }\r\n\r\n const initDialogHeight = computed(() => {\r\n const viewH = getMaxContentHeight()\r\n if (!isFullscreen.value) {\r\n if (props.maxHeight) {\r\n return {\r\n maxHeight:\r\n typeof props.maxHeight === 'number'\r\n ? `${props.maxHeight}px`\r\n : (props.maxHeight as string),\r\n }\r\n }\r\n return { maxHeight: viewH + 'px' }\r\n }\r\n return { height: viewH + 'px' }\r\n })\r\n\r\n const getCurrentInstanceModel = computed(() => ({\r\n renderBodyRefs: (renderBodyRefsObject as Record<string, unknown>).currentRef,\r\n renderBodyRefsObject,\r\n lyFormInstance,\r\n dialogInstance,\r\n getRefs: () => renderBodyRefsObject,\r\n }))\r\n\r\n const handleBtnClick = (it: BtnConfig) => {\r\n const click = (it as Record<string, unknown>).click as Function | undefined\r\n if (typeof click === 'function') {\r\n click((renderBodyRefsObject as Record<string, unknown>).currentRef, {\r\n close: handleClose,\r\n getRefs: (name?: string) => {\r\n if (name)\r\n return (renderBodyRefsObject as Record<string, unknown>)[name] || null\r\n return renderBodyRefsObject\r\n },\r\n dialogInstance,\r\n })\r\n }\r\n }\r\n\r\n // 子组件 EsForm 注册的回调(兼容 EsForm <-> EsDialog 联动)\r\n provide('bodyFormInstance', (e: unknown) => {\r\n lyFormInstance.value = e\r\n })\r\n\r\n // dialogComponents:包给 RenderJsx 的组件映射(Vue 2 没有 Vue 3 的全局 components 注入)\r\n // 用户在 useDialog 调用时若需要 EsTable/EsForm,需自行 import 并通过 components prop 透传\r\n const dialogComponents = computed(() => ({\r\n ...(props.components as Record<string, unknown>),\r\n }))\r\n\r\n const exposed = {\r\n closed: handleClose,\r\n }\r\n if (typeof expose === 'function') {\r\n expose(exposed)\r\n }\r\n\r\n return {\r\n // state\r\n dialogVisible,\r\n isFullscreen,\r\n lyFormInstance,\r\n renderBodyRefsObject,\r\n // computeds\r\n filteredAttrs,\r\n initDialogCls,\r\n initDialogHeight,\r\n getCurrentInstanceModel,\r\n dialogComponents,\r\n // methods\r\n handleClose,\r\n handleFullscreen,\r\n handleBtnClick,\r\n onDialogClose,\r\n onDialogClosed,\r\n beforeCloseHandler,\r\n checkPermission,\r\n filterOptions,\r\n getDisabled,\r\n getCompIcon,\r\n // exposed\r\n ...exposed,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.dp-dialog_wrapper {\r\n ::v-deep(.dialogAuto) {\r\n margin: 0px !important;\r\n }\r\n ::v-deep(.el-dialog) {\r\n padding: 10px;\r\n\r\n .el-dialog__footer {\r\n padding-top: 0px;\r\n }\r\n\r\n .el-dialog__body {\r\n padding: 10px 0px;\r\n }\r\n\r\n .el-dialog__header {\r\n border-bottom: 1px solid #eee;\r\n display: flex;\r\n padding: 0px 0px 10px 0px;\r\n align-items: center;\r\n justify-content: space-between;\r\n margin: 0;\r\n }\r\n }\r\n}\r\n\r\n.dialog-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n width: 100%;\r\n}\r\n\r\n.dialog-title {\r\n line-height: 24px;\r\n font-size: 14px;\r\n color: #303133;\r\n font-weight: bold;\r\n}\r\n\r\n.btns {\r\n display: flex;\r\n align-items: center;\r\n\r\n i {\r\n margin-right: 8px;\r\n font-size: 14px;\r\n cursor: pointer;\r\n\r\n &:last-child {\r\n margin-right: 0;\r\n }\r\n }\r\n}\r\n\r\n.dialog_body_layouts {\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n scrollbar-width: thin;\r\n scrollbar-color: #87a2bd26 #c8d5e147;\r\n}\r\n\r\n/* 滚动条样式 */\r\n*::-webkit-scrollbar {\r\n width: 14px;\r\n height: 14px;\r\n}\r\n\r\n*::-webkit-scrollbar-button {\r\n width: 0;\r\n height: 0;\r\n display: none;\r\n}\r\n\r\n*::-webkit-scrollbar-corner {\r\n background-color: transparent;\r\n}\r\n\r\n*::-webkit-scrollbar-thumb {\r\n min-height: 12px;\r\n border: 4px solid transparent;\r\n background-clip: content-box;\r\n border-radius: 7px;\r\n background-color: #c8d5e1;\r\n\r\n &:hover {\r\n background-color: #a8bbcf;\r\n }\r\n\r\n &:active {\r\n background-color: #87a2bd;\r\n }\r\n}\r\n\r\n*::-webkit-scrollbar-track {\r\n background-color: transparent;\r\n}\r\n\r\n*::-webkit-scrollbar-track-piece {\r\n background-color: transparent;\r\n}\r\n</style>\r\n","/**\r\n * useDialog 编程式弹窗 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 实现的核心差异:\r\n * Vue 3: createVNode(Component, props) → render(vNode, container) → 通过 vNode.component.props 修改\r\n * Vue 2: Vue.extend(Component) → new Ctor({ propsData }) → $mount() → 实例方法/$props 修改\r\n *\r\n * 实现策略:\r\n * 1. Vue.extend 把组件定义转为可实例化的构造函数\r\n * 2. new Ctor({ propsData }) 创建实例\r\n * 3. $mount() 后把 $el 追加到 appendTo 元素(默认 document.body)\r\n * 4. 关闭时通过设置 dialogInstance.visible = false 触发动画 + emit closed\r\n * 5. destroy 时调用 $destroy() 并 remove DOM 节点\r\n *\r\n * 与 Vue 3 版本保持一致的对外 API:\r\n * useDialog()(opts) → 默认模式:单例式,重复调用复用同一实例\r\n * useDialog(comp, { onlyInstance: true })(opts) → 每次都创建新实例\r\n *\r\n * 兼容性说明:\r\n * - Vue 2 没有 appContext,但 Vue.extend 创建的实例会继承全局 plugin(如 Vue.use(ElementUI))\r\n * - 依赖注入:useDialog 创建的弹窗组件 与 父组件没有 provide/inject 关系\r\n * 若需要 i18n / 全局配置注入,请通过 props 显式传入\r\n */\r\n\r\nimport { Vue, getCurrentInstance } from '../../vue-compat'\r\nimport EsDialog from './component.vue'\r\nimport type { DialogOptions } from '@es-plus/core'\r\n\r\nexport interface DialogCallable {\r\n (dialogOptions: DialogOptions): unknown\r\n close: () => void\r\n}\r\n\r\nexport interface DialogCallableWithDestroy extends DialogCallable {\r\n destroy: () => void\r\n}\r\n\r\nconst getAppendToElement = (appendTo?: string | HTMLElement): HTMLElement => {\r\n if (typeof appendTo === 'string') {\r\n return (document.querySelector(appendTo) as HTMLElement) || document.body\r\n }\r\n return appendTo instanceof HTMLElement ? appendTo : document.body\r\n}\r\n\r\n/**\r\n * Vue 2 中将 Vue 3 风格的 onXxx 事件回调转为 propsData/$on 监听\r\n *\r\n * Vue 3 用户写法:useDialog()({ onClosed: () => {}, onSubmit: () => {} })\r\n * Vue 2 中需要:把 onClosed → 监听 'closed' 事件,onSubmit → 监听 'submit' 事件\r\n */\r\nconst extractEventHandlers = (\r\n options: Record<string, unknown>\r\n): { propsData: Record<string, unknown>; events: Record<string, Function> } => {\r\n const events: Record<string, Function> = {}\r\n const propsData: Record<string, unknown> = {}\r\n\r\n Object.entries(options).forEach(([key, value]) => {\r\n if (key.startsWith('on') && typeof value === 'function' && key.length > 2) {\r\n // 'onClosed' → 'closed', 'onSubmit' → 'submit', 'onUpdate:visible' → 'update:visible'\r\n const eventName = key.slice(2)\r\n // 'Closed' → 'closed', 保留 'update:visible' 中的 ':'\r\n const normalized = eventName.charAt(0).toLowerCase() + eventName.slice(1)\r\n events[normalized] = value as Function\r\n } else {\r\n propsData[key] = value\r\n }\r\n })\r\n\r\n return { propsData, events }\r\n}\r\n\r\nconst initInstance = (\r\n Component: any,\r\n options: DialogOptions,\r\n appendTo?: string | HTMLElement\r\n) => {\r\n const { propsData, events } = extractEventHandlers(options as Record<string, unknown>)\r\n\r\n // Vue.extend(Component) 把组件定义转为构造函数\r\n const Ctor = (Vue as any).extend(Component)\r\n const vm = new Ctor({ propsData })\r\n\r\n // 注册事件监听(注意:Vue 2 中通过 $on 监听)\r\n Object.entries(events).forEach(([eventName, handler]) => {\r\n vm.$on(eventName, handler)\r\n })\r\n\r\n // $mount() 不传参数 = 创建一个游离的 $el(不挂到 DOM 树)\r\n // 然后我们手工 appendChild 到目标节点\r\n vm.$mount()\r\n const target = getAppendToElement(appendTo)\r\n target.appendChild(vm.$el)\r\n\r\n return vm\r\n}\r\n\r\nexport function useDialog(\r\n Component?: any,\r\n opt?: { onlyInstance?: false }\r\n): DialogCallableWithDestroy\r\nexport function useDialog(Component?: any, opt?: { onlyInstance: true }): DialogCallable\r\nexport function useDialog(Component?: any, opt: { onlyInstance?: boolean } = {}) {\r\n Component = Component || EsDialog\r\n const options = Object.assign({ onlyInstance: false }, opt)\r\n\r\n if (options.onlyInstance) {\r\n // ─── 多实例模式:每次调用都创建新弹窗 ───\r\n let lastVm: any = null\r\n\r\n const close = () => {\r\n if (lastVm) {\r\n lastVm.visible = false\r\n // 等动画结束后销毁\r\n setTimeout(() => {\r\n if (lastVm) {\r\n lastVm.$destroy()\r\n if (lastVm.$el && lastVm.$el.parentNode) {\r\n lastVm.$el.parentNode.removeChild(lastVm.$el)\r\n }\r\n lastVm = null\r\n }\r\n }, 300)\r\n }\r\n }\r\n\r\n const DialogComponent = (dialogOptions: DialogOptions) => {\r\n if (dialogOptions.visible === undefined) {\r\n dialogOptions.visible = true\r\n }\r\n\r\n const originalOnClosed = (dialogOptions as Record<string, unknown>).onClosed as\r\n | Function\r\n | undefined\r\n const originalOnSubmit = (dialogOptions as Record<string, unknown>).onSubmit as\r\n | Function\r\n | undefined\r\n\r\n ;(dialogOptions as Record<string, unknown>).onClosed = (...args: unknown[]) => {\r\n originalOnClosed?.(...args)\r\n close()\r\n }\r\n\r\n ;(dialogOptions as Record<string, unknown>).onSubmit = (closeFn: Function = close) => {\r\n originalOnSubmit?.(closeFn)\r\n }\r\n\r\n lastVm = initInstance(Component, dialogOptions, dialogOptions.appendTo)\r\n return lastVm\r\n }\r\n\r\n DialogComponent.close = close\r\n return DialogComponent\r\n } else {\r\n // ─── 单例模式:复用同一弹窗实例 ───\r\n let vm: any = null\r\n\r\n const close = () => {\r\n if (vm) {\r\n vm.visible = false\r\n }\r\n }\r\n\r\n const destroy = () => {\r\n if (vm) {\r\n vm.$destroy()\r\n if (vm.$el && vm.$el.parentNode) {\r\n vm.$el.parentNode.removeChild(vm.$el)\r\n }\r\n vm = null\r\n }\r\n }\r\n\r\n const DialogComponent = (dialogOptions: DialogOptions) => {\r\n // 已有实例 → 复用并更新 props\r\n if (vm) {\r\n Object.entries(dialogOptions).forEach(([key, value]) => {\r\n if (!key.startsWith('on')) {\r\n vm[key] = value\r\n }\r\n })\r\n vm.visible = true\r\n return vm\r\n }\r\n\r\n const mergedOptions: DialogOptions = {\r\n visible: true,\r\n width: '50%',\r\n destroyOnClose: true,\r\n ...dialogOptions,\r\n } as DialogOptions\r\n\r\n const originalOnClosed = (mergedOptions as Record<string, unknown>).onClosed as\r\n | Function\r\n | undefined\r\n const originalOnSubmit = (mergedOptions as Record<string, unknown>).onSubmit as\r\n | Function\r\n | undefined\r\n\r\n ;(mergedOptions as Record<string, unknown>).onClosed = () => {\r\n originalOnClosed?.()\r\n close()\r\n }\r\n\r\n ;(mergedOptions as Record<string, unknown>).onSubmit = (closeFn: Function = close) => {\r\n originalOnSubmit?.(closeFn)\r\n }\r\n\r\n vm = initInstance(Component, mergedOptions, mergedOptions.appendTo)\r\n return vm\r\n }\r\n\r\n DialogComponent.close = close\r\n DialogComponent.destroy = destroy\r\n return DialogComponent\r\n }\r\n}\r\n\r\nexport default useDialog\r\n","/**\r\n * EsDialog 组件入口\r\n *\r\n * 使用方式:\r\n * 1. 默认导入:import EsDialog, { useDialog } from '@es-plus/vue2/es-dialog'\r\n * 2. install 安装:通过 Vue.use(EsPlus) 全局注册(同时会通过 Vue.prototype.$useDialog 暴露)\r\n */\r\n\r\nimport EsDialog from './component.vue'\r\nimport useDialog from './use-dialog'\r\nimport type { Vue } from '../../vue-compat'\r\n\r\n;(EsDialog as unknown as { install: (V: typeof Vue) => void }).install = function (Vue) {\r\n Vue.component((EsDialog as unknown as { name: string }).name || 'EsDialog', EsDialog)\r\n // 同时挂载到 Vue.prototype,方便 Options API 中通过 this.$useDialog() 调用\r\n ;(Vue as unknown as { prototype: Record<string, unknown> }).prototype.$useDialog = useDialog\r\n}\r\n\r\nexport default EsDialog\r\nexport { EsDialog, useDialog }\r\n","<template>\r\n <div class=\"es-crud-page\">\r\n <!--\r\n Vue 3 → Vue 2 关键差异:\r\n - v-model:data-source → :data-source.sync\r\n - v-model:pagination → :pagination.sync\r\n Vue 2.3+ 支持 .sync 修饰符自动展开为 :data-source + @update:data-source\r\n -->\r\n <es-table\r\n ref=\"tableRef\"\r\n :columns=\"mergedColumns\"\r\n :options=\"mergedOptions\"\r\n :data-source.sync=\"tableData\"\r\n :pagination.sync=\"paginationState\"\r\n v-bind=\"$attrs\"\r\n >\r\n <es-form\r\n v-if=\"schema.formItems && schema.formItems.length\"\r\n ref=\"formRef\"\r\n :model=\"queryModel\"\r\n :form-item-list=\"schema.formItems\"\r\n :config-btn=\"mergedFormBtns\"\r\n :layout-form-props=\"formLayoutProps\"\r\n />\r\n <template v-for=\"(_, name) in $slots\" #[name]=\"slotData\">\r\n <slot :name=\"name\" v-bind=\"slotData || {}\" />\r\n </template>\r\n </es-table>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsCrudPage —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的关键差异:\r\n * 1. <script setup> + defineProps/defineEmits/defineExpose → defineComponent + setup()\r\n * 2. v-model:* → .sync 修饰符\r\n * 3. ElMessageBox 替换为:\r\n * a) Element UI 的 MessageBox.confirm(兼容 Vue.use(ElementUI) 全局注册)\r\n * b) 或通过 Vue.prototype.$confirm(同样由 Element UI 全局注册)\r\n * 此处直接 import 'element-ui' 的 MessageBox 以避免依赖原型方法\r\n * 4. useDialog 来自 Vue 2 版本(Vue.extend + $mount)\r\n *\r\n * 业务逻辑(schema 归一化、按钮处理、弹窗管理)100% 与 Vue 3 版本一致。\r\n */\r\nimport { defineComponent, ref, reactive, computed, watch } from '../../vue-compat'\r\nimport { MessageBox } from 'element-ui'\r\nimport EsForm from '../es-form/es-form.vue'\r\nimport EsTable from '../es-table/component.vue'\r\nimport useDialog from '../es-dialog/use-dialog'\r\nimport type {\r\n CrudPageSchema,\r\n CrudBtnConfig,\r\n TableBtnConfig,\r\n OperationColumnConfig,\r\n RowBtnConfig,\r\n CrudDialogConfig,\r\n DialogActionContext,\r\n} from './types'\r\nimport type { BtnConfig, TableColumn } from '@es-plus/core'\r\n\r\nexport default defineComponent({\r\n name: 'EsCrudPage',\r\n components: { EsForm, EsTable },\r\n inheritAttrs: false,\r\n props: {\r\n schema: { type: Object as () => CrudPageSchema, required: true },\r\n httpRequest: {\r\n type: Function as unknown as () => (params: Record<string, unknown>) => Promise<unknown>,\r\n default: undefined,\r\n },\r\n autoLoad: { type: Boolean, default: true },\r\n },\r\n emits: [\r\n 'query',\r\n 'add',\r\n 'edit',\r\n 'delete',\r\n 'view',\r\n 'export',\r\n 'row-click',\r\n 'btn-click',\r\n 'dialog-confirm',\r\n 'dialog-cancel',\r\n 'dialog-open',\r\n ],\r\n setup(props, { emit, expose }) {\r\n const tableRef = ref<any>(null)\r\n const formRef = ref<any>(null)\r\n const tableData = ref<Record<string, unknown>[]>([])\r\n const queryModel = reactive<Record<string, unknown>>({})\r\n\r\n // 同步 schema.formItems → queryModel 默认字段\r\n watch(\r\n () => props.schema.formItems,\r\n (items) => {\r\n if (items) {\r\n items.forEach((item) => {\r\n if (item.prop && !(item.prop in queryModel)) {\r\n ;(queryModel as Record<string, unknown>)[item.prop as string] = ''\r\n }\r\n })\r\n }\r\n },\r\n { immediate: true }\r\n )\r\n\r\n const paginationState = ref({\r\n current: 1,\r\n pageSize: 10,\r\n total: 0,\r\n ...(props.schema.pagination || {}),\r\n })\r\n\r\n // ─── 弹窗归一化(向后兼容旧 dialogFormItems / actions 模式) ─────\r\n const normalizedDialogs = computed<Record<string, CrudDialogConfig>>(() => {\r\n if (props.schema.dialogs) return props.schema.dialogs\r\n if (!props.schema.dialogFormItems?.length) return {}\r\n\r\n const dialogBase = {\r\n width: props.schema.dialogOptions?.width || '600px',\r\n formItems: props.schema.dialogFormItems,\r\n ...(props.schema.dialogOptions || {}),\r\n } as CrudDialogConfig\r\n\r\n const result: Record<string, CrudDialogConfig> = {}\r\n const actions = props.schema.actions || ['add', 'edit', 'delete']\r\n\r\n if (actions.includes('add')) result.add = { ...dialogBase, title: '新增' }\r\n if (actions.includes('edit')) result.edit = { ...dialogBase, title: '编辑' }\r\n if (actions.includes('view'))\r\n result.view = { ...dialogBase, title: '查看', isHiddenFooter: true }\r\n\r\n return result\r\n })\r\n\r\n const normalizedToolbarBtns = computed<CrudBtnConfig[]>(() => {\r\n if (props.schema.toolbarBtns) return props.schema.toolbarBtns\r\n if (props.schema.dialogs || props.schema.operationColumn !== undefined) return []\r\n\r\n const actions = props.schema.actions || ['add', 'edit', 'delete']\r\n const btns: CrudBtnConfig[] = []\r\n\r\n if (actions.includes('add')) {\r\n btns.push({\r\n name: '新增',\r\n type: 'primary',\r\n key: 'add',\r\n icon: 'Plus',\r\n dialogKey: 'add',\r\n } as CrudBtnConfig)\r\n }\r\n if (actions.includes('export')) {\r\n btns.push({\r\n name: '导出',\r\n key: 'export',\r\n icon: 'Download',\r\n actionType: 'export',\r\n } as CrudBtnConfig)\r\n }\r\n if (actions.includes('import')) {\r\n btns.push({\r\n name: '导入',\r\n key: 'import',\r\n icon: 'Upload',\r\n actionType: 'import',\r\n } as CrudBtnConfig)\r\n }\r\n\r\n return btns\r\n })\r\n\r\n const normalizedOperationColumn = computed<OperationColumnConfig | false | undefined>(\r\n () => {\r\n if (props.schema.operationColumn !== undefined) return props.schema.operationColumn\r\n\r\n const actions = props.schema.actions || ['add', 'edit', 'delete']\r\n const hasActionCol = props.schema.columns?.some(\r\n (c) => c.prop === 'action' || c.prop === 'operate' || c.btns\r\n )\r\n if (hasActionCol) return undefined\r\n\r\n const rowActions = actions.filter((a) => ['edit', 'delete', 'view'].includes(a))\r\n if (rowActions.length === 0) return false\r\n\r\n const btns: RowBtnConfig[] = []\r\n if (actions.includes('view'))\r\n btns.push({ name: '查看', type: 'primary', key: 'view', dialogKey: 'view' })\r\n if (actions.includes('edit'))\r\n btns.push({ name: '编辑', type: 'primary', key: 'edit', dialogKey: 'edit' })\r\n if (actions.includes('delete'))\r\n btns.push({\r\n name: '删除',\r\n type: 'danger',\r\n key: 'delete',\r\n confirm: '确定删除该条数据吗?',\r\n })\r\n\r\n return {\r\n label: '操作',\r\n width: btns.length * 80 + 20,\r\n fixed: 'right',\r\n btns,\r\n }\r\n }\r\n )\r\n\r\n // ─── 表单按钮合并 ─────\r\n const mergedFormBtns = computed<BtnConfig[]>(() => {\r\n if (props.schema.queryBtns) return props.schema.queryBtns\r\n\r\n const baseBtns: BtnConfig[] = [\r\n { name: '查询', type: 'primary', key: 'query', triggerEvent: true } as BtnConfig,\r\n { name: '重置', key: 'rest', triggerEvent: true } as BtnConfig,\r\n ]\r\n\r\n const toolbarBtns = normalizedToolbarBtns.value.map((btn) => {\r\n const resolvedBtn: BtnConfig = { ...btn }\r\n if (!(resolvedBtn as Record<string, unknown>).click) {\r\n ;(resolvedBtn as Record<string, unknown>).click = () => handleToolbarBtnClick(btn)\r\n }\r\n return resolvedBtn\r\n })\r\n\r\n return [...baseBtns, ...toolbarBtns]\r\n })\r\n\r\n // ─── 表格列合并(追加操作列) ─────\r\n const mergedColumns = computed<TableColumn[]>(() => {\r\n const cols = [...(props.schema.columns || [])]\r\n const opCol = normalizedOperationColumn.value\r\n\r\n if (opCol === false || opCol === undefined) return cols\r\n\r\n const actionBtns = (opCol as OperationColumnConfig).btns.map((btn) => ({\r\n name: btn.name,\r\n type: btn.type,\r\n permissionValue: btn.permissionValue,\r\n clickEvent: (row: Record<string, unknown>) => handleRowBtnClick(btn, row),\r\n }))\r\n\r\n cols.push({\r\n prop: 'operate',\r\n label: (opCol as OperationColumnConfig).label || '操作',\r\n width:\r\n (opCol as OperationColumnConfig).width || actionBtns.length * 80 + 20,\r\n fixed: ((opCol as OperationColumnConfig).fixed as string) || 'right',\r\n btns: actionBtns,\r\n } as unknown as TableColumn)\r\n\r\n return cols\r\n })\r\n\r\n // ─── 表格工具栏按钮 ─────\r\n const normalizedTableBtns = computed(() => {\r\n if (!props.schema.tableBtns?.length) return []\r\n return props.schema.tableBtns.map((btn: TableBtnConfig) => ({\r\n name: btn.name,\r\n type: btn.type,\r\n size: (btn as Record<string, unknown>).size || 'small',\r\n icon: btn.icon,\r\n code: btn.code || 1,\r\n permissionValue: btn.permissionValue,\r\n loading: (btn as Record<string, unknown>).loading,\r\n disabled: (btn as Record<string, unknown>).disabled,\r\n click: () => handleToolbarBtnClick(btn),\r\n }))\r\n })\r\n\r\n // ─── 表格选项 ─────\r\n const mergedOptions = computed(() => {\r\n const base: Record<string, unknown> = {\r\n border: true,\r\n isInitRun: props.autoLoad,\r\n ...(props.schema.tableOptions || {}),\r\n }\r\n if (props.httpRequest) {\r\n base.httpRequest = props.httpRequest\r\n }\r\n const tBtns = normalizedTableBtns.value\r\n if (tBtns.length > 0) {\r\n const existing = (base.configBtn as unknown[]) || []\r\n base.configBtn = [...existing, ...tBtns]\r\n }\r\n return base\r\n })\r\n\r\n // ─── 表单布局 ─────\r\n const formLayoutProps = computed(() => {\r\n const layout = props.schema.formLayout\r\n if (!layout) return undefined\r\n return {\r\n rowLayProps: { gutter: 16 },\r\n formLayProps: {\r\n labelBtnWidth: layout.labelWidth,\r\n ...(layout.minFoldRows ? { minFoldRows: layout.minFoldRows } : {}),\r\n },\r\n } as Record<string, unknown>\r\n })\r\n\r\n // ─── 工具栏按钮处理 ─────\r\n async function handleToolbarBtnClick(btn: CrudBtnConfig) {\r\n const key = btn.key || btn.actionType || ''\r\n\r\n if (btn.confirm) {\r\n const msg = typeof btn.confirm === 'string' ? btn.confirm : '确定执行此操作吗?'\r\n try {\r\n await MessageBox.confirm(msg, '提示', { type: 'warning' })\r\n } catch {\r\n return\r\n }\r\n }\r\n\r\n if (btn.dialogKey) {\r\n if (key === 'add') emit('add')\r\n openDialog(btn.dialogKey)\r\n return\r\n }\r\n\r\n if (key === 'export' || btn.actionType === 'export') {\r\n emit('export', { ...queryModel })\r\n } else if (key === 'add') {\r\n emit('add')\r\n }\r\n\r\n emit('btn-click', key, { ...queryModel })\r\n }\r\n\r\n // ─── 行按钮处理 ─────\r\n async function handleRowBtnClick(btn: RowBtnConfig, row: Record<string, unknown>) {\r\n const key = btn.key || ''\r\n\r\n if (btn.confirm) {\r\n const msg = typeof btn.confirm === 'string' ? btn.confirm : '确定执行此操作吗?'\r\n try {\r\n await MessageBox.confirm(msg, '提示', { type: 'warning' })\r\n } catch {\r\n return\r\n }\r\n }\r\n\r\n if (btn.click) {\r\n btn.click(row, { refresh, getSelectedRows, openDialog })\r\n return\r\n }\r\n\r\n if (btn.dialogKey) {\r\n openDialog(btn.dialogKey, row)\r\n return\r\n }\r\n\r\n if (key === 'edit') emit('edit', row)\r\n else if (key === 'delete') emit('delete', row)\r\n else if (key === 'view') emit('view', row)\r\n\r\n emit('btn-click', key, row)\r\n }\r\n\r\n // ─── 弹窗管理 ─────\r\n const dialogInstances = new Map<string, ReturnType<typeof useDialog>>()\r\n\r\n function openDialog(key: string, row?: Record<string, unknown>) {\r\n const dialogConfig = normalizedDialogs.value[key]\r\n if (!dialogConfig) return\r\n\r\n emit('dialog-open', key, row)\r\n\r\n const dialog = useDialog()\r\n dialogInstances.set(key, dialog)\r\n\r\n const formData = reactive<Record<string, unknown>>({})\r\n if (dialogConfig.formItems) {\r\n dialogConfig.formItems.forEach((item) => {\r\n if (item.prop) {\r\n ;(formData as Record<string, unknown>)[item.prop] =\r\n row?.[item.prop] ?? ''\r\n }\r\n })\r\n }\r\n\r\n const title =\r\n typeof dialogConfig.title === 'function'\r\n ? (dialogConfig.title as Function)(row)\r\n : dialogConfig.title || ''\r\n\r\n dialogConfig.onOpen?.(row)\r\n\r\n const configBtn = resolveDialogBtns(key, dialogConfig, formData, row || {})\r\n\r\n dialog({\r\n title,\r\n width: dialogConfig.width || '600px',\r\n isDraggable: dialogConfig.isDraggable,\r\n maxHeight: dialogConfig.maxHeight,\r\n fullscreen: dialogConfig.fullscreen,\r\n isHiddenFooter: dialogConfig.isHiddenFooter,\r\n // 用户自定义 render\r\n render: dialogConfig.render\r\n ? (h: any, inst: any) => {\r\n return dialogConfig.render!(h, {\r\n row: row || {},\r\n model: formData,\r\n registerRef: inst.registerRef,\r\n close: () => closeDialog(key),\r\n refresh,\r\n })\r\n }\r\n : dialogConfig.formItems\r\n ? (h: any, { registerRef }: any) => {\r\n /**\r\n * Vue 2 createElement 签名:\r\n * h(Component, { props, attrs, on, ref }, children)\r\n * 通过 ref 字符串拿到子组件,再通过 registerRef 传递回 EsDialog\r\n *\r\n * 但因为 useDialog 创建的是独立 vm,无法直接用字符串 ref 跨实例。\r\n * 改为:在 mounted 钩子里通过 vnode.componentInstance 取到 EsForm 实例。\r\n */\r\n const vnode = h(EsForm, {\r\n props: {\r\n model: formData,\r\n formItemList: dialogConfig.formItems,\r\n layoutFormProps: {\r\n rowLayProps: { gutter: 16 },\r\n formLayProps: {\r\n isBtnHidden: true,\r\n ...(dialogConfig.formLayout || {}),\r\n },\r\n },\r\n },\r\n // Vue 2 函数式 ref:通过 RenderJsx 暴露的 registerRef 注册\r\n ref: 'dialogForm',\r\n })\r\n\r\n // 等组件挂载后,通过 vnode 取到实例并 register\r\n // 由 RenderJsx 的 onMounted/onUpdated 钩子负责把 componentInstance 写入 currentRef\r\n if (vnode && (vnode as any).data) {\r\n ;(vnode as any).data.hook = (vnode as any).data.hook || {}\r\n ;(vnode as any).data.hook.insert = (insertedVnode: any) => {\r\n if (insertedVnode.componentInstance) {\r\n registerRef('dialogForm', insertedVnode.componentInstance)\r\n }\r\n }\r\n }\r\n return vnode\r\n }\r\n : undefined,\r\n configBtn,\r\n // useDialog 的 onClosed 通过 extractEventHandlers 转为 'closed' 事件\r\n onClosed: () => {\r\n dialogInstances.delete(key)\r\n dialogConfig.onClose?.()\r\n },\r\n })\r\n }\r\n\r\n function closeDialog(key: string) {\r\n const dialog = dialogInstances.get(key)\r\n if (dialog) {\r\n dialog.close()\r\n dialogInstances.delete(key)\r\n }\r\n }\r\n\r\n function resolveDialogBtns(\r\n key: string,\r\n config: CrudDialogConfig,\r\n formData: Record<string, unknown>,\r\n row: Record<string, unknown>\r\n ): unknown[] | undefined {\r\n if (config.isHiddenFooter) return undefined\r\n\r\n if (config.configBtn) {\r\n return config.configBtn.map((btn) => {\r\n if (btn.action === 'cancel') {\r\n return {\r\n ...btn,\r\n click: (_: unknown, { close }: any) => {\r\n emit('dialog-cancel', key)\r\n close()\r\n },\r\n }\r\n }\r\n if (btn.action === 'confirm') {\r\n return {\r\n ...btn,\r\n click: async (_: unknown, { close, getRefs }: any) => {\r\n await validateAndConfirm(key, config, formData, row, close, getRefs)\r\n },\r\n }\r\n }\r\n return btn\r\n })\r\n }\r\n\r\n return [\r\n {\r\n name: '取消',\r\n click: (_: unknown, { close }: any) => {\r\n emit('dialog-cancel', key)\r\n close()\r\n },\r\n },\r\n {\r\n name: '确定',\r\n type: 'primary',\r\n click: async (_: unknown, { close, getRefs }: any) => {\r\n await validateAndConfirm(key, config, formData, row, close, getRefs)\r\n },\r\n },\r\n ]\r\n }\r\n\r\n async function validateAndConfirm(\r\n key: string,\r\n config: CrudDialogConfig,\r\n formData: Record<string, unknown>,\r\n row: Record<string, unknown>,\r\n close: () => void,\r\n getRefs: (name?: string) => any\r\n ) {\r\n if (config.formItems?.length) {\r\n const dialogForm = getRefs('dialogForm')\r\n if (dialogForm?.validate) {\r\n await dialogForm.validate()\r\n }\r\n }\r\n\r\n const context: DialogActionContext = { close, refresh, getRefs, row }\r\n\r\n if (config.onConfirm) {\r\n await config.onConfirm(formData, context)\r\n } else {\r\n const legacyKey =\r\n key === 'add' ? 'add-confirm' : key === 'edit' ? 'edit-confirm' : `${key}-confirm`\r\n emit('btn-click', legacyKey, formData)\r\n close()\r\n refresh()\r\n }\r\n\r\n emit('dialog-confirm', key, formData)\r\n }\r\n\r\n // ─── 公共方法 ─────\r\n function refresh() {\r\n ;(tableRef.value as any)?.httpRequestInstance?.()\r\n }\r\n\r\n function getSelectedRows(): Record<string, unknown>[] {\r\n return (tableRef.value as any)?.getSelectionRows?.() || []\r\n }\r\n\r\n const exposed = {\r\n refresh,\r\n getSelectedRows,\r\n tableRef,\r\n formRef,\r\n queryModel,\r\n openDialog,\r\n closeDialog,\r\n }\r\n\r\n if (typeof expose === 'function') {\r\n expose(exposed)\r\n }\r\n\r\n return {\r\n // refs\r\n tableRef,\r\n formRef,\r\n tableData,\r\n queryModel,\r\n paginationState,\r\n // computeds\r\n mergedColumns,\r\n mergedOptions,\r\n mergedFormBtns,\r\n formLayoutProps,\r\n // exposed\r\n ...exposed,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style scoped>\r\n.es-crud-page {\r\n width: 100%;\r\n}\r\n</style>\r\n","/**\r\n * EsCrudPage 组件入口\r\n *\r\n * 使用方式:\r\n * 1. 默认导入:import EsCrudPage from '@es-plus/vue2/es-crud-page'\r\n * 2. install 安装:通过 Vue.use(EsPlus) 全局注册\r\n */\r\n\r\nimport EsCrudPage from './es-crud-page.vue'\r\nimport type { Vue } from '../../vue-compat'\r\n\r\n;(EsCrudPage as unknown as { install: (V: typeof Vue) => void }).install = function (Vue) {\r\n Vue.component(\r\n (EsCrudPage as unknown as { name: string }).name || 'EsCrudPage',\r\n EsCrudPage\r\n )\r\n}\r\n\r\nexport default EsCrudPage\r\nexport { EsCrudPage }\r\nexport type {\r\n CrudPageSchema,\r\n CrudBtnConfig,\r\n TableBtnConfig,\r\n OperationColumnConfig,\r\n RowBtnConfig,\r\n RowBtnContext,\r\n CrudDialogConfig,\r\n DialogRenderContext,\r\n DialogBtnConfig,\r\n DialogActionContext,\r\n CrudAction,\r\n} from './types'\r\n","/**\r\n * @es-plus/vue2 主入口\r\n *\r\n * 与 Vue 3 版本(packages/es-plus)的关键差异:\r\n * 1. install 签名为 (Vue: typeof Vue, options) 而非 (app: App, options)\r\n * 2. 全局组件注册:Vue.component(name, comp) 而非 app.component(name, comp)\r\n * 3. 全局属性注入:Vue.prototype.$xxx 而非 app.config.globalProperties\r\n * 4. 跨组件依赖注入:通过 Vue.mixin 全局 provide,而非 app.provide\r\n *\r\n * 用户使用方式(在 main.js / main.ts 中):\r\n *\r\n * ┌─ Vue 2.7+ ───────────────────────────────────┐\r\n * │ import Vue from 'vue' │\r\n * │ import ElementUI from 'element-ui' │\r\n * │ import 'element-ui/lib/theme-chalk/index.css' │\r\n * │ import EsPlus from '@es-plus/vue2' │\r\n * │ │\r\n * │ Vue.use(ElementUI) │\r\n * │ Vue.use(EsPlus, { permission: (v) => true }) │\r\n * └────────────────────────────────────────────────┘\r\n *\r\n * ┌─ Vue 2.6 ─────────────────────────────────────┐\r\n * │ import Vue from 'vue' │\r\n * │ import VueCompositionAPI from '@vue/composition-api' │\r\n * │ import ElementUI from 'element-ui' │\r\n * │ import EsPlus from '@es-plus/vue2' │\r\n * │ │\r\n * │ Vue.use(VueCompositionAPI) │\r\n * │ Vue.use(ElementUI) │\r\n * │ Vue.use(EsPlus) │\r\n * └────────────────────────────────────────────────┘\r\n *\r\n * 配置示例:\r\n * Vue.use(EsPlus, {\r\n * permission: (value) => userPermissions.includes(value),\r\n * componentSize: 'small',\r\n * skipComponentRegistration: false, // true 时跳过组件全局注册(按需导入场景)\r\n * globalProperties: true, // false 时跳过 Vue.prototype.$useDialog 注入\r\n * })\r\n */\r\n\r\nimport { configureEsPlus } from '@es-plus/core'\r\nimport type { Vue as VueType } from './vue-compat'\r\n\r\nimport EsForm from './components/es-form'\r\nimport EsTable from './components/es-table'\r\nimport EsDialog, { useDialog } from './components/es-dialog'\r\nimport EsCrudPage from './components/es-crud-page'\r\n\r\n// 组件清单(用于全局注册)\r\nconst components = [EsForm, EsTable, EsDialog, EsCrudPage]\r\n\r\ninterface InstallOptions extends Record<string, unknown> {\r\n /** 是否跳过组件的全局注册(按需导入场景下置为 true) */\r\n skipComponentRegistration?: boolean\r\n /** 是否跳过 Vue.prototype 上的全局属性注入(默认 true 注入) */\r\n globalProperties?: boolean\r\n}\r\n\r\n/**\r\n * Vue 2 插件安装函数\r\n *\r\n * 与 Vue 3 版本的安装逻辑保持语义一致:\r\n * - 写入模块级单例(configureEsPlus),让 composable 内部能读到全局配置\r\n * - 全局注册组件(除非 skipComponentRegistration: true)\r\n * - 注入全局属性(Vue.prototype.$useDialog)\r\n * - 通过 Vue.mixin 实现 provide('$EsPlus') 全局可注入\r\n */\r\n/**\r\n * 兼容垫片:把旧 es-eui 的 options 形状归一化为 @es-plus/vue2 期望的扁平形状\r\n *\r\n * 旧 es-eui 形状:\r\n * { EsTable: { methods: { $httpRequest, paginationLayout, configQueryfieldOutput } },\r\n * EsForm: { methods: { $httpRequest, fieldFieldOutput } } }\r\n *\r\n * @es-plus/vue2 形状:\r\n * { EsTable: { $httpRequest, paginationLayout, configQueryFieldOutput },\r\n * EsForm: { $httpRequest, fieldFieldOutput } }\r\n *\r\n * 差异处理:\r\n * 1. 把 .methods 子对象展平到上一层\r\n * 2. 把 configQueryfieldOutput(小写 f)改名为 configQueryFieldOutput(大写 F)\r\n *\r\n * 这样原 es-eui 的 main.js 中 `Vue.use(esEui, { EsTable: { methods: { ... } } })`\r\n * 配置可以一字不改地切换到 `Vue.use(EsPlus, { ... })`。\r\n */\r\nconst normalizeLegacyOptions = (options: InstallOptions): InstallOptions => {\r\n const out: Record<string, unknown> = { ...options }\r\n for (const key of ['EsTable', 'EsForm', 'EsDialog']) {\r\n const sub = out[key] as Record<string, unknown> | undefined\r\n if (!sub || typeof sub !== 'object') continue\r\n const methods = (sub as Record<string, unknown>).methods as\r\n | Record<string, unknown>\r\n | undefined\r\n if (methods && typeof methods === 'object') {\r\n // 展平 methods 到 sub 上(不覆盖已有同名键)\r\n const { methods: _drop, ...rest } = sub as Record<string, unknown>\r\n out[key] = { ...methods, ...rest }\r\n }\r\n // 重命名 configQueryfieldOutput → configQueryFieldOutput\r\n const flat = out[key] as Record<string, unknown>\r\n if (\r\n typeof flat.configQueryfieldOutput === 'function' &&\r\n typeof flat.configQueryFieldOutput !== 'function'\r\n ) {\r\n flat.configQueryFieldOutput = flat.configQueryfieldOutput\r\n }\r\n }\r\n return out as InstallOptions\r\n}\r\n\r\nconst install = (Vue: typeof VueType, options: InstallOptions = {}) => {\r\n // 兼容旧 es-eui options 形状(methods 嵌套 + 字段名差异)\r\n const normalized = normalizeLegacyOptions(options)\r\n\r\n // 写入全局配置单例(permission / 默认 size 等)\r\n configureEsPlus(normalized as any)\r\n\r\n // 全局注册所有组件\r\n if (!normalized.skipComponentRegistration) {\r\n components.forEach((component) => {\r\n const compName = (component as unknown as { name?: string }).name\r\n if (compName) {\r\n Vue.component(compName, component as any)\r\n }\r\n })\r\n }\r\n\r\n if (normalized.globalProperties !== false) {\r\n // 编程式弹窗挂到 Vue.prototype 上,方便 Options API 通过 this.$useDialog() 调用\r\n ;(Vue as unknown as { prototype: Record<string, unknown> }).prototype.$useDialog = useDialog\r\n }\r\n\r\n /**\r\n * Vue 2 没有 app.provide(),但可以通过 Vue.mixin 在每个组件实例上注入 provide:\r\n * Vue.mixin({ provide: { $EsPlus: { ... } } })\r\n *\r\n * 注意:此处的 provide 在 Vue 2 中是函数还是对象都可以。\r\n * 内部组件通过 inject('$EsPlus') 即可拿到(与 Vue 3 版本 API 完全一致)。\r\n */\r\n Vue.mixin({\r\n provide: {\r\n $EsPlus: {\r\n useDialog,\r\n ...normalized,\r\n },\r\n },\r\n })\r\n}\r\n\r\n// ─── 命名导出 ───\r\nexport {\r\n EsForm,\r\n EsTable,\r\n EsDialog,\r\n EsCrudPage,\r\n useDialog,\r\n configureEsPlus,\r\n install,\r\n}\r\n\r\n// ─── 类型导出(与 Vue 3 版本保持完全一致的类型契约) ───\r\nexport type {\r\n CrudPageSchema,\r\n CrudAction,\r\n CrudBtnConfig,\r\n TableBtnConfig,\r\n OperationColumnConfig,\r\n RowBtnConfig,\r\n RowBtnContext,\r\n CrudDialogConfig,\r\n DialogRenderContext,\r\n DialogBtnConfig,\r\n DialogActionContext,\r\n} from './components/es-crud-page'\r\n\r\nexport type {\r\n ModelData,\r\n RenderFn,\r\n AnyVNode,\r\n EsButtonType,\r\n EsButtonSize,\r\n EsTableSize,\r\n ApiParams,\r\n FormType,\r\n FormItemOption,\r\n BtnConfig,\r\n LayoutFormProps,\r\n TableColumn,\r\n ConfigTableOut,\r\n TableOptions,\r\n PaginationConfig,\r\n DialogOptions,\r\n EsFormInstance,\r\n EsTableInstance,\r\n EsPlusOptions,\r\n} from './types'\r\n\r\n// ─── 默认导出(带 install 的对象,可直接 Vue.use()) ───\r\n// NOTE: keep `version` in sync with package.json — __tests__/exports.spec.ts\r\n// asserts equality so a drift fails CI.\r\nexport default {\r\n version: '1.0.0',\r\n install,\r\n}\r\n"],"names":["resolveDataOptions","dataOptions","result","resolveAttrs","row","attrs","buildEventHandlers","defaultInputHandler","userOn","handlers","key","handler","useFormInputs","item","formPutList","h","model","value","getNestedValue","val","setNestedValue","opt","idx","prop","userProps","fileList","isCustomUpload","triggerRender","fileRender","triggerVnode","processSuccess","response","file","list","url","_a","_b","processError","err","httpRequestProp","options","customRequest","res","resp","eventToProp","uploadCallbackProps","propName","newList","f","formtype","direct","flipped","flippedHit","lower","useFormLayout","props","folded","ref","isBtnHidden","computed","fromLay","resolveFormLayProps","legacy","fixed","rowLayout","formLayout","getSetOptionsStatus","getRowColsAlgorithm","coreGetRowColsAlgorithm","getMinFoldRow","camel","isFold","minFoldRow","getBtnColSpan","rowNum","columnRow","lastColumn","btnColSpan","hasSpan","sum","formItem","columnNodeIndex","lastFoldIndex","it","index","watch","useFormRequest","httpRequestGlobal","params","coreQueryTableListMethod","rowsList","fieldFieldOutput","coreGetEveryFormQueryField","keyList","coreFormatConfigOut","coreConfigFormField","SIZE_MAP","mapSize","size","RenderDomForm","defineComponent","createElement","ctx","render","renderContent","RenderBtn","formItemList","formModel","_sfc_main$6","instance","getCurrentInstance","templateRefs","proxy","resolvedModel","rawJsxModel","$esPlusForm","inject","getGlobalConfig","esPlus","_d","_c","checkPermission","pvalue","fn","translateLabel","injectedTableInstant","getTableInstant","isParentTable","t","getCompIcon","filterOptions","_icon","mapped","resolveDisabled","d","formInstance","formItemRowsList","formInputComponents","fieldFieldOutputGlobal","getEveryFormQueryField","formLayoutRef","formProps","merged","loadedApiProps","needLoadList","existing","old","rows","fromApi","r","formItemListFilter","visible","legacyHide","fixedHide","hideFn","autoCount","autoSpan","fixedTotal","remaining","layoutResult","changeFolded","colRightLeftList","isRenderBtn","handleBtnClick","formRef","httpFn","queryTableRequest","clickBtn","initFormItemOptions","opts","style","rest","getFormRef","validate","resolve","maybePromise","valid","e","resetFields","clearValidate","p","validateField","formItmeRequestInstance","propsList","targetItems","apiOption","itemIndex","nextTick","bodyFormFn","EsForm","Vue","RenderDomTb","dataKey","renderResult","error","firstWordUpperCase","str","_sfc_main$5","cols","parts","camelKey","i","RenderDom","_sfc_main$4","hasPermission","_btnList","permFn","processButtonConfig","config","processed","processedBtnLeft","getButtonPosition","processedBtnRight","showContainer","_r","_i","_p","_co","_ih","_n","_s","useTableResize","tableContainerRef","headBarRef","tbBtnRef","paginationRef","tableHeight","observer","isNegative","num","totalContainerNum","headBarHeight","tbBtnHeight","paginationHeight","resizeObservers","element","containerHeight","maxContainer","minTableNum","tabContainer","_e","newHeight","startObserver","target","stopObserver","onMounted","onBeforeUnmount","useTableSelection","rowkey","state","createSelectionState","multipleSelection","selectionsByPage","isInitChange","sync","currentPage","applySelectionChange","tableRef","coreClearAll","dataList","restoreSelectionForPage","defaultOptions","TABLE_INTERNAL_KEYS","char","columnBindAttr","newkey","j","checkQueryFields","obj","checkListKey","isObject","its","_sfc_main$3","ColumnItem","TableBtns","emit","slots","expose","$esPlusTable","tableId","tableData","columnRowList","loadingStatus","slotState","showPagination","setTableContainer","el","bodyFormInstance","getVisibleShow","visibleShow","paginationConfig","getListEntry","eq","configTableField","configFields","isFormInstance","formChild","child","hasDefaultSlot","vnodes","heightType","tabHeight","containerStyle","slotStyles","paginationLayoutConfig","cfg","layout","paginationPageSizes","paginationIsSmall","paginationBackground","paginationStyle","loadStatus","isRequestConf","filteredColumns","_h","btn","col","flexIdx","tableAttrs","_align","tableBindAttrs","handleSelectionChange","initSelection","clearAllSelectionInternal","handleTableSelectionChange","oldVal","httpRequestInstance","getListenToCallBack","eventName","cb","getCallback","formatConfigOut","cf","rowData","findValueByKey","queryTableListMethod","success","fail","apiParams","formObj","formData","fnParams","finalParams","requestOption","requestHandler","requestFn","responseData","reject","changePageIndexRequest","changePageSizeRequest","handleSizeChange","handleIndexChange","changeTableSort","column","provide","exposed","_row","EsTable","_sfc_main$2","refsObject","reactive","componentVNode","flushRef","inst","onUpdated","enhancedInstance","name","renderFn","_sfc_main$1","RenderJsx","lyFormInstance","renderBodyRefsObject","isFullscreen","dialogInstance","_k","getDisabled","closeFullscreen","handleFullscreen","dialogVisible","handleClose","onDialogClose","onDialogClosed","beforeCloseHandler","done","filteredAttrs","initDialogCls","getMaxContentHeight","viewH","initDialogHeight","getCurrentInstanceModel","click","dialogComponents","getAppendToElement","appendTo","extractEventHandlers","events","propsData","normalized","initInstance","Component","Ctor","vm","useDialog","EsDialog","lastVm","close","DialogComponent","dialogOptions","originalOnClosed","originalOnSubmit","args","closeFn","destroy","mergedOptions","_sfc_main","queryModel","items","paginationState","normalizedDialogs","dialogBase","actions","normalizedToolbarBtns","btns","normalizedOperationColumn","c","a","mergedFormBtns","baseBtns","toolbarBtns","resolvedBtn","handleToolbarBtnClick","mergedColumns","opCol","actionBtns","handleRowBtnClick","normalizedTableBtns","base","tBtns","formLayoutProps","msg","MessageBox","openDialog","refresh","getSelectedRows","dialogInstances","dialogConfig","dialog","title","configBtn","resolveDialogBtns","closeDialog","registerRef","vnode","insertedVnode","_","getRefs","validateAndConfirm","dialogForm","context","legacyKey","EsCrudPage","components","normalizeLegacyOptions","out","sub","methods","_drop","flat","install","configureEsPlus","component","compName"],"mappings":"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"}
1
+ {"version":3,"file":"es-plus-vue2.js","sources":["../src/composables/use-form-inputs.ts","../src/composables/use-form-layout.ts","../src/composables/use-form-request.ts","../src/utils/size.ts","../src/components/es-form/es-form.vue","../src/components/es-form/index.ts","../src/components/es-table/column-item.vue","../src/utils/icon.ts","../src/components/es-table/table-btns.vue","../src/composables/use-table-resize.ts","../src/composables/use-table-selection.ts","../src/components/es-table/component.vue","../src/components/es-table/index.ts","../src/components/es-dialog/render-jsx.vue","../src/components/es-dialog/component.vue","../src/components/es-dialog/use-dialog.ts","../src/components/es-dialog/index.ts","../src/components/es-crud-page/es-crud-page.vue","../src/components/es-crud-page/index.ts","../src/index.ts"],"sourcesContent":["/**\r\n * Vue 2 + Element UI 表单输入适配器\r\n *\r\n * 与 Vue 3 + Element Plus 版本(packages/vue3/src/composables/use-form-inputs.ts)的核心差异:\r\n *\r\n * 1. h() 签名:\r\n * - Vue 3:h(Comp, { modelValue, 'onUpdate:modelValue': fn, ...props })\r\n * - Vue 2:h(Comp, { props: { value, ... }, on: { input, ... }, attrs: {...} })\r\n *\r\n * 2. v-model 实现:\r\n * - Vue 3 默认 v-model 等价于 :modelValue + @update:modelValue\r\n * - Vue 2 默认 v-model 等价于 :value + @input(原生输入框是 :value + @input;\r\n * el-* 控件大多遵循该规范,少数有特殊 model 配置如 el-checkbox 用 checked/change)\r\n *\r\n * 3. 组件名:el-input / el-select / el-date-picker ...(kebab-case 字符串注册)\r\n * - Element UI 通过 Vue.use(ElementUI) 全局注册了所有组件,可直接用字符串引用\r\n *\r\n * 4. 图标系统:Element UI 用 class(el-icon-xxx),不再使用图标组件\r\n *\r\n * 5. 嵌套属性 path:复用核心层的 getNestedValue / setNestedValue(Vue 2 中 setNestedValue\r\n * 需要配合 Vue.set 才能触发响应式 —— 由 EsForm 组件的 currentModel 经 reactive 包装解决)\r\n *\r\n * 用户保持一致的写法:\r\n * {\r\n * formtype: 'Input',\r\n * prop: 'name',\r\n * label: '姓名',\r\n * attrs: { placeholder: '请输入', clearable: true },\r\n * on: { input: (val) => console.log(val) }\r\n * }\r\n *\r\n * 这样无论是 Vue 2 还是 Vue 3 项目,配置 schema 完全一致 —— 只有内部渲染层做差异化处理。\r\n */\r\n\r\nimport { getNestedValue, setNestedValue } from '@es-plus/core'\r\nimport type { FormItemOption, ModelData } from '@es-plus/core'\r\n\r\n/**\r\n * Vue 2 createElement 函数类型\r\n * 来自 Vue 实例的 $createElement 或 render 函数的第一参数\r\n */\r\nexport type CreateElement = (tag: string | object, dataOrChildren?: unknown, children?: unknown) => unknown\r\n\r\n/**\r\n * 表单输入渲染函数签名\r\n * - h:createElement 函数(Vue 2)\r\n * - model:当前 model 数据(响应式对象,需通过 setNestedValue 写入以触发响应式)\r\n * - ctx:包含 row(当前 FormItemOption)的上下文\r\n */\r\nexport type FormInputRenderer = (\r\n h: CreateElement,\r\n model: ModelData,\r\n ctx: { row: FormItemOption; index?: number }\r\n) => unknown\r\n\r\n/**\r\n * 解析 dataOptions:支持 Array 或 () => Array 两种形式\r\n */\r\nfunction resolveDataOptions(dataOptions: FormItemOption['dataOptions'] | (() => unknown[])): Array<{\r\n label: string\r\n value: unknown\r\n disabled?: boolean\r\n children?: unknown[]\r\n}> {\r\n if (Array.isArray(dataOptions)) return dataOptions\r\n if (typeof dataOptions === 'function') {\r\n const result = (dataOptions as () => unknown)()\r\n return Array.isArray(result) ? (result as Array<{ label: string; value: unknown }>) : []\r\n }\r\n return []\r\n}\r\n\r\n/**\r\n * 解析 attrs,特别处理 disabled 函数形式(与 es-eui 保持一致)\r\n */\r\nfunction resolveAttrs(row: FormItemOption): Record<string, unknown> {\r\n const attrs: Record<string, unknown> = { ...(row.attrs || {}) }\r\n if (typeof attrs.disabled === 'function') {\r\n attrs.disabled = (attrs.disabled as () => boolean)()\r\n }\r\n return attrs\r\n}\r\n\r\n/**\r\n * 构造统一的事件监听器对象:\r\n * - 默认 input 事件用于 v-model 同步(写回 model)\r\n * - 用户配置的 input 优先(可拦截/转换值)\r\n * - 其它事件(focus/blur/change...)原样透传\r\n */\r\nfunction buildEventHandlers(\r\n row: FormItemOption,\r\n defaultInputHandler: (val: unknown) => void\r\n): Record<string, unknown> {\r\n const userOn = (row.on || {}) as Record<string, unknown>\r\n const handlers: Record<string, unknown> = {}\r\n\r\n for (const [key, handler] of Object.entries(userOn)) {\r\n if (typeof handler === 'function') {\r\n handlers[key] = handler\r\n }\r\n }\r\n\r\n // 用户没显式配置 input 时,绑定默认写回逻辑\r\n if (typeof handlers.input !== 'function') {\r\n handlers.input = defaultInputHandler\r\n }\r\n\r\n return handlers\r\n}\r\n\r\n/**\r\n * 创建一个表单输入渲染器映射\r\n *\r\n * 与 Vue 3 版本通过 useFormInputs() composable 调用一致;\r\n * Vue 2 中也提供同名函数以保证 API 一致性,方便未来共享代码。\r\n */\r\nexport function useFormInputs() {\r\n const formInputComponents = (item: FormItemOption): FormInputRenderer => {\r\n const formPutList = new Map<string, FormInputRenderer>([\r\n // ─────────────────────────────────────────────────────────────────\r\n // Input - 文本输入\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Input',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-input', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // InputNumber - 数字输入(保留兼容 es-eui 的扩展类型)\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'InputNumber',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-input-number', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Select - 下拉选择\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Select',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const dataOptions = resolveDataOptions(row.dataOptions as never)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h(\r\n 'el-select',\r\n {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n },\r\n dataOptions.map((opt, idx) =>\r\n h('el-option', {\r\n key: idx,\r\n props: { value: opt.value, label: opt.label, disabled: opt.disabled },\r\n })\r\n )\r\n )\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // datePicker - 日期选择(注意 Vue 3 用大写 DatePicker,Vue 2 用 datePicker;\r\n // 这里 Map key 跟 Vue 3 版本对齐,使用 'datePicker')\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'datePicker',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-date-picker', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // timePicker - 时间选择\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'timePicker',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-time-picker', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Slider - 滑块\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Slider',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-slider', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // ColorPicker - 颜色选择\r\n // Element UI 的 el-color-picker 使用 v-model 默认 prop 为 'value',事件 'change'/'active-change'\r\n // 但同时支持 input 事件透传,这里保持 input 用作默认写回\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'ColorPicker',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n // ColorPicker 没有 input 事件,使用 change 作为默认写回\r\n const userOn = (row.on || {}) as Record<string, unknown>\r\n const handlers: Record<string, unknown> = {}\r\n for (const [key, handler] of Object.entries(userOn)) {\r\n if (typeof handler === 'function') handlers[key] = handler\r\n }\r\n if (typeof handlers.change !== 'function') {\r\n handlers.change = (val: unknown) => setNestedValue(model, row.prop, val)\r\n }\r\n return h('el-color-picker', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Transfer - 穿梭框\r\n // Element UI 中 el-transfer 默认 v-model 为 :value + @input,data 通过 props 传入\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Transfer',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const dataOptions = resolveDataOptions(row.dataOptions as never)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-transfer', {\r\n attrs,\r\n props: {\r\n value,\r\n data: dataOptions.map((opt) => ({ key: opt.value, label: opt.label, disabled: opt.disabled })),\r\n ...row.props,\r\n },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Cascader - 级联选择\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Cascader',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const dataOptions = resolveDataOptions(row.dataOptions as never)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-cascader', {\r\n // key 强制 dataOptions 变化时重渲染,Element UI 内部 cache 否则不刷新\r\n key: JSON.stringify(dataOptions),\r\n attrs,\r\n props: {\r\n value,\r\n options: dataOptions,\r\n ...row.props,\r\n },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Radio - 单选组\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Radio',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const dataOptions = resolveDataOptions(row.dataOptions as never)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h(\r\n 'el-radio-group',\r\n {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n },\r\n dataOptions.map((opt, idx) =>\r\n h(\r\n 'el-radio',\r\n {\r\n key: idx,\r\n // Element UI 中 el-radio 使用 :label 作为值\r\n props: { label: opt.value, disabled: opt.disabled || (attrs.disabled as boolean) },\r\n },\r\n [opt.label]\r\n )\r\n )\r\n )\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Checkbox - 复选组\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Checkbox',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const dataOptions = resolveDataOptions(row.dataOptions as never)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h(\r\n 'el-checkbox-group',\r\n {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n },\r\n dataOptions.map((opt, idx) =>\r\n h(\r\n 'el-checkbox',\r\n {\r\n key: idx,\r\n props: { label: opt.value, disabled: opt.disabled || (attrs.disabled as boolean) },\r\n },\r\n [opt.label]\r\n )\r\n )\r\n )\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Switch - 开关\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Switch',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n // Element UI 的 el-switch 默认 v-model 用 :value + @input\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-switch', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Rate - 评分\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Rate',\r\n (h, model, { row }) => {\r\n const attrs = resolveAttrs(row)\r\n const value = getNestedValue(model, row.prop)\r\n const handlers = buildEventHandlers(row, (val) => setNestedValue(model, row.prop, val))\r\n return h('el-rate', {\r\n attrs,\r\n props: { value, ...row.props },\r\n on: handlers,\r\n })\r\n },\r\n ],\r\n\r\n // ─────────────────────────────────────────────────────────────────\r\n // Upload - 上传(最复杂的一个,需处理 fileList、httpRequest、自定义 trigger 等)\r\n // ─────────────────────────────────────────────────────────────────\r\n [\r\n 'Upload',\r\n (h, model, { row }) => {\r\n const prop = row.prop\r\n const attrs = resolveAttrs(row)\r\n const userProps = (row.props || {}) as Record<string, unknown>\r\n const userOn = (row.on || {}) as Record<string, unknown>\r\n const fileList = (getNestedValue(model, prop) as unknown[]) || []\r\n\r\n const isCustomUpload = typeof row.httpRequest === 'function'\r\n\r\n // 用户配置 trigger 渲染(picture-card 模式 / 普通模式 都用 default slot 占位)\r\n const triggerRender = (row as FormItemOption & {\r\n triggerRender?: (h: CreateElement) => unknown\r\n }).triggerRender\r\n const fileRender = (row as FormItemOption & {\r\n fileRender?: (h: CreateElement, file: unknown, onRemove: () => void) => unknown\r\n }).fileRender\r\n\r\n // 默认 trigger 按钮(size 与 EsForm 默认 mini 对齐,避免视觉割裂)\r\n const triggerVnode = triggerRender\r\n ? triggerRender(h)\r\n : h('el-button', { props: { size: 'mini', type: 'primary' } }, ['选择文件'])\r\n\r\n // ── 上传成功处理(与 es-eui 保持一致的字段抽取规则) ──\r\n const processSuccess = (response: Record<string, unknown> | undefined, file: Record<string, unknown>, list: unknown[]) => {\r\n const url =\r\n (response?.link as string) ||\r\n (response?.url as string) ||\r\n ((response?.data as Record<string, unknown> | undefined)?.link as string) ||\r\n ((response?.data as Record<string, unknown> | undefined)?.url as string)\r\n\r\n if (url) file.url = url\r\n file.status = 'success'\r\n file.response = response\r\n\r\n if (typeof userOn.success === 'function') {\r\n ;(userOn.success as (...a: unknown[]) => void)(response, file, list)\r\n }\r\n // 触发响应式更新(替换为新数组引用以让 Vue 2 检测变化)\r\n setNestedValue(model, prop, [...list])\r\n }\r\n\r\n const processError = (err: unknown, file: Record<string, unknown>, list: unknown[]) => {\r\n file.status = 'fail'\r\n file.error = err\r\n if (typeof userOn.error === 'function') {\r\n ;(userOn.error as (...a: unknown[]) => void)(err, file, list)\r\n }\r\n setNestedValue(model, prop, [...list])\r\n }\r\n\r\n // ── 自定义 httpRequest 包装:el-upload 的 http-request 接收 { file, onSuccess, onError, onProgress } ──\r\n const httpRequestProp = isCustomUpload\r\n ? (options: { file: File; onSuccess: (res: unknown) => void; onError: (err: unknown) => void; onProgress?: (e: { percent: number }) => void }) => {\r\n const customRequest = row.httpRequest as (params: Record<string, unknown>) => Promise<unknown>\r\n customRequest({\r\n file: options.file,\r\n filename: options.file.name,\r\n onProgress: options.onProgress,\r\n })\r\n .then((res) => {\r\n const resp = (res as Record<string, unknown>)?.data || res\r\n options.onSuccess(resp)\r\n })\r\n .catch((err) => options.onError(err))\r\n }\r\n : undefined\r\n\r\n /**\r\n * Element UI 的 <el-upload> 把所有上传生命周期回调都暴露为 Function 类型 prop\r\n * (onPreview / onSuccess / onChange / onRemove / onError / onProgress / onExceed),\r\n * 而非通过 $emit 派发事件 —— 因此用户写 `on: { preview }` 在 Vue 2 render 函数里\r\n * 等价于 `v-on:preview`,永远不会触发(el-upload 不会 $emit('preview'))。\r\n *\r\n * 关键点:onPreview 在 Element UI 中**没有 noop 默认值**,\r\n * 当 prop 缺失时 upload-list 的 `v-if=\"handlePreview\"` 为 false,\r\n * picture-card 模式下的\"预览(放大镜)\"图标会被隐藏 —— 这就是用户报的 bug。\r\n *\r\n * 修复:把 row.on 中的回调按 camelCase 转为 prop(key → onKey)。\r\n */\r\n const eventToProp: Record<string, string> = {\r\n preview: 'onPreview',\r\n change: 'onChange',\r\n success: 'onSuccess',\r\n error: 'onError',\r\n progress: 'onProgress',\r\n remove: 'onRemove',\r\n exceed: 'onExceed',\r\n }\r\n const uploadCallbackProps: Record<string, unknown> = {}\r\n for (const [key, handler] of Object.entries(userOn)) {\r\n if (typeof handler !== 'function') continue\r\n // success / error / remove 由我们包装后再写入,跳过原始用户函数\r\n if (key === 'success' || key === 'error' || key === 'remove') continue\r\n const propName = eventToProp[key]\r\n if (propName) uploadCallbackProps[propName] = handler\r\n }\r\n // 始终接管 success / error / remove —— 既调用用户回调,也同步 fileList 到 model\r\n uploadCallbackProps.onSuccess = processSuccess\r\n uploadCallbackProps.onError = processError\r\n uploadCallbackProps.onRemove = (file: Record<string, unknown>, list: unknown[]) => {\r\n if (typeof userOn.remove === 'function') {\r\n ;(userOn.remove as (...a: unknown[]) => void)(file, list)\r\n }\r\n setNestedValue(model, prop, [...list])\r\n }\r\n\r\n // 主体\r\n return h(\r\n 'el-upload',\r\n {\r\n attrs: {\r\n ...attrs,\r\n action: (userProps.action as string) || (attrs.action as string) || '#',\r\n 'file-list': fileList,\r\n },\r\n props: {\r\n ...userProps,\r\n fileList,\r\n // 自定义上传时禁用 auto-upload,由 httpRequest 接管\r\n autoUpload: isCustomUpload ? false : (userProps.autoUpload !== false),\r\n httpRequest: httpRequestProp,\r\n // 把 row.on.* 转换为 onXxx prop(覆盖在 userProps 之上:\r\n // 若用户已直接在 props 里给了 onPreview,这里仍以 row.on 为优先权来源)\r\n ...uploadCallbackProps,\r\n },\r\n // Vue 2 的 scopedSlots 用于自定义文件项渲染\r\n scopedSlots: fileRender\r\n ? {\r\n file: ({ file }: { file: Record<string, unknown> }) =>\r\n fileRender(h, file, () => {\r\n const newList = fileList.filter((f) => f !== file)\r\n setNestedValue(model, prop, newList)\r\n }),\r\n }\r\n : undefined,\r\n },\r\n [triggerVnode]\r\n )\r\n },\r\n ],\r\n ])\r\n\r\n /**\r\n * formtype 大小写兼容查找:\r\n * - Vue 3 版本约定 `datePicker` / `timePicker` 用 camelCase,其它用 PascalCase\r\n * - 原 es-eui 历史上一律使用 PascalCase(`DatePicker` / `TimePicker`)\r\n * 为了让旧 es-eui 案例无修改即可使用 @es-plus/vue2,这里做大小写兼容:\r\n * 1) 精确匹配(保持 Vue 3 习惯)\r\n * 2) 首字母翻转再试一次(覆盖 'DatePicker' ↔ 'datePicker' 这类差异)\r\n * 3) 全表 case-insensitive 兜底\r\n * 都未命中则返回空渲染器。\r\n */\r\n const formtype = (item.formtype ?? '') as string\r\n if (!formtype) return (): unknown => null\r\n\r\n const direct = formPutList.get(formtype)\r\n if (direct) return direct\r\n\r\n const flipped = formtype[0]\r\n ? (formtype[0] === formtype[0].toLowerCase()\r\n ? formtype[0].toUpperCase() + formtype.slice(1)\r\n : formtype[0].toLowerCase() + formtype.slice(1))\r\n : formtype\r\n const flippedHit = formPutList.get(flipped)\r\n if (flippedHit) return flippedHit\r\n\r\n const lower = formtype.toLowerCase()\r\n for (const [key, val] of formPutList) {\r\n if (key.toLowerCase() === lower) return val\r\n }\r\n return (): unknown => null\r\n }\r\n\r\n return { formInputComponents }\r\n}\r\n","/**\r\n * EsForm 布局 composable —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - 仅 import 路径不同:从 'vue' 替换为 './vue-compat',从本地 utils 替换为 '@es-plus/core'\r\n * - 24 栅格行列分组算法 100% 复用 @es-plus/core 提供的 getRowColsAlgorithm\r\n *\r\n * 该 composable 不依赖任何 Element UI 组件,是纯逻辑层。\r\n */\r\n\r\nimport { computed, ref, watch } from '../vue-compat'\r\nimport {\r\n getRowColsAlgorithm as coreGetRowColsAlgorithm,\r\n resolveFormLayProps,\r\n type FormLayoutResult,\r\n} from '@es-plus/core'\r\nimport type { FormItemOption, LayoutFormProps } from '@es-plus/core'\r\n\r\nexport interface UseFormLayoutProps {\r\n layoutFormProps?: LayoutFormProps\r\n /** 注意:调用方需保证此处是响应式来源(或用 getter 形式:`get formItemList() { ... }`) */\r\n formItemList: FormItemOption[]\r\n}\r\n\r\nexport function useFormLayout(props: UseFormLayoutProps) {\r\n const folded = ref(false)\r\n\r\n /**\r\n * 隐藏按钮区字段名兼容:原 es-eui 使用 `isBtnHiden`(少一个 d,原始拼写错误),\r\n * 后续 schema/类型规范化为 `isBtnHidden`。两者都接受,原始拼写优先。\r\n */\r\n const isBtnHidden = computed(() => {\r\n const fromLay = resolveFormLayProps(props.layoutFormProps) as Record<string, unknown> | undefined\r\n if (!fromLay || !Object.keys(fromLay).length) return false\r\n const legacy = fromLay.isBtnHiden\r\n const fixed = fromLay.isBtnHidden\r\n return Boolean(legacy ?? fixed ?? false)\r\n })\r\n /**\r\n * el-row 布局参数。\r\n *\r\n * 注意:Element UI v2 的 `el-row` 默认是 **浮动布局**(float-based),\r\n * 而 Element Plus 的 `el-row` 默认是 **flex 布局**。\r\n *\r\n * 浮动布局的问题:当不同 el-col 的高度不一致时(比如 Checkbox 组在窄屏下换成两行、\r\n * DatePicker 高度比 Switch 略高),后面的 el-col 会卡进高的列下方留白处,\r\n * 而不是干净地换行 —— 表现为「布局错乱」。\r\n *\r\n * 修复策略:默认使用 `type=\"flex\"`,并通过 SFC 样式给 `.es-form .el-row--flex`\r\n * 加上 `flex-wrap: wrap`,让换行行为与 Element Plus 一致。用户若显式传入\r\n * `rowLayProps: { type: '' }` 仍可回退为浮动布局。\r\n */\r\n const rowLayout = computed(() => {\r\n const userProps = (props.layoutFormProps?.rowLayProps as Record<string, unknown>) || {}\r\n return {\r\n type: 'flex',\r\n gutter: 20,\r\n ...userProps,\r\n }\r\n })\r\n const formLayout = computed(() => resolveFormLayProps(props.layoutFormProps))\r\n const getSetOptionsStatus = computed(() => props.layoutFormProps?.setOptions)\r\n\r\n const getRowColsAlgorithm = computed<FormLayoutResult>(() =>\r\n coreGetRowColsAlgorithm(props.formItemList || [])\r\n )\r\n\r\n /**\r\n * 折叠行阈值字段名兼容:\r\n * - 原 es-eui 使用小写 `minfoldRows`(fold 全小写)\r\n * - 后续部分文档示例与 EsCrudPage schema 使用驼峰 `minFoldRows`\r\n * 这里两个都接受,原始小写优先(保持旧文档案例不改字面量即可工作)。\r\n */\r\n const getMinFoldRow = (): number => {\r\n const fromLay = resolveFormLayProps(props.layoutFormProps) as Record<string, unknown> | undefined\r\n if (!fromLay || !Object.keys(fromLay).length) return 0\r\n const legacy = fromLay.minfoldRows\r\n const camel = fromLay.minFoldRows\r\n return Number(legacy ?? camel ?? 0) || 0\r\n }\r\n\r\n const isFold = computed(() => {\r\n const minFoldRow = getMinFoldRow()\r\n return minFoldRow > 0 && minFoldRow < getRowColsAlgorithm.value.rowNum\r\n })\r\n\r\n const getBtnColSpan = computed(() => {\r\n const { rowNum, columnRow } = getRowColsAlgorithm.value\r\n const lastColumn = columnRow[rowNum - 1] || []\r\n const btnColSpan = Number((resolveFormLayProps(props.layoutFormProps) as Record<string, unknown>)?.btnColSpan) || 0\r\n const totalSpan = lastColumn.reduce(\r\n (sum: number, idx: number) => sum + (props.formItemList[idx]?.span || 24),\r\n 0\r\n )\r\n const hasSpan = 24 - totalSpan\r\n return !folded.value && btnColSpan <= hasSpan ? hasSpan : 24\r\n })\r\n\r\n const formItem = computed(() => {\r\n const minFoldRow = getMinFoldRow()\r\n const { columnNodeIndex } = getRowColsAlgorithm.value\r\n\r\n if (folded.value) {\r\n const lastFoldIndex =\r\n columnNodeIndex[minFoldRow - 1] ?? columnNodeIndex[columnNodeIndex.length - 1] ?? 9999\r\n return (props.formItemList || []).map((it: FormItemOption, index: number) => ({\r\n ...it,\r\n isFold: index > lastFoldIndex,\r\n }))\r\n }\r\n return (props.formItemList || []).map((it: FormItemOption) => ({ ...it, isFold: false }))\r\n })\r\n\r\n watch(\r\n isFold,\r\n (val: boolean) => {\r\n folded.value = val\r\n },\r\n { immediate: true }\r\n )\r\n\r\n const changeFolded = () => {\r\n folded.value = !folded.value\r\n }\r\n\r\n return {\r\n folded,\r\n isBtnHidden,\r\n rowLayout,\r\n formLayout,\r\n getSetOptionsStatus,\r\n getRowColsAlgorithm,\r\n isFold,\r\n getBtnColSpan,\r\n formItem,\r\n changeFolded,\r\n }\r\n}\r\n","/**\r\n * EsForm 请求 composable —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - nextTick 来源从 'vue' 改为 './vue-compat'\r\n * - toRaw/unref 不再需要:Vue 2 的响应式对象天然是 plain object(仅在 setter 处被 wrapped),\r\n * 而我们在请求时只读取值,无需 unwrap\r\n * - 核心格式化逻辑 100% 复用 @es-plus/core/request\r\n *\r\n * 该 composable 仅做 Vue 包装,所有数据转换都委托给 @es-plus/core。\r\n */\r\n\r\nimport { nextTick } from '../vue-compat'\r\nimport {\r\n queryTableListMethod as coreQueryTableListMethod,\r\n configFormField as coreConfigFormField,\r\n formatConfigOut as coreFormatConfigOut,\r\n httpRequestFormInstance as coreHttpRequestFormInstance,\r\n getEveryFormQueryField as coreGetEveryFormQueryField,\r\n type RequestConfig,\r\n type ConfigFormFieldOut,\r\n} from '@es-plus/core'\r\nimport type { FormItemOption } from '@es-plus/core'\r\n\r\nexport type { RequestConfig, ConfigFormFieldOut }\r\n\r\nexport function useFormRequest(\r\n httpRequestGlobal?: (params: Record<string, unknown>) => Promise<unknown>\r\n) {\r\n const queryTableListMethod = (\r\n params: Record<string, unknown>,\r\n options: RequestConfig = {}\r\n ) => coreQueryTableListMethod(params, options, httpRequestGlobal)\r\n\r\n const configFormField = (\r\n options: Record<string, unknown> = {},\r\n fieldFieldOutput?: (defaults: ConfigFormFieldOut) => ConfigFormFieldOut\r\n ) => coreConfigFormField(options, fieldFieldOutput)\r\n\r\n const formatConfigOut = (\r\n row: Record<string, unknown> | unknown[],\r\n keyList: string[],\r\n options: Record<string, unknown> = {},\r\n fieldFieldOutput?: (defaults: ConfigFormFieldOut) => ConfigFormFieldOut\r\n ) => coreFormatConfigOut(row, keyList, options, fieldFieldOutput)\r\n\r\n const httpRequestFormInstance = (\r\n model: Record<string, unknown>,\r\n options: RequestConfig,\r\n rows: FormItemOption,\r\n fieldFieldOutput?: (defaults: ConfigFormFieldOut) => ConfigFormFieldOut\r\n ) =>\r\n // 与原 es-eui httpRquestFormInstace 一致:data 字段已剥一层 res.data,\r\n // 因此类型是 unknown(可能是数组、对象或 undefined)。\r\n new Promise<{ data: unknown; configRows: Record<string, unknown> }>((resolve, reject) => {\r\n nextTick(() => {\r\n coreHttpRequestFormInstance(model, options, rows, httpRequestGlobal, fieldFieldOutput)\r\n .then(resolve)\r\n .catch(reject)\r\n })\r\n })\r\n\r\n const getEveryFormQueryField = (\r\n rowsList: FormItemOption[],\r\n fieldFieldOutput?: (defaults: ConfigFormFieldOut) => ConfigFormFieldOut\r\n ) => coreGetEveryFormQueryField(rowsList, httpRequestGlobal, fieldFieldOutput)\r\n\r\n return {\r\n queryTableListMethod,\r\n getEveryFormQueryField,\r\n formatConfigOut,\r\n configFormField,\r\n }\r\n}\r\n","/**\r\n * Element UI v2 与 Element Plus 尺寸语义映射\r\n *\r\n * 背景:用户在两套版本之间复用同一份配置(如 size: 'small'),但两个组件库的尺寸系统并不一致:\r\n * Element Plus: large(40px) / default(32px) / small(24px)\r\n * Element UI v2: medium(36px) / small(32px) / mini(28px)\r\n *\r\n * 直接透传会导致同样的字符串渲染出截然不同的物理高度(small 在 EP 是 24px,在 EUI 是 32px),\r\n * 视觉上 Vue 2 版本明显比 Vue 3 版本\"大一圈\"。\r\n *\r\n * 本工具按\"接近视觉高度\"做语义映射:\r\n * large → medium (40 → 36)\r\n * default → small (32 → 32) — 高度本身一致\r\n * small → mini (24 → 28) — EUI 没有更小的,mini 已是最贴近\r\n * mini → mini (透传 — EUI 原生支持)\r\n * medium → medium (透传 — EUI 原生支持)\r\n *\r\n * 这样一来,在 Vue 3 版本里使用 size: 'small' 的紧凑表单,迁到 Vue 2 版本会自动落到 mini,\r\n * 整体视觉密度保持一致。用户若显式希望使用 EUI 原生尺寸(如 medium),原样透传即可。\r\n */\r\n\r\nexport type ElPlusSize = 'large' | 'default' | 'small' | ''\r\nexport type ElUiSize = 'medium' | 'small' | 'mini' | ''\r\n\r\nconst SIZE_MAP: Record<string, ElUiSize> = {\r\n large: 'medium',\r\n default: 'small',\r\n small: 'mini',\r\n // EUI 原生值透传\r\n medium: 'medium',\r\n mini: 'mini',\r\n}\r\n\r\n/**\r\n * 将任意尺寸字符串映射为 Element UI v2 支持的尺寸。\r\n * - 未识别的值返回 undefined,让组件回退到自身默认值\r\n * - 空字符串/空值同样返回 undefined\r\n */\r\nexport function mapSize(size: unknown): ElUiSize | undefined {\r\n if (size === undefined || size === null || size === '') return undefined\r\n const key = String(size).trim()\r\n if (!key) return undefined\r\n return SIZE_MAP[key]\r\n}\r\n","<template>\r\n <el-form ref=\"formRef\" v-bind=\"formProps\" class=\"es-form\">\r\n <div class=\"flex-center\">\r\n <el-row v-bind=\"rowLayout\">\r\n <template v-for=\"(item, index) in formItem\">\r\n <el-col\r\n v-show=\"!item.isFold\"\r\n :key=\"item.prop || index\"\r\n :span=\"item.span\"\r\n >\r\n <el-form-item\r\n :label=\"translateLabel(item)\"\r\n v-bind=\"initFormItemOptions(item.formItemOptions || {})\"\r\n :prop=\"item.prop\"\r\n @click.native.stop=\"noop\"\r\n >\r\n <template v-if=\"item.formtype\">\r\n <render-dom-form\r\n :row=\"item\"\r\n :render=\"formInputComponents(item)\"\r\n :index=\"index\"\r\n :model=\"model\"\r\n />\r\n </template>\r\n <template v-else-if=\"item.render\">\r\n <render-dom-form\r\n :row=\"item\"\r\n :render=\"item.render\"\r\n :index=\"index\"\r\n :model=\"model\"\r\n />\r\n </template>\r\n </el-form-item>\r\n </el-col>\r\n </template>\r\n\r\n <template v-if=\"!isBtnHidden\">\r\n <render-btn\r\n v-if=\"isRenderBtn\"\r\n :row=\"{ isFold, folded, getBtnColSpan, getRowColsAlgorithm, changeFolded, refsForm: formInstance }\"\r\n :form-model=\"model\"\r\n :form-item-list=\"formItem\"\r\n :render=\"renderBtn\"\r\n />\r\n <el-col v-else :span=\"btnColSpanRow ? 24 : getBtnColSpan\">\r\n <!-- btnColSpanRow=true 时左右分布 -->\r\n <div\r\n v-if=\"btnColSpanRow && configBtn.length\"\r\n class=\"buttonOperate leftRightBtn\"\r\n >\r\n <div class=\"btn-left\">\r\n <el-form-item label-width=\"0px\" class=\"btn-formItem\">\r\n <template v-for=\"(it, inx) in colRightLeftList.colLeftBtn\">\r\n <el-button\r\n v-if=\"checkPermission(it.permissionValue)\"\r\n :key=\"it.key || inx\"\r\n v-bind=\"filterOptions(it)\"\r\n :icon=\"getCompIcon(it.icon)\"\r\n :disabled=\"resolveDisabled(it)\"\r\n @click=\"handleBtnClick(it)\"\r\n >\r\n {{ it.name }}\r\n </el-button>\r\n </template>\r\n </el-form-item>\r\n </div>\r\n <div class=\"btn-right\">\r\n <el-form-item label-width=\"0px\" class=\"btn-formItem\">\r\n <template v-for=\"(it, inx) in colRightLeftList.colRightBtn\">\r\n <el-button\r\n v-if=\"checkPermission(it.permissionValue)\"\r\n :key=\"it.key || inx\"\r\n v-bind=\"filterOptions(it)\"\r\n :icon=\"getCompIcon(it.icon)\"\r\n :disabled=\"resolveDisabled(it)\"\r\n @click=\"clickBtn(it)\"\r\n >\r\n {{ it.name }}\r\n </el-button>\r\n </template>\r\n <el-button\r\n v-if=\"isFold\"\r\n type=\"text\"\r\n :icon=\"folded ? 'el-icon-arrow-down' : 'el-icon-arrow-up'\"\r\n style=\"padding-left: 0; border: none\"\r\n @click=\"changeFolded\"\r\n >\r\n {{ folded ? '展开' : '收起' }}\r\n </el-button>\r\n </el-form-item>\r\n </div>\r\n </div>\r\n <!-- btnColSpanRow=false 时单行布局 -->\r\n <el-form-item\r\n v-if=\"!btnColSpanRow && configBtn.length\"\r\n :label=\"' '\"\r\n :label-width=\"formProps.labelBtnWidth ? formProps.labelBtnWidth : formProps.labelWidth\"\r\n :class=\"{ formItemCols: btnColSpanRow ? true : getBtnColSpan === 24 }\"\r\n class=\"btn-formItem\"\r\n >\r\n <div\r\n class=\"buttonOperate\"\r\n :style=\"{ 'text-align': getBtnColSpan === 24 ? 'right' : 'left' }\"\r\n >\r\n <template v-for=\"(it, inx) in configBtn\">\r\n <el-button\r\n v-if=\"checkPermission(it.permissionValue)\"\r\n :key=\"it.key || inx\"\r\n v-bind=\"filterOptions(it)\"\r\n :icon=\"getCompIcon(it.icon)\"\r\n :disabled=\"resolveDisabled(it)\"\r\n @click=\"handleBtnClick(it)\"\r\n >\r\n {{ it.name }}\r\n </el-button>\r\n </template>\r\n <el-button\r\n v-if=\"isFold\"\r\n type=\"text\"\r\n :icon=\"folded ? 'el-icon-arrow-down' : 'el-icon-arrow-up'\"\r\n style=\"padding-left: 0; border: none\"\r\n @click=\"changeFolded\"\r\n >\r\n {{ folded ? '展开' : '收起' }}\r\n </el-button>\r\n </div>\r\n </el-form-item>\r\n </el-col>\r\n </template>\r\n </el-row>\r\n </div>\r\n </el-form>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsForm —— Vue 2 + Element UI 配置化表单\r\n *\r\n * 与 Vue 3 + Element Plus 版本(packages/vue3/.../es-form.vue)的功能等价点:\r\n * - 24 栅格自动布局 / 折叠展开\r\n * - 13 种内置 formtype\r\n * - 远端 dataOptions 加载(apiParams + httpRequest)\r\n * - 工具栏按钮(左右分布、权限过滤、内置 query/rest 行为)\r\n * - 与 EsTable 联动(通过 inject getTableInstantce)\r\n * - exposed 方法:validate / resetFields / clearValidate / scrollToField\r\n *\r\n * Vue 2 关键差异点:\r\n * - 使用 defineComponent + setup() 替代 <script setup>\r\n * - 取 formRef 用 templateRefs().formRef(而非 Vue 3 的 ref())\r\n * - 图标改为字符串 class(el-icon-xxx)替代 Element Plus 图标组件\r\n * - 工具栏 dropdown 暂未实现自定义查询/自定义表格 → 后续 phase 5 验证后再补\r\n */\r\n\r\nimport { defineComponent, ref, computed, watch, inject, getCurrentInstance, nextTick, h, type PropType } from '../../vue-compat'\r\nimport { useFormInputs } from '../../composables/use-form-inputs'\r\nimport { useFormLayout } from '../../composables/use-form-layout'\r\nimport { useFormRequest } from '../../composables/use-form-request'\r\nimport { mapSize } from '../../utils/size'\r\nimport { getGlobalConfig, resolveFormLayProps } from '@es-plus/core'\r\nimport type { FormItemOption, BtnConfig, LayoutFormProps, ModelData } from '@es-plus/core'\r\n\r\n/**\r\n * 内联子组件:渲染 form-input 函数返回的 VNode\r\n *\r\n * 与 Vue 3 版本不同,Vue 2 中 render 函数签名为 (createElement, ctx),\r\n * 因此这里把传入的 render(已是 useFormInputs 暴露的 (h, model, ctx) 风格)\r\n * 桥接为 functional 组件。\r\n */\r\nconst RenderDomForm = defineComponent({\r\n name: 'RenderDomForm',\r\n functional: true,\r\n props: {\r\n row: { type: Object as PropType<FormItemOption>, default: () => ({}) },\r\n index: { type: Number, default: 0 },\r\n render: { type: Function, default: undefined },\r\n model: { type: Object as PropType<ModelData>, default: () => ({}) },\r\n },\r\n render(createElement, ctx) {\r\n const { row, index, model, render } = ctx.props\r\n if (typeof render !== 'function') return null\r\n const safeRow = row || {}\r\n const renderContent = render(createElement, model || {}, { row: safeRow, index })\r\n return typeof renderContent === 'string' ? createElement('span', renderContent) : renderContent\r\n },\r\n})\r\n\r\n/**\r\n * 自定义按钮区渲染(用户传 renderBtn 时使用)\r\n */\r\nconst RenderBtn = defineComponent({\r\n name: 'RenderBtn',\r\n functional: true,\r\n props: {\r\n row: { type: Object, default: () => ({}) },\r\n formItemList: { type: Array, default: () => [] },\r\n formModel: { type: Object, default: () => ({}) },\r\n render: { type: Function, default: undefined },\r\n },\r\n render(createElement, ctx) {\r\n const { formItemList, formModel, row, render } = ctx.props\r\n if (typeof render !== 'function') return null\r\n const renderContent = render(row, formModel, formItemList, createElement) || ''\r\n return typeof renderContent === 'string' ? createElement('span', renderContent) : renderContent\r\n },\r\n})\r\n\r\nexport default defineComponent({\r\n name: 'EsForm',\r\n components: { RenderDomForm, RenderBtn },\r\n props: {\r\n /** 表单 model 数据 */\r\n model: { type: Object as PropType<ModelData>, default: () => ({}) },\r\n /** 表单字段配置 */\r\n formItemList: { type: Array as PropType<FormItemOption[]>, default: () => [] },\r\n /** 布局配置 */\r\n layoutFormProps: { type: Object as PropType<LayoutFormProps>, default: () => ({}) },\r\n /** 工具栏按钮 */\r\n configBtn: { type: Array as PropType<BtnConfig[]>, default: () => [] },\r\n /** 自定义按钮区渲染函数 */\r\n renderBtn: { type: [Function, Boolean] as PropType<((row: object, model: ModelData, list: FormItemOption[], h: Function) => unknown) | boolean>, default: false },\r\n /** 是否一行内左右分布按钮 */\r\n btnColSpanRow: { type: Boolean, default: true },\r\n /** 校验规则 */\r\n rules: { type: Object as PropType<Record<string, unknown>>, default: () => ({}) },\r\n /** 字段映射注入函数 */\r\n fieldFieldOutput: { type: Function as PropType<(defaults: Record<string, string>) => Record<string, string>>, default: undefined },\r\n },\r\n setup(props, ctx) {\r\n const instance = getCurrentInstance()\r\n /**\r\n * Vue 2.7 的 setup(props, ctx) 中 ctx 仅有 attrs/listeners/slots/emit/expose,\r\n * 并不存在 ctx.refs。模板里 ref=\"formRef\" 拿到的实例只能从组件代理 vm.$refs 上读取。\r\n * 这里包一层 proxy 访问器,所有需要拿 formRef 的地方统一走 templateRefs.formRef。\r\n */\r\n const templateRefs = (): Record<string, unknown> => {\r\n const proxy = (instance as unknown as { proxy?: Record<string, unknown> } | null)?.proxy\r\n return ((proxy?.$refs as Record<string, unknown>) || {})\r\n }\r\n\r\n /**\r\n * 解析真实的 form data model —— 统一从两个来源回退:\r\n *\r\n * 1. `$vnode.data.model` —— 兼容 JSX `<es-form model={data} />`。\r\n * 背景:@vue/babel-preset-jsx@1.4.0 把 `model` 列为 rootAttribute,所以 JSX\r\n * `<es-form model={x} />` 编译产物是 `h(EsForm, { attrs: {...}, model: x })`,\r\n * `model` 落在 data 根级而非 attrs。Vue 2 运行时随后调用 transformModel,\r\n * 期待 v-model 形状 `{ value, callback }`,把 data.attrs.value = data.model.value\r\n * 写回;但用户传入的是普通数据对象,既无 .value 也无 .callback,结果\r\n * props.model 收到默认 `{}`。判定:若值为非空对象且 .callback 不是函数,则视为\r\n * 用户数据对象。\r\n *\r\n * 2. `props.model`(兜底)—— template `:model=\"x\"` 或真正的 v-model 走这里。\r\n */\r\n const resolvedModel = computed<ModelData>(() => {\r\n const proxy = (instance as unknown as { proxy?: { $vnode?: { data?: { model?: unknown } } } } | null)?.proxy\r\n const rawJsxModel = proxy?.$vnode?.data?.model\r\n if (\r\n rawJsxModel &&\r\n typeof rawJsxModel === 'object' &&\r\n typeof (rawJsxModel as { callback?: unknown }).callback !== 'function'\r\n ) {\r\n return rawJsxModel as ModelData\r\n }\r\n return props.model\r\n })\r\n const $esPlusForm = (inject('$esPlusForm', null) as Record<string, unknown> | null) ?? getGlobalConfig().EsForm ?? {}\r\n const esPlus = (inject('$EsPlus', null) as Record<string, unknown> | null) ?? getGlobalConfig() ?? {}\r\n\r\n // ─── 权限 / i18n ──\r\n const checkPermission = (pvalue?: string): boolean => {\r\n if (!pvalue) return true\r\n const fn = esPlus.permission as ((v: string) => boolean) | undefined\r\n return typeof fn === 'function' ? fn(pvalue) : true\r\n }\r\n const translateLabel = (item: FormItemOption): string => {\r\n if (item.labelKey && typeof esPlus.t === 'function') {\r\n return (esPlus.t as (k: string) => string)(item.labelKey)\r\n }\r\n return item.label\r\n }\r\n\r\n // ─── 与 EsTable 联动 ──\r\n const injectedTableInstant = inject<(() => unknown) | null>('getTableInstantce', null)\r\n const getTableInstant = computed(() => {\r\n if (injectedTableInstant) {\r\n return typeof injectedTableInstant === 'function'\r\n ? injectedTableInstant()\r\n : injectedTableInstant\r\n }\r\n const proxy = (instance as unknown as { proxy?: Record<string, unknown> })?.proxy\r\n const fn = proxy?.getTableInstantce\r\n if (typeof fn === 'function') return (fn as () => unknown)()\r\n return fn\r\n })\r\n const isParentTable = computed(() => {\r\n const t = getTableInstant.value as Record<string, unknown> | null | undefined\r\n return !!(t && Object.keys(t).length)\r\n })\r\n\r\n // ─── 图标处理(Element UI 用 class 字符串) ──\r\n const getCompIcon = (key?: string): string | undefined => {\r\n if (!key) return undefined\r\n // 兼容 Element Plus 图标名(如 'Plus')→ 'el-icon-plus'\r\n // 已经是 el-icon-xxx 的直接返回\r\n if (key.startsWith('el-icon-')) return key\r\n // PascalCase → kebab-case\r\n const kebab = key.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/[\\s_]+/g, '-').toLowerCase()\r\n return `el-icon-${kebab}`\r\n }\r\n const filterOptions = (it: BtnConfig) => {\r\n const { icon: _icon, ...opt } = it as unknown as Record<string, unknown>\r\n // 把用户传入的 size 经 mapSize 翻译到 Element UI v2 语义;缺省时与表单默认尺寸\r\n // (mini) 对齐,避免按钮比表单输入大一截。详见 packages/vue2/src/utils/size.ts。\r\n if (opt.size !== undefined) {\r\n const mapped = mapSize(opt.size)\r\n if (mapped !== undefined) opt.size = mapped\r\n } else {\r\n opt.size = 'mini'\r\n }\r\n return opt\r\n }\r\n const resolveDisabled = (it: BtnConfig): boolean => {\r\n const d = it.disabled\r\n if (typeof d === 'function') return Boolean((d as () => boolean | undefined)())\r\n return Boolean(d)\r\n }\r\n\r\n // ─── refs ──\r\n const formInstance = ref<Record<string, unknown>>({})\r\n const formItemRowsList = ref<FormItemOption[]>(props.formItemList || [])\r\n\r\n // ─── composables ──\r\n const { formInputComponents } = useFormInputs()\r\n const httpRequestGlobal = ($esPlusForm?.$httpRequest as ((p: Record<string, unknown>) => Promise<unknown>) | undefined) || undefined\r\n const fieldFieldOutputGlobal = (props.fieldFieldOutput || $esPlusForm?.fieldFieldOutput) as\r\n | ((defaults: Record<string, string>) => Record<string, string>)\r\n | undefined\r\n const { getEveryFormQueryField } = useFormRequest(httpRequestGlobal)\r\n\r\n // ─── formProps (供 el-form 使用) ──\r\n const formLayoutRef = ref<Record<string, unknown>>(resolveFormLayProps(props.layoutFormProps) as Record<string, unknown>)\r\n /**\r\n * Element UI v2 的 el-form 在 `labelWidth` 缺省时会让 label 浮动在自然位置,\r\n * 当外层是 flex/wrap 布局且 label 较长时会被挤到 input 上方(label 与 content 分行),\r\n * 严重破坏栅格视觉。原 es-eui 的 esForm 对此做了缺省 `labelWidth: 'auto'` 的兜底\r\n * (详见 es-eui/src/components/es-eui/esForm/src/esForm.vue 的 fromProps 计算属性)。\r\n *\r\n * 这里保持同样的兜底策略,确保未显式传 labelWidth 时 label 与 content 同行展示。\r\n *\r\n * 默认 size 与原 es-eui 对齐为 `mini`(el-form size=mini 时表单控件高度 ≈ 28px),\r\n * 同时通过 mapSize 把用户从 Vue 3 / Element Plus 习惯传来的 `large/default/small`\r\n * 自动转译为 Element UI v2 语义,避免两个版本\"同一份配置渲染出明显不同尺寸\"。\r\n */\r\n const formProps = computed<Record<string, unknown>>(() => {\r\n const userLayout = formLayoutRef.value || {}\r\n const merged: Record<string, unknown> = {\r\n size: 'mini',\r\n ...userLayout,\r\n model: resolvedModel.value,\r\n rules: props.rules,\r\n validateOnRuleChange: false,\r\n }\r\n const mapped = mapSize(merged.size)\r\n if (mapped !== undefined) merged.size = mapped\r\n if (merged.labelWidth === undefined || merged.labelWidth === '' || merged.labelWidth === null) {\r\n merged.labelWidth = 'auto'\r\n }\r\n return merged\r\n })\r\n\r\n // ─── 远端选项加载(仅对未加载过的字段执行) ──\r\n const loadedApiProps = ref<Set<string>>(new Set<string>())\r\n\r\n watch(\r\n () => props.formItemList,\r\n async (val) => {\r\n const list = Array.isArray(val) ? val : []\r\n const needLoadList = list.filter(\r\n (it) => it && it.isInitRun !== false && !loadedApiProps.value.has(it.prop)\r\n )\r\n if (!needLoadList.length) {\r\n formItemRowsList.value = list\r\n .map((it) => {\r\n if (!it) return null\r\n const existing = formItemRowsList.value.find((old) => old && old.prop === it.prop)\r\n return existing?.dataOptions?.length ? { ...it, dataOptions: existing.dataOptions } : it\r\n })\r\n .filter((it): it is FormItemOption => !!it)\r\n return\r\n }\r\n const rows = await getEveryFormQueryField(needLoadList, fieldFieldOutputGlobal)\r\n needLoadList.forEach((it) => loadedApiProps.value.add(it.prop))\r\n formItemRowsList.value = list\r\n .map((it) => {\r\n if (!it) return null\r\n const fromApi = rows.find((r) => r && r.prop === it.prop)\r\n const existing = formItemRowsList.value.find((old) => old && old.prop === it.prop)\r\n if (fromApi) {\r\n return {\r\n ...it,\r\n dataOptions: fromApi.listData as Array<{ label: string; value: unknown }>,\r\n }\r\n }\r\n if (existing?.dataOptions?.length) return { ...it, dataOptions: existing.dataOptions }\r\n return it\r\n })\r\n .filter((it): it is FormItemOption => !!it)\r\n },\r\n { immediate: true, deep: true }\r\n )\r\n\r\n // ─── 可见 + auto-span 计算 ──\r\n const formItemListFilter = computed(() => {\r\n const list = formItemRowsList.value || []\r\n const visible = list\r\n .map((it) => (it ? { ...it, dataOptions: it.dataOptions || [] } : null))\r\n .filter((it): it is FormItemOption & { dataOptions: Array<{ label: string; value: unknown }> } => {\r\n if (!it) return false\r\n // 字段名兼容:原 es-eui 用 `isHiden`(少一个 d,原始拼写错误),\r\n // 后续规范化为 `isHidden`。两者都接受,原始拼写优先(保持旧文档案例可直接运行)。\r\n const legacyHide = (it as unknown as { isHiden?: unknown }).isHiden\r\n const fixedHide = it.isHidden\r\n const hideFn = typeof legacyHide === 'function'\r\n ? (legacyHide as (m: ModelData, item: FormItemOption, props: Record<string, unknown>) => boolean)\r\n : typeof fixedHide === 'function'\r\n ? fixedHide\r\n : null\r\n if (hideFn) {\r\n return !hideFn(resolvedModel.value, it, formProps.value)\r\n }\r\n return true\r\n })\r\n\r\n const itemsWithoutSpan = visible.filter((it) => !it.span)\r\n const autoCount = itemsWithoutSpan.length\r\n let autoSpan = 6\r\n if (autoCount > 0) {\r\n const fixedTotal = visible.reduce((sum, it) => sum + (it.span || 0), 0)\r\n const remaining = 24 - (fixedTotal % 24 || (fixedTotal ? 24 : 0))\r\n if (fixedTotal === 0) {\r\n if (autoCount === 1) autoSpan = 24\r\n else if (autoCount === 2) autoSpan = 12\r\n else if (autoCount === 3) autoSpan = 8\r\n else autoSpan = 6\r\n } else {\r\n autoSpan = remaining >= autoCount ? Math.floor(remaining / autoCount) : 6\r\n if (autoSpan > 12) autoSpan = 12\r\n if (autoSpan < 4) autoSpan = 6\r\n }\r\n }\r\n return visible.map((it) => ({ ...it, span: it.span || autoSpan }))\r\n })\r\n\r\n const layoutResult = useFormLayout({\r\n layoutFormProps: props.layoutFormProps,\r\n get formItemList() {\r\n return formItemListFilter.value\r\n },\r\n } as never)\r\n\r\n const {\r\n folded,\r\n isBtnHidden,\r\n rowLayout,\r\n formLayout,\r\n getRowColsAlgorithm,\r\n isFold,\r\n getBtnColSpan,\r\n formItem,\r\n changeFolded,\r\n } = layoutResult\r\n\r\n watch(\r\n formLayout,\r\n (val: Record<string, unknown>) => {\r\n formLayoutRef.value = val\r\n },\r\n { immediate: true }\r\n )\r\n\r\n // ─── 按钮分组(左右) ──\r\n const colRightLeftList = computed(() => ({\r\n colRightBtn: props.configBtn.filter((it) => it.direction === 'right' || !it.direction),\r\n colLeftBtn: props.configBtn.filter((it) => it.direction === 'left'),\r\n }))\r\n\r\n const isRenderBtn = computed(() => typeof props.renderBtn === 'function')\r\n\r\n // ─── 按钮点击逻辑 ──\r\n const handleBtnClick = (it: BtnConfig) => {\r\n const formRef = (templateRefs().formRef as unknown) as Record<string, unknown> | null\r\n const httpFn = (getTableInstant.value as { httpRequestInstance?: (p: unknown) => void } | null)?.httpRequestInstance\r\n it.click?.(resolvedModel.value, formRef as unknown, httpFn)\r\n }\r\n\r\n const queryTableRequest = (model: ModelData, formRef: { resetFields?: () => void } | null, key?: string) => {\r\n const t = getTableInstant.value as { httpRequestInstance?: (p: unknown) => void } | null\r\n if (key === 'query') {\r\n if (isParentTable.value) {\r\n t?.httpRequestInstance?.(model)\r\n }\r\n } else if (key === 'rest' && formRef) {\r\n if (isParentTable.value) {\r\n t?.httpRequestInstance?.(model)\r\n }\r\n formRef.resetFields?.()\r\n }\r\n }\r\n\r\n const clickBtn = (it: BtnConfig) => {\r\n const formRef = (templateRefs().formRef as unknown) as { resetFields?: () => void } | null\r\n if (it.triggerEvent && ['query', 'rest'].includes(it.key || '')) {\r\n queryTableRequest(resolvedModel.value, formRef, it.key)\r\n } else {\r\n if (it.key === 'rest' && formRef) {\r\n formRef.resetFields?.()\r\n }\r\n const httpFn = (getTableInstant.value as { httpRequestInstance?: (p: unknown) => void } | null)?.httpRequestInstance\r\n it.click?.(resolvedModel.value, formRef as unknown, httpFn)\r\n }\r\n }\r\n\r\n const initFormItemOptions = (opts: Record<string, unknown>) => {\r\n if (isParentTable.value) {\r\n const { style, ...rest } = opts\r\n return { style: { marginBottom: '10px', ...((style as Record<string, unknown>) || {}) }, ...rest }\r\n }\r\n return opts\r\n }\r\n\r\n // ─── 暴露给外部的方法 ──\r\n const getFormRef = () => templateRefs().formRef as unknown as {\r\n validate: (cb?: (valid: boolean) => void) => Promise<boolean>\r\n resetFields: () => void\r\n clearValidate: (props?: string | string[]) => void\r\n validateField: (props: string | string[], cb?: (msg: string) => void) => void\r\n }\r\n\r\n const validate = (): Promise<boolean> => {\r\n const ref = getFormRef()\r\n if (!ref) return Promise.resolve(false)\r\n // Element UI el-form.validate 接受 callback;若返回 Promise 我们以 callback 形式包装\r\n return new Promise<boolean>((resolve) => {\r\n try {\r\n const maybePromise = (ref as unknown as { validate: (cb: (valid: boolean) => void) => void | Promise<boolean> }).validate((valid: boolean) => {\r\n resolve(!!valid)\r\n })\r\n if (maybePromise && typeof (maybePromise as Promise<boolean>).then === 'function') {\r\n ;(maybePromise as Promise<boolean>).then(resolve).catch(() => resolve(false))\r\n }\r\n } catch (e) {\r\n resolve(false)\r\n }\r\n })\r\n }\r\n const resetFields = () => getFormRef()?.resetFields()\r\n const clearValidate = (p?: string | string[]) => getFormRef()?.clearValidate(p)\r\n const validateField = (p: string | string[]) => getFormRef()?.validateField(p)\r\n\r\n const formItmeRequestInstance = async (propsList: string[]) => {\r\n const list = formItemListFilter.value\r\n const targetItems = list.filter((it) => it && propsList.includes(it.prop))\r\n if (!targetItems.length) return\r\n const rows = await getEveryFormQueryField(targetItems, fieldFieldOutputGlobal)\r\n rows.forEach((apiOption) => {\r\n if (!apiOption) return\r\n const itemIndex = formItemRowsList.value.findIndex((it) => it && it.prop === apiOption.prop)\r\n if (itemIndex !== -1) {\r\n formItemRowsList.value[itemIndex] = {\r\n ...formItemRowsList.value[itemIndex],\r\n dataOptions: apiOption.listData as Array<{ label: string; value: unknown }>,\r\n }\r\n }\r\n })\r\n }\r\n\r\n nextTick(() => {\r\n formInstance.value = templateRefs().formRef as unknown as Record<string, unknown>\r\n const proxy = (instance as unknown as { proxy?: Record<string, unknown> })?.proxy\r\n const bodyFormFn = proxy?.bodyFormInstance as ((inst: Record<string, unknown>) => void) | undefined\r\n bodyFormFn?.(formInstance.value)\r\n })\r\n\r\n // 暴露给 ref 拿到的 expose(Vue 2 + composition-api 用 expose;Vue 2.7 setupContext 也支持)\r\n if (typeof (ctx as unknown as { expose?: (e: Record<string, unknown>) => void }).expose === 'function') {\r\n ;(ctx as unknown as { expose: (e: Record<string, unknown>) => void }).expose({\r\n formItmeRequestInstance,\r\n getFormRef,\r\n validate,\r\n resetFields,\r\n clearValidate,\r\n validateField,\r\n })\r\n }\r\n\r\n return {\r\n // 模板使用\r\n formProps,\r\n rowLayout,\r\n formItem,\r\n isBtnHidden,\r\n isFold,\r\n folded,\r\n getBtnColSpan,\r\n isRenderBtn,\r\n colRightLeftList,\r\n configBtn: computed(() => props.configBtn),\r\n formInputComponents,\r\n formInstance,\r\n model: resolvedModel,\r\n btnColSpanRow: computed(() => props.btnColSpanRow),\r\n renderBtn: computed(() => props.renderBtn),\r\n getRowColsAlgorithm,\r\n changeFolded,\r\n // 方法\r\n checkPermission,\r\n translateLabel,\r\n getCompIcon,\r\n filterOptions,\r\n resolveDisabled,\r\n handleBtnClick,\r\n clickBtn,\r\n initFormItemOptions,\r\n noop: () => {},\r\n // expose 公开方法(供 $refs.<esForm>.validate() 直接调用,不经过 ctx.expose)\r\n formItmeRequestInstance,\r\n getFormRef,\r\n validate,\r\n resetFields,\r\n clearValidate,\r\n validateField,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.es-form {\r\n /**\r\n * 修复 Element UI v2 的栅格布局错乱问题。\r\n *\r\n * 默认的 el-row 是 float 布局,子 el-col 高度不一致时会出现「卡进上一列尾部留白」\r\n * 的换行错乱。我们在 use-form-layout 中默认给 el-row 加了 type=\"flex\",\r\n * 但 Element UI 的 .el-row--flex 没有自带 flex-wrap,需要这里补上。\r\n *\r\n * 这个写法只影响 .es-form 内部的 el-row,不污染外部的栅格布局。\r\n */\r\n ::v-deep(.el-row--flex) {\r\n flex-wrap: wrap;\r\n }\r\n ::v-deep(.el-form-item) {\r\n margin-bottom: 18px;\r\n }\r\n ::v-deep(.el-form-item__label) {\r\n font-weight: 500;\r\n }\r\n .buttonOperate {\r\n display: flex;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n gap: 8px;\r\n }\r\n .leftRightBtn {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n width: 100%;\r\n .btn-left,\r\n .btn-right {\r\n display: flex;\r\n align-items: center;\r\n }\r\n }\r\n .btn-formItem {\r\n margin-bottom: 0;\r\n }\r\n .formItemCols {\r\n width: 100%;\r\n }\r\n}\r\n</style>\r\n","/**\r\n * EsForm 组件入口\r\n *\r\n * 提供两种导入方式:\r\n * 1. 默认导入:import EsForm from '@es-plus/vue2/es-form'\r\n * 2. install 安装:通过 Vue.use(EsPlus) 全局注册\r\n */\r\n\r\nimport EsForm from './es-form.vue'\r\nimport type { Vue } from '../../vue-compat'\r\n\r\n// Element UI 组件作为 EsForm 的依赖,由用户在 main.js 中通过 Vue.use(ElementUI) 全局注册。\r\n// 这里不重复注册,但提供 install 函数让 Vue.use(EsForm) 也能局部使用。\r\n;(EsForm as unknown as { install: (V: typeof Vue) => void }).install = function (Vue) {\r\n Vue.component((EsForm as unknown as { name: string }).name || 'EsForm', EsForm)\r\n}\r\n\r\nexport default EsForm\r\nexport { EsForm }\r\n","<template>\r\n <!-- 分组列处理 -->\r\n <el-table-column\r\n v-if=\"cols.groups && Array.isArray(cols.groups)\"\r\n v-bind=\"columnBindAttr(cols)\"\r\n >\r\n <el-table-column\r\n v-for=\"(item, index) in cols.groups\"\r\n :key=\"item.prop || item.key || index\"\r\n v-bind=\"columnBindAttr(Object.assign({}, item, { columnIndex: index }))\"\r\n >\r\n <template v-if=\"item.render && typeof item.render === 'function'\" #default=\"scope\">\r\n <render-dom-tb\r\n v-if=\"scope && scope.row\"\r\n :row=\"scope.row\"\r\n :index=\"scope.$index\"\r\n :data-key=\"item.key\"\r\n :render=\"item.render\"\r\n />\r\n <span v-else>-</span>\r\n </template>\r\n <template v-else-if=\"item.scopedSlots && item.scopedSlots.customRender\" #default=\"scope\">\r\n <slot\r\n v-if=\"scope && scope.row\"\r\n v-bind=\"Object.assign({}, item, { row: scope.row, column: scope.column, scope: scope })\"\r\n :name=\"item.scopedSlots.customRender\"\r\n />\r\n <span v-else>-</span>\r\n </template>\r\n </el-table-column>\r\n </el-table-column>\r\n\r\n <!-- 自定义渲染函数列 -->\r\n <el-table-column\r\n v-else-if=\"cols.render && typeof cols.render === 'function'\"\r\n v-bind=\"columnBindAttr(cols)\"\r\n >\r\n <template #default=\"scope\">\r\n <render-dom-tb\r\n v-if=\"scope && scope.row\"\r\n :row=\"scope.row\"\r\n :index=\"scope.$index\"\r\n :data-key=\"cols.key\"\r\n :render=\"cols.render\"\r\n />\r\n <span v-else>-</span>\r\n </template>\r\n </el-table-column>\r\n\r\n <!-- 作用域插槽列 -->\r\n <el-table-column\r\n v-else-if=\"cols.scopedSlots && cols.scopedSlots.customRender\"\r\n v-bind=\"columnBindAttr(cols)\"\r\n >\r\n <template #default=\"scope\">\r\n <slot\r\n v-if=\"scope && scope.row\"\r\n v-bind=\"Object.assign({}, cols, { row: scope.row, column: scope.column, scope: scope })\"\r\n :name=\"cols.scopedSlots.customRender\"\r\n />\r\n <span v-else>-</span>\r\n </template>\r\n </el-table-column>\r\n\r\n <!-- 省略号工具提示列 -->\r\n <el-table-column\r\n v-else-if=\"cols.ellipsis && typeof cols.ellipsis === 'boolean'\"\r\n show-overflow-tooltip\r\n v-bind=\"columnBindAttr(cols)\"\r\n />\r\n\r\n <!-- 普通列 -->\r\n <el-table-column v-else v-bind=\"columnBindAttr(cols)\" />\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsTable 列递归渲染组件 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - 不使用 <script setup>,改为 defineComponent + setup()\r\n * - h 来自 './vue-compat'(实际是 Vue 2 的 createElement)\r\n * - inject 来自 @vue/composition-api,签名一致\r\n * - el-table-column 在 Element UI 与 Element Plus 中 API 基本一致\r\n *\r\n * 列配置约定:\r\n * - cols.groups: 嵌套表头(多级表头)\r\n * - cols.render: 自定义渲染函数 (h, { value, row, index }) => VNode\r\n * - cols.scopedSlots.customRender: 作用域插槽名称\r\n * - cols.ellipsis: 文字超出时显示 tooltip\r\n * - cols.key: 数据字段(自动映射为 prop)\r\n * - cols.labelKey: 国际化 label 键\r\n */\r\n\r\nimport { h, defineComponent, inject } from '../../vue-compat'\r\nimport { getGlobalConfig } from '@es-plus/core'\r\nimport type { TableColumn } from '../../types'\r\n\r\n// 函数式 render 包装组件 —— 把用户传入的 render(h, ctx) 渲染为 VNode\r\nconst RenderDomTb = defineComponent({\r\n name: 'RenderDomTb',\r\n props: {\r\n row: { type: Object, default: () => ({}) },\r\n index: { type: Number, default: 0 },\r\n dataKey: String,\r\n render: { type: Function, required: true },\r\n },\r\n setup(props: any) {\r\n return () => {\r\n const { row, index, dataKey, render } = props\r\n if (!row) return h('span', '-')\r\n const value = dataKey ? row[dataKey] : null\r\n try {\r\n const renderResult = render(h, { value, row, index })\r\n if (typeof renderResult === 'string') return h('span', renderResult)\r\n return renderResult\r\n } catch (error) {\r\n return h('span', '-')\r\n }\r\n }\r\n },\r\n})\r\n\r\nconst firstWordUpperCase = (str: string): string => {\r\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'EsTableColumnItem',\r\n components: { RenderDomTb },\r\n props: {\r\n cols: {\r\n type: Object as () => TableColumn,\r\n required: true,\r\n },\r\n },\r\n setup() {\r\n // 注入全局 EsPlus 配置(含 i18n t 函数)\r\n const esPlus =\r\n inject<Record<string, unknown>>('$EsPlus', null as unknown as Record<string, unknown>) ??\r\n (getGlobalConfig() as Record<string, unknown>) ??\r\n {}\r\n\r\n /**\r\n * 把用户写的列配置规范化为 el-table-column 的 props\r\n * - 跳过 groups/scopedSlots/render(它们走单独的渲染路径)\r\n * - 中划线属性自动转驼峰(如 'show-overflow-tooltip' → 'showOverflowTooltip')\r\n * - key → prop 双向映射\r\n * - labelKey + 全局 t 函数 → 国际化 label\r\n * - 默认 align: center(与 Vue 3 版本保持一致)\r\n */\r\n const columnBindAttr = (cols: TableColumn) => {\r\n const options: Record<string, unknown> = {}\r\n\r\n for (const t in cols) {\r\n if (t === 'groups' || t === 'scopedSlots' || t === 'render') continue\r\n\r\n if (t.includes('-')) {\r\n const parts = t.split('-')\r\n let camelKey = parts[0]\r\n for (let i = 1; i < parts.length; i++) {\r\n camelKey += firstWordUpperCase(parts[i])\r\n }\r\n options[camelKey] = (cols as Record<string, unknown>)[t]\r\n } else if (t === 'key') {\r\n options.prop = (cols as Record<string, unknown>)[t]\r\n options[t] = (cols as Record<string, unknown>)[t]\r\n } else if (t === 'label' && cols.labelKey && typeof esPlus.t === 'function') {\r\n options.label = (esPlus.t as (k: string) => string)(cols.labelKey as string)\r\n } else {\r\n options[t] = (cols as Record<string, unknown>)[t]\r\n }\r\n }\r\n\r\n if (!options.align) {\r\n options.align = 'center'\r\n }\r\n\r\n return options\r\n }\r\n\r\n return {\r\n columnBindAttr,\r\n }\r\n },\r\n})\r\n</script>\r\n","/**\r\n * Element UI 图标适配工具\r\n *\r\n * Element Plus 使用图标组件(如 `<Plus />`),Element UI 使用 class 字符串(如 `el-icon-plus`)。\r\n * 用户配置可能传入:\r\n * - 'Plus' (Element Plus 风格 PascalCase)\r\n * - 'el-icon-plus' (Element UI 原生 class)\r\n * - 'plus' (短名)\r\n *\r\n * 本函数统一规范化为 Element UI 的 class 字符串。\r\n */\r\nexport const getCompIcon = (key?: string): string | undefined => {\r\n if (!key) return undefined\r\n // 已经是 el-icon-xxx 的直接返回\r\n if (key.startsWith('el-icon-')) return key\r\n // PascalCase / camelCase → kebab-case,并加 el-icon- 前缀\r\n const kebab = key\r\n .replace(/([a-z])([A-Z])/g, '$1-$2')\r\n .replace(/[\\s_]+/g, '-')\r\n .toLowerCase()\r\n return `el-icon-${kebab}`\r\n}\r\n","<template>\r\n <div v-if=\"showContainer\" class=\"flex-float btns\">\r\n <div class=\"left-text\">\r\n {{ leftText }}\r\n </div>\r\n\r\n <div class=\"btn-container_block\">\r\n <!-- 左侧按钮组 -->\r\n <div class=\"btn-left\">\r\n <template v-for=\"(item, index) in processedBtnLeft\">\r\n <div v-if=\"!item.isHide\" :key=\"item.name || index\" :style=\"buttonContainerStyle(index)\">\r\n <render-dom\r\n v-if=\"item.render && typeof item.render === 'function'\"\r\n :render=\"item.render\"\r\n />\r\n <el-button\r\n v-else\r\n :type=\"item.type || ''\"\r\n :size=\"resolveBtnSize(item)\"\r\n :icon=\"getCompIcon(item.icon)\"\r\n :loading=\"item.loading || false\"\r\n v-bind=\"filterOptions(item)\"\r\n :disabled=\"getDisabledState(item)\"\r\n @click=\"() => item.click && item.click(instance)\"\r\n >\r\n {{ item.name }}\r\n </el-button>\r\n </div>\r\n </template>\r\n </div>\r\n\r\n <!-- 右侧按钮组 -->\r\n <div class=\"btn-right\">\r\n <template v-for=\"(item, index) in processedBtnRight\">\r\n <div v-if=\"!item.isHide\" :key=\"item.name || index\" :style=\"buttonContainerStyle(index)\">\r\n <render-dom\r\n v-if=\"item.render && typeof item.render === 'function'\"\r\n :render=\"item.render\"\r\n />\r\n <el-button\r\n v-else\r\n :type=\"item.type || ''\"\r\n :size=\"resolveBtnSize(item)\"\r\n :icon=\"getCompIcon(item.icon)\"\r\n :loading=\"item.loading || false\"\r\n v-bind=\"filterOptions(item)\"\r\n :disabled=\"getDisabledState(item)\"\r\n @click=\"() => item.click && item.click(instance)\"\r\n >\r\n {{ item.name }}\r\n </el-button>\r\n </div>\r\n </template>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsTable 工具栏按钮组件 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - 不使用 <script setup>\r\n * - 图标用 el-icon-* class 字符串(getCompIcon 转换 Element Plus 风格)\r\n * - 按钮 v-bind 时排除 icon/render/click/permissionValue 等已单独处理或非 DOM 属性\r\n *\r\n * 按钮配置约定:\r\n * - code === 1: 渲染到左侧\r\n * - code === 2: 渲染到右侧\r\n * - permissionValue: 配合全局 esPlus.permission(value) 做权限过滤\r\n * - isHide: boolean | () => boolean,函数形式会被解析\r\n * - render: 用户自定义渲染函数\r\n * - click(instance): 点击回调,注入 EsTable 实例\r\n */\r\n\r\nimport { defineComponent, computed, inject, h } from '../../vue-compat'\r\nimport { getGlobalConfig, getButtonPosition, type BtnConfig } from '@es-plus/core'\r\nimport { getCompIcon } from '../../utils/icon'\r\nimport { mapSize } from '../../utils/size'\r\n\r\n/**\r\n * 工具栏按钮的运行时形状(在 BtnConfig 基础上加 isHide)\r\n *\r\n * BtnConfig 上的 `[key: string]: unknown` 索引签名会让 vue-tsc 在模板里\r\n * 把 item.name / item.icon / item.click 全部窄化成 unknown。这里显式\r\n * 用一个最小契约(只覆盖模板真正会用到的字段)来阻断那条索引签名,\r\n * 让 :key / :icon / @click 在生成 .d.ts 时通过类型校验。\r\n */\r\ntype RenderableBtn = {\r\n name?: string\r\n icon?: string\r\n click?: (...args: unknown[]) => void\r\n type?: string\r\n size?: string\r\n loading?: boolean\r\n disabled?: boolean | ((...args: unknown[]) => boolean)\r\n render?: (...args: unknown[]) => unknown\r\n isHide?: boolean\r\n permissionValue?: string\r\n code?: 1 | 2\r\n}\r\n\r\n// 函数式 render 包装组件\r\nconst RenderDom = defineComponent({\r\n name: 'RenderDomTbBtn',\r\n props: {\r\n render: { type: Function, required: true },\r\n },\r\n setup(props: any) {\r\n return () => {\r\n if (!props.render || typeof props.render !== 'function') return null\r\n try {\r\n return props.render()\r\n } catch {\r\n return null\r\n }\r\n }\r\n },\r\n})\r\n\r\nexport default defineComponent({\r\n name: 'EsTableBtns',\r\n components: { RenderDom },\r\n props: {\r\n leftText: { type: String, default: '' },\r\n btnConfig: {\r\n type: Array as () => BtnConfig[],\r\n default: () => [],\r\n },\r\n instance: {\r\n type: Object as () => Record<string, unknown>,\r\n default: () => ({}),\r\n },\r\n },\r\n setup(props) {\r\n const esPlus =\r\n inject<Record<string, unknown>>('$EsPlus', null as unknown as Record<string, unknown>) ??\r\n (getGlobalConfig() as Record<string, unknown>) ??\r\n {}\r\n\r\n const hasPermission = (_btnList: unknown[], pvalue?: string) => {\r\n if (!pvalue) return true\r\n const permFn = esPlus.permission\r\n if (typeof permFn === 'function') return (permFn as (v: string) => boolean)(pvalue)\r\n return true\r\n }\r\n\r\n const processButtonConfig = (config: Array<Record<string, unknown>>) => {\r\n return config.map((item) => {\r\n const processed = { ...item }\r\n const hasPerm = hasPermission([], item.permissionValue as string)\r\n\r\n if (!hasPerm) {\r\n processed.isHide = true\r\n } else if (typeof item.isHide === 'function') {\r\n processed.isHide = (item.isHide as () => boolean)()\r\n } else {\r\n processed.isHide = item.isHide || false\r\n }\r\n\r\n return processed\r\n })\r\n }\r\n\r\n const processedBtnLeft = computed<RenderableBtn[]>(() => {\r\n return processButtonConfig(\r\n (props.btnConfig || []).filter((item) => getButtonPosition(item as BtnConfig) === 'left') as Array<Record<string, unknown>>\r\n ).filter((item) => !item.isHide) as RenderableBtn[]\r\n })\r\n\r\n const processedBtnRight = computed<RenderableBtn[]>(() => {\r\n return processButtonConfig(\r\n (props.btnConfig || []).filter((item) => getButtonPosition(item as BtnConfig) === 'right') as Array<Record<string, unknown>>\r\n ).filter((item) => !item.isHide) as RenderableBtn[]\r\n })\r\n\r\n const showContainer = computed(() => {\r\n return (\r\n !!props.leftText ||\r\n processedBtnLeft.value.length > 0 ||\r\n processedBtnRight.value.length > 0\r\n )\r\n })\r\n\r\n const getDisabledState = (item: Record<string, unknown>): boolean => {\r\n if (typeof item.disabled === 'function') {\r\n return (item.disabled as () => boolean)()\r\n }\r\n return (item.disabled as boolean) || false\r\n }\r\n\r\n const buttonContainerStyle = (index: number) => {\r\n return {\r\n display: 'inline-block',\r\n marginLeft: index !== 0 ? '8px' : '0px',\r\n }\r\n }\r\n\r\n /**\r\n * 过滤掉非 el-button 原生 props 的字段,避免 v-bind 透传出错\r\n */\r\n const filterOptions = (item: Record<string, unknown>) => {\r\n const {\r\n render: _r,\r\n click: _c,\r\n icon: _i,\r\n permissionValue: _p,\r\n code: _co,\r\n isHide: _ih,\r\n name: _n,\r\n size: _s,\r\n ...rest\r\n } = item\r\n return rest\r\n }\r\n\r\n /**\r\n * 解析按钮尺寸:先按用户传入值经 mapSize 翻译为 Element UI v2 语义;\r\n * 用户未传时默认 mini,与 EsForm 的默认值保持一致,避免 EsTable 工具栏按钮\r\n * 比表单控件视觉上\"大一截\"。\r\n */\r\n const resolveBtnSize = (item: { size?: string }): string => {\r\n const mapped = mapSize(item.size)\r\n return mapped || 'mini'\r\n }\r\n\r\n return {\r\n processedBtnLeft,\r\n processedBtnRight,\r\n showContainer,\r\n getDisabledState,\r\n buttonContainerStyle,\r\n getCompIcon,\r\n filterOptions,\r\n resolveBtnSize,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.btns {\r\n padding: 0;\r\n padding-bottom: 5px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n}\r\n\r\n.left-text {\r\n color: rgb(125, 125, 125);\r\n font-size: 14px;\r\n}\r\n\r\n.btn-container_block {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n flex: 1;\r\n\r\n .btn-left {\r\n display: flex;\r\n justify-content: flex-start;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n }\r\n\r\n .btn-right {\r\n display: flex;\r\n justify-content: flex-end;\r\n align-items: center;\r\n flex-wrap: wrap;\r\n }\r\n}\r\n\r\n@media (max-width: 768px) {\r\n .btns {\r\n flex-direction: column;\r\n align-items: flex-start;\r\n }\r\n\r\n .btn-container_block {\r\n flex-direction: column;\r\n align-items: flex-start;\r\n gap: 10px;\r\n\r\n .btn-left,\r\n .btn-right {\r\n width: 100%;\r\n justify-content: flex-start;\r\n }\r\n }\r\n}\r\n</style>\r\n","/**\r\n * EsTable 容器尺寸自适应 composable —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - ref/nextTick/onMounted/onBeforeUnmount 来自 './vue-compat'\r\n * - 业务逻辑 100% 一致(只是 Vue API 来源不同)\r\n *\r\n * 核心思路:通过 ResizeObserver 监听表格容器及表头按钮区高度,动态计算 el-table 的 height/maxHeight,\r\n * 让表格在 height 模式下分页固定贴底、在 auto 模式下随内容自适应。\r\n */\r\n\r\nimport { ref, nextTick, onMounted, onBeforeUnmount } from '../vue-compat'\r\n\r\nexport function useTableResize(\r\n tableContainerRef: { value: HTMLElement | null },\r\n headBarRef: { value: HTMLElement | null },\r\n tbBtnRef: { value: { $el?: HTMLElement } | null },\r\n paginationRef: { value: HTMLElement | null },\r\n options: { heightType?: 'auto' | 'height'; tabHeight?: number | string }\r\n) {\r\n const tableHeight = ref(400)\r\n const observer = ref<ResizeObserver | null>(null)\r\n\r\n const isNegative = (num: number) => Math.sign(num) === -1\r\n\r\n const totalContainerNum = () => {\r\n const headBarHeight = headBarRef.value?.offsetHeight || 0\r\n const tbBtnHeight = tbBtnRef.value?.$el?.offsetHeight || 0\r\n const paginationHeight = paginationRef.value?.offsetHeight || 0\r\n return Math.round(paginationHeight + headBarHeight + tbBtnHeight)\r\n }\r\n\r\n const resizeObservers = () => {\r\n const element = tableContainerRef.value\r\n if (!element) return\r\n\r\n const containerHeight =\r\n typeof options.tabHeight === 'number'\r\n ? options.tabHeight\r\n : options.heightType === 'height'\r\n ? element.parentElement?.offsetHeight || element.offsetHeight\r\n : parseInt(options.tabHeight as string, 10) || 450\r\n\r\n const maxContainer = !isNaN(containerHeight) ? containerHeight : 450\r\n const minTableNum = maxContainer - totalContainerNum()\r\n const tabContainer = isNegative(minTableNum) ? totalContainerNum() + 300 : maxContainer\r\n\r\n const paginationHeight = paginationRef.value?.offsetHeight || 0\r\n const headBarHeight = headBarRef.value?.offsetHeight || 0\r\n const tbBtnHeight = tbBtnRef.value?.$el?.offsetHeight || 0\r\n\r\n const newHeight =\r\n Math.floor(tabContainer) - Math.round(paginationHeight + headBarHeight + tbBtnHeight)\r\n if (tableHeight.value !== newHeight) {\r\n tableHeight.value = newHeight\r\n }\r\n }\r\n\r\n const startObserver = () => {\r\n nextTick(() => {\r\n if (!tableContainerRef.value || typeof ResizeObserver === 'undefined') return\r\n\r\n observer.value = new ResizeObserver(() => {\r\n requestAnimationFrame(() => {\r\n if (tableContainerRef.value) resizeObservers()\r\n })\r\n })\r\n\r\n const target =\r\n options.heightType === 'height'\r\n ? tableContainerRef.value.parentElement || tableContainerRef.value\r\n : tableContainerRef.value\r\n observer.value.observe(target)\r\n\r\n if (headBarRef.value) {\r\n observer.value.observe(headBarRef.value)\r\n }\r\n })\r\n }\r\n\r\n const stopObserver = () => {\r\n if (observer.value) {\r\n observer.value.disconnect()\r\n observer.value = null\r\n }\r\n }\r\n\r\n onMounted(() => startObserver())\r\n onBeforeUnmount(() => stopObserver())\r\n\r\n return { tableHeight, resizeObservers, startObserver, stopObserver }\r\n}\r\n","/**\r\n * EsTable 跨页选择状态 composable —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异:\r\n * - ref/nextTick 来自 './vue-compat'\r\n * - 选择集合算法 100% 复用 @es-plus/core/table-selection\r\n *\r\n * 实现说明:\r\n * - core 层的 SelectionState 是普通对象,直接 mutate 不会触发响应式\r\n * - 因此本 wrapper 在每次状态变更后调用 sync(),把字段同步到 ref,触发视图更新\r\n * - rowkey 由 wrapper 在闭包中持有,转发给 core 函数\r\n */\r\n\r\nimport { ref, nextTick } from '../vue-compat'\r\nimport {\r\n createSelectionState,\r\n applySelectionChange,\r\n restoreSelectionForPage,\r\n clearAllSelection as coreClearAll,\r\n type TableRefLike,\r\n} from '@es-plus/core'\r\n\r\nexport function useTableSelection(rowkey?: string) {\r\n const state = createSelectionState()\r\n const multipleSelection = ref<Record<string, unknown>[]>([])\r\n const selectionsByPage = ref<Record<number, Record<string, unknown>[]>>({})\r\n const isInitChange = ref(false)\r\n\r\n // 把 core state 的字段同步到 ref —— Vue 2 通过浅拷贝触发响应式\r\n const sync = () => {\r\n multipleSelection.value = [...state.multipleSelection]\r\n selectionsByPage.value = { ...state.selectionsByPage }\r\n isInitChange.value = state.isInitChange\r\n }\r\n\r\n const handleSelectionChange = (val: Record<string, unknown>[], currentPage: number) => {\r\n if (state.isInitChange && rowkey) return\r\n applySelectionChange(state, val, currentPage, rowkey)\r\n sync()\r\n }\r\n\r\n const clearAllSelection = (tableRef: TableRefLike | null) => {\r\n if (!tableRef) {\r\n // 没有 tableRef 时手工重置 state(core 要求 tableRef 非空)\r\n state.multipleSelection = []\r\n state.selectionsByPage = {}\r\n } else {\r\n coreClearAll(state, tableRef)\r\n }\r\n sync()\r\n }\r\n\r\n const initSelection = (dataList: Record<string, unknown>[], tableRef: TableRefLike | null) => {\r\n state.isInitChange = true\r\n sync()\r\n if (!tableRef) {\r\n state.isInitChange = false\r\n sync()\r\n return\r\n }\r\n if (rowkey) {\r\n nextTick(() => {\r\n restoreSelectionForPage(state, dataList, tableRef, rowkey)\r\n state.isInitChange = false\r\n sync()\r\n })\r\n } else {\r\n nextTick(() => {\r\n tableRef.clearSelection?.()\r\n state.isInitChange = false\r\n sync()\r\n })\r\n }\r\n }\r\n\r\n return {\r\n multipleSelection,\r\n selectionsByPage,\r\n isInitChange,\r\n handleSelectionChange,\r\n clearAllSelection,\r\n initSelection,\r\n }\r\n}\r\n","<template>\r\n <div :ref=\"setTableContainer\" class=\"table_component\" :style=\"containerStyle\">\r\n <div class=\"table_containers\">\r\n <div\r\n v-if=\"showHeaderBar\"\r\n ref=\"headBarRef\"\r\n class=\"btn-slot\"\r\n :style=\"slotStyles.type === 'object' ? slotStyles.value : null\"\r\n :class=\"slotStyles.type === 'string' ? slotStyles.value : null\"\r\n >\r\n <div\r\n v-if=\"hasDefaultSlot\"\r\n class=\"headerBar\"\r\n :style=\"{ paddingBottom: hasDefaultSlot ? '10px' : '0px' }\"\r\n >\r\n <slot />\r\n </div>\r\n </div>\r\n\r\n <div\r\n v-loading=\"loadStatus\"\r\n element-loading-background=\"rgba(0, 0, 0, 0.03)\"\r\n element-loading-text=\"努力加载中...\"\r\n class=\"page-loading-con tableContainer\"\r\n >\r\n <div class=\"table_inner_containers\">\r\n <table-btns\r\n v-if=\"(options.configBtn && options.configBtn.length) || options.leftText\"\r\n ref=\"tbBtnRef\"\r\n :instance=\"{ tableRef: instance, formInstance: formInstance }\"\r\n :btn-config=\"options.configBtn\"\r\n :left-text=\"options.leftText\"\r\n />\r\n\r\n <!--\r\n Vue 2 / Element UI 版本不支持虚拟滚动 (Element UI 无 el-table-v2)\r\n 当用户配置 options.virtual === true 时,控制台会警告,仍按普通 el-table 渲染\r\n -->\r\n <el-table\r\n class=\"el-dp_tables\"\r\n :id=\"tableId\"\r\n :key=\"tableId\"\r\n ref=\"tableRef\"\r\n style=\"width: 100%\"\r\n v-bind=\"tableBindAttrs\"\r\n :data=\"dataSource\"\r\n @sort-change=\"changeTableSort\"\r\n @selection-change=\"handleTableSelectionChange\"\r\n >\r\n <template #empty>\r\n <div class=\"ant-empty ant-empty-normal\">\r\n <div class=\"ant-empty-image\">\r\n <svg\r\n class=\"ant-empty-img-simple\"\r\n width=\"64\"\r\n height=\"41\"\r\n viewBox=\"0 0 64 41\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <g transform=\"translate(0 1)\" fill=\"none\" fill-rule=\"evenodd\">\r\n <ellipse\r\n class=\"ant-empty-img-simple-ellipse\"\r\n cx=\"32\"\r\n cy=\"33\"\r\n rx=\"32\"\r\n ry=\"7\"\r\n />\r\n <g class=\"ant-empty-img-simple-g\" fill-rule=\"nonzero\">\r\n <path\r\n d=\"M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z\"\r\n />\r\n <path\r\n d=\"M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z\"\r\n class=\"ant-empty-img-simple-path\"\r\n />\r\n </g>\r\n </g>\r\n </svg>\r\n </div>\r\n <div class=\"ant-empty-description\">暂无数据</div>\r\n </div>\r\n </template>\r\n\r\n <column-item\r\n v-for=\"(cols, index) in filteredColumns\"\r\n :key=\"cols.prop || cols.key || index\"\r\n :cols=\"Object.assign({}, cols, { columnIndex: index })\"\r\n >\r\n <template\r\n v-if=\"cols.scopedSlots && cols.scopedSlots.customRender\"\r\n #[cols.scopedSlots.customRender]=\"{ scope }\"\r\n >\r\n <slot\r\n :name=\"cols.scopedSlots.customRender\"\r\n v-bind=\"\r\n Object.assign({}, cols, {\r\n columnIndex: index,\r\n row: scope.row,\r\n column: scope.column,\r\n })\r\n \"\r\n :scope=\"scope\"\r\n />\r\n </template>\r\n </column-item>\r\n </el-table>\r\n </div>\r\n\r\n <div\r\n v-if=\"showPagination\"\r\n ref=\"paginationRef\"\r\n class=\"pagination_page\"\r\n :style=\"paginationStyle\"\r\n >\r\n <!--\r\n Element UI 与 Element Plus 分页组件 API 差异:\r\n - current-page: .sync 双向绑定 (vs Vue 3 v-model:current-page)\r\n - page-size: .sync 双向绑定\r\n -->\r\n <el-pagination\r\n :background=\"paginationBackground\"\r\n :size=\"paginationIsSmall ? 'small' : paginationConfig.size\"\r\n :total=\"paginationConfig.total\"\r\n :page-size.sync=\"paginationConfig.pageSize\"\r\n :page-sizes=\"paginationPageSizes\"\r\n :current-page.sync=\"paginationConfig.current\"\r\n :layout=\"layout\"\r\n style=\"padding: 0; margin: 10px 0; text-align: center\"\r\n @size-change=\"handleSizeChange\"\r\n @current-change=\"handleIndexChange\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsTable 表格组件 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的核心差异:\r\n * 1. <script setup> → defineComponent + setup(),props/emits/expose 通过返回值与 setup 第二参数实现\r\n * 2. el-pagination 双向绑定从 v-model:current-page → :current-page.sync\r\n * 3. ElConfigProvider 在 Element UI 中不存在 —— 国际化 locale 由用户在 main.js 中\r\n * 通过 Vue.use(ElementUI, { locale }) 全局配置\r\n * 4. 虚拟滚动 (virtual: true) Element UI 无对应 el-table-v2,本版本不支持,\r\n * 仅控制台警告并降级为普通 el-table 渲染\r\n * 5. ElButton 用于操作列时,Element UI 的 type='text' 取代 Element Plus 的 text 属性\r\n * 6. v-loading 指令在 Element UI 中由 Vue.use(ElementUI) 自动注册,无需 ./vLoading 导入\r\n *\r\n * 业务逻辑(请求/分页/选择/列规范化)100% 与 Vue 3 版本保持一致。\r\n */\r\nimport {\r\n defineComponent,\r\n ref,\r\n computed,\r\n watch,\r\n inject,\r\n provide,\r\n getCurrentInstance,\r\n onMounted,\r\n h,\r\n nextTick,\r\n} from '../../vue-compat'\r\nimport {\r\n getGlobalConfig,\r\n isObject,\r\n findValueByKey,\r\n getCallback,\r\n type TableColumn,\r\n type PaginationConfig,\r\n type TableOptions,\r\n} from '@es-plus/core'\r\nimport ColumnItem from './column-item.vue'\r\nimport TableBtns from './table-btns.vue'\r\nimport { useTableResize } from '../../composables/use-table-resize'\r\nimport { useTableSelection } from '../../composables/use-table-selection'\r\nimport { mapSize } from '../../utils/size'\r\n\r\nconst defaultOptions: TableOptions = {\r\n multiSelect: false,\r\n expand: false,\r\n snIndex: false,\r\n loading: false,\r\n border: false,\r\n size: 'small',\r\n headerCellStyle: { background: '#f5f7fa' },\r\n highlightCurrentRow: true,\r\n cachePageSelection: true,\r\n}\r\n\r\n// es-table 内部选项键,不应透传给 el-table\r\nconst TABLE_INTERNAL_KEYS = new Set([\r\n 'multiSelect',\r\n 'expand',\r\n 'snIndex',\r\n 'loading',\r\n 'cachePageSelection',\r\n 'httpRequest',\r\n 'configTableOut',\r\n 'listenToCallBack',\r\n 'apiParams',\r\n 'actionUrl',\r\n 'heightType',\r\n 'tabHeight',\r\n 'isInitRun',\r\n 'entryQuery',\r\n 'configBtn',\r\n 'leftText',\r\n 'rowkey',\r\n 'virtual',\r\n 'engine',\r\n 'rowHeight',\r\n 'estimatedRowHeight',\r\n 'overscanCount',\r\n 'rowClassName',\r\n])\r\n\r\nconst firstWordUpperCase = (str: string): string => {\r\n return str.toLowerCase().replace(/(\\s|^)[a-z]/g, (char) => char.toUpperCase())\r\n}\r\n\r\n/**\r\n * 把 options 中的中划线属性、key/prop 双向映射等规范化为 el-table 可接受的 props\r\n */\r\nconst columnBindAttr = (cols: Record<string, unknown>) => {\r\n const options: Record<string, unknown> = {}\r\n for (const t in cols) {\r\n if (t === 'groups' || t === 'scopedSlots' || t === 'render') continue\r\n\r\n if (t.includes('-')) {\r\n const parts = t.split('-')\r\n let newkey = parts[0]\r\n for (let j = 1; j < parts.length; j++) {\r\n newkey += firstWordUpperCase(parts[j])\r\n }\r\n options[newkey] = cols[t]\r\n } else if (t === 'key') {\r\n options.prop = cols[t]\r\n options[t] = cols[t]\r\n } else {\r\n options[t] = cols[t]\r\n }\r\n }\r\n if (!options.align) {\r\n options.align = 'center'\r\n }\r\n return options\r\n}\r\n\r\nconst checkQueryFields = (obj: Record<string, unknown>): boolean => {\r\n const checkListKey = ['total', 'pageSize', 'current', 'tableData']\r\n if (isObject(obj)) {\r\n return Object.keys(obj).every((it) => {\r\n return checkListKey.find((its) => its === it) && obj[it] && typeof obj[it] === 'string'\r\n })\r\n }\r\n return false\r\n}\r\n\r\nexport default defineComponent({\r\n name: 'EsTable',\r\n components: { ColumnItem, TableBtns },\r\n // 关闭自动 attrs 继承,避免 fallthrough 重复绑定\r\n inheritAttrs: false,\r\n props: {\r\n initTabHeight: { type: Number, default: 400 },\r\n headBarClass: {\r\n type: [String, Object] as unknown as () => string | Record<string, unknown>,\r\n default: '',\r\n },\r\n showHeaderBar: { type: Boolean, default: true },\r\n dataSource: {\r\n type: Array as () => Record<string, unknown>[],\r\n default: () => [],\r\n },\r\n columns: {\r\n type: Array as () => TableColumn[],\r\n default: () => [],\r\n },\r\n options: {\r\n type: Object as () => TableOptions,\r\n default: () => ({ ...defaultOptions }),\r\n },\r\n pagination: {\r\n type: Object as () => PaginationConfig,\r\n default: () => ({}),\r\n },\r\n },\r\n emits: [\r\n 'update:dataSource',\r\n 'update:pagination',\r\n 'pagination-current-change',\r\n 'size-change',\r\n 'change-table-sort',\r\n ],\r\n setup(props, { emit, slots, attrs, expose }) {\r\n // ─── 注入全局配置 ─────────────────────────\r\n const instance = getCurrentInstance() as unknown as Record<string, unknown>\r\n const $esPlusTable =\r\n inject<Record<string, unknown>>(\r\n '$esPlusTable',\r\n null as unknown as Record<string, unknown>\r\n ) ??\r\n ((getGlobalConfig() as Record<string, unknown>).EsTable as Record<string, unknown>) ??\r\n {}\r\n const esPlus =\r\n inject<Record<string, unknown>>('$EsPlus', null as unknown as Record<string, unknown>) ??\r\n (getGlobalConfig() as Record<string, unknown>) ??\r\n {}\r\n\r\n const checkPermission = (pvalue?: string): boolean => {\r\n if (!pvalue) return true\r\n const fn = esPlus.permission\r\n return typeof fn === 'function' ? (fn as (v: string) => boolean)(pvalue) : true\r\n }\r\n\r\n // ─── 虚拟滚动降级 ─────────────────────────\r\n if (props.options.virtual === true || props.options.engine === 'virtual') {\r\n // eslint-disable-next-line no-console\r\n console.warn(\r\n '[@es-plus/vue2] 虚拟滚动 (virtual: true) 在 Vue 2 + Element UI 下不可用,已降级为普通 el-table 渲染。如需虚拟滚动请使用 Vue 3 + Element Plus 版本(@es-plus/vue3)。'\r\n )\r\n }\r\n\r\n // ─── Refs ─────────────────────────────────\r\n const tableRef = ref<any>(null)\r\n const tbBtnRef = ref<any>(null)\r\n const headBarRef = ref<HTMLElement | null>(null)\r\n const paginationRef = ref<HTMLElement | null>(null)\r\n const tableContainerRef = ref<HTMLElement | null>(null)\r\n const tableId = ref(`table_${Math.random().toString(36).substring(2, 12)}`)\r\n const tableData = ref<Record<string, unknown>[]>([])\r\n const columnRowList = ref<TableColumn[]>([...props.columns])\r\n\r\n watch(\r\n () => props.columns,\r\n (val) => {\r\n columnRowList.value = [...val]\r\n },\r\n { deep: true }\r\n )\r\n\r\n const loadingStatus = ref(false)\r\n const slotState = ref(false)\r\n const showPagination = ref(false)\r\n\r\n // Vue 2 函数式 ref:用 :ref=\"setTableContainer\" 避免 ref 被赋值为 string\r\n const setTableContainer = (el: HTMLElement | null) => {\r\n if (el) tableContainerRef.value = el\r\n }\r\n\r\n // ─── 与 EsForm 的耦合 ─────────────────────\r\n const bodyFormInstance = inject<(inst: unknown) => void>('bodyFormInstance', () => {})\r\n const getVisibleShow = inject<(() => boolean) | boolean>('getVisibleShow', false)\r\n\r\n const visibleShow = computed(() =>\r\n typeof getVisibleShow === 'function' ? getVisibleShow() : getVisibleShow\r\n )\r\n\r\n const paginationConfig = ref<PaginationConfig>({\r\n pageSize: 10,\r\n current: 1,\r\n total: 0,\r\n pageSizes: [],\r\n size: 'small',\r\n isSmall: true,\r\n ...props.pagination,\r\n })\r\n\r\n const formInstance = ref<unknown>(null)\r\n\r\n // ─── 计算属性 ──────────────────────────────\r\n const getListEntry = computed(() => {\r\n const eq = props.options.entryQuery\r\n if (eq && isObject(eq) && Object.keys(eq).length) {\r\n return eq\r\n }\r\n return {}\r\n })\r\n\r\n const configTableField = computed(() => {\r\n if (\r\n props.options.configTableOut &&\r\n isObject(props.options.configTableOut) &&\r\n Object.keys(props.options.configTableOut).length &&\r\n checkQueryFields(props.options.configTableOut)\r\n ) {\r\n return props.options.configTableOut\r\n }\r\n\r\n if (\r\n $esPlusTable?.configQueryFieldOutput &&\r\n typeof $esPlusTable.configQueryFieldOutput === 'function'\r\n ) {\r\n const configFields = ($esPlusTable.configQueryFieldOutput as Function)({\r\n total: 'records',\r\n pageSize: 'pageSize',\r\n current: 'pageNo',\r\n tableData: 'rows',\r\n })\r\n if (checkQueryFields(configFields)) return configFields\r\n }\r\n\r\n return {\r\n total: 'records',\r\n pageSize: 'pageSize',\r\n current: 'pageNo',\r\n tableData: 'rows',\r\n }\r\n })\r\n\r\n /**\r\n * 探测 default slot 中是否含 EsForm 实例 —— Vue 2 的 $children 模式\r\n *\r\n * 与 Vue 3 不同:Vue 2 中 vnode 没有 ctx,需要通过 $children 遍历查找。\r\n * 这里采用:等待挂载后,在 instance.$children 中找 name === 'EsForm' 的子组件。\r\n */\r\n const isFormInstance = computed(() => {\r\n const proxy = (instance as any)?.proxy\r\n if (!proxy || !proxy.$children) return {}\r\n const formChild = proxy.$children.find((child: any) => {\r\n const n = child?.$options?.name\r\n return n === 'EsForm'\r\n })\r\n if (formChild) {\r\n formInstance.value = formChild\r\n bodyFormInstance(formChild)\r\n // 返回的对象至少要保证 .props.model 可用\r\n return formChild\r\n }\r\n return {}\r\n })\r\n\r\n const hasDefaultSlot = computed(() => {\r\n // Vue 2 的 slots 是函数集合,调用后取得 vnode 数组\r\n const fn = (slots as any).default\r\n if (typeof fn === 'function') {\r\n const result = fn()\r\n return Array.isArray(result) ? result.length > 0 : !!result\r\n }\r\n // 兼容老式:$slots 是 vnode 数组\r\n const vnodes = (slots as any).default\r\n return Array.isArray(vnodes) && vnodes.length > 0\r\n })\r\n\r\n const heightType = computed(\r\n () => (props.options.heightType || 'auto') as 'auto' | 'height' | 'maxHeight'\r\n )\r\n\r\n const tabHeight = computed(() => {\r\n if (typeof props.options.tabHeight === 'number') {\r\n return `${props.options.tabHeight}px`\r\n }\r\n if (heightType.value === 'height' && typeof props.options.height === 'number') {\r\n return `${props.options.height}px`\r\n }\r\n return '100%'\r\n })\r\n\r\n const containerStyle = computed(() => ({\r\n [heightType.value]: tabHeight.value,\r\n }))\r\n\r\n const slotStyles = computed(() => {\r\n if (props.headBarClass) {\r\n return {\r\n type: typeof props.headBarClass === 'string' ? 'string' : 'object',\r\n value: props.headBarClass,\r\n }\r\n }\r\n return { type: 'string', value: '' }\r\n })\r\n\r\n // ─── 分页布局配置(来自全局 EsTable 配置) ──\r\n const paginationLayoutConfig = computed(() => {\r\n const cfg = $esPlusTable?.paginationLayout\r\n if (!cfg) return null\r\n return typeof cfg === 'function' ? (cfg as Function)() : cfg\r\n })\r\n\r\n const layout = computed(\r\n () =>\r\n (paginationLayoutConfig.value as any)?.layout ||\r\n 'prev, pager, next, jumper, sizes, ->, total'\r\n )\r\n const paginationPageSizes = computed(\r\n () =>\r\n (paginationLayoutConfig.value as any)?.pageSizes ||\r\n paginationConfig.value.pageSizes\r\n )\r\n const paginationIsSmall = computed(\r\n () => (paginationLayoutConfig.value as any)?.isSmall ?? paginationConfig.value.isSmall\r\n )\r\n const paginationBackground = computed(\r\n () => (paginationLayoutConfig.value as any)?.background ?? true\r\n )\r\n\r\n const paginationStyle = computed(() => ({\r\n position: heightType.value === 'height' ? 'absolute' : 'static',\r\n bottom: '0px',\r\n left: '0px',\r\n zIndex: 5,\r\n background: '#fff',\r\n }))\r\n\r\n const loadStatus = computed(() => props.options.loading || loadingStatus.value)\r\n const isRequestConf = computed(\r\n () =>\r\n !!props.options.actionUrl ||\r\n (props.options.apiParams &&\r\n isObject(props.options.apiParams) &&\r\n Object.keys(props.options.apiParams).length > 0)\r\n )\r\n\r\n // ─── 列处理 ────────────────────────────────\r\n const filteredColumns = computed(() => {\r\n const list = columnRowList.value.filter((item) => !item.hidCol)\r\n list.forEach((el) => {\r\n if (\r\n el.prop !== 'operate' &&\r\n el.key !== 'operate' &&\r\n (el.prop || el.key) &&\r\n !el.formatter\r\n ) {\r\n el.formatter = (row: Record<string, unknown>) => {\r\n const value = row[el.prop as string] || row[el.key as string]\r\n if (value == null || value === '') {\r\n return (el.emptyPlaceholder as string) || '-'\r\n }\r\n return value as string\r\n }\r\n }\r\n\r\n if ((el.prop === 'operate' || el.key === 'operate') && el.btns && !el.render) {\r\n el.render = (_h: any, { row }: { row: Record<string, unknown> }) => {\r\n return h('div', [\r\n el.btns\r\n ?.filter((btn: any) => checkPermission(btn.permissionValue))\r\n .map((btn: any) =>\r\n // Element UI text 按钮:type=\"text\" 而非 text 属性\r\n h(\r\n 'el-button',\r\n {\r\n props: {\r\n type: 'text',\r\n },\r\n attrs: {\r\n ...(btn.type ? { 'data-btn-type': btn.type } : {}),\r\n },\r\n on: {\r\n click: () => btn.clickEvent?.(row),\r\n },\r\n },\r\n btn.name\r\n )\r\n ),\r\n ])\r\n }\r\n }\r\n })\r\n\r\n // 当所有列都设置了固定 width 且没有 minWidth 时,把最后一个非固定列的 width 转为 minWidth\r\n const allFixedWidth = list.length > 0 && list.every((col) => col.width && !col.minWidth)\r\n if (allFixedWidth) {\r\n let flexIdx = -1\r\n for (let i = list.length - 1; i >= 0; i--) {\r\n const col = list[i]\r\n if (!col.fixed && col.prop !== 'operate' && col.key !== 'operate') {\r\n flexIdx = i\r\n break\r\n }\r\n }\r\n if (flexIdx === -1) flexIdx = list.length - 1\r\n if (flexIdx >= 0) {\r\n const col = list[flexIdx]\r\n col.minWidth = col.width\r\n delete col.width\r\n }\r\n }\r\n\r\n return list\r\n })\r\n\r\n const tableAttrs = computed(() => {\r\n const merged = columnBindAttr({ ...defaultOptions, ...props.options })\r\n const { align: _align, ...rest } = merged\r\n const result: Record<string, unknown> = {}\r\n for (const key in rest) {\r\n if (!TABLE_INTERNAL_KEYS.has(key)) {\r\n result[key] = rest[key]\r\n }\r\n }\r\n // 把 Element Plus 语义的 size(large/default/small)映射到 Element UI v2 语义\r\n // (medium/small/mini),让两套版本同一份 options 渲染出一致的视觉密度。\r\n // 详见 packages/vue2/src/utils/size.ts。\r\n if (result.size !== undefined) {\r\n const mapped = mapSize(result.size)\r\n if (mapped !== undefined) {\r\n result.size = mapped\r\n }\r\n }\r\n return result\r\n })\r\n\r\n // ─── ResizeObserver 自适应高度 ─────────────\r\n const { tableHeight, resizeObservers } = useTableResize(\r\n tableContainerRef,\r\n headBarRef,\r\n tbBtnRef,\r\n paginationRef,\r\n {\r\n heightType: heightType.value as 'auto' | 'height',\r\n tabHeight: props.options.tabHeight,\r\n }\r\n )\r\n\r\n // 合并 options + fallthrough attrs,供 el-table 使用\r\n const tableBindAttrs = computed(() => {\r\n const result: Record<string, unknown> = { ...tableAttrs.value, ...(attrs as any) }\r\n if (props.options.rowkey) {\r\n result.rowKey = props.options.rowkey\r\n }\r\n if (heightType.value === 'height') {\r\n result.height = tableHeight.value\r\n } else if (heightType.value === 'maxHeight') {\r\n result.maxHeight = tableHeight.value\r\n }\r\n return result\r\n })\r\n\r\n // ─── 选择逻辑 ──────────────────────────────\r\n const {\r\n multipleSelection,\r\n handleSelectionChange,\r\n initSelection,\r\n clearAllSelection: clearAllSelectionInternal,\r\n } = useTableSelection(props.options.rowkey)\r\n\r\n const handleTableSelectionChange = (val: Record<string, unknown>[]) => {\r\n handleSelectionChange(val, paginationConfig.value.current || 1)\r\n }\r\n\r\n // ─── Watchers ─────────────────────────────\r\n watch(visibleShow, async (val, oldVal) => {\r\n if (val && val !== oldVal) {\r\n if (props.options.actionUrl) {\r\n await httpRequestInstance()\r\n }\r\n ;(tableRef.value as any)?.doLayout?.()\r\n }\r\n })\r\n\r\n watch(\r\n () => props.pagination,\r\n (val) => {\r\n paginationConfig.value = { ...paginationConfig.value, ...val }\r\n showPagination.value = val.total !== undefined\r\n },\r\n { deep: true, immediate: true }\r\n )\r\n\r\n watch(\r\n () => props.dataSource,\r\n (val) => {\r\n initSelection(val, tableRef.value)\r\n },\r\n { deep: true }\r\n )\r\n\r\n watch(\r\n tableData,\r\n (val) => {\r\n if (Array.isArray(val)) {\r\n emit('update:dataSource', val)\r\n }\r\n },\r\n { deep: true }\r\n )\r\n\r\n onMounted(() => {\r\n if (isRequestConf.value && props.options.isInitRun !== false) {\r\n httpRequestInstance()\r\n }\r\n // 等待 EsForm 子组件挂载后再触发一次依赖收集\r\n nextTick(() => {\r\n // eslint-disable-next-line no-unused-expressions\r\n isFormInstance.value\r\n })\r\n })\r\n\r\n // ─── 请求逻辑 ──────────────────────────────\r\n const getListenToCallBack = (eventName: string, params: unknown) => {\r\n const cb = props.options.listenToCallBack\r\n if (!cb) return undefined\r\n const fn = getCallback(cb as any, eventName)\r\n if (typeof fn === 'function') {\r\n return fn(params)\r\n }\r\n return undefined\r\n }\r\n\r\n const formatConfigOut = (row: Record<string, unknown>, keyList: string[]) => {\r\n const cf = configTableField.value as Record<string, unknown>\r\n if (isObject(cf) && Object.keys(cf).length) {\r\n Object.entries(cf).forEach(([key, value]) => {\r\n const isKeyUsed = keyList.includes(key)\r\n if (!isKeyUsed) return\r\n\r\n const rowData = row[value as string] ?? findValueByKey(row, value as string)\r\n if (key === 'tableData') {\r\n tableData.value = Array.isArray(rowData) ? rowData : []\r\n } else {\r\n ;(paginationConfig.value as any)[key] =\r\n typeof rowData === 'number' ? rowData : parseInt(rowData as string, 10) || 0\r\n }\r\n })\r\n }\r\n }\r\n\r\n const queryTableListMethod = (\r\n params: Record<string, unknown>,\r\n options: {\r\n success?: (res: Record<string, unknown>) => void\r\n fail?: (err: unknown) => void\r\n } = {}\r\n ) => {\r\n const { success, fail } = options\r\n const apiParams = (props.options?.apiParams || {}) as Record<string, any>\r\n const url = props.options?.actionUrl || apiParams.url || ''\r\n\r\n if (!url || !Object.keys(apiParams).length) return\r\n\r\n // Vue 2 中响应式对象天然是 plain object,无需 toRaw / unref\r\n const formObj = isFormInstance.value as any\r\n const formData =\r\n formObj && formObj.props && formObj.props.model\r\n ? { ...formObj.props.model }\r\n : getListEntry.value || {}\r\n\r\n const fnParams = getListenToCallBack('beforeRequest', {\r\n ...formData,\r\n ...params,\r\n ...(apiParams.model || {}),\r\n })\r\n const finalParams = isObject(fnParams)\r\n ? fnParams\r\n : { ...formData, ...(apiParams.model || {}), ...params }\r\n const requestOption = { ...(apiParams.options || {}) }\r\n if (apiParams?.method) {\r\n requestOption.method = apiParams?.method\r\n }\r\n\r\n const requestHandler = async (requestFn: Function) => {\r\n if (loadingStatus.value) return\r\n loadingStatus.value = true\r\n try {\r\n const res = await requestFn({\r\n url,\r\n formParams: finalParams,\r\n headers: apiParams.headers || {},\r\n ...requestOption,\r\n ...params,\r\n })\r\n const responseData = getListenToCallBack('afterResponse', res) || res\r\n if (\r\n isObject(res) &&\r\n Object.keys(res as object).length &&\r\n typeof success === 'function'\r\n ) {\r\n success(responseData as Record<string, unknown>)\r\n }\r\n } catch (e) {\r\n if (typeof fail === 'function') {\r\n fail(e)\r\n }\r\n } finally {\r\n loadingStatus.value = false\r\n }\r\n }\r\n\r\n if (props.options.httpRequest) {\r\n requestHandler(props.options.httpRequest as Function)\r\n } else if ($esPlusTable.$httpRequest) {\r\n requestHandler($esPlusTable.$httpRequest as Function)\r\n }\r\n }\r\n\r\n const httpRequestInstance = (model?: Record<string, unknown>) => {\r\n return new Promise((resolve, reject) => {\r\n paginationConfig.value.current = 1\r\n queryTableListMethod(\r\n {\r\n ...(model || {}),\r\n pageIndex: paginationConfig.value.current,\r\n pageSize: paginationConfig.value.pageSize,\r\n },\r\n {\r\n success: (res) => {\r\n formatConfigOut(res, ['total', 'tableData'])\r\n if (Object.keys(props.pagination).length) {\r\n emit('update:pagination', paginationConfig.value)\r\n }\r\n resolve(res)\r\n },\r\n fail: (err) => {\r\n reject(err)\r\n },\r\n }\r\n )\r\n })\r\n }\r\n\r\n const changePageIndexRequest = () => {\r\n queryTableListMethod(\r\n {\r\n pageIndex: paginationConfig.value.current,\r\n pageSize: paginationConfig.value.pageSize,\r\n },\r\n {\r\n success: (res) => {\r\n formatConfigOut(res, ['total', 'tableData'])\r\n emit('update:pagination', paginationConfig.value)\r\n emit('pagination-current-change', paginationConfig.value)\r\n },\r\n }\r\n )\r\n }\r\n\r\n const changePageSizeRequest = () => {\r\n queryTableListMethod(\r\n {\r\n pageIndex: paginationConfig.value.current,\r\n pageSize: paginationConfig.value.pageSize,\r\n },\r\n {\r\n success: (res) => {\r\n formatConfigOut(res, ['total', 'tableData'])\r\n emit('update:pagination', paginationConfig.value)\r\n },\r\n }\r\n )\r\n }\r\n\r\n const handleSizeChange = (size: number) => {\r\n paginationConfig.value.pageSize = size\r\n paginationConfig.value.current = 1\r\n if (isRequestConf.value) {\r\n changePageSizeRequest()\r\n } else {\r\n emit('update:pagination', paginationConfig.value)\r\n emit('size-change', paginationConfig.value, size)\r\n }\r\n }\r\n\r\n const handleIndexChange = (val: number) => {\r\n paginationConfig.value.current = val\r\n if (isRequestConf.value) {\r\n changePageIndexRequest()\r\n } else {\r\n emit('update:pagination', paginationConfig.value)\r\n emit('pagination-current-change', paginationConfig.value)\r\n }\r\n }\r\n\r\n const changeTableSort = (column: Record<string, unknown>) => {\r\n emit('change-table-sort', column)\r\n }\r\n\r\n // ─── 提供给子组件的实例 ────────────────────\r\n provide('getTableInstantce', () => ({\r\n tableRef,\r\n toggleSelection: (rows: Record<string, unknown>[]) => {\r\n if (rows) {\r\n rows.forEach((row) => {\r\n ;(tableRef.value as any)?.toggleRowSelection?.(row)\r\n })\r\n } else {\r\n ;(tableRef.value as any)?.clearSelection?.()\r\n }\r\n },\r\n clearAllSelection: () => clearAllSelectionInternal(tableRef.value),\r\n refsInstance: () => tableRef.value,\r\n httpRequestInstance,\r\n }))\r\n\r\n // ─── 暴露方法(Vue 2 通过 expose 或 return) ──\r\n const exposed = {\r\n httpRequestInstance,\r\n getSelectionRows: () => multipleSelection.value,\r\n clearSelection: () => (tableRef.value as any)?.clearSelection?.(),\r\n clearAllSelection: () => clearAllSelectionInternal(tableRef.value),\r\n refresh: () => (tableRef.value as any)?.doLayout?.(),\r\n // virtual 滚动占位(保持 API 一致,Vue 2 版本无效)\r\n scrollToRow: (_row: number) => {\r\n // noop in Vue 2 + Element UI\r\n },\r\n }\r\n\r\n if (typeof expose === 'function') {\r\n expose(exposed)\r\n }\r\n\r\n return {\r\n // refs\r\n tableRef,\r\n tbBtnRef,\r\n headBarRef,\r\n paginationRef,\r\n tableId,\r\n tableData,\r\n // state\r\n loadStatus,\r\n paginationConfig,\r\n formInstance,\r\n // computeds\r\n filteredColumns,\r\n tableBindAttrs,\r\n hasDefaultSlot,\r\n heightType,\r\n tabHeight,\r\n slotStyles,\r\n slotState,\r\n showPagination,\r\n containerStyle,\r\n paginationStyle,\r\n layout,\r\n paginationPageSizes,\r\n paginationIsSmall,\r\n paginationBackground,\r\n // handlers\r\n setTableContainer,\r\n handleTableSelectionChange,\r\n changeTableSort,\r\n handleSizeChange,\r\n handleIndexChange,\r\n // exposed methods (also accessible via $refs.tableRef.xxx in Vue 2)\r\n ...exposed,\r\n instance,\r\n resizeObservers,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.el-dp_tables {\r\n height: auto;\r\n ::v-deep(.el-table__body-wrapper) {\r\n height: auto;\r\n }\r\n}\r\n\r\n.table_component {\r\n width: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: space-between;\r\n align-items: flex-start;\r\n overflow: hidden;\r\n}\r\n\r\n.table_containers {\r\n flex: 1;\r\n width: 100%;\r\n height: 100%;\r\n display: flex;\r\n justify-content: space-between;\r\n flex-direction: column;\r\n align-items: flex-start;\r\n position: relative;\r\n}\r\n\r\n.pagination_page {\r\n width: 100%;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.btn-slot {\r\n width: 100%;\r\n\r\n .headerBar {\r\n box-sizing: border-box;\r\n background-color: #fff;\r\n border-radius: 6px;\r\n\r\n ::v-deep(.el-form-item--small .el-form-item__label) {\r\n box-sizing: border-box;\r\n }\r\n }\r\n}\r\n\r\n.tableContainer {\r\n border-radius: 0px;\r\n transition: all 1.5s;\r\n flex: 1;\r\n width: 100%;\r\n display: flex;\r\n justify-content: space-between;\r\n flex-direction: column;\r\n align-items: flex-start;\r\n\r\n .table_inner_containers {\r\n width: 100%;\r\n }\r\n\r\n ::v-deep(.el-table__empty-block) {\r\n width: 100% !important;\r\n margin: 32px 0;\r\n font-size: 14px;\r\n line-height: 1.5715;\r\n\r\n .el-table__empty-text {\r\n width: auto !important;\r\n }\r\n\r\n .ant-empty-image {\r\n height: 40px;\r\n margin-bottom: 8px;\r\n\r\n .ant-empty-img-simple-ellipse {\r\n fill: #f5f5f5;\r\n }\r\n\r\n .ant-empty-img-simple-g {\r\n stroke: #d9d9d9;\r\n }\r\n\r\n .ant-empty-img-simple-path {\r\n fill: #fafafa;\r\n }\r\n }\r\n\r\n .ant-empty-description {\r\n line-height: 1.5715;\r\n color: rgba(0, 0, 0, 0.25);\r\n }\r\n }\r\n\r\n ::v-deep(.el-tag) {\r\n height: 20px;\r\n padding: 0 7px;\r\n line-height: 20px;\r\n background: #fafafa;\r\n border: none;\r\n border-radius: 4px;\r\n\r\n &.el-tag--info {\r\n color: rgba(0, 0, 0, 0.85);\r\n }\r\n\r\n &.el-tag--success {\r\n color: #52c41a;\r\n background: #f6ffed;\r\n border-color: #b7eb8f;\r\n }\r\n }\r\n}\r\n</style>\r\n","/**\r\n * EsTable 组件入口\r\n *\r\n * 使用方式:\r\n * 1. 默认导入:import EsTable from '@es-plus/vue2/es-table'\r\n * 2. install 安装:通过 Vue.use(EsPlus) 全局注册\r\n *\r\n * Element UI 组件(el-table / el-pagination 等)作为 EsTable 的依赖,\r\n * 由用户在 main.js 中通过 Vue.use(ElementUI) 全局注册。\r\n */\r\n\r\nimport EsTable from './component.vue'\r\nimport type { Vue } from '../../vue-compat'\r\n\r\n;(EsTable as unknown as { install: (V: typeof Vue) => void }).install = function (Vue) {\r\n Vue.component((EsTable as unknown as { name: string }).name || 'EsTable', EsTable)\r\n}\r\n\r\nexport default EsTable\r\nexport { EsTable }\r\n","<script lang=\"ts\">\r\n/**\r\n * EsDialog 内部内容渲染器 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的核心差异:\r\n * - h(...) 是 createElement,签名 `h(tag, data, children)`,data 中区分 props/attrs/on/ref\r\n * - vnode.componentInstance 取代 Vue 3 的 vnode.component(用于回填 currentRef)\r\n * - Element UI 没有 ElConfigProvider,国际化由 Vue.use(ElementUI, { locale }) 全局配置\r\n *\r\n * 职责:\r\n * - 调用用户传入的 render(h, instance, components) → VNode/字符串/组件\r\n * - 把渲染结果挂到 refsObject.currentRef,供 EsDialog 工具栏按钮 click 回调取到\r\n */\r\nimport {\r\n defineComponent,\r\n h,\r\n reactive,\r\n onMounted,\r\n onUpdated,\r\n} from '../../vue-compat'\r\n\r\nexport default defineComponent({\r\n name: 'RenderJsx',\r\n props: {\r\n refs: { type: [Function, Object] as unknown as () => Function | Record<string, unknown>, default: null },\r\n row: { type: Object, default: () => ({}) },\r\n render: { type: Function, default: () => undefined },\r\n model: { type: Object, default: () => ({}) },\r\n instance: { type: Object, default: () => ({}) },\r\n components: { type: Object, default: () => ({}) },\r\n },\r\n setup(props) {\r\n const refsObject =\r\n props.refs && typeof props.refs === 'object'\r\n ? (props.refs as Record<string, unknown>)\r\n : reactive<Record<string, unknown>>({})\r\n\r\n let componentVNode: any = null\r\n\r\n /**\r\n * Vue 2 vnode 结构:\r\n * - 组件 vnode: vnode.componentInstance 是组件实例(即 vm)\r\n * - 普通元素: vnode.elm 是 DOM\r\n */\r\n function flushRef() {\r\n if (!componentVNode) return\r\n const inst = componentVNode.componentInstance\r\n if (!inst) return\r\n ;(refsObject as Record<string, unknown>).currentRef = inst\r\n }\r\n\r\n onMounted(() => flushRef())\r\n onUpdated(() => flushRef())\r\n\r\n return () => {\r\n const { instance } = props as { instance: Record<string, unknown> }\r\n const enhancedInstance = {\r\n ...instance,\r\n registerRef: (name: string, el: unknown) => {\r\n if (el !== null && el !== undefined) {\r\n ;(refsObject as Record<string, unknown>)[name] = el\r\n }\r\n },\r\n getRefs: () => refsObject,\r\n }\r\n\r\n // 调用用户的 render(h, instance, components)\r\n const renderFn = props.render as Function\r\n const renderContent =\r\n renderFn && typeof renderFn === 'function'\r\n ? renderFn(h, enhancedInstance, props.components || {})\r\n : ''\r\n\r\n // 字符串/数字 → 包成 span\r\n if (typeof renderContent === 'string' || typeof renderContent === 'number') {\r\n componentVNode = null\r\n return h(\r\n 'span',\r\n {\r\n ref: 'currentRef',\r\n // Vue 2 的函数式 ref 通过 v-bind 不可直接传,用以下方式赋值\r\n },\r\n [String(renderContent)]\r\n )\r\n }\r\n\r\n // VNode:判断是否为组件(type 不是 string 即视为组件 vnode)\r\n if (renderContent && typeof renderContent === 'object' && 'tag' in renderContent) {\r\n // Vue 2 的组件 vnode tag 形如 'vue-component-1-EsForm',只要存在 componentOptions 就视为组件\r\n const isComponent = !!renderContent.componentOptions\r\n if (isComponent) {\r\n componentVNode = renderContent\r\n return renderContent\r\n }\r\n componentVNode = null\r\n return h('div', [renderContent])\r\n }\r\n\r\n componentVNode = null\r\n // 退化兜底\r\n return h('div', [String(renderContent || '')])\r\n }\r\n },\r\n})\r\n</script>\r\n","<template>\r\n <div class=\"dp-dialog_wrapper\">\r\n <!--\r\n Element UI dialog 与 Element Plus 关键差异:\r\n - 双向绑定::visible.sync (Vue 3 是 v-model)\r\n - 不支持 draggable 属性(Element UI 2.x 无此特性,已去掉传透)\r\n - 全屏:fullscreen 同名属性\r\n - header/footer 槽位写法相同,但不能用 #header (Vue 2.6+ 支持新语法,2.5 及以下需 slot=\"header\")\r\n - 图标改用 i.el-icon-* class 字符串\r\n -->\r\n <el-dialog\r\n :class=\"['dg-dialog', initDialogCls]\"\r\n v-bind=\"filteredAttrs\"\r\n :visible.sync=\"dialogVisible\"\r\n :width=\"typeof width === 'number' ? width + 'px' : width\"\r\n :show-close=\"false\"\r\n :fullscreen=\"filteredAttrs && filteredAttrs.fullscreen != null ? filteredAttrs.fullscreen : isFullscreen\"\r\n :append-to-body=\"appendToBody\"\r\n :modal-append-to-body=\"modalAppendToBody\"\r\n :close-on-click-modal=\"closeOnClickModal\"\r\n :close-on-press-escape=\"closeOnPressEscape\"\r\n :destroy-on-close=\"destroyOnClose\"\r\n :before-close=\"beforeCloseHandler\"\r\n @close=\"onDialogClose\"\r\n @closed=\"onDialogClosed\"\r\n >\r\n <template #title>\r\n <render-jsx\r\n v-if=\"renderHeader && typeof renderHeader === 'function'\"\r\n :render=\"renderHeader\"\r\n :instance=\"getCurrentInstanceModel\"\r\n />\r\n <template v-else>\r\n <div class=\"dialog-header\">\r\n <span class=\"dialog-title\">{{ title }}</span>\r\n <div class=\"btns\">\r\n <i\r\n v-show=\"!hiddenFullBtn\"\r\n :class=\"isFullscreen ? 'el-icon-copy-document' : 'el-icon-full-screen'\"\r\n @click=\"handleFullscreen\"\r\n />\r\n <i class=\"el-icon-close\" @click=\"handleClose\" />\r\n </div>\r\n </div>\r\n </template>\r\n </template>\r\n\r\n <div class=\"dialog_body_layouts\" :style=\"initDialogHeight\">\r\n <render-jsx\r\n v-if=\"render && typeof render === 'function'\"\r\n :refs=\"renderBodyRefsObject\"\r\n :instance=\"getCurrentInstanceModel\"\r\n :render=\"render\"\r\n :components=\"dialogComponents\"\r\n />\r\n </div>\r\n\r\n <template v-if=\"!isHiddenFooter\" #footer>\r\n <span v-if=\"!$slots.footer\" class=\"dialog-footer\">\r\n <render-jsx\r\n v-if=\"renderFooter && typeof renderFooter === 'function'\"\r\n :render=\"renderFooter\"\r\n :instance=\"getCurrentInstanceModel\"\r\n />\r\n <template v-else-if=\"configBtn && configBtn.length\">\r\n <template v-for=\"(it, inx) in configBtn\">\r\n <el-button\r\n v-if=\"checkPermission(it.permissionValue)\"\r\n :key=\"it.key || inx\"\r\n size=\"small\"\r\n v-bind=\"filterOptions(it)\"\r\n :icon=\"getCompIcon(it.icon)\"\r\n :disabled=\"getDisabled(it)\"\r\n @click=\"() => handleBtnClick(it)\"\r\n >\r\n {{ it.name }}\r\n </el-button>\r\n </template>\r\n </template>\r\n </span>\r\n <slot v-else name=\"footer\" />\r\n </template>\r\n </el-dialog>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsDialog 弹窗组件 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的差异(详细列举):\r\n * 1. <script setup> → defineComponent + setup()\r\n * 2. dialog 双向绑定::visible.sync 替代 v-model\r\n * 3. 图标系统:el-icon-* class 字符串替代 Element Plus 图标组件\r\n * 4. ElConfigProvider 不存在 —— 国际化由 Vue.use(ElementUI, { locale }) 全局完成\r\n * 5. draggable 属性在 Element UI 2.x 中不存在,本组件不再支持 isDraggable\r\n * (prop 仍保留兼容,仅传递给底层用户使用,但 el-dialog 会忽略)\r\n * 6. exposed 方法:通过 expose() 或挂到 vm 上(Vue 2 中通过 setup 返回值即可)\r\n *\r\n * 业务能力(render slot/configBtn/全屏/maxHeight/事件)100% 与 Vue 3 版本一致。\r\n */\r\nimport {\r\n defineComponent,\r\n ref,\r\n reactive,\r\n computed,\r\n inject,\r\n provide,\r\n getCurrentInstance,\r\n} from '../../vue-compat'\r\nimport { getGlobalConfig, type BtnConfig } from '@es-plus/core'\r\nimport RenderJsx from './render-jsx.vue'\r\nimport { getCompIcon } from '../../utils/icon'\r\n\r\nexport default defineComponent({\r\n name: 'EsDialog',\r\n components: { RenderJsx },\r\n inheritAttrs: false,\r\n props: {\r\n title: { type: String, default: '' },\r\n visible: { type: Boolean, default: false },\r\n appendTo: { type: [Object, String], default: undefined },\r\n appendToBody: { type: Boolean, default: false },\r\n modalAppendToBody: { type: Boolean, default: true },\r\n closeOnClickModal: { type: Boolean, default: true },\r\n closeOnPressEscape: { type: Boolean, default: true },\r\n destroyOnClose: { type: Boolean, default: false },\r\n hiddenFullBtn: { type: Boolean, default: false },\r\n width: { type: [String, Number], default: '50%' },\r\n // Element UI 不支持 draggable,保留 prop 兼容用户配置但实际不生效\r\n isDraggable: { type: Boolean, default: false },\r\n confirmText: { type: String, default: '' },\r\n cancelText: { type: String, default: '' },\r\n configBtn: { type: Array as () => BtnConfig[], default: () => [] },\r\n maxHeight: { type: [String, Number], default: undefined },\r\n isHiddenFooter: { type: Boolean, default: false },\r\n renderHeader: { type: Function, default: undefined },\r\n renderFooter: { type: Function, default: undefined },\r\n render: { type: Function, default: undefined },\r\n fullscreen: { type: Boolean, default: false },\r\n // 用户透传给 RenderJsx 的额外组件映射(如 EsTable / EsForm 引用)\r\n components: { type: Object, default: () => ({}) },\r\n },\r\n emits: ['update:visible', 'closed', 'submit'],\r\n setup(props, { emit, attrs, slots, expose }) {\r\n const instance = getCurrentInstance() as unknown as Record<string, unknown>\r\n const lyFormInstance = ref<unknown>(null)\r\n const renderBodyRefsObject = reactive<Record<string, unknown>>({})\r\n const isFullscreen = ref(false)\r\n const dialogInstance = instance\r\n\r\n const esPlus =\r\n inject<Record<string, unknown>>('$EsPlus', null as unknown as Record<string, unknown>) ??\r\n (getGlobalConfig() as Record<string, unknown>) ??\r\n {}\r\n\r\n const checkPermission = (pvalue?: string): boolean => {\r\n if (!pvalue) return true\r\n const fn = esPlus.permission\r\n return typeof fn === 'function' ? (fn as (v: string) => boolean)(pvalue) : true\r\n }\r\n\r\n const filterOptions = (it: BtnConfig) => {\r\n const {\r\n icon: _icon,\r\n click: _c,\r\n permissionValue: _p,\r\n name: _n,\r\n disabled: _d,\r\n key: _k,\r\n ...opt\r\n } = it as unknown as Record<string, unknown>\r\n return opt\r\n }\r\n\r\n const getDisabled = (it: BtnConfig): boolean => {\r\n const d = (it as Record<string, unknown>).disabled\r\n if (typeof d === 'function') return (d as () => boolean)()\r\n return !!d\r\n }\r\n\r\n const closeFullscreen = () => {\r\n setTimeout(() => {\r\n if (isFullscreen.value) {\r\n isFullscreen.value = false\r\n }\r\n }, 500)\r\n }\r\n\r\n const handleFullscreen = () => {\r\n if ((attrs as Record<string, unknown>)?.fullscreen) return\r\n isFullscreen.value = !isFullscreen.value\r\n }\r\n\r\n const dialogVisible = computed({\r\n get: () => props.visible || false,\r\n set: (val: boolean) => {\r\n emit('update:visible', val)\r\n if (!val) {\r\n emit('closed', val)\r\n closeFullscreen()\r\n }\r\n },\r\n })\r\n\r\n const handleClose = () => {\r\n // 通过 set dialogVisible 触发 :visible.sync → emit('update:visible', false)\r\n ;(dialogVisible as unknown as { value: boolean }).value = false\r\n emit('closed', false)\r\n closeFullscreen()\r\n }\r\n\r\n const onDialogClose = () => {\r\n // el-dialog @close 触发,与 handleClose 等价\r\n emit('closed', false)\r\n closeFullscreen()\r\n }\r\n\r\n const onDialogClosed = () => {\r\n // 动画结束后触发\r\n }\r\n\r\n /**\r\n * el-dialog 的 before-close 钩子:返回 false 可阻止关闭\r\n * 此处保持开放(done() 调用即关闭)\r\n */\r\n const beforeCloseHandler = (done: () => void) => {\r\n done()\r\n }\r\n\r\n const filteredAttrs = computed(() => ({ ...(attrs as Record<string, unknown>) }))\r\n\r\n const initDialogCls = computed(() => {\r\n if (!isFullscreen.value) {\r\n if (props.maxHeight) return 'dialogShadow'\r\n return 'dialogAuto'\r\n }\r\n return 'dialogFull'\r\n })\r\n\r\n const getMaxContentHeight = () => {\r\n const viewH = typeof window !== 'undefined' ? window.innerHeight : 800\r\n return Math.max(viewH - 135, 200)\r\n }\r\n\r\n const initDialogHeight = computed(() => {\r\n const viewH = getMaxContentHeight()\r\n if (!isFullscreen.value) {\r\n if (props.maxHeight) {\r\n return {\r\n maxHeight:\r\n typeof props.maxHeight === 'number'\r\n ? `${props.maxHeight}px`\r\n : (props.maxHeight as string),\r\n }\r\n }\r\n return { maxHeight: viewH + 'px' }\r\n }\r\n return { height: viewH + 'px' }\r\n })\r\n\r\n const getCurrentInstanceModel = computed(() => ({\r\n renderBodyRefs: (renderBodyRefsObject as Record<string, unknown>).currentRef,\r\n renderBodyRefsObject,\r\n lyFormInstance,\r\n dialogInstance,\r\n getRefs: () => renderBodyRefsObject,\r\n }))\r\n\r\n const handleBtnClick = (it: BtnConfig) => {\r\n const click = (it as Record<string, unknown>).click as Function | undefined\r\n if (typeof click === 'function') {\r\n click((renderBodyRefsObject as Record<string, unknown>).currentRef, {\r\n close: handleClose,\r\n getRefs: (name?: string) => {\r\n if (name)\r\n return (renderBodyRefsObject as Record<string, unknown>)[name] || null\r\n return renderBodyRefsObject\r\n },\r\n dialogInstance,\r\n })\r\n }\r\n }\r\n\r\n // 子组件 EsForm 注册的回调(兼容 EsForm <-> EsDialog 联动)\r\n provide('bodyFormInstance', (e: unknown) => {\r\n lyFormInstance.value = e\r\n })\r\n\r\n // dialogComponents:包给 RenderJsx 的组件映射(Vue 2 没有 Vue 3 的全局 components 注入)\r\n // 用户在 useDialog 调用时若需要 EsTable/EsForm,需自行 import 并通过 components prop 透传\r\n const dialogComponents = computed(() => ({\r\n ...(props.components as Record<string, unknown>),\r\n }))\r\n\r\n const exposed = {\r\n closed: handleClose,\r\n }\r\n if (typeof expose === 'function') {\r\n expose(exposed)\r\n }\r\n\r\n return {\r\n // state\r\n dialogVisible,\r\n isFullscreen,\r\n lyFormInstance,\r\n renderBodyRefsObject,\r\n // computeds\r\n filteredAttrs,\r\n initDialogCls,\r\n initDialogHeight,\r\n getCurrentInstanceModel,\r\n dialogComponents,\r\n // methods\r\n handleClose,\r\n handleFullscreen,\r\n handleBtnClick,\r\n onDialogClose,\r\n onDialogClosed,\r\n beforeCloseHandler,\r\n checkPermission,\r\n filterOptions,\r\n getDisabled,\r\n getCompIcon,\r\n // exposed\r\n ...exposed,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n.dp-dialog_wrapper {\r\n ::v-deep(.dialogAuto) {\r\n margin: 0px !important;\r\n }\r\n ::v-deep(.el-dialog) {\r\n padding: 10px;\r\n\r\n .el-dialog__footer {\r\n padding-top: 0px;\r\n }\r\n\r\n .el-dialog__body {\r\n padding: 10px 0px;\r\n }\r\n\r\n .el-dialog__header {\r\n border-bottom: 1px solid #eee;\r\n display: flex;\r\n padding: 0px 0px 10px 0px;\r\n align-items: center;\r\n justify-content: space-between;\r\n margin: 0;\r\n }\r\n }\r\n}\r\n\r\n.dialog-header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n width: 100%;\r\n}\r\n\r\n.dialog-title {\r\n line-height: 24px;\r\n font-size: 14px;\r\n color: #303133;\r\n font-weight: bold;\r\n}\r\n\r\n.btns {\r\n display: flex;\r\n align-items: center;\r\n\r\n i {\r\n margin-right: 8px;\r\n font-size: 14px;\r\n cursor: pointer;\r\n\r\n &:last-child {\r\n margin-right: 0;\r\n }\r\n }\r\n}\r\n\r\n.dialog_body_layouts {\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n scrollbar-width: thin;\r\n scrollbar-color: #87a2bd26 #c8d5e147;\r\n}\r\n\r\n/* 滚动条样式 */\r\n*::-webkit-scrollbar {\r\n width: 14px;\r\n height: 14px;\r\n}\r\n\r\n*::-webkit-scrollbar-button {\r\n width: 0;\r\n height: 0;\r\n display: none;\r\n}\r\n\r\n*::-webkit-scrollbar-corner {\r\n background-color: transparent;\r\n}\r\n\r\n*::-webkit-scrollbar-thumb {\r\n min-height: 12px;\r\n border: 4px solid transparent;\r\n background-clip: content-box;\r\n border-radius: 7px;\r\n background-color: #c8d5e1;\r\n\r\n &:hover {\r\n background-color: #a8bbcf;\r\n }\r\n\r\n &:active {\r\n background-color: #87a2bd;\r\n }\r\n}\r\n\r\n*::-webkit-scrollbar-track {\r\n background-color: transparent;\r\n}\r\n\r\n*::-webkit-scrollbar-track-piece {\r\n background-color: transparent;\r\n}\r\n</style>\r\n","/**\r\n * useDialog 编程式弹窗 —— Vue 2 版本\r\n *\r\n * 与 Vue 3 实现的核心差异:\r\n * Vue 3: createVNode(Component, props) → render(vNode, container) → 通过 vNode.component.props 修改\r\n * Vue 2: Vue.extend(Component) → new Ctor({ propsData }) → $mount() → 实例方法/$props 修改\r\n *\r\n * 实现策略:\r\n * 1. Vue.extend 把组件定义转为可实例化的构造函数\r\n * 2. new Ctor({ propsData }) 创建实例\r\n * 3. $mount() 后把 $el 追加到 appendTo 元素(默认 document.body)\r\n * 4. 关闭时通过设置 dialogInstance.visible = false 触发动画 + emit closed\r\n * 5. destroy 时调用 $destroy() 并 remove DOM 节点\r\n *\r\n * 与 Vue 3 版本保持一致的对外 API:\r\n * useDialog()(opts) → 默认模式:单例式,重复调用复用同一实例\r\n * useDialog(comp, { onlyInstance: true })(opts) → 每次都创建新实例\r\n *\r\n * 兼容性说明:\r\n * - Vue 2 没有 appContext,但 Vue.extend 创建的实例会继承全局 plugin(如 Vue.use(ElementUI))\r\n * - 依赖注入:useDialog 创建的弹窗组件 与 父组件没有 provide/inject 关系\r\n * 若需要 i18n / 全局配置注入,请通过 props 显式传入\r\n */\r\n\r\nimport { Vue, getCurrentInstance } from '../../vue-compat'\r\nimport EsDialog from './component.vue'\r\nimport type { DialogOptions } from '@es-plus/core'\r\n\r\nexport interface DialogCallable {\r\n (dialogOptions: DialogOptions): unknown\r\n close: () => void\r\n}\r\n\r\nexport interface DialogCallableWithDestroy extends DialogCallable {\r\n destroy: () => void\r\n}\r\n\r\nconst getAppendToElement = (appendTo?: string | HTMLElement): HTMLElement => {\r\n if (typeof appendTo === 'string') {\r\n return (document.querySelector(appendTo) as HTMLElement) || document.body\r\n }\r\n return appendTo instanceof HTMLElement ? appendTo : document.body\r\n}\r\n\r\n/**\r\n * Vue 2 中将 Vue 3 风格的 onXxx 事件回调转为 propsData/$on 监听\r\n *\r\n * Vue 3 用户写法:useDialog()({ onClosed: () => {}, onSubmit: () => {} })\r\n * Vue 2 中需要:把 onClosed → 监听 'closed' 事件,onSubmit → 监听 'submit' 事件\r\n */\r\nconst extractEventHandlers = (\r\n options: Record<string, unknown>\r\n): { propsData: Record<string, unknown>; events: Record<string, Function> } => {\r\n const events: Record<string, Function> = {}\r\n const propsData: Record<string, unknown> = {}\r\n\r\n Object.entries(options).forEach(([key, value]) => {\r\n if (key.startsWith('on') && typeof value === 'function' && key.length > 2) {\r\n // 'onClosed' → 'closed', 'onSubmit' → 'submit', 'onUpdate:visible' → 'update:visible'\r\n const eventName = key.slice(2)\r\n // 'Closed' → 'closed', 保留 'update:visible' 中的 ':'\r\n const normalized = eventName.charAt(0).toLowerCase() + eventName.slice(1)\r\n events[normalized] = value as Function\r\n } else {\r\n propsData[key] = value\r\n }\r\n })\r\n\r\n return { propsData, events }\r\n}\r\n\r\nconst initInstance = (\r\n Component: any,\r\n options: DialogOptions,\r\n appendTo?: string | HTMLElement\r\n) => {\r\n const { propsData, events } = extractEventHandlers(options as Record<string, unknown>)\r\n\r\n // Vue.extend(Component) 把组件定义转为构造函数\r\n const Ctor = (Vue as any).extend(Component)\r\n const vm = new Ctor({ propsData })\r\n\r\n // 注册事件监听(注意:Vue 2 中通过 $on 监听)\r\n Object.entries(events).forEach(([eventName, handler]) => {\r\n vm.$on(eventName, handler)\r\n })\r\n\r\n // $mount() 不传参数 = 创建一个游离的 $el(不挂到 DOM 树)\r\n // 然后我们手工 appendChild 到目标节点\r\n vm.$mount()\r\n const target = getAppendToElement(appendTo)\r\n target.appendChild(vm.$el)\r\n\r\n return vm\r\n}\r\n\r\nexport function useDialog(\r\n Component?: any,\r\n opt?: { onlyInstance?: false }\r\n): DialogCallableWithDestroy\r\nexport function useDialog(Component?: any, opt?: { onlyInstance: true }): DialogCallable\r\nexport function useDialog(Component?: any, opt: { onlyInstance?: boolean } = {}) {\r\n Component = Component || EsDialog\r\n const options = Object.assign({ onlyInstance: false }, opt)\r\n\r\n if (options.onlyInstance) {\r\n // ─── 多实例模式:每次调用都创建新弹窗 ───\r\n let lastVm: any = null\r\n\r\n const close = () => {\r\n if (lastVm) {\r\n lastVm.visible = false\r\n // 等动画结束后销毁\r\n setTimeout(() => {\r\n if (lastVm) {\r\n lastVm.$destroy()\r\n if (lastVm.$el && lastVm.$el.parentNode) {\r\n lastVm.$el.parentNode.removeChild(lastVm.$el)\r\n }\r\n lastVm = null\r\n }\r\n }, 300)\r\n }\r\n }\r\n\r\n const DialogComponent = (dialogOptions: DialogOptions) => {\r\n if (dialogOptions.visible === undefined) {\r\n dialogOptions.visible = true\r\n }\r\n\r\n const originalOnClosed = (dialogOptions as Record<string, unknown>).onClosed as\r\n | Function\r\n | undefined\r\n const originalOnSubmit = (dialogOptions as Record<string, unknown>).onSubmit as\r\n | Function\r\n | undefined\r\n\r\n ;(dialogOptions as Record<string, unknown>).onClosed = (...args: unknown[]) => {\r\n originalOnClosed?.(...args)\r\n close()\r\n }\r\n\r\n ;(dialogOptions as Record<string, unknown>).onSubmit = (closeFn: Function = close) => {\r\n originalOnSubmit?.(closeFn)\r\n }\r\n\r\n lastVm = initInstance(Component, dialogOptions, dialogOptions.appendTo)\r\n return lastVm\r\n }\r\n\r\n DialogComponent.close = close\r\n return DialogComponent\r\n } else {\r\n // ─── 单例模式:复用同一弹窗实例 ───\r\n let vm: any = null\r\n\r\n const close = () => {\r\n if (vm) {\r\n vm.visible = false\r\n }\r\n }\r\n\r\n const destroy = () => {\r\n if (vm) {\r\n vm.$destroy()\r\n if (vm.$el && vm.$el.parentNode) {\r\n vm.$el.parentNode.removeChild(vm.$el)\r\n }\r\n vm = null\r\n }\r\n }\r\n\r\n const DialogComponent = (dialogOptions: DialogOptions) => {\r\n // 已有实例 → 复用并更新 props\r\n if (vm) {\r\n Object.entries(dialogOptions).forEach(([key, value]) => {\r\n if (!key.startsWith('on')) {\r\n vm[key] = value\r\n }\r\n })\r\n vm.visible = true\r\n return vm\r\n }\r\n\r\n const mergedOptions: DialogOptions = {\r\n visible: true,\r\n width: '50%',\r\n destroyOnClose: true,\r\n ...dialogOptions,\r\n } as DialogOptions\r\n\r\n const originalOnClosed = (mergedOptions as Record<string, unknown>).onClosed as\r\n | Function\r\n | undefined\r\n const originalOnSubmit = (mergedOptions as Record<string, unknown>).onSubmit as\r\n | Function\r\n | undefined\r\n\r\n ;(mergedOptions as Record<string, unknown>).onClosed = () => {\r\n originalOnClosed?.()\r\n close()\r\n }\r\n\r\n ;(mergedOptions as Record<string, unknown>).onSubmit = (closeFn: Function = close) => {\r\n originalOnSubmit?.(closeFn)\r\n }\r\n\r\n vm = initInstance(Component, mergedOptions, mergedOptions.appendTo)\r\n return vm\r\n }\r\n\r\n DialogComponent.close = close\r\n DialogComponent.destroy = destroy\r\n return DialogComponent\r\n }\r\n}\r\n\r\nexport default useDialog\r\n","/**\r\n * EsDialog 组件入口\r\n *\r\n * 使用方式:\r\n * 1. 默认导入:import EsDialog, { useDialog } from '@es-plus/vue2/es-dialog'\r\n * 2. install 安装:通过 Vue.use(EsPlus) 全局注册(同时会通过 Vue.prototype.$useDialog 暴露)\r\n */\r\n\r\nimport EsDialog from './component.vue'\r\nimport useDialog from './use-dialog'\r\nimport type { Vue } from '../../vue-compat'\r\n\r\n;(EsDialog as unknown as { install: (V: typeof Vue) => void }).install = function (Vue) {\r\n Vue.component((EsDialog as unknown as { name: string }).name || 'EsDialog', EsDialog)\r\n // 同时挂载到 Vue.prototype,方便 Options API 中通过 this.$useDialog() 调用\r\n ;(Vue as unknown as { prototype: Record<string, unknown> }).prototype.$useDialog = useDialog\r\n}\r\n\r\nexport default EsDialog\r\nexport { EsDialog, useDialog }\r\n","<template>\r\n <div class=\"es-crud-page\">\r\n <!--\r\n Vue 3 → Vue 2 关键差异:\r\n - v-model:data-source → :data-source.sync\r\n - v-model:pagination → :pagination.sync\r\n Vue 2.3+ 支持 .sync 修饰符自动展开为 :data-source + @update:data-source\r\n -->\r\n <es-table\r\n ref=\"tableRef\"\r\n :columns=\"mergedColumns\"\r\n :options=\"mergedOptions\"\r\n :data-source.sync=\"tableData\"\r\n :pagination.sync=\"paginationState\"\r\n v-bind=\"$attrs\"\r\n >\r\n <es-form\r\n v-if=\"schema.formItems && schema.formItems.length\"\r\n ref=\"formRef\"\r\n :model=\"queryModel\"\r\n :form-item-list=\"schema.formItems\"\r\n :config-btn=\"mergedFormBtns\"\r\n :layout-form-props=\"formLayoutProps\"\r\n />\r\n <template v-for=\"(_, name) in $slots\" #[name]=\"slotData\">\r\n <slot :name=\"name\" v-bind=\"slotData || {}\" />\r\n </template>\r\n </es-table>\r\n </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\n/**\r\n * EsCrudPage —— Vue 2 版本\r\n *\r\n * 与 Vue 3 版本的关键差异:\r\n * 1. <script setup> + defineProps/defineEmits/defineExpose → defineComponent + setup()\r\n * 2. v-model:* → .sync 修饰符\r\n * 3. ElMessageBox 替换为:\r\n * a) Element UI 的 MessageBox.confirm(兼容 Vue.use(ElementUI) 全局注册)\r\n * b) 或通过 Vue.prototype.$confirm(同样由 Element UI 全局注册)\r\n * 此处直接 import 'element-ui' 的 MessageBox 以避免依赖原型方法\r\n * 4. useDialog 来自 Vue 2 版本(Vue.extend + $mount)\r\n *\r\n * 业务逻辑(schema 归一化、按钮处理、弹窗管理)100% 与 Vue 3 版本一致。\r\n */\r\nimport { defineComponent, ref, reactive, computed, watch } from '../../vue-compat'\r\nimport { MessageBox } from 'element-ui'\r\nimport EsForm from '../es-form/es-form.vue'\r\nimport EsTable from '../es-table/component.vue'\r\nimport useDialog from '../es-dialog/use-dialog'\r\nimport type {\r\n CrudPageSchema,\r\n CrudBtnConfig,\r\n TableBtnConfig,\r\n OperationColumnConfig,\r\n RowBtnConfig,\r\n CrudDialogConfig,\r\n DialogActionContext,\r\n} from './types'\r\nimport type { BtnConfig, TableColumn } from '@es-plus/core'\r\n\r\nexport default defineComponent({\r\n name: 'EsCrudPage',\r\n components: { EsForm, EsTable },\r\n inheritAttrs: false,\r\n props: {\r\n schema: { type: Object as () => CrudPageSchema, required: true },\r\n httpRequest: {\r\n type: Function as unknown as () => (params: Record<string, unknown>) => Promise<unknown>,\r\n default: undefined,\r\n },\r\n autoLoad: { type: Boolean, default: true },\r\n },\r\n emits: [\r\n 'query',\r\n 'add',\r\n 'edit',\r\n 'delete',\r\n 'view',\r\n 'export',\r\n 'row-click',\r\n 'btn-click',\r\n 'dialog-confirm',\r\n 'dialog-cancel',\r\n 'dialog-open',\r\n ],\r\n setup(props, { emit, expose }) {\r\n const tableRef = ref<any>(null)\r\n const formRef = ref<any>(null)\r\n const tableData = ref<Record<string, unknown>[]>([])\r\n const queryModel = reactive<Record<string, unknown>>({})\r\n\r\n // 同步 schema.formItems → queryModel 默认字段\r\n watch(\r\n () => props.schema.formItems,\r\n (items) => {\r\n if (items) {\r\n items.forEach((item) => {\r\n if (item.prop && !(item.prop in queryModel)) {\r\n ;(queryModel as Record<string, unknown>)[item.prop as string] = ''\r\n }\r\n })\r\n }\r\n },\r\n { immediate: true }\r\n )\r\n\r\n const paginationState = ref({\r\n current: 1,\r\n pageSize: 10,\r\n total: 0,\r\n ...(props.schema.pagination || {}),\r\n })\r\n\r\n // ─── 弹窗归一化(向后兼容旧 dialogFormItems / actions 模式) ─────\r\n const normalizedDialogs = computed<Record<string, CrudDialogConfig>>(() => {\r\n if (props.schema.dialogs) return props.schema.dialogs\r\n if (!props.schema.dialogFormItems?.length) return {}\r\n\r\n const dialogBase = {\r\n width: props.schema.dialogOptions?.width || '600px',\r\n formItems: props.schema.dialogFormItems,\r\n ...(props.schema.dialogOptions || {}),\r\n } as CrudDialogConfig\r\n\r\n const result: Record<string, CrudDialogConfig> = {}\r\n const actions = props.schema.actions || ['add', 'edit', 'delete']\r\n\r\n if (actions.includes('add')) result.add = { ...dialogBase, title: '新增' }\r\n if (actions.includes('edit')) result.edit = { ...dialogBase, title: '编辑' }\r\n if (actions.includes('view'))\r\n result.view = { ...dialogBase, title: '查看', isHiddenFooter: true }\r\n\r\n return result\r\n })\r\n\r\n const normalizedToolbarBtns = computed<CrudBtnConfig[]>(() => {\r\n if (props.schema.toolbarBtns) return props.schema.toolbarBtns\r\n if (props.schema.dialogs || props.schema.operationColumn !== undefined) return []\r\n\r\n const actions = props.schema.actions || ['add', 'edit', 'delete']\r\n const btns: CrudBtnConfig[] = []\r\n\r\n if (actions.includes('add')) {\r\n btns.push({\r\n name: '新增',\r\n type: 'primary',\r\n key: 'add',\r\n icon: 'Plus',\r\n dialogKey: 'add',\r\n } as CrudBtnConfig)\r\n }\r\n if (actions.includes('export')) {\r\n btns.push({\r\n name: '导出',\r\n key: 'export',\r\n icon: 'Download',\r\n actionType: 'export',\r\n } as CrudBtnConfig)\r\n }\r\n if (actions.includes('import')) {\r\n btns.push({\r\n name: '导入',\r\n key: 'import',\r\n icon: 'Upload',\r\n actionType: 'import',\r\n } as CrudBtnConfig)\r\n }\r\n\r\n return btns\r\n })\r\n\r\n const normalizedOperationColumn = computed<OperationColumnConfig | false | undefined>(\r\n () => {\r\n if (props.schema.operationColumn !== undefined) return props.schema.operationColumn\r\n\r\n const actions = props.schema.actions || ['add', 'edit', 'delete']\r\n const hasActionCol = props.schema.columns?.some(\r\n (c) => c.prop === 'action' || c.prop === 'operate' || c.btns\r\n )\r\n if (hasActionCol) return undefined\r\n\r\n const rowActions = actions.filter((a) => ['edit', 'delete', 'view'].includes(a))\r\n if (rowActions.length === 0) return false\r\n\r\n const btns: RowBtnConfig[] = []\r\n if (actions.includes('view'))\r\n btns.push({ name: '查看', type: 'primary', key: 'view', dialogKey: 'view' })\r\n if (actions.includes('edit'))\r\n btns.push({ name: '编辑', type: 'primary', key: 'edit', dialogKey: 'edit' })\r\n if (actions.includes('delete'))\r\n btns.push({\r\n name: '删除',\r\n type: 'danger',\r\n key: 'delete',\r\n confirm: '确定删除该条数据吗?',\r\n })\r\n\r\n return {\r\n label: '操作',\r\n width: btns.length * 80 + 20,\r\n fixed: 'right',\r\n btns,\r\n }\r\n }\r\n )\r\n\r\n // ─── 表单按钮合并 ─────\r\n const mergedFormBtns = computed<BtnConfig[]>(() => {\r\n if (props.schema.queryBtns) return props.schema.queryBtns\r\n\r\n const baseBtns: BtnConfig[] = [\r\n { name: '查询', type: 'primary', key: 'query', triggerEvent: true } as BtnConfig,\r\n { name: '重置', key: 'rest', triggerEvent: true } as BtnConfig,\r\n ]\r\n\r\n const toolbarBtns = normalizedToolbarBtns.value.map((btn) => {\r\n const resolvedBtn: BtnConfig = { ...btn }\r\n if (!(resolvedBtn as Record<string, unknown>).click) {\r\n ;(resolvedBtn as Record<string, unknown>).click = () => handleToolbarBtnClick(btn)\r\n }\r\n return resolvedBtn\r\n })\r\n\r\n return [...baseBtns, ...toolbarBtns]\r\n })\r\n\r\n // ─── 表格列合并(追加操作列) ─────\r\n const mergedColumns = computed<TableColumn[]>(() => {\r\n const cols = [...(props.schema.columns || [])]\r\n const opCol = normalizedOperationColumn.value\r\n\r\n if (opCol === false || opCol === undefined) return cols\r\n\r\n const actionBtns = (opCol as OperationColumnConfig).btns.map((btn) => ({\r\n name: btn.name,\r\n type: btn.type,\r\n permissionValue: btn.permissionValue,\r\n clickEvent: (row: Record<string, unknown>) => handleRowBtnClick(btn, row),\r\n }))\r\n\r\n cols.push({\r\n prop: 'operate',\r\n label: (opCol as OperationColumnConfig).label || '操作',\r\n width:\r\n (opCol as OperationColumnConfig).width || actionBtns.length * 80 + 20,\r\n fixed: ((opCol as OperationColumnConfig).fixed as string) || 'right',\r\n btns: actionBtns,\r\n } as unknown as TableColumn)\r\n\r\n return cols\r\n })\r\n\r\n // ─── 表格工具栏按钮 ─────\r\n const normalizedTableBtns = computed(() => {\r\n if (!props.schema.tableBtns?.length) return []\r\n return props.schema.tableBtns.map((btn: TableBtnConfig) => ({\r\n name: btn.name,\r\n type: btn.type,\r\n size: (btn as Record<string, unknown>).size || 'small',\r\n icon: btn.icon,\r\n code: btn.code || 1,\r\n permissionValue: btn.permissionValue,\r\n loading: (btn as Record<string, unknown>).loading,\r\n disabled: (btn as Record<string, unknown>).disabled,\r\n click: () => handleToolbarBtnClick(btn),\r\n }))\r\n })\r\n\r\n // ─── 表格选项 ─────\r\n const mergedOptions = computed(() => {\r\n const base: Record<string, unknown> = {\r\n border: true,\r\n isInitRun: props.autoLoad,\r\n ...(props.schema.tableOptions || {}),\r\n }\r\n if (props.httpRequest) {\r\n base.httpRequest = props.httpRequest\r\n }\r\n const tBtns = normalizedTableBtns.value\r\n if (tBtns.length > 0) {\r\n const existing = (base.configBtn as unknown[]) || []\r\n base.configBtn = [...existing, ...tBtns]\r\n }\r\n return base\r\n })\r\n\r\n // ─── 表单布局 ─────\r\n const formLayoutProps = computed(() => {\r\n const layout = props.schema.formLayout\r\n if (!layout) return undefined\r\n return {\r\n rowLayProps: { gutter: 16 },\r\n formLayProps: {\r\n labelBtnWidth: layout.labelWidth,\r\n ...(layout.minFoldRows ? { minFoldRows: layout.minFoldRows } : {}),\r\n },\r\n } as Record<string, unknown>\r\n })\r\n\r\n // ─── 工具栏按钮处理 ─────\r\n async function handleToolbarBtnClick(btn: CrudBtnConfig) {\r\n const key = btn.key || btn.actionType || ''\r\n\r\n if (btn.confirm) {\r\n const msg = typeof btn.confirm === 'string' ? btn.confirm : '确定执行此操作吗?'\r\n try {\r\n await MessageBox.confirm(msg, '提示', { type: 'warning' })\r\n } catch {\r\n return\r\n }\r\n }\r\n\r\n if (btn.dialogKey) {\r\n if (key === 'add') emit('add')\r\n openDialog(btn.dialogKey)\r\n return\r\n }\r\n\r\n if (key === 'export' || btn.actionType === 'export') {\r\n emit('export', { ...queryModel })\r\n } else if (key === 'add') {\r\n emit('add')\r\n }\r\n\r\n emit('btn-click', key, { ...queryModel })\r\n }\r\n\r\n // ─── 行按钮处理 ─────\r\n async function handleRowBtnClick(btn: RowBtnConfig, row: Record<string, unknown>) {\r\n const key = btn.key || ''\r\n\r\n if (btn.confirm) {\r\n const msg = typeof btn.confirm === 'string' ? btn.confirm : '确定执行此操作吗?'\r\n try {\r\n await MessageBox.confirm(msg, '提示', { type: 'warning' })\r\n } catch {\r\n return\r\n }\r\n }\r\n\r\n if (btn.click) {\r\n btn.click(row, { refresh, getSelectedRows, openDialog })\r\n return\r\n }\r\n\r\n if (btn.dialogKey) {\r\n openDialog(btn.dialogKey, row)\r\n return\r\n }\r\n\r\n if (key === 'edit') emit('edit', row)\r\n else if (key === 'delete') emit('delete', row)\r\n else if (key === 'view') emit('view', row)\r\n\r\n emit('btn-click', key, row)\r\n }\r\n\r\n // ─── 弹窗管理 ─────\r\n const dialogInstances = new Map<string, ReturnType<typeof useDialog>>()\r\n\r\n function openDialog(key: string, row?: Record<string, unknown>) {\r\n const dialogConfig = normalizedDialogs.value[key]\r\n if (!dialogConfig) return\r\n\r\n emit('dialog-open', key, row)\r\n\r\n const dialog = useDialog()\r\n dialogInstances.set(key, dialog)\r\n\r\n const formData = reactive<Record<string, unknown>>({})\r\n if (dialogConfig.formItems) {\r\n dialogConfig.formItems.forEach((item) => {\r\n if (item.prop) {\r\n ;(formData as Record<string, unknown>)[item.prop] =\r\n row?.[item.prop] ?? ''\r\n }\r\n })\r\n }\r\n\r\n const title =\r\n typeof dialogConfig.title === 'function'\r\n ? (dialogConfig.title as Function)(row)\r\n : dialogConfig.title || ''\r\n\r\n dialogConfig.onOpen?.(row)\r\n\r\n const configBtn = resolveDialogBtns(key, dialogConfig, formData, row || {})\r\n\r\n dialog({\r\n title,\r\n width: dialogConfig.width || '600px',\r\n isDraggable: dialogConfig.isDraggable,\r\n maxHeight: dialogConfig.maxHeight,\r\n fullscreen: dialogConfig.fullscreen,\r\n isHiddenFooter: dialogConfig.isHiddenFooter,\r\n // 用户自定义 render\r\n render: dialogConfig.render\r\n ? (h: any, inst: any) => {\r\n return dialogConfig.render!(h, {\r\n row: row || {},\r\n model: formData,\r\n registerRef: inst.registerRef,\r\n close: () => closeDialog(key),\r\n refresh,\r\n })\r\n }\r\n : dialogConfig.formItems\r\n ? (h: any, { registerRef }: any) => {\r\n /**\r\n * Vue 2 createElement 签名:\r\n * h(Component, { props, attrs, on, ref }, children)\r\n * 通过 ref 字符串拿到子组件,再通过 registerRef 传递回 EsDialog\r\n *\r\n * 但因为 useDialog 创建的是独立 vm,无法直接用字符串 ref 跨实例。\r\n * 改为:在 mounted 钩子里通过 vnode.componentInstance 取到 EsForm 实例。\r\n */\r\n const vnode = h(EsForm, {\r\n props: {\r\n model: formData,\r\n formItemList: dialogConfig.formItems,\r\n layoutFormProps: {\r\n rowLayProps: { gutter: 16 },\r\n formLayProps: {\r\n isBtnHidden: true,\r\n ...(dialogConfig.formLayout || {}),\r\n },\r\n },\r\n },\r\n // Vue 2 函数式 ref:通过 RenderJsx 暴露的 registerRef 注册\r\n ref: 'dialogForm',\r\n })\r\n\r\n // 等组件挂载后,通过 vnode 取到实例并 register\r\n // 由 RenderJsx 的 onMounted/onUpdated 钩子负责把 componentInstance 写入 currentRef\r\n if (vnode && (vnode as any).data) {\r\n ;(vnode as any).data.hook = (vnode as any).data.hook || {}\r\n ;(vnode as any).data.hook.insert = (insertedVnode: any) => {\r\n if (insertedVnode.componentInstance) {\r\n registerRef('dialogForm', insertedVnode.componentInstance)\r\n }\r\n }\r\n }\r\n return vnode\r\n }\r\n : undefined,\r\n configBtn,\r\n // useDialog 的 onClosed 通过 extractEventHandlers 转为 'closed' 事件\r\n onClosed: () => {\r\n dialogInstances.delete(key)\r\n dialogConfig.onClose?.()\r\n },\r\n })\r\n }\r\n\r\n function closeDialog(key: string) {\r\n const dialog = dialogInstances.get(key)\r\n if (dialog) {\r\n dialog.close()\r\n dialogInstances.delete(key)\r\n }\r\n }\r\n\r\n function resolveDialogBtns(\r\n key: string,\r\n config: CrudDialogConfig,\r\n formData: Record<string, unknown>,\r\n row: Record<string, unknown>\r\n ): unknown[] | undefined {\r\n if (config.isHiddenFooter) return undefined\r\n\r\n if (config.configBtn) {\r\n return config.configBtn.map((btn) => {\r\n if (btn.action === 'cancel') {\r\n return {\r\n ...btn,\r\n click: (_: unknown, { close }: any) => {\r\n emit('dialog-cancel', key)\r\n close()\r\n },\r\n }\r\n }\r\n if (btn.action === 'confirm') {\r\n return {\r\n ...btn,\r\n click: async (_: unknown, { close, getRefs }: any) => {\r\n await validateAndConfirm(key, config, formData, row, close, getRefs)\r\n },\r\n }\r\n }\r\n return btn\r\n })\r\n }\r\n\r\n return [\r\n {\r\n name: '取消',\r\n click: (_: unknown, { close }: any) => {\r\n emit('dialog-cancel', key)\r\n close()\r\n },\r\n },\r\n {\r\n name: '确定',\r\n type: 'primary',\r\n click: async (_: unknown, { close, getRefs }: any) => {\r\n await validateAndConfirm(key, config, formData, row, close, getRefs)\r\n },\r\n },\r\n ]\r\n }\r\n\r\n async function validateAndConfirm(\r\n key: string,\r\n config: CrudDialogConfig,\r\n formData: Record<string, unknown>,\r\n row: Record<string, unknown>,\r\n close: () => void,\r\n getRefs: (name?: string) => any\r\n ) {\r\n if (config.formItems?.length) {\r\n const dialogForm = getRefs('dialogForm')\r\n if (dialogForm?.validate) {\r\n await dialogForm.validate()\r\n }\r\n }\r\n\r\n const context: DialogActionContext = { close, refresh, getRefs, row }\r\n\r\n if (config.onConfirm) {\r\n await config.onConfirm(formData, context)\r\n } else {\r\n const legacyKey =\r\n key === 'add' ? 'add-confirm' : key === 'edit' ? 'edit-confirm' : `${key}-confirm`\r\n emit('btn-click', legacyKey, formData)\r\n close()\r\n refresh()\r\n }\r\n\r\n emit('dialog-confirm', key, formData)\r\n }\r\n\r\n // ─── 公共方法 ─────\r\n function refresh() {\r\n ;(tableRef.value as any)?.httpRequestInstance?.()\r\n }\r\n\r\n function getSelectedRows(): Record<string, unknown>[] {\r\n return (tableRef.value as any)?.getSelectionRows?.() || []\r\n }\r\n\r\n const exposed = {\r\n refresh,\r\n getSelectedRows,\r\n tableRef,\r\n formRef,\r\n queryModel,\r\n openDialog,\r\n closeDialog,\r\n }\r\n\r\n if (typeof expose === 'function') {\r\n expose(exposed)\r\n }\r\n\r\n return {\r\n // refs\r\n tableRef,\r\n formRef,\r\n tableData,\r\n queryModel,\r\n paginationState,\r\n // computeds\r\n mergedColumns,\r\n mergedOptions,\r\n mergedFormBtns,\r\n formLayoutProps,\r\n // exposed\r\n ...exposed,\r\n }\r\n },\r\n})\r\n</script>\r\n\r\n<style scoped>\r\n.es-crud-page {\r\n width: 100%;\r\n}\r\n</style>\r\n","/**\r\n * EsCrudPage 组件入口\r\n *\r\n * 使用方式:\r\n * 1. 默认导入:import EsCrudPage from '@es-plus/vue2/es-crud-page'\r\n * 2. install 安装:通过 Vue.use(EsPlus) 全局注册\r\n */\r\n\r\nimport EsCrudPage from './es-crud-page.vue'\r\nimport type { Vue } from '../../vue-compat'\r\n\r\n;(EsCrudPage as unknown as { install: (V: typeof Vue) => void }).install = function (Vue) {\r\n Vue.component(\r\n (EsCrudPage as unknown as { name: string }).name || 'EsCrudPage',\r\n EsCrudPage\r\n )\r\n}\r\n\r\nexport default EsCrudPage\r\nexport { EsCrudPage }\r\nexport type {\r\n CrudPageSchema,\r\n CrudBtnConfig,\r\n TableBtnConfig,\r\n OperationColumnConfig,\r\n RowBtnConfig,\r\n RowBtnContext,\r\n CrudDialogConfig,\r\n DialogRenderContext,\r\n DialogBtnConfig,\r\n DialogActionContext,\r\n CrudAction,\r\n} from './types'\r\n","/**\r\n * @es-plus/vue2 主入口\r\n *\r\n * 与 Vue 3 版本(packages/es-plus)的关键差异:\r\n * 1. install 签名为 (Vue: typeof Vue, options) 而非 (app: App, options)\r\n * 2. 全局组件注册:Vue.component(name, comp) 而非 app.component(name, comp)\r\n * 3. 全局属性注入:Vue.prototype.$xxx 而非 app.config.globalProperties\r\n * 4. 跨组件依赖注入:通过 Vue.mixin 全局 provide,而非 app.provide\r\n *\r\n * 用户使用方式(在 main.js / main.ts 中):\r\n *\r\n * ┌─ Vue 2.7+ ───────────────────────────────────┐\r\n * │ import Vue from 'vue' │\r\n * │ import ElementUI from 'element-ui' │\r\n * │ import 'element-ui/lib/theme-chalk/index.css' │\r\n * │ import EsPlus from '@es-plus/vue2' │\r\n * │ │\r\n * │ Vue.use(ElementUI) │\r\n * │ Vue.use(EsPlus, { permission: (v) => true }) │\r\n * └────────────────────────────────────────────────┘\r\n *\r\n * ┌─ Vue 2.6 ─────────────────────────────────────┐\r\n * │ import Vue from 'vue' │\r\n * │ import VueCompositionAPI from '@vue/composition-api' │\r\n * │ import ElementUI from 'element-ui' │\r\n * │ import EsPlus from '@es-plus/vue2' │\r\n * │ │\r\n * │ Vue.use(VueCompositionAPI) │\r\n * │ Vue.use(ElementUI) │\r\n * │ Vue.use(EsPlus) │\r\n * └────────────────────────────────────────────────┘\r\n *\r\n * 配置示例:\r\n * Vue.use(EsPlus, {\r\n * permission: (value) => userPermissions.includes(value),\r\n * componentSize: 'small',\r\n * skipComponentRegistration: false, // true 时跳过组件全局注册(按需导入场景)\r\n * globalProperties: true, // false 时跳过 Vue.prototype.$useDialog 注入\r\n * })\r\n */\r\n\r\nimport { configureEsPlus } from '@es-plus/core'\r\nimport type { Vue as VueType } from './vue-compat'\r\n\r\nimport EsForm from './components/es-form'\r\nimport EsTable from './components/es-table'\r\nimport EsDialog, { useDialog } from './components/es-dialog'\r\nimport EsCrudPage from './components/es-crud-page'\r\n\r\n// 组件清单(用于全局注册)\r\nconst components = [EsForm, EsTable, EsDialog, EsCrudPage]\r\n\r\ninterface InstallOptions extends Record<string, unknown> {\r\n /** 是否跳过组件的全局注册(按需导入场景下置为 true) */\r\n skipComponentRegistration?: boolean\r\n /** 是否跳过 Vue.prototype 上的全局属性注入(默认 true 注入) */\r\n globalProperties?: boolean\r\n}\r\n\r\n/**\r\n * Vue 2 插件安装函数\r\n *\r\n * 与 Vue 3 版本的安装逻辑保持语义一致:\r\n * - 写入模块级单例(configureEsPlus),让 composable 内部能读到全局配置\r\n * - 全局注册组件(除非 skipComponentRegistration: true)\r\n * - 注入全局属性(Vue.prototype.$useDialog)\r\n * - 通过 Vue.mixin 实现 provide('$EsPlus') 全局可注入\r\n */\r\n/**\r\n * 兼容垫片:把旧 es-eui 的 options 形状归一化为 @es-plus/vue2 期望的扁平形状\r\n *\r\n * 旧 es-eui 形状:\r\n * { EsTable: { methods: { $httpRequest, paginationLayout, configQueryfieldOutput } },\r\n * EsForm: { methods: { $httpRequest, fieldFieldOutput } } }\r\n *\r\n * @es-plus/vue2 形状:\r\n * { EsTable: { $httpRequest, paginationLayout, configQueryFieldOutput },\r\n * EsForm: { $httpRequest, fieldFieldOutput } }\r\n *\r\n * 差异处理:\r\n * 1. 把 .methods 子对象展平到上一层\r\n * 2. 把 configQueryfieldOutput(小写 f)改名为 configQueryFieldOutput(大写 F)\r\n *\r\n * 这样原 es-eui 的 main.js 中 `Vue.use(esEui, { EsTable: { methods: { ... } } })`\r\n * 配置可以一字不改地切换到 `Vue.use(EsPlus, { ... })`。\r\n */\r\nconst normalizeLegacyOptions = (options: InstallOptions): InstallOptions => {\r\n const out: Record<string, unknown> = { ...options }\r\n for (const key of ['EsTable', 'EsForm', 'EsDialog']) {\r\n const sub = out[key] as Record<string, unknown> | undefined\r\n if (!sub || typeof sub !== 'object') continue\r\n const methods = (sub as Record<string, unknown>).methods as\r\n | Record<string, unknown>\r\n | undefined\r\n if (methods && typeof methods === 'object') {\r\n // 展平 methods 到 sub 上(不覆盖已有同名键)\r\n const { methods: _drop, ...rest } = sub as Record<string, unknown>\r\n out[key] = { ...methods, ...rest }\r\n }\r\n // 重命名 configQueryfieldOutput → configQueryFieldOutput\r\n const flat = out[key] as Record<string, unknown>\r\n if (\r\n typeof flat.configQueryfieldOutput === 'function' &&\r\n typeof flat.configQueryFieldOutput !== 'function'\r\n ) {\r\n flat.configQueryFieldOutput = flat.configQueryfieldOutput\r\n }\r\n }\r\n return out as InstallOptions\r\n}\r\n\r\nconst install = (Vue: typeof VueType, options: InstallOptions = {}) => {\r\n // 兼容旧 es-eui options 形状(methods 嵌套 + 字段名差异)\r\n const normalized = normalizeLegacyOptions(options)\r\n\r\n // 写入全局配置单例(permission / 默认 size 等)\r\n configureEsPlus(normalized as any)\r\n\r\n // 全局注册所有组件\r\n if (!normalized.skipComponentRegistration) {\r\n components.forEach((component) => {\r\n const compName = (component as unknown as { name?: string }).name\r\n if (compName) {\r\n Vue.component(compName, component as any)\r\n }\r\n })\r\n }\r\n\r\n if (normalized.globalProperties !== false) {\r\n // 编程式弹窗挂到 Vue.prototype 上,方便 Options API 通过 this.$useDialog() 调用\r\n ;(Vue as unknown as { prototype: Record<string, unknown> }).prototype.$useDialog = useDialog\r\n }\r\n\r\n /**\r\n * Vue 2 没有 app.provide(),但可以通过 Vue.mixin 在每个组件实例上注入 provide:\r\n * Vue.mixin({ provide: { $EsPlus: { ... } } })\r\n *\r\n * 注意:此处的 provide 在 Vue 2 中是函数还是对象都可以。\r\n * 内部组件通过 inject('$EsPlus') 即可拿到(与 Vue 3 版本 API 完全一致)。\r\n */\r\n Vue.mixin({\r\n provide: {\r\n $EsPlus: {\r\n useDialog,\r\n ...normalized,\r\n },\r\n },\r\n })\r\n}\r\n\r\n// ─── 命名导出 ───\r\nexport {\r\n EsForm,\r\n EsTable,\r\n EsDialog,\r\n EsCrudPage,\r\n useDialog,\r\n configureEsPlus,\r\n install,\r\n}\r\n\r\n// ─── 类型导出(与 Vue 3 版本保持完全一致的类型契约) ───\r\nexport type {\r\n CrudPageSchema,\r\n CrudAction,\r\n CrudBtnConfig,\r\n TableBtnConfig,\r\n OperationColumnConfig,\r\n RowBtnConfig,\r\n RowBtnContext,\r\n CrudDialogConfig,\r\n DialogRenderContext,\r\n DialogBtnConfig,\r\n DialogActionContext,\r\n} from './components/es-crud-page'\r\n\r\nexport type {\r\n ModelData,\r\n RenderFn,\r\n AnyVNode,\r\n EsButtonType,\r\n EsButtonSize,\r\n EsTableSize,\r\n ApiParams,\r\n FormType,\r\n FormItemOption,\r\n BtnConfig,\r\n LayoutFormProps,\r\n TableColumn,\r\n ConfigTableOut,\r\n TableOptions,\r\n PaginationConfig,\r\n DialogOptions,\r\n EsFormInstance,\r\n EsTableInstance,\r\n EsPlusOptions,\r\n} from './types'\r\n\r\n// ─── 默认导出(带 install 的对象,可直接 Vue.use()) ───\r\n// NOTE: keep `version` in sync with package.json — __tests__/exports.spec.ts\r\n// asserts equality so a drift fails CI.\r\nexport default {\r\n version: '1.0.2',\r\n install,\r\n}\r\n"],"names":["resolveDataOptions","dataOptions","result","resolveAttrs","row","attrs","buildEventHandlers","defaultInputHandler","userOn","handlers","key","handler","useFormInputs","item","formPutList","h","model","value","getNestedValue","val","setNestedValue","opt","idx","prop","userProps","fileList","isCustomUpload","triggerRender","fileRender","triggerVnode","processSuccess","response","file","list","url","_a","_b","processError","err","httpRequestProp","options","customRequest","res","resp","eventToProp","uploadCallbackProps","propName","newList","f","formtype","direct","flipped","flippedHit","lower","useFormLayout","props","folded","ref","isBtnHidden","computed","fromLay","resolveFormLayProps","legacy","fixed","rowLayout","formLayout","getSetOptionsStatus","getRowColsAlgorithm","coreGetRowColsAlgorithm","getMinFoldRow","camel","isFold","minFoldRow","getBtnColSpan","rowNum","columnRow","lastColumn","btnColSpan","hasSpan","sum","formItem","columnNodeIndex","lastFoldIndex","it","index","watch","useFormRequest","httpRequestGlobal","params","coreQueryTableListMethod","rowsList","fieldFieldOutput","coreGetEveryFormQueryField","keyList","coreFormatConfigOut","coreConfigFormField","SIZE_MAP","mapSize","size","RenderDomForm","defineComponent","createElement","ctx","render","renderContent","RenderBtn","formItemList","formModel","_sfc_main$6","instance","getCurrentInstance","templateRefs","proxy","resolvedModel","rawJsxModel","$esPlusForm","inject","getGlobalConfig","esPlus","_d","_c","checkPermission","pvalue","fn","translateLabel","injectedTableInstant","getTableInstant","isParentTable","t","getCompIcon","filterOptions","_icon","mapped","resolveDisabled","d","formInstance","formItemRowsList","formInputComponents","fieldFieldOutputGlobal","getEveryFormQueryField","formLayoutRef","formProps","merged","loadedApiProps","needLoadList","existing","old","rows","fromApi","r","formItemListFilter","visible","legacyHide","fixedHide","hideFn","autoCount","autoSpan","fixedTotal","remaining","layoutResult","changeFolded","colRightLeftList","isRenderBtn","handleBtnClick","formRef","httpFn","queryTableRequest","clickBtn","initFormItemOptions","opts","style","rest","getFormRef","validate","resolve","maybePromise","valid","e","resetFields","clearValidate","p","validateField","formItmeRequestInstance","propsList","targetItems","apiOption","itemIndex","nextTick","bodyFormFn","EsForm","Vue","RenderDomTb","dataKey","renderResult","error","firstWordUpperCase","str","_sfc_main$5","cols","parts","camelKey","i","RenderDom","_sfc_main$4","hasPermission","_btnList","permFn","processButtonConfig","config","processed","processedBtnLeft","getButtonPosition","processedBtnRight","showContainer","_r","_i","_p","_co","_ih","_n","_s","useTableResize","tableContainerRef","headBarRef","tbBtnRef","paginationRef","tableHeight","observer","isNegative","num","totalContainerNum","headBarHeight","tbBtnHeight","paginationHeight","resizeObservers","element","containerHeight","maxContainer","minTableNum","tabContainer","_e","newHeight","startObserver","target","stopObserver","onMounted","onBeforeUnmount","useTableSelection","rowkey","state","createSelectionState","multipleSelection","selectionsByPage","isInitChange","sync","currentPage","applySelectionChange","tableRef","coreClearAll","dataList","restoreSelectionForPage","defaultOptions","TABLE_INTERNAL_KEYS","char","columnBindAttr","newkey","j","checkQueryFields","obj","checkListKey","isObject","its","_sfc_main$3","ColumnItem","TableBtns","emit","slots","expose","$esPlusTable","tableId","tableData","columnRowList","loadingStatus","slotState","showPagination","setTableContainer","el","bodyFormInstance","getVisibleShow","visibleShow","paginationConfig","getListEntry","eq","configTableField","configFields","isFormInstance","formChild","child","hasDefaultSlot","vnodes","heightType","tabHeight","containerStyle","slotStyles","paginationLayoutConfig","cfg","layout","paginationPageSizes","paginationIsSmall","paginationBackground","paginationStyle","loadStatus","isRequestConf","filteredColumns","_h","btn","col","flexIdx","tableAttrs","_align","tableBindAttrs","handleSelectionChange","initSelection","clearAllSelectionInternal","handleTableSelectionChange","oldVal","httpRequestInstance","getListenToCallBack","eventName","cb","getCallback","formatConfigOut","cf","rowData","findValueByKey","queryTableListMethod","success","fail","apiParams","formObj","formData","fnParams","finalParams","requestOption","requestHandler","requestFn","responseData","reject","changePageIndexRequest","changePageSizeRequest","handleSizeChange","handleIndexChange","changeTableSort","column","provide","exposed","_row","EsTable","_sfc_main$2","refsObject","reactive","componentVNode","flushRef","inst","onUpdated","enhancedInstance","name","renderFn","_sfc_main$1","RenderJsx","lyFormInstance","renderBodyRefsObject","isFullscreen","dialogInstance","_k","getDisabled","closeFullscreen","handleFullscreen","dialogVisible","handleClose","onDialogClose","onDialogClosed","beforeCloseHandler","done","filteredAttrs","initDialogCls","getMaxContentHeight","viewH","initDialogHeight","getCurrentInstanceModel","click","dialogComponents","getAppendToElement","appendTo","extractEventHandlers","events","propsData","normalized","initInstance","Component","Ctor","vm","useDialog","EsDialog","lastVm","close","DialogComponent","dialogOptions","originalOnClosed","originalOnSubmit","args","closeFn","destroy","mergedOptions","_sfc_main","queryModel","items","paginationState","normalizedDialogs","dialogBase","actions","normalizedToolbarBtns","btns","normalizedOperationColumn","c","a","mergedFormBtns","baseBtns","toolbarBtns","resolvedBtn","handleToolbarBtnClick","mergedColumns","opCol","actionBtns","handleRowBtnClick","normalizedTableBtns","base","tBtns","formLayoutProps","msg","MessageBox","openDialog","refresh","getSelectedRows","dialogInstances","dialogConfig","dialog","title","configBtn","resolveDialogBtns","closeDialog","registerRef","vnode","insertedVnode","_","getRefs","validateAndConfirm","dialogForm","context","legacyKey","EsCrudPage","components","normalizeLegacyOptions","out","sub","methods","_drop","flat","install","configureEsPlus","component","compName"],"mappings":"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"}