@es-plus/vue2 1.1.2 → 1.1.4

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/vue-compat.ts","../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 兼容层 —— 运行时按 Vue 版本动态切换 Composition API 来源\r\n *\r\n * 行为:\r\n * - Vue 2.7+:使用 vue 原生导出的 Composition API(ref / reactive / inject / ...)\r\n * - Vue 2.6.x:使用 @vue/composition-api 的 polyfill\r\n *\r\n * 为什么不直接从 '@vue/composition-api' 静态 re-export:\r\n * 官方说明里 @vue/composition-api 1.7+ 在 Vue 2.7 下应通过 postinstall 自动\r\n * redirect 到原生 API,但在 monorepo / npm workspace / file: 协议安装时\r\n * postinstall 经常不执行,导致 dist 仍然是完整 polyfill。结果在 Vue 2.7 项目里\r\n * 原生 setup 与 polyfill 的 wrappedData 双双激活,setup 被调用两次,触发:\r\n * \"[Vue warn]: The setup binding property xxx is already declared\"\r\n * \"[Vue warn]: inject() can only be used inside setup() or functional components.\"\r\n *\r\n * 不使用 vue-demi 的原因:\r\n * vue-demi 的 postinstall 在嵌套 node_modules 安装时会解析到本包的 devDependency\r\n * vue@2.7 而非用户项目的 vue 版本,生成错误的 lib(在 Vue 2.6 项目里产生\r\n * \"export 'xxx' was not found in 'vue'\" 报错)。\r\n *\r\n * 本文件的策略:在模块加载时读取 `Vue.version`,按 major.minor 选择正确的来源。\r\n * 两个候选源都通过静态 import 引入,构建器可以分析;运行时只有一份会被实际使用。\r\n */\r\n\r\nimport Vue from 'vue'\r\nimport * as VueNative from 'vue'\r\nimport * as CompositionApiPolyfill from '@vue/composition-api'\r\n\r\n// 解析 Vue 版本\r\nconst versionString: string = (Vue as unknown as { version?: string }).version || ''\r\nconst [majorStr = '0', minorStr = '0'] = versionString.split('.')\r\nconst major = Number(majorStr)\r\nconst minor = Number(minorStr)\r\n\r\n/** Vue 2.7+ 原生支持 Composition API,无需 polyfill */\r\nexport const isVue27Plus: boolean = major === 2 && minor >= 7\r\n\r\n// 选择实际使用的 API 源:\r\n// Vue 2.7+ → 原生(VueNative.ref 等)\r\n// Vue 2.6 → polyfill(CompositionApiPolyfill.ref 等)\r\n//\r\n// 注意:在 Vue 2.6 环境里 VueNative 上不会有 ref / reactive 等键,但因为\r\n// isVue27Plus 为 false,永远不会读到这些 undefined。反向同理。\r\nconst api: typeof CompositionApiPolyfill = (\r\n isVue27Plus ? VueNative : CompositionApiPolyfill\r\n) as typeof CompositionApiPolyfill\r\n\r\n// ─── Composition API 命名导出 ───\r\n//\r\n// 不能用 `export const ref = api.ref` 这种顶层重新声明,因为部分构建器\r\n// (特别是 ES 模块 named export)只允许从单一静态源 re-export,不允许动态。\r\n// 为此我们把每个 API 包成一个变量声明 + export 语句:\r\n//\r\n// const _ref = api.ref\r\n// export { _ref as ref }\r\n//\r\n// 这样 TypeScript 不会做静态 re-export 树摇,但能正确通过类型检查。\r\n\r\nconst _ref = api.ref\r\nconst _reactive = api.reactive\r\nconst _computed = api.computed\r\nconst _watch = api.watch\r\nconst _watchEffect = api.watchEffect\r\nconst _onMounted = api.onMounted\r\nconst _onUnmounted = api.onUnmounted\r\nconst _onBeforeUnmount = api.onBeforeUnmount\r\nconst _onBeforeMount = api.onBeforeMount\r\nconst _onUpdated = api.onUpdated\r\nconst _onActivated = api.onActivated\r\nconst _onDeactivated = api.onDeactivated\r\nconst _defineComponent = api.defineComponent\r\nconst _inject = api.inject\r\nconst _provide = api.provide\r\nconst _nextTick = api.nextTick\r\nconst _getCurrentInstance = api.getCurrentInstance\r\nconst _toRefs = api.toRefs\r\nconst _toRef = api.toRef\r\nconst _unref = api.unref\r\nconst _isRef = api.isRef\r\n// `h` 的类型在 @vue/composition-api 内部使用了未导出的命名空间 `H`,\r\n// 直接 const _h = api.h 会触发 TS4023 (Exported variable uses unnameable type)。\r\n// 用 typeof CompositionApiPolyfill.h 把类型固定到一个可命名的外部符号上。\r\nconst _h: typeof CompositionApiPolyfill.h = api.h\r\n\r\nexport {\r\n _ref as ref,\r\n _reactive as reactive,\r\n _computed as computed,\r\n _watch as watch,\r\n _watchEffect as watchEffect,\r\n _onMounted as onMounted,\r\n _onUnmounted as onUnmounted,\r\n _onBeforeUnmount as onBeforeUnmount,\r\n _onBeforeMount as onBeforeMount,\r\n _onUpdated as onUpdated,\r\n _onActivated as onActivated,\r\n _onDeactivated as onDeactivated,\r\n _defineComponent as defineComponent,\r\n _inject as inject,\r\n _provide as provide,\r\n _nextTick as nextTick,\r\n _getCurrentInstance as getCurrentInstance,\r\n _toRefs as toRefs,\r\n _toRef as toRef,\r\n _unref as unref,\r\n _isRef as isRef,\r\n _h as h,\r\n}\r\n\r\n/** 暴露 polyfill plugin(default export)给 install() 在 Vue 2.6 下按需安装 */\r\nexport const VueCompositionAPIPlugin: unknown =\r\n (CompositionApiPolyfill as unknown as { default?: unknown }).default ??\r\n CompositionApiPolyfill\r\n\r\n// Vue 构造器必须从 'vue' 直接导入:\r\n// @vue/composition-api 的 default export 是 plugin({ install }),\r\n// 没有 .extend / .component 等静态方法,useDialog 内部 Vue.extend(...) 会报错。\r\nexport { default as Vue } from 'vue'\r\n\r\n// 类型导出:Vue 2.7+ 与 @vue/composition-api 的类型定义结构兼容,\r\n// 这里统一从 polyfill 包导出,避免 Vue 2.6 下 'vue' 没有这些类型导致编译失败。\r\nexport type { PropType, Ref, ComputedRef, WatchSource } from '@vue/composition-api'\r\n\r\n/**\r\n * Vue 2 constructor type that includes static methods\r\n * (component, mixin, use, prototype) which @vue/composition-api's\r\n * type definitions omit.\r\n *\r\n * Use this instead of `typeof Vue` in install function signatures.\r\n */\r\nexport interface Vue2Constructor {\r\n version?: string\r\n component(name: string, component?: any): any\r\n mixin(mixin: Record<string, any>): void\r\n use(plugin: any, ...options: any[]): any\r\n prototype: Record<string, any>\r\n}\r\n","/**\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=\"resolvedModel\"\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=\"resolvedModel\"\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=\"resolvedModel\"\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 } 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: any) => any)\r\n | undefined\r\n const { getEveryFormQueryField } = useFormRequest(httpRequestGlobal)\r\n\r\n // ─── formProps (供 el-form 使用) ──\r\n const formLayoutRef = ref<Record<string, unknown>>(\r\n ((props.layoutFormProps as { fromLayProps?: Record<string, unknown> } | undefined)?.fromLayProps) || {}\r\n )\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 formInputComponents,\r\n formInstance,\r\n // 注意:不要在 setup return 中暴露与 props 同名的 key(configBtn / model /\r\n // btnColSpanRow / renderBtn)——Vue 2 已自动把 props 挂到 vm 实例,\r\n // 重复暴露会在 @vue/composition-api 下触发 \"already declared as a prop\" 警告。\r\n // 模板中的 :model 引用 resolvedModel(用于解析 v-model 兼容),其它 props 直接使用名称。\r\n resolvedModel,\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 { Vue2Constructor } 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: Vue2Constructor) => 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 // 主动触发一次计算,避免依赖 ResizeObserver 的首次回调(某些环境不触发)。\r\n resizeObservers()\r\n\r\n if (headBarRef.value) {\r\n observer.value.observe(headBarRef.value)\r\n }\r\n if (paginationRef.value) {\r\n observer.value.observe(paginationRef.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=\"tableContainerEl\" 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=\"slotStyleValue\"\r\n :class=\"slotClassValue\"\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 <!--\r\n v-on=\"$listeners\" 把宿主在 <es-table> 上写的所有监听器透传到 <el-table>,\r\n 让 row-click / cell-click / select / header-click 等 Element UI Table 原生事件\r\n 能直接被使用方监听。Vue 2 的 _g 会把 $listeners 与下面显式的 @sort-change /\r\n @selection-change 合并为数组,不会覆盖我们的内部处理。\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 v-on=\"$listeners\"\r\n :data=\"effectiveDataSource\"\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 </div>\r\n\r\n <!--\r\n 分页区域放在 v-loading 元素之外(作为 .table_containers 的子元素),\r\n 以避免 loading mask(z-index 2000)遮挡分页;\r\n 分页用 static 定位(默认)参与 flex 列布局,使 .tableContainer (flex:1) 自动让出空间。\r\n -->\r\n <div\r\n v-if=\"showPagination\"\r\n ref=\"paginationRef\"\r\n class=\"pagination_page\"\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 :prev-text=\"paginationPrevText\"\r\n :next-text=\"paginationNextText\"\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</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 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\r\n // Effective data source: 内部 tableData 优先(接口请求的数据),\r\n // 兼容父组件不使用 .sync 但又希望看到接口拉取数据的场景。\r\n // 当父组件传入了非空 dataSource 且内部 tableData 为空时,使用 dataSource。\r\n const effectiveDataSource = computed(() => {\r\n if (tableData.value && tableData.value.length) return tableData.value\r\n return props.dataSource\r\n })\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 + @vue/composition-api 下函数式 ref `:ref=\"setterFn\"` 在 SFC 模板中\r\n // 不会被运行时调用(已知兼容性问题)。改用字符串 ref(模板中 ref=\"xxx\"),\r\n // 在 onMounted 内通过 vm.$refs.xxx 手动同步到 setup 中的 ref 变量。\r\n // 这是 Vue 2 + composition-api 下 100% 可靠的 DOM 引用方式。\r\n const syncDomRefs = () => {\r\n const proxy = (instance as any)?.proxy\r\n if (!proxy || !proxy.$refs) return\r\n tableContainerRef.value = (proxy.$refs.tableContainerEl as HTMLElement) || null\r\n headBarRef.value = (proxy.$refs.headBarRef as HTMLElement) || null\r\n paginationRef.value = (proxy.$refs.paginationRef as HTMLElement) || null\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 /** Typed style/class for header bar slot — avoids Vue StyleValue type mismatch in template */\r\n const slotStyleValue = computed<Record<string, string | number>>(() => {\r\n const s = slotStyles.value\r\n if (s.type === 'object' && s.value && typeof s.value === 'object') {\r\n return s.value as Record<string, string | number>\r\n }\r\n return {}\r\n })\r\n const slotClassValue = computed<string>(() => {\r\n const s = slotStyles.value\r\n return s.type === 'string' ? (s.value as string) : ''\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 // prev/next 文字:未配置时返回空字符串,让 el-pagination 渲染默认 ‹/› 箭头\r\n const paginationPrevText = computed(\r\n () => ((paginationLayoutConfig.value as any)?.prevText as string) || ''\r\n )\r\n const paginationNextText = computed(\r\n () => ((paginationLayoutConfig.value as any)?.nextText as string) || ''\r\n )\r\n\r\n const paginationStyle = computed(() => ({\r\n position: heightType.value === 'height' ? ('absolute' as const) : ('static' as const),\r\n bottom: '0px',\r\n left: '0px',\r\n // z-index 必须高于 element-loading 蒙层(默认 2000),否则请求加载过程中分页会被蒙层遮挡。\r\n zIndex: 2001,\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 // 兼容性修复:在 Vue 2.6 + @vue/composition-api 下,watch(() => props.pagination, ...)\r\n // 即使比对相同也会因为父组件 .sync 回传引发 watcher 触发 → 父组件 render watcher 循环。\r\n // 解决:emit 前先更新 lastPaginationStr,watcher 收到回传时序列化相同则 return。\r\n let lastPaginationStr = JSON.stringify(props.pagination || {})\r\n if (props.pagination && Object.keys(props.pagination).length) {\r\n paginationConfig.value = { ...paginationConfig.value, ...props.pagination }\r\n showPagination.value = (props.pagination as PaginationConfig).total !== undefined\r\n }\r\n /** Emit pagination 更新,并预先记录序列化值以阻断 .sync 回传循环 */\r\n const emitPaginationUpdate = () => {\r\n const snapshot = { ...paginationConfig.value }\r\n lastPaginationStr = JSON.stringify(snapshot)\r\n emit('update:pagination', snapshot)\r\n }\r\n watch(\r\n () => props.pagination,\r\n (val: PaginationConfig) => {\r\n const str = JSON.stringify(val || {})\r\n if (str === lastPaginationStr) return\r\n lastPaginationStr = str\r\n paginationConfig.value = { ...paginationConfig.value, ...val }\r\n showPagination.value = val.total !== undefined\r\n }\r\n )\r\n\r\n // 兼容性修复:移除 deep,仅监听数组引用变化即可触发 selection 重置。\r\n // .sync 回传相同引用时不会重复触发,避免循环。\r\n watch(\r\n () => props.dataSource,\r\n (val) => {\r\n initSelection(val, tableRef.value)\r\n }\r\n )\r\n\r\n // 兼容性修复:避免 Vue 2.6 + @vue/composition-api 下 .sync 双向绑定循环。\r\n // 仅在 tableData 引用变化时 emit,去掉 deep;并通过 lastEmittedRef 跳过\r\n // 「外部 .sync 回传 → props.dataSource 变化 → 内部赋值 → emit 再次回传」的循环。\r\n let lastEmittedTableData: unknown = null\r\n watch(tableData, (val) => {\r\n if (!Array.isArray(val)) return\r\n if (val === lastEmittedTableData) return\r\n lastEmittedTableData = val\r\n emit('update:dataSource', val)\r\n })\r\n\r\n onMounted(() => {\r\n // 立即同步一次 vm.$refs 到 setup 中的 ref 变量\r\n syncDomRefs()\r\n if (isRequestConf.value && props.options.isInitRun !== false) {\r\n httpRequestInstance()\r\n }\r\n // 等待所有子元素(含 pagination / EsForm)挂载完成后再同步并重算高度。\r\n nextTick(() => {\r\n syncDomRefs()\r\n // eslint-disable-next-line no-unused-expressions\r\n isFormInstance.value\r\n if (typeof requestAnimationFrame !== 'undefined') {\r\n requestAnimationFrame(() => {\r\n syncDomRefs()\r\n resizeObservers()\r\n })\r\n } else {\r\n resizeObservers()\r\n }\r\n })\r\n })\r\n\r\n // ─── 请求逻辑 ──────────────────────────────\r\n const getListenToCallBack = (eventName: string, params: unknown) => {\r\n const eventNameList = [\r\n { eventName: 'brcb', isReturn: true },\r\n { eventName: 'qrcb', isReturn: true },\r\n ]\r\n const hasEventNameIndex = eventNameList.findIndex((it) => it.eventName === eventName)\r\n if (\r\n props.options.listenToCallBack &&\r\n (props.options.listenToCallBack as any)[eventName] &&\r\n hasEventNameIndex !== -1\r\n ) {\r\n const callObj = eventNameList[hasEventNameIndex]\r\n if (callObj.isReturn) {\r\n return (props.options.listenToCallBack as any)[eventName](params)\r\n }\r\n }\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 // 累积所有 pagination 字段更新,最后一次性整体替换 paginationConfig.value,\r\n // 避免直接 paginationConfig.value[key] = x 触发多次 setter / 多轮渲染。\r\n const paginationPatch: Record<string, unknown> = {}\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 paginationPatch[key] =\r\n typeof rowData === 'number' ? rowData : parseInt(rowData as string, 10) || 0\r\n }\r\n })\r\n if (Object.keys(paginationPatch).length) {\r\n paginationConfig.value = { ...paginationConfig.value, ...paginationPatch }\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('brcb', {\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('qrcb', 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 = { ...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 emitPaginationUpdate()\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 emitPaginationUpdate()\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 emitPaginationUpdate()\r\n },\r\n }\r\n )\r\n }\r\n\r\n const handleSizeChange = (size: number) => {\r\n paginationConfig.value = { ...paginationConfig.value, pageSize: size, current: 1 }\r\n if (isRequestConf.value) {\r\n changePageSizeRequest()\r\n } else {\r\n emitPaginationUpdate()\r\n emit('size-change', paginationConfig.value, size)\r\n }\r\n }\r\n\r\n const handleIndexChange = (val: number) => {\r\n paginationConfig.value = { ...paginationConfig.value, current: val }\r\n if (isRequestConf.value) {\r\n changePageIndexRequest()\r\n } else {\r\n emitPaginationUpdate()\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 effectiveDataSource,\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 slotStyleValue,\r\n slotClassValue,\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 paginationPrevText,\r\n paginationNextText,\r\n // handlers\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 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 { Vue2Constructor } from '../../vue-compat'\r\n\r\n;(EsTable as unknown as { install: (V: Vue2Constructor) => 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 { Vue2Constructor } from '../../vue-compat'\r\n\r\n;(EsDialog as unknown as { install: (V: Vue2Constructor) => 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 ): BtnConfig[] | 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 { Vue2Constructor } from '../../vue-compat'\r\n\r\n;(EsCrudPage as unknown as { install: (V: Vue2Constructor) => 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 版本,用户都不需要手动 `Vue.use(VueCompositionAPI)`:\r\n * - Vue 2.7+:本库的 vue-compat 直接使用 vue 原生 Composition API\r\n * - Vue 2.6:本库 install() 会自动调用 `Vue.use(VueCompositionAPI)` 安装 polyfill\r\n *\r\n * ┌─ Vue 2.6 / 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.7 项目中**不要**额外 `Vue.use(VueCompositionAPI)`,否则原生 setup\r\n * 与 polyfill 的 wrappedData 会双重执行,本库 install 会发出警告。\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 { Vue2Constructor } from './vue-compat'\r\nimport { isVue27Plus, VueCompositionAPIPlugin } 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: Vue2Constructor, options: InstallOptions = {}) => {\r\n // 自动管理 @vue/composition-api 安装:\r\n // - Vue 2.6.x:必须装 polyfill,否则库内 setup / inject / ref 等无法工作\r\n // - Vue 2.7+:原生支持 Composition API,不应安装 polyfill;如已被用户主动\r\n // `Vue.use(VueCompositionAPI)`,原生 setup 与 polyfill 的 wrappedData 会双重\r\n // 执行,导致 \"setup binding ... already declared\" 与 \"inject() outside setup\"\r\n // 等告警。这里只能发警告,无法在运行时卸载 plugin。\r\n const alreadyInstalled = (Vue as unknown as Record<string, unknown>).__composition_api_installed__ === true\r\n if (!isVue27Plus) {\r\n if (!alreadyInstalled && VueCompositionAPIPlugin) {\r\n Vue.use(VueCompositionAPIPlugin as any)\r\n }\r\n } else if (alreadyInstalled) {\r\n // eslint-disable-next-line no-console\r\n console.warn(\r\n '[@es-plus/vue2] Vue 2.7+ detected together with @vue/composition-api plugin already installed. ' +\r\n 'This causes setup() to run twice (once natively, once via the polyfill\\'s data() wrapper) and ' +\r\n 'will produce \"setup binding ... already declared\" warnings. Remove `Vue.use(VueCompositionAPI)` ' +\r\n 'from your main.js — Vue 2.7 has Composition API natively.',\r\n )\r\n }\r\n\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.1.2',\r\n install,\r\n}\r\n"],"names":["versionString","Vue","majorStr","minorStr","major","minor","isVue27Plus","api","VueNative","CompositionApiPolyfill","_ref","_reactive","_computed","_watch","_onMounted","_onBeforeUnmount","_onUpdated","_defineComponent","_inject","_provide","_nextTick","_getCurrentInstance","_h","VueCompositionAPIPlugin","_a","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","_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","checkPermission","pvalue","fn","translateLabel","injectedTableInstant","getTableInstant","isParentTable","t","getCompIcon","filterOptions","_icon","mapped","resolveDisabled","d","formInstance","formItemRowsList","formInputComponents","fieldFieldOutputGlobal","getEveryFormQueryField","formLayoutRef","_e","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","_c","clickBtn","initFormItemOptions","opts","style","rest","getFormRef","validate","resolve","maybePromise","valid","e","resetFields","clearValidate","p","validateField","formItmeRequestInstance","propsList","targetItems","apiOption","itemIndex","nextTick","bodyFormFn","EsForm","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","_d","resizeObservers","element","containerHeight","maxContainer","minTableNum","tabContainer","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","effectiveDataSource","columnRowList","loadingStatus","slotState","showPagination","syncDomRefs","bodyFormInstance","getVisibleShow","visibleShow","paginationConfig","getListEntry","eq","configTableField","configFields","isFormInstance","formChild","child","hasDefaultSlot","vnodes","heightType","tabHeight","containerStyle","slotStyles","slotStyleValue","slotClassValue","paginationLayoutConfig","cfg","layout","paginationPageSizes","paginationIsSmall","paginationBackground","paginationPrevText","paginationNextText","paginationStyle","loadStatus","isRequestConf","filteredColumns","el","btn","col","flexIdx","tableAttrs","_align","tableBindAttrs","handleSelectionChange","initSelection","clearAllSelectionInternal","handleTableSelectionChange","oldVal","httpRequestInstance","lastPaginationStr","emitPaginationUpdate","snapshot","lastEmittedTableData","getListenToCallBack","eventName","eventNameList","hasEventNameIndex","formatConfigOut","cf","paginationPatch","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","alreadyInstalled","configureEsPlus","component","compName"],"mappings":"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"}
1
+ {"version":3,"file":"es-plus-vue2.js","sources":["../src/vue-compat.ts","../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 兼容层 —— 运行时按 Vue 版本动态切换 Composition API 来源\r\n *\r\n * 行为:\r\n * - Vue 2.7+:使用 vue 原生导出的 Composition API(ref / reactive / inject / ...)\r\n * - Vue 2.6.x:使用 @vue/composition-api 的 polyfill\r\n *\r\n * 为什么不直接从 '@vue/composition-api' 静态 re-export:\r\n * 官方说明里 @vue/composition-api 1.7+ 在 Vue 2.7 下应通过 postinstall 自动\r\n * redirect 到原生 API,但在 monorepo / npm workspace / file: 协议安装时\r\n * postinstall 经常不执行,导致 dist 仍然是完整 polyfill。结果在 Vue 2.7 项目里\r\n * 原生 setup 与 polyfill 的 wrappedData 双双激活,setup 被调用两次,触发:\r\n * \"[Vue warn]: The setup binding property xxx is already declared\"\r\n * \"[Vue warn]: inject() can only be used inside setup() or functional components.\"\r\n *\r\n * 不使用 vue-demi 的原因:\r\n * vue-demi 的 postinstall 在嵌套 node_modules 安装时会解析到本包的 devDependency\r\n * vue@2.7 而非用户项目的 vue 版本,生成错误的 lib(在 Vue 2.6 项目里产生\r\n * \"export 'xxx' was not found in 'vue'\" 报错)。\r\n *\r\n * 本文件的策略:在模块加载时读取 `Vue.version`,按 major.minor 选择正确的来源。\r\n * 两个候选源都通过静态 import 引入,构建器可以分析;运行时只有一份会被实际使用。\r\n */\r\n\r\nimport Vue from 'vue'\r\nimport * as VueNative from 'vue'\r\nimport * as CompositionApiPolyfill from '@vue/composition-api'\r\n\r\n// 解析 Vue 版本\r\nconst versionString: string = (Vue as unknown as { version?: string }).version || ''\r\nconst [majorStr = '0', minorStr = '0'] = versionString.split('.')\r\nconst major = Number(majorStr)\r\nconst minor = Number(minorStr)\r\n\r\n/** Vue 2.7+ 原生支持 Composition API,无需 polyfill */\r\nexport const isVue27Plus: boolean = major === 2 && minor >= 7\r\n\r\n// 选择实际使用的 API 源:\r\n// Vue 2.7+ → 原生(VueNative.ref 等)\r\n// Vue 2.6 → polyfill(CompositionApiPolyfill.ref 等)\r\n//\r\n// 注意:在 Vue 2.6 环境里 VueNative 上不会有 ref / reactive 等键,但因为\r\n// isVue27Plus 为 false,永远不会读到这些 undefined。反向同理。\r\nconst api: typeof CompositionApiPolyfill = (\r\n isVue27Plus ? VueNative : CompositionApiPolyfill\r\n) as typeof CompositionApiPolyfill\r\n\r\n// ─── Composition API 命名导出 ───\r\n//\r\n// 不能用 `export const ref = api.ref` 这种顶层重新声明,因为部分构建器\r\n// (特别是 ES 模块 named export)只允许从单一静态源 re-export,不允许动态。\r\n// 为此我们把每个 API 包成一个变量声明 + export 语句:\r\n//\r\n// const _ref = api.ref\r\n// export { _ref as ref }\r\n//\r\n// 这样 TypeScript 不会做静态 re-export 树摇,但能正确通过类型检查。\r\n\r\nconst _ref = api.ref\r\nconst _reactive = api.reactive\r\nconst _computed = api.computed\r\nconst _watch = api.watch\r\nconst _watchEffect = api.watchEffect\r\nconst _onMounted = api.onMounted\r\nconst _onUnmounted = api.onUnmounted\r\nconst _onBeforeUnmount = api.onBeforeUnmount\r\nconst _onBeforeMount = api.onBeforeMount\r\nconst _onUpdated = api.onUpdated\r\nconst _onActivated = api.onActivated\r\nconst _onDeactivated = api.onDeactivated\r\nconst _defineComponent = api.defineComponent\r\nconst _inject = api.inject\r\nconst _provide = api.provide\r\nconst _nextTick = api.nextTick\r\nconst _getCurrentInstance = api.getCurrentInstance\r\nconst _toRefs = api.toRefs\r\nconst _toRef = api.toRef\r\nconst _unref = api.unref\r\nconst _isRef = api.isRef\r\n// `h` 的类型在 @vue/composition-api 内部使用了未导出的命名空间 `H`,\r\n// 直接 const _h = api.h 会触发 TS4023 (Exported variable uses unnameable type)。\r\n// 用 typeof CompositionApiPolyfill.h 把类型固定到一个可命名的外部符号上。\r\nconst _h: typeof CompositionApiPolyfill.h = api.h\r\n\r\nexport {\r\n _ref as ref,\r\n _reactive as reactive,\r\n _computed as computed,\r\n _watch as watch,\r\n _watchEffect as watchEffect,\r\n _onMounted as onMounted,\r\n _onUnmounted as onUnmounted,\r\n _onBeforeUnmount as onBeforeUnmount,\r\n _onBeforeMount as onBeforeMount,\r\n _onUpdated as onUpdated,\r\n _onActivated as onActivated,\r\n _onDeactivated as onDeactivated,\r\n _defineComponent as defineComponent,\r\n _inject as inject,\r\n _provide as provide,\r\n _nextTick as nextTick,\r\n _getCurrentInstance as getCurrentInstance,\r\n _toRefs as toRefs,\r\n _toRef as toRef,\r\n _unref as unref,\r\n _isRef as isRef,\r\n _h as h,\r\n}\r\n\r\n/** 暴露 polyfill plugin(default export)给 install() 在 Vue 2.6 下按需安装 */\r\nexport const VueCompositionAPIPlugin: unknown =\r\n (CompositionApiPolyfill as unknown as { default?: unknown }).default ??\r\n CompositionApiPolyfill\r\n\r\n// Vue 构造器必须从 'vue' 直接导入:\r\n// @vue/composition-api 的 default export 是 plugin({ install }),\r\n// 没有 .extend / .component 等静态方法,useDialog 内部 Vue.extend(...) 会报错。\r\nexport { default as Vue } from 'vue'\r\n\r\n// 类型导出:Vue 2.7+ 与 @vue/composition-api 的类型定义结构兼容,\r\n// 这里统一从 polyfill 包导出,避免 Vue 2.6 下 'vue' 没有这些类型导致编译失败。\r\nexport type { PropType, Ref, ComputedRef, WatchSource } from '@vue/composition-api'\r\n\r\n/**\r\n * Vue 2 constructor type that includes static methods\r\n * (component, mixin, use, prototype) which @vue/composition-api's\r\n * type definitions omit.\r\n *\r\n * Use this instead of `typeof Vue` in install function signatures.\r\n */\r\nexport interface Vue2Constructor {\r\n version?: string\r\n component(name: string, component?: any): any\r\n mixin(mixin: Record<string, any>): void\r\n use(plugin: any, ...options: any[]): any\r\n prototype: Record<string, any>\r\n}\r\n","/**\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=\"resolvedModel\"\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=\"resolvedModel\"\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=\"resolvedModel\"\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 } 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: any) => any)\r\n | undefined\r\n const { getEveryFormQueryField } = useFormRequest(httpRequestGlobal)\r\n\r\n // ─── formProps (供 el-form 使用) ──\r\n const formLayoutRef = ref<Record<string, unknown>>(\r\n ((props.layoutFormProps as { fromLayProps?: Record<string, unknown> } | undefined)?.fromLayProps) || {}\r\n )\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 formInputComponents,\r\n formInstance,\r\n // 注意:不要在 setup return 中暴露与 props 同名的 key(configBtn / model /\r\n // btnColSpanRow / renderBtn)——Vue 2 已自动把 props 挂到 vm 实例,\r\n // 重复暴露会在 @vue/composition-api 下触发 \"already declared as a prop\" 警告。\r\n // 模板中的 :model 引用 resolvedModel(用于解析 v-model 兼容),其它 props 直接使用名称。\r\n resolvedModel,\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 { Vue2Constructor } 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: Vue2Constructor) => 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 /**\r\n * 读取父容器可用于布局子元素的高度(即\"内容区\"高度)。\r\n *\r\n * `offsetHeight` 包含 padding + border + 滚动条;直接拿来当 .table_component 的\r\n * 可用空间,会让 es-table 撑出父容器的内容区,挤进父级 padding 甚至越过父级边界。\r\n *\r\n * `clientHeight` = padding + content(不含 border / 滚动条),再扣掉上下 padding 即为\r\n * 真实可放子元素的高度。fallback 到 offsetHeight - 上下 border 也行,但 clientHeight\r\n * 已自动排除 border,更直接。\r\n */\r\n const getParentContentHeight = (parent: HTMLElement | null | undefined): number => {\r\n if (!parent) return 0\r\n const cs = typeof window !== 'undefined' ? window.getComputedStyle(parent) : null\r\n const paddingTop = cs ? parseFloat(cs.paddingTop) || 0 : 0\r\n const paddingBottom = cs ? parseFloat(cs.paddingBottom) || 0 : 0\r\n const inner = parent.clientHeight - paddingTop - paddingBottom\r\n return inner > 0 ? inner : parent.clientHeight || parent.offsetHeight || 0\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 ? getParentContentHeight(element.parentElement) || 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 // 主动触发一次计算,避免依赖 ResizeObserver 的首次回调(某些环境不触发)。\r\n resizeObservers()\r\n\r\n if (headBarRef.value) {\r\n observer.value.observe(headBarRef.value)\r\n }\r\n if (paginationRef.value) {\r\n observer.value.observe(paginationRef.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=\"tableContainerEl\" 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=\"slotStyleValue\"\r\n :class=\"slotClassValue\"\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 <!--\r\n v-on=\"$listeners\" 把宿主在 <es-table> 上写的所有监听器透传到 <el-table>,\r\n 让 row-click / cell-click / select / header-click 等 Element UI Table 原生事件\r\n 能直接被使用方监听。Vue 2 的 _g 会把 $listeners 与下面显式的 @sort-change /\r\n @selection-change 合并为数组,不会覆盖我们的内部处理。\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 v-on=\"$listeners\"\r\n :data=\"effectiveDataSource\"\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 </div>\r\n\r\n <!--\r\n 分页区域放在 v-loading 元素之外(作为 .table_containers 的子元素),\r\n 以避免 loading mask(z-index 2000)遮挡分页;\r\n 分页用 static 定位(默认)参与 flex 列布局,使 .tableContainer (flex:1) 自动让出空间。\r\n -->\r\n <div\r\n v-if=\"showPagination\"\r\n ref=\"paginationRef\"\r\n class=\"pagination_page\"\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 :prev-text=\"paginationPrevText\"\r\n :next-text=\"paginationNextText\"\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</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 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 'lazyLoad',\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\r\n // Effective data source: 内部 tableData 优先(接口请求的数据),\r\n // 兼容父组件不使用 .sync 但又希望看到接口拉取数据的场景。\r\n // 当父组件传入了非空 dataSource 且内部 tableData 为空时,使用 dataSource。\r\n const effectiveDataSource = computed(() => {\r\n if (tableData.value && tableData.value.length) return tableData.value\r\n return props.dataSource\r\n })\r\n const columnRowList = ref<TableColumn[]>([...props.columns])\r\n\r\n // Only watch the columns array reference — not deep mutations.\r\n // deep: true would react to el.formatter / el.render / el.minWidth mutations\r\n // that filteredColumns applies to the column objects during render. In Vue 2,\r\n // props come from the parent's deeply observed data; each mutation triggers the\r\n // watcher → columnRowList reassign → filteredColumns recompute → potential\r\n // \"infinite update loop\" warning. Vue 3 avoids this because its props are\r\n // shallow-reactive by default.\r\n watch(\r\n () => props.columns,\r\n (val) => {\r\n columnRowList.value = [...val]\r\n }\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 + @vue/composition-api 下函数式 ref `:ref=\"setterFn\"` 在 SFC 模板中\r\n // 不会被运行时调用(已知兼容性问题)。改用字符串 ref(模板中 ref=\"xxx\"),\r\n // 在 onMounted 内通过 vm.$refs.xxx 手动同步到 setup 中的 ref 变量。\r\n // 这是 Vue 2 + composition-api 下 100% 可靠的 DOM 引用方式。\r\n const syncDomRefs = () => {\r\n const proxy = (instance as any)?.proxy\r\n if (!proxy || !proxy.$refs) return\r\n tableContainerRef.value = (proxy.$refs.tableContainerEl as HTMLElement) || null\r\n headBarRef.value = (proxy.$refs.headBarRef as HTMLElement) || null\r\n paginationRef.value = (proxy.$refs.paginationRef as HTMLElement) || null\r\n // tbBtnRef 是 TableBtns 组件实例(不是 DOM),useTableResize 通过 .$el.offsetHeight 读高度。\r\n // 必须同步,否则 tbBtnHeight 永远为 0,导致 tableHeight 多算一个 toolbar 的高度(~40px),\r\n // 让 el-table 撞穿 .tableContainer 的 overflow:hidden 边界把最后一行裁掉。\r\n tbBtnRef.value = (proxy.$refs.tbBtnRef as any) || null\r\n // tableRef 同理 —— 虽然 useTableResize 不直接读它的高度,但 expose 出去的\r\n // clearSelection / refresh / scrollToRow / toggleSelection 等都依赖它指向真实 el-table 实例。\r\n tableRef.value = (proxy.$refs.tableRef as any) || null\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 /** Typed style/class for header bar slot — avoids Vue StyleValue type mismatch in template */\r\n const slotStyleValue = computed<Record<string, string | number>>(() => {\r\n const s = slotStyles.value\r\n if (s.type === 'object' && s.value && typeof s.value === 'object') {\r\n return s.value as Record<string, string | number>\r\n }\r\n return {}\r\n })\r\n const slotClassValue = computed<string>(() => {\r\n const s = slotStyles.value\r\n return s.type === 'string' ? (s.value as string) : ''\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 // prev/next 文字:未配置时返回空字符串,让 el-pagination 渲染默认 ‹/› 箭头\r\n const paginationPrevText = computed(\r\n () => ((paginationLayoutConfig.value as any)?.prevText as string) || ''\r\n )\r\n const paginationNextText = computed(\r\n () => ((paginationLayoutConfig.value as any)?.nextText as string) || ''\r\n )\r\n\r\n const paginationStyle = computed(() => ({\r\n position: heightType.value === 'height' ? ('absolute' as const) : ('static' as const),\r\n bottom: '0px',\r\n left: '0px',\r\n // z-index 必须高于 element-loading 蒙层(默认 2000),否则请求加载过程中分页会被蒙层遮挡。\r\n zIndex: 2001,\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 // Element UI 的 el-table 懒加载回调 prop 叫 load,但我们的公开 API 用 lazyLoad\r\n // 与 Vue 3 版本保持一致(el-table-v2 中也是 load)。映射后 el-table 的懒加载行为\r\n //(loadOrToggle → loadData → 用户提供的 lazyLoad 回调)才能正常工作。\r\n if (typeof props.options.lazyLoad === 'function') {\r\n result.load = props.options.lazyLoad\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 // 兼容性修复:在 Vue 2.6 + @vue/composition-api 下,watch(() => props.pagination, ...)\r\n // 即使比对相同也会因为父组件 .sync 回传引发 watcher 触发 → 父组件 render watcher 循环。\r\n // 解决:emit 前先更新 lastPaginationStr,watcher 收到回传时序列化相同则 return。\r\n let lastPaginationStr = JSON.stringify(props.pagination || {})\r\n if (props.pagination && Object.keys(props.pagination).length) {\r\n paginationConfig.value = { ...paginationConfig.value, ...props.pagination }\r\n showPagination.value = (props.pagination as PaginationConfig).total !== undefined\r\n }\r\n /** Emit pagination 更新,并预先记录序列化值以阻断 .sync 回传循环 */\r\n const emitPaginationUpdate = () => {\r\n const snapshot = { ...paginationConfig.value }\r\n lastPaginationStr = JSON.stringify(snapshot)\r\n emit('update:pagination', snapshot)\r\n }\r\n watch(\r\n () => props.pagination,\r\n (val: PaginationConfig) => {\r\n const str = JSON.stringify(val || {})\r\n if (str === lastPaginationStr) return\r\n lastPaginationStr = str\r\n paginationConfig.value = { ...paginationConfig.value, ...val }\r\n showPagination.value = val.total !== undefined\r\n }\r\n )\r\n\r\n // 兼容性修复:移除 deep,仅监听数组引用变化即可触发 selection 重置。\r\n // .sync 回传相同引用时不会重复触发,避免循环。\r\n watch(\r\n () => props.dataSource,\r\n (val) => {\r\n initSelection(val, tableRef.value)\r\n }\r\n )\r\n\r\n // 兼容性修复:避免 Vue 2.6 + @vue/composition-api 下 .sync 双向绑定循环。\r\n // 仅在 tableData 引用变化时 emit,去掉 deep;并通过 lastEmittedRef 跳过\r\n // 「外部 .sync 回传 → props.dataSource 变化 → 内部赋值 → emit 再次回传」的循环。\r\n let lastEmittedTableData: unknown = null\r\n watch(tableData, (val) => {\r\n if (!Array.isArray(val)) return\r\n if (val === lastEmittedTableData) return\r\n lastEmittedTableData = val\r\n emit('update:dataSource', val)\r\n })\r\n\r\n onMounted(() => {\r\n // 立即同步一次 vm.$refs 到 setup 中的 ref 变量\r\n syncDomRefs()\r\n if (isRequestConf.value && props.options.isInitRun !== false) {\r\n httpRequestInstance()\r\n }\r\n // 等待所有子元素(含 pagination / EsForm)挂载完成后再同步并重算高度。\r\n nextTick(() => {\r\n syncDomRefs()\r\n // eslint-disable-next-line no-unused-expressions\r\n isFormInstance.value\r\n if (typeof requestAnimationFrame !== 'undefined') {\r\n requestAnimationFrame(() => {\r\n syncDomRefs()\r\n resizeObservers()\r\n })\r\n } else {\r\n resizeObservers()\r\n }\r\n })\r\n })\r\n\r\n // ─── 请求逻辑 ──────────────────────────────\r\n const getListenToCallBack = (eventName: string, params: unknown) => {\r\n const eventNameList = [\r\n { eventName: 'brcb', isReturn: true },\r\n { eventName: 'qrcb', isReturn: true },\r\n ]\r\n const hasEventNameIndex = eventNameList.findIndex((it) => it.eventName === eventName)\r\n if (\r\n props.options.listenToCallBack &&\r\n (props.options.listenToCallBack as any)[eventName] &&\r\n hasEventNameIndex !== -1\r\n ) {\r\n const callObj = eventNameList[hasEventNameIndex]\r\n if (callObj.isReturn) {\r\n return (props.options.listenToCallBack as any)[eventName](params)\r\n }\r\n }\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 // 累积所有 pagination 字段更新,最后一次性整体替换 paginationConfig.value,\r\n // 避免直接 paginationConfig.value[key] = x 触发多次 setter / 多轮渲染。\r\n const paginationPatch: Record<string, unknown> = {}\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 paginationPatch[key] =\r\n typeof rowData === 'number' ? rowData : parseInt(rowData as string, 10) || 0\r\n }\r\n })\r\n if (Object.keys(paginationPatch).length) {\r\n paginationConfig.value = { ...paginationConfig.value, ...paginationPatch }\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('brcb', {\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('qrcb', 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 = { ...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 emitPaginationUpdate()\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 emitPaginationUpdate()\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 emitPaginationUpdate()\r\n },\r\n }\r\n )\r\n }\r\n\r\n const handleSizeChange = (size: number) => {\r\n paginationConfig.value = { ...paginationConfig.value, pageSize: size, current: 1 }\r\n if (isRequestConf.value) {\r\n changePageSizeRequest()\r\n } else {\r\n emitPaginationUpdate()\r\n emit('size-change', paginationConfig.value, size)\r\n }\r\n }\r\n\r\n const handleIndexChange = (val: number) => {\r\n paginationConfig.value = { ...paginationConfig.value, current: val }\r\n if (isRequestConf.value) {\r\n changePageIndexRequest()\r\n } else {\r\n emitPaginationUpdate()\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 effectiveDataSource,\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 slotStyleValue,\r\n slotClassValue,\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 paginationPrevText,\r\n paginationNextText,\r\n // handlers\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 flex: 1;\r\n // flex 子项默认 min-height: auto(= min-content)会拒绝收缩到比内容还小,\r\n // 导致表单展开时 el-table prop height 还没更新的那 1-2 帧里\r\n // .tableContainer 被旧表格内容撑高,把分页栏推出视口然后回弹 —— 视觉上分页栏在跳。\r\n // min-height:0 + overflow:hidden 让 .tableContainer 严格服从 flex 分配的尺寸,\r\n // 内部表格尺寸暂时偏大时被裁住而不影响外部布局,分页栏全程稳定。\r\n min-height: 0;\r\n overflow: hidden;\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 { Vue2Constructor } from '../../vue-compat'\r\n\r\n;(EsTable as unknown as { install: (V: Vue2Constructor) => 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 { Vue2Constructor } from '../../vue-compat'\r\n\r\n;(EsDialog as unknown as { install: (V: Vue2Constructor) => 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 ): BtnConfig[] | 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 { Vue2Constructor } from '../../vue-compat'\r\n\r\n;(EsCrudPage as unknown as { install: (V: Vue2Constructor) => 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 版本,用户都不需要手动 `Vue.use(VueCompositionAPI)`:\r\n * - Vue 2.7+:本库的 vue-compat 直接使用 vue 原生 Composition API\r\n * - Vue 2.6:本库 install() 会自动调用 `Vue.use(VueCompositionAPI)` 安装 polyfill\r\n *\r\n * ┌─ Vue 2.6 / 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.7 项目中**不要**额外 `Vue.use(VueCompositionAPI)`,否则原生 setup\r\n * 与 polyfill 的 wrappedData 会双重执行,本库 install 会发出警告。\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 { Vue2Constructor } from './vue-compat'\r\nimport { isVue27Plus, VueCompositionAPIPlugin } 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: Vue2Constructor, options: InstallOptions = {}) => {\r\n // 自动管理 @vue/composition-api 安装:\r\n // - Vue 2.6.x:必须装 polyfill,否则库内 setup / inject / ref 等无法工作\r\n // - Vue 2.7+:原生支持 Composition API,不应安装 polyfill;如已被用户主动\r\n // `Vue.use(VueCompositionAPI)`,原生 setup 与 polyfill 的 wrappedData 会双重\r\n // 执行,导致 \"setup binding ... already declared\" 与 \"inject() outside setup\"\r\n // 等告警。这里只能发警告,无法在运行时卸载 plugin。\r\n const alreadyInstalled = (Vue as unknown as Record<string, unknown>).__composition_api_installed__ === true\r\n if (!isVue27Plus) {\r\n if (!alreadyInstalled && VueCompositionAPIPlugin) {\r\n Vue.use(VueCompositionAPIPlugin as any)\r\n }\r\n } else if (alreadyInstalled) {\r\n // eslint-disable-next-line no-console\r\n console.warn(\r\n '[@es-plus/vue2] Vue 2.7+ detected together with @vue/composition-api plugin already installed. ' +\r\n 'This causes setup() to run twice (once natively, once via the polyfill\\'s data() wrapper) and ' +\r\n 'will produce \"setup binding ... already declared\" warnings. Remove `Vue.use(VueCompositionAPI)` ' +\r\n 'from your main.js — Vue 2.7 has Composition API natively.',\r\n )\r\n }\r\n\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.1.4',\r\n install,\r\n}\r\n"],"names":["versionString","Vue","majorStr","minorStr","major","minor","isVue27Plus","api","VueNative","CompositionApiPolyfill","_ref","_reactive","_computed","_watch","_onMounted","_onBeforeUnmount","_onUpdated","_defineComponent","_inject","_provide","_nextTick","_getCurrentInstance","_h","VueCompositionAPIPlugin","_a","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","_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","checkPermission","pvalue","fn","translateLabel","injectedTableInstant","getTableInstant","isParentTable","t","getCompIcon","filterOptions","_icon","mapped","resolveDisabled","d","formInstance","formItemRowsList","formInputComponents","fieldFieldOutputGlobal","getEveryFormQueryField","formLayoutRef","_e","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","_c","clickBtn","initFormItemOptions","opts","style","rest","getFormRef","validate","resolve","maybePromise","valid","e","resetFields","clearValidate","p","validateField","formItmeRequestInstance","propsList","targetItems","apiOption","itemIndex","nextTick","bodyFormFn","EsForm","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","_d","getParentContentHeight","parent","cs","paddingTop","paddingBottom","inner","resizeObservers","element","containerHeight","maxContainer","minTableNum","tabContainer","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","effectiveDataSource","columnRowList","loadingStatus","slotState","showPagination","syncDomRefs","bodyFormInstance","getVisibleShow","visibleShow","paginationConfig","getListEntry","eq","configTableField","configFields","isFormInstance","formChild","child","hasDefaultSlot","vnodes","heightType","tabHeight","containerStyle","slotStyles","slotStyleValue","slotClassValue","paginationLayoutConfig","cfg","layout","paginationPageSizes","paginationIsSmall","paginationBackground","paginationPrevText","paginationNextText","paginationStyle","loadStatus","isRequestConf","filteredColumns","el","btn","col","flexIdx","tableAttrs","_align","tableBindAttrs","handleSelectionChange","initSelection","clearAllSelectionInternal","handleTableSelectionChange","oldVal","httpRequestInstance","lastPaginationStr","emitPaginationUpdate","snapshot","lastEmittedTableData","getListenToCallBack","eventName","eventNameList","hasEventNameIndex","formatConfigOut","cf","paginationPatch","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","alreadyInstalled","configureEsPlus","component","compName"],"mappings":"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"}