keli-ui 0.3.13 → 0.3.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ApprovalRecord-BncClAVJ.js → ApprovalRecord-CAUi65p8.js} +2 -2
- package/dist/{ApprovalRecord-BncClAVJ.js.map → ApprovalRecord-CAUi65p8.js.map} +1 -1
- package/dist/{api-BijZYgZr.js → api-DPWBxyJL.js} +48 -48
- package/dist/{api-BijZYgZr.js.map → api-DPWBxyJL.js.map} +1 -1
- package/dist/components/FormComponent/FormCodeEditor/index.d.ts +2 -1
- package/dist/components/FormComponent/FormCodeEditor/language/index.d.ts +114 -0
- package/dist/components/FormComponent/FormCodeEditor/language/java.d.ts +1 -1
- package/dist/components/FormComponent/FormCodeEditor/language/postgresql.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/{java-XIxqoWBD.js → java-CanB8gLZ.js} +39 -33
- package/dist/java-CanB8gLZ.js.map +1 -0
- package/dist/keli-ui.js +1270 -1250
- package/dist/keli-ui.js.map +1 -1
- package/dist/keli-ui.umd.cjs +6 -6
- package/dist/keli-ui.umd.cjs.map +1 -1
- package/dist/{mysql-D_yXY3Wl.js → mysql-BfiDepTc.js} +8 -4
- package/dist/{mysql-D_yXY3Wl.js.map → mysql-BfiDepTc.js.map} +1 -1
- package/dist/{postgresql-KYgISeDf.js → postgresql-63S_TxNE.js} +29 -23
- package/dist/postgresql-63S_TxNE.js.map +1 -0
- package/package.json +1 -1
- package/dist/java-XIxqoWBD.js.map +0 -1
- package/dist/postgresql-KYgISeDf.js.map +0 -1
package/dist/keli-ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keli-ui.js","names":["$slots"],"sources":["../src/components/ElPlusComponent/ElButtonPlus/ElButtonPlus.vue","../src/components/ElPlusComponent/ElButtonPlus/ElButtonPlus.vue","../src/components/ElPlusComponent/ElButtonPlus/index.ts","../src/components/ElPlusComponent/ElColPlus/ElColPlus.vue","../src/components/ElPlusComponent/ElColPlus/ElColPlus.vue","../src/components/ElPlusComponent/ElColPlus/index.ts","../src/components/ElPlusComponent/ElRowPlus/ElRowPlus.vue","../src/components/ElPlusComponent/ElRowPlus/ElRowPlus.vue","../src/components/ElPlusComponent/ElRowPlus/index.ts","../src/utils/arrayUtils.ts","../src/assets/avatar.svg","../src/assets/question.svg","../src/utils/baseFunction.ts","../src/utils/validate.ts","../src/utils/dataFormatter.ts","../src/utils/dateTime.ts","../src/utils/emitter.ts","../src/utils/formValidates.ts","../src/utils/msgTips.ts","../src/components/QueryComponent/QueryBar/hooks/index.ts","../src/components/QueryComponent/QueryBar/QueryBar.vue","../src/components/QueryComponent/QueryBar/QueryBar.vue","../src/components/QueryComponent/QueryBar/index.ts","../src/components/QueryComponent/QueryDateTime/QueryDateTime.vue","../src/components/QueryComponent/QueryDateTime/QueryDateTime.vue","../src/components/QueryComponent/QueryDateTime/index.ts","../src/components/QueryComponent/QueryInput/QueryInput.vue","../src/components/QueryComponent/QueryInput/QueryInput.vue","../src/components/QueryComponent/QueryInput/index.ts","../src/components/QueryComponent/QueryInputLike/QueryInputLike.vue","../src/components/QueryComponent/QueryInputLike/QueryInputLike.vue","../src/components/QueryComponent/QueryInputLike/index.ts","../src/components/QueryComponent/QuerySelect/QuerySelect.vue","../src/components/QueryComponent/QuerySelect/QuerySelect.vue","../src/components/QueryComponent/QuerySelect/index.ts","../src/components/QueryComponent/QueryTreeFilter/QueryTreeFilter.vue","../src/components/QueryComponent/QueryTreeFilter/QueryTreeFilter.vue","../src/components/QueryComponent/QueryTreeFilter/index.ts","../src/components/TableComponent/TableInput/TableInput.vue","../src/components/TableComponent/TableInput/TableInput.vue","../src/components/TableComponent/TableInput/index.ts","../src/components/TableComponent/TableInputNumber/TableInputNumber.vue","../src/components/TableComponent/TableInputNumber/TableInputNumber.vue","../src/components/TableComponent/TableInputNumber/index.ts","../src/components/TableComponent/TableSelect/TableSelect.vue","../src/components/TableComponent/TableSelect/TableSelect.vue","../src/components/TableComponent/TableSelect/index.ts","../src/components/TableComponent/TableSelectAsync/TableSelectAsync.vue","../src/components/TableComponent/TableSelectAsync/TableSelectAsync.vue","../src/components/TableComponent/TableSelectAsync/index.ts","../src/components/TableComponent/TableSwitch/TableSwitch.vue","../src/components/TableComponent/TableSwitch/TableSwitch.vue","../src/components/TableComponent/TableSwitch/index.ts","../src/components/TableComponent/TableListSelect/TableListSelect.vue","../src/components/TableComponent/TableListSelect/TableListSelect.vue","../src/components/TableComponent/TableListSelect/index.ts","../src/components/TableComponent/hooks/tableSelectAsync.hook.ts","../src/components/TableComponent/TableListSelectAsync/TableListSelectAsync.vue","../src/components/TableComponent/TableListSelectAsync/TableListSelectAsync.vue","../src/components/TableComponent/TableListSelectAsync/index.ts","../src/components/TableComponent/TableCheckBoxAsync/TableCheckBoxAsync.vue","../src/components/TableComponent/TableCheckBoxAsync/TableCheckBoxAsync.vue","../src/components/TableComponent/TableCheckBoxAsync/index.ts","../src/components/TableComponent/TableRender/hooks/useVxeGrid.hook.ts","../src/components/TableComponent/TableRender/TableRender.vue","../src/components/TableComponent/TableRender/TableRender.vue","../src/components/TableComponent/TableRender/index.ts","../src/components/TableComponent/TableCardRender/TableCardRender.vue","../src/components/TableComponent/TableCardRender/TableCardRender.vue","../src/components/TableComponent/TableCardRender/index.ts","../src/components/FormComponent/hooks/useMitt.hook.ts","../src/components/FormComponent/FormInput/FormInput.vue","../src/components/FormComponent/FormInput/FormInput.vue","../src/components/FormComponent/FormInput/index.ts","../src/components/FormComponent/FormInputNumber/FormInputNumber.vue","../src/components/FormComponent/FormInputNumber/FormInputNumber.vue","../src/components/FormComponent/FormInputNumber/index.ts","../src/components/FormComponent/FormTextArea/FormTextArea.vue","../src/components/FormComponent/FormTextArea/FormTextArea.vue","../src/components/FormComponent/FormTextArea/index.ts","../src/components/FormComponent/FormText/FormText.vue","../src/components/FormComponent/FormText/FormText.vue","../src/components/FormComponent/FormText/index.ts","../src/components/FormComponent/FormSelect/FormSelect.vue","../src/components/FormComponent/FormSelect/FormSelect.vue","../src/components/FormComponent/FormSelect/index.ts","../src/components/FormComponent/hooks/selectAsync.hook.ts","../src/components/FormComponent/FormSelectAsync/FormSelectAsync.vue","../src/components/FormComponent/FormSelectAsync/FormSelectAsync.vue","../src/components/FormComponent/FormSelectAsync/index.ts","../src/components/FormComponent/FormSelectRemote/FormSelectRemote.vue","../src/components/FormComponent/FormSelectRemote/FormSelectRemote.vue","../src/components/FormComponent/FormSelectRemote/index.ts","../src/components/FormComponent/FormRadio/FormRadio.vue","../src/components/FormComponent/FormRadio/FormRadio.vue","../src/components/FormComponent/FormRadio/index.ts","../src/components/FormComponent/FormCheckBox/FormCheckBox.vue","../src/components/FormComponent/FormCheckBox/FormCheckBox.vue","../src/components/FormComponent/FormCheckBox/index.ts","../src/components/FormComponent/FormCheckBoxAsync/FormCheckBoxAsync.vue","../src/components/FormComponent/FormCheckBoxAsync/FormCheckBoxAsync.vue","../src/components/FormComponent/FormCheckBoxAsync/index.ts","../src/components/FormComponent/FormSwitch/FormSwitch.vue","../src/components/FormComponent/FormSwitch/FormSwitch.vue","../src/components/FormComponent/FormSwitch/index.ts","../src/components/FormComponent/FormDatePicker/FormDatePicker.vue","../src/components/FormComponent/FormDatePicker/FormDatePicker.vue","../src/components/FormComponent/FormDatePicker/index.ts","../src/components/FormComponent/FormDateTimePicker/FormDateTimePicker.vue","../src/components/FormComponent/FormDateTimePicker/FormDateTimePicker.vue","../src/components/FormComponent/FormDateTimePicker/index.ts","../src/components/FormComponent/FormCascaderAsync/FormCascaderAsync.vue","../src/components/FormComponent/FormCascaderAsync/FormCascaderAsync.vue","../src/components/FormComponent/FormCascaderAsync/index.ts","../src/components/FormComponent/FormTableSelect/FormTableSelect.vue","../src/components/FormComponent/FormTableSelect/FormTableSelect.vue","../src/components/FormComponent/FormTableSelect/index.ts","../src/components/FormComponent/FormTableSelectAsync/FormTableSelectAsync.vue","../src/components/FormComponent/FormTableSelectAsync/FormTableSelectAsync.vue","../src/components/FormComponent/FormTableSelectAsync/index.ts","../src/components/FormComponent/FormDictSelector/FormDictSelector.vue","../src/components/FormComponent/FormDictSelector/FormDictSelector.vue","../src/components/FormComponent/FormDictSelector/index.ts","../src/components/FormComponent/FormIconPicker/FormIconPicker.vue","../src/components/FormComponent/FormIconPicker/FormIconPicker.vue","../src/components/FormComponent/FormIconPicker/index.ts","../src/components/FormComponent/FormImageUpload/FormImageUpload.vue","../src/components/FormComponent/FormImageUpload/FormImageUpload.vue","../src/components/FormComponent/FormImageUpload/index.ts","../src/components/FormComponent/FormCodeEditor/volar/setup.ts","../src/components/FormComponent/FormCodeEditor/FormCodeEditor.vue","../src/components/FormComponent/FormCodeEditor/FormCodeEditor.vue","../src/components/FormComponent/FormCodeEditor/index.ts","../src/components/FormComponent/FormDivider/FormDivider.vue","../src/components/FormComponent/FormDivider/FormDivider.vue","../src/components/FormComponent/FormDivider/index.ts","../src/components/FormComponent/FormFieldset/FormFieldset.vue","../src/components/FormComponent/FormFieldset/FormFieldset.vue","../src/components/FormComponent/FormFieldset/index.ts","../src/components/FormComponent/FormDynamicTable/FormDynamicTable.vue","../src/components/FormComponent/FormDynamicTable/FormDynamicTable.vue","../src/components/FormComponent/FormDynamicTable/index.ts","../src/components/FormComponent/DynamicMapTable/DynamicMapTable.vue","../src/components/FormComponent/DynamicMapTable/DynamicMapTable.vue","../src/components/FormComponent/DynamicMapTable/index.ts","../src/components/FormComponent/FormRender/components/FormAreaRender.vue","../src/components/FormComponent/FormRender/components/FormAreaRender.vue","../src/components/FormComponent/FormRender/hooks/formRender.hook.ts","../src/components/FormComponent/FormRender/FormRender.vue","../src/components/FormComponent/FormRender/FormRender.vue","../src/components/FormComponent/FormRender/index.ts","../src/components/FormComponent/hooks/useColumnRender.hook.ts","../src/hooks/useTableFormats.hook.ts","../src/components/AppComponent/hooks/useSplitApiButton.ts","../src/components/AppComponent/hooks/useTable.hook.ts","../src/components/AppComponent/components/embedded/EmbeddedDialogForm.vue","../src/components/AppComponent/components/embedded/EmbeddedDialogForm.vue","../src/components/AppComponent/components/embedded/EmbeddedTable.vue","../src/components/AppComponent/components/embedded/EmbeddedTable.vue","../src/components/AppComponent/components/FileIsland.vue","../src/components/AppComponent/components/FileIsland.vue","../src/components/AppComponent/components/FlowUserDialog.vue","../src/components/AppComponent/components/FlowUserDialog.vue","../src/components/AppComponent/hooks/useAutoForm.hook.ts","../src/components/AppComponent/AppFormRender.vue","../src/components/AppComponent/AppFormRender.vue","../src/components/AppComponent/components/chartList/ChartRender.vue","../src/components/AppComponent/components/chartList/ChartRender.vue","../src/components/AppComponent/components/chartList/index.vue","../src/components/AppComponent/components/chartList/index.vue","../src/components/AppComponent/components/DialogForm.vue","../src/components/AppComponent/components/DialogForm.vue","../src/components/AppComponent/components/DrawerForm.vue","../src/components/AppComponent/components/DrawerForm.vue","../src/components/AppComponent/AppTableRender.vue","../src/components/AppComponent/AppTableRender.vue","../src/components/AppComponent/DynamicDialogHost.vue","../src/components/AppComponent/DynamicDialogHost.vue","../src/components/AppComponent/index.ts","../src/utils/openHostDialog.ts","../src/utils/sleep.ts","../src/hooks/useButtonExec.hook.ts","../src/components/ToolBar/ToolBar.vue","../src/components/ToolBar/ToolBar.vue","../src/components/ToolBar/index.ts","../src/components/TableComponent/TableRender/plugin/vxe-table-clipboard.ts","../src/index.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport { defineComponent, h, useAttrs } from 'vue';\n\nimport { Icon } from '@iconify/vue';\nimport { ElButton } from 'element-plus';\n\ninterface Props {\n icon?: object | string;\n label?: string | undefined;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n icon: undefined,\n label: undefined,\n});\n\nconst attrs = useAttrs();\n\n// 创建 Iconify 图标组件\nfunction createIconifyIcon(iconName: string) {\n return defineComponent({\n name: `Icon-${iconName}`,\n setup(iconProps, { attrs: iconAttrs }) {\n return () => h(Icon, { icon: iconName, ...iconProps, ...iconAttrs });\n },\n });\n}\n\nfunction getIconComponent() {\n if (!props.icon) return undefined;\n\n if (typeof props.icon === 'string' && props.icon.includes(':')) {\n return createIconifyIcon(props.icon);\n }\n\n return props.icon;\n}\n</script>\n\n<template>\n <component\n v-if=\"label\"\n :is=\"ElButton\"\n v-bind=\"attrs\"\n :icon=\"getIconComponent()\"\n >\n {{ label }}\n </component>\n <component v-else :is=\"ElButton\" v-bind=\"attrs\" :icon=\"getIconComponent()\" />\n</template>\n","<script setup lang=\"ts\">\nimport { defineComponent, h, useAttrs } from 'vue';\n\nimport { Icon } from '@iconify/vue';\nimport { ElButton } from 'element-plus';\n\ninterface Props {\n icon?: object | string;\n label?: string | undefined;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n icon: undefined,\n label: undefined,\n});\n\nconst attrs = useAttrs();\n\n// 创建 Iconify 图标组件\nfunction createIconifyIcon(iconName: string) {\n return defineComponent({\n name: `Icon-${iconName}`,\n setup(iconProps, { attrs: iconAttrs }) {\n return () => h(Icon, { icon: iconName, ...iconProps, ...iconAttrs });\n },\n });\n}\n\nfunction getIconComponent() {\n if (!props.icon) return undefined;\n\n if (typeof props.icon === 'string' && props.icon.includes(':')) {\n return createIconifyIcon(props.icon);\n }\n\n return props.icon;\n}\n</script>\n\n<template>\n <component\n v-if=\"label\"\n :is=\"ElButton\"\n v-bind=\"attrs\"\n :icon=\"getIconComponent()\"\n >\n {{ label }}\n </component>\n <component v-else :is=\"ElButton\" v-bind=\"attrs\" :icon=\"getIconComponent()\" />\n</template>\n","import ElButtonPlus from './ElButtonPlus.vue';\nimport type { App } from 'vue';\n\n(ElButtonPlus as any).name = 'ElButtonPlus';\n\nElButtonPlus.install = (app: App) => {\n app.component('ElButtonPlus', ElButtonPlus);\n};\n\nexport { ElButtonPlus };\n","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue';\n\ninterface Props {\n span?: number;\n offset?: number;\n break?: boolean;\n tag?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n span: 24,\n offset: 0,\n break: false,\n tag: 'div',\n});\n\nconst gridRef = inject<any>('elRowPlusGrid', computed(() => 24));\nconst gutterRef = inject<any>('elRowPlusGutter', computed(() => 0));\n\nconst grid = computed(() => gridRef?.value ?? 24);\nconst gutter = computed(() => gutterRef?.value ?? 0);\n\nconst isBreak = computed(() => props.break);\n\nconst colStyle = computed(() => {\n const style: any = {\n boxSizing: 'border-box',\n };\n\n const widthPercent = (props.span / grid.value) * 100;\n style.width = `${widthPercent}%`;\n style.flex = `0 0 ${widthPercent}%`;\n\n if (props.offset > 0) {\n const offsetPercent = (props.offset / grid.value) * 100;\n style.marginLeft = `${offsetPercent}%`;\n }\n\n if (gutter.value) {\n style.paddingLeft = `${gutter.value / 2}px`;\n style.paddingRight = `${gutter.value / 2}px`;\n }\n\n return style;\n});\n\nconst colClass = computed(() => {\n return ['el-col-plus'];\n});\n\nconst breakStyle = {\n flex: '1 0 100%',\n width: '100%',\n height: '0',\n visibility: 'hidden' as const,\n};\n</script>\n\n<template>\n <div v-if=\"isBreak\" :style=\"breakStyle\" aria-hidden=\"true\"></div>\n <component :is=\"tag\" :class=\"colClass\" :style=\"colStyle\">\n <slot></slot>\n </component>\n</template>\n\n<style scoped lang=\"scss\">\n.el-col-plus {\n box-sizing: border-box;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue';\n\ninterface Props {\n span?: number;\n offset?: number;\n break?: boolean;\n tag?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n span: 24,\n offset: 0,\n break: false,\n tag: 'div',\n});\n\nconst gridRef = inject<any>('elRowPlusGrid', computed(() => 24));\nconst gutterRef = inject<any>('elRowPlusGutter', computed(() => 0));\n\nconst grid = computed(() => gridRef?.value ?? 24);\nconst gutter = computed(() => gutterRef?.value ?? 0);\n\nconst isBreak = computed(() => props.break);\n\nconst colStyle = computed(() => {\n const style: any = {\n boxSizing: 'border-box',\n };\n\n const widthPercent = (props.span / grid.value) * 100;\n style.width = `${widthPercent}%`;\n style.flex = `0 0 ${widthPercent}%`;\n\n if (props.offset > 0) {\n const offsetPercent = (props.offset / grid.value) * 100;\n style.marginLeft = `${offsetPercent}%`;\n }\n\n if (gutter.value) {\n style.paddingLeft = `${gutter.value / 2}px`;\n style.paddingRight = `${gutter.value / 2}px`;\n }\n\n return style;\n});\n\nconst colClass = computed(() => {\n return ['el-col-plus'];\n});\n\nconst breakStyle = {\n flex: '1 0 100%',\n width: '100%',\n height: '0',\n visibility: 'hidden' as const,\n};\n</script>\n\n<template>\n <div v-if=\"isBreak\" :style=\"breakStyle\" aria-hidden=\"true\"></div>\n <component :is=\"tag\" :class=\"colClass\" :style=\"colStyle\">\n <slot></slot>\n </component>\n</template>\n\n<style scoped lang=\"scss\">\n.el-col-plus {\n box-sizing: border-box;\n}\n</style>\n","import ElColPlus from './ElColPlus.vue';\nimport type { App } from 'vue';\n\n(ElColPlus as any).name = 'ElColPlus';\n\nElColPlus.install = (app: App) => {\n app.component('ElColPlus', ElColPlus);\n};\n\nexport { ElColPlus };\n","<script setup lang=\"ts\">\nimport { computed, provide, useAttrs } from 'vue';\n\ninterface Props {\n grid?: number;\n gutter?: number;\n justify?:\n | 'center'\n | 'end'\n | 'space-around'\n | 'space-between'\n | 'space-evenly'\n | 'start';\n align?: 'bottom' | 'middle' | 'top';\n tag?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n grid: 24,\n gutter: 0,\n justify: 'start',\n align: 'top',\n tag: 'div',\n});\n\nconst attrs = useAttrs();\n\nprovide('elRowPlusGrid', computed(() => props.grid));\nprovide('elRowPlusGutter', computed(() => props.gutter));\n\nconst rowStyle = computed(() => {\n const style: any = {\n display: 'flex',\n flexWrap: 'wrap',\n };\n\n if (props.gutter) {\n style.marginLeft = `-${props.gutter / 2}px`;\n style.marginRight = `-${props.gutter / 2}px`;\n }\n\n const justifyMap = {\n start: 'flex-start',\n end: 'flex-end',\n center: 'center',\n 'space-around': 'space-around',\n 'space-between': 'space-between',\n 'space-evenly': 'space-evenly',\n };\n style.justifyContent = justifyMap[props.justify];\n\n const alignMap = {\n top: 'flex-start',\n middle: 'center',\n bottom: 'flex-end',\n };\n style.alignItems = alignMap[props.align];\n\n return style;\n});\n\nconst rowClass = computed(() => {\n return ['el-row-plus', attrs.class];\n});\n</script>\n\n<template>\n <component :is=\"tag\" :class=\"rowClass\" :style=\"rowStyle\">\n <slot></slot>\n </component>\n</template>\n\n<style scoped lang=\"scss\">\n.el-row-plus {\n box-sizing: border-box;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, provide, useAttrs } from 'vue';\n\ninterface Props {\n grid?: number;\n gutter?: number;\n justify?:\n | 'center'\n | 'end'\n | 'space-around'\n | 'space-between'\n | 'space-evenly'\n | 'start';\n align?: 'bottom' | 'middle' | 'top';\n tag?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n grid: 24,\n gutter: 0,\n justify: 'start',\n align: 'top',\n tag: 'div',\n});\n\nconst attrs = useAttrs();\n\nprovide('elRowPlusGrid', computed(() => props.grid));\nprovide('elRowPlusGutter', computed(() => props.gutter));\n\nconst rowStyle = computed(() => {\n const style: any = {\n display: 'flex',\n flexWrap: 'wrap',\n };\n\n if (props.gutter) {\n style.marginLeft = `-${props.gutter / 2}px`;\n style.marginRight = `-${props.gutter / 2}px`;\n }\n\n const justifyMap = {\n start: 'flex-start',\n end: 'flex-end',\n center: 'center',\n 'space-around': 'space-around',\n 'space-between': 'space-between',\n 'space-evenly': 'space-evenly',\n };\n style.justifyContent = justifyMap[props.justify];\n\n const alignMap = {\n top: 'flex-start',\n middle: 'center',\n bottom: 'flex-end',\n };\n style.alignItems = alignMap[props.align];\n\n return style;\n});\n\nconst rowClass = computed(() => {\n return ['el-row-plus', attrs.class];\n});\n</script>\n\n<template>\n <component :is=\"tag\" :class=\"rowClass\" :style=\"rowStyle\">\n <slot></slot>\n </component>\n</template>\n\n<style scoped lang=\"scss\">\n.el-row-plus {\n box-sizing: border-box;\n}\n</style>\n","import ElRowPlus from './ElRowPlus.vue';\nimport type { App } from 'vue';\n\n(ElRowPlus as any).name = 'ElRowPlus';\n\nElRowPlus.install = (app: App) => {\n app.component('ElRowPlus', ElRowPlus);\n};\n\nexport { ElRowPlus };\n","/**\n * 判断某个值是否存在与某个数组中\n * 如果key是字符串则直接取array的item[key] 数组则是取array的item[key0][key1][key2]... 留空则直接返回item是否等于value\n * @param value 值\n * @param array 数组\n * @param key 键\n */\nexport function isInArray(\n value: any,\n array: any[],\n key?: null | string | string[],\n): boolean {\n return array.some((item) => {\n if (typeof key === 'string') {\n return item[key] === value;\n } else if (Array.isArray(key)) {\n let v = item;\n for (const element of key) {\n if (!v) {\n return false;\n }\n v = v[element];\n }\n\n return (v = value);\n } else {\n return item === key;\n }\n });\n}\n\n/**\n * 获取valueArray还在array的值\n * @param valueArray\n * @param array\n * @param key\n */\nexport function valueArrayInArray(\n valueArray: any[],\n array: any[],\n key?: null | string | string[],\n): any[] {\n return valueArray.filter((v) => {\n const foundItem = array.find((opt) => {\n // 如果是字符串 则直接取下标值\n if (typeof key === 'string') {\n return opt[key] === v;\n } else if (Array.isArray(key)) {\n // 若是数组 则循环取得下标值\n let subscript = opt;\n for (const element of key) {\n if (!subscript) {\n return false;\n }\n\n subscript = subscript[element];\n }\n\n return v === subscript;\n } else {\n return v === opt;\n }\n });\n\n return !!foundItem;\n });\n}\n\n/**\n * 入参是一个数组和一个值,如果数组存在这个值,则移除掉里面所有的这个值并返回移除后的数组\n * @param array\n * @param value\n */\nexport function removeValueFromArray(array: any[], value: any): any[] {\n return array.filter((item) => item !== value);\n}\n\ninterface LabelFromArrayByValue {\n /**\n * 选项 类似于下拉框选项格式\n * [\n * {\n * value: 'option1',\n * label: '选项1',\n * },\n * {\n * value: 'option2',\n * label: '选项2',\n * },\n * {\n * value: 'option3',\n * label: '选项3',\n * }\n * ]\n */\n options: any[];\n /**\n * 查询值\n * 例如option1 或者 ['option1', 'option3']\n */\n value: number | number[] | string | string[];\n /**\n * value字段 对应例子里面的value\n */\n valueField: string;\n /**\n * label字段 对应例子里面的label\n */\n labelField: string;\n}\n\n/**\n * 在数组里面查询label\n * @param params\n */\nexport function getLabelFromArrayByValue(params: LabelFromArrayByValue): any {\n const { options, value, valueField, labelField } = params;\n\n // 构建一个Map,便于快速查找\n const valueLabelMap = new Map(\n options.map((item) => [item[valueField], item[labelField]]),\n );\n\n return Array.isArray(value)\n ? value\n .map((val) => valueLabelMap.get(val))\n .filter((label) => label !== undefined)\n : valueLabelMap.get(value);\n}\n\n/**\n * 去除数组对象中的某些字段\n * @param array\n * @param fieldsToOmit\n */\nexport function omitFieldsFromObjects(\n array: any[],\n fieldsToOmit: string | string[],\n) {\n // 确保 fieldsToOmit 是数组\n const fieldsSet = new Set(\n Array.isArray(fieldsToOmit) ? fieldsToOmit : [fieldsToOmit],\n );\n\n return array.map((obj) => {\n const newObj = { ...obj };\n fieldsSet.forEach((field) => {\n delete newObj[field];\n });\n return newObj;\n });\n}\n\n/**\n * 合并数组\n * @param array1 被更新的数组\n * @param array2 更新数组数据\n * @param keyField 主键字段\n */\nexport function mergeArraysByKey(\n array1: any[],\n array2: any[],\n keyField: string,\n) {\n // 将 array2 转为以 keyField 为键的 Map,便于快速查找\n const map2 = new Map(array2.map((item) => [item[keyField], item]));\n\n // 遍历 array1,合并对应项\n return array1.map((item) => {\n const match = map2.get(item[keyField]);\n if (match) {\n // 存在匹配项,合并对象(array2 覆盖 array1)\n return { ...item, ...match };\n }\n // 无匹配,直接返回 array1 的原始项\n return { ...item };\n });\n}\n","export default \"data:image/svg+xml,%3c?xml%20version='1.0'%20standalone='no'?%3e%3c!DOCTYPE%20svg%20PUBLIC%20'-//W3C//DTD%20SVG%201.1//EN'%20'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'%3e%3csvg%20t='1733885957959'%20class='icon'%20viewBox='0%200%201024%201024'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20p-id='2989'%20width='32'%20height='32'%20xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3cpath%20d='M1012.216%20466.752l-91.96-30.936%2050.56-82.808c-53.152-42.144-146.784-51.36-239.864-17.48a353.328%20353.328%200%200%200-36.904%2015.888c0.608-8.424%200.936-16.976%200.936-25.64%200-99.048-40.688-183.888-98.464-219.416L536%20182.192l-60.52-75.832c-57.776%2035.536-98.464%20120.368-98.464%20219.416%200%208.664%200.328%2017.216%200.936%2025.64a353.328%20353.328%200%200%200-36.904-15.888c-93.08-33.88-186.712-24.664-239.864%2017.48l50.56%2082.808-91.96%2030.936c13.632%2066.448%2079.432%20133.696%20172.512%20167.576%2011.088%204.032%2022.176%207.44%2033.208%2010.264-2.8%202.936-5.56%205.936-8.288%209-65.848%2073.992-91.856%20164.416-72.312%20229.368l95.624-16.416-5.2%2096.88c66.784%2011.864%20153.576-24.456%20219.424-98.456A346.672%20346.672%200%200%200%20536%20808.04a346.336%20346.336%200%200%200%2041.248%2056.928c65.848%2073.992%20152.64%20110.32%20219.424%2098.456l-5.2-96.88%2095.624%2016.416c19.544-64.96-6.464-155.376-72.312-229.368a372.976%20372.976%200%200%200-8.288-9%20355.84%20355.84%200%200%200%2033.208-10.264c93.08-33.88%20158.88-101.128%20172.512-167.576z'%20fill='%23E6E7E8'%20p-id='2990'%3e%3c/path%3e%3cpath%20d='M972.216%20426.752l-91.96-30.936%2050.56-82.808c-53.152-42.144-146.784-51.36-239.864-17.48a353.328%20353.328%200%200%200-36.904%2015.888c0.608-8.424%200.936-16.976%200.936-25.64%200-99.048-40.688-183.888-98.464-219.416L496%20142.192l-60.52-75.832c-57.776%2035.536-98.464%20120.368-98.464%20219.416%200%208.664%200.328%2017.216%200.936%2025.64a353.328%20353.328%200%200%200-36.904-15.888c-93.08-33.88-186.712-24.664-239.864%2017.48l50.56%2082.808-91.96%2030.936c13.632%2066.448%2079.432%20133.696%20172.512%20167.576%2011.088%204.032%2022.176%207.44%2033.208%2010.264-2.8%202.936-5.56%205.936-8.288%209-65.848%2073.992-91.856%20164.416-72.312%20229.368l95.624-16.416-5.2%2096.88c66.784%2011.864%20153.576-24.456%20219.424-98.456A346.672%20346.672%200%200%200%20496%20768.04a346.336%20346.336%200%200%200%2041.248%2056.928c65.848%2073.992%20152.64%20110.32%20219.424%2098.456l-5.2-96.88%2095.624%2016.416c19.544-64.96-6.464-155.376-72.312-229.368a372.976%20372.976%200%200%200-8.288-9%20355.84%20355.84%200%200%200%2033.208-10.264c93.08-33.88%20158.88-101.128%20172.512-167.576z'%20fill='%23FFFFFF'%20p-id='2991'%3e%3c/path%3e%3cpath%20d='M972.216%20450.752l-91.96-30.936%2050.56-82.808c-53.152-42.144-146.784-51.36-239.864-17.48a353.328%20353.328%200%200%200-36.904%2015.888c0.608-8.424%200.936-16.976%200.936-25.64%200-99.048-40.688-183.888-98.464-219.416L496%20166.192l-60.52-75.832c-57.776%2035.536-98.464%20120.368-98.464%20219.416%200%208.664%200.328%2017.216%200.936%2025.64a353.328%20353.328%200%200%200-36.904-15.888c-93.08-33.88-186.712-24.664-239.864%2017.48l50.56%2082.808-91.96%2030.936c13.632%2066.448%2079.432%20133.696%20172.512%20167.576%2011.088%204.032%2022.176%207.44%2033.208%2010.264-2.8%202.936-5.56%205.936-8.288%209-65.848%2073.992-91.856%20164.416-72.312%20229.368l95.624-16.416-5.2%2096.88c66.784%2011.864%20153.576-24.456%20219.424-98.456A346.672%20346.672%200%200%200%20496%20792.04a346.336%20346.336%200%200%200%2041.248%2056.928c65.848%2073.992%20152.64%20110.32%20219.424%2098.456l-5.2-96.88%2095.624%2016.416c19.544-64.96-6.464-155.376-72.312-229.368a372.976%20372.976%200%200%200-8.288-9%20355.84%20355.84%200%200%200%2033.208-10.264c93.08-33.88%20158.88-101.128%20172.512-167.576z'%20fill='%23FFD7E5'%20p-id='2992'%3e%3c/path%3e%3cpath%20d='M445.552%20823.232a340.816%20340.816%200%200%201-39.248%2036.696%208%208%200%200%200%209.952%2012.528%20355.864%20355.864%200%200%200%2041.096-38.424%208%208%200%201%200-11.8-10.8z'%20fill='%233A2C60'%20p-id='2993'%3e%3c/path%3e%3cpath%20d='M974.768%20419.168l-82.464-27.744%2045.336-74.248a8%208%200%200%200-1.856-10.44c-57.152-45.312-154.328-52.664-247.568-18.728-8.52%203.104-17.04%206.584-25.464%2010.4%200.152-4.24%200.224-8.464%200.224-12.632%200-99.224-40.144-188.024-102.272-226.24a8.024%208.024%200%200%200-10.448%201.832L496%20129.36l-54.272-68a8.008%208.008%200%200%200-10.448-1.824c-62.128%2038.208-102.272%20127.008-102.272%20226.232%200%204.16%200.08%208.376%200.224%2012.632a357.12%20357.12%200%200%200-25.456-10.392c-93.24-33.944-190.424-26.592-247.568%2018.728a8%208%200%200%200-1.856%2010.44l45.336%2074.248-82.456%2027.744a8%208%200%200%200-5.288%209.184C26.6%20499.808%2096.32%20567.904%20189.56%20601.84c6.928%202.52%2014.016%204.856%2021.192%206.976-65.624%2074.032-94.48%20166.776-73.512%20236.448a7.984%207.984%200%200%200%209.016%205.576L232%20836.128l-4.664%2086.872a8%208%200%200%200%206.592%208.304c46.632%208.304%20103.168-6.064%20155.12-39.368a7.992%207.992%200%200%200%202.416-11.048%207.976%207.976%200%200%200-11.048-2.416c-45.992%2029.472-95.384%2043.16-136.704%2038.128l4.656-86.816%2041.384-46.496a8%208%200%200%200-11.952-10.64l-41.384%2046.504-85.696%2014.712c-15.624-63.848%2012.296-147.312%2072.488-214.936%202.184-2.456%204.408-4.84%206.64-7.216l60.512-16.504a8%208%200%200%200-4.208-15.44l-60.608%2016.528a350.48%20350.48%200%200%201-30.504-9.48C109.96%20555.84%2045.776%20495.632%2029.224%20432.016l82.416-27.728%2058.496%2021.288a8%208%200%200%200%205.472-15.032l-58.48-21.288-45.328-74.216c53.568-38.096%20141.432-42.96%20226.52-11.992a345.72%20345.72%200%200%201%2034.56%2014.824l45.344%2045.304a8.008%208.008%200%200%200%2011.32-11.328l-43.744-43.704a348.424%20348.424%200%200%201-0.776-22.376c0-90.528%2034.624-171.44%2088.744-208.752L488%20144.992v62.24a8%208%200%200%200%2016%200v-62.248l54.24-67.968c54.12%2037.32%2088.744%20118.216%2088.744%20208.752%200%207.264-0.28%2014.688-0.76%2022.12l-43.84%2043.808a8%208%200%201%200%2011.32%2011.328l44.976-44.936a346.04%20346.04%200%200%201%2035.016-15.04c85.072-30.96%20172.944-26.096%20226.512%2012l-45.32%2074.224-58.48%2021.288a8%208%200%201%200%205.472%2015.032l58.496-21.288%2082.416%2027.728c-16.552%2063.616-80.736%20123.824-165.808%20154.792-9.896%203.6-20.16%206.76-30.512%209.48l-60.608-16.536a8%208%200%200%200-4.208%2015.44l60.528%2016.512c2.232%202.368%204.456%204.752%206.632%207.208%2060.184%2067.632%2088.112%20151.088%2072.488%20214.936l-85.696-14.712-41.384-46.504a8%208%200%200%200-11.952%2010.64l41.384%2046.496%204.656%2086.832c-65.208%208.096-144.88-29.312-205.064-96.952a338.216%20338.216%200%200%201-39.224-53.864V703.04a8%208%200%200%200-16%200v62.736a332.024%20332.024%200%200%201-22.12%2033.104%208%208%200%201%200%2012.736%209.68%20355.04%20355.04%200%200%200%2017.376-25.032%20358.056%20358.056%200%200%200%2035.272%2046.776c57.76%2064.912%20133.192%20103.384%20199.28%20103.376%209.384%200%2018.592-0.776%2027.52-2.36a8%208%200%200%200%206.592-8.304L760%20836.128l85.736%2014.712a7.96%207.96%200%200%200%209.016-5.576c20.968-69.672-7.888-162.408-73.512-236.448a362.76%20362.76%200%200%200%2021.192-6.976c93.24-33.944%20162.96-102.032%20177.616-173.488a7.984%207.984%200%200%200-5.28-9.184z'%20fill='%233A2C60'%20p-id='2994'%3e%3c/path%3e%3cpath%20d='M674.424%20463.856a28.72%2028.72%200%200%200-35.176-20.304%2028.624%2028.624%200%200%200-21.152%2027.12L531.632%20493.84c-5.424-10.8-15.448-18.896-27.632-21.368V375.12a28.624%2028.624%200%200%200%2020.72-27.448%2028.72%2028.72%200%201%200-57.44%200A28.624%2028.624%200%200%200%20488%20375.12v97.352c-12.184%202.472-22.208%2010.56-27.632%2021.368l-86.472-23.168a28.632%2028.632%200%200%200-21.152-27.12%2028.72%2028.72%200%200%200-14.872%2055.48c12.624%203.384%2025.424-2.28%2031.88-12.912l86.48%2023.168c-0.048%200.8-0.24%201.56-0.24%202.376%200%2010.16%203.904%2019.32%2010.144%2026.376l-53.816%2071.536a28.64%2028.64%200%200%200-33.056%209.48%2028.72%2028.72%200%201%200%2045.904%2034.528c7.856-10.44%207.392-24.432-0.056-34.392l53.792-71.504c5.2%202.472%2010.952%203.968%2017.096%203.968s11.896-1.496%2017.096-3.968l53.792%2071.504c-7.448%209.96-7.912%2023.952-0.056%2034.392a28.72%2028.72%200%200%200%2045.904-34.528%2028.64%2028.64%200%200%200-33.056-9.48l-53.816-71.536A39.68%2039.68%200%200%200%20536%20511.664c0-0.816-0.192-1.576-0.24-2.376l86.48-23.168a28.64%2028.64%200%200%200%2031.88%2012.912%2028.72%2028.72%200%200%200%2020.304-35.176z'%20fill='%23FA759E'%20p-id='2995'%3e%3c/path%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3c?xml%20version='1.0'%20standalone='no'?%3e%3c!DOCTYPE%20svg%20PUBLIC%20'-//W3C//DTD%20SVG%201.1//EN'%20'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'%3e%3csvg%20t='1735202912040'%20class='icon'%20viewBox='0%200%201024%201024'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20p-id='4284'%20width='16'%20height='16'%20xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3cpath%20d='M517.119%20954.878c244.589%200%20442.879-198.289%20442.879-442.879%200-244.594-198.289-442.879-442.879-442.879C272.524%2069.12%2074.24%20267.404%2074.24%20511.999%2074.24%20756.588%20272.524%20954.878%20517.119%20954.878L517.119%20954.878zM517.119%20891.608c-209.654%200-379.612-169.955-379.612-379.609s169.957-379.612%20379.612-379.612%20379.609%20169.957%20379.609%20379.612S726.773%20891.608%20517.119%20891.608L517.119%20891.608zM523.949%20243.992c-54.662%200-97.177%2016.705-127.547%2050.112-30.367%2031.885-44.795%2074.402-44.795%20127.547l59.98%200c0-37.202%208.35-66.052%2025.055-87.31%2018.222-25.055%2046.312-37.202%2084.272-37.202%2031.885%200%2056.945%208.352%2074.405%2026.572%2016.705%2016.702%2025.81%2040.24%2025.81%2070.607%200%2021.26-7.59%2041-22.775%2059.98-4.55%206.072-13.665%2015.185-25.81%2027.33-41%2036.445-66.055%2065.295-76.685%2088.075-9.11%2018.98-13.665%2040.995-13.665%2066.05l0%2017.465%2060.735%200%200-17.465c0-20.5%204.56-38.725%2014.43-55.425%207.59-13.665%2018.98-27.335%2035.68-41.755%2033.405-29.612%2053.91-49.352%2061.5-58.462%2018.98-25.055%2028.85-54.665%2028.85-88.83%200-45.552-14.425-81.235-42.515-107.05C611.258%20256.902%20572.544%20243.992%20523.949%20243.992L523.949%20243.992zM512.564%20706.363c-12.907%200-23.535%203.795-32.647%2012.905-9.11%208.345-12.905%2018.98-12.905%2031.885s3.795%2023.54%2012.905%2032.65c9.112%208.345%2019.74%2012.905%2032.647%2012.905%2012.91%200%2023.535-4.56%2032.645-12.905%209.11-8.355%2013.665-18.985%2013.665-32.65%200-12.905-4.555-23.54-12.905-31.885C536.859%20710.158%20525.474%20706.363%20512.564%20706.363L512.564%20706.363z'%20fill='%23272636'%20p-id='4285'%3e%3c/path%3e%3c/svg%3e\"","import dayjs from 'dayjs';\n\nconst modules = import.meta.glob('../assets/**', {\n eager: true,\n import: 'default',\n});\n\n/**\n * 获取指定长度的随机字符串\n * @param length\n */\nexport function getRandomString(length: number): string {\n let result = '';\n const characters =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n const charactersLength = characters.length;\n for (let i = 0; i < length; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n return result;\n}\n\n/**\n * 获取资源目录下的文件\n * @param filePath components-image/chart/BarChart.jpg\n */\nexport const getAssetUrl = (filePath: string): any => {\n return modules[`../assets/${filePath}`];\n};\n","export function isEmpty<T>(val: '' | null | T | undefined): val is '' | null | undefined {\n return val === undefined || val === null || val === '';\n}\nexport function isNotEmpty<T>(val: '' | null | T | undefined): val is T {\n return val !== undefined && val !== null && val !== '';\n}\n\nconst patternList = {\n mail: /\\w[-\\w.+]*@([A-Z0-9][-A-Z0-9]+\\.)+[A-Z]{2,14}/i,\n // 密码强度:数字+非数字,或小写字母+非小写字母(即至少两类)\n CryptographicStrength:\n /(?:(?=.*\\d)(?=.*\\D)|(?=.*[a-z])(?=.*[^a-z]))(?!^[^\\n\\r\\u2028\\u2029\\u4E00-\\u9FA5]*[\\u4E00-\\u9FA5].*$)/i,\n};\n\n// 密码强度 数字 字母 符号至少包含两种\nexport function cryptographicStrength(password: string) {\n return patternList.CryptographicStrength.test(password);\n}\n\nexport function isImage(type: string): boolean {\n return ['image/gif', 'image/jpeg', 'image/png'].includes(type);\n}\nexport function isMail(mail: string): boolean {\n return patternList.mail.test(mail);\n}","import { dayjs } from 'element-plus';\n\nimport { isEmpty, isNotEmpty } from './validate';\nimport type { translateJSON, translateObj } from '@/types';\n\n/**\n * 格式化时间戳\n *\n * @param t\n * @param f\n */\nexport const timestamp = (t: string, f?: string) => {\n if (t === null) {\n return t;\n }\n return dayjs(t).format(f || 'YYYY-MM-DD HH:mm:ss');\n};\n\nexport const stringList = (s: any): string | null => {\n if (typeof s === 'object' && !Array.isArray(s)) {\n try {\n if (s !== '' && s !== null && s.type) return s.value;\n } catch (error) {\n // console.log(cellValue)\n console.error(error);\n }\n } else if (s.type) {\n const array: [string] = JSON.parse(s.value);\n return array.length > 0 ? array[array.length - 1] : '';\n }\n\n return s === null ? null : s.toString();\n};\n\ninterface FormatterArray {\n /**\n * cellValue\n */\n value: any;\n /**\n * 翻译的数组\n */\n array: { label: any; value: any }[];\n /**\n * 字段名\n */\n fieldName: string;\n /**\n * 已经循环过存放的数据\n * {\n * field1: {\n * value: label,\n * value2: label2\n * },\n * field2: {\n * value: label\n * }\n * }\n */\n translateObject: any;\n /**\n * 存放已循环过的索引\n */\n translateIndexArray: any;\n}\nexport const formatterData = {\n toString: (value: any) => {\n if (value === null || value === undefined) {\n return null;\n }\n return typeof value === 'string' ? value : value.toString();\n },\n parseInt: (value: any) => {\n return Number.parseInt(value, 10);\n },\n array: (params: FormatterArray) => {\n // 从translateData查找是否已经通过for循环获取 如果已经获取则直接返回\n if (\n params.translateObject[params.fieldName] &&\n isNotEmpty(params.translateObject[params.fieldName][params.value])\n )\n return params.translateObject[params.fieldName][params.value];\n\n if (!params.translateObject[params.fieldName]) {\n params.translateObject[params.fieldName] = {};\n params.translateIndexArray[params.fieldName] = {\n index: 0,\n };\n }\n\n for (\n let i = params.translateIndexArray[params.fieldName].index;\n i < params.array.length;\n i += 1\n ) {\n // 将循环的结果存到translateData\n params.translateObject[params.fieldName][params.array[i].value] =\n params.array[i].label;\n // 把当前索引存放 避免存放循环\n params.translateIndexArray[params.fieldName].index = i;\n if (params.array[i].value === params.value) {\n // 找到了则已经循环过的数据\n\n return params.array[i].label;\n }\n }\n\n // 如果循环完了也没找到 则直接返回原数据\n return params.value;\n },\n};\n\nconst dataFormatter: any = { timestamp, stringList, ...formatterData };\n\n\ninterface FormatterOptions {\n /** 表格数据 */\n cellValue: any;\n tabObj?: 'translate' | translateObj;\n translateJson: translateJSON;\n fieldName: string;\n /**\n * 翻译后的数据缓存 // 配合formatterData.array食用\n */\n translateObject?: any;\n /**\n * 循环索引\n */\n translateIndexArray?: { [propName: string]: any };\n}\n\nexport const customFormatter = (options: FormatterOptions): any => {\n if (isEmpty(options.cellValue) || isEmpty(options.tabObj))\n return options.cellValue;\n\n if (options.tabObj === 'translate') {\n return dataFormatter.array({\n value: options.cellValue,\n array: <{ label: any; value: any }[]>options.translateJson,\n fieldName: options.fieldName,\n translateObject: options.translateObject,\n translateIndexArray: options.translateIndexArray,\n });\n }\n\n if (options.tabObj) {\n return dataFormatter[options.tabObj](options.cellValue);\n }\n return options.cellValue;\n};\n\nexport { dataFormatter };\n","import { isNotEmpty } from './validate';\nimport solarday2lunarday from 'solarday2lunarday';\n\n/**\n * 获取n天后的时间戳\n * @param n\n */\nexport function getTimeStampAfterNDay(n: number) {\n const now = new Date();\n now.setDate(now.getDate() + n);\n return now;\n}\n\n/**\n * 获取农历\n * @param date\n */\nexport const getLunar = (date: any) => {\n const lunar: any = solarday2lunarday.solar2lunar(date.timestamp);\n\n if (isNotEmpty(lunar.festivalName)) {\n return lunar.festivalName;\n } else if (lunar.IDayCn === '初一') {\n return lunar.IMonthCn;\n }\n\n return lunar.IDayCn;\n};\n\n/**\n * 根据时间戳获取相差时间\n * @param startTimestamp 小的时间\n * @param endTimestamp 大的时间\n */\nexport const calculateTimeDifference = (\n startTimestamp: number,\n endTimestamp: number,\n) => {\n const diffInMilliseconds = endTimestamp - startTimestamp; // 获取时间差(毫秒)\n\n const days = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24)); // 计算天数\n const hours = Math.floor(\n (diffInMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60),\n ); // 计算小时\n const minutes = Math.floor(\n (diffInMilliseconds % (1000 * 60 * 60)) / (1000 * 60),\n ); // 计算分钟\n const seconds = Math.floor((diffInMilliseconds % (1000 * 60)) / 1000); // 计算秒数\n\n return `${days}天 ${hours}时 ${minutes}分 ${seconds}秒`;\n};\n\n/**\n * 获取显示时间\n * @param dateTimeStr\n * @param onlyOne 当非今天时 是否只显示日期\n */\nexport function getShowFormatDateTime(dateTimeStr: string, onlyOne?: boolean) {\n const inputDate = new Date(dateTimeStr);\n const today = new Date();\n\n // 判断是否为今天\n const isToday =\n inputDate.getFullYear() === today.getFullYear() &&\n inputDate.getMonth() === today.getMonth() &&\n inputDate.getDate() === today.getDate();\n\n if (isToday) {\n // 返回时间(格式:HH:mm:ss)\n return inputDate.toTimeString().split(' ')[0];\n } else {\n if (onlyOne) {\n return inputDate.toISOString().split('T')[0];\n }\n // 返回日期(格式:YYYY-MM-DD)\n return `${inputDate.toISOString().split('T')[0]} ${inputDate.toTimeString().split(' ')[0]}`;\n }\n}\n","import type { Emitter } from 'mitt';\n\nimport mitt from 'mitt';\n\ntype Events = {\n [key: string]: any; // 你可以具体定义事件和参数类型\n};\n\nexport const emitter: Emitter<Events> = mitt();\n","import type { FormInstance } from 'element-plus';\n\nimport { cryptographicStrength, isMail } from './validate';\n\n/** 表单验证 */\nconst formCheck = async (ref: FormInstance) => {\n if (!ref) return false;\n try {\n await ref.validate();\n return true;\n } catch (error) {\n console.error(error);\n return false;\n }\n};\n\n/** 表单rule验证 */\nconst formValidates = {\n isEmail: (_rule: any, value: string, callback: any) => {\n if (value === '' || isMail(value)) {\n callback();\n }\n callback(new Error('邮箱格式不正确!'));\n },\n /**\n * 判断值的长度或值的范围\n *\n * @param _rule\n * @param value\n * @param callback\n * @param l1 不能小于此参数 | 长度必须等于此\n * @param l2\n */\n length: (\n _rule: any,\n value: string,\n callback: any,\n l1: number,\n l2?: number,\n ) => {\n // 如果l2不存在 则表示是判断长度是否想等\n if (l2) {\n if (value.length <= l1) {\n callback(new Error(`长度不能小于${l1}`));\n return;\n }\n\n if (value.length > l2) {\n callback(new Error(`长度不能大于${l2}`));\n return;\n }\n\n callback();\n } else {\n if (value.length === l1) {\n callback();\n } else {\n callback(new Error(`该值不等于${l1}`));\n }\n }\n },\n /**\n * 判断密码是否包含了数字和字母\n *\n * @param _rule\n * @param value\n * @param callback\n */\n passwordVerify: (_rule: any, value: string, callback: any) => {\n if (cryptographicStrength(value)) {\n callback();\n } else {\n callback(\n new Error('密码需至少包含数字 字母 符号两种,且长度必须大于8小于16'),\n );\n }\n },\n same: (\n _rule: any,\n value: string,\n callback: any,\n value2: any,\n msg?: string,\n ) => {\n if (value === value2) {\n callback();\n } else {\n callback(new Error(msg ?? '两个值不相同'));\n }\n },\n};\n\nexport { formCheck, formValidates };\n","import { ElMessage, ElMessageBox, ElNotification } from 'element-plus';\n\nimport { isEmpty, isNotEmpty } from './validate';\n\ntype TipsType = 'error' | 'info' | 'success' | 'warning';\n\nconst getTitle = (type: TipsType = 'info'): string => {\n if (isEmpty(type)) {\n return '';\n }\n return type;\n // return $t(`tipsType.${type === 'error' ? 'danger' : type}`);\n};\n\ninterface MsgParams {\n title?: string;\n msg: string;\n /**\n * 确定回调\n */\n callback?: Function;\n /**\n * 取消回调\n */\n catch?: Function;\n /**\n * 消息持续时间\n */\n duration?: number;\n}\ninterface MsgParamsTips extends MsgParams {\n type?: TipsType;\n}\n\n/**\n * 弹窗提示\n * @param params\n */\nconst alert = (params: MsgParamsTips) => {\n // 当有一个不为空时 则需要确认\n if (isNotEmpty(params.callback) || isNotEmpty(params.catch)) {\n ElMessageBox.confirm(params.msg, getTitle(params.type), {\n confirmButtonText: 'OK',\n cancelButtonText: 'Cancel',\n type: params.type,\n })\n .then(() => {\n if (params.callback) params.callback();\n })\n .catch(() => {\n if (params.catch) params.catch();\n });\n } else {\n ElMessageBox.alert(params.msg, getTitle(params.type), {\n type: params.type,\n });\n }\n};\n\nconst tips = (params: MsgParamsTips) => {\n ElMessage({\n message: params.msg,\n type: params.type ?? undefined,\n duration: params.duration ?? 3000,\n showClose: true,\n });\n};\n\n/**\n * 通知提示框\n *\n * @param params params\n */\nconst elNotification = (params: MsgParamsTips) => {\n ElNotification({\n title: params.title,\n message: params.msg,\n type: params.type,\n duration:\n params.type === 'warning' ? 6000 : (params.type === 'error' ? 8000 : 3000),\n });\n};\n\nconst msgTips = { alert, elNotification, tips };\n\nexport { msgTips };\n","import { isNotEmpty } from '@/utils';\n\nexport const mergeObjects = (queryData: any, typeData: any) => {\n const mergedObj: { [key: string]: { queryType?: string; val: any } } = {};\n\n // 合并 queryData 中的数据\n for (const key in queryData) {\n if (Object.hasOwn(queryData, key) && isNotEmpty(queryData[key])) {\n mergedObj[key] = {\n val: queryData[key],\n queryType: '',\n };\n }\n }\n\n // 将 typeData 中对应的类型信息添加到 mergedObj 中\n for (const key in typeData) {\n if (Object.hasOwn(typeData, key) && mergedObj[key]?.val) {\n mergedObj[key].queryType = typeData[key];\n }\n }\n\n return mergedObj;\n};\n","<script setup lang=\"ts\">\nimport { computed, reactive, ref, useTemplateRef } from 'vue';\n\nimport type { TableQueryFrame } from '@/types';\n\nimport { mergeObjects } from './hooks';\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\ninterface Props {\n frame: TableQueryFrame[];\n}\n\nconst props = defineProps<Props>();\n\nconst emits = defineEmits(['queryClick']);\n\nconst queryDataState = reactive<any>({});\nconst queryDataTypeState = reactive<any>({});\nconst showAll = ref(false);\n\nconst queryBarRef = useTemplateRef<HTMLDivElement>('query-bar-ref');\nconst debouncedWidth = ref(0);\nuseResizeObserver(\n queryBarRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedWidth.value = entry.contentRect.width;\n }\n }, 300),\n);\n\nconst spanEl = computed(() => {\n if (props.frame.length < 1) {\n return 24;\n } else if (debouncedWidth.value > 1920) {\n return 6;\n } else if (debouncedWidth.value >= 1200) {\n return 6;\n } else if (debouncedWidth.value >= 992) {\n return 8;\n } else if (debouncedWidth.value >= 768) {\n return 12;\n } else if (debouncedWidth.value >= 600) {\n return 12;\n }\n\n return 24;\n});\n\nconst queryClick = () => {\n emits('queryClick', mergeObjects(queryDataState, queryDataTypeState));\n};\n\nconst resetQuery = () => {\n Object.keys(queryDataState).forEach((key) => {\n queryDataState[key] = undefined;\n });\n Object.assign(queryDataState, {});\n};\n</script>\n\n<template>\n <el-form ref=\"query-bar-ref\" :model=\"queryDataState\" class=\"query-bar-client\">\n <el-row :gutter=\"12\">\n <template v-for=\"(item, index) in frame\" :key=\"item.fieldName\">\n <el-col\n v-show=\"showAll === true || (index + 2) * spanEl <= 24\"\n :span=\"spanEl\"\n >\n <el-form-item :label=\"item.fieldTitle\" :prop=\"item.fieldName\">\n <component\n :is=\"item.queryEditor\"\n v-model:query-type=\"queryDataTypeState[item.fieldName]\"\n v-model:value=\"queryDataState[item.fieldName]\"\n :detail=\"item\"\n />\n </el-form-item>\n </el-col>\n </template>\n <el-col :span=\"spanEl\">\n <el-form-item>\n <div style=\"width: 100%; text-align: right\">\n <el-button type=\"primary\" @click=\"queryClick\">\n 搜索\n </el-button>\n <el-button type=\"warning\" @click=\"resetQuery\">\n 重置\n </el-button>\n <el-button\n v-if=\"(frame.length + 1) * spanEl > 24\"\n text\n type=\"success\"\n @click=\"showAll = !showAll\"\n >\n {{ showAll ? '折叠' : '展开' }}\n </el-button>\n </div>\n </el-form-item>\n </el-col>\n </el-row>\n </el-form>\n</template>\n\n<style>\n.query-bar-client {\n padding: 8px 8px 0 8px;\n background: var(--el-fill-color-blank);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, reactive, ref, useTemplateRef } from 'vue';\n\nimport type { TableQueryFrame } from '@/types';\n\nimport { mergeObjects } from './hooks';\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\ninterface Props {\n frame: TableQueryFrame[];\n}\n\nconst props = defineProps<Props>();\n\nconst emits = defineEmits(['queryClick']);\n\nconst queryDataState = reactive<any>({});\nconst queryDataTypeState = reactive<any>({});\nconst showAll = ref(false);\n\nconst queryBarRef = useTemplateRef<HTMLDivElement>('query-bar-ref');\nconst debouncedWidth = ref(0);\nuseResizeObserver(\n queryBarRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedWidth.value = entry.contentRect.width;\n }\n }, 300),\n);\n\nconst spanEl = computed(() => {\n if (props.frame.length < 1) {\n return 24;\n } else if (debouncedWidth.value > 1920) {\n return 6;\n } else if (debouncedWidth.value >= 1200) {\n return 6;\n } else if (debouncedWidth.value >= 992) {\n return 8;\n } else if (debouncedWidth.value >= 768) {\n return 12;\n } else if (debouncedWidth.value >= 600) {\n return 12;\n }\n\n return 24;\n});\n\nconst queryClick = () => {\n emits('queryClick', mergeObjects(queryDataState, queryDataTypeState));\n};\n\nconst resetQuery = () => {\n Object.keys(queryDataState).forEach((key) => {\n queryDataState[key] = undefined;\n });\n Object.assign(queryDataState, {});\n};\n</script>\n\n<template>\n <el-form ref=\"query-bar-ref\" :model=\"queryDataState\" class=\"query-bar-client\">\n <el-row :gutter=\"12\">\n <template v-for=\"(item, index) in frame\" :key=\"item.fieldName\">\n <el-col\n v-show=\"showAll === true || (index + 2) * spanEl <= 24\"\n :span=\"spanEl\"\n >\n <el-form-item :label=\"item.fieldTitle\" :prop=\"item.fieldName\">\n <component\n :is=\"item.queryEditor\"\n v-model:query-type=\"queryDataTypeState[item.fieldName]\"\n v-model:value=\"queryDataState[item.fieldName]\"\n :detail=\"item\"\n />\n </el-form-item>\n </el-col>\n </template>\n <el-col :span=\"spanEl\">\n <el-form-item>\n <div style=\"width: 100%; text-align: right\">\n <el-button type=\"primary\" @click=\"queryClick\">\n 搜索\n </el-button>\n <el-button type=\"warning\" @click=\"resetQuery\">\n 重置\n </el-button>\n <el-button\n v-if=\"(frame.length + 1) * spanEl > 24\"\n text\n type=\"success\"\n @click=\"showAll = !showAll\"\n >\n {{ showAll ? '折叠' : '展开' }}\n </el-button>\n </div>\n </el-form-item>\n </el-col>\n </el-row>\n </el-form>\n</template>\n\n<style>\n.query-bar-client {\n padding: 8px 8px 0 8px;\n background: var(--el-fill-color-blank);\n}\n</style>\n","import QueryBar from './QueryBar.vue';\nimport type { App } from 'vue';\n\n(QueryBar as any).name = 'QueryBar';\n\nQueryBar.install = (app: App) => {\n app.component('QueryBar', QueryBar);\n};\n\nexport { QueryBar };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: string[];\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [Array] as PropType<string[]>,\n});\n\nconst shortcuts = [\n {\n text: '上周',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - 7);\n return [start, end];\n },\n },\n {\n text: '上个月',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setMonth(start.getMonth() - 1);\n return [start, end];\n },\n },\n {\n text: '三个月前',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setMonth(start.getMonth() - 3);\n return [start, end];\n },\n },\n];\n\nonMounted(() => {\n emit('update:queryType', 'range');\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueModel\"\n :shortcuts=\"shortcuts\"\n end-placeholder=\"结束日期\"\n format=\"YYYY-MM-DD HH:mm:ss\"\n range-separator=\"至\"\n start-placeholder=\"开始日期\"\n type=\"datetimerange\"\n value-format=\"YYYY-MM-DD HH:mm:ss\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: string[];\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [Array] as PropType<string[]>,\n});\n\nconst shortcuts = [\n {\n text: '上周',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - 7);\n return [start, end];\n },\n },\n {\n text: '上个月',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setMonth(start.getMonth() - 1);\n return [start, end];\n },\n },\n {\n text: '三个月前',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setMonth(start.getMonth() - 3);\n return [start, end];\n },\n },\n];\n\nonMounted(() => {\n emit('update:queryType', 'range');\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueModel\"\n :shortcuts=\"shortcuts\"\n end-placeholder=\"结束日期\"\n format=\"YYYY-MM-DD HH:mm:ss\"\n range-separator=\"至\"\n start-placeholder=\"开始日期\"\n type=\"datetimerange\"\n value-format=\"YYYY-MM-DD HH:mm:ss\"\n />\n</template>\n","import QueryDateTime from './QueryDateTime.vue';\nimport type { App } from 'vue';\n\n(QueryDateTime as any).name = 'QueryDateTime';\n\nQueryDateTime.install = (app: App) => {\n app.component('QueryDateTime', QueryDateTime);\n};\n\nexport { QueryDateTime };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: number | string;\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [String, Number] as PropType<number | string>,\n});\n\nonMounted(() => {\n emit('update:queryType', 'equals');\n});\n</script>\n\n<template>\n <el-input v-model=\"valueModel\" clearable />\n</template>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: number | string;\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [String, Number] as PropType<number | string>,\n});\n\nonMounted(() => {\n emit('update:queryType', 'equals');\n});\n</script>\n\n<template>\n <el-input v-model=\"valueModel\" clearable />\n</template>\n","import QueryInput from './QueryInput.vue';\nimport type { App } from 'vue';\n\n(QueryInput as any).name = 'QueryInput';\n\nQueryInput.install = (app: App) => {\n app.component('QueryInput', QueryInput);\n};\n\nexport { QueryInput };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: string | number;\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [String, Number] as PropType<number | string>,\n});\n\nonMounted(() => {\n emit('update:queryType', 'like');\n});\n</script>\n\n<template>\n <el-input v-model=\"valueModel\" clearable />\n</template>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: string | number;\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [String, Number] as PropType<number | string>,\n});\n\nonMounted(() => {\n emit('update:queryType', 'like');\n});\n</script>\n\n<template>\n <el-input v-model=\"valueModel\" clearable />\n</template>\n","import QueryInputLike from './QueryInputLike.vue';\nimport type { App } from 'vue';\n\n(QueryInputLike as any).name = 'QueryInputLike';\n\nQueryInputLike.install = (app: App) => {\n app.component('QueryInputLike', QueryInputLike);\n};\n\nexport { QueryInputLike };\n","<script setup lang=\"ts\">\nimport type { QuerySelector } from '../../../types';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value?: any;\n detail: QuerySelector;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: () => null,\n});\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueRef = defineModel('value');\n\nonMounted(() => {\n emit('update:queryType', 'equals');\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :options=\"detail?.options\"\n class=\"min-width\"\n clearable\n >\n <el-option\n v-for=\"item in detail?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped>\n.min-width {\n min-width: 120px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { QuerySelector } from '../../../types';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value?: any;\n detail: QuerySelector;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: () => null,\n});\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueRef = defineModel('value');\n\nonMounted(() => {\n emit('update:queryType', 'equals');\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :options=\"detail?.options\"\n class=\"min-width\"\n clearable\n >\n <el-option\n v-for=\"item in detail?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped>\n.min-width {\n min-width: 120px;\n}\n</style>\n","import QuerySelect from './QuerySelect.vue';\nimport type { App } from 'vue';\n\n(QuerySelect as any).name = 'QuerySelect';\n\nQuerySelect.install = (app: App) => {\n app.component('QuerySelect', QuerySelect);\n};\n\nexport { QuerySelect };\n","<script setup lang=\"ts\">\nimport type { FilterData } from './QueryTreeFilter';\n\nimport { ref } from 'vue';\n\nimport { getQueryTreeFilterDataApi } from '@/api';\nimport { removeValueFromArray } from '@/utils';\nimport { LoadFunction } from 'element-plus';\n\ninterface Props {\n pageId: number;\n}\n\nconst props = defineProps<Props>();\nconst emits = defineEmits(['checkChange']);\n/**\n * 被选择的\n */\nconst checkboxes = ref<any[]>([]);\n\n/**\n * 当复选框被点击的时候触发\n * @param data 传递给 data 属性的数组中该节点所对应的对象\n * @param checked 节点本身是否被选中\n * @param _indeterminate 节点的子树中是否有被选中的节点\n */\nconst handleCheckChange = (\n data: FilterData,\n checked: boolean,\n _indeterminate: boolean,\n) => {\n checkboxes.value =\n checked\n ? [...checkboxes.value, data.value]\n : removeValueFromArray(checkboxes.value, data.value);\n emits('checkChange');\n};\n\n/**\n * 加载节点\n */\nconst loadNode: LoadFunction = async (node, resolve: (data: any[]) => void, reject) => {\n const pid = node.data.value ?? null;\n const result = await getQueryTreeFilterDataApi({\n pageId: props.pageId,\n pid,\n });\n if (\n result.code === 0 &&\n Array.isArray(result.data.filterData) &&\n result.data.filterData.length > 0\n ) {\n return resolve(result.data.filterData);\n }\n\n reject();\n};\n\nconst getCheckboxes = () => {\n return {\n val: checkboxes.value,\n };\n};\n\ndefineExpose({ getCheckboxes });\n</script>\n\n<template>\n <div class=\"filterBoard\">\n <el-button type=\"primary\">全选</el-button>\n <div class=\"tree-container\">\n <el-scrollbar>\n <el-tree\n :load=\"loadNode\"\n lazy\n show-checkbox\n @check-change=\"handleCheckChange\"\n >\n <template #default=\"{ node, data }\">\n <span\n :class=\"checkboxes.includes(data.value) ? 'is-checked' : ''\"\n class=\"custom-tree-node\"\n >\n <span>{{ node.label }}</span>\n </span>\n </template>\n </el-tree>\n </el-scrollbar>\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.filterBoard {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n background: var(--el-fill-color-blank);\n margin: 6px 6px 6px 0;\n padding: 12px 8px 8px;\n height: calc(100% - 12px);\n\n .tree-container {\n margin-top: 12px;\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n }\n}\n\n.custom-tree-node {\n display: flex;\n flex: 1;\n align-items: center;\n justify-content: space-between;\n padding: 4px 4px 4px 6px;\n font-size: 14px;\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\n.is-checked {\n color: white;\n background-color: var(--el-color-primary) !important; /* 自定义背景颜色 */\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FilterData } from './QueryTreeFilter';\n\nimport { ref } from 'vue';\n\nimport { getQueryTreeFilterDataApi } from '@/api';\nimport { removeValueFromArray } from '@/utils';\nimport { LoadFunction } from 'element-plus';\n\ninterface Props {\n pageId: number;\n}\n\nconst props = defineProps<Props>();\nconst emits = defineEmits(['checkChange']);\n/**\n * 被选择的\n */\nconst checkboxes = ref<any[]>([]);\n\n/**\n * 当复选框被点击的时候触发\n * @param data 传递给 data 属性的数组中该节点所对应的对象\n * @param checked 节点本身是否被选中\n * @param _indeterminate 节点的子树中是否有被选中的节点\n */\nconst handleCheckChange = (\n data: FilterData,\n checked: boolean,\n _indeterminate: boolean,\n) => {\n checkboxes.value =\n checked\n ? [...checkboxes.value, data.value]\n : removeValueFromArray(checkboxes.value, data.value);\n emits('checkChange');\n};\n\n/**\n * 加载节点\n */\nconst loadNode: LoadFunction = async (node, resolve: (data: any[]) => void, reject) => {\n const pid = node.data.value ?? null;\n const result = await getQueryTreeFilterDataApi({\n pageId: props.pageId,\n pid,\n });\n if (\n result.code === 0 &&\n Array.isArray(result.data.filterData) &&\n result.data.filterData.length > 0\n ) {\n return resolve(result.data.filterData);\n }\n\n reject();\n};\n\nconst getCheckboxes = () => {\n return {\n val: checkboxes.value,\n };\n};\n\ndefineExpose({ getCheckboxes });\n</script>\n\n<template>\n <div class=\"filterBoard\">\n <el-button type=\"primary\">全选</el-button>\n <div class=\"tree-container\">\n <el-scrollbar>\n <el-tree\n :load=\"loadNode\"\n lazy\n show-checkbox\n @check-change=\"handleCheckChange\"\n >\n <template #default=\"{ node, data }\">\n <span\n :class=\"checkboxes.includes(data.value) ? 'is-checked' : ''\"\n class=\"custom-tree-node\"\n >\n <span>{{ node.label }}</span>\n </span>\n </template>\n </el-tree>\n </el-scrollbar>\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.filterBoard {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n background: var(--el-fill-color-blank);\n margin: 6px 6px 6px 0;\n padding: 12px 8px 8px;\n height: calc(100% - 12px);\n\n .tree-container {\n margin-top: 12px;\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n }\n}\n\n.custom-tree-node {\n display: flex;\n flex: 1;\n align-items: center;\n justify-content: space-between;\n padding: 4px 4px 4px 6px;\n font-size: 14px;\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\n.is-checked {\n color: white;\n background-color: var(--el-color-primary) !important; /* 自定义背景颜色 */\n}\n</style>\n","import QueryTreeFilter from './QueryTreeFilter.vue';\nimport type { App } from 'vue';\n\n(QueryTreeFilter as any).name = 'QueryTreeFilter';\n\nQueryTreeFilter.install = (app: App) => {\n app.component('QueryTreeFilter', QueryTreeFilter);\n};\n\nexport { QueryTreeFilter };\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '@/types';\n\nimport { nextTick, ref, unref } from 'vue';\n\ninterface Props {\n value?: null | number | string;\n detail: TableComponentFrame;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange']);\n\nconst popoverRef = ref();\nconst buttonRef = ref();\nconst modelVal = defineModel('value', {\n required: false,\n default: null,\n});\nconst inputValue = ref(null);\n\nconst edit = () => {\n inputValue.value = modelVal.value;\n};\n\nconst confirm = async () => {\n if (modelVal.value !== inputValue.value) {\n modelVal.value = inputValue.value;\n await nextTick();\n unref(popoverRef).popperRef?.delayHide?.();\n emits('valueChange', props.detail?.field, modelVal.value, props.rowData);\n }\n};\n</script>\n\n<template>\n <div>\n <span ref=\"buttonRef\" class=\"text\" @click.stop=\"edit\">\n <template\n v-if=\"modelVal === null || modelVal === '' || modelVal === undefined\"\n >\n <el-skeleton :rows=\"0\" />\n </template>\n <template v-else>\n {{ modelVal }}\n </template>\n </span>\n <el-popover\n ref=\"popoverRef\"\n :virtual-ref=\"buttonRef\"\n :width=\"200\"\n trigger=\"click\"\n virtual-triggering\n @hide=\"confirm\"\n >\n <el-input\n v-model=\"inputValue\"\n :placeholder=\"detail.placeholder\"\n v-bind=\"detail.editRender?.props?.componentParams\"\n />\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.text {\n width: 100%;\n cursor: pointer;\n display: inline-block;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '@/types';\n\nimport { nextTick, ref, unref } from 'vue';\n\ninterface Props {\n value?: null | number | string;\n detail: TableComponentFrame;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange']);\n\nconst popoverRef = ref();\nconst buttonRef = ref();\nconst modelVal = defineModel('value', {\n required: false,\n default: null,\n});\nconst inputValue = ref(null);\n\nconst edit = () => {\n inputValue.value = modelVal.value;\n};\n\nconst confirm = async () => {\n if (modelVal.value !== inputValue.value) {\n modelVal.value = inputValue.value;\n await nextTick();\n unref(popoverRef).popperRef?.delayHide?.();\n emits('valueChange', props.detail?.field, modelVal.value, props.rowData);\n }\n};\n</script>\n\n<template>\n <div>\n <span ref=\"buttonRef\" class=\"text\" @click.stop=\"edit\">\n <template\n v-if=\"modelVal === null || modelVal === '' || modelVal === undefined\"\n >\n <el-skeleton :rows=\"0\" />\n </template>\n <template v-else>\n {{ modelVal }}\n </template>\n </span>\n <el-popover\n ref=\"popoverRef\"\n :virtual-ref=\"buttonRef\"\n :width=\"200\"\n trigger=\"click\"\n virtual-triggering\n @hide=\"confirm\"\n >\n <el-input\n v-model=\"inputValue\"\n :placeholder=\"detail.placeholder\"\n v-bind=\"detail.editRender?.props?.componentParams\"\n />\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.text {\n width: 100%;\n cursor: pointer;\n display: inline-block;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n</style>\n","import TableInput from './TableInput.vue';\nimport type { App } from 'vue';\n\n(TableInput as any).name = 'TableInput';\n\nTableInput.install = (app: App) => {\n app.component('TableInput', TableInput);\n};\n\nexport { TableInput };\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '@/types';\n\nimport { nextTick, ref, unref } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableComponentFrame;\n rowData?: any;\n disabled?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n rowData: () => ({}),\n disabled: true,\n});\n\nconst emits = defineEmits(['valueChange']);\n\nconst popoverRef = ref();\nconst buttonRef = ref();\nconst modelVal = defineModel<number | null>('value', {\n required: false,\n default: null,\n});\nconst inputValue = ref<null | number>(null);\n\nconst edit = () => {\n inputValue.value = modelVal.value;\n};\n\nconst confirm = async () => {\n if (inputValue.value !== modelVal.value) {\n modelVal.value = inputValue.value;\n await nextTick();\n emits('valueChange', props.detail?.field, inputValue.value, props.rowData);\n }\n unref(popoverRef).popperRef?.delayHide?.();\n};\n</script>\n\n<template>\n <div style=\"width: 100%\">\n <span ref=\"buttonRef\" class=\"text\" @click.stop=\"edit\">\n <template v-if=\"modelVal === null || modelVal === undefined\">\n <el-skeleton :rows=\"0\" />\n </template>\n <template v-else>\n {{ modelVal }}\n </template>\n </span>\n <el-popover\n ref=\"popoverRef\"\n :virtual-ref=\"buttonRef\"\n :width=\"210\"\n trigger=\"click\"\n virtual-triggering\n @hide=\"confirm\"\n >\n <el-input-number\n v-model=\"inputValue\"\n :placeholder=\"detail.placeholder\"\n style=\"width: 184px\"\n v-bind=\"detail.editRender?.props?.componentParams\"\n >\n <template\n v-if=\"\n detail.editRender?.props?.componentParams &&\n detail.editRender.props.componentParams.suffix\n \"\n #suffix\n >\n <span>{{ detail.editRender.props.componentParams.suffix }}</span>\n </template>\n </el-input-number>\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.text {\n width: 100%;\n cursor: pointer;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '@/types';\n\nimport { nextTick, ref, unref } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableComponentFrame;\n rowData?: any;\n disabled?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n rowData: () => ({}),\n disabled: true,\n});\n\nconst emits = defineEmits(['valueChange']);\n\nconst popoverRef = ref();\nconst buttonRef = ref();\nconst modelVal = defineModel<number | null>('value', {\n required: false,\n default: null,\n});\nconst inputValue = ref<null | number>(null);\n\nconst edit = () => {\n inputValue.value = modelVal.value;\n};\n\nconst confirm = async () => {\n if (inputValue.value !== modelVal.value) {\n modelVal.value = inputValue.value;\n await nextTick();\n emits('valueChange', props.detail?.field, inputValue.value, props.rowData);\n }\n unref(popoverRef).popperRef?.delayHide?.();\n};\n</script>\n\n<template>\n <div style=\"width: 100%\">\n <span ref=\"buttonRef\" class=\"text\" @click.stop=\"edit\">\n <template v-if=\"modelVal === null || modelVal === undefined\">\n <el-skeleton :rows=\"0\" />\n </template>\n <template v-else>\n {{ modelVal }}\n </template>\n </span>\n <el-popover\n ref=\"popoverRef\"\n :virtual-ref=\"buttonRef\"\n :width=\"210\"\n trigger=\"click\"\n virtual-triggering\n @hide=\"confirm\"\n >\n <el-input-number\n v-model=\"inputValue\"\n :placeholder=\"detail.placeholder\"\n style=\"width: 184px\"\n v-bind=\"detail.editRender?.props?.componentParams\"\n >\n <template\n v-if=\"\n detail.editRender?.props?.componentParams &&\n detail.editRender.props.componentParams.suffix\n \"\n #suffix\n >\n <span>{{ detail.editRender.props.componentParams.suffix }}</span>\n </template>\n </el-input-number>\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.text {\n width: 100%;\n cursor: pointer;\n}\n</style>\n","import TableInputNumber from './TableInputNumber.vue';\nimport type { App } from 'vue';\n\n(TableInputNumber as any).name = 'TableInputNumber';\n\nTableInputNumber.install = (app: App) => {\n app.component('TableInputNumber', TableInputNumber);\n};\n\nexport { TableInputNumber };\n","<script setup lang=\"ts\">\nimport type { TableSelectorProp } from '@/types';\n\nimport { onMounted, ref, watch } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = ref<any>(undefined);\n\nconst handleChange = () => {\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\n};\n\nwatch(\n () => props.value,\n (newValue) => {\n setValue(newValue);\n },\n);\n\nconst setValue = (v: any) => {\n if (props.detail?.editRender?.props?.multiple) {\n valueRef.value = Array.isArray(v) ? v : [];\n } else if (['number', 'string'].includes(typeof v) || v === null) {\n valueRef.value = v;\n }\n};\n\nonMounted(() => {\n setValue(props.value);\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.editRender?.props?.multiple === true\"\n filterable\n style=\"width: 100%\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail?.editRender.props.componentParams\n : {}\n \"\n :disabled=\"detail.disabled !== false\"\n :options=\"detail?.editRender?.props?.options\"\n :placeholder=\"detail?.placeholder\"\n @change=\"handleChange\"\n >\n <el-option\n v-for=\"item in detail?.editRender?.props?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { TableSelectorProp } from '@/types';\n\nimport { onMounted, ref, watch } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = ref<any>(undefined);\n\nconst handleChange = () => {\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\n};\n\nwatch(\n () => props.value,\n (newValue) => {\n setValue(newValue);\n },\n);\n\nconst setValue = (v: any) => {\n if (props.detail?.editRender?.props?.multiple) {\n valueRef.value = Array.isArray(v) ? v : [];\n } else if (['number', 'string'].includes(typeof v) || v === null) {\n valueRef.value = v;\n }\n};\n\nonMounted(() => {\n setValue(props.value);\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.editRender?.props?.multiple === true\"\n filterable\n style=\"width: 100%\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail?.editRender.props.componentParams\n : {}\n \"\n :disabled=\"detail.disabled !== false\"\n :options=\"detail?.editRender?.props?.options\"\n :placeholder=\"detail?.placeholder\"\n @change=\"handleChange\"\n >\n <el-option\n v-for=\"item in detail?.editRender?.props?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","import TableSelect from './TableSelect.vue';\nimport type { App } from 'vue';\n\n(TableSelect as any).name = 'TableSelect';\n\nTableSelect.install = (app: App) => {\n app.component('TableSelect', TableSelect);\n};\n\nexport { TableSelect };\n","<script setup lang=\"ts\">\nimport type { TableSelectorProp } from '@/types';\n\ninterface Props {\n value?: any;\n detail: TableSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value');\n\nconst handleChange = (value: any) => {\n emits('valueChange', props.detail?.field, value, props.rowData);\n};\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.editRender?.props.multiple === true\"\n filterable\n style=\"width: 100%\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail?.editRender.props.componentParams\n : {}\n \"\n :disabled=\"detail?.disabled !== false\"\n :placeholder=\"detail?.placeholder\"\n @change=\"handleChange\"\n >\n <el-option\n v-for=\"item in detail?.editRender?.props.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n","<script setup lang=\"ts\">\nimport type { TableSelectorProp } from '@/types';\n\ninterface Props {\n value?: any;\n detail: TableSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value');\n\nconst handleChange = (value: any) => {\n emits('valueChange', props.detail?.field, value, props.rowData);\n};\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.editRender?.props.multiple === true\"\n filterable\n style=\"width: 100%\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail?.editRender.props.componentParams\n : {}\n \"\n :disabled=\"detail?.disabled !== false\"\n :placeholder=\"detail?.placeholder\"\n @change=\"handleChange\"\n >\n <el-option\n v-for=\"item in detail?.editRender?.props.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n","import TableSelectAsync from './TableSelectAsync.vue';\nimport type { App } from 'vue';\n\n(TableSelectAsync as any).name = 'TableSelectAsync';\n\nTableSelectAsync.install = (app: App) => {\n app.component('TableSelectAsync', TableSelectAsync);\n};\n\nexport { TableSelectAsync };\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '../../../types';\n\ninterface Props {\n value?: boolean;\n detail: TableComponentFrame;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: false,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value', {\n type: Boolean,\n});\n\nconst send = (val: boolean) => {\n emits('valueChange', props.detail?.field, val, props.rowData);\n};\n</script>\n\n<template>\n <el-switch\n v-model=\"valueRef\"\n :disabled=\"detail?.disabled !== false\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail.editRender.props.componentParams\n : {}\n \"\n @change=\"send\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '../../../types';\n\ninterface Props {\n value?: boolean;\n detail: TableComponentFrame;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: false,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value', {\n type: Boolean,\n});\n\nconst send = (val: boolean) => {\n emits('valueChange', props.detail?.field, val, props.rowData);\n};\n</script>\n\n<template>\n <el-switch\n v-model=\"valueRef\"\n :disabled=\"detail?.disabled !== false\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail.editRender.props.componentParams\n : {}\n \"\n @change=\"send\"\n />\n</template>\n","import TableSwitch from './TableSwitch.vue';\nimport type { App } from 'vue';\n\n(TableSwitch as any).name = 'TableSwitch';\n\nTableSwitch.install = (app: App) => {\n app.component('TableSwitch', TableSwitch);\n};\n\nexport { TableSwitch };\n","<script setup lang=\"ts\">\nimport type { TableListSelectorProp } from '@/types';\n\nimport { nextTick } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableListSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value');\n\nconst handleChange = async () => {\n await nextTick();\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\n};\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"\n detail.editRender?.props.componentParams\n ? detail.editRender.props.componentParams\n : {}\n \"\n :multiple=\"detail?.editRender?.props?.multiple === true\"\n :placeholder=\"detail.placeholder\"\n :value-key=\"detail.editRender?.props.componentParams.keyField\"\n @change=\"handleChange\"\n clearable\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.editRender?.props.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in detail.editRender?.props.options\"\n :key=\"item[detail.editRender.props.componentParams.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.editRender.props.componentParams.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.editRender?.props.componentParams?.optionWidth\n ? `${detail.editRender?.props.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.editRender?.props.componentParams\n ?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n","<script setup lang=\"ts\">\nimport type { TableListSelectorProp } from '@/types';\n\nimport { nextTick } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableListSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value');\n\nconst handleChange = async () => {\n await nextTick();\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\n};\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"\n detail.editRender?.props.componentParams\n ? detail.editRender.props.componentParams\n : {}\n \"\n :multiple=\"detail?.editRender?.props?.multiple === true\"\n :placeholder=\"detail.placeholder\"\n :value-key=\"detail.editRender?.props.componentParams.keyField\"\n @change=\"handleChange\"\n clearable\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.editRender?.props.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in detail.editRender?.props.options\"\n :key=\"item[detail.editRender.props.componentParams.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.editRender.props.componentParams.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.editRender?.props.componentParams?.optionWidth\n ? `${detail.editRender?.props.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.editRender?.props.componentParams\n ?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n","import TableListSelect from './TableListSelect.vue';\nimport type { App } from 'vue';\n\n(TableListSelect as any).name = 'TableListSelect';\n\nTableListSelect.install = (app: App) => {\n app.component('TableListSelect', TableListSelect);\n};\n\nexport { TableListSelect };\n","import type { Ref } from 'vue';\n\nimport type { OptionInterface } from '@/types';\n\nimport { ref } from 'vue';\n\nimport { isEmpty, msgTips, sleep } from '@/utils';\n\ninterface Props {\n detail: any;\n rowData?: any;\n}\n\ninterface TableSelectAsync<EE extends (...args: any) => void> {\n emits: EE;\n props: Props;\n valueRef: Ref;\n}\n\nexport const useTableSelectAsync = <EE extends (...args: any) => void>(\n params: TableSelectAsync<EE>,\n) => {\n const { emits, props } = params;\n\n const loading = ref<boolean>(false);\n let load = false;\n let isLoadFail = false;\n let oldComponentValueMap: any = {};\n\n // 选项\n const optionsData = ref<any[] | OptionInterface[]>([]);\n\n const init = async () => {\n await sleep(0.05 + Math.floor(Math.random() * 300) / 100);\n await getOptions();\n };\n\n /**\n * 验证从当前行数据中获取的其他参数是否有效\n * @param params\n * @param fieldNames\n */\n const verifyHttpOtherParams = (params: any, fieldNames: string[]) => {\n let result = true;\n if (fieldNames.length > 0 && !params) {\n return false;\n }\n fieldNames.forEach((fieldName) => {\n if (params[fieldName] === undefined || params[fieldName] === null) {\n result = false;\n }\n });\n\n return result;\n };\n\n /** 远程获取 */\n const getOptions = async () => {\n if (loading.value) return;\n const editProps = props.detail?.editRender?.props;\n if (!editProps || isEmpty(editProps.optionHttpUrl)) return;\n\n // 从当前行数据 rowData 中获取其他字段的值作为请求参数\n let componentValueMap: any = {};\n const fieldNames: string[] = editProps.optionHttpParamsValue || [];\n if (fieldNames.length > 0 && props.rowData) {\n fieldNames.forEach((fieldName: string) => {\n componentValueMap[fieldName] = props.rowData[fieldName];\n });\n }\n\n // 如果(已经加载 || 加载失败)且新获取的数据与旧数据一样,则不再重新请求\n if (\n (load || isLoadFail) &&\n JSON.stringify(componentValueMap) === JSON.stringify(oldComponentValueMap)\n )\n return;\n\n if (!verifyHttpOtherParams(componentValueMap, fieldNames)) {\n // 验证失败则不发http请求\n return;\n }\n\n loading.value = true;\n oldComponentValueMap = componentValueMap;\n\n const opt: any = {\n method: editProps.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (!['get', 'GET', 'head', 'HEAD'].includes(editProps.optionHttpMethod)) {\n opt.body = JSON.stringify({\n prop: props.detail.field,\n ...editProps.optionHttpParams,\n ...componentValueMap,\n });\n }\n const response = await fetch(editProps.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n load = true;\n optionsData.value = result.data;\n } else {\n msgTips.alert({\n msg: `${props.detail?.title || ''}数据获取失败!`,\n type: 'warning',\n });\n isLoadFail = true;\n }\n loading.value = false;\n };\n\n return {\n getOptions,\n optionsData,\n loading,\n init,\n };\n};\n","<script setup lang=\"ts\">\nimport type { TableListSelectorAsyncProp } from '@/types';\n\nimport { nextTick, onMounted } from 'vue';\n\nimport { useTableSelectAsync } from '../hooks/tableSelectAsync.hook';\n\ninterface Props {\n value?: any;\n detail: TableListSelectorAsyncProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value');\n\nconst { loading, getOptions, optionsData, init } = useTableSelectAsync({\n emits,\n props,\n valueRef,\n});\n\nconst handleChange = async () => {\n await nextTick();\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\n};\n\nonMounted(() => {\n init();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"\n detail.editRender?.props.componentParams\n ? detail.editRender.props.componentParams\n : {}\n \"\n v-loading=\"loading\"\n :multiple=\"detail?.editRender?.props?.multiple === true\"\n :loading=\"loading\"\n :placeholder=\"detail.placeholder\"\n :value-key=\"detail.editRender?.props.componentParams.keyField\"\n clearable\n @change=\"handleChange\"\n @focus=\"getOptions\"\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.editRender?.props.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item[detail.editRender.props.componentParams.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.editRender.props.componentParams.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.editRender?.props.componentParams?.optionWidth\n ? `${detail.editRender?.props.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.editRender?.props.componentParams\n ?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { TableListSelectorAsyncProp } from '@/types';\n\nimport { nextTick, onMounted } from 'vue';\n\nimport { useTableSelectAsync } from '../hooks/tableSelectAsync.hook';\n\ninterface Props {\n value?: any;\n detail: TableListSelectorAsyncProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value');\n\nconst { loading, getOptions, optionsData, init } = useTableSelectAsync({\n emits,\n props,\n valueRef,\n});\n\nconst handleChange = async () => {\n await nextTick();\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\n};\n\nonMounted(() => {\n init();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"\n detail.editRender?.props.componentParams\n ? detail.editRender.props.componentParams\n : {}\n \"\n v-loading=\"loading\"\n :multiple=\"detail?.editRender?.props?.multiple === true\"\n :loading=\"loading\"\n :placeholder=\"detail.placeholder\"\n :value-key=\"detail.editRender?.props.componentParams.keyField\"\n clearable\n @change=\"handleChange\"\n @focus=\"getOptions\"\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.editRender?.props.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item[detail.editRender.props.componentParams.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.editRender.props.componentParams.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.editRender?.props.componentParams?.optionWidth\n ? `${detail.editRender?.props.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.editRender?.props.componentParams\n ?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n\n<style scoped></style>\n","import TableListSelectAsync from './TableListSelectAsync.vue';\nimport type { App } from 'vue';\n\n(TableListSelectAsync as any).name = 'TableListSelectAsync';\n\nTableListSelectAsync.install = (app: App) => {\n app.component('TableListSelectAsync', TableListSelectAsync);\n};\n\nexport { TableListSelectAsync };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { TableSelectorProp } from '@/types';\n\nimport { reactive, ref } from 'vue';\nimport { TableCheckBoxAsyncI18n } from '@/components/TableComponent/TableCheckBoxAsync/type';\n\ninterface Props {\n value?: any[];\n detail: TableSelectorProp;\n i18Text?: TableCheckBoxAsyncI18n;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => [],\n i18Text: () => ({\n save: '保存',\n cancel: '取消',\n close: '关闭',\n }),\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['update:value', 'valueChange', 'setShow']);\n\nconst valueRef = defineModel('value', {\n type: Array as PropType<any[]>,\n default: () => [],\n});\n\nconst state = reactive({\n dialogVisible: false,\n showText: '',\n});\n\nconst checkData = ref<any[]>([]);\n\nconst change = () => {\n valueRef.value = checkData.value;\n emits('valueChange', props.detail.field, checkData.value, props.rowData);\n state.dialogVisible = false;\n setShowText(checkData.value);\n};\n\nconst textCache: any = {};\n\nconst setShowText = (componentData: any[]) => {\n if (Array.isArray(props.detail?.editRender?.props?.options)) {\n props.detail.editRender.props.options.forEach((item) => {\n textCache[item.value] = item.label;\n });\n }\n let text = '';\n for (const componentDatum of componentData) {\n text = `${text} ${\n textCache[componentDatum] === undefined\n ? componentDatum\n : textCache[componentDatum]\n }`;\n }\n state.showText = text;\n};\n\nconst openDialog = () => {\n state.dialogVisible = true;\n checkData.value = valueRef.value;\n};\n</script>\n\n<template>\n <div class=\"table-check-box-async\">\n <span class=\"text\" @click.stop=\"openDialog\">\n {{ state.showText ? state.showText : '空' }}\n </span>\n <el-dialog\n v-model=\"state.dialogVisible\"\n :show-close=\"false\"\n append-to-body\n center\n >\n <template #header>\n <div class=\"dialog-header\">\n <div>\n <el-button size=\"small\" type=\"primary\" @click=\"change\">\n {{ i18Text.save }}\n </el-button>\n <el-button size=\"small\" @click=\"state.dialogVisible = false\">\n {{ i18Text.cancel }}\n </el-button>\n </div>\n <el-button\n size=\"small\"\n type=\"danger\"\n @click=\"state.dialogVisible = false\"\n >\n {{ i18Text.close }}\n </el-button>\n </div>\n </template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in detail?.editRender?.props?.options\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n </el-dialog>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.table-check-box-async {\n width: 100%;\n\n .text {\n cursor: pointer;\n }\n}\n\n.dialog-header {\n display: flex;\n flex-direction: row;\n gap: 16px;\n justify-content: space-between;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { TableSelectorProp } from '@/types';\n\nimport { reactive, ref } from 'vue';\nimport { TableCheckBoxAsyncI18n } from '@/components/TableComponent/TableCheckBoxAsync/type';\n\ninterface Props {\n value?: any[];\n detail: TableSelectorProp;\n i18Text?: TableCheckBoxAsyncI18n;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => [],\n i18Text: () => ({\n save: '保存',\n cancel: '取消',\n close: '关闭',\n }),\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['update:value', 'valueChange', 'setShow']);\n\nconst valueRef = defineModel('value', {\n type: Array as PropType<any[]>,\n default: () => [],\n});\n\nconst state = reactive({\n dialogVisible: false,\n showText: '',\n});\n\nconst checkData = ref<any[]>([]);\n\nconst change = () => {\n valueRef.value = checkData.value;\n emits('valueChange', props.detail.field, checkData.value, props.rowData);\n state.dialogVisible = false;\n setShowText(checkData.value);\n};\n\nconst textCache: any = {};\n\nconst setShowText = (componentData: any[]) => {\n if (Array.isArray(props.detail?.editRender?.props?.options)) {\n props.detail.editRender.props.options.forEach((item) => {\n textCache[item.value] = item.label;\n });\n }\n let text = '';\n for (const componentDatum of componentData) {\n text = `${text} ${\n textCache[componentDatum] === undefined\n ? componentDatum\n : textCache[componentDatum]\n }`;\n }\n state.showText = text;\n};\n\nconst openDialog = () => {\n state.dialogVisible = true;\n checkData.value = valueRef.value;\n};\n</script>\n\n<template>\n <div class=\"table-check-box-async\">\n <span class=\"text\" @click.stop=\"openDialog\">\n {{ state.showText ? state.showText : '空' }}\n </span>\n <el-dialog\n v-model=\"state.dialogVisible\"\n :show-close=\"false\"\n append-to-body\n center\n >\n <template #header>\n <div class=\"dialog-header\">\n <div>\n <el-button size=\"small\" type=\"primary\" @click=\"change\">\n {{ i18Text.save }}\n </el-button>\n <el-button size=\"small\" @click=\"state.dialogVisible = false\">\n {{ i18Text.cancel }}\n </el-button>\n </div>\n <el-button\n size=\"small\"\n type=\"danger\"\n @click=\"state.dialogVisible = false\"\n >\n {{ i18Text.close }}\n </el-button>\n </div>\n </template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in detail?.editRender?.props?.options\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n </el-dialog>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.table-check-box-async {\n width: 100%;\n\n .text {\n cursor: pointer;\n }\n}\n\n.dialog-header {\n display: flex;\n flex-direction: row;\n gap: 16px;\n justify-content: space-between;\n}\n</style>\n","import TableCheckBoxAsync from './TableCheckBoxAsync.vue';\nimport type { App } from 'vue';\n\n(TableCheckBoxAsync as any).name = 'TableCheckBoxAsync';\n\nTableCheckBoxAsync.install = (app: App) => {\n app.component('TableCheckBoxAsync', TableCheckBoxAsync);\n};\n\nexport { TableCheckBoxAsync };\n","import type { VxeGridListeners } from 'vxe-table';\n\nimport type { Ref } from 'vue';\n\nimport { msgTips } from '@/utils';\n\ninterface Props {\n xGrid: Ref;\n fieldValueChanged: Function;\n}\n\ninterface Paste {\n col: number;\n row: number;\n field: string;\n oldValue: any;\n newValue: any;\n rowData: any;\n rowId: string;\n}\n\nexport const useVxeGrid = (props: Props) => {\n const { xGrid, fieldValueChanged } = props;\n /**\n * 导出数据\n */\n const exportData = () => {\n xGrid.value.openExport();\n };\n\n /**\n * 自定义列\n */\n const openCustomColumn = () => {\n xGrid.value.openCustom();\n };\n\n const vxeClipboard = {\n rowSelectColumn: 'seq',\n onCopy: (e: any) => {\n msgTips.tips({\n msg: '复制成功!',\n type: 'success',\n });\n },\n onPaste: (e: Paste[]) => {\n e.forEach((item: Paste) => {\n if (item.oldValue !== item.newValue) {\n fieldValueChanged(item.field, item.newValue, item.rowData);\n }\n });\n },\n onCut: (e: any) => {\n console.log('cut', e);\n },\n onSelectionChange: (e: any) => {\n console.log('selectionChange', e);\n },\n };\n\n const gridEvents: VxeGridListeners<any> = {\n // ready() {\n // console.log('ready 表格准备就绪');\n // },\n // dataChange({ visibleData, visibleColumn, $event }) {\n // console.log('data-change 数据列表发生改变', visibleData, visibleColumn);\n // },\n // initRendered() {\n // console.log('init-rendered 数据列表被赋值并首次渲染完成');\n // },\n // dataRendered() {\n // console.log('data-rendered 数据列表被赋值并渲染完成');\n // },\n };\n\n return { exportData, openCustomColumn, vxeClipboard, gridEvents };\n};\n","<script setup lang=\"ts\">\nimport type { VxeGridProps } from 'vxe-table';\n\nimport type { PropType } from 'vue';\n\nimport type { KeButton, TableConfigInterface, TableQueryFrame, Pagination } from '@/types';\n\nimport { computed, ref, resolveComponent } from 'vue';\n\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\nimport { ToolBar } from '@/components/ToolBar';\nimport { useButtonExec } from '@/hooks/useButtonExec.hook';\n\nimport { useVxeGrid } from './hooks/useVxeGrid.hook';\n\nimport { QueryBar } from '@/components/QueryComponent/QueryBar'\n\ndefineOptions({\n name: 'TableRender',\n});\n\nconst VxeGrid = resolveComponent('VxeGrid') as any;\n\nconst props = withDefaults(\n defineProps<{\n columns: any[];\n queryConfig?: TableQueryFrame[];\n tableConfig: TableConfigInterface;\n tableData?: any[];\n tableId: number | string;\n tablePagination?: Pagination;\n tableRowButtons?: KeButton[];\n tableToolButtons?: KeButton[];\n vxeGridOptions?: VxeGridProps;\n }>(),\n {\n vxeGridOptions: undefined,\n queryConfig: () => [],\n tableToolButtons: () => [],\n tableRowButtons: () => [],\n tableData: () => [],\n tablePagination: () => ({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n }),\n },\n);\n\nconst emits = defineEmits([\n // 获取表格配置\n 'getTableConfig',\n 'btnClick', // 按钮\n 'queryClick', // 查询按钮点击事件\n 'valueChange', // 当某个单元格发生数据变化时\n 'treeLazyLoad', // 懒加载事件\n 'onSelection', // 当选择项发生变化时会触发该事件\n]);\n\n// 获取vxeTable表格节点\nconst xGrid = ref();\n\nconst pagination = defineModel('tablePagination', {\n required: false,\n type: Object as PropType<Pagination>,\n default: () => {\n return {\n currentPage: 1,\n /**\n * 页面大小\n */\n pageSize: 0,\n /**\n * 总数\n */\n total: 0,\n };\n },\n});\n\n/**\n * 字段值改动通知\n * @param fieldName 字段名\n * @param newValue 改动后的值\n * @param rowData\n */\nconst fieldValueChanged = (fieldName: string, newValue: any, rowData: any) => {\n emits('valueChange', fieldName, newValue, rowData[props.tableConfig?.rowKey]);\n};\n\nconst { exportData, openCustomColumn, vxeClipboard, gridEvents } =\n useVxeGrid({ xGrid, fieldValueChanged });\n\n/**\n * frame\n */\nconst tableColumns = computed(() => {\n if (\n props.tableRowButtons.length > 0 &&\n props.columns.length > 0 &&\n props.columns[props.columns.length - 1].field !== 'tableButtonOperate'\n ) {\n const newColumns = [...props.columns];\n newColumns.push({\n field: 'tableButtonOperate',\n title: '操作',\n width: props.tableRowButtons.length * 50 + 40,\n fixed: 'right',\n slots: {\n default: 'tableButtonOperate',\n },\n });\n return newColumns;\n }\n return props.columns;\n});\n\nconst vxeGridContainerRef = ref();\nconst debouncedHeight = ref(0);\nuseResizeObserver(\n vxeGridContainerRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedHeight.value = entry.contentRect.height;\n }\n }, 200),\n);\n\nlet queryData = {};\n\n/**\n * 列表按钮\n *\n * @param data\n * @param button\n * @param rowIndex\n */\nconst btnClick = (data: any, button: any, rowIndex: number) => {\n useButtonExec(data, button, rowIndex);\n};\n\nconst queryClick = (data: any) => {\n queryData = data;\n emits('queryClick', queryData);\n};\n\n/**\n * 翻页\n */\nconst paginationChange = () => {\n emits('queryClick', queryData);\n};\n</script>\n\n<template>\n <div class=\"ke-table-render-client\">\n <QueryBar\n v-if=\"queryConfig && queryConfig.length > 0\"\n :frame=\"queryConfig\"\n class=\"ke-query-bar-client\"\n @query-click=\"queryClick\"\n />\n <div\n v-if=\"tableToolButtons && tableToolButtons.length > 0\"\n class=\"ke-table-tool-button\"\n >\n <ToolBar :tool-buttons=\"tableToolButtons\">\n <template #custom-button>\n <slot name=\"tool-bar\"></slot>\n <ElButtonPlus @click=\"exportData\" icon=\"mingcute:download-line\" />\n <ElButtonPlus @click=\"openCustomColumn\" icon=\"lets-icons:setting-line\" />\n </template>\n </ToolBar>\n </div>\n <div ref=\"vxeGridContainerRef\" class=\"ke-vxe-grid-container\">\n <VxeGrid\n ref=\"xGrid\"\n v-clipboard=\"vxeClipboard\"\n v-on=\"gridEvents\"\n v-bind=\"{\n ...vxeGridOptions,\n showOverflow: 'title',\n columns: tableColumns,\n id: tableConfig.rowKey,\n rowConfig: {\n keyField: tableConfig?.rowKey,\n },\n seqConfig: {\n startIndex: tablePagination\n ? (tablePagination.currentPage - 1) * tablePagination.pageSize\n : 1,\n },\n data: tableData,\n height: debouncedHeight,\n }\"\n >\n <!-- 普通编辑器-->\n <template #renderCell=\"{ row, column }\">\n <component\n :is=\"column.editRender.name\"\n v-model:value=\"row[column.field]\"\n :detail=\"column\"\n :disabled=\"column.disabled !== false\"\n :row-data=\"row\"\n @value-change=\"fieldValueChanged\"\n />\n </template>\n <!-- 异步编辑器-->\n <template #renderAsyncCell=\"{ row, column }\">\n <component\n :is=\"column.editRender.name\"\n v-model:value=\"row[column.field]\"\n :detail=\"column\"\n :disabled=\"column.disabled !== false\"\n :row-data=\"row\"\n @value-change=\"fieldValueChanged\"\n />\n <!-- getTableColumnDetailData(column.editRender.props)-->\n </template>\n <!-- 操作列-->\n <template #tableButtonOperate=\"{ row, rowIndex }\">\n <ElButtonPlus\n v-for=\"btn in tableRowButtons\"\n :key=\"btn.id\"\n :class=\"btn.buttonClass\"\n :style=\"btn.buttonStyle\"\n :label=\"btn.label\"\n :icon=\"btn.icon\"\n :type=\"btn.type\"\n size=\"small\"\n @click.stop=\"btnClick(row, btn, rowIndex)\"\n />\n </template>\n </VxeGrid>\n </div>\n <div v-if=\"!tableConfig.tree && tablePagination\" class=\"ke-pagination-div\">\n <el-pagination\n v-model:current-page=\"pagination.currentPage\"\n v-model:page-size=\"pagination.pageSize\"\n :total=\"tablePagination.total\"\n background\n :layout=\"\n pagination.pageSize > 0 ? 'total, prev, pager, next, jumper' : 'total'\n \"\n size=\"small\"\n @current-change=\"paginationChange\"\n />\n </div>\n </div>\n</template>\n\n<style lang=\"scss\">\n.ke-table-render-client {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n background: var(--overlay-content);\n}\n.ke-query-bar-client {\n margin-top: 6px;\n}\n.ke-table-tool-button {\n margin: 6px 2px;\n}\n\n.ke-query-bar-client,\n.ke-table-tool-button,\n.ke-pagination-div {\n flex-shrink: 0;\n}\n\n.ke-vxe-grid-container {\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n overflow: hidden; /* 防止内容溢出 */\n}\n\n.ke-vxe-grid-container .vxe-grid {\n height: 100%; /* 让 VxeGrid 占满容器高度 */\n overflow: auto; /* 让 VxeGrid 内容滚动 */\n}\n\n.ke-pagination-div {\n padding: 6px;\n margin-top: 10px; /* 可选:分页与表格之间的间距 */\n border-radius: 4px;\n background: var(--el-fill-color-blank);\n}\n\n.vxe-grid {\n //禁用浏览器默认选中\n -webkit-user-select: none;\n /* Safari */\n -moz-user-select: none;\n /* Firefox */\n -ms-user-select: none;\n /* Internet Explorer/Edge */\n user-select: none;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { VxeGridProps } from 'vxe-table';\n\nimport type { PropType } from 'vue';\n\nimport type { KeButton, TableConfigInterface, TableQueryFrame, Pagination } from '@/types';\n\nimport { computed, ref, resolveComponent } from 'vue';\n\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\nimport { ToolBar } from '@/components/ToolBar';\nimport { useButtonExec } from '@/hooks/useButtonExec.hook';\n\nimport { useVxeGrid } from './hooks/useVxeGrid.hook';\n\nimport { QueryBar } from '@/components/QueryComponent/QueryBar'\n\ndefineOptions({\n name: 'TableRender',\n});\n\nconst VxeGrid = resolveComponent('VxeGrid') as any;\n\nconst props = withDefaults(\n defineProps<{\n columns: any[];\n queryConfig?: TableQueryFrame[];\n tableConfig: TableConfigInterface;\n tableData?: any[];\n tableId: number | string;\n tablePagination?: Pagination;\n tableRowButtons?: KeButton[];\n tableToolButtons?: KeButton[];\n vxeGridOptions?: VxeGridProps;\n }>(),\n {\n vxeGridOptions: undefined,\n queryConfig: () => [],\n tableToolButtons: () => [],\n tableRowButtons: () => [],\n tableData: () => [],\n tablePagination: () => ({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n }),\n },\n);\n\nconst emits = defineEmits([\n // 获取表格配置\n 'getTableConfig',\n 'btnClick', // 按钮\n 'queryClick', // 查询按钮点击事件\n 'valueChange', // 当某个单元格发生数据变化时\n 'treeLazyLoad', // 懒加载事件\n 'onSelection', // 当选择项发生变化时会触发该事件\n]);\n\n// 获取vxeTable表格节点\nconst xGrid = ref();\n\nconst pagination = defineModel('tablePagination', {\n required: false,\n type: Object as PropType<Pagination>,\n default: () => {\n return {\n currentPage: 1,\n /**\n * 页面大小\n */\n pageSize: 0,\n /**\n * 总数\n */\n total: 0,\n };\n },\n});\n\n/**\n * 字段值改动通知\n * @param fieldName 字段名\n * @param newValue 改动后的值\n * @param rowData\n */\nconst fieldValueChanged = (fieldName: string, newValue: any, rowData: any) => {\n emits('valueChange', fieldName, newValue, rowData[props.tableConfig?.rowKey]);\n};\n\nconst { exportData, openCustomColumn, vxeClipboard, gridEvents } =\n useVxeGrid({ xGrid, fieldValueChanged });\n\n/**\n * frame\n */\nconst tableColumns = computed(() => {\n if (\n props.tableRowButtons.length > 0 &&\n props.columns.length > 0 &&\n props.columns[props.columns.length - 1].field !== 'tableButtonOperate'\n ) {\n const newColumns = [...props.columns];\n newColumns.push({\n field: 'tableButtonOperate',\n title: '操作',\n width: props.tableRowButtons.length * 50 + 40,\n fixed: 'right',\n slots: {\n default: 'tableButtonOperate',\n },\n });\n return newColumns;\n }\n return props.columns;\n});\n\nconst vxeGridContainerRef = ref();\nconst debouncedHeight = ref(0);\nuseResizeObserver(\n vxeGridContainerRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedHeight.value = entry.contentRect.height;\n }\n }, 200),\n);\n\nlet queryData = {};\n\n/**\n * 列表按钮\n *\n * @param data\n * @param button\n * @param rowIndex\n */\nconst btnClick = (data: any, button: any, rowIndex: number) => {\n useButtonExec(data, button, rowIndex);\n};\n\nconst queryClick = (data: any) => {\n queryData = data;\n emits('queryClick', queryData);\n};\n\n/**\n * 翻页\n */\nconst paginationChange = () => {\n emits('queryClick', queryData);\n};\n</script>\n\n<template>\n <div class=\"ke-table-render-client\">\n <QueryBar\n v-if=\"queryConfig && queryConfig.length > 0\"\n :frame=\"queryConfig\"\n class=\"ke-query-bar-client\"\n @query-click=\"queryClick\"\n />\n <div\n v-if=\"tableToolButtons && tableToolButtons.length > 0\"\n class=\"ke-table-tool-button\"\n >\n <ToolBar :tool-buttons=\"tableToolButtons\">\n <template #custom-button>\n <slot name=\"tool-bar\"></slot>\n <ElButtonPlus @click=\"exportData\" icon=\"mingcute:download-line\" />\n <ElButtonPlus @click=\"openCustomColumn\" icon=\"lets-icons:setting-line\" />\n </template>\n </ToolBar>\n </div>\n <div ref=\"vxeGridContainerRef\" class=\"ke-vxe-grid-container\">\n <VxeGrid\n ref=\"xGrid\"\n v-clipboard=\"vxeClipboard\"\n v-on=\"gridEvents\"\n v-bind=\"{\n ...vxeGridOptions,\n showOverflow: 'title',\n columns: tableColumns,\n id: tableConfig.rowKey,\n rowConfig: {\n keyField: tableConfig?.rowKey,\n },\n seqConfig: {\n startIndex: tablePagination\n ? (tablePagination.currentPage - 1) * tablePagination.pageSize\n : 1,\n },\n data: tableData,\n height: debouncedHeight,\n }\"\n >\n <!-- 普通编辑器-->\n <template #renderCell=\"{ row, column }\">\n <component\n :is=\"column.editRender.name\"\n v-model:value=\"row[column.field]\"\n :detail=\"column\"\n :disabled=\"column.disabled !== false\"\n :row-data=\"row\"\n @value-change=\"fieldValueChanged\"\n />\n </template>\n <!-- 异步编辑器-->\n <template #renderAsyncCell=\"{ row, column }\">\n <component\n :is=\"column.editRender.name\"\n v-model:value=\"row[column.field]\"\n :detail=\"column\"\n :disabled=\"column.disabled !== false\"\n :row-data=\"row\"\n @value-change=\"fieldValueChanged\"\n />\n <!-- getTableColumnDetailData(column.editRender.props)-->\n </template>\n <!-- 操作列-->\n <template #tableButtonOperate=\"{ row, rowIndex }\">\n <ElButtonPlus\n v-for=\"btn in tableRowButtons\"\n :key=\"btn.id\"\n :class=\"btn.buttonClass\"\n :style=\"btn.buttonStyle\"\n :label=\"btn.label\"\n :icon=\"btn.icon\"\n :type=\"btn.type\"\n size=\"small\"\n @click.stop=\"btnClick(row, btn, rowIndex)\"\n />\n </template>\n </VxeGrid>\n </div>\n <div v-if=\"!tableConfig.tree && tablePagination\" class=\"ke-pagination-div\">\n <el-pagination\n v-model:current-page=\"pagination.currentPage\"\n v-model:page-size=\"pagination.pageSize\"\n :total=\"tablePagination.total\"\n background\n :layout=\"\n pagination.pageSize > 0 ? 'total, prev, pager, next, jumper' : 'total'\n \"\n size=\"small\"\n @current-change=\"paginationChange\"\n />\n </div>\n </div>\n</template>\n\n<style lang=\"scss\">\n.ke-table-render-client {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n background: var(--overlay-content);\n}\n.ke-query-bar-client {\n margin-top: 6px;\n}\n.ke-table-tool-button {\n margin: 6px 2px;\n}\n\n.ke-query-bar-client,\n.ke-table-tool-button,\n.ke-pagination-div {\n flex-shrink: 0;\n}\n\n.ke-vxe-grid-container {\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n overflow: hidden; /* 防止内容溢出 */\n}\n\n.ke-vxe-grid-container .vxe-grid {\n height: 100%; /* 让 VxeGrid 占满容器高度 */\n overflow: auto; /* 让 VxeGrid 内容滚动 */\n}\n\n.ke-pagination-div {\n padding: 6px;\n margin-top: 10px; /* 可选:分页与表格之间的间距 */\n border-radius: 4px;\n background: var(--el-fill-color-blank);\n}\n\n.vxe-grid {\n //禁用浏览器默认选中\n -webkit-user-select: none;\n /* Safari */\n -moz-user-select: none;\n /* Firefox */\n -ms-user-select: none;\n /* Internet Explorer/Edge */\n user-select: none;\n}\n</style>\n","import TableRender from './TableRender.vue';\nimport type { App } from 'vue';\n\n(TableRender as any).name = 'TableRender';\n\nTableRender.install = (app: App) => {\n app.component('TableRender', TableRender);\n};\n\nexport { TableRender };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type {\n KeButton,\n Pagination,\n TableConfigInterface,\n TableQueryFrame,\n} from '@/types';\n\nimport { ref } from 'vue';\n\nimport { More } from '@element-plus/icons-vue';\n\nimport { useButtonExec } from '@/hooks/useButtonExec.hook';\nimport { isNotEmpty } from '@/utils';\n\nimport { customFormatter } from '@/utils';\n\ninterface Props {\n tableId: number | string;\n tableConfig: TableConfigInterface;\n vxeGridOptions?: any;\n columns: any[];\n queryConfig?: TableQueryFrame[];\n tableToolButtons?: KeButton[];\n tableRowButtons?: KeButton[];\n tableData: any[];\n tablePagination?: Pagination;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n vxeGridOptions: undefined,\n queryConfig: () => [],\n tableToolButtons: () => [],\n tableRowButtons: () => [],\n tableData: () => [],\n tablePagination: () => ({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n }),\n});\n\nconst emits = defineEmits([\n 'btnClick', // 按钮\n 'queryClick', // 查询按钮点击事件\n 'valueChange', // 当某个单元格发生数据变化时\n 'treeLazyLoad', // 懒加载事件\n 'onSelection', // 当选择项发生变化时会触发该事件\n]);\n\nconst pagination = defineModel('tablePagination', {\n required: true,\n type: Object as PropType<Pagination>,\n});\n\n/**\n * 查询内容\n */\nconst queryData = {};\n\n/**\n * 查询\n * @param data\n */\nconst queryClick = (data: any) => {\n emits('queryClick', data);\n};\n\nlet titleField = '';\n/**\n * 获取标题\n * @param cardItem\n */\nconst getTitle = (cardItem: any) => {\n if (props.tableConfig.titleField) {\n return cardItem[props.tableConfig.titleField];\n } else if (isNotEmpty(titleField)) {\n return cardItem[titleField];\n }\n\n for (const key in cardItem) {\n if (typeof cardItem[key] === 'string' && isNotEmpty(cardItem[key])) {\n titleField = key;\n return cardItem[key];\n }\n }\n return '';\n};\n\nconst queryBarRef = ref();\n\n/**\n * 按钮事件\n *\n * @param data\n * @param button\n */\nconst btnClick = (data: any, button: any) => {\n useButtonExec(data, button);\n};\n\n/**\n * 已循环过的格式化对象\n */\nconst translateObject = {};\n/**\n * 循环到的索引\n */\nconst translateIndexArray: any[] = [];\n/**\n * 格式化方法\n */\nconst formatterCellValue = (value: any, cell: any) => {\n return customFormatter({\n cellValue: value,\n tabObj: cell.tabObj,\n translateJson: cell.translate,\n fieldName: cell.field,\n translateObject,\n translateIndexArray,\n });\n};\n\n/**\n * 字段值改动通知\n * @param fieldName 字段名\n * @param newValue 改动后的值\n * @param rowId\n */\nconst fieldValueChanged = (\n fieldName: string,\n newValue: any,\n rowId: number | string,\n) => {\n emits('valueChange', fieldName, newValue, rowId);\n};\n\n/**\n * 翻页\n */\nconst paginationChange = () => {\n emits('queryClick', queryData);\n};\n</script>\n\n<template>\n <div class=\"table-card-render-client\">\n <KeQueryBar\n v-if=\"queryConfig && queryConfig.length > 0\"\n ref=\"queryBarRef\"\n :frame=\"queryConfig\"\n @query-click=\"queryClick\"\n />\n <div v-if=\"tableToolButtons.length > 0\" class=\"table-tool-button\">\n <KeToolBar :tool-buttons=\"tableToolButtons\" />\n </div>\n <div class=\"card-container\">\n <el-scrollbar>\n <el-row :gutter=\"12\">\n <el-col\n v-for=\"cardItem in tableData\"\n :key=\"cardItem[tableConfig.rowKey]\"\n :lg=\"8\"\n :md=\"8\"\n :sm=\"12\"\n :xl=\"6\"\n :xs=\"24\"\n style=\"margin-top: 6px; margin-bottom: 6px\"\n >\n <el-card>\n <template v-if=\"tableConfig.coverField\">\n <!-- 封面图片-->\n <img :src=\"cardItem[tableConfig.coverField]\" alt=\"\" />\n </template>\n <h1 class=\"title-wrapper\">\n <span class=\"title-text\">{{ getTitle(cardItem) }}</span>\n <el-dropdown\n v-if=\"\n Array.isArray(tableRowButtons) && tableRowButtons.length > 0\n \"\n class=\"dropdown-wrapper\"\n >\n <el-button :icon=\"More\" text />\n <template #dropdown>\n <el-dropdown-menu>\n <el-dropdown-item\n v-for=\"btn in tableRowButtons\"\n :key=\"btn.id\"\n @click=\"btnClick(cardItem, btn)\"\n >\n <template #default>\n <span\n :style=\"{ color: `var(--el-color-${btn.type})` }\"\n >\n {{ btn.label }}\n </span>\n </template>\n </el-dropdown-item>\n </el-dropdown-menu>\n </template>\n </el-dropdown>\n </h1>\n <template v-for=\"cardCol in columns\" :key=\"cardCol.field\">\n <el-form-item\n v-if=\"cardCol.field !== tableConfig.coverField\"\n :label=\"cardCol.title\"\n >\n <template v-if=\"cardCol.cellRender || cardCol.editRender\">\n <!-- {{ dataFormatter({ })}}-->\n <component\n :is=\"cardCol.editRender.name\"\n v-model:value=\"cardItem[cardCol.field]\"\n :detail=\"cardCol\"\n :disabled=\"cardCol.editRender.enabled\"\n :row-data=\"cardItem\"\n @value-change=\"fieldValueChanged\"\n />\n </template>\n <template v-else>\n {{ formatterCellValue(cardItem[cardCol.field], cardCol) }}\n </template>\n </el-form-item>\n </template>\n </el-card>\n </el-col>\n </el-row>\n </el-scrollbar>\n </div>\n <div class=\"pagination-div\">\n <el-pagination\n v-model:current-page=\"pagination.currentPage\"\n v-model:page-size=\"pagination.pageSize\"\n :total=\"tablePagination.total\"\n background\n layout=\"total, prev, pager, next, jumper\"\n size=\"small\"\n @current-change=\"paginationChange\"\n />\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n/**\n禁用横向滚动条\n */\n:deep(.el-scrollbar__wrap) {\n overflow-x: hidden !important;\n}\n\n:deep(.el-scrollbar__bar.is-horizontal) {\n height: 0 !important;\n}\n\n:deep(.el-form-item) {\n margin-bottom: 0 !important;\n}\n\n.table-card-render-client {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n}\n\n.title-wrapper {\n display: flex;\n align-items: center;\n justify-content: space-between; /* 确保内容与按钮分布在两端 */\n\n .title-text {\n flex: 1; /* 确保文字部分可以占满剩余空间 */\n }\n\n .dropdown-wrapper {\n margin-left: auto; /* 确保按钮总是靠右对齐 */\n }\n}\n\n.table-tool-button {\n margin-top: 6px; /* 可选:给工具条加一些顶部间距 */\n}\n\n.card-container {\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n overflow: hidden; /* 防止内容溢出 */\n}\n\n.pagination-div {\n padding: 6px;\n margin-top: 10px; /* 可选:分页与表格之间的间距 */\n background: var(--el-fill-color-blank);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type {\n KeButton,\n Pagination,\n TableConfigInterface,\n TableQueryFrame,\n} from '@/types';\n\nimport { ref } from 'vue';\n\nimport { More } from '@element-plus/icons-vue';\n\nimport { useButtonExec } from '@/hooks/useButtonExec.hook';\nimport { isNotEmpty } from '@/utils';\n\nimport { customFormatter } from '@/utils';\n\ninterface Props {\n tableId: number | string;\n tableConfig: TableConfigInterface;\n vxeGridOptions?: any;\n columns: any[];\n queryConfig?: TableQueryFrame[];\n tableToolButtons?: KeButton[];\n tableRowButtons?: KeButton[];\n tableData: any[];\n tablePagination?: Pagination;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n vxeGridOptions: undefined,\n queryConfig: () => [],\n tableToolButtons: () => [],\n tableRowButtons: () => [],\n tableData: () => [],\n tablePagination: () => ({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n }),\n});\n\nconst emits = defineEmits([\n 'btnClick', // 按钮\n 'queryClick', // 查询按钮点击事件\n 'valueChange', // 当某个单元格发生数据变化时\n 'treeLazyLoad', // 懒加载事件\n 'onSelection', // 当选择项发生变化时会触发该事件\n]);\n\nconst pagination = defineModel('tablePagination', {\n required: true,\n type: Object as PropType<Pagination>,\n});\n\n/**\n * 查询内容\n */\nconst queryData = {};\n\n/**\n * 查询\n * @param data\n */\nconst queryClick = (data: any) => {\n emits('queryClick', data);\n};\n\nlet titleField = '';\n/**\n * 获取标题\n * @param cardItem\n */\nconst getTitle = (cardItem: any) => {\n if (props.tableConfig.titleField) {\n return cardItem[props.tableConfig.titleField];\n } else if (isNotEmpty(titleField)) {\n return cardItem[titleField];\n }\n\n for (const key in cardItem) {\n if (typeof cardItem[key] === 'string' && isNotEmpty(cardItem[key])) {\n titleField = key;\n return cardItem[key];\n }\n }\n return '';\n};\n\nconst queryBarRef = ref();\n\n/**\n * 按钮事件\n *\n * @param data\n * @param button\n */\nconst btnClick = (data: any, button: any) => {\n useButtonExec(data, button);\n};\n\n/**\n * 已循环过的格式化对象\n */\nconst translateObject = {};\n/**\n * 循环到的索引\n */\nconst translateIndexArray: any[] = [];\n/**\n * 格式化方法\n */\nconst formatterCellValue = (value: any, cell: any) => {\n return customFormatter({\n cellValue: value,\n tabObj: cell.tabObj,\n translateJson: cell.translate,\n fieldName: cell.field,\n translateObject,\n translateIndexArray,\n });\n};\n\n/**\n * 字段值改动通知\n * @param fieldName 字段名\n * @param newValue 改动后的值\n * @param rowId\n */\nconst fieldValueChanged = (\n fieldName: string,\n newValue: any,\n rowId: number | string,\n) => {\n emits('valueChange', fieldName, newValue, rowId);\n};\n\n/**\n * 翻页\n */\nconst paginationChange = () => {\n emits('queryClick', queryData);\n};\n</script>\n\n<template>\n <div class=\"table-card-render-client\">\n <KeQueryBar\n v-if=\"queryConfig && queryConfig.length > 0\"\n ref=\"queryBarRef\"\n :frame=\"queryConfig\"\n @query-click=\"queryClick\"\n />\n <div v-if=\"tableToolButtons.length > 0\" class=\"table-tool-button\">\n <KeToolBar :tool-buttons=\"tableToolButtons\" />\n </div>\n <div class=\"card-container\">\n <el-scrollbar>\n <el-row :gutter=\"12\">\n <el-col\n v-for=\"cardItem in tableData\"\n :key=\"cardItem[tableConfig.rowKey]\"\n :lg=\"8\"\n :md=\"8\"\n :sm=\"12\"\n :xl=\"6\"\n :xs=\"24\"\n style=\"margin-top: 6px; margin-bottom: 6px\"\n >\n <el-card>\n <template v-if=\"tableConfig.coverField\">\n <!-- 封面图片-->\n <img :src=\"cardItem[tableConfig.coverField]\" alt=\"\" />\n </template>\n <h1 class=\"title-wrapper\">\n <span class=\"title-text\">{{ getTitle(cardItem) }}</span>\n <el-dropdown\n v-if=\"\n Array.isArray(tableRowButtons) && tableRowButtons.length > 0\n \"\n class=\"dropdown-wrapper\"\n >\n <el-button :icon=\"More\" text />\n <template #dropdown>\n <el-dropdown-menu>\n <el-dropdown-item\n v-for=\"btn in tableRowButtons\"\n :key=\"btn.id\"\n @click=\"btnClick(cardItem, btn)\"\n >\n <template #default>\n <span\n :style=\"{ color: `var(--el-color-${btn.type})` }\"\n >\n {{ btn.label }}\n </span>\n </template>\n </el-dropdown-item>\n </el-dropdown-menu>\n </template>\n </el-dropdown>\n </h1>\n <template v-for=\"cardCol in columns\" :key=\"cardCol.field\">\n <el-form-item\n v-if=\"cardCol.field !== tableConfig.coverField\"\n :label=\"cardCol.title\"\n >\n <template v-if=\"cardCol.cellRender || cardCol.editRender\">\n <!-- {{ dataFormatter({ })}}-->\n <component\n :is=\"cardCol.editRender.name\"\n v-model:value=\"cardItem[cardCol.field]\"\n :detail=\"cardCol\"\n :disabled=\"cardCol.editRender.enabled\"\n :row-data=\"cardItem\"\n @value-change=\"fieldValueChanged\"\n />\n </template>\n <template v-else>\n {{ formatterCellValue(cardItem[cardCol.field], cardCol) }}\n </template>\n </el-form-item>\n </template>\n </el-card>\n </el-col>\n </el-row>\n </el-scrollbar>\n </div>\n <div class=\"pagination-div\">\n <el-pagination\n v-model:current-page=\"pagination.currentPage\"\n v-model:page-size=\"pagination.pageSize\"\n :total=\"tablePagination.total\"\n background\n layout=\"total, prev, pager, next, jumper\"\n size=\"small\"\n @current-change=\"paginationChange\"\n />\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n/**\n禁用横向滚动条\n */\n:deep(.el-scrollbar__wrap) {\n overflow-x: hidden !important;\n}\n\n:deep(.el-scrollbar__bar.is-horizontal) {\n height: 0 !important;\n}\n\n:deep(.el-form-item) {\n margin-bottom: 0 !important;\n}\n\n.table-card-render-client {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n}\n\n.title-wrapper {\n display: flex;\n align-items: center;\n justify-content: space-between; /* 确保内容与按钮分布在两端 */\n\n .title-text {\n flex: 1; /* 确保文字部分可以占满剩余空间 */\n }\n\n .dropdown-wrapper {\n margin-left: auto; /* 确保按钮总是靠右对齐 */\n }\n}\n\n.table-tool-button {\n margin-top: 6px; /* 可选:给工具条加一些顶部间距 */\n}\n\n.card-container {\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n overflow: hidden; /* 防止内容溢出 */\n}\n\n.pagination-div {\n padding: 6px;\n margin-top: 10px; /* 可选:分页与表格之间的间距 */\n background: var(--el-fill-color-blank);\n}\n</style>\n","import TableCardRender from './TableCardRender.vue';\nimport type { App } from 'vue';\n\n(TableCardRender as any).name = 'TableCardRender';\n\nTableCardRender.install = (app: App) => {\n app.component('TableCardRender', TableCardRender);\n};\n\nexport { TableCardRender };\n","import { emitter } from '@/utils';\n\nexport const useMittHook = (\n fieldName: string,\n mittId: null | number | string,\n) => {\n if (!mittId) {\n return {\n registerMitt: () => {},\n offMitt: () => {},\n }\n }\n /**\n * 注册mitt广播事件\n */\n const registerMitt = (func?: Function) => {\n if (mittId && emitter) {\n emitter.on(fieldName + mittId, (_eventData) => {\n if (func) {\n func(_eventData);\n }\n });\n }\n };\n\n /**\n * 关闭mitt订阅\n */\n const offMitt = () => {\n if (mittId && emitter) {\n emitter.off(fieldName + mittId);\n }\n };\n\n return { registerMitt, offMitt };\n};\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\nconst inputValue = defineModel('value');\n\n/** 值发生变化时 */\n// const change = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// inputValue,\n// );\n// }\n// };\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n inputValue.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input\n v-model=\"inputValue\"\n :placeholder=\"props.detail?.placeholder\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n >\n <template\n v-if=\"detail.componentParams && detail.componentParams.prepend\"\n #prepend\n >\n <span>{{ detail.componentParams.prepend }}</span>\n </template>\n <template\n v-if=\"detail.componentParams && detail.componentParams.append\"\n #append\n >\n <span>{{ detail.componentParams.append }}</span>\n </template>\n </el-input>\n</template>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\nconst inputValue = defineModel('value');\n\n/** 值发生变化时 */\n// const change = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// inputValue,\n// );\n// }\n// };\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n inputValue.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input\n v-model=\"inputValue\"\n :placeholder=\"props.detail?.placeholder\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n >\n <template\n v-if=\"detail.componentParams && detail.componentParams.prepend\"\n #prepend\n >\n <span>{{ detail.componentParams.prepend }}</span>\n </template>\n <template\n v-if=\"detail.componentParams && detail.componentParams.append\"\n #append\n >\n <span>{{ detail.componentParams.append }}</span>\n </template>\n </el-input>\n</template>\n","import FormInput from './FormInput.vue';\nimport type { App } from 'vue';\n\n(FormInput as any).name = 'FormInput';\n\nFormInput.install = (app: App) => {\n app.component('FormInput', FormInput);\n};\n\nexport { FormInput };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: null | number;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n mittId: () => null,\n});\n\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input-number\n v-model=\"valueRef\"\n :placeholder=\"detail.placeholder\"\n class=\"full\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n >\n <template\n v-if=\"detail.componentParams && detail.componentParams.prefix\"\n #prefix\n >\n <span>{{ detail.componentParams.prefix }}</span>\n </template>\n <template\n v-if=\"detail.componentParams && detail.componentParams.suffix\"\n #suffix\n >\n <span>{{ detail.componentParams.suffix }}</span>\n </template>\n </el-input-number>\n</template>\n\n<style scoped>\n.full {\n width: 100%;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: null | number;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n mittId: () => null,\n});\n\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input-number\n v-model=\"valueRef\"\n :placeholder=\"detail.placeholder\"\n class=\"full\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n >\n <template\n v-if=\"detail.componentParams && detail.componentParams.prefix\"\n #prefix\n >\n <span>{{ detail.componentParams.prefix }}</span>\n </template>\n <template\n v-if=\"detail.componentParams && detail.componentParams.suffix\"\n #suffix\n >\n <span>{{ detail.componentParams.suffix }}</span>\n </template>\n </el-input-number>\n</template>\n\n<style scoped>\n.full {\n width: 100%;\n}\n</style>\n","import FormInputNumber from './FormInputNumber.vue';\nimport type { App } from 'vue';\n\n(FormInputNumber as any).name = 'FormInputNumber';\n\nFormInputNumber.install = (app: App) => {\n app.component('FormInputNumber', FormInputNumber);\n};\n\nexport { FormInputNumber };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 值发生变化时 */\n// const change = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// inputValue,\n// );\n// }\n// };\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input\n v-model=\"valueRef\"\n :autosize=\"{ minRows: 2 }\"\n :placeholder=\"\n props.detail?.placeholder\n ? props.detail.placeholder\n : `请输入${props.detail?.title}`\n \"\n type=\"textarea\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 值发生变化时 */\n// const change = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// inputValue,\n// );\n// }\n// };\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input\n v-model=\"valueRef\"\n :autosize=\"{ minRows: 2 }\"\n :placeholder=\"\n props.detail?.placeholder\n ? props.detail.placeholder\n : `请输入${props.detail?.title}`\n \"\n type=\"textarea\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n />\n</template>\n","import FormTextArea from './FormTextArea.vue';\nimport type { App } from 'vue';\n\n(FormTextArea as any).name = 'FormTextArea';\n\nFormTextArea.install = (app: App) => {\n app.component('FormTextArea', FormTextArea);\n};\n\nexport { FormTextArea };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst valueRef = defineModel('value');\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-text\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n >\n {{ valueRef }}\n </el-text>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst valueRef = defineModel('value');\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-text\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n >\n {{ valueRef }}\n </el-text>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import FormText from './FormText.vue';\nimport type { App } from 'vue';\n\n(FormText as any).name = 'FormText';\n\nFormText.install = (app: App) => {\n app.component('FormText', FormText);\n};\n\nexport { FormText };\n","<script setup lang=\"ts\">\nimport type { FormSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits(['update:value', 'getComponentValue', 'valueChange']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 如果是多选 value位数组类型时, value就不能为null\n */\nconst multipleClear = async () => {\n await sleep(0.1);\n if (\n (props.detail.multiple || props.detail.componentParams?.mode === 'tags') &&\n valueRef.value === null\n ) {\n valueRef.value = [];\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n multipleClear();\n});\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.multiple\"\n :placeholder=\"detail.placeholder\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n clearable\n >\n <el-option\n v-for=\"item in props.detail?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits(['update:value', 'getComponentValue', 'valueChange']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 如果是多选 value位数组类型时, value就不能为null\n */\nconst multipleClear = async () => {\n await sleep(0.1);\n if (\n (props.detail.multiple || props.detail.componentParams?.mode === 'tags') &&\n valueRef.value === null\n ) {\n valueRef.value = [];\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n multipleClear();\n});\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.multiple\"\n :placeholder=\"detail.placeholder\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n clearable\n >\n <el-option\n v-for=\"item in props.detail?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","import FormSelect from './FormSelect.vue';\nimport type { App } from 'vue';\n\n(FormSelect as any).name = 'FormSelect';\n\nFormSelect.install = (app: App) => {\n app.component('FormSelect', FormSelect);\n};\n\nexport { FormSelect };\n","import type { Ref } from 'vue';\n\nimport type { FormSelectAsyncProp, OptionInterface } from '@/types';\n\nimport { ref } from 'vue';\n\nimport { isEmpty, msgTips, sleep } from '@/utils';\n\ninterface Props {\n detail: FormSelectAsyncProp;\n fieldTitle: string;\n mittId?: number | string;\n}\n\n// 2. SelectAsync 接口绑定\ninterface SelectAsync<EE extends (...args: any) => void> {\n emits: EE;\n props: Readonly<Props>;\n valueRef: Ref;\n}\n\nexport const useSelectAsync = <EE extends (...args: any) => void>(\n params: SelectAsync<EE>,\n) => {\n const { emits, props } = params;\n\n const loading = ref<boolean>(false);\n let load = false;\n let isLoadFail = false;\n let oldComponentValueMap: any = {};\n\n // 选项\n const optionsData = ref<any[] | OptionInterface[]>([]);\n\n const init = async () => {\n await sleep(0.05 + Math.floor(Math.random() * 300) / 100);\n await getOptions();\n };\n\n /**\n * 验证获取的其他组件的参数是否有\n * @param params\n * @param fieldNames\n */\n const verifyHttpOtherParams = (params: any, fieldNames: string[]) => {\n let result = true;\n if (fieldNames.length > 0 && !params) {\n return false;\n }\n fieldNames.forEach((fieldName) => {\n if (params[fieldName] === undefined || params[fieldName] === null) {\n result = false;\n }\n });\n\n return result;\n };\n\n /** 远程获取 */\n const getOptions = async () => {\n if (loading.value) return;\n if (isEmpty(props.detail.optionHttpUrl)) return;\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n // 如果(已经加载 || 加载失败)且新获取的表单数据与旧数据一样,则不再重新请求\n if (\n (load || isLoadFail) &&\n JSON.stringify(componentValueMap) === JSON.stringify(oldComponentValueMap)\n )\n return;\n\n if (\n !verifyHttpOtherParams(\n componentValueMap,\n props.detail.optionHttpComponentValue,\n )\n ) {\n // 验证失败则不发http请求\n return;\n }\n\n loading.value = true;\n oldComponentValueMap = componentValueMap;\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (\n !['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)\n ) {\n opt.body = JSON.stringify({\n prop: props.detail.field,\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n load = true;\n optionsData.value = result.data;\n } else {\n msgTips.alert({\n msg: `${props.fieldTitle}数据获取失败!`,\n type: 'warning',\n });\n isLoadFail = true;\n }\n loading.value = false;\n };\n\n /** 当值发生变化时 */\n // const handleChange = async () => {\n // // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n // if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n // await nextTick();\n // emits(\n // 'valueChange',\n // props.detail?.noticeField,\n // props.detail?.field,\n // valueRef.value,\n // );\n // }\n // };\n\n return {\n getOptions,\n optionsData,\n loading,\n // handleChange,\n init,\n };\n};\n","<script setup lang=\"ts\">\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useSelectAsync } from '../hooks/selectAsync.hook';\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\n// 1. 定义 emits 类型(强类型)\nconst emits = defineEmits<{\n (event: 'update:value', value: any): void;\n (\n event: 'getComponentValue',\n componentValue: any,\n callback: (val: any) => void,\n ): void;\n (event: 'valueChange', value: any): void;\n (event: 'setShow', show: boolean): void;\n}>();\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst { loading, getOptions, optionsData, init } = useSelectAsync({\n emits,\n props,\n valueRef,\n});\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n init();\n registerMitt((_eventData: any) => {\n receiveBroadcasts(_eventData);\n getOptions();\n });\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"props.detail.multiple\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n :loading=\"loading\"\n :placeholder=\"props.detail?.placeholder\"\n v-loading=\"loading\"\n @focus=\"getOptions\"\n >\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useSelectAsync } from '../hooks/selectAsync.hook';\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\n// 1. 定义 emits 类型(强类型)\nconst emits = defineEmits<{\n (event: 'update:value', value: any): void;\n (\n event: 'getComponentValue',\n componentValue: any,\n callback: (val: any) => void,\n ): void;\n (event: 'valueChange', value: any): void;\n (event: 'setShow', show: boolean): void;\n}>();\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst { loading, getOptions, optionsData, init } = useSelectAsync({\n emits,\n props,\n valueRef,\n});\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n init();\n registerMitt((_eventData: any) => {\n receiveBroadcasts(_eventData);\n getOptions();\n });\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"props.detail.multiple\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n :loading=\"loading\"\n :placeholder=\"props.detail?.placeholder\"\n v-loading=\"loading\"\n @focus=\"getOptions\"\n >\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","import FormSelectAsync from './FormSelectAsync.vue';\nimport type { App } from 'vue';\n\n(FormSelectAsync as any).name = 'FormSelectAsync';\n\nFormSelectAsync.install = (app: App) => {\n app.component('FormSelectAsync', FormSelectAsync);\n};\n\nexport { FormSelectAsync };\n","<script setup lang=\"ts\">\nimport type { FormSelectAsyncProp, OptionInterface } from '@/types';\n\nimport { onMounted, onUnmounted, ref } from 'vue';\n\nimport { isEmpty } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst valueRef = defineModel('value');\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst optionsData = ref<OptionInterface[]>([]);\nconst loading = ref(false);\n\n/**\n * 远程搜索\n * @param queryStr\n */\nconst remoteMethod = async (queryStr: string) => {\n if (isEmpty(queryStr)) {\n return;\n }\n if (isEmpty(props.detail.optionHttpUrl)) return;\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n loading.value = true;\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (!['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n searchValue: queryStr,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n // 如果获取成功!\n optionsData.value = result.code === 0 ? result.data : [];\n loading.value = false;\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"props.detail.multiple\"\n filterable\n remote\n reserve-keyword\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n :loading=\"loading\"\n :placeholder=\"props.detail?.placeholder\"\n :remote-method=\"remoteMethod\"\n >\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport type { FormSelectAsyncProp, OptionInterface } from '@/types';\n\nimport { onMounted, onUnmounted, ref } from 'vue';\n\nimport { isEmpty } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst valueRef = defineModel('value');\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst optionsData = ref<OptionInterface[]>([]);\nconst loading = ref(false);\n\n/**\n * 远程搜索\n * @param queryStr\n */\nconst remoteMethod = async (queryStr: string) => {\n if (isEmpty(queryStr)) {\n return;\n }\n if (isEmpty(props.detail.optionHttpUrl)) return;\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n loading.value = true;\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (!['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n searchValue: queryStr,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n // 如果获取成功!\n optionsData.value = result.code === 0 ? result.data : [];\n loading.value = false;\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"props.detail.multiple\"\n filterable\n remote\n reserve-keyword\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n :loading=\"loading\"\n :placeholder=\"props.detail?.placeholder\"\n :remote-method=\"remoteMethod\"\n >\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import FormSelectRemote from './FormSelectRemote.vue';\nimport type { App } from 'vue';\n\n(FormSelectRemote as any).name = 'FormSelectRemote';\n\nFormSelectRemote.install = (app: App) => {\n app.component('FormSelectRemote', FormSelectRemote);\n};\n\nexport { FormSelectRemote };\n","<script setup lang=\"ts\">\nimport type { FormRadioProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormRadioProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\n\nconst valueRef = defineModel('value', {\n required: true,\n});\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-radio-group v-model=\"valueRef\">\n <el-radio\n v-for=\"item in detail.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :value=\"item.value\"\n >\n {{ item.label }}\n </el-radio>\n </el-radio-group>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport type { FormRadioProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormRadioProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\n\nconst valueRef = defineModel('value', {\n required: true,\n});\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-radio-group v-model=\"valueRef\">\n <el-radio\n v-for=\"item in detail.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :value=\"item.value\"\n >\n {{ item.label }}\n </el-radio>\n </el-radio-group>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import FormRadio from './FormRadio.vue';\nimport type { App } from 'vue';\n\n(FormRadio as any).name = 'FormRadio';\n\nFormRadio.install = (app: App) => {\n app.component('FormRadio', FormRadio);\n};\n\nexport { FormRadio };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst checkData = defineModel('value', {\n type: Array as PropType<any[]>,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n checkData.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in detail.options\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst checkData = defineModel('value', {\n type: Array as PropType<any[]>,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n checkData.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in detail.options\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n</template>\n\n<style scoped></style>\n","import FormCheckBox from './FormCheckBox.vue';\nimport type { App } from 'vue';\n\n(FormCheckBox as any).name = 'FormCheckBox';\n\nFormCheckBox.install = (app: App) => {\n app.component('FormCheckBox', FormCheckBox);\n};\n\nexport { FormCheckBox };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted, reactive } from 'vue';\n\nimport { isEmpty, msgTips } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectAsyncProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst checkData = defineModel('value', {\n type: Array as PropType<any[]>,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst options = reactive<any>({\n loading: false,\n load: false,\n data: [],\n});\n\nlet oldComponentValueMap: any = {};\nconst isLoadFail = false;\n/** 获取选项 */\nconst getOptions = async () => {\n // 如果url为空 则不进行加载\n if (isEmpty(props.detail?.optionHttpUrl)) return;\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n // 如果(已经加载 || 加载失败)且新获取的表单数据与旧数据一样,则不再重新请求\n if (\n (options.load || isLoadFail) &&\n JSON.stringify(componentValueMap) === JSON.stringify(oldComponentValueMap)\n )\n return;\n\n options.loading = true;\n oldComponentValueMap = componentValueMap;\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (!['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n prop: props.detail.field,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n options.load = true;\n options.data = result.data;\n } else {\n msgTips.tips({\n msg: `${result.msg}`,\n type: 'warning',\n });\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n checkData.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n getOptions();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in options.data\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted, reactive } from 'vue';\n\nimport { isEmpty, msgTips } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectAsyncProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst checkData = defineModel('value', {\n type: Array as PropType<any[]>,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst options = reactive<any>({\n loading: false,\n load: false,\n data: [],\n});\n\nlet oldComponentValueMap: any = {};\nconst isLoadFail = false;\n/** 获取选项 */\nconst getOptions = async () => {\n // 如果url为空 则不进行加载\n if (isEmpty(props.detail?.optionHttpUrl)) return;\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n // 如果(已经加载 || 加载失败)且新获取的表单数据与旧数据一样,则不再重新请求\n if (\n (options.load || isLoadFail) &&\n JSON.stringify(componentValueMap) === JSON.stringify(oldComponentValueMap)\n )\n return;\n\n options.loading = true;\n oldComponentValueMap = componentValueMap;\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (!['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n prop: props.detail.field,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n options.load = true;\n options.data = result.data;\n } else {\n msgTips.tips({\n msg: `${result.msg}`,\n type: 'warning',\n });\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n checkData.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n getOptions();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in options.data\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n</template>\n\n<style scoped></style>\n","import FormCheckBoxAsync from './FormCheckBoxAsync.vue';\nimport type { App } from 'vue';\n\n(FormCheckBoxAsync as any).name = 'FormCheckBoxAsync';\n\nFormCheckBoxAsync.install = (app: App) => {\n app.component('FormCheckBoxAsync', FormCheckBoxAsync);\n};\n\nexport { FormCheckBoxAsync };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value: boolean;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => false,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel<boolean>('value');\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst setDefaultValue = async () => {\n await sleep(0.1);\n if (!valueRef.value) {\n valueRef.value = false;\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: boolean) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n setDefaultValue();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-switch v-model=\"valueRef\" v-bind=\"detail.componentParams\" />\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value: boolean;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => false,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel<boolean>('value');\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst setDefaultValue = async () => {\n await sleep(0.1);\n if (!valueRef.value) {\n valueRef.value = false;\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: boolean) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n setDefaultValue();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-switch v-model=\"valueRef\" v-bind=\"detail.componentParams\" />\n</template>\n\n<style scoped></style>\n","import FormSwitch from './FormSwitch.vue';\nimport type { App } from 'vue';\n\n(FormSwitch as any).name = 'FormSwitch';\n\nFormSwitch.install = (app: App) => {\n app.component('FormSwitch', FormSwitch);\n};\n\nexport { FormSwitch };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { getLunar } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'valueChange']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\nconst getShowText = (cell: any) => {\n if (cell.renderText) {\n return cell.renderText;\n }\n return cell.text;\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueRef\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n format=\"YYYY-MM-DD\"\n style=\"width: 100%\"\n value-format=\"YYYY-MM-DD\"\n >\n <template #default=\"cell\">\n <div class=\"dateCell\">\n <span class=\"solar_calendar\">\n {{ getShowText(cell) }}\n </span>\n <span class=\"lunar_calendar\">{{ getLunar(cell) }}</span>\n </div>\n </template>\n </el-date-picker>\n</template>\n\n<style scoped lang=\"scss\">\ntd.current .dateCell {\n color: #fff; /* 文本颜色变为白色 */\n background-color: var(--el-color-primary); /* 黄色背景,表示高亮 */\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\ntd.today .dateCell {\n color: var(--el-color-primary);\n}\n\n.dateCell {\n width: 48px;\n height: 42px;\n\n span {\n display: block;\n }\n\n .solar_calendar {\n font-size: 16px;\n font-weight: 400;\n }\n\n .lunar_calendar {\n margin-top: -14px;\n margin-bottom: -6px;\n overflow: hidden;\n font-size: 10px;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { getLunar } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'valueChange']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\nconst getShowText = (cell: any) => {\n if (cell.renderText) {\n return cell.renderText;\n }\n return cell.text;\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueRef\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n format=\"YYYY-MM-DD\"\n style=\"width: 100%\"\n value-format=\"YYYY-MM-DD\"\n >\n <template #default=\"cell\">\n <div class=\"dateCell\">\n <span class=\"solar_calendar\">\n {{ getShowText(cell) }}\n </span>\n <span class=\"lunar_calendar\">{{ getLunar(cell) }}</span>\n </div>\n </template>\n </el-date-picker>\n</template>\n\n<style scoped lang=\"scss\">\ntd.current .dateCell {\n color: #fff; /* 文本颜色变为白色 */\n background-color: var(--el-color-primary); /* 黄色背景,表示高亮 */\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\ntd.today .dateCell {\n color: var(--el-color-primary);\n}\n\n.dateCell {\n width: 48px;\n height: 42px;\n\n span {\n display: block;\n }\n\n .solar_calendar {\n font-size: 16px;\n font-weight: 400;\n }\n\n .lunar_calendar {\n margin-top: -14px;\n margin-bottom: -6px;\n overflow: hidden;\n font-size: 10px;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n}\n</style>\n","import FormDatePicker from './FormDatePicker.vue';\nimport type { App } from 'vue';\n\n(FormDatePicker as any).name = 'FormDatePicker';\n\nFormDatePicker.install = (app: App) => {\n app.component('FormDatePicker', FormDatePicker);\n};\n\nexport { FormDatePicker };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { getLunar } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\nconst getShowText = (cell: any) => {\n if (cell.renderText) {\n return cell.renderText;\n }\n return cell.text;\n};\n\n/**\n * 用于日期组件的shortcuts预设\n */\nconst elShortcuts = [\n {\n text: '昨天',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() - 3600 * 1000 * 24);\n return date;\n },\n },\n {\n text: '明天',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() + 3600 * 1000 * 24);\n return date;\n },\n },\n {\n text: '上周',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);\n return date;\n },\n },\n {\n text: '1周前',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() + 3600 * 1000 * 24 * 7);\n return date;\n },\n },\n];\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueRef\"\n :shortcuts=\"elShortcuts\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n format=\"YYYY-MM-DD HH:mm:ss\"\n style=\"width: 100%\"\n type=\"datetime\"\n value-format=\"YYYY-MM-DD HH:mm:ss\"\n >\n <template #default=\"cell\">\n <div class=\"dateCell\">\n <span class=\"solar_calendar\">\n {{ getShowText(cell) }}\n </span>\n <span class=\"lunar_calendar\">{{ getLunar(cell) }}</span>\n </div>\n </template>\n </el-date-picker>\n</template>\n\n<style scoped lang=\"scss\">\ntd.current .dateCell {\n color: #fff; /* 文本颜色变为白色 */\n background-color: var(--el-color-primary); /* 黄色背景,表示高亮 */\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\ntd.today .dateCell {\n color: var(--el-color-primary);\n}\n\n.dateCell {\n width: 48px;\n height: 42px;\n\n span {\n display: block;\n }\n\n .solar_calendar {\n font-size: 16px;\n font-weight: 400;\n }\n\n .lunar_calendar {\n margin-top: -14px;\n margin-bottom: -6px;\n overflow: hidden;\n font-size: 10px;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { getLunar } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\nconst getShowText = (cell: any) => {\n if (cell.renderText) {\n return cell.renderText;\n }\n return cell.text;\n};\n\n/**\n * 用于日期组件的shortcuts预设\n */\nconst elShortcuts = [\n {\n text: '昨天',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() - 3600 * 1000 * 24);\n return date;\n },\n },\n {\n text: '明天',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() + 3600 * 1000 * 24);\n return date;\n },\n },\n {\n text: '上周',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);\n return date;\n },\n },\n {\n text: '1周前',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() + 3600 * 1000 * 24 * 7);\n return date;\n },\n },\n];\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueRef\"\n :shortcuts=\"elShortcuts\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n format=\"YYYY-MM-DD HH:mm:ss\"\n style=\"width: 100%\"\n type=\"datetime\"\n value-format=\"YYYY-MM-DD HH:mm:ss\"\n >\n <template #default=\"cell\">\n <div class=\"dateCell\">\n <span class=\"solar_calendar\">\n {{ getShowText(cell) }}\n </span>\n <span class=\"lunar_calendar\">{{ getLunar(cell) }}</span>\n </div>\n </template>\n </el-date-picker>\n</template>\n\n<style scoped lang=\"scss\">\ntd.current .dateCell {\n color: #fff; /* 文本颜色变为白色 */\n background-color: var(--el-color-primary); /* 黄色背景,表示高亮 */\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\ntd.today .dateCell {\n color: var(--el-color-primary);\n}\n\n.dateCell {\n width: 48px;\n height: 42px;\n\n span {\n display: block;\n }\n\n .solar_calendar {\n font-size: 16px;\n font-weight: 400;\n }\n\n .lunar_calendar {\n margin-top: -14px;\n margin-bottom: -6px;\n overflow: hidden;\n font-size: 10px;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n}\n</style>\n","import FormDateTimePicker from './FormDateTimePicker.vue';\nimport type { App } from 'vue';\n\n(FormDateTimePicker as any).name = 'FormDateTimePicker';\n\nFormDateTimePicker.install = (app: App) => {\n app.component('FormDateTimePicker', FormDateTimePicker);\n};\n\nexport { FormDateTimePicker };\n","<script setup lang=\"ts\">\nimport type { CascaderProps } from 'element-plus';\n\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { isEmpty, msgTips } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: null | number[] | string[];\n detail: FormSelectAsyncProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst cascaderProps: CascaderProps = {\n lazy: true,\n lazyLoad: async (node, resolve) => {\n if (isEmpty(props.detail.optionHttpUrl)) resolve([]);\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n if (node.data && node.data.value) {\n componentValueMap.nodeValue = node.data.value;\n }\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (\n !['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)\n ) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n resolve(result.data);\n } else {\n msgTips.tips({\n msg: `${props.detail.title}数据获取失败!${result.msg}`,\n type: 'warning',\n });\n resolve([]);\n }\n },\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-cascader\n v-model=\"valueRef\"\n :props=\"{ ...cascaderProps, ...props.detail.componentParams }\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n />\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport type { CascaderProps } from 'element-plus';\n\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { isEmpty, msgTips } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: null | number[] | string[];\n detail: FormSelectAsyncProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst cascaderProps: CascaderProps = {\n lazy: true,\n lazyLoad: async (node, resolve) => {\n if (isEmpty(props.detail.optionHttpUrl)) resolve([]);\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n if (node.data && node.data.value) {\n componentValueMap.nodeValue = node.data.value;\n }\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (\n !['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)\n ) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n resolve(result.data);\n } else {\n msgTips.tips({\n msg: `${props.detail.title}数据获取失败!${result.msg}`,\n type: 'warning',\n });\n resolve([]);\n }\n },\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-cascader\n v-model=\"valueRef\"\n :props=\"{ ...cascaderProps, ...props.detail.componentParams }\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n />\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import FormCascaderAsync from './FormCascaderAsync.vue';\nimport type { App } from 'vue';\n\n(FormCascaderAsync as any).name = 'FormCascaderAsync';\n\nFormCascaderAsync.install = (app: App) => {\n app.component('FormCascaderAsync', FormCascaderAsync);\n};\n\nexport { FormCascaderAsync };\n","<script setup lang=\"ts\">\nimport type { FormTableSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormTableSelectProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits(['getComponentValue', 'valueChange']);\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\nconst valueRef = defineModel('value');\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\n/**\n * 如果是多选 value位数组类型时, value就不能为null\n */\nconst multipleClear = async () => {\n await sleep(0.1);\n if (\n (props.detail.multiple || props.detail.componentParams?.mode === 'tags') &&\n valueRef.value === null\n ) {\n valueRef.value = [];\n }\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n console.log('Receive event data', eventData);\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n multipleClear();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n :multiple=\"detail?.multiple\"\n :placeholder=\"detail.placeholder\"\n :value-key=\"detail.componentParams.keyField\"\n clearable\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in detail?.options\"\n :key=\"item[detail.componentParams?.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.componentParams?.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.componentParams?.optionWidth\n ? `${detail.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.componentParams?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormTableSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormTableSelectProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits(['getComponentValue', 'valueChange']);\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\nconst valueRef = defineModel('value');\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\n/**\n * 如果是多选 value位数组类型时, value就不能为null\n */\nconst multipleClear = async () => {\n await sleep(0.1);\n if (\n (props.detail.multiple || props.detail.componentParams?.mode === 'tags') &&\n valueRef.value === null\n ) {\n valueRef.value = [];\n }\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n console.log('Receive event data', eventData);\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n multipleClear();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n :multiple=\"detail?.multiple\"\n :placeholder=\"detail.placeholder\"\n :value-key=\"detail.componentParams.keyField\"\n clearable\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in detail?.options\"\n :key=\"item[detail.componentParams?.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.componentParams?.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.componentParams?.optionWidth\n ? `${detail.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.componentParams?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n\n<style scoped></style>\n","import FormTableSelect from './FormTableSelect.vue';\nimport type { App } from 'vue';\n\n(FormTableSelect as any).name = 'FormTableSelect';\n\nFormTableSelect.install = (app: App) => {\n app.component('FormTableSelect', FormTableSelect);\n};\n\nexport { FormTableSelect };\n","<script setup lang=\"ts\">\nimport type { FormTableSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useSelectAsync } from '../hooks/selectAsync.hook';\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormTableSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\n// 1. 定义 emits 类型(强类型)\nconst emits = defineEmits<{\n (event: 'update:value', value: any): void;\n (\n event: 'getComponentValue',\n componentValue: any,\n callback: (val: any) => void,\n ): void;\n (event: 'valueChange', value: any): void;\n (event: 'setShow', show: boolean): void;\n}>();\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst { loading, getOptions, optionsData, init } = useSelectAsync({\n emits,\n props,\n valueRef,\n});\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n init();\n registerMitt((_eventData: any) => {\n receiveBroadcasts(_eventData);\n getOptions();\n });\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n v-loading=\"loading\"\n :multiple=\"detail.multiple\"\n :loading=\"loading\"\n :placeholder=\"detail?.placeholder\"\n :value-key=\"detail.componentParams.keyField\"\n @focus=\"getOptions\"\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item[detail.componentParams?.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.componentParams?.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.componentParams?.optionWidth\n ? `${detail.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.componentParams?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormTableSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useSelectAsync } from '../hooks/selectAsync.hook';\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormTableSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\n// 1. 定义 emits 类型(强类型)\nconst emits = defineEmits<{\n (event: 'update:value', value: any): void;\n (\n event: 'getComponentValue',\n componentValue: any,\n callback: (val: any) => void,\n ): void;\n (event: 'valueChange', value: any): void;\n (event: 'setShow', show: boolean): void;\n}>();\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst { loading, getOptions, optionsData, init } = useSelectAsync({\n emits,\n props,\n valueRef,\n});\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n init();\n registerMitt((_eventData: any) => {\n receiveBroadcasts(_eventData);\n getOptions();\n });\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n v-loading=\"loading\"\n :multiple=\"detail.multiple\"\n :loading=\"loading\"\n :placeholder=\"detail?.placeholder\"\n :value-key=\"detail.componentParams.keyField\"\n @focus=\"getOptions\"\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item[detail.componentParams?.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.componentParams?.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.componentParams?.optionWidth\n ? `${detail.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.componentParams?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n\n<style scoped></style>\n","import FormTableSelectAsync from './FormTableSelectAsync.vue';\nimport type { App } from 'vue';\n\n(FormTableSelectAsync as any).name = 'FormTableSelectAsync';\n\nFormTableSelectAsync.install = (app: App) => {\n app.component('FormTableSelectAsync', FormTableSelectAsync);\n};\n\nexport { FormTableSelectAsync };\n","<script setup lang=\"ts\">\r\nimport type { FormFrame } from '@/types';\r\n\r\nimport { computed, onMounted, ref } from 'vue';\r\n\r\nimport { Search } from '@element-plus/icons-vue';\r\n\r\nimport { datasetApi } from '@/api';\r\n\r\ninterface Props {\r\n value?: string;\r\n detail: FormFrame;\r\n mittId?: any;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n value: '',\r\n mittId: () => null,\r\n});\r\n\r\nconst emits = defineEmits(['update:value', 'valueChange']);\r\nconst valueRef = defineModel('value');\r\n\r\n// 对话框控制\r\nconst dialogVisible = ref(false);\r\nconst dialogTitle = ref('');\r\nconst dialogMode = ref<'add' | 'edit' | 'preview'>('preview');\r\n\r\n// 当前选中的字典\r\nconst selectedDict = ref<any>(null);\r\n\r\n// 字典表列表\r\nconst dictTables = ref<any[]>([]);\r\n\r\n// 字典项列表\r\nconst dictItems = ref<any[]>([]);\r\n\r\n// 搜索关键词\r\nconst searchKeyword = ref('');\r\n\r\n// 加载状态\r\nconst loading = ref(false);\r\nconst itemsLoading = ref(false);\r\n\r\n// 表单数据\r\nconst formData = ref<any>({});\r\n\r\n// 获取字典表列表\r\nconst loadDictTables = async () => {\r\n loading.value = true;\r\n try {\r\n const res = await datasetApi('getDictionaryDataByFieldName', {\r\n fieldName: 'catalogue',\r\n });\r\n if (res.code === 0 && res.data) {\r\n dictTables.value = res.data.map((item: any) => ({\r\n id: item.id,\r\n code: item.dic_value, // dic_value 是字典编码\r\n name: item.dic_name, // dic_name 是字典名称\r\n description: item.remark || '',\r\n disabled: item.disabled,\r\n sort: item.sort,\r\n }));\r\n }\r\n } catch (error) {\r\n console.error('加载字典表列表失败:', error);\r\n } finally {\r\n loading.value = false;\r\n }\r\n};\r\n\r\n// 获取字典项列表\r\nconst loadDictItems = async (fieldName: string) => {\r\n itemsLoading.value = true;\r\n try {\r\n const res = await datasetApi('getDictionaryDataByFieldName', {\r\n fieldName,\r\n });\r\n\r\n if (res.code === 0 && res.data) {\r\n dictItems.value = res.data.map((item: any) => ({\r\n id: item.id,\r\n dictCode: fieldName,\r\n label: item.dic_name, // dic_name 是显示标签\r\n value: item.dic_value, // dic_value 是值\r\n sort: item.sort,\r\n disabled: item.disabled,\r\n remark: item.remark,\r\n }));\r\n }\r\n } catch (error) {\r\n console.error('加载字典项失败:', error);\r\n } finally {\r\n itemsLoading.value = false;\r\n }\r\n};\r\n\r\n// 打开选择器\r\nconst openSelector = async () => {\r\n dialogVisible.value = true;\r\n dialogTitle.value = '字典表选择器';\r\n dialogMode.value = 'preview';\r\n searchKeyword.value = '';\r\n await loadDictTables();\r\n};\r\n\r\n// 选择字典表\r\nconst selectDict = (dict: any) => {\r\n selectedDict.value = dict;\r\n valueRef.value = dict.code;\r\n dialogVisible.value = false; // 关闭对话框\r\n emits('valueChange', props.detail.field, dict.code);\r\n};\r\n\r\n// 查看字典详情\r\nconst viewDict = async (dict: any) => {\r\n selectedDict.value = dict;\r\n await loadDictItems(dict.code);\r\n};\r\n\r\n// 编辑字典表\r\nconst editDictTable = (dict: any) => {\r\n dialogMode.value = 'edit';\r\n formData.value = { ...dict };\r\n};\r\n\r\n// 获取当前字典的项\r\nconst getCurrentDictItems = () => {\r\n return dictItems.value;\r\n};\r\n\r\n// 获取显示的字典名称\r\nconst getDisplayName = () => {\r\n const dict = dictTables.value.find((d) => d.code === valueRef.value);\r\n return dict ? dict.name : valueRef.value || '请选择字典';\r\n};\r\n\r\n// 过滤字典表列表\r\nconst filteredDictTables = computed(() => {\r\n if (!searchKeyword.value) {\r\n return dictTables.value;\r\n }\r\n const keyword = searchKeyword.value.toLowerCase();\r\n return dictTables.value.filter(\r\n (dict) =>\r\n dict.name.toLowerCase().includes(keyword) ||\r\n dict.code.toLowerCase().includes(keyword) ||\r\n (dict.description && dict.description.toLowerCase().includes(keyword)),\r\n );\r\n});\r\n\r\n// 初始化时加载字典表列表(如果有初始值)\r\nonMounted(() => {\r\n if (valueRef.value) {\r\n loadDictTables();\r\n }\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"dict-selector\">\r\n <el-input\r\n :model-value=\"getDisplayName()\"\r\n :placeholder=\"detail.placeholder || '请选择字典'\"\r\n readonly\r\n @click=\"openSelector\"\r\n >\r\n <template #suffix>\r\n <el-icon class=\"cursor-pointer\">\r\n <Search />\r\n </el-icon>\r\n </template>\r\n </el-input>\r\n\r\n <el-dialog\r\n v-model=\"dialogVisible\"\r\n :title=\"dialogTitle\"\r\n width=\"80%\"\r\n top=\"5vh\"\r\n destroy-on-close\r\n class=\"dict-selector-dialog\"\r\n >\r\n <div class=\"dict-selector-content\">\r\n <!-- 左侧:字典表列表 -->\r\n <div class=\"dict-list\">\r\n <div class=\"dict-list-header\">\r\n <span class=\"title\">字典表列表</span>\r\n </div>\r\n <div class=\"dict-search\">\r\n <el-input\r\n v-model=\"searchKeyword\"\r\n placeholder=\"搜索字典名称或编码\"\r\n clearable\r\n size=\"small\"\r\n >\r\n <template #prefix>\r\n <el-icon>\r\n <Search />\r\n </el-icon>\r\n </template>\r\n </el-input>\r\n </div>\r\n <div v-loading=\"loading\" class=\"dict-list-body\">\r\n <div\r\n v-for=\"dict in filteredDictTables\"\r\n :key=\"dict.id\"\r\n class=\"dict-item\"\r\n :class=\"[{ active: selectedDict?.id === dict.id }]\"\r\n @click=\"viewDict(dict)\"\r\n >\r\n <div class=\"dict-item-content\">\r\n <div class=\"dict-name\">{{ dict.name }}</div>\r\n <div class=\"dict-code\">{{ dict.code }}</div>\r\n </div>\r\n <div class=\"dict-item-actions\">\r\n <el-button\r\n link\r\n size=\"small\"\r\n type=\"primary\"\r\n @click.stop=\"selectDict(dict)\"\r\n >\r\n 选择\r\n </el-button>\r\n <el-button\r\n link\r\n size=\"small\"\r\n type=\"primary\"\r\n @click.stop=\"editDictTable(dict)\"\r\n >\r\n 编辑\r\n </el-button>\r\n </div>\r\n </div>\r\n <div v-if=\"filteredDictTables.length === 0\" class=\"empty-result\">\r\n <el-empty description=\"未找到匹配的字典\" :image-size=\"80\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 右侧:字典详情/表单 -->\r\n <div class=\"dict-detail\">\r\n <!-- 预览模式 -->\r\n <template v-if=\"dialogMode === 'preview' && selectedDict\">\r\n <div class=\"dict-detail-header\">\r\n <span class=\"title\">字典详情</span>\r\n </div>\r\n <div class=\"dict-info\">\r\n <el-descriptions :column=\"1\" border>\r\n <el-descriptions-item label=\"字典编码\">\r\n {{ selectedDict.code }}\r\n </el-descriptions-item>\r\n <el-descriptions-item label=\"字典名称\">\r\n {{ selectedDict.name }}\r\n </el-descriptions-item>\r\n <el-descriptions-item label=\"描述\">\r\n {{ selectedDict.description }}\r\n </el-descriptions-item>\r\n </el-descriptions>\r\n </div>\r\n\r\n <div class=\"dict-items\">\r\n <div class=\"dict-items-header\">\r\n <span class=\"title\">字典项</span>\r\n </div>\r\n <el-table :data=\"getCurrentDictItems()\" border stripe>\r\n <el-table-column label=\"标签\" prop=\"label\" />\r\n <el-table-column label=\"值\" prop=\"value\" />\r\n <el-table-column label=\"排序\" prop=\"sort\" width=\"80\" />\r\n </el-table>\r\n </div>\r\n </template>\r\n\r\n <!-- 未选择状态 -->\r\n <template v-else>\r\n <div class=\"empty-state\">\r\n <el-empty description=\"请选择一个字典表查看详情\" />\r\n </div>\r\n </template>\r\n </div>\r\n </div>\r\n </el-dialog>\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.dict-selector {\r\n width: 100%;\r\n\r\n :deep(.el-input__inner) {\r\n cursor: pointer;\r\n }\r\n}\r\n\r\n:deep(.dict-selector-dialog) {\r\n .el-dialog {\r\n max-height: 90vh;\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n\r\n .el-dialog__body {\r\n height: 70vh;\r\n padding: 0;\r\n overflow: hidden;\r\n flex: 1;\r\n }\r\n}\r\n\r\n.dict-selector-content {\r\n display: flex;\r\n gap: 16px;\r\n height: 100%;\r\n padding: 16px;\r\n}\r\n\r\n.dict-list {\r\n flex: 0 0 300px;\r\n display: flex;\r\n flex-direction: column;\r\n border: 1px solid var(--el-border-color);\r\n border-radius: 4px;\r\n overflow: hidden;\r\n}\r\n\r\n.dict-list-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 12px 16px;\r\n background-color: var(--el-fill-color-light);\r\n border-bottom: 1px solid var(--el-border-color);\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n.dict-search {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid var(--el-border-color-lighter);\r\n}\r\n\r\n.dict-list-body {\r\n flex: 1;\r\n overflow-y: auto;\r\n}\r\n\r\n.empty-result {\r\n padding: 20px;\r\n text-align: center;\r\n}\r\n\r\n.dict-item {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid var(--el-border-color-lighter);\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n\r\n &:hover {\r\n background-color: var(--el-fill-color-light);\r\n }\r\n\r\n &.active {\r\n background-color: var(--el-color-primary-light-9);\r\n border-left: 3px solid var(--el-color-primary);\r\n }\r\n\r\n &:last-child {\r\n border-bottom: none;\r\n }\r\n}\r\n\r\n.dict-item-content {\r\n margin-bottom: 8px;\r\n\r\n .dict-name {\r\n font-weight: 500;\r\n font-size: 14px;\r\n margin-bottom: 4px;\r\n }\r\n\r\n .dict-code {\r\n font-size: 12px;\r\n color: var(--el-text-color-secondary);\r\n }\r\n}\r\n\r\n.dict-item-actions {\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.dict-detail {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n border: 1px solid var(--el-border-color);\r\n border-radius: 4px;\r\n overflow: hidden;\r\n}\r\n\r\n.dict-detail-header {\r\n padding: 12px 16px;\r\n background-color: var(--el-fill-color-light);\r\n border-bottom: 1px solid var(--el-border-color);\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n.dict-info {\r\n padding: 16px;\r\n}\r\n\r\n.dict-items {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n padding: 16px;\r\n overflow: hidden;\r\n\r\n .dict-items-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 12px;\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n }\r\n\r\n :deep(.el-table) {\r\n flex: 1;\r\n }\r\n}\r\n\r\n.empty-state {\r\n flex: 1;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.cursor-pointer {\r\n cursor: pointer;\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport type { FormFrame } from '@/types';\r\n\r\nimport { computed, onMounted, ref } from 'vue';\r\n\r\nimport { Search } from '@element-plus/icons-vue';\r\n\r\nimport { datasetApi } from '@/api';\r\n\r\ninterface Props {\r\n value?: string;\r\n detail: FormFrame;\r\n mittId?: any;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n value: '',\r\n mittId: () => null,\r\n});\r\n\r\nconst emits = defineEmits(['update:value', 'valueChange']);\r\nconst valueRef = defineModel('value');\r\n\r\n// 对话框控制\r\nconst dialogVisible = ref(false);\r\nconst dialogTitle = ref('');\r\nconst dialogMode = ref<'add' | 'edit' | 'preview'>('preview');\r\n\r\n// 当前选中的字典\r\nconst selectedDict = ref<any>(null);\r\n\r\n// 字典表列表\r\nconst dictTables = ref<any[]>([]);\r\n\r\n// 字典项列表\r\nconst dictItems = ref<any[]>([]);\r\n\r\n// 搜索关键词\r\nconst searchKeyword = ref('');\r\n\r\n// 加载状态\r\nconst loading = ref(false);\r\nconst itemsLoading = ref(false);\r\n\r\n// 表单数据\r\nconst formData = ref<any>({});\r\n\r\n// 获取字典表列表\r\nconst loadDictTables = async () => {\r\n loading.value = true;\r\n try {\r\n const res = await datasetApi('getDictionaryDataByFieldName', {\r\n fieldName: 'catalogue',\r\n });\r\n if (res.code === 0 && res.data) {\r\n dictTables.value = res.data.map((item: any) => ({\r\n id: item.id,\r\n code: item.dic_value, // dic_value 是字典编码\r\n name: item.dic_name, // dic_name 是字典名称\r\n description: item.remark || '',\r\n disabled: item.disabled,\r\n sort: item.sort,\r\n }));\r\n }\r\n } catch (error) {\r\n console.error('加载字典表列表失败:', error);\r\n } finally {\r\n loading.value = false;\r\n }\r\n};\r\n\r\n// 获取字典项列表\r\nconst loadDictItems = async (fieldName: string) => {\r\n itemsLoading.value = true;\r\n try {\r\n const res = await datasetApi('getDictionaryDataByFieldName', {\r\n fieldName,\r\n });\r\n\r\n if (res.code === 0 && res.data) {\r\n dictItems.value = res.data.map((item: any) => ({\r\n id: item.id,\r\n dictCode: fieldName,\r\n label: item.dic_name, // dic_name 是显示标签\r\n value: item.dic_value, // dic_value 是值\r\n sort: item.sort,\r\n disabled: item.disabled,\r\n remark: item.remark,\r\n }));\r\n }\r\n } catch (error) {\r\n console.error('加载字典项失败:', error);\r\n } finally {\r\n itemsLoading.value = false;\r\n }\r\n};\r\n\r\n// 打开选择器\r\nconst openSelector = async () => {\r\n dialogVisible.value = true;\r\n dialogTitle.value = '字典表选择器';\r\n dialogMode.value = 'preview';\r\n searchKeyword.value = '';\r\n await loadDictTables();\r\n};\r\n\r\n// 选择字典表\r\nconst selectDict = (dict: any) => {\r\n selectedDict.value = dict;\r\n valueRef.value = dict.code;\r\n dialogVisible.value = false; // 关闭对话框\r\n emits('valueChange', props.detail.field, dict.code);\r\n};\r\n\r\n// 查看字典详情\r\nconst viewDict = async (dict: any) => {\r\n selectedDict.value = dict;\r\n await loadDictItems(dict.code);\r\n};\r\n\r\n// 编辑字典表\r\nconst editDictTable = (dict: any) => {\r\n dialogMode.value = 'edit';\r\n formData.value = { ...dict };\r\n};\r\n\r\n// 获取当前字典的项\r\nconst getCurrentDictItems = () => {\r\n return dictItems.value;\r\n};\r\n\r\n// 获取显示的字典名称\r\nconst getDisplayName = () => {\r\n const dict = dictTables.value.find((d) => d.code === valueRef.value);\r\n return dict ? dict.name : valueRef.value || '请选择字典';\r\n};\r\n\r\n// 过滤字典表列表\r\nconst filteredDictTables = computed(() => {\r\n if (!searchKeyword.value) {\r\n return dictTables.value;\r\n }\r\n const keyword = searchKeyword.value.toLowerCase();\r\n return dictTables.value.filter(\r\n (dict) =>\r\n dict.name.toLowerCase().includes(keyword) ||\r\n dict.code.toLowerCase().includes(keyword) ||\r\n (dict.description && dict.description.toLowerCase().includes(keyword)),\r\n );\r\n});\r\n\r\n// 初始化时加载字典表列表(如果有初始值)\r\nonMounted(() => {\r\n if (valueRef.value) {\r\n loadDictTables();\r\n }\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"dict-selector\">\r\n <el-input\r\n :model-value=\"getDisplayName()\"\r\n :placeholder=\"detail.placeholder || '请选择字典'\"\r\n readonly\r\n @click=\"openSelector\"\r\n >\r\n <template #suffix>\r\n <el-icon class=\"cursor-pointer\">\r\n <Search />\r\n </el-icon>\r\n </template>\r\n </el-input>\r\n\r\n <el-dialog\r\n v-model=\"dialogVisible\"\r\n :title=\"dialogTitle\"\r\n width=\"80%\"\r\n top=\"5vh\"\r\n destroy-on-close\r\n class=\"dict-selector-dialog\"\r\n >\r\n <div class=\"dict-selector-content\">\r\n <!-- 左侧:字典表列表 -->\r\n <div class=\"dict-list\">\r\n <div class=\"dict-list-header\">\r\n <span class=\"title\">字典表列表</span>\r\n </div>\r\n <div class=\"dict-search\">\r\n <el-input\r\n v-model=\"searchKeyword\"\r\n placeholder=\"搜索字典名称或编码\"\r\n clearable\r\n size=\"small\"\r\n >\r\n <template #prefix>\r\n <el-icon>\r\n <Search />\r\n </el-icon>\r\n </template>\r\n </el-input>\r\n </div>\r\n <div v-loading=\"loading\" class=\"dict-list-body\">\r\n <div\r\n v-for=\"dict in filteredDictTables\"\r\n :key=\"dict.id\"\r\n class=\"dict-item\"\r\n :class=\"[{ active: selectedDict?.id === dict.id }]\"\r\n @click=\"viewDict(dict)\"\r\n >\r\n <div class=\"dict-item-content\">\r\n <div class=\"dict-name\">{{ dict.name }}</div>\r\n <div class=\"dict-code\">{{ dict.code }}</div>\r\n </div>\r\n <div class=\"dict-item-actions\">\r\n <el-button\r\n link\r\n size=\"small\"\r\n type=\"primary\"\r\n @click.stop=\"selectDict(dict)\"\r\n >\r\n 选择\r\n </el-button>\r\n <el-button\r\n link\r\n size=\"small\"\r\n type=\"primary\"\r\n @click.stop=\"editDictTable(dict)\"\r\n >\r\n 编辑\r\n </el-button>\r\n </div>\r\n </div>\r\n <div v-if=\"filteredDictTables.length === 0\" class=\"empty-result\">\r\n <el-empty description=\"未找到匹配的字典\" :image-size=\"80\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 右侧:字典详情/表单 -->\r\n <div class=\"dict-detail\">\r\n <!-- 预览模式 -->\r\n <template v-if=\"dialogMode === 'preview' && selectedDict\">\r\n <div class=\"dict-detail-header\">\r\n <span class=\"title\">字典详情</span>\r\n </div>\r\n <div class=\"dict-info\">\r\n <el-descriptions :column=\"1\" border>\r\n <el-descriptions-item label=\"字典编码\">\r\n {{ selectedDict.code }}\r\n </el-descriptions-item>\r\n <el-descriptions-item label=\"字典名称\">\r\n {{ selectedDict.name }}\r\n </el-descriptions-item>\r\n <el-descriptions-item label=\"描述\">\r\n {{ selectedDict.description }}\r\n </el-descriptions-item>\r\n </el-descriptions>\r\n </div>\r\n\r\n <div class=\"dict-items\">\r\n <div class=\"dict-items-header\">\r\n <span class=\"title\">字典项</span>\r\n </div>\r\n <el-table :data=\"getCurrentDictItems()\" border stripe>\r\n <el-table-column label=\"标签\" prop=\"label\" />\r\n <el-table-column label=\"值\" prop=\"value\" />\r\n <el-table-column label=\"排序\" prop=\"sort\" width=\"80\" />\r\n </el-table>\r\n </div>\r\n </template>\r\n\r\n <!-- 未选择状态 -->\r\n <template v-else>\r\n <div class=\"empty-state\">\r\n <el-empty description=\"请选择一个字典表查看详情\" />\r\n </div>\r\n </template>\r\n </div>\r\n </div>\r\n </el-dialog>\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.dict-selector {\r\n width: 100%;\r\n\r\n :deep(.el-input__inner) {\r\n cursor: pointer;\r\n }\r\n}\r\n\r\n:deep(.dict-selector-dialog) {\r\n .el-dialog {\r\n max-height: 90vh;\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n\r\n .el-dialog__body {\r\n height: 70vh;\r\n padding: 0;\r\n overflow: hidden;\r\n flex: 1;\r\n }\r\n}\r\n\r\n.dict-selector-content {\r\n display: flex;\r\n gap: 16px;\r\n height: 100%;\r\n padding: 16px;\r\n}\r\n\r\n.dict-list {\r\n flex: 0 0 300px;\r\n display: flex;\r\n flex-direction: column;\r\n border: 1px solid var(--el-border-color);\r\n border-radius: 4px;\r\n overflow: hidden;\r\n}\r\n\r\n.dict-list-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 12px 16px;\r\n background-color: var(--el-fill-color-light);\r\n border-bottom: 1px solid var(--el-border-color);\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n.dict-search {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid var(--el-border-color-lighter);\r\n}\r\n\r\n.dict-list-body {\r\n flex: 1;\r\n overflow-y: auto;\r\n}\r\n\r\n.empty-result {\r\n padding: 20px;\r\n text-align: center;\r\n}\r\n\r\n.dict-item {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid var(--el-border-color-lighter);\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n\r\n &:hover {\r\n background-color: var(--el-fill-color-light);\r\n }\r\n\r\n &.active {\r\n background-color: var(--el-color-primary-light-9);\r\n border-left: 3px solid var(--el-color-primary);\r\n }\r\n\r\n &:last-child {\r\n border-bottom: none;\r\n }\r\n}\r\n\r\n.dict-item-content {\r\n margin-bottom: 8px;\r\n\r\n .dict-name {\r\n font-weight: 500;\r\n font-size: 14px;\r\n margin-bottom: 4px;\r\n }\r\n\r\n .dict-code {\r\n font-size: 12px;\r\n color: var(--el-text-color-secondary);\r\n }\r\n}\r\n\r\n.dict-item-actions {\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.dict-detail {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n border: 1px solid var(--el-border-color);\r\n border-radius: 4px;\r\n overflow: hidden;\r\n}\r\n\r\n.dict-detail-header {\r\n padding: 12px 16px;\r\n background-color: var(--el-fill-color-light);\r\n border-bottom: 1px solid var(--el-border-color);\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n.dict-info {\r\n padding: 16px;\r\n}\r\n\r\n.dict-items {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n padding: 16px;\r\n overflow: hidden;\r\n\r\n .dict-items-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 12px;\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n }\r\n\r\n :deep(.el-table) {\r\n flex: 1;\r\n }\r\n}\r\n\r\n.empty-state {\r\n flex: 1;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.cursor-pointer {\r\n cursor: pointer;\r\n}\r\n</style>\r\n","import FormDictSelector from './FormDictSelector.vue';\nimport type { App } from 'vue';\n\n(FormDictSelector as any).name = 'FormDictSelector';\n\nFormDictSelector.install = (app: App) => {\n app.component('FormDictSelector', FormDictSelector);\n};\n\nexport { FormDictSelector };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { computed, onMounted, ref, watch } from 'vue';\n\nimport { Icon } from '@iconify/vue';\n\nimport { getCollectionsApi, searchPageApi } from '@/api';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n}\n\ninterface IconCollection {\n prefix: string;\n name: string;\n total?: number;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: undefined,\n});\n\nconst valueRef = defineModel('value', { default: '', type: String });\n\n// 状态\nconst visible = ref(false);\nconst loading = ref(false);\nconst loadingMore = ref(false);\nconst collectionsLoading = ref(false);\nconst searchQuery = ref('');\nconst selectedPrefix = ref('all'); // 'all' 表示搜索所有图标集\nconst icons = ref<string[]>([]);\nconst collections = ref<IconCollection[]>([]);\nconst currentPage = ref(1);\nconst pageSize = ref(36);\nconst totalIcons = ref(0);\nconst hasMore = ref(true);\nconst iconGridRef = ref<HTMLElement | null>(null);\n\n// 计算属性\nconst currentIcon = computed({\n get: () => valueRef.value || '',\n set: (val) => {\n valueRef.value = val;\n },\n});\n\n// 方法\nconst getIconName = (fullIcon: string) => {\n if (fullIcon.includes(':')) {\n return fullIcon.split(':')[1];\n }\n return fullIcon;\n};\n\nconst loadCollections = async () => {\n collectionsLoading.value = true;\n try {\n // const response = await fetch(`${BASE_URL}/iconify/collections`);\n // const data = await response.json();\n\n const data = await getCollectionsApi();\n\n if (data) {\n collections.value = Object.entries(data).map(\n ([prefix, info]: [string, any]) => ({\n prefix,\n name: info.name || prefix,\n total: info.total,\n }),\n );\n\n // 如果当前有图标值,尝试从中提取 prefix\n if (currentIcon.value && currentIcon.value.includes(':')) {\n const prefix = currentIcon.value.split(':')[0];\n if (prefix && collections.value.some((c) => c.prefix === prefix)) {\n selectedPrefix.value = prefix;\n }\n }\n }\n } catch (error) {\n console.error('加载图标集失败:', error);\n collections.value = [];\n } finally {\n collectionsLoading.value = false;\n }\n};\n\nconst searchIcons = async (reset = false) => {\n if (reset) {\n currentPage.value = 1;\n icons.value = [];\n hasMore.value = true;\n }\n\n if (!hasMore.value || loading.value || loadingMore.value) return;\n\n if (currentPage.value === 1) {\n loading.value = true;\n } else {\n loadingMore.value = true;\n }\n\n try {\n const params: any = {\n query: searchQuery.value,\n page: String(currentPage.value),\n pageSize: String(pageSize.value),\n };\n\n // 只有选择了特定图标集时才传 prefix 参数\n if (selectedPrefix.value && selectedPrefix.value !== 'all') {\n params.prefix = selectedPrefix.value;\n }\n const data = await searchPageApi(params);\n\n if (data && data.icons) {\n icons.value = reset ? data.icons : [...icons.value, ...data.icons];\n totalIcons.value = data.total || 0;\n hasMore.value = data.hasMore !== false;\n currentPage.value++;\n }\n } catch (error) {\n console.error('搜索图标失败:', error);\n } finally {\n loading.value = false;\n loadingMore.value = false;\n }\n};\n\n// 检查是否需要加载更多数据来填满容器\nconst checkIfNeedLoadMore = () => {\n if (!iconGridRef.value) return;\n\n const { scrollHeight, clientHeight } = iconGridRef.value;\n\n if (\n scrollHeight <= clientHeight &&\n hasMore.value &&\n !loadingMore.value &&\n !loading.value\n ) {\n searchIcons();\n }\n};\n\n// 滚动加载更多\nconst handleScroll = (e: Event) => {\n const target = e.target as HTMLElement;\n const { scrollTop, scrollHeight, clientHeight } = target;\n\n const distanceToBottom = scrollHeight - scrollTop - clientHeight;\n\n // 距离底部 100px 时加载更多\n if (\n distanceToBottom < 100 &&\n !loadingMore.value &&\n !loading.value &&\n hasMore.value\n ) {\n searchIcons();\n }\n};\n\nconst selectIcon = (icon: string) => {\n currentIcon.value = icon;\n visible.value = false;\n};\n\nconst clearIcon = () => {\n currentIcon.value = '';\n};\n\nconst handleVisibleChange = async (show: boolean) => {\n if (show) {\n if (collections.value.length === 0) {\n await loadCollections();\n }\n if (icons.value.length === 0) {\n await searchIcons(true);\n // 加载完成后检查是否需要继续加载\n setTimeout(checkIfNeedLoadMore, 100);\n }\n }\n};\n\n// 监听搜索关键词变化 - 添加防抖\nlet searchTimer: null | ReturnType<typeof setTimeout> = null;\nwatch(searchQuery, () => {\n if (searchTimer) {\n clearTimeout(searchTimer);\n }\n searchTimer = setTimeout(() => {\n searchIcons(true);\n }, 300);\n});\n\n// 监听图标集变化\nwatch(selectedPrefix, () => {\n if (visible.value) {\n searchIcons(true);\n }\n});\n\n// 监听 value 变化,自动切换到对应的图标集\nwatch(currentIcon, (newVal) => {\n if (newVal && newVal.includes(':') && collections.value.length > 0) {\n const prefix = newVal.split(':')[0];\n if (\n prefix &&\n collections.value.some((c) => c.prefix === prefix) &&\n prefix !== selectedPrefix.value\n ) {\n selectedPrefix.value = prefix;\n }\n }\n});\n\nonMounted(() => {\n loadCollections();\n});\n</script>\n\n<template>\n <div class=\"icon-picker\">\n <el-popover\n v-model:visible=\"visible\"\n placement=\"bottom-start\"\n :width=\"600\"\n trigger=\"click\"\n :hide-after=\"0\"\n popper-class=\"icon-picker-popover\"\n @show=\"handleVisibleChange(true)\"\n >\n <template #reference>\n <el-input :model-value=\"currentIcon\" placeholder=\"选择图标\" readonly>\n <template #prefix>\n <Icon\n v-if=\"currentIcon\"\n :icon=\"currentIcon\"\n :width=\"20\"\n :height=\"20\"\n />\n <el-icon v-else>\n <component is=\"Grid\" />\n </el-icon>\n </template>\n <template #suffix>\n <el-icon\n v-if=\"currentIcon\"\n class=\"clear-icon\"\n @click.stop=\"clearIcon\"\n >\n <component is=\"CircleClose\" />\n </el-icon>\n </template>\n </el-input>\n </template>\n\n <!-- Popover 内容 -->\n <div class=\"picker-content\" @click.stop>\n <!-- 搜索和筛选 -->\n <div class=\"picker-header\">\n <el-select\n filterable\n v-model=\"selectedPrefix\"\n placeholder=\"选择图标集\"\n size=\"small\"\n style=\"width: 180px\"\n :loading=\"collectionsLoading\"\n :teleported=\"false\"\n >\n <el-option label=\"全部图标集\" value=\"all\" />\n <el-option\n v-for=\"collection in collections\"\n :key=\"collection.prefix\"\n :label=\"`${collection.name} (${collection.total || 0})`\"\n :value=\"collection.prefix\"\n />\n </el-select>\n\n <el-input\n v-model=\"searchQuery\"\n placeholder=\"搜索图标...\"\n size=\"small\"\n clearable\n style=\"flex: 1; margin-left: 8px\"\n >\n <template #prefix>\n <el-icon>\n <component is=\"Search\" />\n </el-icon>\n </template>\n </el-input>\n </div>\n\n <!-- 图标网格 -->\n <div\n ref=\"iconGridRef\"\n v-loading=\"loading && icons.length === 0\"\n class=\"icon-grid\"\n @scroll=\"handleScroll\"\n >\n <div\n v-for=\"icon in icons\"\n :key=\"icon\"\n class=\"icon-item\"\n :class=\"{ selected: currentIcon === icon }\"\n :title=\"icon\"\n @click=\"selectIcon(icon)\"\n >\n <div class=\"icon-wrapper\">\n <Icon :icon=\"icon\" :width=\"24\" :height=\"24\" />\n <span class=\"icon-name\">{{ getIconName(icon) }}</span>\n </div>\n </div>\n\n <!-- 加载更多提示 -->\n <div v-if=\"loadingMore\" class=\"loading-more\">\n <el-icon class=\"is-loading\"><component is=\"Loading\" /></el-icon>\n <span>加载更多...</span>\n </div>\n\n <div v-else-if=\"!hasMore && icons.length > 0\" class=\"no-more\">\n <el-text type=\"info\">已加载全部 {{ totalIcons }} 个图标</el-text>\n </div>\n\n <el-empty\n v-if=\"!loading && icons.length === 0\"\n description=\"未找到图标\"\n :image-size=\"60\"\n />\n </div>\n </div>\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.icon-picker {\n width: 100%;\n\n .clear-icon {\n cursor: pointer;\n &:hover {\n color: var(--el-color-primary);\n }\n }\n}\n\n.picker-content {\n padding: 8px;\n}\n\n.picker-header {\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.icon-grid {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 8px;\n max-height: 400px;\n overflow-y: auto;\n padding: 8px;\n border: 1px solid var(--el-border-color-lighter);\n border-radius: 4px;\n background: var(--el-fill-color-blank);\n position: relative;\n\n .icon-item {\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border: 1px solid transparent;\n border-radius: 4px;\n transition: all 0.2s;\n padding: 8px 4px;\n min-height: 70px;\n\n .icon-wrapper {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n width: 100%;\n\n .icon-name {\n font-size: 10px;\n color: var(--el-text-color-secondary);\n text-align: center;\n word-break: break-all;\n line-height: 1.2;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n }\n\n &:hover {\n background: var(--el-fill-color-light);\n border-color: var(--el-color-primary-light-5);\n transform: scale(1.05);\n\n .icon-name {\n color: var(--el-text-color-primary);\n }\n }\n\n &.selected {\n background: var(--el-color-primary-light-9);\n border-color: var(--el-color-primary);\n\n .icon-name {\n color: var(--el-color-primary);\n font-weight: 500;\n }\n }\n }\n\n .loading-more,\n .no-more {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 16px;\n color: var(--el-text-color-secondary);\n }\n\n // 当为空时,el-empty 需要占据整个网格区域并居中\n &:has(.el-empty) {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n}\n\n.picker-footer {\n display: flex;\n justify-content: center;\n margin-top: 8px;\n padding-top: 8px;\n}\n</style>\n\n<style lang=\"scss\">\n.icon-picker-popover {\n padding: 12px !important;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { computed, onMounted, ref, watch } from 'vue';\n\nimport { Icon } from '@iconify/vue';\n\nimport { getCollectionsApi, searchPageApi } from '@/api';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n}\n\ninterface IconCollection {\n prefix: string;\n name: string;\n total?: number;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: undefined,\n});\n\nconst valueRef = defineModel('value', { default: '', type: String });\n\n// 状态\nconst visible = ref(false);\nconst loading = ref(false);\nconst loadingMore = ref(false);\nconst collectionsLoading = ref(false);\nconst searchQuery = ref('');\nconst selectedPrefix = ref('all'); // 'all' 表示搜索所有图标集\nconst icons = ref<string[]>([]);\nconst collections = ref<IconCollection[]>([]);\nconst currentPage = ref(1);\nconst pageSize = ref(36);\nconst totalIcons = ref(0);\nconst hasMore = ref(true);\nconst iconGridRef = ref<HTMLElement | null>(null);\n\n// 计算属性\nconst currentIcon = computed({\n get: () => valueRef.value || '',\n set: (val) => {\n valueRef.value = val;\n },\n});\n\n// 方法\nconst getIconName = (fullIcon: string) => {\n if (fullIcon.includes(':')) {\n return fullIcon.split(':')[1];\n }\n return fullIcon;\n};\n\nconst loadCollections = async () => {\n collectionsLoading.value = true;\n try {\n // const response = await fetch(`${BASE_URL}/iconify/collections`);\n // const data = await response.json();\n\n const data = await getCollectionsApi();\n\n if (data) {\n collections.value = Object.entries(data).map(\n ([prefix, info]: [string, any]) => ({\n prefix,\n name: info.name || prefix,\n total: info.total,\n }),\n );\n\n // 如果当前有图标值,尝试从中提取 prefix\n if (currentIcon.value && currentIcon.value.includes(':')) {\n const prefix = currentIcon.value.split(':')[0];\n if (prefix && collections.value.some((c) => c.prefix === prefix)) {\n selectedPrefix.value = prefix;\n }\n }\n }\n } catch (error) {\n console.error('加载图标集失败:', error);\n collections.value = [];\n } finally {\n collectionsLoading.value = false;\n }\n};\n\nconst searchIcons = async (reset = false) => {\n if (reset) {\n currentPage.value = 1;\n icons.value = [];\n hasMore.value = true;\n }\n\n if (!hasMore.value || loading.value || loadingMore.value) return;\n\n if (currentPage.value === 1) {\n loading.value = true;\n } else {\n loadingMore.value = true;\n }\n\n try {\n const params: any = {\n query: searchQuery.value,\n page: String(currentPage.value),\n pageSize: String(pageSize.value),\n };\n\n // 只有选择了特定图标集时才传 prefix 参数\n if (selectedPrefix.value && selectedPrefix.value !== 'all') {\n params.prefix = selectedPrefix.value;\n }\n const data = await searchPageApi(params);\n\n if (data && data.icons) {\n icons.value = reset ? data.icons : [...icons.value, ...data.icons];\n totalIcons.value = data.total || 0;\n hasMore.value = data.hasMore !== false;\n currentPage.value++;\n }\n } catch (error) {\n console.error('搜索图标失败:', error);\n } finally {\n loading.value = false;\n loadingMore.value = false;\n }\n};\n\n// 检查是否需要加载更多数据来填满容器\nconst checkIfNeedLoadMore = () => {\n if (!iconGridRef.value) return;\n\n const { scrollHeight, clientHeight } = iconGridRef.value;\n\n if (\n scrollHeight <= clientHeight &&\n hasMore.value &&\n !loadingMore.value &&\n !loading.value\n ) {\n searchIcons();\n }\n};\n\n// 滚动加载更多\nconst handleScroll = (e: Event) => {\n const target = e.target as HTMLElement;\n const { scrollTop, scrollHeight, clientHeight } = target;\n\n const distanceToBottom = scrollHeight - scrollTop - clientHeight;\n\n // 距离底部 100px 时加载更多\n if (\n distanceToBottom < 100 &&\n !loadingMore.value &&\n !loading.value &&\n hasMore.value\n ) {\n searchIcons();\n }\n};\n\nconst selectIcon = (icon: string) => {\n currentIcon.value = icon;\n visible.value = false;\n};\n\nconst clearIcon = () => {\n currentIcon.value = '';\n};\n\nconst handleVisibleChange = async (show: boolean) => {\n if (show) {\n if (collections.value.length === 0) {\n await loadCollections();\n }\n if (icons.value.length === 0) {\n await searchIcons(true);\n // 加载完成后检查是否需要继续加载\n setTimeout(checkIfNeedLoadMore, 100);\n }\n }\n};\n\n// 监听搜索关键词变化 - 添加防抖\nlet searchTimer: null | ReturnType<typeof setTimeout> = null;\nwatch(searchQuery, () => {\n if (searchTimer) {\n clearTimeout(searchTimer);\n }\n searchTimer = setTimeout(() => {\n searchIcons(true);\n }, 300);\n});\n\n// 监听图标集变化\nwatch(selectedPrefix, () => {\n if (visible.value) {\n searchIcons(true);\n }\n});\n\n// 监听 value 变化,自动切换到对应的图标集\nwatch(currentIcon, (newVal) => {\n if (newVal && newVal.includes(':') && collections.value.length > 0) {\n const prefix = newVal.split(':')[0];\n if (\n prefix &&\n collections.value.some((c) => c.prefix === prefix) &&\n prefix !== selectedPrefix.value\n ) {\n selectedPrefix.value = prefix;\n }\n }\n});\n\nonMounted(() => {\n loadCollections();\n});\n</script>\n\n<template>\n <div class=\"icon-picker\">\n <el-popover\n v-model:visible=\"visible\"\n placement=\"bottom-start\"\n :width=\"600\"\n trigger=\"click\"\n :hide-after=\"0\"\n popper-class=\"icon-picker-popover\"\n @show=\"handleVisibleChange(true)\"\n >\n <template #reference>\n <el-input :model-value=\"currentIcon\" placeholder=\"选择图标\" readonly>\n <template #prefix>\n <Icon\n v-if=\"currentIcon\"\n :icon=\"currentIcon\"\n :width=\"20\"\n :height=\"20\"\n />\n <el-icon v-else>\n <component is=\"Grid\" />\n </el-icon>\n </template>\n <template #suffix>\n <el-icon\n v-if=\"currentIcon\"\n class=\"clear-icon\"\n @click.stop=\"clearIcon\"\n >\n <component is=\"CircleClose\" />\n </el-icon>\n </template>\n </el-input>\n </template>\n\n <!-- Popover 内容 -->\n <div class=\"picker-content\" @click.stop>\n <!-- 搜索和筛选 -->\n <div class=\"picker-header\">\n <el-select\n filterable\n v-model=\"selectedPrefix\"\n placeholder=\"选择图标集\"\n size=\"small\"\n style=\"width: 180px\"\n :loading=\"collectionsLoading\"\n :teleported=\"false\"\n >\n <el-option label=\"全部图标集\" value=\"all\" />\n <el-option\n v-for=\"collection in collections\"\n :key=\"collection.prefix\"\n :label=\"`${collection.name} (${collection.total || 0})`\"\n :value=\"collection.prefix\"\n />\n </el-select>\n\n <el-input\n v-model=\"searchQuery\"\n placeholder=\"搜索图标...\"\n size=\"small\"\n clearable\n style=\"flex: 1; margin-left: 8px\"\n >\n <template #prefix>\n <el-icon>\n <component is=\"Search\" />\n </el-icon>\n </template>\n </el-input>\n </div>\n\n <!-- 图标网格 -->\n <div\n ref=\"iconGridRef\"\n v-loading=\"loading && icons.length === 0\"\n class=\"icon-grid\"\n @scroll=\"handleScroll\"\n >\n <div\n v-for=\"icon in icons\"\n :key=\"icon\"\n class=\"icon-item\"\n :class=\"{ selected: currentIcon === icon }\"\n :title=\"icon\"\n @click=\"selectIcon(icon)\"\n >\n <div class=\"icon-wrapper\">\n <Icon :icon=\"icon\" :width=\"24\" :height=\"24\" />\n <span class=\"icon-name\">{{ getIconName(icon) }}</span>\n </div>\n </div>\n\n <!-- 加载更多提示 -->\n <div v-if=\"loadingMore\" class=\"loading-more\">\n <el-icon class=\"is-loading\"><component is=\"Loading\" /></el-icon>\n <span>加载更多...</span>\n </div>\n\n <div v-else-if=\"!hasMore && icons.length > 0\" class=\"no-more\">\n <el-text type=\"info\">已加载全部 {{ totalIcons }} 个图标</el-text>\n </div>\n\n <el-empty\n v-if=\"!loading && icons.length === 0\"\n description=\"未找到图标\"\n :image-size=\"60\"\n />\n </div>\n </div>\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.icon-picker {\n width: 100%;\n\n .clear-icon {\n cursor: pointer;\n &:hover {\n color: var(--el-color-primary);\n }\n }\n}\n\n.picker-content {\n padding: 8px;\n}\n\n.picker-header {\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.icon-grid {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 8px;\n max-height: 400px;\n overflow-y: auto;\n padding: 8px;\n border: 1px solid var(--el-border-color-lighter);\n border-radius: 4px;\n background: var(--el-fill-color-blank);\n position: relative;\n\n .icon-item {\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border: 1px solid transparent;\n border-radius: 4px;\n transition: all 0.2s;\n padding: 8px 4px;\n min-height: 70px;\n\n .icon-wrapper {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n width: 100%;\n\n .icon-name {\n font-size: 10px;\n color: var(--el-text-color-secondary);\n text-align: center;\n word-break: break-all;\n line-height: 1.2;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n }\n\n &:hover {\n background: var(--el-fill-color-light);\n border-color: var(--el-color-primary-light-5);\n transform: scale(1.05);\n\n .icon-name {\n color: var(--el-text-color-primary);\n }\n }\n\n &.selected {\n background: var(--el-color-primary-light-9);\n border-color: var(--el-color-primary);\n\n .icon-name {\n color: var(--el-color-primary);\n font-weight: 500;\n }\n }\n }\n\n .loading-more,\n .no-more {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 16px;\n color: var(--el-text-color-secondary);\n }\n\n // 当为空时,el-empty 需要占据整个网格区域并居中\n &:has(.el-empty) {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n}\n\n.picker-footer {\n display: flex;\n justify-content: center;\n margin-top: 8px;\n padding-top: 8px;\n}\n</style>\n\n<style lang=\"scss\">\n.icon-picker-popover {\n padding: 12px !important;\n}\n</style>\n","import FormIconPicker from './FormIconPicker.vue';\nimport type { App } from 'vue';\n\n(FormIconPicker as any).name = 'FormIconPicker';\n\nFormIconPicker.install = (app: App) => {\n app.component('FormIconPicker', FormIconPicker);\n};\n\nexport { FormIconPicker };\n","<script setup lang=\"ts\">\r\nimport type { FormUploadProp } from '@/types';\r\nimport type { UploadFile, UploadRawFile } from 'element-plus';\r\n\r\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue';\r\n\r\nimport { Plus } from '@element-plus/icons-vue';\r\n\r\nimport { msgTips } from '@/utils';\r\n\r\nimport { useMittHook } from '../hooks/useMitt.hook';\r\n\r\ninterface Props {\r\n value?: string[];\r\n detail: FormUploadProp;\r\n mittId?: any;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n value: () => [],\r\n mittId: () => null,\r\n});\r\n\r\nconst emits = defineEmits([\r\n 'update:value',\r\n 'getComponentValue',\r\n 'valueChange',\r\n 'setShow',\r\n]);\r\n\r\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\r\nconst valueRef = defineModel<string[]>('value', { default: () => [] });\r\n\r\n/** 文件列表 */\r\nconst fileList = ref<UploadFile[]>([]);\r\n\r\n/** 图片预览 */\r\nconst previewVisible = ref(false);\r\nconst previewIndex = ref(0);\r\n\r\n/** 是否禁用 */\r\nconst isDisabled = computed(() => props.detail?.disabled ?? false);\r\n\r\n/** accept 属性,用于限制文件选择对话框的文件类型 */\r\nconst acceptTypes = computed(() => {\r\n if (props.detail?.fileType && props.detail.fileType.length > 0) {\r\n return props.detail.fileType.join(',');\r\n }\r\n return 'image/*';\r\n});\r\n\r\n/** 预览 URL 列表 */\r\nconst previewUrlList = computed(() => {\r\n return fileList.value\r\n .map((f) => f.url || '')\r\n .filter((url) => url.length > 0);\r\n});\r\n\r\n/** 将 URL 字符串数组转换为 UploadFile 数组 */\r\nconst urlsToFileList = (urls: string[]): UploadFile[] => {\r\n return urls\r\n .filter((url) => !!url)\r\n .map((url, index) => ({\r\n name: url.split('/').pop() || `image-${index}`,\r\n url,\r\n uid: Date.now() + index,\r\n status: 'success' as const,\r\n }));\r\n};\r\n\r\n/** 初始化:从 value 同步到 fileList */\r\nconst initFileList = () => {\r\n if (valueRef.value && valueRef.value.length > 0) {\r\n fileList.value = urlsToFileList(valueRef.value);\r\n }\r\n};\r\n\r\n/**\r\n * 从 fileList 同步到 value\r\n * 仅当数量发生变化时更新,避免与外部 watch 形成循环\r\n */\r\nconst syncValue = () => {\r\n const urls = fileList.value\r\n .filter((f) => f.status === 'success' || f.status === undefined)\r\n .map((f) => f.url || '')\r\n .filter((url) => url.length > 0);\r\n\r\n if (urls.length !== (valueRef.value?.length ?? 0)) {\r\n valueRef.value = urls;\r\n }\r\n};\r\n\r\n/** 文件上传前的校验 */\r\nconst beforeUpload = (rawFile: UploadRawFile): boolean => {\r\n // 校验文件类型\r\n if (props.detail?.fileType && props.detail.fileType.length > 0) {\r\n const isAllowed = props.detail.fileType.some((type) => {\r\n const ext = type.toLowerCase().replace('.', '');\r\n const fileName = rawFile.name.toLowerCase();\r\n const mimeType = rawFile.type.toLowerCase();\r\n return (\r\n fileName.endsWith(`.${ext}`) ||\r\n mimeType === type ||\r\n mimeType === `image/${ext}`\r\n );\r\n });\r\n\r\n if (!isAllowed) {\r\n const allowed = props.detail.fileType.join('、');\r\n msgTips.tips({ msg: `只能上传 ${allowed} 格式的文件`, type: 'warning' });\r\n return false;\r\n }\r\n }\r\n\r\n // 校验文件大小(通过 componentParams.maxSize 传入,单位 KB)\r\n if (props.detail?.componentParams?.maxSize) {\r\n const maxSize = props.detail.componentParams.maxSize * 1024;\r\n if (rawFile.size > maxSize) {\r\n msgTips.tips({\r\n msg: `文件大小不能超过 ${props.detail.componentParams.maxSize}KB`,\r\n type: 'warning',\r\n });\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n};\r\n\r\n/** 超出最大上传数量 */\r\nconst handleExceed = () => {\r\n msgTips.tips({ msg: `最多只能上传 ${props.detail.maxNumber} 张图片`, type: 'warning' });\r\n};\r\n\r\n/** 文件状态发生变化 */\r\nconst handleChange = () => {\r\n syncValue();\r\n};\r\n\r\n/** 移除文件 */\r\nconst handleRemove = () => {\r\n syncValue();\r\n};\r\n\r\n/** 上传成功回调 */\r\nconst handleSuccess = (response: any, uploadFile: UploadFile) => {\r\n // 尝试从响应中提取图片 URL\r\n let url = '';\r\n if (typeof response === 'string') {\r\n url = response;\r\n } else if (response?.data) {\r\n url = typeof response.data === 'string' ? response.data : response.data.url || '';\r\n } else if (response?.url) {\r\n url = response.url;\r\n }\r\n\r\n if (url) {\r\n uploadFile.url = url;\r\n }\r\n\r\n syncValue();\r\n};\r\n\r\n/** 上传失败回调 */\r\nconst handleError = () => {\r\n msgTips.tips({ msg: '图片上传失败', type: 'error' });\r\n syncValue();\r\n};\r\n\r\n/** 预览图片 */\r\nconst handlePreview = (uploadFile: UploadFile) => {\r\n const index = fileList.value.findIndex((f) => f.uid === uploadFile.uid);\r\n previewIndex.value = index >= 0 ? index : 0;\r\n previewVisible.value = true;\r\n};\r\n\r\n/** 设置值(mitt 广播回调使用) */\r\nconst setValue = (value: string[]) => {\r\n valueRef.value = value;\r\n fileList.value = urlsToFileList(value);\r\n};\r\n\r\n/** 接收广播消息 */\r\nconst receiveBroadcasts = (eventData: any) => {\r\n if (props.detail.noticeReceive) {\r\n props.detail.noticeReceive(eventData, setValue);\r\n }\r\n};\r\n\r\n/** 监听外部 value 变化(如表单重置) */\r\nwatch(\r\n () => valueRef.value,\r\n (newVal) => {\r\n if (!newVal || newVal.length === 0) {\r\n fileList.value = [];\r\n }\r\n },\r\n);\r\n\r\nonMounted(() => {\r\n registerMitt(receiveBroadcasts);\r\n initFileList();\r\n});\r\n\r\nonUnmounted(() => {\r\n offMitt();\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"form-image-upload\">\r\n <el-upload\r\n v-model:file-list=\"fileList\"\r\n :action=\"props.detail.uploadUrl\"\r\n :accept=\"acceptTypes\"\r\n list-type=\"picture-card\"\r\n :limit=\"props.detail.maxNumber\"\r\n :disabled=\"isDisabled\"\r\n :before-upload=\"beforeUpload\"\r\n :on-exceed=\"handleExceed\"\r\n :on-change=\"handleChange\"\r\n :on-remove=\"handleRemove\"\r\n :on-success=\"handleSuccess\"\r\n :on-error=\"handleError\"\r\n :on-preview=\"handlePreview\"\r\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\r\n >\r\n <el-icon><Plus /></el-icon>\r\n </el-upload>\r\n\r\n <el-image-viewer\r\n v-if=\"previewVisible\"\r\n :initial-index=\"previewIndex\"\r\n :url-list=\"previewUrlList\"\r\n @close=\"previewVisible = false\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.form-image-upload {\r\n :deep(.el-upload--picture-card) {\r\n width: 100px;\r\n height: 100px;\r\n }\r\n\r\n :deep(.el-upload-list--picture-card .el-upload-list__item) {\r\n width: 100px;\r\n height: 100px;\r\n }\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport type { FormUploadProp } from '@/types';\r\nimport type { UploadFile, UploadRawFile } from 'element-plus';\r\n\r\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue';\r\n\r\nimport { Plus } from '@element-plus/icons-vue';\r\n\r\nimport { msgTips } from '@/utils';\r\n\r\nimport { useMittHook } from '../hooks/useMitt.hook';\r\n\r\ninterface Props {\r\n value?: string[];\r\n detail: FormUploadProp;\r\n mittId?: any;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n value: () => [],\r\n mittId: () => null,\r\n});\r\n\r\nconst emits = defineEmits([\r\n 'update:value',\r\n 'getComponentValue',\r\n 'valueChange',\r\n 'setShow',\r\n]);\r\n\r\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\r\nconst valueRef = defineModel<string[]>('value', { default: () => [] });\r\n\r\n/** 文件列表 */\r\nconst fileList = ref<UploadFile[]>([]);\r\n\r\n/** 图片预览 */\r\nconst previewVisible = ref(false);\r\nconst previewIndex = ref(0);\r\n\r\n/** 是否禁用 */\r\nconst isDisabled = computed(() => props.detail?.disabled ?? false);\r\n\r\n/** accept 属性,用于限制文件选择对话框的文件类型 */\r\nconst acceptTypes = computed(() => {\r\n if (props.detail?.fileType && props.detail.fileType.length > 0) {\r\n return props.detail.fileType.join(',');\r\n }\r\n return 'image/*';\r\n});\r\n\r\n/** 预览 URL 列表 */\r\nconst previewUrlList = computed(() => {\r\n return fileList.value\r\n .map((f) => f.url || '')\r\n .filter((url) => url.length > 0);\r\n});\r\n\r\n/** 将 URL 字符串数组转换为 UploadFile 数组 */\r\nconst urlsToFileList = (urls: string[]): UploadFile[] => {\r\n return urls\r\n .filter((url) => !!url)\r\n .map((url, index) => ({\r\n name: url.split('/').pop() || `image-${index}`,\r\n url,\r\n uid: Date.now() + index,\r\n status: 'success' as const,\r\n }));\r\n};\r\n\r\n/** 初始化:从 value 同步到 fileList */\r\nconst initFileList = () => {\r\n if (valueRef.value && valueRef.value.length > 0) {\r\n fileList.value = urlsToFileList(valueRef.value);\r\n }\r\n};\r\n\r\n/**\r\n * 从 fileList 同步到 value\r\n * 仅当数量发生变化时更新,避免与外部 watch 形成循环\r\n */\r\nconst syncValue = () => {\r\n const urls = fileList.value\r\n .filter((f) => f.status === 'success' || f.status === undefined)\r\n .map((f) => f.url || '')\r\n .filter((url) => url.length > 0);\r\n\r\n if (urls.length !== (valueRef.value?.length ?? 0)) {\r\n valueRef.value = urls;\r\n }\r\n};\r\n\r\n/** 文件上传前的校验 */\r\nconst beforeUpload = (rawFile: UploadRawFile): boolean => {\r\n // 校验文件类型\r\n if (props.detail?.fileType && props.detail.fileType.length > 0) {\r\n const isAllowed = props.detail.fileType.some((type) => {\r\n const ext = type.toLowerCase().replace('.', '');\r\n const fileName = rawFile.name.toLowerCase();\r\n const mimeType = rawFile.type.toLowerCase();\r\n return (\r\n fileName.endsWith(`.${ext}`) ||\r\n mimeType === type ||\r\n mimeType === `image/${ext}`\r\n );\r\n });\r\n\r\n if (!isAllowed) {\r\n const allowed = props.detail.fileType.join('、');\r\n msgTips.tips({ msg: `只能上传 ${allowed} 格式的文件`, type: 'warning' });\r\n return false;\r\n }\r\n }\r\n\r\n // 校验文件大小(通过 componentParams.maxSize 传入,单位 KB)\r\n if (props.detail?.componentParams?.maxSize) {\r\n const maxSize = props.detail.componentParams.maxSize * 1024;\r\n if (rawFile.size > maxSize) {\r\n msgTips.tips({\r\n msg: `文件大小不能超过 ${props.detail.componentParams.maxSize}KB`,\r\n type: 'warning',\r\n });\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n};\r\n\r\n/** 超出最大上传数量 */\r\nconst handleExceed = () => {\r\n msgTips.tips({ msg: `最多只能上传 ${props.detail.maxNumber} 张图片`, type: 'warning' });\r\n};\r\n\r\n/** 文件状态发生变化 */\r\nconst handleChange = () => {\r\n syncValue();\r\n};\r\n\r\n/** 移除文件 */\r\nconst handleRemove = () => {\r\n syncValue();\r\n};\r\n\r\n/** 上传成功回调 */\r\nconst handleSuccess = (response: any, uploadFile: UploadFile) => {\r\n // 尝试从响应中提取图片 URL\r\n let url = '';\r\n if (typeof response === 'string') {\r\n url = response;\r\n } else if (response?.data) {\r\n url = typeof response.data === 'string' ? response.data : response.data.url || '';\r\n } else if (response?.url) {\r\n url = response.url;\r\n }\r\n\r\n if (url) {\r\n uploadFile.url = url;\r\n }\r\n\r\n syncValue();\r\n};\r\n\r\n/** 上传失败回调 */\r\nconst handleError = () => {\r\n msgTips.tips({ msg: '图片上传失败', type: 'error' });\r\n syncValue();\r\n};\r\n\r\n/** 预览图片 */\r\nconst handlePreview = (uploadFile: UploadFile) => {\r\n const index = fileList.value.findIndex((f) => f.uid === uploadFile.uid);\r\n previewIndex.value = index >= 0 ? index : 0;\r\n previewVisible.value = true;\r\n};\r\n\r\n/** 设置值(mitt 广播回调使用) */\r\nconst setValue = (value: string[]) => {\r\n valueRef.value = value;\r\n fileList.value = urlsToFileList(value);\r\n};\r\n\r\n/** 接收广播消息 */\r\nconst receiveBroadcasts = (eventData: any) => {\r\n if (props.detail.noticeReceive) {\r\n props.detail.noticeReceive(eventData, setValue);\r\n }\r\n};\r\n\r\n/** 监听外部 value 变化(如表单重置) */\r\nwatch(\r\n () => valueRef.value,\r\n (newVal) => {\r\n if (!newVal || newVal.length === 0) {\r\n fileList.value = [];\r\n }\r\n },\r\n);\r\n\r\nonMounted(() => {\r\n registerMitt(receiveBroadcasts);\r\n initFileList();\r\n});\r\n\r\nonUnmounted(() => {\r\n offMitt();\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"form-image-upload\">\r\n <el-upload\r\n v-model:file-list=\"fileList\"\r\n :action=\"props.detail.uploadUrl\"\r\n :accept=\"acceptTypes\"\r\n list-type=\"picture-card\"\r\n :limit=\"props.detail.maxNumber\"\r\n :disabled=\"isDisabled\"\r\n :before-upload=\"beforeUpload\"\r\n :on-exceed=\"handleExceed\"\r\n :on-change=\"handleChange\"\r\n :on-remove=\"handleRemove\"\r\n :on-success=\"handleSuccess\"\r\n :on-error=\"handleError\"\r\n :on-preview=\"handlePreview\"\r\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\r\n >\r\n <el-icon><Plus /></el-icon>\r\n </el-upload>\r\n\r\n <el-image-viewer\r\n v-if=\"previewVisible\"\r\n :initial-index=\"previewIndex\"\r\n :url-list=\"previewUrlList\"\r\n @close=\"previewVisible = false\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.form-image-upload {\r\n :deep(.el-upload--picture-card) {\r\n width: 100px;\r\n height: 100px;\r\n }\r\n\r\n :deep(.el-upload-list--picture-card .el-upload-list__item) {\r\n width: 100px;\r\n height: 100px;\r\n }\r\n}\r\n</style>\r\n","import FormImageUpload from './FormImageUpload.vue';\nimport type { App } from 'vue';\n\n(FormImageUpload as any).name = 'FormImageUpload';\n\nFormImageUpload.install = (app: App) => {\n app.component('FormImageUpload', FormImageUpload);\n};\n\nexport { FormImageUpload };\n","import * as monaco from 'monaco-editor';\n\nlet initialized = false;\nlet disposable: monaco.IDisposable | null = null;\n\nexport async function initVueLanguageSupport() {\n if (initialized) return;\n initialized = true;\n\n try {\n // 检查是否已注册\n const languages = monaco.languages.getLanguages();\n const vueRegistered = languages.some(l => l.id === 'vue');\n \n if (!vueRegistered) {\n monaco.languages.register({ id: 'vue', extensions: ['.vue'] });\n }\n\n monaco.languages.setLanguageConfiguration('vue', {\n comments: { blockComment: ['<!--', '-->'] },\n brackets: [['{', '}'], ['(', ')'], ['[', ']']],\n autoClosingPairs: [\n { open: '{', close: '}' }, { open: '[', close: ']' }, { open: '(', close: ')' },\n { open: '\"', close: '\"' }, { open: \"'\", close: \"'\" }, { open: '`', close: '`' },\n ],\n });\n\n monaco.languages.setMonarchTokensProvider('vue', createVueLanguage());\n \n // 先销毁旧的,再注册新的\n if (disposable) {\n disposable.dispose();\n }\n disposable = registerVueCompletion();\n \n defineVueThemes();\n } catch (e) {\n console.error('[Vue] init failed:', e);\n }\n}\n\nfunction defineVueThemes() {\n monaco.editor.defineTheme('vue-dark', {\n base: 'vs-dark',\n inherit: true,\n rules: [\n { token: 'tag', foreground: '569CD6', fontStyle: 'bold' },\n { token: 'attribute.name', foreground: '9CDCFE' },\n { token: 'attribute.value', foreground: 'CE9178' },\n { token: 'metatag', foreground: 'C586C0' },\n { token: 'delimiter.html', foreground: '808080' },\n { token: 'delimiter.bracket', foreground: 'FFD700' },\n { token: 'keyword', foreground: '569CD6' },\n { token: 'keyword.control', foreground: 'C586C0' },\n { token: 'string', foreground: 'CE9178' },\n { token: 'number', foreground: 'B5CEA8' },\n { token: 'comment', foreground: '6A9955' },\n { token: 'type', foreground: '4EC9B0' },\n { token: 'identifier', foreground: '9CDCFE' },\n { token: 'variable', foreground: '9CDCFE' },\n { token: 'function', foreground: 'DCDCAA' }, // 黄色 - 函数\n ],\n colors: {},\n });\n\n monaco.editor.defineTheme('vue-light', {\n base: 'vs',\n inherit: true,\n rules: [\n { token: 'tag', foreground: '800000', fontStyle: 'bold' },\n { token: 'attribute.name', foreground: 'E50000' },\n { token: 'attribute.value', foreground: '0000FF' },\n { token: 'metatag', foreground: 'AF00DB' },\n { token: 'delimiter.html', foreground: '800000' },\n { token: 'delimiter.bracket', foreground: 'AF00DB' },\n { token: 'keyword', foreground: '0000FF' },\n { token: 'keyword.control', foreground: 'AF00DB' },\n { token: 'string', foreground: 'A31515' },\n { token: 'number', foreground: '098658' },\n { token: 'comment', foreground: '008000' },\n { token: 'type', foreground: '267F99' },\n { token: 'identifier', foreground: '001080' },\n { token: 'variable', foreground: '001080' },\n { token: 'function', foreground: '795E26' }, // 棕黄色 - 函数\n ],\n colors: {},\n });\n}\n\n\nfunction createVueLanguage(): monaco.languages.IMonarchLanguage {\n return {\n defaultToken: '',\n ignoreCase: false,\n\n // 关键字定义\n keywords: ['import', 'export', 'from', 'default', 'const', 'let', 'var', 'function', 'class', 'extends', 'new', 'this', 'async', 'await', 'typeof', 'instanceof', 'interface', 'type', 'as'],\n controlKeywords: ['if', 'else', 'for', 'while', 'switch', 'case', 'break', 'continue', 'return', 'throw', 'try', 'catch', 'finally'],\n constants: ['true', 'false', 'null', 'undefined'],\n vueApis: [\n // 响应式核心\n 'ref', 'reactive', 'readonly', 'computed', 'shallowRef', 'shallowReactive', 'shallowReadonly',\n // 响应式工具\n 'toRef', 'toRefs', 'toValue', 'toRaw', 'unref', 'isRef', 'isReactive', 'isReadonly', 'isProxy',\n 'markRaw', 'triggerRef', 'customRef', 'effectScope', 'getCurrentScope', 'onScopeDispose',\n // 侦听器\n 'watch', 'watchEffect', 'watchPostEffect', 'watchSyncEffect',\n // 生命周期\n 'onMounted', 'onUpdated', 'onUnmounted', 'onBeforeMount', 'onBeforeUpdate', 'onBeforeUnmount',\n 'onActivated', 'onDeactivated', 'onErrorCaptured', 'onRenderTracked', 'onRenderTriggered', 'onServerPrefetch',\n // 依赖注入\n 'provide', 'inject', 'hasInjectionContext',\n // 组件定义\n 'defineProps', 'defineEmits', 'defineExpose', 'defineOptions', 'defineModel', 'defineSlots', 'withDefaults',\n // 其他\n 'nextTick', 'useSlots', 'useAttrs', 'useCssModule', 'useCssVars', 'useId', 'useModel', 'useTemplateRef',\n 'getCurrentInstance', 'h', 'createApp', 'defineComponent', 'defineAsyncComponent', 'resolveComponent',\n ],\n typeKeywords: ['any', 'boolean', 'number', 'string', 'void', 'never', 'Array', 'Object', 'Ref', 'PropType'],\n\n tokenizer: {\n // 根状态\n root: [\n [/<!--/, 'comment', '@comment'],\n [/(<)(script)/, ['delimiter.html', { token: 'tag', next: '@script' }]],\n [/(<)(style)/, ['delimiter.html', { token: 'tag', next: '@style' }]],\n [/(<)(template)/, ['delimiter.html', { token: 'tag', next: '@templateTag' }]],\n { include: '@templateContent' },\n ],\n\n comment: [[/-->/, 'comment', '@pop'], [/./, 'comment']],\n\n // script 标签\n script: [\n [/\\s+/, ''],\n [/setup/, 'metatag'],\n [/lang/, 'attribute.name'],\n [/=/, 'delimiter'],\n [/\"[^\"]*\"|'[^']*'/, 'attribute.value'],\n [/>/, { token: 'delimiter.html', next: '@scriptBody' }],\n ],\n scriptBody: [\n [/(<\\/)(script)\\s*(>)/, ['delimiter.html', 'tag', { token: 'delimiter.html', next: '@popall' }]],\n { include: '@jsCode' },\n ],\n\n // style 标签\n style: [\n [/\\s+/, ''],\n [/scoped|module/, 'metatag'],\n [/lang/, 'attribute.name'],\n [/=/, 'delimiter'],\n [/\"[^\"]*\"|'[^']*'/, 'attribute.value'],\n [/>/, { token: 'delimiter.html', next: '@styleBody' }],\n ],\n styleBody: [\n [/(<\\/)(style)\\s*(>)/, ['delimiter.html', 'tag', { token: 'delimiter.html', next: '@popall' }]],\n [/[^<]+/, ''],\n ],\n\n // template 标签属性\n templateTag: [\n [/\\s+/, ''],\n [/lang/, 'attribute.name'],\n [/=/, 'delimiter'],\n [/\"[^\"]*\"|'[^']*'/, 'attribute.value'],\n [/>/, { token: 'delimiter.html', next: '@templateBody' }],\n ],\n templateBody: [\n [/(<\\/)(template)\\s*(>)/, ['delimiter.html', 'tag', { token: 'delimiter.html', next: '@popall' }]],\n { include: '@templateContent' },\n ],\n\n // template 内容(HTML + Vue)\n templateContent: [\n [/<!--/, 'comment', '@comment'],\n // 开始标签\n [/<[\\w-]+/, { token: 'tag', next: '@tag' }],\n // 结束标签\n [/<\\/[\\w-]+\\s*>/, 'tag'],\n // 插值\n [/\\{\\{/, { token: 'delimiter.bracket', next: '@interpolation' }],\n // 文本\n [/[^<{]+/, ''],\n ],\n\n // HTML 标签属性\n tag: [\n [/\\s+/, ''],\n // Vue 指令(紫色)- v-bind:xxx, v-on:xxx 等\n [/(v-[\\w]+)(:)([\\w.-]+)/, ['metatag', 'delimiter', 'metatag']],\n [/v-[\\w-]+/, 'metatag'],\n // @ 事件简写(紫色)\n [/(@)([\\w.-]+)/, ['metatag', 'metatag']],\n // : 绑定简写(紫色)\n [/(:)([\\w.-]+)/, ['metatag', 'metatag']],\n // # 插槽简写(紫色)\n [/(#)([\\w.-]+)/, ['metatag', 'metatag']],\n // 普通属性\n [/[\\w-]+(?=\\s*=)/, 'attribute.name'],\n [/[\\w-]+/, 'attribute.name'],\n [/=/, 'delimiter'],\n // 属性值 - 绑定属性使用 JS 表达式高亮\n [/\"/, { token: 'string', next: '@attrValueDQ' }],\n [/'/, { token: 'string', next: '@attrValueSQ' }],\n // 标签结束\n [/\\/?>/, { token: 'delimiter.html', next: '@pop' }],\n ],\n\n // 双引号属性值(包含 JS 表达式)\n attrValueDQ: [\n [/\\{\\{/, { token: 'delimiter.bracket', next: '@interpolation' }],\n // JS 表达式内容\n [/[a-zA-Z_$][\\w$]*/, {\n cases: {\n '@controlKeywords': 'keyword.control',\n '@constants': 'keyword',\n '@vueApis': 'function',\n '@keywords': 'keyword',\n '@default': 'variable',\n },\n }],\n [/\\d+(\\.\\d+)?/, 'number'],\n [/[=!<>?:&|+\\-*/]+/, 'delimiter'],\n [/[()[\\].,]/, 'delimiter'],\n [/'[^']*'/, 'string'],\n [/\"/, { token: 'string', next: '@pop' }],\n [/[^\"]+/, 'variable'],\n ],\n // 单引号属性值\n attrValueSQ: [\n [/\\{\\{/, { token: 'delimiter.bracket', next: '@interpolation' }],\n [/[a-zA-Z_$][\\w$]*/, {\n cases: {\n '@controlKeywords': 'keyword.control',\n '@constants': 'keyword',\n '@vueApis': 'function',\n '@keywords': 'keyword',\n '@default': 'variable',\n },\n }],\n [/\\d+(\\.\\d+)?/, 'number'],\n [/[=!<>?:&|+\\-*/]+/, 'delimiter'],\n [/[()[\\].,]/, 'delimiter'],\n [/\"[^\"]*\"/, 'string'],\n [/'/, { token: 'string', next: '@pop' }],\n [/[^']+/, 'variable'],\n ],\n\n // 插值表达式\n interpolation: [\n [/\\}\\}/, { token: 'delimiter.bracket', next: '@pop' }],\n { include: '@jsExpr' },\n ],\n\n // JS 表达式(简化版)\n jsExpr: [\n [/\\s+/, ''],\n [/'[^']*'|\"[^\"]*\"/, 'string'],\n [/\\d+(\\.\\d+)?/, 'number'],\n [/[a-zA-Z_$][\\w$]*/, {\n cases: {\n '@controlKeywords': 'keyword.control',\n '@constants': 'keyword',\n '@vueApis': 'function',\n '@keywords': 'keyword',\n '@default': 'identifier',\n },\n }],\n [/[=!<>?:&|+\\-*/]+/, 'delimiter'],\n [/[{}()[\\].,;]/, 'delimiter'],\n ],\n\n // JS 完整代码\n jsCode: [\n [/\\s+/, ''],\n [/\\/\\/.*$/, 'comment'],\n [/\\/\\*/, 'comment', '@jsComment'],\n [/'([^'\\\\]|\\\\.)*'/, 'string'],\n [/\"([^\"\\\\]|\\\\.)*\"/, 'string'],\n [/`/, 'string', '@templateStr'],\n [/\\d+(\\.\\d+)?/, 'number'],\n [/[a-zA-Z_$][\\w$]*/, {\n cases: {\n '@controlKeywords': 'keyword.control',\n '@constants': 'keyword',\n '@vueApis': 'function',\n '@keywords': 'keyword',\n '@typeKeywords': 'type',\n '@default': 'identifier',\n },\n }],\n [/[=!<>?:&|+\\-*/]+/, 'delimiter'],\n [/[{}()[\\].,;]/, 'delimiter'],\n ],\n jsComment: [[/\\*\\//, 'comment', '@pop'], [/./, 'comment']],\n templateStr: [\n [/\\$\\{/, { token: 'delimiter', next: '@templateExpr' }],\n [/`/, 'string', '@pop'],\n [/./, 'string'],\n ],\n templateExpr: [[/\\}/, { token: 'delimiter', next: '@pop' }], { include: '@jsExpr' }],\n },\n };\n}\n\n\nfunction registerVueCompletion(): monaco.IDisposable {\n return monaco.languages.registerCompletionItemProvider('vue', {\n triggerCharacters: ['<', '.', '@', ':', '-', 'v'],\n provideCompletionItems: (model, position) => {\n const word = model.getWordUntilPosition(position);\n const line = model.getLineContent(position.lineNumber);\n const before = line.substring(0, position.column - 1);\n const suggestions: monaco.languages.CompletionItem[] = [];\n \n // 判断是否在 script 区域内\n const fullText = model.getValue();\n const offset = model.getOffsetAt(position);\n const textBefore = fullText.substring(0, offset);\n const scriptStart = textBefore.lastIndexOf('<script');\n const scriptEnd = textBefore.lastIndexOf('</script');\n const isInScript = scriptStart > -1 && (scriptEnd === -1 || scriptEnd < scriptStart);\n \n // 判断是否在 template 标签属性区域(在 < 之后,> 之前)\n const lastOpenTag = before.lastIndexOf('<');\n const lastCloseTag = before.lastIndexOf('>');\n const isInTagAttr = lastOpenTag > lastCloseTag && !before.substring(lastOpenTag).includes('</');\n \n // 当前输入的单词(用于过滤)\n const currentWord = word.word.toLowerCase();\n\n // Vue 指令 - 在标签属性区域输入 v 或 v- 时触发\n const vueDirectiveMatch = /\\s(v-?)([\\w-]*)$/.exec(before + word.word);\n if (isInTagAttr && vueDirectiveMatch) {\n const prefix = vueDirectiveMatch[1] || '';\n const typed = vueDirectiveMatch[2]?.toLowerCase() || '';\n // range 需要包含 v 或 v- 前缀\n const vIndex = before.lastIndexOf(prefix.startsWith('v-') ? 'v-' : ' v');\n const startCol = prefix.startsWith('v-') ? vIndex + 1 : vIndex + 2;\n const directiveRange = {\n startLineNumber: position.lineNumber,\n endLineNumber: position.lineNumber,\n startColumn: startCol,\n endColumn: position.column,\n };\n const items: [string, string, string][] = [\n ['v-if', '条件渲染', 'v-if=\"$1\"'],\n ['v-else-if', '条件渲染', 'v-else-if=\"$1\"'],\n ['v-else', '条件渲染', 'v-else'],\n ['v-for', '列表渲染', 'v-for=\"$1 in $2\" :key=\"$3\"'],\n ['v-show', '显示隐藏', 'v-show=\"$1\"'],\n ['v-model', '双向绑定', 'v-model=\"$1\"'],\n ['v-model.number', '数字双向绑定', 'v-model.number=\"$1\"'],\n ['v-model.trim', '去空格双向绑定', 'v-model.trim=\"$1\"'],\n ['v-model.lazy', '懒更新双向绑定', 'v-model.lazy=\"$1\"'],\n ['v-bind', '属性绑定', 'v-bind:$1=\"$2\"'],\n ['v-on', '事件绑定', 'v-on:$1=\"$2\"'],\n ['v-slot', '插槽', 'v-slot:$1'],\n ['v-html', 'HTML内容', 'v-html=\"$1\"'],\n ['v-text', '文本内容', 'v-text=\"$1\"'],\n ['v-pre', '跳过编译', 'v-pre'],\n ['v-once', '只渲染一次', 'v-once'],\n ['v-memo', '缓存模板', 'v-memo=\"[$1]\"'],\n ['v-cloak', '隐藏未编译', 'v-cloak'],\n ];\n const filterText = prefix + typed;\n items.filter(([label]) => label.toLowerCase().startsWith(filterText) || label.toLowerCase().includes(filterText)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range: directiveRange, kind: monaco.languages.CompletionItemKind.Keyword, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // 默认 range\n const range = {\n startLineNumber: position.lineNumber,\n endLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endColumn: word.endColumn,\n };\n\n // @ 事件简写 - 匹配 @ 开头\n const eventMatch = /@([\\w.-]*)$/.exec(before + word.word);\n if (eventMatch) {\n const typed = eventMatch[1]?.toLowerCase() || '';\n const atIndex = before.lastIndexOf('@');\n const eventRange = {\n startLineNumber: position.lineNumber,\n endLineNumber: position.lineNumber,\n startColumn: atIndex + 1,\n endColumn: position.column,\n };\n const events: [string, string, string][] = [\n ['@click', '点击事件', '@click=\"$1\"'],\n ['@click.stop', '点击(阻止冒泡)', '@click.stop=\"$1\"'],\n ['@click.prevent', '点击(阻止默认)', '@click.prevent=\"$1\"'],\n ['@dblclick', '双击事件', '@dblclick=\"$1\"'],\n ['@change', '变更事件', '@change=\"$1\"'],\n ['@input', '输入事件', '@input=\"$1\"'],\n ['@submit', '提交事件', '@submit.prevent=\"$1\"'],\n ['@keyup', '键盘抬起', '@keyup=\"$1\"'],\n ['@keyup.enter', '回车键', '@keyup.enter=\"$1\"'],\n ['@keydown', '键盘按下', '@keydown=\"$1\"'],\n ['@focus', '获得焦点', '@focus=\"$1\"'],\n ['@blur', '失去焦点', '@blur=\"$1\"'],\n ['@mouseenter', '鼠标进入', '@mouseenter=\"$1\"'],\n ['@mouseleave', '鼠标离开', '@mouseleave=\"$1\"'],\n ];\n events.filter(([label]) => typed.length === 0 || label.toLowerCase().includes('@' + typed)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range: eventRange, kind: monaco.languages.CompletionItemKind.Event, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // Vue 3 Composition API - 只在 script 区域,输入 1 个字符即可触发\n if (isInScript && currentWord.length >= 1) {\n const apis: [string, string, string][] = [\n // 响应式核心\n ['ref', '创建响应式引用', 'ref($1)'],\n ['reactive', '创建响应式对象', 'reactive({$1})'],\n ['readonly', '创建只读代理', 'readonly($1)'],\n ['computed', '创建计算属性', 'computed(() => $1)'],\n ['computed get/set', '可写计算属性', 'computed({\\n get: () => $1,\\n set: (val) => {\\n $2\\n }\\n})'],\n // 响应式工具\n ['toRef', '转换为ref', 'toRef($1, \"$2\")'],\n ['toRefs', '转换为refs', 'toRefs($1)'],\n ['toValue', '获取值', 'toValue($1)'],\n ['toRaw', '获取原始对象', 'toRaw($1)'],\n ['unref', '解包ref', 'unref($1)'],\n ['isRef', '判断是否ref', 'isRef($1)'],\n ['isReactive', '判断是否reactive', 'isReactive($1)'],\n ['isReadonly', '判断是否readonly', 'isReadonly($1)'],\n ['isProxy', '判断是否代理', 'isProxy($1)'],\n // 浅层响应式\n ['shallowRef', '浅层响应式引用', 'shallowRef($1)'],\n ['shallowReactive', '浅层响应式对象', 'shallowReactive({$1})'],\n ['shallowReadonly', '浅层只读', 'shallowReadonly($1)'],\n ['triggerRef', '手动触发ref', 'triggerRef($1)'],\n ['customRef', '自定义ref', 'customRef((track, trigger) => ({\\n get() {\\n track();\\n return $1;\\n },\\n set(val) {\\n $2\\n trigger();\\n }\\n}))'],\n // 侦听器\n ['watch', '侦听响应式数据', 'watch($1, (newVal, oldVal) => {\\n $2\\n})'],\n ['watch immediate', '立即执行侦听', 'watch($1, (newVal, oldVal) => {\\n $2\\n}, { immediate: true })'],\n ['watch deep', '深度侦听', 'watch($1, (newVal, oldVal) => {\\n $2\\n}, { deep: true })'],\n ['watchEffect', '副作用侦听', 'watchEffect(() => {\\n $1\\n})'],\n ['watchPostEffect', 'DOM更新后执行', 'watchPostEffect(() => {\\n $1\\n})'],\n ['watchSyncEffect', '同步执行', 'watchSyncEffect(() => {\\n $1\\n})'],\n // 生命周期\n ['onMounted', '挂载后', 'onMounted(() => {\\n $1\\n})'],\n ['onUpdated', '更新后', 'onUpdated(() => {\\n $1\\n})'],\n ['onUnmounted', '卸载后', 'onUnmounted(() => {\\n $1\\n})'],\n ['onBeforeMount', '挂载前', 'onBeforeMount(() => {\\n $1\\n})'],\n ['onBeforeUpdate', '更新前', 'onBeforeUpdate(() => {\\n $1\\n})'],\n ['onBeforeUnmount', '卸载前', 'onBeforeUnmount(() => {\\n $1\\n})'],\n ['onActivated', 'keep-alive激活', 'onActivated(() => {\\n $1\\n})'],\n ['onDeactivated', 'keep-alive停用', 'onDeactivated(() => {\\n $1\\n})'],\n ['onErrorCaptured', '错误捕获', 'onErrorCaptured((err, instance, info) => {\\n $1\\n})'],\n // 依赖注入\n ['provide', '提供依赖', \"provide('$1', $2)\"],\n ['inject', '注入依赖', \"inject('$1')\"],\n ['inject default', '带默认值注入', \"inject('$1', $2)\"],\n // 组件定义\n ['defineProps', '定义props', 'defineProps<{\\n $1\\n}>()'],\n ['defineProps runtime', '运行时props', 'defineProps({\\n $1: {\\n type: $2,\\n required: $3\\n }\\n})'],\n ['defineEmits', '定义emits', \"defineEmits<{\\n (e: '$1', $2): void\\n}>()\"],\n ['defineExpose', '暴露属性', 'defineExpose({\\n $1\\n})'],\n ['defineOptions', '定义选项', 'defineOptions({\\n name: \"$1\"\\n})'],\n ['defineModel', '定义model', 'defineModel<$1>()'],\n ['defineSlots', '定义slots类型', 'defineSlots<{\\n default(props: { $1 }): any\\n}>()'],\n ['withDefaults', '设置默认值', 'withDefaults(defineProps<{\\n $1\\n}>(), {\\n $2\\n})'],\n // 其他\n ['nextTick', '下一tick执行', 'nextTick(() => {\\n $1\\n})'],\n ['useSlots', '获取slots', 'useSlots()'],\n ['useAttrs', '获取attrs', 'useAttrs()'],\n ['useCssModule', '获取CSS模块', 'useCssModule()'],\n ['effectScope', '创建effect作用域', 'effectScope()'],\n ['getCurrentInstance', '获取组件实例', 'getCurrentInstance()'],\n ];\n apis.filter(([label]) => label.toLowerCase().includes(currentWord)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.Function, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // HTML 标签补全\n if (before.endsWith('<') || /^<\\w*$/.test(word.word)) {\n const htmlTags: [string, string, string][] = [\n ['div', 'div容器', 'div$1>$2</div>'],\n ['span', 'span行内', 'span$1>$2</span>'],\n ['p', '段落', 'p>$1</p>'],\n ['a', '链接', 'a href=\"$1\">$2</a>'],\n ['img', '图片', 'img src=\"$1\" alt=\"$2\" />'],\n ['ul', '无序列表', 'ul>\\n <li>$1</li>\\n</ul>'],\n ['ol', '有序列表', 'ol>\\n <li>$1</li>\\n</ol>'],\n ['li', '列表项', 'li>$1</li>'],\n ['table', '表格', 'table>\\n <thead>\\n <tr>\\n <th>$1</th>\\n </tr>\\n </thead>\\n <tbody>\\n <tr>\\n <td>$2</td>\\n </tr>\\n </tbody>\\n</table>'],\n ['form', '表单', 'form @submit.prevent=\"$1\">\\n $2\\n</form>'],\n ['input', '输入框', 'input type=\"$1\" v-model=\"$2\" />'],\n ['button', '按钮', 'button @click=\"$1\">$2</button>'],\n ['textarea', '文本域', 'textarea v-model=\"$1\"></textarea>'],\n ['select', '下拉框', 'select v-model=\"$1\">\\n <option value=\"$2\">$3</option>\\n</select>'],\n ['template', 'template块', 'template>\\n $1\\n</template>'],\n ['script setup', 'script setup', 'script setup lang=\"ts\">\\n$1\\n</script>'],\n ['style scoped', 'scoped样式', 'style scoped lang=\"scss\">\\n$1\\n</style>'],\n ];\n\n // Element Plus 组件\n const elComponents: [string, string, string][] = [\n ['el-button', 'Element按钮', 'el-button type=\"$1\">$2</el-button>'],\n ['el-input', 'Element输入框', 'el-input v-model=\"$1\" placeholder=\"$2\" />'],\n ['el-select', 'Element下拉框', 'el-select v-model=\"$1\">\\n <el-option label=\"$2\" value=\"$3\" />\\n</el-select>'],\n ['el-form', 'Element表单', 'el-form :model=\"$1\" :rules=\"$2\" ref=\"formRef\">\\n <el-form-item label=\"$3\" prop=\"$4\">\\n $5\\n </el-form-item>\\n</el-form>'],\n ['el-form-item', 'Element表单项', 'el-form-item label=\"$1\" prop=\"$2\">\\n $3\\n</el-form-item>'],\n ['el-table', 'Element表格', 'el-table :data=\"$1\">\\n <el-table-column prop=\"$2\" label=\"$3\" />\\n</el-table>'],\n ['el-table-column', 'Element表格列', 'el-table-column prop=\"$1\" label=\"$2\" />'],\n ['el-dialog', 'Element对话框', 'el-dialog v-model=\"$1\" title=\"$2\">\\n $3\\n</el-dialog>'],\n ['el-row', 'Element行', 'el-row :gutter=\"$1\">\\n <el-col :span=\"$2\">$3</el-col>\\n</el-row>'],\n ['el-col', 'Element列', 'el-col :span=\"$1\">$2</el-col>'],\n ['el-card', 'Element卡片', 'el-card>\\n <template #header>$1</template>\\n $2\\n</el-card>'],\n ['el-tabs', 'Element标签页', 'el-tabs v-model=\"$1\">\\n <el-tab-pane label=\"$2\" name=\"$3\">$4</el-tab-pane>\\n</el-tabs>'],\n ['el-pagination', 'Element分页', 'el-pagination\\n v-model:current-page=\"$1\"\\n v-model:page-size=\"$2\"\\n :total=\"$3\"\\n @current-change=\"$4\"\\n/>'],\n ['el-tag', 'Element标签', 'el-tag type=\"$1\">$2</el-tag>'],\n ['el-switch', 'Element开关', 'el-switch v-model=\"$1\" />'],\n ['el-checkbox', 'Element复选框', 'el-checkbox v-model=\"$1\">$2</el-checkbox>'],\n ['el-radio', 'Element单选框', 'el-radio v-model=\"$1\" label=\"$2\">$3</el-radio>'],\n ['el-date-picker', 'Element日期选择', 'el-date-picker v-model=\"$1\" type=\"$2\" placeholder=\"$3\" />'],\n ['el-upload', 'Element上传', 'el-upload\\n action=\"$1\"\\n :on-success=\"$2\"\\n>\\n <el-button>上传</el-button>\\n</el-upload>'],\n ['el-tree', 'Element树', 'el-tree :data=\"$1\" :props=\"$2\" />'],\n ['el-icon', 'Element图标', 'el-icon><$1 /></el-icon>'],\n ['el-tooltip', 'Element提示', 'el-tooltip content=\"$1\">\\n $2\\n</el-tooltip>'],\n ['el-popover', 'Element弹出框', 'el-popover trigger=\"$1\">\\n <template #reference>$2</template>\\n $3\\n</el-popover>'],\n ['el-drawer', 'Element抽屉', 'el-drawer v-model=\"$1\" title=\"$2\">\\n $3\\n</el-drawer>'],\n ['el-dropdown', 'Element下拉菜单', 'el-dropdown>\\n <span>$1</span>\\n <template #dropdown>\\n <el-dropdown-menu>\\n <el-dropdown-item>$2</el-dropdown-item>\\n </el-dropdown-menu>\\n </template>\\n</el-dropdown>'],\n ['el-menu', 'Element菜单', 'el-menu :default-active=\"$1\">\\n <el-menu-item index=\"$2\">$3</el-menu-item>\\n</el-menu>'],\n ['el-breadcrumb', 'Element面包屑', 'el-breadcrumb>\\n <el-breadcrumb-item :to=\"{ path: \\'$1\\' }\">$2</el-breadcrumb-item>\\n</el-breadcrumb>'],\n ['el-steps', 'Element步骤条', 'el-steps :active=\"$1\">\\n <el-step title=\"$2\" />\\n</el-steps>'],\n ['el-alert', 'Element警告', 'el-alert title=\"$1\" type=\"$2\" />'],\n ['el-loading', 'Element加载', 'el-loading v-loading=\"$1\" />'],\n ['el-empty', 'Element空状态', 'el-empty description=\"$1\" />'],\n ['el-result', 'Element结果', 'el-result icon=\"$1\" title=\"$2\" sub-title=\"$3\" />'],\n ['el-skeleton', 'Element骨架屏', 'el-skeleton :loading=\"$1\">\\n $2\\n</el-skeleton>'],\n ['el-image', 'Element图片', 'el-image :src=\"$1\" fit=\"$2\" />'],\n ['el-avatar', 'Element头像', 'el-avatar :src=\"$1\" />'],\n ['el-badge', 'Element徽章', 'el-badge :value=\"$1\">\\n $2\\n</el-badge>'],\n ['el-progress', 'Element进度条', 'el-progress :percentage=\"$1\" />'],\n ['el-divider', 'Element分割线', 'el-divider>$1</el-divider>'],\n ['el-space', 'Element间距', 'el-space>\\n $1\\n</el-space>'],\n ['el-scrollbar', 'Element滚动条', 'el-scrollbar height=\"$1\">\\n $2\\n</el-scrollbar>'],\n ];\n\n [...htmlTags, ...elComponents].forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.Snippet, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // import 语句\n if (/^import\\s*$/.test(before) || /^import\\s+\\{?\\s*$/.test(before)) {\n const imports: [string, string, string][] = [\n ['import vue', 'Vue核心导入', \"import { ref, reactive, computed, watch, onMounted } from 'vue';\"],\n ['import ref', '导入ref', \"import { ref } from 'vue';\"],\n ['import reactive', '导入reactive', \"import { reactive } from 'vue';\"],\n ['import computed', '导入computed', \"import { computed } from 'vue';\"],\n ['import watch', '导入watch', \"import { watch, watchEffect } from 'vue';\"],\n ['import lifecycle', '导入生命周期', \"import { onMounted, onUnmounted, onBeforeMount, onBeforeUnmount } from 'vue';\"],\n ['import router', '导入路由', \"import { useRouter, useRoute } from 'vue-router';\"],\n ['import axios', '导入axios', \"import axios from 'axios';\"],\n ['import element', '导入Element组件', \"import { ElMessage, ElMessageBox } from 'element-plus';\"],\n ];\n imports.forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.Module, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // TypeScript 类型 - 只在 script 区域,输入 1 个字符即可触发\n if (isInScript && currentWord.length >= 1) {\n const tsTypes: [string, string, string][] = [\n ['interface', '接口定义', 'interface $1 {\\n $2\\n}'],\n ['type', '类型别名', 'type $1 = $2;'],\n ['type union', '联合类型', \"type $1 = '$2' | '$3';\"],\n ['enum', '枚举', 'enum $1 {\\n $2\\n}'],\n ['Ref<T>', 'Ref类型', 'Ref<$1>'],\n ['ComputedRef<T>', 'ComputedRef类型', 'ComputedRef<$1>'],\n ['PropType<T>', 'PropType类型', 'PropType<$1>'],\n ['Partial<T>', 'Partial类型', 'Partial<$1>'],\n ['Required<T>', 'Required类型', 'Required<$1>'],\n ['Pick<T,K>', 'Pick类型', 'Pick<$1, $2>'],\n ['Omit<T,K>', 'Omit类型', 'Omit<$1, $2>'],\n ['Record<K,V>', 'Record类型', 'Record<$1, $2>'],\n ];\n tsTypes.filter(([label]) => label.toLowerCase().includes(currentWord)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.TypeParameter, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // JavaScript 关键字 - 只在 script 区域,输入 1 个字符即可触发\n if (isInScript && currentWord.length >= 1) {\n const jsKeywords: [string, string, string][] = [\n ['const', '常量声明', 'const $1 = $2;'],\n ['let', '变量声明', 'let $1 = $2;'],\n ['var', '变量声明(旧)', 'var $1 = $2;'],\n ['function', '函数声明', 'function $1($2) {\\n $3\\n}'],\n ['async function', '异步函数', 'async function $1($2) {\\n $3\\n}'],\n ['arrow function', '箭头函数', '($1) => {\\n $2\\n}'],\n ['arrow function short', '箭头函数简写', '($1) => $2'],\n ['class', '类声明', 'class $1 {\\n constructor($2) {\\n $3\\n }\\n}'],\n ['if', '条件语句', 'if ($1) {\\n $2\\n}'],\n ['if else', '条件分支', 'if ($1) {\\n $2\\n} else {\\n $3\\n}'],\n ['else if', '否则如果', 'else if ($1) {\\n $2\\n}'],\n ['switch', 'switch语句', 'switch ($1) {\\n case $2:\\n $3\\n break;\\n default:\\n $4\\n}'],\n ['for', 'for循环', 'for (let i = 0; i < $1; i++) {\\n $2\\n}'],\n ['for of', 'for...of循环', 'for (const $1 of $2) {\\n $3\\n}'],\n ['for in', 'for...in循环', 'for (const $1 in $2) {\\n $3\\n}'],\n ['while', 'while循环', 'while ($1) {\\n $2\\n}'],\n ['do while', 'do...while循环', 'do {\\n $1\\n} while ($2);'],\n ['try catch', 'try...catch', 'try {\\n $1\\n} catch (error) {\\n $2\\n}'],\n ['try catch finally', 'try...catch...finally', 'try {\\n $1\\n} catch (error) {\\n $2\\n} finally {\\n $3\\n}'],\n ['throw', '抛出错误', \"throw new Error('$1');\"],\n ['return', '返回', 'return $1;'],\n ['await', '等待Promise', 'await $1'],\n ['new Promise', '创建Promise', 'new Promise((resolve, reject) => {\\n $1\\n})'],\n ['async await', '异步等待', 'const $1 = await $2;'],\n ['export default', '默认导出', 'export default $1;'],\n ['export', '命名导出', 'export { $1 };'],\n ['import', '导入', \"import { $1 } from '$2';\"],\n ['import default', '默认导入', \"import $1 from '$2';\"],\n ['destructure object', '对象解构', 'const { $1 } = $2;'],\n ['destructure array', '数组解构', 'const [$1] = $2;'],\n ['spread object', '对象展开', '{ ...$1 }'],\n ['spread array', '数组展开', '[...$1]'],\n ['template literal', '模板字符串', '`$1${$2}$3`'],\n ['ternary', '三元表达式', '$1 ? $2 : $3'],\n ['nullish coalescing', '空值合并', '$1 ?? $2'],\n ['optional chaining', '可选链', '$1?.$2'],\n ];\n jsKeywords.filter(([label]) => label.toLowerCase().includes(currentWord)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.Keyword, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // JavaScript 内置对象和方法 - 只在 script 区域,输入 . 或 1 个字符即可触发\n if (isInScript && (before.endsWith('.') || currentWord.length >= 1)) {\n const jsMethods: [string, string, string][] = [\n // Console\n ['console.log', '控制台输出', \"console.log($1);\"],\n ['console.error', '控制台错误', \"console.error($1);\"],\n ['console.warn', '控制台警告', \"console.warn($1);\"],\n ['console.info', '控制台信息', \"console.info($1);\"],\n ['console.table', '控制台表格', \"console.table($1);\"],\n ['console.time', '计时开始', \"console.time('$1');\"],\n ['console.timeEnd', '计时结束', \"console.timeEnd('$1');\"],\n ['console.group', '分组开始', \"console.group('$1');\"],\n ['console.groupEnd', '分组结束', \"console.groupEnd();\"],\n // Array\n ['array.map', '数组映射', '$1.map(($2) => $3)'],\n ['array.filter', '数组过滤', '$1.filter(($2) => $3)'],\n ['array.find', '数组查找', '$1.find(($2) => $3)'],\n ['array.findIndex', '数组查找索引', '$1.findIndex(($2) => $3)'],\n ['array.forEach', '数组遍历', '$1.forEach(($2) => {\\n $3\\n})'],\n ['array.reduce', '数组归约', '$1.reduce((acc, $2) => {\\n $3\\n return acc;\\n}, $4)'],\n ['array.some', '数组某些', '$1.some(($2) => $3)'],\n ['array.every', '数组每个', '$1.every(($2) => $3)'],\n ['array.includes', '数组包含', '$1.includes($2)'],\n ['array.indexOf', '数组索引', '$1.indexOf($2)'],\n ['array.push', '数组添加', '$1.push($2)'],\n ['array.pop', '数组弹出', '$1.pop()'],\n ['array.shift', '数组移除首个', '$1.shift()'],\n ['array.unshift', '数组添加到首', '$1.unshift($2)'],\n ['array.slice', '数组切片', '$1.slice($2, $3)'],\n ['array.splice', '数组拼接', '$1.splice($2, $3)'],\n ['array.concat', '数组连接', '$1.concat($2)'],\n ['array.join', '数组连接字符串', \"$1.join('$2')\"],\n ['array.reverse', '数组反转', '$1.reverse()'],\n ['array.sort', '数组排序', '$1.sort((a, b) => $2)'],\n ['array.flat', '数组扁平化', '$1.flat($2)'],\n ['array.flatMap', '数组扁平映射', '$1.flatMap(($2) => $3)'],\n ['Array.from', '从类数组创建', 'Array.from($1)'],\n ['Array.isArray', '判断是否数组', 'Array.isArray($1)'],\n // Object\n ['Object.keys', '对象键数组', 'Object.keys($1)'],\n ['Object.values', '对象值数组', 'Object.values($1)'],\n ['Object.entries', '对象键值对', 'Object.entries($1)'],\n ['Object.assign', '对象合并', 'Object.assign({}, $1, $2)'],\n ['Object.fromEntries', '从键值对创建', 'Object.fromEntries($1)'],\n ['Object.hasOwn', '判断自有属性', 'Object.hasOwn($1, \"$2\")'],\n ['Object.freeze', '冻结对象', 'Object.freeze($1)'],\n // String\n ['string.split', '字符串分割', \"$1.split('$2')\"],\n ['string.trim', '去除空格', '$1.trim()'],\n ['string.toLowerCase', '转小写', '$1.toLowerCase()'],\n ['string.toUpperCase', '转大写', '$1.toUpperCase()'],\n ['string.replace', '字符串替换', \"$1.replace('$2', '$3')\"],\n ['string.replaceAll', '全部替换', \"$1.replaceAll('$2', '$3')\"],\n ['string.includes', '字符串包含', \"$1.includes('$2')\"],\n ['string.startsWith', '以...开头', \"$1.startsWith('$2')\"],\n ['string.endsWith', '以...结尾', \"$1.endsWith('$2')\"],\n ['string.substring', '子字符串', '$1.substring($2, $3)'],\n ['string.slice', '字符串切片', '$1.slice($2, $3)'],\n ['string.padStart', '前填充', \"$1.padStart($2, '$3')\"],\n ['string.padEnd', '后填充', \"$1.padEnd($2, '$3')\"],\n // Number/Math\n ['parseInt', '解析整数', \"parseInt($1, 10)\"],\n ['parseFloat', '解析浮点数', 'parseFloat($1)'],\n ['Number.isNaN', '判断NaN', 'Number.isNaN($1)'],\n ['Number.isFinite', '判断有限', 'Number.isFinite($1)'],\n ['Math.floor', '向下取整', 'Math.floor($1)'],\n ['Math.ceil', '向上取整', 'Math.ceil($1)'],\n ['Math.round', '四舍五入', 'Math.round($1)'],\n ['Math.abs', '绝对值', 'Math.abs($1)'],\n ['Math.max', '最大值', 'Math.max($1, $2)'],\n ['Math.min', '最小值', 'Math.min($1, $2)'],\n ['Math.random', '随机数', 'Math.random()'],\n ['toFixed', '保留小数', '$1.toFixed($2)'],\n // JSON\n ['JSON.stringify', 'JSON序列化', 'JSON.stringify($1)'],\n ['JSON.stringify pretty', 'JSON格式化', 'JSON.stringify($1, null, 2)'],\n ['JSON.parse', 'JSON解析', 'JSON.parse($1)'],\n // Promise\n ['Promise.all', '等待所有', 'Promise.all([$1])'],\n ['Promise.race', '竞速', 'Promise.race([$1])'],\n ['Promise.allSettled', '等待所有完成', 'Promise.allSettled([$1])'],\n ['Promise.resolve', '解决Promise', 'Promise.resolve($1)'],\n ['Promise.reject', '拒绝Promise', 'Promise.reject($1)'],\n // setTimeout/setInterval\n ['setTimeout', '延时执行', 'setTimeout(() => {\\n $1\\n}, $2);'],\n ['setInterval', '定时执行', 'setInterval(() => {\\n $1\\n}, $2);'],\n ['clearTimeout', '清除延时', 'clearTimeout($1);'],\n ['clearInterval', '清除定时', 'clearInterval($1);'],\n // DOM\n ['document.getElementById', '通过ID获取', \"document.getElementById('$1')\"],\n ['document.querySelector', '选择器获取', \"document.querySelector('$1')\"],\n ['document.querySelectorAll', '选择器获取所有', \"document.querySelectorAll('$1')\"],\n ['addEventListener', '添加事件监听', \"$1.addEventListener('$2', ($3) => {\\n $4\\n});\"],\n ['removeEventListener', '移除事件监听', \"$1.removeEventListener('$2', $3);\"],\n // Fetch\n ['fetch', 'Fetch请求', \"fetch('$1')\\n .then(res => res.json())\\n .then(data => {\\n $2\\n });\"],\n ['fetch async', 'Fetch异步', \"const response = await fetch('$1');\\nconst data = await response.json();\"],\n // LocalStorage\n ['localStorage.getItem', '获取本地存储', \"localStorage.getItem('$1')\"],\n ['localStorage.setItem', '设置本地存储', \"localStorage.setItem('$1', $2);\"],\n ['localStorage.removeItem', '移除本地存储', \"localStorage.removeItem('$1');\"],\n // 其他\n ['typeof', '类型判断', \"typeof $1 === '$2'\"],\n ['instanceof', '实例判断', '$1 instanceof $2'],\n ['structuredClone', '深拷贝', 'structuredClone($1)'],\n ];\n jsMethods.filter(([label]) => currentWord.length === 0 || label.toLowerCase().includes(currentWord)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.Method, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n return { suggestions };\n },\n });\n}\n\nexport function getVueTheme(isDark: boolean): string {\n return isDark ? 'vue-dark' : 'vue-light';\n}\n","<script setup lang=\"ts\">\nimport type { FormCodeEditorProp, SupportedLanguage } from '@/types';\n\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n shallowRef,\n watch,\n} from 'vue';\n\n\nimport { FullScreen } from '@element-plus/icons-vue';\nimport * as monaco from 'monaco-editor';\n\nimport { isEmpty, isNotEmpty } from '@/utils';\n\nimport { initVueLanguageSupport } from './volar/setup';\n\ninterface Props {\n detail: FormCodeEditorProp;\n value?: object | string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n});\n\n// ✅ 7. emit update\nconst emit = defineEmits<{\n (e: 'update:value', value: string): void;\n}>();\n\n// const { isDark } = usePreferences();\nconst isDark = ref(true);\n\nconst showDialog = ref(false);\nconst mainEditor = ref<HTMLElement | null>(null);\nconst dialogEditor = ref<HTMLElement | null>(null);\nconst mainEditorInstance =\n shallowRef<monaco.editor.IStandaloneCodeEditor | null>(null);\nconst dialogEditorInstance =\n shallowRef<monaco.editor.IStandaloneCodeEditor | null>(null);\nconst model = shallowRef<monaco.editor.ITextModel | null>(null);\n\n// 注册语言\nconst registerLanguage = async (langId: SupportedLanguage) => {\n if (['css', 'html', 'javascript', 'typescript'].includes(langId)) return;\n\n // Vue 使用 Volar 初始化\n if (langId === 'vue') {\n await initVueLanguageSupport();\n return;\n }\n\n const registered = monaco.languages\n .getLanguages()\n .some((l) => l.id === langId);\n\n let mod: any;\n try {\n switch (langId) {\n case 'java': {\n mod = await import('./language/java');\n // 先定义主题,再注册补全\n mod.defineJavaThemes?.();\n mod.registerJavaCompletion?.();\n if (registered) return;\n break;\n }\n case 'json': {\n if (registered) return;\n mod = {};\n break;\n }\n case 'mysql': {\n if (registered) return;\n mod = await import('./language/mysql');\n break;\n }\n case 'postgresql': {\n mod = await import('./language/postgresql');\n // 注册 PostgreSQL 代码提示和主题\n mod.definePgsqlThemes?.();\n mod.registerPgsqlCompletion?.();\n if (registered) return;\n break;\n }\n default: {\n return;\n }\n }\n } catch (error) {\n console.warn(\n `[Monaco] Language ${langId} may already be registered`,\n error,\n );\n return;\n }\n\n monaco.languages.register({ id: langId });\n monaco.languages.setMonarchTokensProvider(langId, mod.language);\n monaco.languages.setLanguageConfiguration(langId, mod.conf);\n};\n\nconst initCodeTips = () => {\n // 在 onMounted 中,create 之后添加\n monaco.languages.registerCompletionItemProvider('javascript', {\n // 触发字符\n triggerCharacters: ['.'],\n\n provideCompletionItems: (model, position) => {\n const word = model.getWordUntilPosition(position);\n const range = {\n startLineNumber: position.lineNumber,\n endLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endColumn: word.endColumn,\n };\n\n // 获取当前光标前的文本(用于判断上下文)\n const textUntilPosition = model.getValueInRange({\n startLineNumber: 1,\n startColumn: 1,\n endLineNumber: position.lineNumber,\n endColumn: position.column,\n });\n\n // 匹配 btnClick.\n const match = /btnClick\\.(\\w*)$/.exec(textUntilPosition);\n if (match) {\n return {\n suggestions: [\n {\n label: 'openForm',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '打开表单',\n insertText: 'openForm(data, rowIndex)',\n insertTextRules:\n monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,\n range,\n },\n {\n label: 'deleteData',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '删除数据',\n insertText: 'btnClick.deleteData(data)',\n range,\n },\n {\n label: 'refreshTableData',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '获取数据',\n insertText: 'btnClick.refreshTableData()',\n range,\n },\n {\n label: 'routerPush',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '获取数据',\n insertText:\n 'btnClick.routerPush(路由name, router.push除了name的参数)',\n range,\n },\n ],\n };\n }\n\n // 也可以为 data. 提示\n const dataMatch = /data\\.(\\w*)$/.exec(textUntilPosition);\n if (dataMatch) {\n return {\n suggestions: Object.keys((window as any).mockData || {}).map(\n (key) => ({\n label: key,\n kind: monaco.languages.CompletionItemKind.Property,\n documentation: 'data 的属性',\n insertText: key,\n range,\n }),\n ),\n };\n }\n\n return { suggestions: [] };\n },\n });\n};\n\n/**\n * 获取默认值\n */\nconst getDefaultValue = (): string => {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n if (newLang === 'json') {\n if (typeof props.detail.defaultValue === 'object') {\n return JSON.stringify(props.detail.defaultValue);\n }\n\n return props.detail.defaultValue || '';\n }\n\n return props.detail.defaultValue as string;\n};\n\nlet mainLoaded = false;\nlet dialogLoaded = false;\n\nconst initMainEditor = async () => {\n if (mainLoaded || !mainEditor.value) return;\n await initEditor(mainEditor.value, (instance) => {\n mainEditorInstance.value = instance;\n });\n mainLoaded = true;\n};\n\nconst openDialog = async () => {\n showDialog.value = true;\n if (dialogLoaded) return;\n await nextTick();\n await initEditor(dialogEditor.value!, (instance) => {\n dialogEditorInstance.value = instance;\n });\n dialogLoaded = true;\n};\n\nconst initEditor = async (\n container: HTMLElement,\n setInstance: (instance: monaco.editor.IStandaloneCodeEditor) => void,\n) => {\n const lang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n\n await registerLanguage(lang);\n\n if (!model.value) {\n let val: string = '';\n if (lang === 'json' && typeof props.value === 'object') {\n val = JSON.stringify(props.value, null, 2);\n } else if (typeof props.value === 'string') {\n val = props.value;\n }\n model.value = monaco.editor.createModel(val, lang);\n }\n\n if (lang === 'javascript') {\n monaco.languages.typescript.javascriptDefaults.addExtraLib(\n `\nconst data = {};\nconst rowIndex = 0;\nconst btnClick = {\n openForm: function(data, rowIndex) {},\n closeForm: function() {},\n getData: function() {}\n};\n`,\n 'extra:context.d.ts',\n );\n }\n\n const getEditorTheme = (lang: SupportedLanguage, dark: boolean): string => {\n if (lang === 'vue') {\n return dark ? 'vue-dark' : 'vue-light';\n }\n if (lang === 'java') {\n return dark ? 'java-dark' : 'java-light';\n }\n return dark ? 'vs-dark' : 'vs';\n };\n\n const instance = monaco.editor.create(container, {\n model: model.value,\n theme: getEditorTheme(lang, isDark.value),\n automaticLayout: true,\n readOnly: props.detail.disabled === true,\n suggest: {\n showKeywords: true,\n showFunctions: true,\n },\n quickSuggestions: {\n other: true,\n strings: true,\n },\n tabSize: 4,\n });\n\n setInstance(instance);\n\n instance.onDidChangeModelContent(() => {\n const value = model.value?.getValue();\n if (value !== undefined && value !== props.value) {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n try {\n if (newLang === 'json') {\n emit('update:value', JSON.parse(value));\n } else {\n emit('update:value', value);\n }\n } catch {\n // JSON 解析失败时不 emit\n }\n }\n });\n\n initCodeTips();\n};\n\n// 组件挂载后初始化主编辑器\nnextTick(() => {\n initMainEditor();\n});\n\n// 监听主题变化\nwatch(isDark, (dark) => {\n const lang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n let theme = dark ? 'vs-dark' : 'vs';\n if (lang === 'vue') {\n theme = dark ? 'vue-dark' : 'vue-light';\n } else if (lang === 'java') {\n theme = dark ? 'java-dark' : 'java-light';\n }\n if (mainEditorInstance.value) {\n monaco.editor.setTheme(theme);\n }\n});\n\n// ✅ 5. 监听语言切换(在 model 存在后才执行)\nwatch(\n () => props.detail,\n async () => {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n if (model.value) {\n await registerLanguage(newLang);\n monaco.editor.setModelLanguage(model.value, newLang);\n }\n },\n { deep: true },\n);\n\n// ✅ 6. 监听 value 变化(确保 model 已创建)\nwatch(\n () => props.value,\n (newVal) => {\n if (!model.value) return;\n\n if (isEmpty(newVal)) {\n if (isNotEmpty(model.value.getValue())) {\n model.value.setValue('');\n }\n if (isNotEmpty(props.detail.defaultValue)) {\n const defaultValue = getDefaultValue();\n model.value.setValue(defaultValue);\n }\n return;\n }\n\n const currentValue = model.value.getValue();\n\n let nextValue = '';\n\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n\n if (newLang === 'json' && typeof newVal === 'object') {\n try {\n nextValue = JSON.stringify(newVal, null, 2);\n } catch {\n return;\n }\n } else if (typeof newVal === 'string') {\n nextValue = newVal;\n }\n\n // ✅ 避免重复 setValue\n if (nextValue !== currentValue) {\n model.value.setValue(nextValue || '');\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (mainEditorInstance.value) {\n mainEditorInstance.value.dispose();\n mainEditorInstance.value = null;\n }\n if (dialogEditorInstance.value) {\n dialogEditorInstance.value.dispose();\n dialogEditorInstance.value = null;\n }\n if (model.value) {\n model.value.dispose();\n model.value = null;\n }\n});\n\nconst maxHeight = computed(() => {\n if (props.detail?.componentParams?.maxLine) {\n const em = props.detail?.componentParams?.maxLine * 1.4;\n return `${em}em`;\n }\n\n return '24em';\n});\n</script>\n<template>\n <div class=\"container\">\n <div class=\"code-preview\">\n <p v-if=\"detail.componentParams?.prefix\" class=\"code-prefix\">\n {{ detail.componentParams.prefix }}\n </p>\n <div\n ref=\"mainEditor\"\n class=\"main-editor\"\n :style=\"{ height: maxHeight }\"\n ></div>\n <p v-if=\"detail.componentParams?.suffix\" class=\"code-suffix\">\n {{ detail.componentParams.suffix }}\n </p>\n <el-button\n class=\"expand-btn\"\n :icon=\"FullScreen\"\n circle\n size=\"small\"\n @click=\"openDialog\"\n />\n </div>\n <el-dialog\n v-model=\"showDialog\"\n append-to-body\n align-center\n center\n width=\"80%\"\n class=\"code-editor-dialog\"\n >\n <div class=\"dialog-container\">\n <p v-if=\"detail.componentParams?.prefix\" class=\"code-prefix\">\n {{ detail.componentParams.prefix }}\n </p>\n <div ref=\"dialogEditor\" class=\"dialog-editor\"></div>\n <p v-if=\"detail.componentParams?.suffix\" class=\"code-suffix\">\n {{ detail.componentParams.suffix }}\n </p>\n </div>\n </el-dialog>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.container {\n width: 100%;\n height: 100%;\n padding: 0;\n}\n.code-preview {\n position: relative;\n width: 100%;\n height: 100%;\n}\n.code-prefix,\n.code-suffix {\n margin: 0;\n padding: 4px 8px;\n font-size: 12px;\n color: var(--el-text-color-secondary);\n background: var(--el-fill-color-light);\n border: 1px solid var(--el-border-color);\n font-family: monospace;\n white-space: pre-wrap;\n}\n.code-prefix {\n border-bottom: none;\n border-radius: var(--el-border-radius-base) var(--el-border-radius-base) 0 0;\n}\n.code-suffix {\n border-top: none;\n border-radius: 0 0 var(--el-border-radius-base) var(--el-border-radius-base);\n}\n.main-editor {\n width: 100%;\n border-radius: var(--el-border-radius-base);\n overflow: hidden;\n border: 1px solid var(--el-border-color);\n}\n.code-prefix + .main-editor {\n border-radius: 0;\n}\n.main-editor:has(+ .code-suffix) {\n border-radius: var(--el-border-radius-base) var(--el-border-radius-base) 0 0;\n}\n.code-prefix + .main-editor:has(+ .code-suffix) {\n border-radius: 0;\n}\n.expand-btn {\n position: absolute;\n top: 4px;\n right: 4px;\n z-index: 10;\n}\n.dialog-container {\n width: 100%;\n height: 100%;\n padding: 0;\n}\n.dialog-editor {\n width: 100%;\n border-radius: var(--el-border-radius-base);\n overflow: hidden;\n height: 80vh;\n border: 1px solid var(--el-border-color);\n}\n</style>\n\n<style lang=\"scss\">\n/* 弹窗样式覆盖 - 减少内边距 */\n.code-editor-dialog {\n .el-dialog__body {\n padding: 8px 12px 12px;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FormCodeEditorProp, SupportedLanguage } from '@/types';\n\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n shallowRef,\n watch,\n} from 'vue';\n\n\nimport { FullScreen } from '@element-plus/icons-vue';\nimport * as monaco from 'monaco-editor';\n\nimport { isEmpty, isNotEmpty } from '@/utils';\n\nimport { initVueLanguageSupport } from './volar/setup';\n\ninterface Props {\n detail: FormCodeEditorProp;\n value?: object | string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n});\n\n// ✅ 7. emit update\nconst emit = defineEmits<{\n (e: 'update:value', value: string): void;\n}>();\n\n// const { isDark } = usePreferences();\nconst isDark = ref(true);\n\nconst showDialog = ref(false);\nconst mainEditor = ref<HTMLElement | null>(null);\nconst dialogEditor = ref<HTMLElement | null>(null);\nconst mainEditorInstance =\n shallowRef<monaco.editor.IStandaloneCodeEditor | null>(null);\nconst dialogEditorInstance =\n shallowRef<monaco.editor.IStandaloneCodeEditor | null>(null);\nconst model = shallowRef<monaco.editor.ITextModel | null>(null);\n\n// 注册语言\nconst registerLanguage = async (langId: SupportedLanguage) => {\n if (['css', 'html', 'javascript', 'typescript'].includes(langId)) return;\n\n // Vue 使用 Volar 初始化\n if (langId === 'vue') {\n await initVueLanguageSupport();\n return;\n }\n\n const registered = monaco.languages\n .getLanguages()\n .some((l) => l.id === langId);\n\n let mod: any;\n try {\n switch (langId) {\n case 'java': {\n mod = await import('./language/java');\n // 先定义主题,再注册补全\n mod.defineJavaThemes?.();\n mod.registerJavaCompletion?.();\n if (registered) return;\n break;\n }\n case 'json': {\n if (registered) return;\n mod = {};\n break;\n }\n case 'mysql': {\n if (registered) return;\n mod = await import('./language/mysql');\n break;\n }\n case 'postgresql': {\n mod = await import('./language/postgresql');\n // 注册 PostgreSQL 代码提示和主题\n mod.definePgsqlThemes?.();\n mod.registerPgsqlCompletion?.();\n if (registered) return;\n break;\n }\n default: {\n return;\n }\n }\n } catch (error) {\n console.warn(\n `[Monaco] Language ${langId} may already be registered`,\n error,\n );\n return;\n }\n\n monaco.languages.register({ id: langId });\n monaco.languages.setMonarchTokensProvider(langId, mod.language);\n monaco.languages.setLanguageConfiguration(langId, mod.conf);\n};\n\nconst initCodeTips = () => {\n // 在 onMounted 中,create 之后添加\n monaco.languages.registerCompletionItemProvider('javascript', {\n // 触发字符\n triggerCharacters: ['.'],\n\n provideCompletionItems: (model, position) => {\n const word = model.getWordUntilPosition(position);\n const range = {\n startLineNumber: position.lineNumber,\n endLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endColumn: word.endColumn,\n };\n\n // 获取当前光标前的文本(用于判断上下文)\n const textUntilPosition = model.getValueInRange({\n startLineNumber: 1,\n startColumn: 1,\n endLineNumber: position.lineNumber,\n endColumn: position.column,\n });\n\n // 匹配 btnClick.\n const match = /btnClick\\.(\\w*)$/.exec(textUntilPosition);\n if (match) {\n return {\n suggestions: [\n {\n label: 'openForm',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '打开表单',\n insertText: 'openForm(data, rowIndex)',\n insertTextRules:\n monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,\n range,\n },\n {\n label: 'deleteData',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '删除数据',\n insertText: 'btnClick.deleteData(data)',\n range,\n },\n {\n label: 'refreshTableData',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '获取数据',\n insertText: 'btnClick.refreshTableData()',\n range,\n },\n {\n label: 'routerPush',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '获取数据',\n insertText:\n 'btnClick.routerPush(路由name, router.push除了name的参数)',\n range,\n },\n ],\n };\n }\n\n // 也可以为 data. 提示\n const dataMatch = /data\\.(\\w*)$/.exec(textUntilPosition);\n if (dataMatch) {\n return {\n suggestions: Object.keys((window as any).mockData || {}).map(\n (key) => ({\n label: key,\n kind: monaco.languages.CompletionItemKind.Property,\n documentation: 'data 的属性',\n insertText: key,\n range,\n }),\n ),\n };\n }\n\n return { suggestions: [] };\n },\n });\n};\n\n/**\n * 获取默认值\n */\nconst getDefaultValue = (): string => {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n if (newLang === 'json') {\n if (typeof props.detail.defaultValue === 'object') {\n return JSON.stringify(props.detail.defaultValue);\n }\n\n return props.detail.defaultValue || '';\n }\n\n return props.detail.defaultValue as string;\n};\n\nlet mainLoaded = false;\nlet dialogLoaded = false;\n\nconst initMainEditor = async () => {\n if (mainLoaded || !mainEditor.value) return;\n await initEditor(mainEditor.value, (instance) => {\n mainEditorInstance.value = instance;\n });\n mainLoaded = true;\n};\n\nconst openDialog = async () => {\n showDialog.value = true;\n if (dialogLoaded) return;\n await nextTick();\n await initEditor(dialogEditor.value!, (instance) => {\n dialogEditorInstance.value = instance;\n });\n dialogLoaded = true;\n};\n\nconst initEditor = async (\n container: HTMLElement,\n setInstance: (instance: monaco.editor.IStandaloneCodeEditor) => void,\n) => {\n const lang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n\n await registerLanguage(lang);\n\n if (!model.value) {\n let val: string = '';\n if (lang === 'json' && typeof props.value === 'object') {\n val = JSON.stringify(props.value, null, 2);\n } else if (typeof props.value === 'string') {\n val = props.value;\n }\n model.value = monaco.editor.createModel(val, lang);\n }\n\n if (lang === 'javascript') {\n monaco.languages.typescript.javascriptDefaults.addExtraLib(\n `\nconst data = {};\nconst rowIndex = 0;\nconst btnClick = {\n openForm: function(data, rowIndex) {},\n closeForm: function() {},\n getData: function() {}\n};\n`,\n 'extra:context.d.ts',\n );\n }\n\n const getEditorTheme = (lang: SupportedLanguage, dark: boolean): string => {\n if (lang === 'vue') {\n return dark ? 'vue-dark' : 'vue-light';\n }\n if (lang === 'java') {\n return dark ? 'java-dark' : 'java-light';\n }\n return dark ? 'vs-dark' : 'vs';\n };\n\n const instance = monaco.editor.create(container, {\n model: model.value,\n theme: getEditorTheme(lang, isDark.value),\n automaticLayout: true,\n readOnly: props.detail.disabled === true,\n suggest: {\n showKeywords: true,\n showFunctions: true,\n },\n quickSuggestions: {\n other: true,\n strings: true,\n },\n tabSize: 4,\n });\n\n setInstance(instance);\n\n instance.onDidChangeModelContent(() => {\n const value = model.value?.getValue();\n if (value !== undefined && value !== props.value) {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n try {\n if (newLang === 'json') {\n emit('update:value', JSON.parse(value));\n } else {\n emit('update:value', value);\n }\n } catch {\n // JSON 解析失败时不 emit\n }\n }\n });\n\n initCodeTips();\n};\n\n// 组件挂载后初始化主编辑器\nnextTick(() => {\n initMainEditor();\n});\n\n// 监听主题变化\nwatch(isDark, (dark) => {\n const lang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n let theme = dark ? 'vs-dark' : 'vs';\n if (lang === 'vue') {\n theme = dark ? 'vue-dark' : 'vue-light';\n } else if (lang === 'java') {\n theme = dark ? 'java-dark' : 'java-light';\n }\n if (mainEditorInstance.value) {\n monaco.editor.setTheme(theme);\n }\n});\n\n// ✅ 5. 监听语言切换(在 model 存在后才执行)\nwatch(\n () => props.detail,\n async () => {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n if (model.value) {\n await registerLanguage(newLang);\n monaco.editor.setModelLanguage(model.value, newLang);\n }\n },\n { deep: true },\n);\n\n// ✅ 6. 监听 value 变化(确保 model 已创建)\nwatch(\n () => props.value,\n (newVal) => {\n if (!model.value) return;\n\n if (isEmpty(newVal)) {\n if (isNotEmpty(model.value.getValue())) {\n model.value.setValue('');\n }\n if (isNotEmpty(props.detail.defaultValue)) {\n const defaultValue = getDefaultValue();\n model.value.setValue(defaultValue);\n }\n return;\n }\n\n const currentValue = model.value.getValue();\n\n let nextValue = '';\n\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n\n if (newLang === 'json' && typeof newVal === 'object') {\n try {\n nextValue = JSON.stringify(newVal, null, 2);\n } catch {\n return;\n }\n } else if (typeof newVal === 'string') {\n nextValue = newVal;\n }\n\n // ✅ 避免重复 setValue\n if (nextValue !== currentValue) {\n model.value.setValue(nextValue || '');\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (mainEditorInstance.value) {\n mainEditorInstance.value.dispose();\n mainEditorInstance.value = null;\n }\n if (dialogEditorInstance.value) {\n dialogEditorInstance.value.dispose();\n dialogEditorInstance.value = null;\n }\n if (model.value) {\n model.value.dispose();\n model.value = null;\n }\n});\n\nconst maxHeight = computed(() => {\n if (props.detail?.componentParams?.maxLine) {\n const em = props.detail?.componentParams?.maxLine * 1.4;\n return `${em}em`;\n }\n\n return '24em';\n});\n</script>\n<template>\n <div class=\"container\">\n <div class=\"code-preview\">\n <p v-if=\"detail.componentParams?.prefix\" class=\"code-prefix\">\n {{ detail.componentParams.prefix }}\n </p>\n <div\n ref=\"mainEditor\"\n class=\"main-editor\"\n :style=\"{ height: maxHeight }\"\n ></div>\n <p v-if=\"detail.componentParams?.suffix\" class=\"code-suffix\">\n {{ detail.componentParams.suffix }}\n </p>\n <el-button\n class=\"expand-btn\"\n :icon=\"FullScreen\"\n circle\n size=\"small\"\n @click=\"openDialog\"\n />\n </div>\n <el-dialog\n v-model=\"showDialog\"\n append-to-body\n align-center\n center\n width=\"80%\"\n class=\"code-editor-dialog\"\n >\n <div class=\"dialog-container\">\n <p v-if=\"detail.componentParams?.prefix\" class=\"code-prefix\">\n {{ detail.componentParams.prefix }}\n </p>\n <div ref=\"dialogEditor\" class=\"dialog-editor\"></div>\n <p v-if=\"detail.componentParams?.suffix\" class=\"code-suffix\">\n {{ detail.componentParams.suffix }}\n </p>\n </div>\n </el-dialog>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.container {\n width: 100%;\n height: 100%;\n padding: 0;\n}\n.code-preview {\n position: relative;\n width: 100%;\n height: 100%;\n}\n.code-prefix,\n.code-suffix {\n margin: 0;\n padding: 4px 8px;\n font-size: 12px;\n color: var(--el-text-color-secondary);\n background: var(--el-fill-color-light);\n border: 1px solid var(--el-border-color);\n font-family: monospace;\n white-space: pre-wrap;\n}\n.code-prefix {\n border-bottom: none;\n border-radius: var(--el-border-radius-base) var(--el-border-radius-base) 0 0;\n}\n.code-suffix {\n border-top: none;\n border-radius: 0 0 var(--el-border-radius-base) var(--el-border-radius-base);\n}\n.main-editor {\n width: 100%;\n border-radius: var(--el-border-radius-base);\n overflow: hidden;\n border: 1px solid var(--el-border-color);\n}\n.code-prefix + .main-editor {\n border-radius: 0;\n}\n.main-editor:has(+ .code-suffix) {\n border-radius: var(--el-border-radius-base) var(--el-border-radius-base) 0 0;\n}\n.code-prefix + .main-editor:has(+ .code-suffix) {\n border-radius: 0;\n}\n.expand-btn {\n position: absolute;\n top: 4px;\n right: 4px;\n z-index: 10;\n}\n.dialog-container {\n width: 100%;\n height: 100%;\n padding: 0;\n}\n.dialog-editor {\n width: 100%;\n border-radius: var(--el-border-radius-base);\n overflow: hidden;\n height: 80vh;\n border: 1px solid var(--el-border-color);\n}\n</style>\n\n<style lang=\"scss\">\n/* 弹窗样式覆盖 - 减少内边距 */\n.code-editor-dialog {\n .el-dialog__body {\n padding: 8px 12px 12px;\n }\n}\n</style>\n","import FormCodeEditor from './FormCodeEditor.vue';\nimport type { App } from 'vue';\n\n(FormCodeEditor as any).name = 'FormCodeEditor';\n\nFormCodeEditor.install = (app: App) => {\n app.component('FormCodeEditor', FormCodeEditor);\n};\n\nexport { FormCodeEditor };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\n</script>\n\n<template>\n <el-divider v-bind=\"detail.componentParams\">\n {{ detail.placeholder }}\n </el-divider>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\n</script>\n\n<template>\n <el-divider v-bind=\"detail.componentParams\">\n {{ detail.placeholder }}\n </el-divider>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import FormDivider from './FormDivider.vue';\nimport type { App } from 'vue';\n\n(FormDivider as any).name = 'FormDivider';\n\nFormDivider.install = (app: App) => {\n app.component('FormDivider', FormDivider);\n};\n\nexport { FormDivider };\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\n\nimport { ArrowDown, ArrowRight } from '@element-plus/icons-vue';\n\nconst props = withDefaults(\n defineProps<{\n /** 是否显示边框 */\n bordered?: boolean;\n /** 是否可折叠 */\n collapsible?: boolean;\n /** 是否禁用 */\n disabled?: boolean;\n /** 是否展开(v-model) */\n modelValue?: boolean;\n /** 标题 */\n title?: string;\n }>(),\n {\n title: '',\n collapsible: false,\n modelValue: true,\n bordered: true,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void;\n (e: 'change', value: boolean): void;\n}>();\n\nconst internalExpanded = ref(true);\n\nconst isExpanded = computed({\n get: () => props.modelValue ?? internalExpanded.value,\n set: (val) => {\n internalExpanded.value = val;\n emit('update:modelValue', val);\n emit('change', val);\n },\n});\n\nconst toggle = () => {\n if (props.collapsible && !props.disabled) {\n isExpanded.value = !isExpanded.value;\n }\n};\n\nconst legendClass = computed(() => ({\n 'fieldset-legend': true,\n 'fieldset-legend--collapsible': props.collapsible && !props.disabled,\n 'fieldset-legend--disabled': props.disabled,\n}));\n</script>\n\n<template>\n <fieldset\n class=\"fieldset\"\n :class=\"{\n 'fieldset--bordered': bordered,\n 'fieldset--collapsed': !isExpanded,\n }\"\n >\n <legend v-if=\"title || $slots.title\" :class=\"legendClass\" @click=\"toggle\">\n <span v-if=\"collapsible\" class=\"fieldset-arrow\">\n <el-icon>\n <ArrowDown v-if=\"isExpanded\" />\n <ArrowRight v-else />\n </el-icon>\n </span>\n <slot name=\"title\">{{ title }}</slot>\n </legend>\n <el-collapse-transition>\n <div v-show=\"isExpanded\" class=\"fieldset-content\">\n <slot></slot>\n </div>\n </el-collapse-transition>\n </fieldset>\n</template>\n\n<style scoped lang=\"scss\">\n.fieldset {\n margin: 0;\n padding: 0;\n border: none;\n min-width: 0;\n\n &--bordered {\n border: 1px solid var(--el-border-color);\n border-radius: var(--el-border-radius-base);\n padding: 12px;\n }\n\n &--collapsed.fieldset--bordered {\n padding-bottom: 0;\n }\n}\n\n.fieldset-legend {\n padding: 0 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--el-text-color-primary);\n display: inline-flex;\n align-items: center;\n gap: 4px;\n\n &--collapsible {\n cursor: pointer;\n user-select: none;\n\n &:hover {\n color: var(--el-color-primary);\n }\n }\n\n &--disabled {\n cursor: not-allowed;\n color: var(--el-text-color-disabled);\n\n &:hover {\n color: var(--el-text-color-disabled);\n }\n }\n}\n\n.fieldset-arrow {\n display: inline-flex;\n align-items: center;\n transition: transform 0.3s;\n}\n\n.fieldset-content {\n overflow: hidden;\n}\nt-collapse-enter-active,\n.fieldset-collapse-leave-active {\n transition: all 0.3s ease;\n}\n\n.fieldset-collapse-enter-from,\n.fieldset-collapse-leave-to {\n opacity: 0;\n max-height: 0;\n}\n\n.fieldset-collapse-enter-to,\n.fieldset-collapse-leave-from {\n opacity: 1;\n max-height: 1000px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\n\nimport { ArrowDown, ArrowRight } from '@element-plus/icons-vue';\n\nconst props = withDefaults(\n defineProps<{\n /** 是否显示边框 */\n bordered?: boolean;\n /** 是否可折叠 */\n collapsible?: boolean;\n /** 是否禁用 */\n disabled?: boolean;\n /** 是否展开(v-model) */\n modelValue?: boolean;\n /** 标题 */\n title?: string;\n }>(),\n {\n title: '',\n collapsible: false,\n modelValue: true,\n bordered: true,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void;\n (e: 'change', value: boolean): void;\n}>();\n\nconst internalExpanded = ref(true);\n\nconst isExpanded = computed({\n get: () => props.modelValue ?? internalExpanded.value,\n set: (val) => {\n internalExpanded.value = val;\n emit('update:modelValue', val);\n emit('change', val);\n },\n});\n\nconst toggle = () => {\n if (props.collapsible && !props.disabled) {\n isExpanded.value = !isExpanded.value;\n }\n};\n\nconst legendClass = computed(() => ({\n 'fieldset-legend': true,\n 'fieldset-legend--collapsible': props.collapsible && !props.disabled,\n 'fieldset-legend--disabled': props.disabled,\n}));\n</script>\n\n<template>\n <fieldset\n class=\"fieldset\"\n :class=\"{\n 'fieldset--bordered': bordered,\n 'fieldset--collapsed': !isExpanded,\n }\"\n >\n <legend v-if=\"title || $slots.title\" :class=\"legendClass\" @click=\"toggle\">\n <span v-if=\"collapsible\" class=\"fieldset-arrow\">\n <el-icon>\n <ArrowDown v-if=\"isExpanded\" />\n <ArrowRight v-else />\n </el-icon>\n </span>\n <slot name=\"title\">{{ title }}</slot>\n </legend>\n <el-collapse-transition>\n <div v-show=\"isExpanded\" class=\"fieldset-content\">\n <slot></slot>\n </div>\n </el-collapse-transition>\n </fieldset>\n</template>\n\n<style scoped lang=\"scss\">\n.fieldset {\n margin: 0;\n padding: 0;\n border: none;\n min-width: 0;\n\n &--bordered {\n border: 1px solid var(--el-border-color);\n border-radius: var(--el-border-radius-base);\n padding: 12px;\n }\n\n &--collapsed.fieldset--bordered {\n padding-bottom: 0;\n }\n}\n\n.fieldset-legend {\n padding: 0 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--el-text-color-primary);\n display: inline-flex;\n align-items: center;\n gap: 4px;\n\n &--collapsible {\n cursor: pointer;\n user-select: none;\n\n &:hover {\n color: var(--el-color-primary);\n }\n }\n\n &--disabled {\n cursor: not-allowed;\n color: var(--el-text-color-disabled);\n\n &:hover {\n color: var(--el-text-color-disabled);\n }\n }\n}\n\n.fieldset-arrow {\n display: inline-flex;\n align-items: center;\n transition: transform 0.3s;\n}\n\n.fieldset-content {\n overflow: hidden;\n}\nt-collapse-enter-active,\n.fieldset-collapse-leave-active {\n transition: all 0.3s ease;\n}\n\n.fieldset-collapse-enter-from,\n.fieldset-collapse-leave-to {\n opacity: 0;\n max-height: 0;\n}\n\n.fieldset-collapse-enter-to,\n.fieldset-collapse-leave-from {\n opacity: 1;\n max-height: 1000px;\n}\n</style>\n","import FormFieldset from './FormFieldset.vue';\nimport type { App } from 'vue';\n\n(FormFieldset as any).name = 'FormFieldset';\n\nFormFieldset.install = (app: App) => {\n app.component('FormFieldset', FormFieldset);\n};\n\nexport { FormFieldset };\n","<script setup lang=\"ts\">\nimport type { FormDynamicTableProp } from '@/types';\n\nimport { onMounted, onUnmounted, reactive, ref } from 'vue';\nimport { VueDraggable } from 'vue-draggable-plus';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any[];\n detail: FormDynamicTableProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => [],\n mittId: () => null,\n});\n// const emits = defineEmits([\n// 'getComponentValue',\n// 'valueChange',\n// 'setShow',\n// ]);\n\nconst modelValue = defineModel('value');\n\nconst state = reactive<any>({\n value: [],\n visible: false,\n frame: {},\n length_: 0,\n tableData: [],\n});\n\nconst modalOpen = ref(false);\nlet oldValue = '';\n\nconst showModal = () => {\n modalOpen.value = true;\n if (Array.isArray(modelValue.value)) {\n oldValue = JSON.stringify(modelValue.value);\n state.value = modelValue.value;\n }\n};\n\n/** 增加行 */\nconst addX = () => {\n state.value.push({});\n};\n\n/**\n * 删除行\n *\n * @param index\n */\nconst deleteX = (index: number) => {\n state.value.splice(index, 1);\n};\n\n/** 当值发生变化时 */\nconst handleChange = () => {\n modelValue.value = state.value;\n modalOpen.value = false;\n};\n\n/** 取消数据修改 */\nconst handleCancel = () => {\n state.value = JSON.parse(oldValue);\n modalOpen.value = false;\n};\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n modelValue.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <div>\n <el-button @click=\"showModal\"> 编辑 </el-button>\n <el-dialog\n v-model=\"modalOpen\"\n :close-on-click-modal=\"false\"\n :show-close=\"false\"\n append-to-body\n :width=\"detail.componentParams?.width || '90%'\"\n >\n <template #footer>\n <el-button type=\"primary\" @click=\"handleChange\"> 确认 </el-button>\n <el-button danger @click=\"handleCancel\"> 取消 </el-button>\n </template>\n\n <VueDraggable\n v-model=\"state.value\"\n :animation=\"150\"\n target=\".el-table__body-wrapper tbody\"\n >\n <el-table\n v-if=\"\n detail.componentParams.column &&\n detail.componentParams.column.length > 0\n \"\n :data=\"state.value\"\n max-height=\"90vh\"\n style=\"width: 100%\"\n >\n <el-table-column\n v-for=\"(item, index) in detail.componentParams.column\"\n :key=\"index\"\n :label=\"item.title\"\n :min-width=\"item.width > 0 ? item.width : 60\"\n :prop=\"item.field\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </el-table-column>\n\n <el-table-column label=\"添加\" :width=\"72\" fixed=\"right\">\n <template #header>\n <el-button size=\"small\" type=\"primary\" @click=\"addX\">\n 添加\n </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button\n size=\"small\"\n type=\"danger\"\n @click=\"deleteX(scope.$index)\"\n >\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n <el-table\n v-else-if=\"\n props.detail.componentParams?.column &&\n Array.isArray(props.detail.componentParams?.column)\n \"\n :data=\"state.value\"\n max-height=\"380\"\n style=\"width: 100%\"\n >\n <el-table-column\n v-for=\"(item, index) in detail.componentParams?.column\"\n :key=\"index\"\n :label=\"item.title\"\n :prop=\"item.field\"\n :width=\"item.width > 0 ? item.width : 60\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </el-table-column>\n\n <el-table-column label=\"添加\" :width=\"72\" fixed=\"right\">\n <template #header>\n <el-button size=\"small\" @click=\"addX\"> 添加 </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n </VueDraggable>\n </el-dialog>\n </div>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormDynamicTableProp } from '@/types';\n\nimport { onMounted, onUnmounted, reactive, ref } from 'vue';\nimport { VueDraggable } from 'vue-draggable-plus';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any[];\n detail: FormDynamicTableProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => [],\n mittId: () => null,\n});\n// const emits = defineEmits([\n// 'getComponentValue',\n// 'valueChange',\n// 'setShow',\n// ]);\n\nconst modelValue = defineModel('value');\n\nconst state = reactive<any>({\n value: [],\n visible: false,\n frame: {},\n length_: 0,\n tableData: [],\n});\n\nconst modalOpen = ref(false);\nlet oldValue = '';\n\nconst showModal = () => {\n modalOpen.value = true;\n if (Array.isArray(modelValue.value)) {\n oldValue = JSON.stringify(modelValue.value);\n state.value = modelValue.value;\n }\n};\n\n/** 增加行 */\nconst addX = () => {\n state.value.push({});\n};\n\n/**\n * 删除行\n *\n * @param index\n */\nconst deleteX = (index: number) => {\n state.value.splice(index, 1);\n};\n\n/** 当值发生变化时 */\nconst handleChange = () => {\n modelValue.value = state.value;\n modalOpen.value = false;\n};\n\n/** 取消数据修改 */\nconst handleCancel = () => {\n state.value = JSON.parse(oldValue);\n modalOpen.value = false;\n};\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n modelValue.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <div>\n <el-button @click=\"showModal\"> 编辑 </el-button>\n <el-dialog\n v-model=\"modalOpen\"\n :close-on-click-modal=\"false\"\n :show-close=\"false\"\n append-to-body\n :width=\"detail.componentParams?.width || '90%'\"\n >\n <template #footer>\n <el-button type=\"primary\" @click=\"handleChange\"> 确认 </el-button>\n <el-button danger @click=\"handleCancel\"> 取消 </el-button>\n </template>\n\n <VueDraggable\n v-model=\"state.value\"\n :animation=\"150\"\n target=\".el-table__body-wrapper tbody\"\n >\n <el-table\n v-if=\"\n detail.componentParams.column &&\n detail.componentParams.column.length > 0\n \"\n :data=\"state.value\"\n max-height=\"90vh\"\n style=\"width: 100%\"\n >\n <el-table-column\n v-for=\"(item, index) in detail.componentParams.column\"\n :key=\"index\"\n :label=\"item.title\"\n :min-width=\"item.width > 0 ? item.width : 60\"\n :prop=\"item.field\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </el-table-column>\n\n <el-table-column label=\"添加\" :width=\"72\" fixed=\"right\">\n <template #header>\n <el-button size=\"small\" type=\"primary\" @click=\"addX\">\n 添加\n </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button\n size=\"small\"\n type=\"danger\"\n @click=\"deleteX(scope.$index)\"\n >\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n <el-table\n v-else-if=\"\n props.detail.componentParams?.column &&\n Array.isArray(props.detail.componentParams?.column)\n \"\n :data=\"state.value\"\n max-height=\"380\"\n style=\"width: 100%\"\n >\n <el-table-column\n v-for=\"(item, index) in detail.componentParams?.column\"\n :key=\"index\"\n :label=\"item.title\"\n :prop=\"item.field\"\n :width=\"item.width > 0 ? item.width : 60\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </el-table-column>\n\n <el-table-column label=\"添加\" :width=\"72\" fixed=\"right\">\n <template #header>\n <el-button size=\"small\" @click=\"addX\"> 添加 </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n </VueDraggable>\n </el-dialog>\n </div>\n</template>\n\n<style scoped></style>\n","import FormDynamicTable from './FormDynamicTable.vue';\nimport type { App } from 'vue';\n\n(FormDynamicTable as any).name = 'FormDynamicTable';\n\nFormDynamicTable.install = (app: App) => {\n app.component('FormDynamicTable', FormDynamicTable);\n};\n\nexport { FormDynamicTable };\n","<script setup lang=\"ts\">\nimport { VueDraggable } from 'vue-draggable-plus';\n\ninterface TableColumn {\n field: string;\n title: string;\n width: number;\n editor: any;\n [key: string]: any;\n}\n\ninterface Props {\n value?: any[];\n column: TableColumn[];\n}\n\nwithDefaults(defineProps<Props>(), {\n value: () => [],\n});\n\nconst tableValue = defineModel('value', {\n required: false,\n default: (): any[] => [],\n type: Array,\n});\n\n/** 增加行 */\nconst addX = () => {\n tableValue.value = [...tableValue.value, {}];\n};\n/**\n * 删除行\n *\n * @param index\n */\nconst deleteX = (index: number) => {\n const data = tableValue.value;\n data.splice(index, 1);\n};\n</script>\n\n<template>\n <VueDraggable\n v-model=\"tableValue\"\n :animation=\"150\"\n target=\".el-table__body-wrapper tbody\"\n >\n <ElTable\n v-if=\"column && column.length > 0\"\n :data=\"tableValue\"\n max-height=\"90vh\"\n style=\"width: 100%\"\n >\n <ElTableColumn\n v-for=\"(item, index) in column\"\n :key=\"index\"\n :label=\"item.title\"\n :min-width=\"item.width > 0 ? item.width : 60\"\n :prop=\"item.field\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </ElTableColumn>\n\n <ElTableColumn :width=\"72\" fixed=\"right\" label=\"添加\">\n <template #header>\n <el-button size=\"small\" type=\"primary\" @click=\"addX\">\n 添加\n </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" type=\"danger\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </ElTableColumn>\n </ElTable>\n <ElTable\n v-else-if=\"column && Array.isArray(column)\"\n :data=\"value\"\n max-height=\"380\"\n style=\"width: 100%\"\n >\n <ElTableColumn\n v-for=\"(item, index) in column\"\n :key=\"index\"\n :label=\"item.title\"\n :prop=\"item.field\"\n :width=\"item.width > 0 ? item.width : 60\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </ElTableColumn>\n\n <ElTableColumn :width=\"72\" fixed=\"right\" label=\"添加\">\n <template #header>\n <el-button size=\"small\" @click=\"addX\"> 添加 </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </ElTableColumn>\n </ElTable>\n </VueDraggable>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport { VueDraggable } from 'vue-draggable-plus';\n\ninterface TableColumn {\n field: string;\n title: string;\n width: number;\n editor: any;\n [key: string]: any;\n}\n\ninterface Props {\n value?: any[];\n column: TableColumn[];\n}\n\nwithDefaults(defineProps<Props>(), {\n value: () => [],\n});\n\nconst tableValue = defineModel('value', {\n required: false,\n default: (): any[] => [],\n type: Array,\n});\n\n/** 增加行 */\nconst addX = () => {\n tableValue.value = [...tableValue.value, {}];\n};\n/**\n * 删除行\n *\n * @param index\n */\nconst deleteX = (index: number) => {\n const data = tableValue.value;\n data.splice(index, 1);\n};\n</script>\n\n<template>\n <VueDraggable\n v-model=\"tableValue\"\n :animation=\"150\"\n target=\".el-table__body-wrapper tbody\"\n >\n <ElTable\n v-if=\"column && column.length > 0\"\n :data=\"tableValue\"\n max-height=\"90vh\"\n style=\"width: 100%\"\n >\n <ElTableColumn\n v-for=\"(item, index) in column\"\n :key=\"index\"\n :label=\"item.title\"\n :min-width=\"item.width > 0 ? item.width : 60\"\n :prop=\"item.field\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </ElTableColumn>\n\n <ElTableColumn :width=\"72\" fixed=\"right\" label=\"添加\">\n <template #header>\n <el-button size=\"small\" type=\"primary\" @click=\"addX\">\n 添加\n </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" type=\"danger\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </ElTableColumn>\n </ElTable>\n <ElTable\n v-else-if=\"column && Array.isArray(column)\"\n :data=\"value\"\n max-height=\"380\"\n style=\"width: 100%\"\n >\n <ElTableColumn\n v-for=\"(item, index) in column\"\n :key=\"index\"\n :label=\"item.title\"\n :prop=\"item.field\"\n :width=\"item.width > 0 ? item.width : 60\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </ElTableColumn>\n\n <ElTableColumn :width=\"72\" fixed=\"right\" label=\"添加\">\n <template #header>\n <el-button size=\"small\" @click=\"addX\"> 添加 </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </ElTableColumn>\n </ElTable>\n </VueDraggable>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import DynamicMapTable from './DynamicMapTable.vue';\nimport type { App } from 'vue';\n\n(DynamicMapTable as any).name = 'DynamicMapTable';\n\nDynamicMapTable.install = (app: App) => {\n app.component('DynamicMapTable', DynamicMapTable);\n};\n\nexport { DynamicMapTable };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormFrame } from '@/types';\n\nimport { reactive } from 'vue';\n\nimport QuestionSVG from '@/assets/question.svg';\nimport { FormDivider } from '../../FormDivider';\nimport { FormFieldset } from '../../FormFieldset';\n\ninterface Props {\n frame: FormFrame;\n showComponents: any;\n formSpan: number;\n formRules?: any;\n data: any;\n mittId: number;\n getComponentValue: Function;\n setShow: Function;\n}\n\nwithDefaults(defineProps<Props>(), {\n formRules: {},\n});\n\nconst dataRef = defineModel('data', {\n type: Object as PropType<any>,\n default: () => {},\n});\n\nconst fieldsetModel = reactive<any>({});\n</script>\n\n<template>\n <FormFieldset\n :name=\"frame.field\"\n :title=\"frame.title\"\n :collapsible=\"true\"\n v-model:model-value=\"fieldsetModel[frame.field]\"\n >\n <ElRowPlus :gutter=\"6\">\n <template v-for=\"item in frame.children\" :key=\"item.field\">\n <template v-if=\"item.formEditor === 'FormFieldset'\">\n <ElColPlus\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <FormAreaRender\n v-model:data=\"dataRef\"\n :frame=\"item\"\n :show-components=\"showComponents\"\n :form-span=\"formSpan\"\n :mitt-id=\"mittId\"\n :get-component-value=\"getComponentValue\"\n :set-show=\"setShow\"\n />\n </ElColPlus>\n </template>\n <template v-else>\n <template v-if=\"showComponents[item.field] !== false\">\n <ElColPlus\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <template v-if=\"item.formEditor === 'KeFormDivider'\">\n <FormDivider :detail=\"item\" />\n </template>\n <template v-else>\n <el-form-item\n :label=\"item.title\"\n :prop=\"item.field\"\n :rules=\"formRules?.[item.field] ? formRules[item.field] : []\"\n :label-width=\"item.labelWidth ? item.labelWidth : undefined\"\n class=\"form-item-label\"\n >\n <template v-if=\"item.placeholder\" #label>\n {{ item.title }}\n <el-tooltip :content=\"item.placeholder\">\n <div class=\"label-question\">\n <img :src=\"QuestionSVG\" alt=\"\" />\n </div>\n </el-tooltip>\n </template>\n\n <component\n :is=\"item.formEditor\"\n v-model:value=\"dataRef[item.field]\"\n :detail=\"item\"\n :disabled=\"item.disabled\"\n :field-name=\"item.field\"\n :field-title=\"item.title\"\n :mitt-id=\"mittId\"\n style=\"width: 100%\"\n @get-component-value=\"getComponentValue\"\n @set-show=\"setShow\"\n />\n </el-form-item>\n </template>\n </ElColPlus>\n </template>\n </template>\n </template>\n </ElRowPlus>\n </FormFieldset>\n</template>\n\n<style scoped lang=\"scss\">\n.form-item-label {\n :deep(.el-form-item__label) {\n font-weight: normal;\n }\n}\n\n.label-question {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormFrame } from '@/types';\n\nimport { reactive } from 'vue';\n\nimport QuestionSVG from '@/assets/question.svg';\nimport { FormDivider } from '../../FormDivider';\nimport { FormFieldset } from '../../FormFieldset';\n\ninterface Props {\n frame: FormFrame;\n showComponents: any;\n formSpan: number;\n formRules?: any;\n data: any;\n mittId: number;\n getComponentValue: Function;\n setShow: Function;\n}\n\nwithDefaults(defineProps<Props>(), {\n formRules: {},\n});\n\nconst dataRef = defineModel('data', {\n type: Object as PropType<any>,\n default: () => {},\n});\n\nconst fieldsetModel = reactive<any>({});\n</script>\n\n<template>\n <FormFieldset\n :name=\"frame.field\"\n :title=\"frame.title\"\n :collapsible=\"true\"\n v-model:model-value=\"fieldsetModel[frame.field]\"\n >\n <ElRowPlus :gutter=\"6\">\n <template v-for=\"item in frame.children\" :key=\"item.field\">\n <template v-if=\"item.formEditor === 'FormFieldset'\">\n <ElColPlus\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <FormAreaRender\n v-model:data=\"dataRef\"\n :frame=\"item\"\n :show-components=\"showComponents\"\n :form-span=\"formSpan\"\n :mitt-id=\"mittId\"\n :get-component-value=\"getComponentValue\"\n :set-show=\"setShow\"\n />\n </ElColPlus>\n </template>\n <template v-else>\n <template v-if=\"showComponents[item.field] !== false\">\n <ElColPlus\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <template v-if=\"item.formEditor === 'KeFormDivider'\">\n <FormDivider :detail=\"item\" />\n </template>\n <template v-else>\n <el-form-item\n :label=\"item.title\"\n :prop=\"item.field\"\n :rules=\"formRules?.[item.field] ? formRules[item.field] : []\"\n :label-width=\"item.labelWidth ? item.labelWidth : undefined\"\n class=\"form-item-label\"\n >\n <template v-if=\"item.placeholder\" #label>\n {{ item.title }}\n <el-tooltip :content=\"item.placeholder\">\n <div class=\"label-question\">\n <img :src=\"QuestionSVG\" alt=\"\" />\n </div>\n </el-tooltip>\n </template>\n\n <component\n :is=\"item.formEditor\"\n v-model:value=\"dataRef[item.field]\"\n :detail=\"item\"\n :disabled=\"item.disabled\"\n :field-name=\"item.field\"\n :field-title=\"item.title\"\n :mitt-id=\"mittId\"\n style=\"width: 100%\"\n @get-component-value=\"getComponentValue\"\n @set-show=\"setShow\"\n />\n </el-form-item>\n </template>\n </ElColPlus>\n </template>\n </template>\n </template>\n </ElRowPlus>\n </FormFieldset>\n</template>\n\n<style scoped lang=\"scss\">\n.form-item-label {\n :deep(.el-form-item__label) {\n font-weight: normal;\n }\n}\n\n.label-question {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n</style>\n","import type { ModelRef, Reactive, Ref } from 'vue';\n\nimport type { FormFrame } from '@/types';\n\nimport { computed, watch, watchEffect } from 'vue';\n\nimport { emitter, isNotEmpty } from '@/utils';\n\n/**\n * 把平摊的表单frame拆分成二级树结构\n * @param treeFrameData 格式化后的响应式对象\n */\nexport const useFrameFormat = (treeFrameData: Ref) => {\n const frameFormat = (data: any[]) => {\n treeFrameData.value = convertAreaToFieldset(data);\n };\n return { frameFormat };\n};\n\ninterface FormRenderParams {\n frame: Ref<FormFrame[]>;\n frameFormat: Function;\n data: Ref<any>;\n componentShowRule: Ref<any>;\n showComponents: Reactive<any>;\n mittId: number;\n pageId: ModelRef<number>;\n rowKey: string;\n}\n\nexport const useFormRender = (params: FormRenderParams) => {\n const {\n frame,\n frameFormat,\n data,\n componentShowRule,\n showComponents,\n mittId,\n pageId,\n rowKey,\n } = params;\n\n // 监听frame,要随时处理frame分解\n watch(\n () => frame.value,\n (newValue) => {\n frameFormat(newValue);\n },\n { deep: true },\n );\n\n /**\n * 设置显示\n * @param params\n */\n const setShow = (params: {\n fieldName: string;\n isShow: boolean | undefined;\n }) => {\n // 不为空且为布尔才配置\n if (isNotEmpty(params.fieldName) && typeof params.isShow === 'boolean') {\n showComponents[params.fieldName] = params.isShow;\n } else {\n console.warn(`参数异常${JSON.stringify(params)}`);\n }\n };\n\n /**\n * 广播字段映射表\n * {\n * a: [\"xx\", \"bb\"]\n * }\n * 当a字段变化时 就要通知xx和bb字段\n */\n const noticeFieldMap = computed(() => {\n const newMap: any = {};\n frame.value.forEach((frame: FormFrame) => {\n newMap[frame.field] = frame.noticeField;\n });\n return newMap;\n });\n\n /**\n * 广播那些字段\n * @param fieldName\n */\n const noticeFieldChange = (fieldName: string) => {\n const noticeFieldList = noticeFieldMap.value[fieldName];\n if (Array.isArray(noticeFieldList)) {\n noticeFieldList.forEach((field: string) => {\n emitter.emit(field + mittId, data.value);\n });\n }\n };\n\n // 执行显示规则方法\n const execShowFunc = (key: string) => {\n if (componentShowRule.value?.[key]) {\n componentShowRule.value[key](data.value, setShow);\n }\n noticeFieldChange(key);\n };\n\n // formData旧值缓存\n const oldValueCacheMap: any = {};\n\n /**\n * 初始化表单变量\n * @param formData\n */\n const initForm = (formData: any) => {\n // 先初始化执行一次watchEffect的内容\n for (const key in formData) {\n if (Object.prototype.hasOwnProperty.call(formData, key)) {\n const val = formData[key];\n execShowFunc(key);\n // 初始化缓存\n oldValueCacheMap[key] = val;\n }\n }\n };\n\n // 表单字段key的数量\n // let keyNum = 0;\n // 监听props.data变化触发显示内容\n watchEffect(() => {\n // if (keyNum !== Object.keys(data.value).length) {\n // // 当监听到表单字段key数量改变时,执行初始化表单变量\n // keyNum = Object.keys(data.value).length;\n // initForm(data.value);\n // return;\n // }\n for (const key in data.value) {\n if (Object.prototype.hasOwnProperty.call(data.value, key)) {\n const val = data.value[key];\n // 如果oldValueCacheMap\n if (oldValueCacheMap[key] !== val) {\n execShowFunc(key);\n oldValueCacheMap[key] = val;\n }\n }\n }\n });\n\n /**\n * 子组件通过父组件获取其他组件的值\n *\n * @param array\n * @param callback\n */\n const getComponentValue = (array: [string], callback: Function) => {\n const map: any = {};\n for (const element of array) {\n if (data.value) {\n if (Array.isArray(data.value[element])) {\n if (data.value[element].length === 0) {\n map[element] = null;\n } else {\n const arr = data.value[element];\n map[element] = arr[arr.length - 1];\n }\n } else {\n map[element] = data.value[element];\n }\n }\n }\n\n map.pageId = pageId.value;\n if (data.value[rowKey]) {\n map.dataId = data.value[rowKey];\n }\n\n callback(map);\n };\n\n return { setShow, initForm, getComponentValue };\n};\n\n/**\n * 将平面的 FormAreaStart 和 FormAreaEnd 结构转换成嵌套的 KeFormFieldset 树状结构\n * @param data 平面数据\n * @returns 树状嵌套数据\n */\nexport const convertAreaToFieldset = (data: any[]): any[] => {\n const result: any[] = [];\n const stack: any[] = [];\n\n for (const item of data) {\n // 跳过空值\n if (!item) continue;\n if (item.formEditor === 'FormAreaStart') {\n // 创建 KeFormFieldset 节点,保留原始属性\n const fieldsetNode = {\n ...item,\n formEditor: 'FormFieldset',\n children: [],\n };\n\n // 如果栈为空,添加到结果数组;否则添加到栈顶元素的 children\n if (stack.length === 0) {\n result.push(fieldsetNode);\n } else {\n stack[stack.length - 1].children.push(fieldsetNode);\n }\n\n // 将当前节点压入栈\n stack.push(fieldsetNode);\n } else if (item.formEditor === 'FormAreaEnd') {\n // 遇到结束标记,弹出栈顶元素\n stack.pop();\n } else {\n // 普通字段\n if (stack.length === 0) {\n // 不在任何区域内,直接添加到结果\n result.push({ ...item });\n } else {\n // 在区域内,添加到栈顶元素的 children\n stack[stack.length - 1].children.push({ ...item });\n }\n }\n }\n\n return result;\n};\n","<script setup lang=\"ts\">\n// import { htmlToPDF } from \"#/utils/html2Util\";\nimport type { FormInstance, FormRules } from 'element-plus';\n\nimport type { PropType } from 'vue';\n\nimport type {\n FormBasicInterface,\n FormEmbeddedTableProp,\n FormFrame,\n} from '@/types';\n\nimport { computed, onMounted, reactive, ref, useTemplateRef } from 'vue';\n\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\nimport QuestionSVG from '@/assets/question.svg';\nimport { FormDivider } from '../FormDivider';\nimport { msgTips, formCheck } from '@/utils';\n\nimport FormAreaRender from './components/FormAreaRender.vue';\nimport { useFormRender, useFrameFormat } from './hooks/formRender.hook';\nimport { ElColPlus, ElRowPlus } from '@/components';\n\ninterface Props {\n isLoading?: boolean;\n data?: Record<string, any>;\n config: FormBasicInterface; // 保持你的类型名\n frame: FormFrame[];\n formRules?: FormRules<any>;\n pageId?: any;\n embeddedTableList?: FormEmbeddedTableProp[];\n formSaveVerifyJs?: Function | null;\n componentShowRule?: Record<string, any>;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n isLoading: false,\n data: () => ({}),\n formRules: () => ({}),\n pageId: undefined,\n embeddedTableList: () => [],\n formSaveVerifyJs: null,\n componentShowRule: () => ({}),\n});\n\nconst ruleFormRef = useTemplateRef<FormInstance>('ruleFormRef');\n\nconst pageIdRef = defineModel('pageId', {\n type: Number,\n required: false,\n default: undefined,\n});\nconst dataRef = defineModel('data', {\n type: Object as PropType<any>,\n default: () => {},\n});\nconst frameRef = defineModel('frame', {\n required: true,\n type: Array as PropType<FormFrame[]>,\n});\nconst componentShowRuleModel = defineModel('componentShowRule', {\n required: false,\n type: Object as PropType<any>,\n default: () => {},\n});\n\n// 此表单广播ID\nconst mittId = Math.floor(Math.random() * (99_999 - 10_000 + 1)) + 10_000;\n\nconst formWrapperRef = useTemplateRef<HTMLDivElement>('formWrapperRef')\nconst debouncedWidth = ref(0);\nuseResizeObserver(\n formWrapperRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedWidth.value = entry.contentRect.width;\n }\n }, 150),\n);\n\nconst formSpan = computed(() => {\n if (props.config.span) {\n return props.config.span;\n }\n if (props.config.responsive === false) {\n return 24;\n }\n if (debouncedWidth.value >= 1920) {\n return 6;\n } else if (debouncedWidth.value >= 1200) {\n return 6;\n } else if (debouncedWidth.value >= 992) {\n return 8;\n } else if (debouncedWidth.value >= 768) {\n return 12;\n } else if (debouncedWidth.value >= 600) {\n return 12;\n }\n return 24;\n});\n\n/** 表单验证 通过返回true 没有验证通过返回false */\nconst validateForm = async (): Promise<boolean> => {\n if (ruleFormRef.value === undefined || ruleFormRef.value === null) return false;\n\n // 不为空 则执行表单验证js\n if (props.formSaveVerifyJs !== null && props.formSaveVerifyJs !== undefined) {\n const err = props.formSaveVerifyJs(props.data);\n if (err) {\n msgTips.alert({\n msg: err,\n type: 'warning',\n });\n return false;\n }\n }\n return await formCheck(ruleFormRef.value);\n};\n\n// 清除验证\nconst clearValidate = () => {};\n\n// 重置表单\nconst resetFields = () => {\n ruleFormRef.value?.resetFields();\n};\n\n/** 打印为PDF */\nconst exportPDF = () => {\n // htmlToPDF(\n // formRenderRef,\n // props.data.datatitle,\n // {\n // scale: 3,\n // useCORS: true,\n // allowTaint: true\n // },\n // true,\n // new Date().toDateString()\n // );\n};\n\n// formData旧值缓存\nconst showComponents = reactive<any>({});\n\n/**\n * 树形框架数据\n */\nconst treeFrameData = ref<FormFrame[]>([]);\n\nconst { frameFormat } = useFrameFormat(treeFrameData);\n\nconst { setShow, initForm, getComponentValue } = useFormRender({\n frame: frameRef,\n frameFormat,\n data: dataRef,\n componentShowRule: componentShowRuleModel,\n showComponents,\n mittId,\n pageId: pageIdRef,\n rowKey: props.config.rowKey,\n});\n\ndefineExpose({\n validateForm,\n clearValidate,\n resetFields,\n exportPDF,\n initForm,\n});\n\nonMounted(() => {\n frameFormat(props.frame);\n});\n</script>\n\n<template>\n <div ref=\"formWrapperRef\" class=\"w-full h-full\">\n <el-form\n ref=\"ruleFormRef\"\n :label-position=\"config.labelPosition ? config.labelPosition : 'right'\"\n :label-width=\"\n config.labelWidth && config.labelWidth > 0 ? config.labelWidth : undefined\n \"\n :model=\"data\"\n :rules=\"formRules\"\n :style=\"{\n height:\n props.embeddedTableList && props.embeddedTableList.length > 0\n ? '60%'\n : '100%',\n }\"\n v-loading=\"isLoading\"\n >\n <ElRowPlus :gutter=\"6\">\n <template v-for=\"item in treeFrameData\" :key=\"item.field\">\n <ElColPlus\n v-if=\"item.formEditor === 'FormFieldset'\"\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <FormAreaRender\n v-model:data=\"dataRef\"\n :frame=\"item\"\n :show-components=\"showComponents\"\n :form-span=\"formSpan\"\n :mitt-id=\"mittId\"\n :get-component-value=\"getComponentValue\"\n :set-show=\"setShow\"\n />\n </ElColPlus>\n <ElColPlus\n v-else-if=\"showComponents[item.field] !== false\"\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <template v-if=\"item.formEditor === 'KeFormDivider'\">\n <FormDivider :detail=\"item\" />\n </template>\n <template v-else>\n <el-form-item\n :label=\"item.title\"\n :prop=\"item.field\"\n :rules=\"formRules?.[item.field] ? formRules[item.field] : []\"\n :label-width=\"item.labelWidth ? item.labelWidth : undefined\"\n class=\"form-item-label\"\n >\n <template v-if=\"item.placeholder\" #label>\n {{ item.title }}\n <el-tooltip :content=\"item.placeholder\">\n <div class=\"label-question\">\n <img :src=\"QuestionSVG\" alt=\"\" />\n </div>\n </el-tooltip>\n </template>\n\n <component\n :is=\"item.formEditor\"\n v-model:value=\"dataRef[item.field]\"\n :detail=\"item\"\n :disabled=\"item.disabled\"\n :field-name=\"item.field\"\n :field-title=\"item.title\"\n :mitt-id=\"mittId\"\n style=\"width: 100%\"\n @get-component-value=\"getComponentValue\"\n @set-show=\"setShow\"\n />\n </el-form-item>\n </template>\n </ElColPlus>\n </template>\n </ElRowPlus>\n </el-form>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.form-item-label {\n :deep(.el-form-item__label) {\n font-weight: normal;\n }\n}\n\n.label-question {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n</style>\n","<script setup lang=\"ts\">\n// import { htmlToPDF } from \"#/utils/html2Util\";\nimport type { FormInstance, FormRules } from 'element-plus';\n\nimport type { PropType } from 'vue';\n\nimport type {\n FormBasicInterface,\n FormEmbeddedTableProp,\n FormFrame,\n} from '@/types';\n\nimport { computed, onMounted, reactive, ref, useTemplateRef } from 'vue';\n\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\nimport QuestionSVG from '@/assets/question.svg';\nimport { FormDivider } from '../FormDivider';\nimport { msgTips, formCheck } from '@/utils';\n\nimport FormAreaRender from './components/FormAreaRender.vue';\nimport { useFormRender, useFrameFormat } from './hooks/formRender.hook';\nimport { ElColPlus, ElRowPlus } from '@/components';\n\ninterface Props {\n isLoading?: boolean;\n data?: Record<string, any>;\n config: FormBasicInterface; // 保持你的类型名\n frame: FormFrame[];\n formRules?: FormRules<any>;\n pageId?: any;\n embeddedTableList?: FormEmbeddedTableProp[];\n formSaveVerifyJs?: Function | null;\n componentShowRule?: Record<string, any>;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n isLoading: false,\n data: () => ({}),\n formRules: () => ({}),\n pageId: undefined,\n embeddedTableList: () => [],\n formSaveVerifyJs: null,\n componentShowRule: () => ({}),\n});\n\nconst ruleFormRef = useTemplateRef<FormInstance>('ruleFormRef');\n\nconst pageIdRef = defineModel('pageId', {\n type: Number,\n required: false,\n default: undefined,\n});\nconst dataRef = defineModel('data', {\n type: Object as PropType<any>,\n default: () => {},\n});\nconst frameRef = defineModel('frame', {\n required: true,\n type: Array as PropType<FormFrame[]>,\n});\nconst componentShowRuleModel = defineModel('componentShowRule', {\n required: false,\n type: Object as PropType<any>,\n default: () => {},\n});\n\n// 此表单广播ID\nconst mittId = Math.floor(Math.random() * (99_999 - 10_000 + 1)) + 10_000;\n\nconst formWrapperRef = useTemplateRef<HTMLDivElement>('formWrapperRef')\nconst debouncedWidth = ref(0);\nuseResizeObserver(\n formWrapperRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedWidth.value = entry.contentRect.width;\n }\n }, 150),\n);\n\nconst formSpan = computed(() => {\n if (props.config.span) {\n return props.config.span;\n }\n if (props.config.responsive === false) {\n return 24;\n }\n if (debouncedWidth.value >= 1920) {\n return 6;\n } else if (debouncedWidth.value >= 1200) {\n return 6;\n } else if (debouncedWidth.value >= 992) {\n return 8;\n } else if (debouncedWidth.value >= 768) {\n return 12;\n } else if (debouncedWidth.value >= 600) {\n return 12;\n }\n return 24;\n});\n\n/** 表单验证 通过返回true 没有验证通过返回false */\nconst validateForm = async (): Promise<boolean> => {\n if (ruleFormRef.value === undefined || ruleFormRef.value === null) return false;\n\n // 不为空 则执行表单验证js\n if (props.formSaveVerifyJs !== null && props.formSaveVerifyJs !== undefined) {\n const err = props.formSaveVerifyJs(props.data);\n if (err) {\n msgTips.alert({\n msg: err,\n type: 'warning',\n });\n return false;\n }\n }\n return await formCheck(ruleFormRef.value);\n};\n\n// 清除验证\nconst clearValidate = () => {};\n\n// 重置表单\nconst resetFields = () => {\n ruleFormRef.value?.resetFields();\n};\n\n/** 打印为PDF */\nconst exportPDF = () => {\n // htmlToPDF(\n // formRenderRef,\n // props.data.datatitle,\n // {\n // scale: 3,\n // useCORS: true,\n // allowTaint: true\n // },\n // true,\n // new Date().toDateString()\n // );\n};\n\n// formData旧值缓存\nconst showComponents = reactive<any>({});\n\n/**\n * 树形框架数据\n */\nconst treeFrameData = ref<FormFrame[]>([]);\n\nconst { frameFormat } = useFrameFormat(treeFrameData);\n\nconst { setShow, initForm, getComponentValue } = useFormRender({\n frame: frameRef,\n frameFormat,\n data: dataRef,\n componentShowRule: componentShowRuleModel,\n showComponents,\n mittId,\n pageId: pageIdRef,\n rowKey: props.config.rowKey,\n});\n\ndefineExpose({\n validateForm,\n clearValidate,\n resetFields,\n exportPDF,\n initForm,\n});\n\nonMounted(() => {\n frameFormat(props.frame);\n});\n</script>\n\n<template>\n <div ref=\"formWrapperRef\" class=\"w-full h-full\">\n <el-form\n ref=\"ruleFormRef\"\n :label-position=\"config.labelPosition ? config.labelPosition : 'right'\"\n :label-width=\"\n config.labelWidth && config.labelWidth > 0 ? config.labelWidth : undefined\n \"\n :model=\"data\"\n :rules=\"formRules\"\n :style=\"{\n height:\n props.embeddedTableList && props.embeddedTableList.length > 0\n ? '60%'\n : '100%',\n }\"\n v-loading=\"isLoading\"\n >\n <ElRowPlus :gutter=\"6\">\n <template v-for=\"item in treeFrameData\" :key=\"item.field\">\n <ElColPlus\n v-if=\"item.formEditor === 'FormFieldset'\"\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <FormAreaRender\n v-model:data=\"dataRef\"\n :frame=\"item\"\n :show-components=\"showComponents\"\n :form-span=\"formSpan\"\n :mitt-id=\"mittId\"\n :get-component-value=\"getComponentValue\"\n :set-show=\"setShow\"\n />\n </ElColPlus>\n <ElColPlus\n v-else-if=\"showComponents[item.field] !== false\"\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <template v-if=\"item.formEditor === 'KeFormDivider'\">\n <FormDivider :detail=\"item\" />\n </template>\n <template v-else>\n <el-form-item\n :label=\"item.title\"\n :prop=\"item.field\"\n :rules=\"formRules?.[item.field] ? formRules[item.field] : []\"\n :label-width=\"item.labelWidth ? item.labelWidth : undefined\"\n class=\"form-item-label\"\n >\n <template v-if=\"item.placeholder\" #label>\n {{ item.title }}\n <el-tooltip :content=\"item.placeholder\">\n <div class=\"label-question\">\n <img :src=\"QuestionSVG\" alt=\"\" />\n </div>\n </el-tooltip>\n </template>\n\n <component\n :is=\"item.formEditor\"\n v-model:value=\"dataRef[item.field]\"\n :detail=\"item\"\n :disabled=\"item.disabled\"\n :field-name=\"item.field\"\n :field-title=\"item.title\"\n :mitt-id=\"mittId\"\n style=\"width: 100%\"\n @get-component-value=\"getComponentValue\"\n @set-show=\"setShow\"\n />\n </el-form-item>\n </template>\n </ElColPlus>\n </template>\n </ElRowPlus>\n </el-form>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.form-item-label {\n :deep(.el-form-item__label) {\n font-weight: normal;\n }\n}\n\n.label-question {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n</style>\n","import FormRender from './FormRender.vue';\nimport type { App } from 'vue';\n\n(FormRender as any).name = 'FormRender';\n\nFormRender.install = (app: App) => {\n app.component('FormRender', FormRender);\n};\n\nexport { FormRender };\n","import type { translateJSON, translateObj } from '@/types';\n\nimport { isEmpty } from '@/utils';\n\ninterface FormatterOptions {\n /** 表格数据 */\n cellValue: any;\n tabObj?: translateObj;\n translateJson: translateJSON;\n fieldName: string;\n /**\n * 翻译后的数据缓存 // 配合formatterData.array食用\n */\n translateObject?: any;\n /**\n * 循环索引\n */\n translateIndexArray?: { [propName: string]: any };\n}\n\n/**\n * 格式化grid-table数据\n *\n * @param options\n */\nexport const tableDataFormatter = (options: FormatterOptions): any => {\n if (isEmpty(options.cellValue)) return options.cellValue;\n\n const { translateJson, cellValue, fieldName } = options;\n\n // 1. 空值检查\n if (!translateJson) return cellValue;\n\n // 2. 类型守卫:排除数组情况,确保它是对象结构\n if (!Array.isArray(translateJson)) {\n // 此时 TS 知道 translateJson 是 { [propName: string]: any }\n // 如果 cellValue 可能是对象/复杂类型,建议转为字符串作为 key\n const key = String(cellValue);\n return translateJson[key] ?? cellValue;\n }\n\n // 3. 如果是数组,按数组逻辑处理(如 find)\n // 这里根据你的业务需求决定如何处理数组类型的 translateJson\n const item = translateJson.find(i => i.value == cellValue);\n return item?.label ?? cellValue;\n};\n","// 存储已经注册的模式化id\nimport { VxeUI } from 'vxe-table';\n\nimport { tableDataFormatter } from '@/components/FormComponent/hooks/useColumnRender.hook';\n\nconst hasFormats: any[] = [];\n// 存储注册的方法\nconst formatsMethods: any = {};\n\nexport const useTableFormats = () => {\n /**\n * 注册全局格式化\n * @param id\n * @param options\n */\n const register = (id: string, options: any) => {\n // console.log(\"注册格式化ID:\" + id);\n // 如果已经存在则不注册\n if (hasFormats.includes(id)) {\n return;\n }\n\n let translateJson: any = {};\n if (Array.isArray(options.translateJson)) {\n options.translateJson.forEach((item: any) => {\n translateJson[item.value] = item.label;\n });\n } else {\n translateJson = options.translateJson;\n }\n\n VxeUI.formats.add(id, {\n tableCellFormatMethod({ cellValue, column }) {\n return tableDataFormatter({\n cellValue,\n fieldName: column.field,\n tabObj: options.tabObj,\n translateJson,\n });\n },\n });\n formatsMethods[id] = ({ cellValue, column }: any) => {\n return tableDataFormatter({\n cellValue,\n fieldName: column.field,\n tabObj: options.tabObj,\n translateJson: options.translate,\n });\n };\n // 添加进已注册列表\n hasFormats.push(id);\n };\n\n const registerGeneralMethods = (id: string, func: Function) => {\n formatsMethods[id] = func;\n VxeUI.formats.add(id, {\n tableCellFormatMethod: (c) => { return func(c) },\n });\n };\n\n return {\n register,\n registerGeneralMethods,\n };\n};\n","import type { KeButton } from '@/types';\n\n/**\n * 拆分成toolbar按钮和数据上的按钮\n *\n * @param buttonList\n * @param buttonParams\n * @param funcModule\n */\nexport const useSplitApiButton = (\n buttonList: KeButton[],\n buttonParams: any,\n funcModule: Record<string, Function>,\n) => {\n const toolButtons: KeButton[] = [];\n const rowButtons: KeButton[] = [];\n\n buttonList.forEach((button) => {\n button.params = buttonParams;\n if (button.webTrigger) {\n button.webFunction = funcModule[button.id];\n }\n if (button.tableRow === true) {\n rowButtons.push(button);\n } else {\n toolButtons.push(button);\n }\n });\n\n return { toolButtons, rowButtons };\n};\n","import type { ModelRef, Ref, ShallowRef } from 'vue';\n\nimport type { AnyFunction, AutoSortTableDTO, BtnFunction, PagePath, Pagination } from '@/types';\n\nimport type { TableConfigInterface } from '@/types';\nimport type { CacheValue } from '@/types';\n\nimport { ref } from 'vue';\n\nimport { VxeUI } from 'vxe-table';\n\nimport { getEmbeddedTableDataApi } from '@/api';\nimport {\n changTableSortApi,\n deleteTableDataApi,\n getTableDataApi,\n getTreeTableDataApi,\n} from '@/api';\nimport { defaultPageTableConfig } from '@/config';\nimport { useTableFormats } from '@/hooks/useTableFormats.hook';\nimport { getRegisterComponent } from '@/config';\nimport { isEmpty, isNotEmpty, msgTips } from '@/utils';\n\nimport { useSplitApiButton } from '../hooks/useSplitApiButton';\nimport { appRouter } from '@/config';\n\n// 已经注册的格式化列表\nlet formatterKeyList: any[] = [];\n\ntype TableFormatterType = {\n columns: any[];\n pageId: number;\n};\n\nconst { register } = useTableFormats();\n\nexport const initTableFormatter = (data: TableFormatterType) => {\n // 先清除此页面的格式化缓存\n if (formatterKeyList.length > 0) {\n formatterKeyList.forEach((key) => {\n VxeUI.formats.delete(key);\n });\n formatterKeyList = [];\n }\n const registerComponent = getRegisterComponent();\n\n data.columns.forEach((col) => {\n // 注册格式化\n columnFormatter(col, data.pageId);\n if (col.editRender && registerComponent) {\n registerComponent(col.editRender?.name);\n }\n });\n\n return data.columns;\n};\n\nconst columnFormatter = (column: any, pageId: number) => {\n if (isNotEmpty(column.tabObj)) {\n if (column.tabObj === 'translate') {\n register(pageId + column.field, {\n tabObj: column.tabObj,\n translateJson: column.translate,\n });\n column.formatter = pageId + column.field;\n } else {\n column.formatter = column.tabObj;\n }\n }\n\n if (column.children && column.children.length > 0) {\n for (let i = 0; i < column.children.length; ++i) {\n columnFormatter(column.children[i], pageId);\n }\n }\n};\n\n/**\n * 拖拽结束前回调\n * @param event\n * @param pageId\n * @param key\n */\nconst dragEndMethod = async (\n event: any,\n pageId: number,\n key: any,\n): Promise<boolean> => {\n if (event.dragPos === 'bottom') {\n msgTips.tips({\n msg: '只能向上拖拽哦!',\n type: 'warning',\n });\n return false;\n }\n\n const params: AutoSortTableDTO = {\n pageId,\n upData: event.oldRow[key].toString(),\n bottomData: event.newRow[key].toString(),\n };\n const result = await changTableSortApi(params);\n return result.code === 0;\n};\n/**\n * 处理从后端获取的tableRender\n * @param data\n * @param pageId\n * @param btnClickFunc\n * @param funcModule 方法对象\n * @param treeLazyLoad\n */\nexport const useConfigurationProcess = (\n data: any,\n pageId: number,\n btnClickFunc: Record<string, AnyFunction>,\n funcModule: BtnFunction,\n treeLazyLoad?: (...args: any) => void,\n): CacheValue => {\n const newTablePageConfig: CacheValue = { ...defaultPageTableConfig };\n\n // // 加工表格frame\n newTablePageConfig.gridOptions.columns = initTableFormatter({\n columns: data.tableFrame,\n pageId,\n });\n\n // 如果是tree 则需要设置树节点\n if (\n data.tableConfig.tree &&\n newTablePageConfig.gridOptions.columns.length >= 2\n ) {\n const col1 = newTablePageConfig.gridOptions.columns[1];\n if (col1 !== null && col1 !== undefined) {\n col1.treeNode = true;\n newTablePageConfig.gridOptions.columns[1] = col1;\n }\n\n // 配置表格的树配置\n newTablePageConfig.gridOptions.treeConfig = {\n transform: true,\n rowField: data.tableConfig.rowKey,\n parentField: data.tableConfig.parentField,\n lazy: true,\n hasChildField: 'has_tree_child',\n loadMethod({ row }) {\n return new Promise<any[]>((resolve) => {\n // 调用你的 treeLazyLoad,把 resolve 传进去\n if (treeLazyLoad) {\n treeLazyLoad(\n row,\n (data: any[]) => {\n // 当 syncTableData 内部调用 resolve(data) 时,\n // 这个 data 会作为 Promise 的结果返回给 vxe-table\n resolve(data || []);\n },\n {}, // 确保 queryData 有定义,比如来自外部 props 或变量\n );\n }\n });\n },\n };\n } else {\n newTablePageConfig.gridOptions.treeConfig = undefined;\n }\n\n // 设置拖拽排序相关\n if (data.tableConfig.dragSort) {\n // 设置允许拖拽\n newTablePageConfig.gridOptions.rowConfig = {\n drag: true,\n };\n // 设置拖拽回调\n newTablePageConfig.gridOptions.rowDragConfig = {\n dragEndMethod: async (event: any) =>\n dragEndMethod(event, pageId, data.tableConfig.rowKey),\n };\n }\n\n btnClickFunc[\"getPageId\"] = () => {\n return pageId;\n }\n // 对按钮分组\n const { toolButtons, rowButtons } = useSplitApiButton(\n data.tableButton,\n btnClickFunc,\n funcModule,\n );\n newTablePageConfig.tableToolButtons = toolButtons;\n newTablePageConfig.tableRowButtons = rowButtons;\n\n return newTablePageConfig;\n};\n\ninterface RequestTable {\n pageId: ModelRef<number | undefined>\n queryTreeFilter: ShallowRef;\n /**\n * 分页\n */\n pagination: Ref<Pagination>;\n /**\n * 弹窗实例\n */\n appFormWindowRef: Ref;\n /**\n * 嵌入页面ID\n */\n embeddedId?: number;\n /**\n * 页面嵌入路径\n */\n pagePath?: PagePath[];\n}\n\n/**\n * 获取/刷新表格数据\n * @param params\n */\nexport function useTableData(params: RequestTable) {\n const {\n queryTreeFilter,\n pagination,\n appFormWindowRef,\n embeddedId,\n pagePath,\n pageId,\n } = params;\n\n const tableConfig = ref<TableConfigInterface>({} as TableConfigInterface);\n const loading = ref(false);\n const tableData = ref<any[]>([]);\n let queryDataLib: any = {};\n\n const getTableData = async (queryData?: any, callback?: () => void) => {\n if (isEmpty(tableConfig.value.pageId)) {\n return;\n }\n loading.value = true;\n\n // 查询数据\n if (queryData) queryDataLib = queryData;\n\n /**\n * 若存在queryTreeFilter 则去获取queryTreeFilter的查询内容\n */\n if (queryTreeFilter.value && tableConfig.value.parentField) {\n const filterData = queryTreeFilter.value.getCheckboxes();\n queryDataLib[tableConfig.value.parentField] = {\n val: filterData.val,\n queryType: 'hasAny',\n };\n }\n\n const result = await getTableDataApi(\n tableConfig.value.pageId,\n pagination.value.currentPage,\n queryDataLib,\n );\n loading.value = false;\n if (result.code === 0) {\n if (callback) {\n callback();\n }\n return result.data;\n // tableData.value = result.data.tableData;\n // pagination.value.pageSize = result.data.pageSize;\n // pagination.value.total = result.data.total;\n }\n\n return null;\n };\n const getEmbeddedTableData = async (\n queryData?: any,\n callback?: () => void,\n ) => {\n if (isEmpty(tableConfig.value.pageId)) {\n return;\n }\n loading.value = true;\n // 查询数据\n if (queryData) queryDataLib = queryData;\n\n /**\n * 若存在queryTreeFilter 则去获取queryTreeFilter的查询内容\n */\n if (queryTreeFilter.value && tableConfig.value.parentField) {\n const filterData = queryTreeFilter.value.getCheckboxes();\n queryDataLib[tableConfig.value.parentField] = {\n val: filterData.val,\n queryType: 'hasAny',\n };\n }\n\n let result;\n if (embeddedId && Array.isArray(pagePath)) {\n result = await getEmbeddedTableDataApi({\n embeddedId,\n pageNum: pagination.value.currentPage,\n pagePaths: pagePath,\n queryData: queryDataLib,\n });\n } else {\n msgTips.alert({\n msg: !embeddedId ? '数据结构异常,未获取到嵌入表ID' : '渲染结构pagePath异常',\n type: 'error'\n });\n result = {\n code: 0,\n data: []\n };\n }\n\n\n\n loading.value = false;\n if (result.code === 0) {\n if (callback) {\n callback();\n }\n return result.data;\n }\n\n return null;\n };\n const getTableTreeData = async (\n queryData?: any,\n callback?: ((data: any) => void) | undefined,\n parentNodeData?: any,\n ) => {\n if (\n isEmpty(tableConfig.value.parentField) ||\n isEmpty(tableConfig.value.pageId)\n ) {\n return;\n }\n loading.value = true;\n // 查询数据\n if (queryData) queryDataLib = queryData;\n\n // 如果不存在父节点需要设置默认值\n if (!queryDataLib[tableConfig.value.parentField]) {\n queryDataLib[tableConfig.value.parentField] = {\n val: parentNodeData || tableConfig.value.treeDefault,\n queryType: 'equals',\n };\n }\n\n const parentId = parentNodeData || tableConfig.value.treeDefault;\n\n // 获取tree懒加载数据\n const result = await getTreeTableDataApi(\n tableConfig.value.pageId,\n parentId,\n queryDataLib,\n );\n if (result.code === 0) {\n if (callback) {\n callback(result.data);\n } else {\n tableData.value = result.data;\n }\n }\n\n loading.value = false;\n };\n\n /**\n * 刷新/获取数据\n */\n const syncTableData = async (\n queryData?: any,\n callback?: AnyFunction,\n parentNodeData?: any,\n ) => {\n if (tableConfig.value.tree) {\n if (\n parentNodeData &&\n parentNodeData[tableConfig.value.rowKey] &&\n tableConfig.value.parentField\n ) {\n if (!queryData) {\n queryData = {};\n }\n queryData[tableConfig.value.parentField] = {\n val: parentNodeData[tableConfig.value.rowKey],\n queryType: 'equals',\n };\n }\n await getTableTreeData(queryData, callback);\n } else {\n const result: any = await (embeddedId\n ? getEmbeddedTableData(queryData, callback)\n : getTableData(queryData, callback));\n tableData.value = result.tableData;\n pagination.value.pageSize = result.pageSize;\n pagination.value.total = result.total;\n }\n };\n\n const btnClickFunc = {\n getConfig: () => {\n return {\n pageId,\n tableConfig,\n pagePath,\n }\n },\n openForm: (data: any, rowIndex: number, render?: AnyFunction) => {\n // 默认传参\n const params = {\n dataId: data[tableConfig.value.rowKey],\n pageId: pageId.value,\n };\n\n // 如果是函数,则从次获取数据\n if (typeof render === 'function') {\n const renderData = render(data);\n\n // 若有数据ID 则赋值\n if (renderData.dataId) {\n params.dataId = renderData.dataId;\n }\n\n // 若有页面ID 则赋值\n if (renderData.pageId) {\n params.pageId = renderData.pageId;\n }\n }\n\n appFormWindowRef.value.openForm({\n rowKey: params.dataId,\n pageId: params.pageId,\n rowIndex,\n });\n },\n deleteData: async (data: any) => {\n if (!tableConfig.value.deleteBtn) {\n msgTips.tips({\n msg: '尚未开启删除功能!',\n type: 'warning',\n });\n return;\n }\n if (isEmpty(pageId.value)) {\n return;\n }\n loading.value = true;\n const result = await deleteTableDataApi(\n pageId.value,\n data[tableConfig.value.rowKey].toString(),\n );\n if (result.code === 0) {\n await syncTableData();\n }\n loading.value = false;\n },\n refreshTableData: async () => {\n await syncTableData();\n },\n routerPush: (key: any, options: any) => {\n appRouter.push(key, options);\n },\n };\n\n return {\n tableData,\n queryDataLib,\n syncTableData,\n btnClickFunc,\n tableConfig,\n pageId,\n };\n}\n\ntype UpdateDataByRow = {\n rowIndex: number;\n tableConfig: Ref<TableConfigInterface>;\n tableData: Ref<any[]>;\n};\n/**\n * 更新指定行的数据\n * @param params\n */\nexport async function updateDataByRowIndex(params: UpdateDataByRow) {\n const { rowIndex, tableConfig, tableData } = params;\n if (isEmpty(tableConfig.value.pageId)) {\n return;\n }\n\n /**\n * 获取主键\n */\n const rowKey: string = tableConfig.value.rowKey;\n const rowData = tableData.value[rowIndex];\n\n /**\n * 构建查询\n */\n const queryDataLib: any = {};\n queryDataLib[rowKey] = {\n val: rowData[rowKey],\n queryType: 'equals',\n };\n\n const result = await getTableDataApi(\n tableConfig.value.pageId,\n 1,\n queryDataLib,\n );\n if (result.code === 0) {\n tableData.value[rowIndex] = result.data.tableData[0];\n }\n}\n","<script setup lang=\"ts\">\nimport type { PagePath } from '@/types';\n\nimport { reactive, ref } from 'vue';\n\nimport AppFormRender from '../../AppFormRender.vue';\n\ninterface Props {\n pageId: number;\n embeddedId: number;\n pagePath: PagePath[];\n}\n\nwithDefaults(defineProps<Props>(), {});\n\nconst emits = defineEmits(['dataChange']);\n\nconst AppFormRenderRef = ref();\nconst dialogState = ref(false);\nconst pageState = reactive({\n embeddedId: 0,\n dataId: '',\n});\n\n/**\n * 当前数据在表格的索引\n */\nlet onDataRowIndex = -1;\n\nconst dataChange = () => {\n emits('dataChange', onDataRowIndex);\n};\n\ninterface OpenForm {\n /**\n * 主键\n */\n rowKey: any;\n /**\n * 页面ID\n */\n embeddedId: number;\n /**\n * 行数\n */\n rowIndex: number;\n}\n\n/**\n * 打开抽屉\n *\n * @param params\n */\nconst openForm = (params: OpenForm) => {\n const isAdd = typeof params.rowKey === 'boolean';\n pageState.dataId = isAdd ? 'new' : params.rowKey;\n pageState.embeddedId = params.embeddedId;\n dialogState.value = true;\n onDataRowIndex = params.rowIndex;\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\n};\n\nconst close = () => {\n dialogState.value = false;\n};\n\ndefineExpose({ openForm });\n</script>\n\n<template>\n <el-dialog\n v-model=\"dialogState\"\n :show-close=\"false\"\n width=\"78%\"\n append-to-body\n destroy-on-close\n draggable\n align-center\n >\n <div class=\"dia-container\">\n <AppFormRender\n ref=\"AppFormRenderRef\"\n v-model:data-id=\"pageState.dataId\"\n :embedded-id=\"embeddedId\"\n :page-id=\"pageId\"\n :page-path=\"pagePath\"\n :show-window-button=\"false\"\n @close=\"close\"\n @data-change=\"dataChange\"\n />\n </div>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.dia-container {\n height: calc(100vh - 220px);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PagePath } from '@/types';\n\nimport { reactive, ref } from 'vue';\n\nimport AppFormRender from '../../AppFormRender.vue';\n\ninterface Props {\n pageId: number;\n embeddedId: number;\n pagePath: PagePath[];\n}\n\nwithDefaults(defineProps<Props>(), {});\n\nconst emits = defineEmits(['dataChange']);\n\nconst AppFormRenderRef = ref();\nconst dialogState = ref(false);\nconst pageState = reactive({\n embeddedId: 0,\n dataId: '',\n});\n\n/**\n * 当前数据在表格的索引\n */\nlet onDataRowIndex = -1;\n\nconst dataChange = () => {\n emits('dataChange', onDataRowIndex);\n};\n\ninterface OpenForm {\n /**\n * 主键\n */\n rowKey: any;\n /**\n * 页面ID\n */\n embeddedId: number;\n /**\n * 行数\n */\n rowIndex: number;\n}\n\n/**\n * 打开抽屉\n *\n * @param params\n */\nconst openForm = (params: OpenForm) => {\n const isAdd = typeof params.rowKey === 'boolean';\n pageState.dataId = isAdd ? 'new' : params.rowKey;\n pageState.embeddedId = params.embeddedId;\n dialogState.value = true;\n onDataRowIndex = params.rowIndex;\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\n};\n\nconst close = () => {\n dialogState.value = false;\n};\n\ndefineExpose({ openForm });\n</script>\n\n<template>\n <el-dialog\n v-model=\"dialogState\"\n :show-close=\"false\"\n width=\"78%\"\n append-to-body\n destroy-on-close\n draggable\n align-center\n >\n <div class=\"dia-container\">\n <AppFormRender\n ref=\"AppFormRenderRef\"\n v-model:data-id=\"pageState.dataId\"\n :embedded-id=\"embeddedId\"\n :page-id=\"pageId\"\n :page-path=\"pagePath\"\n :show-window-button=\"false\"\n @close=\"close\"\n @data-change=\"dataChange\"\n />\n </div>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.dia-container {\n height: calc(100vh - 220px);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PagePath, Pagination, KeButton, TableQueryFrame } from '@/types';\n\nimport { onMounted, ref, useTemplateRef } from 'vue';\n\nimport {\n getEmbeddedTableDataApi,\n getEmbeddedTableRenderApi,\n onValueChangeApi,\n} from '@/api';\nimport { BASE_URL, defaultPageTableConfig } from '@/config';\nimport { getRandomString, msgTips } from '@/utils';\n\nimport {\n useConfigurationProcess,\n useTableData,\n} from '../../hooks/useTable.hook';\nimport EmbeddedDialogForm from './EmbeddedDialogForm.vue';\nimport { QueryTreeFilter } from '@/components/QueryComponent/QueryTreeFilter'\n\ninterface Props {\n embeddedId: number;\n pagePath: PagePath[];\n}\n\ninterface QueryTreeFilter {\n getCheckboxes: Function;\n}\n\nconst props = withDefaults(defineProps<Props>(), {});\n\nconst pageId = defineModel<number>('embeddedId')\n\nconst loading = ref(false);\nconst gridOptions = ref<any>({});\nconst queryTreeFilter = useTemplateRef<QueryTreeFilter>('queryTreeFilter');\nconst appFormWindowRef = useTemplateRef('appFormWindowRef');\n// 表格列\nconst columns = ref<any[]>([]);\nconst queryConfig = ref<TableQueryFrame[]>([]);\nconst tableToolButtons = ref<KeButton[]>([]);\nconst tableRowButtons = ref<KeButton[]>([]);\n\nconst tablePagination = ref<Pagination>({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n});\n\nconst { tableData, syncTableData, btnClickFunc, tableConfig } =\n useTableData({\n pageId,\n queryTreeFilter,\n pagination: tablePagination,\n appFormWindowRef,\n embeddedId: props.embeddedId,\n pagePath: props.pagePath,\n });\n\n/**\n * 指定行数据更新\n * @param rowIndex\n */\nconst onDataChange = async (rowIndex: number) => {\n if (rowIndex < 0 || !rowIndex) {\n await syncTableData();\n return;\n }\n loading.value = true;\n const data = tableData.value[rowIndex];\n\n const queryLib: any = {};\n queryLib[tableConfig.value.rowKey] = {\n val: data[tableConfig.value.rowKey],\n queryType: 'equals',\n };\n const result = await getEmbeddedTableDataApi({\n embeddedId: props.embeddedId,\n pageNum: tablePagination.value.currentPage,\n pagePaths: props.pagePath,\n queryData: queryLib,\n });\n if (result.code === 0 && result.data.tableData.length > 0) {\n tableData.value[rowIndex] = result.data.tableData[0];\n }\n loading.value = false;\n};\n\n/**\n * 当检测到值改变\n * @param fieldName\n * @param newValue\n * @param rowId\n */\nconst onValueChange = async (\n fieldName: string,\n newValue: any,\n rowId: string,\n) => {\n loading.value = true;\n const result = await onValueChangeApi({\n pagePaths: props.pagePath,\n tablePageId: tableConfig.value.pageId,\n fieldName,\n newValue,\n rowId,\n });\n if (result.code === 0) {\n msgTips.tips({\n type: 'success',\n msg: '修改成功!',\n });\n }\n loading.value = false;\n};\n\nconst getEmbeddedTableConfig = async () => {\n loading.value = true;\n const result = await getEmbeddedTableRenderApi(\n props.embeddedId,\n props.pagePath,\n );\n\n if (result.code === 0) {\n pageId.value = result.data.tableConfig.pageId;\n const { tableButtons: modules } = await import(\n `${BASE_URL.value}/app/js/table/${result.data.tableConfig.pageId}?time=${getRandomString(3)}`\n );\n const configCacheValue = useConfigurationProcess(\n result.data,\n result.data.tableConfig.pageId,\n btnClickFunc,\n modules,\n );\n\n tableConfig.value = result.data.tableConfig;\n queryConfig.value = result.data.queryFrameList;\n if (configCacheValue.gridOptions.columns) {\n columns.value = configCacheValue.gridOptions.columns;\n }\n gridOptions.value = configCacheValue.gridOptions;\n gridOptions.value.columns = [];\n tableToolButtons.value = configCacheValue.tableToolButtons;\n tableRowButtons.value = configCacheValue.tableRowButtons;\n await syncTableData();\n }\n loading.value = false;\n};\n\nonMounted(() => {\n gridOptions.value = { ...defaultPageTableConfig.gridOptions };\n getEmbeddedTableConfig();\n});\n</script>\n\n<template>\n <div class=\"board\" v-loading=\"loading\">\n <div\n v-if=\"tableConfig.pageId && tableConfig.hasQueryTreeFilter\"\n class=\"query-tree\"\n >\n <QueryTreeFilter ref=\"queryTreeFilter\" :page-id=\"tableConfig.pageId\" />\n </div>\n <div v-if=\"tableConfig.pageId\" class=\"page-root\">\n <component\n :is=\"tableConfig.showType\"\n :columns=\"columns\"\n :query-config=\"queryConfig\"\n :table-config=\"tableConfig\"\n :table-data=\"tableData\"\n :table-id=\"tableConfig.pageId\"\n :table-pagination=\"tablePagination\"\n :table-row-buttons=\"tableRowButtons\"\n :table-tool-buttons=\"tableToolButtons\"\n :vxe-grid-options=\"gridOptions\"\n @query-click=\"syncTableData\"\n @value-change=\"onValueChange\"\n />\n </div>\n <EmbeddedDialogForm\n v-if=\"tableConfig.pageId\"\n ref=\"appFormWindowRef\"\n :embedded-id=\"embeddedId\"\n :page-id=\"tableConfig.pageId\"\n :page-path=\"pagePath\"\n @data-change=\"onDataChange\"\n />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.board {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n background: var(--overlay-content);\n min-height: 0; /* 防止 flex 子元素在 shrink 时高度异常 */\n}\n.query-tree {\n width: 240px;\n}\n.page-root {\n flex: 1; /* 剩余空间 */\n //width: 100%;\n min-width: 0; /* 避免内容强制撑开 */\n max-width: 100%; /* 防止过大 */\n transition: width 0.1s linear; /* 平滑宽度变化,消除卡顿感 */\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PagePath, Pagination, KeButton, TableQueryFrame } from '@/types';\n\nimport { onMounted, ref, useTemplateRef } from 'vue';\n\nimport {\n getEmbeddedTableDataApi,\n getEmbeddedTableRenderApi,\n onValueChangeApi,\n} from '@/api';\nimport { BASE_URL, defaultPageTableConfig } from '@/config';\nimport { getRandomString, msgTips } from '@/utils';\n\nimport {\n useConfigurationProcess,\n useTableData,\n} from '../../hooks/useTable.hook';\nimport EmbeddedDialogForm from './EmbeddedDialogForm.vue';\nimport { QueryTreeFilter } from '@/components/QueryComponent/QueryTreeFilter'\n\ninterface Props {\n embeddedId: number;\n pagePath: PagePath[];\n}\n\ninterface QueryTreeFilter {\n getCheckboxes: Function;\n}\n\nconst props = withDefaults(defineProps<Props>(), {});\n\nconst pageId = defineModel<number>('embeddedId')\n\nconst loading = ref(false);\nconst gridOptions = ref<any>({});\nconst queryTreeFilter = useTemplateRef<QueryTreeFilter>('queryTreeFilter');\nconst appFormWindowRef = useTemplateRef('appFormWindowRef');\n// 表格列\nconst columns = ref<any[]>([]);\nconst queryConfig = ref<TableQueryFrame[]>([]);\nconst tableToolButtons = ref<KeButton[]>([]);\nconst tableRowButtons = ref<KeButton[]>([]);\n\nconst tablePagination = ref<Pagination>({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n});\n\nconst { tableData, syncTableData, btnClickFunc, tableConfig } =\n useTableData({\n pageId,\n queryTreeFilter,\n pagination: tablePagination,\n appFormWindowRef,\n embeddedId: props.embeddedId,\n pagePath: props.pagePath,\n });\n\n/**\n * 指定行数据更新\n * @param rowIndex\n */\nconst onDataChange = async (rowIndex: number) => {\n if (rowIndex < 0 || !rowIndex) {\n await syncTableData();\n return;\n }\n loading.value = true;\n const data = tableData.value[rowIndex];\n\n const queryLib: any = {};\n queryLib[tableConfig.value.rowKey] = {\n val: data[tableConfig.value.rowKey],\n queryType: 'equals',\n };\n const result = await getEmbeddedTableDataApi({\n embeddedId: props.embeddedId,\n pageNum: tablePagination.value.currentPage,\n pagePaths: props.pagePath,\n queryData: queryLib,\n });\n if (result.code === 0 && result.data.tableData.length > 0) {\n tableData.value[rowIndex] = result.data.tableData[0];\n }\n loading.value = false;\n};\n\n/**\n * 当检测到值改变\n * @param fieldName\n * @param newValue\n * @param rowId\n */\nconst onValueChange = async (\n fieldName: string,\n newValue: any,\n rowId: string,\n) => {\n loading.value = true;\n const result = await onValueChangeApi({\n pagePaths: props.pagePath,\n tablePageId: tableConfig.value.pageId,\n fieldName,\n newValue,\n rowId,\n });\n if (result.code === 0) {\n msgTips.tips({\n type: 'success',\n msg: '修改成功!',\n });\n }\n loading.value = false;\n};\n\nconst getEmbeddedTableConfig = async () => {\n loading.value = true;\n const result = await getEmbeddedTableRenderApi(\n props.embeddedId,\n props.pagePath,\n );\n\n if (result.code === 0) {\n pageId.value = result.data.tableConfig.pageId;\n const { tableButtons: modules } = await import(\n `${BASE_URL.value}/app/js/table/${result.data.tableConfig.pageId}?time=${getRandomString(3)}`\n );\n const configCacheValue = useConfigurationProcess(\n result.data,\n result.data.tableConfig.pageId,\n btnClickFunc,\n modules,\n );\n\n tableConfig.value = result.data.tableConfig;\n queryConfig.value = result.data.queryFrameList;\n if (configCacheValue.gridOptions.columns) {\n columns.value = configCacheValue.gridOptions.columns;\n }\n gridOptions.value = configCacheValue.gridOptions;\n gridOptions.value.columns = [];\n tableToolButtons.value = configCacheValue.tableToolButtons;\n tableRowButtons.value = configCacheValue.tableRowButtons;\n await syncTableData();\n }\n loading.value = false;\n};\n\nonMounted(() => {\n gridOptions.value = { ...defaultPageTableConfig.gridOptions };\n getEmbeddedTableConfig();\n});\n</script>\n\n<template>\n <div class=\"board\" v-loading=\"loading\">\n <div\n v-if=\"tableConfig.pageId && tableConfig.hasQueryTreeFilter\"\n class=\"query-tree\"\n >\n <QueryTreeFilter ref=\"queryTreeFilter\" :page-id=\"tableConfig.pageId\" />\n </div>\n <div v-if=\"tableConfig.pageId\" class=\"page-root\">\n <component\n :is=\"tableConfig.showType\"\n :columns=\"columns\"\n :query-config=\"queryConfig\"\n :table-config=\"tableConfig\"\n :table-data=\"tableData\"\n :table-id=\"tableConfig.pageId\"\n :table-pagination=\"tablePagination\"\n :table-row-buttons=\"tableRowButtons\"\n :table-tool-buttons=\"tableToolButtons\"\n :vxe-grid-options=\"gridOptions\"\n @query-click=\"syncTableData\"\n @value-change=\"onValueChange\"\n />\n </div>\n <EmbeddedDialogForm\n v-if=\"tableConfig.pageId\"\n ref=\"appFormWindowRef\"\n :embedded-id=\"embeddedId\"\n :page-id=\"tableConfig.pageId\"\n :page-path=\"pagePath\"\n @data-change=\"onDataChange\"\n />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.board {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n background: var(--overlay-content);\n min-height: 0; /* 防止 flex 子元素在 shrink 时高度异常 */\n}\n.query-tree {\n width: 240px;\n}\n.page-root {\n flex: 1; /* 剩余空间 */\n //width: 100%;\n min-width: 0; /* 避免内容强制撑开 */\n max-width: 100%; /* 防止过大 */\n transition: width 0.1s linear; /* 平滑宽度变化,消除卡顿感 */\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FileUpload, FileUploadField } from '@/types';\n\nimport { computed, onMounted, reactive, ref } from 'vue';\n\nimport { Refresh, Upload } from '@element-plus/icons-vue';\n\nimport { getPageUploadFileApi, deletePageUploadFileApi } from '@/api';\nimport logoMini from '@/assets/avatar.svg';\nimport { UPLOAD_FILE_URL, FILE_URL } from '@/config';\nimport { dataFormatter, isEmpty, isImage, msgTips } from '@/utils';\n\nconst {\n dataId,\n pageId = null,\n fileKinds = [],\n} = defineProps<{\n dataId: any;\n fileKinds?: FileUploadField[];\n pageId?: number;\n}>();\n\nconst fileKindsArr = computed(() => {\n const newArr: string[] = [];\n fileKinds.forEach((fileKind) => {\n newArr.push(fileKind.fieldName);\n });\n return newArr;\n});\n\nconst loading = ref(false);\n\nconst tableState = reactive<any>({\n onField: '',\n tableData: [] as PropType<FileUpload[]>,\n uploadUrl: '',\n});\n\ninterface GalleryState {\n /**\n * 预览的图片地址\n */\n images: string[]\n /**\n * 当前预览下标\n */\n currentImageIndex: number\n showVisible: boolean\n}\nconst galleryState = reactive<GalleryState>({\n images: [],\n currentImageIndex: 0,\n showVisible: false,\n});\n\nconst viewFile = (index: number) => {\n galleryState.currentImageIndex = index;\n galleryState.showVisible = true;\n};\n\n/**\n * 是否图片\n *\n * @param file\n */\nconst getSrcUrl = (file: FileUpload): string => {\n if (isImage(file.fileType)) {\n return `${FILE_URL.value}/${file.id}/${file.fileOriginalName}`;\n }\n return logoMini;\n};\n\n/** 获取已上传文件列表 */\nconst getUploadFile = async () => {\n if (pageId === null) {\n return;\n }\n loading.value = true;\n const result = await getPageUploadFileApi(pageId, dataId);\n if (result.code === 0) {\n tableState.tableData = result.data;\n\n galleryState.images = [];\n for (let i = 0; i < result.data.length; i += 1) {\n galleryState.images.push(getSrcUrl(result.data[i]));\n }\n }\n\n loading.value = false;\n};\n\n/** 图片上传到服务器前执行程序 */\nconst beforeUpload = () => {\n if (isEmpty(tableState.onField)) {\n msgTips.tips({\n msg: '请先选择上传类型',\n type: 'warning',\n });\n return false;\n }\n tableState.uploadUrl = `${UPLOAD_FILE_URL.value}/${pageId}/${dataId}/${tableState.onField}`;\n};\n\n/**\n * 上传\n */\nconst uploadFileClick = () => {\n if (!beforeUpload()) {\n return;\n }\n let fileInput: any;\n // 创建文件选择输入框(如果尚未创建)\n if (!fileInput) {\n fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.style.display = 'none';\n fileInput.addEventListener('change', async () => {\n // 处理文件选择事件,如果需要的话\n console.log('文件已选择:', fileInput.files[0].name);\n\n // 创建文件的上传对象\n const file = fileInput.files[0];\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await fetch(tableState.uploadUrl, {\n method: 'POST',\n body: formData,\n });\n\n fileInput.value = '';\n\n if (response.ok) {\n const result = await response.json();\n msgTips.alert({\n msg: result.msg,\n type: 'success',\n });\n getUploadFile();\n } else {\n // 请求失败\n msgTips.alert({\n msg: `请求失败:${response.statusText}`,\n type: 'success',\n });\n }\n });\n document.body.append(fileInput);\n\n // 触发文件选择输入框的点击事件\n fileInput.click();\n }\n};\n\nconst deleteFile = async (fileId: number) => {\n await deletePageUploadFileApi(fileId);\n await getUploadFile();\n};\n\n/**\n * 打开dialog\n *\n */\nconst init = () => {\n getUploadFile();\n\n if (isEmpty(tableState.onField) && fileKinds.length > 0) {\n tableState.onField = fileKinds[0]!.fieldName;\n }\n};\n\nonMounted(() => {\n init();\n});\n</script>\n\n<template>\n <div>\n <div class=\"upload-container\">\n <el-select v-model=\"tableState.onField\">\n <el-option\n v-for=\"item in fileKinds\"\n :key=\"item.fieldName\"\n :label=\"item.fieldTitle\"\n :value=\"item.fieldName\"\n />\n </el-select>\n <div class=\"right-button\">\n <el-button @click=\"getUploadFile\" :loading=\"loading\">\n 刷新<el-icon><Refresh /></el-icon>\n </el-button>\n <el-button type=\"primary\" @click=\"uploadFileClick\">\n 上传<el-icon class=\"el-icon--right\"><Upload /></el-icon>\n </el-button>\n </div>\n </div>\n <div class=\"mt-2\" v-loading=\"loading\">\n <el-table :data=\"tableState.tableData\" border style=\"width: 100%\">\n <el-table-column label=\"文件名\" min-width=\"180\" prop=\"fileOriginalName\">\n <template #default=\"{ $index, row }\">\n <el-link type=\"primary\" @click=\"viewFile($index)\">\n {{ row.fileOriginalName }}\n </el-link>\n </template>\n </el-table-column>\n <el-table-column label=\"上传类型\" prop=\"type\">\n <template #default=\"scope\">\n <el-select v-model=\"scope.row.type\" disabled>\n <el-option\n v-for=\"item in fileKinds\"\n :key=\"item.fieldName\"\n :label=\"item.fieldTitle\"\n :value=\"item.fieldName\"\n />\n </el-select>\n </template>\n </el-table-column>\n <el-table-column label=\"文件类型\" prop=\"fileType\" />\n <el-table-column label=\"上传人\" prop=\"createBy\" />\n <el-table-column label=\"上传时间\" prop=\"createTime\" width=\"160\">\n <template #default=\"scope\">\n {{ dataFormatter.timestamp(scope.row.createTime) }}\n </template>\n </el-table-column>\n <el-table-column label=\"操作\" prop=\"options\">\n <template #default=\"{ row }\">\n <el-button\n v-if=\"fileKindsArr.includes(row.type)\"\n size=\"small\"\n type=\"danger\"\n @click=\"deleteFile(row.id)\"\n >\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n <el-image-viewer\n v-if=\"galleryState.showVisible\"\n :initial-index=\"galleryState.currentImageIndex\"\n :url-list=\"galleryState.images\"\n @close=\"galleryState.showVisible = false\"\n />\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.upload-container {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.upload-container .el-select {\n max-width: 300px;\n}\n\n.right-button {\n display: flex;\n justify-content: flex-end; /* 按钮右对齐 */\n align-items: center; /* 按钮垂直居中 */\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FileUpload, FileUploadField } from '@/types';\n\nimport { computed, onMounted, reactive, ref } from 'vue';\n\nimport { Refresh, Upload } from '@element-plus/icons-vue';\n\nimport { getPageUploadFileApi, deletePageUploadFileApi } from '@/api';\nimport logoMini from '@/assets/avatar.svg';\nimport { UPLOAD_FILE_URL, FILE_URL } from '@/config';\nimport { dataFormatter, isEmpty, isImage, msgTips } from '@/utils';\n\nconst {\n dataId,\n pageId = null,\n fileKinds = [],\n} = defineProps<{\n dataId: any;\n fileKinds?: FileUploadField[];\n pageId?: number;\n}>();\n\nconst fileKindsArr = computed(() => {\n const newArr: string[] = [];\n fileKinds.forEach((fileKind) => {\n newArr.push(fileKind.fieldName);\n });\n return newArr;\n});\n\nconst loading = ref(false);\n\nconst tableState = reactive<any>({\n onField: '',\n tableData: [] as PropType<FileUpload[]>,\n uploadUrl: '',\n});\n\ninterface GalleryState {\n /**\n * 预览的图片地址\n */\n images: string[]\n /**\n * 当前预览下标\n */\n currentImageIndex: number\n showVisible: boolean\n}\nconst galleryState = reactive<GalleryState>({\n images: [],\n currentImageIndex: 0,\n showVisible: false,\n});\n\nconst viewFile = (index: number) => {\n galleryState.currentImageIndex = index;\n galleryState.showVisible = true;\n};\n\n/**\n * 是否图片\n *\n * @param file\n */\nconst getSrcUrl = (file: FileUpload): string => {\n if (isImage(file.fileType)) {\n return `${FILE_URL.value}/${file.id}/${file.fileOriginalName}`;\n }\n return logoMini;\n};\n\n/** 获取已上传文件列表 */\nconst getUploadFile = async () => {\n if (pageId === null) {\n return;\n }\n loading.value = true;\n const result = await getPageUploadFileApi(pageId, dataId);\n if (result.code === 0) {\n tableState.tableData = result.data;\n\n galleryState.images = [];\n for (let i = 0; i < result.data.length; i += 1) {\n galleryState.images.push(getSrcUrl(result.data[i]));\n }\n }\n\n loading.value = false;\n};\n\n/** 图片上传到服务器前执行程序 */\nconst beforeUpload = () => {\n if (isEmpty(tableState.onField)) {\n msgTips.tips({\n msg: '请先选择上传类型',\n type: 'warning',\n });\n return false;\n }\n tableState.uploadUrl = `${UPLOAD_FILE_URL.value}/${pageId}/${dataId}/${tableState.onField}`;\n};\n\n/**\n * 上传\n */\nconst uploadFileClick = () => {\n if (!beforeUpload()) {\n return;\n }\n let fileInput: any;\n // 创建文件选择输入框(如果尚未创建)\n if (!fileInput) {\n fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.style.display = 'none';\n fileInput.addEventListener('change', async () => {\n // 处理文件选择事件,如果需要的话\n console.log('文件已选择:', fileInput.files[0].name);\n\n // 创建文件的上传对象\n const file = fileInput.files[0];\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await fetch(tableState.uploadUrl, {\n method: 'POST',\n body: formData,\n });\n\n fileInput.value = '';\n\n if (response.ok) {\n const result = await response.json();\n msgTips.alert({\n msg: result.msg,\n type: 'success',\n });\n getUploadFile();\n } else {\n // 请求失败\n msgTips.alert({\n msg: `请求失败:${response.statusText}`,\n type: 'success',\n });\n }\n });\n document.body.append(fileInput);\n\n // 触发文件选择输入框的点击事件\n fileInput.click();\n }\n};\n\nconst deleteFile = async (fileId: number) => {\n await deletePageUploadFileApi(fileId);\n await getUploadFile();\n};\n\n/**\n * 打开dialog\n *\n */\nconst init = () => {\n getUploadFile();\n\n if (isEmpty(tableState.onField) && fileKinds.length > 0) {\n tableState.onField = fileKinds[0]!.fieldName;\n }\n};\n\nonMounted(() => {\n init();\n});\n</script>\n\n<template>\n <div>\n <div class=\"upload-container\">\n <el-select v-model=\"tableState.onField\">\n <el-option\n v-for=\"item in fileKinds\"\n :key=\"item.fieldName\"\n :label=\"item.fieldTitle\"\n :value=\"item.fieldName\"\n />\n </el-select>\n <div class=\"right-button\">\n <el-button @click=\"getUploadFile\" :loading=\"loading\">\n 刷新<el-icon><Refresh /></el-icon>\n </el-button>\n <el-button type=\"primary\" @click=\"uploadFileClick\">\n 上传<el-icon class=\"el-icon--right\"><Upload /></el-icon>\n </el-button>\n </div>\n </div>\n <div class=\"mt-2\" v-loading=\"loading\">\n <el-table :data=\"tableState.tableData\" border style=\"width: 100%\">\n <el-table-column label=\"文件名\" min-width=\"180\" prop=\"fileOriginalName\">\n <template #default=\"{ $index, row }\">\n <el-link type=\"primary\" @click=\"viewFile($index)\">\n {{ row.fileOriginalName }}\n </el-link>\n </template>\n </el-table-column>\n <el-table-column label=\"上传类型\" prop=\"type\">\n <template #default=\"scope\">\n <el-select v-model=\"scope.row.type\" disabled>\n <el-option\n v-for=\"item in fileKinds\"\n :key=\"item.fieldName\"\n :label=\"item.fieldTitle\"\n :value=\"item.fieldName\"\n />\n </el-select>\n </template>\n </el-table-column>\n <el-table-column label=\"文件类型\" prop=\"fileType\" />\n <el-table-column label=\"上传人\" prop=\"createBy\" />\n <el-table-column label=\"上传时间\" prop=\"createTime\" width=\"160\">\n <template #default=\"scope\">\n {{ dataFormatter.timestamp(scope.row.createTime) }}\n </template>\n </el-table-column>\n <el-table-column label=\"操作\" prop=\"options\">\n <template #default=\"{ row }\">\n <el-button\n v-if=\"fileKindsArr.includes(row.type)\"\n size=\"small\"\n type=\"danger\"\n @click=\"deleteFile(row.id)\"\n >\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n <el-image-viewer\n v-if=\"galleryState.showVisible\"\n :initial-index=\"galleryState.currentImageIndex\"\n :url-list=\"galleryState.images\"\n @close=\"galleryState.showVisible = false\"\n />\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.upload-container {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.upload-container .el-select {\n max-width: 300px;\n}\n\n.right-button {\n display: flex;\n justify-content: flex-end; /* 按钮右对齐 */\n align-items: center; /* 按钮垂直居中 */\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { NodeFlowProcessor } from '@/types';\n\nimport { reactive, ref } from 'vue';\n\nimport { msgTips } from '@/utils';\n\nconst emits = defineEmits(['submit']);\nconst dialog = reactive({\n dialogTableVisible: false,\n loading: false,\n});\n\nlet isSubmit: boolean | null = null;\n\nconst tabsActiveName = ref<number | null>(null);\nconst transfer = reactive({\n value: [],\n suggestion: '',\n});\n\nconst nodeFlowProcessorRef = ref<NodeFlowProcessor[]>([]);\n\nconst tabChange = () => {\n transfer.value = [];\n};\n\n/**\n * 确认\n */\nconst confirm = () => {\n const onTabNode = nodeFlowProcessorRef.value.find(\n (node) => node.nodeId === tabsActiveName.value,\n );\n\n if (!onTabNode?.notTodo && transfer.value.length === 0) {\n msgTips.tips({ msg: '请选择提交的人员', type: 'warning' });\n return;\n }\n emits(\n 'submit',\n tabsActiveName.value,\n transfer.value,\n transfer.suggestion,\n isSubmit,\n );\n};\n\n/**\n * @param nodeFlows\n * @param submitOrBack true表示提交 false表示退回\n */\nconst openDialog = (\n nodeFlows: NodeFlowProcessor[],\n submitOrBack: boolean | null,\n) => {\n if (submitOrBack === null) {\n msgTips.tips({ msg: '参数异常', type: 'error' });\n return;\n }\n dialog.dialogTableVisible = true;\n nodeFlowProcessorRef.value = nodeFlows;\n tabsActiveName.value = nodeFlows[0].nodeId;\n isSubmit = submitOrBack;\n transfer.suggestion = '';\n};\n\nconst closeDialog = () => {\n dialog.dialogTableVisible = false;\n nodeFlowProcessorRef.value = [];\n tabsActiveName.value = null;\n};\n\n/** 是否提交 */\nconst openLoading = () => {\n dialog.loading = true;\n\n transfer.value = [];\n};\n\nconst closeLoading = () => {\n dialog.loading = false;\n};\n\ndefineExpose({ openDialog, closeDialog, openLoading, closeLoading });\n</script>\n<template>\n <el-dialog\n v-model=\"dialog.dialogTableVisible\"\n :show-close=\"false\"\n align-center\n append-to-body\n destroy-on-close\n width=\"632px\"\n >\n <template #header=\"{ titleId, titleClass }\">\n <div class=\"my-header\">\n <h3 :id=\"titleId\" :class=\"titleClass\">选择下一环节处理人</h3>\n </div>\n </template>\n <el-tabs v-model=\"tabsActiveName\" class=\"demo-tabs\" @tab-click=\"tabChange\">\n <el-tab-pane\n v-for=\"nodeFlow in nodeFlowProcessorRef\"\n :key=\"nodeFlow.nodeId\"\n :label=\"nodeFlow.nodeName\"\n :name=\"nodeFlow.nodeId\"\n >\n <el-transfer\n v-model=\"transfer.value\"\n :data=\"nodeFlow.users\"\n :props=\"{\n key: 'userId',\n label: 'realName',\n }\"\n :titles=\"['可选人员', '已选择']\"\n />\n </el-tab-pane>\n </el-tabs>\n <template #footer>\n <div>\n <el-input\n v-model=\"transfer.suggestion\"\n autosize\n placeholder=\"批阅建议\"\n type=\"textarea\"\n />\n <div style=\"right: 0; margin-top: 8px\">\n <el-button\n :loading=\"dialog.loading\"\n @click=\"dialog.dialogTableVisible = false\"\n >\n 取消\n </el-button>\n <el-button :loading=\"dialog.loading\" type=\"primary\" @click=\"confirm\">\n 确认\n </el-button>\n </div>\n </div>\n </template>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.my-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n gap: 16px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { NodeFlowProcessor } from '@/types';\n\nimport { reactive, ref } from 'vue';\n\nimport { msgTips } from '@/utils';\n\nconst emits = defineEmits(['submit']);\nconst dialog = reactive({\n dialogTableVisible: false,\n loading: false,\n});\n\nlet isSubmit: boolean | null = null;\n\nconst tabsActiveName = ref<number | null>(null);\nconst transfer = reactive({\n value: [],\n suggestion: '',\n});\n\nconst nodeFlowProcessorRef = ref<NodeFlowProcessor[]>([]);\n\nconst tabChange = () => {\n transfer.value = [];\n};\n\n/**\n * 确认\n */\nconst confirm = () => {\n const onTabNode = nodeFlowProcessorRef.value.find(\n (node) => node.nodeId === tabsActiveName.value,\n );\n\n if (!onTabNode?.notTodo && transfer.value.length === 0) {\n msgTips.tips({ msg: '请选择提交的人员', type: 'warning' });\n return;\n }\n emits(\n 'submit',\n tabsActiveName.value,\n transfer.value,\n transfer.suggestion,\n isSubmit,\n );\n};\n\n/**\n * @param nodeFlows\n * @param submitOrBack true表示提交 false表示退回\n */\nconst openDialog = (\n nodeFlows: NodeFlowProcessor[],\n submitOrBack: boolean | null,\n) => {\n if (submitOrBack === null) {\n msgTips.tips({ msg: '参数异常', type: 'error' });\n return;\n }\n dialog.dialogTableVisible = true;\n nodeFlowProcessorRef.value = nodeFlows;\n tabsActiveName.value = nodeFlows[0].nodeId;\n isSubmit = submitOrBack;\n transfer.suggestion = '';\n};\n\nconst closeDialog = () => {\n dialog.dialogTableVisible = false;\n nodeFlowProcessorRef.value = [];\n tabsActiveName.value = null;\n};\n\n/** 是否提交 */\nconst openLoading = () => {\n dialog.loading = true;\n\n transfer.value = [];\n};\n\nconst closeLoading = () => {\n dialog.loading = false;\n};\n\ndefineExpose({ openDialog, closeDialog, openLoading, closeLoading });\n</script>\n<template>\n <el-dialog\n v-model=\"dialog.dialogTableVisible\"\n :show-close=\"false\"\n align-center\n append-to-body\n destroy-on-close\n width=\"632px\"\n >\n <template #header=\"{ titleId, titleClass }\">\n <div class=\"my-header\">\n <h3 :id=\"titleId\" :class=\"titleClass\">选择下一环节处理人</h3>\n </div>\n </template>\n <el-tabs v-model=\"tabsActiveName\" class=\"demo-tabs\" @tab-click=\"tabChange\">\n <el-tab-pane\n v-for=\"nodeFlow in nodeFlowProcessorRef\"\n :key=\"nodeFlow.nodeId\"\n :label=\"nodeFlow.nodeName\"\n :name=\"nodeFlow.nodeId\"\n >\n <el-transfer\n v-model=\"transfer.value\"\n :data=\"nodeFlow.users\"\n :props=\"{\n key: 'userId',\n label: 'realName',\n }\"\n :titles=\"['可选人员', '已选择']\"\n />\n </el-tab-pane>\n </el-tabs>\n <template #footer>\n <div>\n <el-input\n v-model=\"transfer.suggestion\"\n autosize\n placeholder=\"批阅建议\"\n type=\"textarea\"\n />\n <div style=\"right: 0; margin-top: 8px\">\n <el-button\n :loading=\"dialog.loading\"\n @click=\"dialog.dialogTableVisible = false\"\n >\n 取消\n </el-button>\n <el-button :loading=\"dialog.loading\" type=\"primary\" @click=\"confirm\">\n 确认\n </el-button>\n </div>\n </div>\n </template>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.my-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n gap: 16px;\n}\n</style>\n","import type { FormSelectProp } from '@/types/index.ts';\n\n/**\n * 给表单设置默认值 (一般提交时使用)\n *\n * @param formData\n * @param formFrame\n */\nexport const useSetDefaultValue = (formData: any, formFrame: FormSelectProp[]) => {\n if (formFrame.length === 0) {\n return formData;\n }\n\n const newFormData = { ...formData };\n formFrame.forEach((item) => {\n if (newFormData[item.field] === undefined) {\n // 如果是多选 说明是数组\n if (item.multiple) {\n if (item.defaultValue) {\n newFormData[item.field] =\n typeof item.defaultValue === 'string'\n ? JSON.parse(item.defaultValue)\n : item.defaultValue;\n }\n } else {\n // 直接设置默认值\n newFormData[item.field] = item.defaultValue;\n }\n }\n });\n\n return newFormData;\n};\n","<script setup lang=\"ts\">\nimport type {\n PagePath,\n FormBasicInterface,\n FormEmbeddedTableProp,\n FormFrame,\n KeButton,\n FlowButton,\n} from '@/types/index.ts';\n\nimport {\n computed,\n defineAsyncComponent,\n nextTick,\n onBeforeUnmount,\n onMounted,\n reactive,\n ref,\n} from 'vue';\n\nimport {\n backBeforeCheckApi,\n backFlowApi,\n getFormRenderDataApi,\n saveFormDataApi,\n submitBeforeCheckApi,\n submitFlowApi,\n getEmbeddedFormRenderDataApi,\n saveEmbeddedTableFormDataApi,\n} from '@/api';\n\nimport EmbeddedTable from './components/embedded/EmbeddedTable.vue';\nimport FileIsland from './components/FileIsland.vue';\nimport FlowUserDialog from './components/FlowUserDialog.vue';\nimport { BASE_URL } from '@/config';\nimport { useSetDefaultValue } from './hooks/useAutoForm.hook.ts';\nimport { useButtonExec } from '@/hooks/useButtonExec.hook.ts';\n\nimport { getRandomString, isNotEmpty, msgTips, sleep } from '@/utils';\nimport { ElButtonPlus } from '@/components';\nimport { FormRender } from '@/components/FormComponent/FormRender';\n\ninterface Props {\n pageId: number;\n dataId: number | string;\n isFullScreen?: boolean;\n embeddedId?: null | number;\n pagePath: PagePath[];\n showWindowButton?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n embeddedId: null,\n showWindowButton: true,\n isFullScreen: false,\n});\n\nconst emits = defineEmits([\n 'close',\n 'fullScreenChange',\n 'update:dataId',\n 'dataChange',\n]);\n\nconst ApprovalRecord = defineAsyncComponent(\n () => import('./components/ApprovalRecord.vue'),\n);\n\nconst flowUserDialogRef = ref();\n\nconst formRenderRef = ref();\n\nconst configRef = ref<FormBasicInterface>({} as FormBasicInterface);\nconst frameRef = ref([]);\nconst dataIdRef = defineModel('dataId');\nconst formDataRef = ref({});\nconst formRuleRef = ref({});\nconst formButtonsRef = ref<KeButton[]>([]);\nconst flowButtonRef = ref<FlowButton>({} as FlowButton);\nconst formSaveVerifyJsRef = ref<Function | null>(null);\nconst embeddedTableListRef = ref<FormEmbeddedTableProp[]>([]);\n\nlet isAdd = false;\n\nconst newPagePaths = computed(() => {\n if (Array.isArray(props.pagePath)) {\n return [\n ...props.pagePath,\n {\n pageId: props.pageId,\n dataId: props.dataId,\n formData: formDataRef.value,\n },\n ];\n }\n return [\n {\n pageId: props.pageId,\n dataId: props.dataId,\n formData: formDataRef.value,\n },\n ];\n});\n\nconst activeName = ref('Form');\n/**\n * 组件显示规则\n */\nconst componentShowRuleRef = ref({});\n/**\n * 文件类别列表\n */\nconst fileUploadList = ref([]);\n\nconst pageState = reactive({\n // 表单是否加载中\n formLoading: false,\n isEdit: false,\n // 编辑ID\n editId: '',\n});\n\nconst onNodeState = reactive({\n nodeId: '',\n nodeName: '',\n});\n\nconst formTabName = computed(() => {\n if (onNodeState.nodeName && configRef.value.startOA) {\n return `表单-${onNodeState.nodeName}`;\n }\n return '表单';\n});\n\n/** 渲染数据 */\nconst initFormFrameAndData = async () => {\n configRef.value = {\n labelWidth: 120,\n rowKey: 'key',\n };\n frameRef.value = [];\n formDataRef.value = {};\n\n embeddedTableListRef.value = [];\n pageState.formLoading = true;\n formSaveVerifyJsRef.value = null;\n\n let result;\n if (newPagePaths.value.length === 1) {\n result = await getFormRenderDataApi(props.pageId, props.dataId ?? 'new', isAdd);\n } else {\n if (props.embeddedId === null) {\n msgTips.alert({\n msg: '数据结构异常',\n type: 'error'\n })\n console.error(props)\n return;\n }\n result = await getEmbeddedFormRenderDataApi(\n {\n embeddedId: props.embeddedId,\n pagePaths: newPagePaths.value,\n },\n props.dataId,\n isAdd,\n );\n }\n\n if (result.code === 0) {\n configRef.value = result.data.formConfig;\n formDataRef.value = JSON.parse(JSON.stringify(result.data.formData));\n\n // 流程按钮\n flowButtonRef.value = result.data.flowButton;\n /**\n * 表单功能按钮\n */\n formButtonsRef.value = Array.isArray(result.data.formButtons)\n ? JSON.parse(JSON.stringify(result.data.formButtons))\n : [];\n onNodeState.nodeId = result.data.editConfig.nodeId;\n onNodeState.nodeName = result.data.editConfig.nodeName;\n\n const {\n formRules,\n formSaveVerifyJs,\n componentShowRule,\n receiveBroadcasts,\n formButtons,\n } = await import(\n `${BASE_URL.value}/app/js/formRender/${props.pageId}/${props.dataId}?time=${getRandomString(3)}`\n );\n // 注入函数\n formButtonsRef.value.forEach((button) => {\n if (button.webTrigger && formButtons[button.id]) {\n button.webFunction = formButtons[button.id];\n }\n });\n\n formRuleRef.value = formRules;\n // 如果表单验证js不为空 则转换为js方法\n if (isNotEmpty(formSaveVerifyJs)) {\n formSaveVerifyJsRef.value = formSaveVerifyJs;\n }\n // 组件显示规则\n componentShowRuleRef.value = componentShowRule;\n\n const formFrameList = JSON.parse(JSON.stringify(result.data.formFrame));\n formFrameList.forEach((formFrame: FormFrame) => {\n formFrame.noticeReceive = receiveBroadcasts[formFrame.field];\n });\n frameRef.value = formFrameList;\n\n pageState.isEdit = result.data.editConfig.edit;\n pageState.editId = result.editId || '';\n\n await nextTick();\n // 初始化表单配置\n formRenderRef.value.initForm(formDataRef.value);\n\n fileUploadList.value = result.data.fileUploadList;\n\n await nextTick();\n embeddedTableListRef.value = result.data.embeddedTableList;\n } else {\n emits('close');\n }\n\n formDataRef.value = useSetDefaultValue(formDataRef.value, frameRef.value);\n pageState.formLoading = false;\n};\n\n/**\n * 表单数据保存\n */\nconst formDataSave = async () => {\n if (pageState.formLoading) {\n return;\n }\n if (!(await formRenderRef.value.validateForm())) return;\n pageState.formLoading = true;\n let result;\n if (newPagePaths.value.length === 1) {\n result = await saveFormDataApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n } else {\n if (props.embeddedId === null) {\n msgTips.alert({\n msg: '数据结构异常',\n type: 'error'\n })\n console.error(props)\n return\n }\n result = await saveEmbeddedTableFormDataApi(\n {\n embeddedId: props.embeddedId,\n pagePaths: props.pagePath,\n formData: formDataRef.value,\n },\n props.dataId,\n pageState.editId,\n isAdd,\n );\n }\n\n if (result.code === 0) {\n if (isAdd) {\n dataIdRef.value = result.data;\n isAdd = false;\n await nextTick();\n await initFormFrameAndData();\n }\n pageState.editId = result.editId || '';\n }\n pageState.formLoading = false;\n emits('dataChange');\n};\n\n/** 流程提交 */\nconst flowSubmitHandle = async () => {\n await formDataSave();\n if (pageState.formLoading) {\n return;\n }\n // 校验表单内容\n if (!(await formRenderRef.value.validateForm())) return;\n\n if (flowButtonRef.value.submitTips) {\n msgTips.alert({\n type: 'warning',\n title: '提示',\n msg: flowButtonRef.value.submitTips,\n callback: () => {\n submitCheck();\n },\n });\n } else {\n await submitCheck();\n }\n};\n/**\n * 提交前检查\n */\nconst submitCheck = async () => {\n pageState.formLoading = true;\n const result = await submitBeforeCheckApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n flowUserDialogRef.value.openDialog(result.data.nodeFlowProcessors, true);\n }\n pageState.formLoading = false;\n};\n\n/** 流程退回 */\nconst flowBackHandle = async () => {\n await formDataSave();\n if (pageState.formLoading) {\n return;\n }\n\n if (flowButtonRef.value.backTips) {\n msgTips.alert({\n type: 'warning',\n title: '提示',\n msg: flowButtonRef.value.backTips,\n callback: () => {\n backCheck();\n },\n });\n } else {\n await backCheck();\n }\n};\n\n/**\n * 退回前检查\n */\nconst backCheck = async () => {\n pageState.formLoading = true;\n const result = await backBeforeCheckApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n flowUserDialogRef.value.openDialog(result.data.nodeFlowProcessors, false);\n }\n pageState.formLoading = false;\n};\n\n/**\n * 提交流程\n *\n * @param submitNodeId\n * @param submitUsers\n * @param suggestion\n * @param submit\n */\nconst submitFlow = async (\n submitNodeId: string,\n submitUsers: string[],\n suggestion: string,\n submit: boolean,\n) => {\n if (pageState.formLoading) {\n return;\n }\n flowUserDialogRef.value.openLoading();\n pageState.formLoading = true;\n\n const result = await (submit\n ? submitFlowApi({\n pageId: props.pageId,\n dataId: props.dataId,\n nodeId: onNodeState.nodeId,\n toNodeId: submitNodeId,\n userId: submitUsers,\n suggestion,\n formData: formDataRef.value,\n })\n : backFlowApi({\n pageId: props.pageId,\n dataId: props.dataId,\n nodeId: onNodeState.nodeId,\n toNodeId: submitNodeId,\n userId: submitUsers,\n suggestion,\n formData: formDataRef.value,\n }));\n\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n await sleep(0.2);\n flowUserDialogRef.value.closeDialog();\n await initFormFrameAndData();\n }\n flowUserDialogRef.value.closeLoading();\n pageState.formLoading = false;\n};\n\n/**\n * 表单按钮\n *\n * @param button\n */\nconst formButtonClick = (button: KeButton) => {\n if (pageState.formLoading) {\n return;\n }\n\n executeFormButton(button);\n};\n\n/**\n * 执行按钮程序\n *\n * @param button\n */\nconst executeFormButton = async (button: KeButton) => {\n if (pageState.formLoading) {\n return;\n }\n pageState.formLoading = true;\n\n button.params = { pageId: props.pageId, dataId: props.dataId };\n // 调用执行按钮程序\n await useButtonExec(formDataRef.value, button);\n\n pageState.formLoading = false;\n};\n\n/**\n * 初始化\n */\nconst initForm = (isNew: boolean) => {\n isAdd = isNew;\n initFormFrameAndData();\n};\n/**\n * 刷新\n */\nconst refresh = () => {\n initFormFrameAndData();\n};\n/**\n * 改变全屏\n */\nconst fullScreenChange = () => {\n emits('fullScreenChange');\n};\n\n/**\n * 关闭表单\n */\nconst closeWindow = () => {\n emits('close');\n};\n\nonMounted(() => {\n const SCROLL_HIDE_DELAY = 300; // ms\n const scrollTimeoutMap = new Map<Element, ReturnType<typeof setTimeout>>();\n\n const panes = document.querySelectorAll('.el-tab-pane');\n panes.forEach((pane) => {\n const onScroll = () => {\n pane.classList.add('scrolling');\n if (scrollTimeoutMap.has(pane)) {\n clearTimeout(scrollTimeoutMap.get(pane));\n }\n const timeout = setTimeout(() => {\n pane.classList.remove('scrolling');\n }, SCROLL_HIDE_DELAY);\n scrollTimeoutMap.set(pane, timeout);\n };\n pane.addEventListener('scroll', onScroll);\n // 保存回收方法\n (pane as any).__onScrollHandler__ = onScroll;\n });\n});\n\nonBeforeUnmount(() => {\n const panes = document.querySelectorAll('.el-tab-pane');\n panes.forEach((pane) => {\n if ((pane as any).__onScrollHandler__) {\n pane.removeEventListener('scroll', (pane as any).__onScrollHandler__);\n delete (pane as any).__onScrollHandler__;\n }\n });\n});\n\ndefineExpose({ initForm, refresh });\n</script>\n\n<template>\n <div class=\"app-form-render\" v-loading=\"pageState.formLoading\">\n <div class=\"app-header\">\n <el-scrollbar class=\"left\">\n <el-tooltip\n effect=\"dark\"\n content=\"刷新\"\n placement=\"top-start\"\n >\n<!-- <el-button @click=\"refresh\" :icon=\"Refresh\" />-->\n <el-button-plus @click=\"refresh\" icon=\"tdesign:refresh\" />\n </el-tooltip>\n <el-tooltip\n v-if=\"pageState.isEdit\"\n effect=\"dark\"\n content=\"保存\"\n placement=\"top-start\"\n >\n<!-- <el-button type=\"primary\" @click=\"formDataSave\" :icon=\"Save\" />-->\n <el-button-plus type=\"primary\" @click=\"formDataSave\" icon=\"ci:save\" />\n </el-tooltip>\n <el-button\n v-if=\"flowButtonRef && isNotEmpty(flowButtonRef.submitLabel)\"\n type=\"primary\"\n @click=\"flowSubmitHandle\"\n >\n {{ flowButtonRef.submitLabel }}\n </el-button>\n <el-button\n v-if=\"flowButtonRef && isNotEmpty(flowButtonRef.backLabel)\"\n type=\"danger\"\n @click=\"flowBackHandle\"\n >\n {{ flowButtonRef.backLabel }}\n </el-button>\n <el-button\n v-for=\"btn in formButtonsRef\"\n :key=\"btn.id\"\n :type=\"btn.type\"\n @click=\"formButtonClick(btn)\"\n >\n {{ btn.label }}\n </el-button>\n </el-scrollbar>\n <div v-if=\"showWindowButton\" class=\"right\">\n <el-button @click=\"fullScreenChange\">\n {{ isFullScreen ? '缩小' : '全屏' }}\n </el-button>\n <el-button type=\"danger\" @click=\"closeWindow\">\n 关闭\n </el-button>\n </div>\n </div>\n <el-tabs v-model=\"activeName\" class=\"form-container\">\n <el-tab-pane :label=\"formTabName\" name=\"Form\">\n <FormRender\n ref=\"formRenderRef\"\n v-model:data=\"formDataRef\"\n :component-show-rule=\"componentShowRuleRef\"\n :config=\"configRef\"\n :form-rules=\"formRuleRef\"\n :form-save-verify-js=\"formSaveVerifyJsRef\"\n :frame=\"frameRef\"\n :page-id=\"pageId\"\n style=\"margin-top: 15px\"\n />\n </el-tab-pane>\n <slot name=\"default\"></slot>\n <el-tab-pane v-if=\"fileUploadList && fileUploadList.length > 0\" label=\"附件上传\" lazy>\n <FileIsland\n :page-id=\"pageId\"\n :data-id=\"dataId\"\n :file-kinds=\"fileUploadList\"\n />\n </el-tab-pane>\n <el-tab-pane\n v-for=\"em in embeddedTableListRef\"\n :key=\"em.embeddedId\"\n :label=\"em.tabTitle\"\n :lazy=\"true\"\n :name=\"em.embeddedId\"\n style=\"height: 100%\"\n >\n <EmbeddedTable :embedded-id=\"em.embeddedId\" :page-path=\"newPagePaths\" />\n </el-tab-pane>\n <el-tab-pane\n v-if=\"configRef.startOA && onNodeState.nodeId\"\n label=\"批阅记录\"\n lazy\n >\n <ApprovalRecord :page-id=\"pageId\" :data-id=\"dataId\" />\n </el-tab-pane>\n </el-tabs>\n <FlowUserDialog ref=\"flowUserDialogRef\" @submit=\"submitFlow\" />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.app-form-render {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden; // 防止它自己滚动\n}\n\n.app-header {\n display: flex;\n flex-wrap: wrap;\n padding-bottom: 6px;\n border-bottom: 2px solid var(--el-border-color);\n .left {\n flex-grow: 1; /* 占用剩余宽度 */\n }\n\n .right {\n flex-shrink: 0; /* 不收缩 */\n width: auto; /* 根据内容宽度撑开 */\n }\n}\n\n.form-buttons {\n //display: flex;\n margin-top: 8px;\n}\n.form-container {\n flex: 1 1 0;\n min-height: 0;\n overflow: hidden;\n\n :deep(.el-tabs__content) {\n height: 100%;\n }\n\n :deep(.el-tab-pane) {\n height: 100%;\n\n & > div {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n }\n\n :deep(.el-tabs__header) {\n margin: 0;\n }\n}\n/* 隐藏 .el-tab-pane 自身的滚动条 */\n:deep(.el-tab-pane) {\n height: 100%;\n overflow-y: auto;\n overflow-x: auto; /* 注意:你原本是 hidden,但设了 auto,建议统一 */\n // 隐藏滚动条但保留滚动功能\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE/Edge */\n}\n\n:deep(.el-tab-pane::-webkit-scrollbar) {\n //display: none; /* WebKit 浏览器隐藏滚动条 */\n}\n\n/* 👇 关键:恢复 el-table 内部滚动条的显示 */\n:deep(.el-table__body-wrapper) {\n scrollbar-width: auto;\n -ms-overflow-style: auto;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar) {\n display: block;\n width: 6px;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar-thumb) {\n background-color: rgba(0, 0, 0, 0.4);\n border-radius: 3px;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar-track) {\n background-color: transparent;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type {\n PagePath,\n FormBasicInterface,\n FormEmbeddedTableProp,\n FormFrame,\n KeButton,\n FlowButton,\n} from '@/types/index.ts';\n\nimport {\n computed,\n defineAsyncComponent,\n nextTick,\n onBeforeUnmount,\n onMounted,\n reactive,\n ref,\n} from 'vue';\n\nimport {\n backBeforeCheckApi,\n backFlowApi,\n getFormRenderDataApi,\n saveFormDataApi,\n submitBeforeCheckApi,\n submitFlowApi,\n getEmbeddedFormRenderDataApi,\n saveEmbeddedTableFormDataApi,\n} from '@/api';\n\nimport EmbeddedTable from './components/embedded/EmbeddedTable.vue';\nimport FileIsland from './components/FileIsland.vue';\nimport FlowUserDialog from './components/FlowUserDialog.vue';\nimport { BASE_URL } from '@/config';\nimport { useSetDefaultValue } from './hooks/useAutoForm.hook.ts';\nimport { useButtonExec } from '@/hooks/useButtonExec.hook.ts';\n\nimport { getRandomString, isNotEmpty, msgTips, sleep } from '@/utils';\nimport { ElButtonPlus } from '@/components';\nimport { FormRender } from '@/components/FormComponent/FormRender';\n\ninterface Props {\n pageId: number;\n dataId: number | string;\n isFullScreen?: boolean;\n embeddedId?: null | number;\n pagePath: PagePath[];\n showWindowButton?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n embeddedId: null,\n showWindowButton: true,\n isFullScreen: false,\n});\n\nconst emits = defineEmits([\n 'close',\n 'fullScreenChange',\n 'update:dataId',\n 'dataChange',\n]);\n\nconst ApprovalRecord = defineAsyncComponent(\n () => import('./components/ApprovalRecord.vue'),\n);\n\nconst flowUserDialogRef = ref();\n\nconst formRenderRef = ref();\n\nconst configRef = ref<FormBasicInterface>({} as FormBasicInterface);\nconst frameRef = ref([]);\nconst dataIdRef = defineModel('dataId');\nconst formDataRef = ref({});\nconst formRuleRef = ref({});\nconst formButtonsRef = ref<KeButton[]>([]);\nconst flowButtonRef = ref<FlowButton>({} as FlowButton);\nconst formSaveVerifyJsRef = ref<Function | null>(null);\nconst embeddedTableListRef = ref<FormEmbeddedTableProp[]>([]);\n\nlet isAdd = false;\n\nconst newPagePaths = computed(() => {\n if (Array.isArray(props.pagePath)) {\n return [\n ...props.pagePath,\n {\n pageId: props.pageId,\n dataId: props.dataId,\n formData: formDataRef.value,\n },\n ];\n }\n return [\n {\n pageId: props.pageId,\n dataId: props.dataId,\n formData: formDataRef.value,\n },\n ];\n});\n\nconst activeName = ref('Form');\n/**\n * 组件显示规则\n */\nconst componentShowRuleRef = ref({});\n/**\n * 文件类别列表\n */\nconst fileUploadList = ref([]);\n\nconst pageState = reactive({\n // 表单是否加载中\n formLoading: false,\n isEdit: false,\n // 编辑ID\n editId: '',\n});\n\nconst onNodeState = reactive({\n nodeId: '',\n nodeName: '',\n});\n\nconst formTabName = computed(() => {\n if (onNodeState.nodeName && configRef.value.startOA) {\n return `表单-${onNodeState.nodeName}`;\n }\n return '表单';\n});\n\n/** 渲染数据 */\nconst initFormFrameAndData = async () => {\n configRef.value = {\n labelWidth: 120,\n rowKey: 'key',\n };\n frameRef.value = [];\n formDataRef.value = {};\n\n embeddedTableListRef.value = [];\n pageState.formLoading = true;\n formSaveVerifyJsRef.value = null;\n\n let result;\n if (newPagePaths.value.length === 1) {\n result = await getFormRenderDataApi(props.pageId, props.dataId ?? 'new', isAdd);\n } else {\n if (props.embeddedId === null) {\n msgTips.alert({\n msg: '数据结构异常',\n type: 'error'\n })\n console.error(props)\n return;\n }\n result = await getEmbeddedFormRenderDataApi(\n {\n embeddedId: props.embeddedId,\n pagePaths: newPagePaths.value,\n },\n props.dataId,\n isAdd,\n );\n }\n\n if (result.code === 0) {\n configRef.value = result.data.formConfig;\n formDataRef.value = JSON.parse(JSON.stringify(result.data.formData));\n\n // 流程按钮\n flowButtonRef.value = result.data.flowButton;\n /**\n * 表单功能按钮\n */\n formButtonsRef.value = Array.isArray(result.data.formButtons)\n ? JSON.parse(JSON.stringify(result.data.formButtons))\n : [];\n onNodeState.nodeId = result.data.editConfig.nodeId;\n onNodeState.nodeName = result.data.editConfig.nodeName;\n\n const {\n formRules,\n formSaveVerifyJs,\n componentShowRule,\n receiveBroadcasts,\n formButtons,\n } = await import(\n `${BASE_URL.value}/app/js/formRender/${props.pageId}/${props.dataId}?time=${getRandomString(3)}`\n );\n // 注入函数\n formButtonsRef.value.forEach((button) => {\n if (button.webTrigger && formButtons[button.id]) {\n button.webFunction = formButtons[button.id];\n }\n });\n\n formRuleRef.value = formRules;\n // 如果表单验证js不为空 则转换为js方法\n if (isNotEmpty(formSaveVerifyJs)) {\n formSaveVerifyJsRef.value = formSaveVerifyJs;\n }\n // 组件显示规则\n componentShowRuleRef.value = componentShowRule;\n\n const formFrameList = JSON.parse(JSON.stringify(result.data.formFrame));\n formFrameList.forEach((formFrame: FormFrame) => {\n formFrame.noticeReceive = receiveBroadcasts[formFrame.field];\n });\n frameRef.value = formFrameList;\n\n pageState.isEdit = result.data.editConfig.edit;\n pageState.editId = result.editId || '';\n\n await nextTick();\n // 初始化表单配置\n formRenderRef.value.initForm(formDataRef.value);\n\n fileUploadList.value = result.data.fileUploadList;\n\n await nextTick();\n embeddedTableListRef.value = result.data.embeddedTableList;\n } else {\n emits('close');\n }\n\n formDataRef.value = useSetDefaultValue(formDataRef.value, frameRef.value);\n pageState.formLoading = false;\n};\n\n/**\n * 表单数据保存\n */\nconst formDataSave = async () => {\n if (pageState.formLoading) {\n return;\n }\n if (!(await formRenderRef.value.validateForm())) return;\n pageState.formLoading = true;\n let result;\n if (newPagePaths.value.length === 1) {\n result = await saveFormDataApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n } else {\n if (props.embeddedId === null) {\n msgTips.alert({\n msg: '数据结构异常',\n type: 'error'\n })\n console.error(props)\n return\n }\n result = await saveEmbeddedTableFormDataApi(\n {\n embeddedId: props.embeddedId,\n pagePaths: props.pagePath,\n formData: formDataRef.value,\n },\n props.dataId,\n pageState.editId,\n isAdd,\n );\n }\n\n if (result.code === 0) {\n if (isAdd) {\n dataIdRef.value = result.data;\n isAdd = false;\n await nextTick();\n await initFormFrameAndData();\n }\n pageState.editId = result.editId || '';\n }\n pageState.formLoading = false;\n emits('dataChange');\n};\n\n/** 流程提交 */\nconst flowSubmitHandle = async () => {\n await formDataSave();\n if (pageState.formLoading) {\n return;\n }\n // 校验表单内容\n if (!(await formRenderRef.value.validateForm())) return;\n\n if (flowButtonRef.value.submitTips) {\n msgTips.alert({\n type: 'warning',\n title: '提示',\n msg: flowButtonRef.value.submitTips,\n callback: () => {\n submitCheck();\n },\n });\n } else {\n await submitCheck();\n }\n};\n/**\n * 提交前检查\n */\nconst submitCheck = async () => {\n pageState.formLoading = true;\n const result = await submitBeforeCheckApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n flowUserDialogRef.value.openDialog(result.data.nodeFlowProcessors, true);\n }\n pageState.formLoading = false;\n};\n\n/** 流程退回 */\nconst flowBackHandle = async () => {\n await formDataSave();\n if (pageState.formLoading) {\n return;\n }\n\n if (flowButtonRef.value.backTips) {\n msgTips.alert({\n type: 'warning',\n title: '提示',\n msg: flowButtonRef.value.backTips,\n callback: () => {\n backCheck();\n },\n });\n } else {\n await backCheck();\n }\n};\n\n/**\n * 退回前检查\n */\nconst backCheck = async () => {\n pageState.formLoading = true;\n const result = await backBeforeCheckApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n flowUserDialogRef.value.openDialog(result.data.nodeFlowProcessors, false);\n }\n pageState.formLoading = false;\n};\n\n/**\n * 提交流程\n *\n * @param submitNodeId\n * @param submitUsers\n * @param suggestion\n * @param submit\n */\nconst submitFlow = async (\n submitNodeId: string,\n submitUsers: string[],\n suggestion: string,\n submit: boolean,\n) => {\n if (pageState.formLoading) {\n return;\n }\n flowUserDialogRef.value.openLoading();\n pageState.formLoading = true;\n\n const result = await (submit\n ? submitFlowApi({\n pageId: props.pageId,\n dataId: props.dataId,\n nodeId: onNodeState.nodeId,\n toNodeId: submitNodeId,\n userId: submitUsers,\n suggestion,\n formData: formDataRef.value,\n })\n : backFlowApi({\n pageId: props.pageId,\n dataId: props.dataId,\n nodeId: onNodeState.nodeId,\n toNodeId: submitNodeId,\n userId: submitUsers,\n suggestion,\n formData: formDataRef.value,\n }));\n\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n await sleep(0.2);\n flowUserDialogRef.value.closeDialog();\n await initFormFrameAndData();\n }\n flowUserDialogRef.value.closeLoading();\n pageState.formLoading = false;\n};\n\n/**\n * 表单按钮\n *\n * @param button\n */\nconst formButtonClick = (button: KeButton) => {\n if (pageState.formLoading) {\n return;\n }\n\n executeFormButton(button);\n};\n\n/**\n * 执行按钮程序\n *\n * @param button\n */\nconst executeFormButton = async (button: KeButton) => {\n if (pageState.formLoading) {\n return;\n }\n pageState.formLoading = true;\n\n button.params = { pageId: props.pageId, dataId: props.dataId };\n // 调用执行按钮程序\n await useButtonExec(formDataRef.value, button);\n\n pageState.formLoading = false;\n};\n\n/**\n * 初始化\n */\nconst initForm = (isNew: boolean) => {\n isAdd = isNew;\n initFormFrameAndData();\n};\n/**\n * 刷新\n */\nconst refresh = () => {\n initFormFrameAndData();\n};\n/**\n * 改变全屏\n */\nconst fullScreenChange = () => {\n emits('fullScreenChange');\n};\n\n/**\n * 关闭表单\n */\nconst closeWindow = () => {\n emits('close');\n};\n\nonMounted(() => {\n const SCROLL_HIDE_DELAY = 300; // ms\n const scrollTimeoutMap = new Map<Element, ReturnType<typeof setTimeout>>();\n\n const panes = document.querySelectorAll('.el-tab-pane');\n panes.forEach((pane) => {\n const onScroll = () => {\n pane.classList.add('scrolling');\n if (scrollTimeoutMap.has(pane)) {\n clearTimeout(scrollTimeoutMap.get(pane));\n }\n const timeout = setTimeout(() => {\n pane.classList.remove('scrolling');\n }, SCROLL_HIDE_DELAY);\n scrollTimeoutMap.set(pane, timeout);\n };\n pane.addEventListener('scroll', onScroll);\n // 保存回收方法\n (pane as any).__onScrollHandler__ = onScroll;\n });\n});\n\nonBeforeUnmount(() => {\n const panes = document.querySelectorAll('.el-tab-pane');\n panes.forEach((pane) => {\n if ((pane as any).__onScrollHandler__) {\n pane.removeEventListener('scroll', (pane as any).__onScrollHandler__);\n delete (pane as any).__onScrollHandler__;\n }\n });\n});\n\ndefineExpose({ initForm, refresh });\n</script>\n\n<template>\n <div class=\"app-form-render\" v-loading=\"pageState.formLoading\">\n <div class=\"app-header\">\n <el-scrollbar class=\"left\">\n <el-tooltip\n effect=\"dark\"\n content=\"刷新\"\n placement=\"top-start\"\n >\n<!-- <el-button @click=\"refresh\" :icon=\"Refresh\" />-->\n <el-button-plus @click=\"refresh\" icon=\"tdesign:refresh\" />\n </el-tooltip>\n <el-tooltip\n v-if=\"pageState.isEdit\"\n effect=\"dark\"\n content=\"保存\"\n placement=\"top-start\"\n >\n<!-- <el-button type=\"primary\" @click=\"formDataSave\" :icon=\"Save\" />-->\n <el-button-plus type=\"primary\" @click=\"formDataSave\" icon=\"ci:save\" />\n </el-tooltip>\n <el-button\n v-if=\"flowButtonRef && isNotEmpty(flowButtonRef.submitLabel)\"\n type=\"primary\"\n @click=\"flowSubmitHandle\"\n >\n {{ flowButtonRef.submitLabel }}\n </el-button>\n <el-button\n v-if=\"flowButtonRef && isNotEmpty(flowButtonRef.backLabel)\"\n type=\"danger\"\n @click=\"flowBackHandle\"\n >\n {{ flowButtonRef.backLabel }}\n </el-button>\n <el-button\n v-for=\"btn in formButtonsRef\"\n :key=\"btn.id\"\n :type=\"btn.type\"\n @click=\"formButtonClick(btn)\"\n >\n {{ btn.label }}\n </el-button>\n </el-scrollbar>\n <div v-if=\"showWindowButton\" class=\"right\">\n <el-button @click=\"fullScreenChange\">\n {{ isFullScreen ? '缩小' : '全屏' }}\n </el-button>\n <el-button type=\"danger\" @click=\"closeWindow\">\n 关闭\n </el-button>\n </div>\n </div>\n <el-tabs v-model=\"activeName\" class=\"form-container\">\n <el-tab-pane :label=\"formTabName\" name=\"Form\">\n <FormRender\n ref=\"formRenderRef\"\n v-model:data=\"formDataRef\"\n :component-show-rule=\"componentShowRuleRef\"\n :config=\"configRef\"\n :form-rules=\"formRuleRef\"\n :form-save-verify-js=\"formSaveVerifyJsRef\"\n :frame=\"frameRef\"\n :page-id=\"pageId\"\n style=\"margin-top: 15px\"\n />\n </el-tab-pane>\n <slot name=\"default\"></slot>\n <el-tab-pane v-if=\"fileUploadList && fileUploadList.length > 0\" label=\"附件上传\" lazy>\n <FileIsland\n :page-id=\"pageId\"\n :data-id=\"dataId\"\n :file-kinds=\"fileUploadList\"\n />\n </el-tab-pane>\n <el-tab-pane\n v-for=\"em in embeddedTableListRef\"\n :key=\"em.embeddedId\"\n :label=\"em.tabTitle\"\n :lazy=\"true\"\n :name=\"em.embeddedId\"\n style=\"height: 100%\"\n >\n <EmbeddedTable :embedded-id=\"em.embeddedId\" :page-path=\"newPagePaths\" />\n </el-tab-pane>\n <el-tab-pane\n v-if=\"configRef.startOA && onNodeState.nodeId\"\n label=\"批阅记录\"\n lazy\n >\n <ApprovalRecord :page-id=\"pageId\" :data-id=\"dataId\" />\n </el-tab-pane>\n </el-tabs>\n <FlowUserDialog ref=\"flowUserDialogRef\" @submit=\"submitFlow\" />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.app-form-render {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden; // 防止它自己滚动\n}\n\n.app-header {\n display: flex;\n flex-wrap: wrap;\n padding-bottom: 6px;\n border-bottom: 2px solid var(--el-border-color);\n .left {\n flex-grow: 1; /* 占用剩余宽度 */\n }\n\n .right {\n flex-shrink: 0; /* 不收缩 */\n width: auto; /* 根据内容宽度撑开 */\n }\n}\n\n.form-buttons {\n //display: flex;\n margin-top: 8px;\n}\n.form-container {\n flex: 1 1 0;\n min-height: 0;\n overflow: hidden;\n\n :deep(.el-tabs__content) {\n height: 100%;\n }\n\n :deep(.el-tab-pane) {\n height: 100%;\n\n & > div {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n }\n\n :deep(.el-tabs__header) {\n margin: 0;\n }\n}\n/* 隐藏 .el-tab-pane 自身的滚动条 */\n:deep(.el-tab-pane) {\n height: 100%;\n overflow-y: auto;\n overflow-x: auto; /* 注意:你原本是 hidden,但设了 auto,建议统一 */\n // 隐藏滚动条但保留滚动功能\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE/Edge */\n}\n\n:deep(.el-tab-pane::-webkit-scrollbar) {\n //display: none; /* WebKit 浏览器隐藏滚动条 */\n}\n\n/* 👇 关键:恢复 el-table 内部滚动条的显示 */\n:deep(.el-table__body-wrapper) {\n scrollbar-width: auto;\n -ms-overflow-style: auto;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar) {\n display: block;\n width: 6px;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar-thumb) {\n background-color: rgba(0, 0, 0, 0.4);\n border-radius: 3px;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar-track) {\n background-color: transparent;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { ChartDataInterfaceDTO, ChartDTO } from '@/types';\n\nimport { onMounted, ref } from 'vue';\n\nimport { getAppChartContentApi } from '@/api';\nimport { BASE_URL } from '@/config';\nimport { getRandomString } from '@/utils';\n\nconst props = defineProps({\n chart: {\n type: Object as PropType<ChartDTO>,\n required: true,\n },\n});\n\nconst chartData = ref<ChartDataInterfaceDTO>({} as ChartDataInterfaceDTO);\nconst data = ref<any[]>([]);\nconst loading = ref(false);\n\nconst formattedData = async () => {\n if (chartData.value.formatterFunc) {\n const { formatterFunc } = await import(\n `${BASE_URL.value}/app/js/chart/${props.chart.id}?time=${getRandomString(3)}`\n );\n if (typeof formatterFunc === 'function') {\n data.value = formatterFunc(\n chartData.value.data,\n chartData.value.translationData,\n );\n }\n } else {\n data.value = chartData.value.data;\n }\n};\n\n/**\n * 初始化\n */\nconst init = async () => {\n loading.value = true;\n const result = await getAppChartContentApi(props.chart.id);\n if (result.code === 0) {\n chartData.value = result.data;\n await formattedData();\n }\n loading.value = false;\n};\n\nconst refresh = () => {\n init();\n};\n\ndefineExpose({\n refresh,\n});\n\nonMounted(() => {\n if (props.chart) {\n init();\n }\n});\n</script>\n\n<template>\n <div class=\"chart-container\" v-loading=\"loading\">\n <component :is=\"chart.chartType\" :data=\"data\" />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.chart-container {\n height: calc(100vh - 320px);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { ChartDataInterfaceDTO, ChartDTO } from '@/types';\n\nimport { onMounted, ref } from 'vue';\n\nimport { getAppChartContentApi } from '@/api';\nimport { BASE_URL } from '@/config';\nimport { getRandomString } from '@/utils';\n\nconst props = defineProps({\n chart: {\n type: Object as PropType<ChartDTO>,\n required: true,\n },\n});\n\nconst chartData = ref<ChartDataInterfaceDTO>({} as ChartDataInterfaceDTO);\nconst data = ref<any[]>([]);\nconst loading = ref(false);\n\nconst formattedData = async () => {\n if (chartData.value.formatterFunc) {\n const { formatterFunc } = await import(\n `${BASE_URL.value}/app/js/chart/${props.chart.id}?time=${getRandomString(3)}`\n );\n if (typeof formatterFunc === 'function') {\n data.value = formatterFunc(\n chartData.value.data,\n chartData.value.translationData,\n );\n }\n } else {\n data.value = chartData.value.data;\n }\n};\n\n/**\n * 初始化\n */\nconst init = async () => {\n loading.value = true;\n const result = await getAppChartContentApi(props.chart.id);\n if (result.code === 0) {\n chartData.value = result.data;\n await formattedData();\n }\n loading.value = false;\n};\n\nconst refresh = () => {\n init();\n};\n\ndefineExpose({\n refresh,\n});\n\nonMounted(() => {\n if (props.chart) {\n init();\n }\n});\n</script>\n\n<template>\n <div class=\"chart-container\" v-loading=\"loading\">\n <component :is=\"chart.chartType\" :data=\"data\" />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.chart-container {\n height: calc(100vh - 320px);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { ChartDTO } from '@/types';\n\nimport { ref } from 'vue';\n\nimport { CircleCloseFilled, Refresh } from '@element-plus/icons-vue';\nimport { isNotEmpty } from '@/utils';\n\nimport { getAppChartListApi } from '@/api';\n\nimport ChartRender from './ChartRender.vue';\n\nconst show = ref(false);\nlet isLoad = false;\nlet pageId: null | number = null;\nconst activeName = ref<null | number>(null);\nconst chartList = ref<ChartDTO[]>([]);\n\nconst chartRefs = ref<any>({});\n/**\n * 动态设置ref实例\n * @param el\n * @param c\n */\nconst setChartRef = (el: any, c: ChartDTO) => {\n chartRefs.value[`${c.id}ref`] = el;\n};\n\nconst refreshChart = () => {\n chartRefs.value[`${activeName.value}ref`].refresh();\n};\n\n/**\n * 加载数据\n */\nconst init = async () => {\n if (isNotEmpty(pageId)) {\n const result = await getAppChartListApi(pageId);\n if (result.code === 0) {\n chartList.value = result.data;\n isLoad = true;\n if (chartList.value.length > 0) {\n activeName.value = chartList.value[0].id;\n }\n }\n }\n};\n\nconst openDialog = (page: number) => {\n show.value = true;\n if (!isLoad) {\n pageId = page;\n init();\n }\n};\n\ndefineExpose({\n openDialog,\n});\n</script>\n\n<template>\n <el-dialog\n v-model=\"show\"\n :show-close=\"false\"\n align-center\n append-to-body\n width=\"80%\"\n >\n <template #header=\"{ close }\">\n <div class=\"my-header\">\n <div>\n <el-button :icon=\"Refresh\" @click=\"refreshChart\" />\n </div>\n <el-button :icon=\"CircleCloseFilled\" type=\"danger\" @click=\"close\" />\n </div>\n </template>\n <el-empty v-if=\"chartList.length === 0\" description=\"当前页面无图表\" />\n <el-tabs v-else v-model=\"activeName\" type=\"border-card\">\n <el-tab-pane\n v-for=\"chart in chartList\"\n :key=\"chart.id\"\n :label=\"chart.chartName\"\n :name=\"chart.id\"\n lazy\n >\n <ChartRender :ref=\"(el) => setChartRef(el, chart)\" :chart=\"chart\" />\n </el-tab-pane>\n </el-tabs>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.my-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n gap: 16px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { ChartDTO } from '@/types';\n\nimport { ref } from 'vue';\n\nimport { CircleCloseFilled, Refresh } from '@element-plus/icons-vue';\nimport { isNotEmpty } from '@/utils';\n\nimport { getAppChartListApi } from '@/api';\n\nimport ChartRender from './ChartRender.vue';\n\nconst show = ref(false);\nlet isLoad = false;\nlet pageId: null | number = null;\nconst activeName = ref<null | number>(null);\nconst chartList = ref<ChartDTO[]>([]);\n\nconst chartRefs = ref<any>({});\n/**\n * 动态设置ref实例\n * @param el\n * @param c\n */\nconst setChartRef = (el: any, c: ChartDTO) => {\n chartRefs.value[`${c.id}ref`] = el;\n};\n\nconst refreshChart = () => {\n chartRefs.value[`${activeName.value}ref`].refresh();\n};\n\n/**\n * 加载数据\n */\nconst init = async () => {\n if (isNotEmpty(pageId)) {\n const result = await getAppChartListApi(pageId);\n if (result.code === 0) {\n chartList.value = result.data;\n isLoad = true;\n if (chartList.value.length > 0) {\n activeName.value = chartList.value[0].id;\n }\n }\n }\n};\n\nconst openDialog = (page: number) => {\n show.value = true;\n if (!isLoad) {\n pageId = page;\n init();\n }\n};\n\ndefineExpose({\n openDialog,\n});\n</script>\n\n<template>\n <el-dialog\n v-model=\"show\"\n :show-close=\"false\"\n align-center\n append-to-body\n width=\"80%\"\n >\n <template #header=\"{ close }\">\n <div class=\"my-header\">\n <div>\n <el-button :icon=\"Refresh\" @click=\"refreshChart\" />\n </div>\n <el-button :icon=\"CircleCloseFilled\" type=\"danger\" @click=\"close\" />\n </div>\n </template>\n <el-empty v-if=\"chartList.length === 0\" description=\"当前页面无图表\" />\n <el-tabs v-else v-model=\"activeName\" type=\"border-card\">\n <el-tab-pane\n v-for=\"chart in chartList\"\n :key=\"chart.id\"\n :label=\"chart.chartName\"\n :name=\"chart.id\"\n lazy\n >\n <ChartRender :ref=\"(el) => setChartRef(el, chart)\" :chart=\"chart\" />\n </el-tab-pane>\n </el-tabs>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.my-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n gap: 16px;\n}\n</style>\n","<script setup lang=\"ts\">\r\nimport { reactive, ref } from 'vue';\r\n\r\nimport AppFormRender from '../AppFormRender.vue';\r\n\r\nconst emits = defineEmits(['dataChange']);\r\n\r\nconst AppFormRenderRef = ref();\r\nconst drawerState = ref(false);\r\nconst pageState = reactive({\r\n isFullScreen: false,\r\n pageId: 0,\r\n dataId: '',\r\n});\r\n\r\n/**\r\n * 当前数据在表格的索引\r\n */\r\nlet onDataRowIndex = -1;\r\n\r\nconst dataChange = () => {\r\n emits('dataChange', onDataRowIndex);\r\n};\r\n\r\ninterface OpenForm {\r\n /**\r\n * 主键\r\n */\r\n rowKey: any;\r\n /**\r\n * 页面ID\r\n */\r\n pageId: number;\r\n /**\r\n * 行数\r\n */\r\n rowIndex: number;\r\n}\r\n/**\r\n * 打开抽屉\r\n *\r\n * @param params\r\n */\r\nconst openForm = (params: OpenForm) => {\r\n const isAdd = typeof params.rowKey === 'boolean';\r\n pageState.dataId = isAdd ? 'new' : params.rowKey;\r\n pageState.pageId = params.pageId;\r\n drawerState.value = true;\r\n onDataRowIndex = params.rowIndex;\r\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\r\n};\r\n\r\nconst close = () => {\r\n drawerState.value = false;\r\n};\r\n\r\ndefineExpose({ openForm });\r\n</script>\r\n\r\n<template>\r\n <el-dialog\r\n v-model=\"drawerState\"\r\n :close-on-click-modal=\"false\"\r\n :show-close=\"false\"\r\n :width=\"pageState.isFullScreen ? '100%' : '70%'\"\r\n append-to-body\r\n align-center\r\n >\r\n <div class=\"dialog-form-container\">\r\n <AppFormRender\r\n ref=\"AppFormRenderRef\"\r\n v-model:data-id=\"pageState.dataId\"\r\n :is-full-screen=\"pageState.isFullScreen\"\r\n :page-id=\"pageState.pageId\"\r\n :page-path=\"[]\"\r\n @close=\"close\"\r\n @data-change=\"dataChange\"\r\n @full-screen-change=\"pageState.isFullScreen = !pageState.isFullScreen\"\r\n />\r\n </div>\r\n </el-dialog>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.dialog-form-container {\r\n height: 80vh;\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport { reactive, ref } from 'vue';\r\n\r\nimport AppFormRender from '../AppFormRender.vue';\r\n\r\nconst emits = defineEmits(['dataChange']);\r\n\r\nconst AppFormRenderRef = ref();\r\nconst drawerState = ref(false);\r\nconst pageState = reactive({\r\n isFullScreen: false,\r\n pageId: 0,\r\n dataId: '',\r\n});\r\n\r\n/**\r\n * 当前数据在表格的索引\r\n */\r\nlet onDataRowIndex = -1;\r\n\r\nconst dataChange = () => {\r\n emits('dataChange', onDataRowIndex);\r\n};\r\n\r\ninterface OpenForm {\r\n /**\r\n * 主键\r\n */\r\n rowKey: any;\r\n /**\r\n * 页面ID\r\n */\r\n pageId: number;\r\n /**\r\n * 行数\r\n */\r\n rowIndex: number;\r\n}\r\n/**\r\n * 打开抽屉\r\n *\r\n * @param params\r\n */\r\nconst openForm = (params: OpenForm) => {\r\n const isAdd = typeof params.rowKey === 'boolean';\r\n pageState.dataId = isAdd ? 'new' : params.rowKey;\r\n pageState.pageId = params.pageId;\r\n drawerState.value = true;\r\n onDataRowIndex = params.rowIndex;\r\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\r\n};\r\n\r\nconst close = () => {\r\n drawerState.value = false;\r\n};\r\n\r\ndefineExpose({ openForm });\r\n</script>\r\n\r\n<template>\r\n <el-dialog\r\n v-model=\"drawerState\"\r\n :close-on-click-modal=\"false\"\r\n :show-close=\"false\"\r\n :width=\"pageState.isFullScreen ? '100%' : '70%'\"\r\n append-to-body\r\n align-center\r\n >\r\n <div class=\"dialog-form-container\">\r\n <AppFormRender\r\n ref=\"AppFormRenderRef\"\r\n v-model:data-id=\"pageState.dataId\"\r\n :is-full-screen=\"pageState.isFullScreen\"\r\n :page-id=\"pageState.pageId\"\r\n :page-path=\"[]\"\r\n @close=\"close\"\r\n @data-change=\"dataChange\"\r\n @full-screen-change=\"pageState.isFullScreen = !pageState.isFullScreen\"\r\n />\r\n </div>\r\n </el-dialog>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.dialog-form-container {\r\n height: 80vh;\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\nimport { reactive, ref } from 'vue';\n\nimport AppFormRender from '../AppFormRender.vue';\n\ninterface Props {\n appendToBody?: boolean;\n closeOnClickModal?: boolean;\n}\n\nwithDefaults(defineProps<Props>(), {\n appendToBody: false,\n closeOnClickModal: false,\n});\n\nconst emits = defineEmits(['dataChange']);\n\nconst AppFormRenderRef = ref();\nconst drawerState = ref(false);\nconst pageState = reactive({\n isFullScreen: false,\n pageId: 0,\n dataId: '',\n});\n\n/**\n * 当前数据在表格的索引\n */\nlet onDataRowIndex = -1;\n\nconst dataChange = () => {\n emits('dataChange', onDataRowIndex);\n};\n\ninterface OpenForm {\n /**\n * 主键\n */\n rowKey: any;\n /**\n * 页面ID\n */\n pageId: number;\n /**\n * 行数\n */\n rowIndex: number;\n}\n/**\n * 打开抽屉\n *\n * @param params\n */\nconst openForm = (params: OpenForm) => {\n const isAdd = typeof params.rowKey === 'boolean';\n pageState.dataId = isAdd ? 'new' : params.rowKey;\n pageState.pageId = params.pageId;\n drawerState.value = true;\n onDataRowIndex = params.rowIndex;\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\n};\n\nconst close = () => {\n drawerState.value = false;\n};\n\ndefineExpose({ openForm });\n</script>\n\n<template>\n <el-drawer\n v-model=\"drawerState\"\n :close-on-click-modal=\"closeOnClickModal\"\n :show-close=\"false\"\n :size=\"pageState.isFullScreen ? '100%' : '70%'\"\n :with-header=\"false\"\n resizable\n :append-to-body=\"appendToBody\"\n >\n <AppFormRender\n ref=\"AppFormRenderRef\"\n v-model:data-id=\"pageState.dataId\"\n :is-full-screen=\"pageState.isFullScreen\"\n :page-id=\"pageState.pageId\"\n :page-path=\"[]\"\n @close=\"close\"\n @data-change=\"dataChange\"\n @full-screen-change=\"pageState.isFullScreen = !pageState.isFullScreen\"\n />\n </el-drawer>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport { reactive, ref } from 'vue';\n\nimport AppFormRender from '../AppFormRender.vue';\n\ninterface Props {\n appendToBody?: boolean;\n closeOnClickModal?: boolean;\n}\n\nwithDefaults(defineProps<Props>(), {\n appendToBody: false,\n closeOnClickModal: false,\n});\n\nconst emits = defineEmits(['dataChange']);\n\nconst AppFormRenderRef = ref();\nconst drawerState = ref(false);\nconst pageState = reactive({\n isFullScreen: false,\n pageId: 0,\n dataId: '',\n});\n\n/**\n * 当前数据在表格的索引\n */\nlet onDataRowIndex = -1;\n\nconst dataChange = () => {\n emits('dataChange', onDataRowIndex);\n};\n\ninterface OpenForm {\n /**\n * 主键\n */\n rowKey: any;\n /**\n * 页面ID\n */\n pageId: number;\n /**\n * 行数\n */\n rowIndex: number;\n}\n/**\n * 打开抽屉\n *\n * @param params\n */\nconst openForm = (params: OpenForm) => {\n const isAdd = typeof params.rowKey === 'boolean';\n pageState.dataId = isAdd ? 'new' : params.rowKey;\n pageState.pageId = params.pageId;\n drawerState.value = true;\n onDataRowIndex = params.rowIndex;\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\n};\n\nconst close = () => {\n drawerState.value = false;\n};\n\ndefineExpose({ openForm });\n</script>\n\n<template>\n <el-drawer\n v-model=\"drawerState\"\n :close-on-click-modal=\"closeOnClickModal\"\n :show-close=\"false\"\n :size=\"pageState.isFullScreen ? '100%' : '70%'\"\n :with-header=\"false\"\n resizable\n :append-to-body=\"appendToBody\"\n >\n <AppFormRender\n ref=\"AppFormRenderRef\"\n v-model:data-id=\"pageState.dataId\"\n :is-full-screen=\"pageState.isFullScreen\"\n :page-id=\"pageState.pageId\"\n :page-path=\"[]\"\n @close=\"close\"\n @data-change=\"dataChange\"\n @full-screen-change=\"pageState.isFullScreen = !pageState.isFullScreen\"\n />\n </el-drawer>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\r\nimport type { VxeGridProps } from 'vxe-table';\r\n\r\nimport { ApiInterface, KeButton, TableQueryFrame, Pagination, TableRenderApiDTO } from '@/types';\r\n\r\nimport { onMounted, ref, useTemplateRef } from 'vue';\r\nimport { useRequest } from 'vue-hooks-plus';\r\n\r\nimport { PieChart } from '@element-plus/icons-vue';\r\n\r\nimport { getTableRenderApi } from '@/api';\r\nimport { ChartList } from '@/components/AppComponent/components/chartList/index';\r\nimport DialogForm from '@/components/AppComponent/components/DialogForm.vue';\r\nimport DrawerForm from '@/components/AppComponent/components/DrawerForm.vue';\r\nimport {\r\n updateDataByRowIndex,\r\n useConfigurationProcess,\r\n useTableData,\r\n} from '@/components/AppComponent/hooks/useTable.hook';\r\nimport { BASE_URL } from '@/config';\r\nimport { TableCardRender, TableRender } from '@/components/TableComponent';\r\nimport { getRandomString } from '@/utils';\r\n\r\nimport { QueryTreeFilter } from '@/components/QueryComponent/QueryTreeFilter';\r\n\r\ndefineOptions({\r\n name: 'AppTableRender',\r\n});\r\n\r\nconst componentMap: Record<string, any> = {\r\n TableRender,\r\n TableCardRender,\r\n};\r\n\r\ninterface Props {\r\n pageId: number;\r\n emPageId?: number | null;\r\n}\r\n\r\nwithDefaults(defineProps<Props>(), {\r\n emPageId: null,\r\n});\r\n\r\nconst pageId = defineModel<number>('pageId')\r\nconst appFormWindowRef = ref();\r\nconst tableRef = ref();\r\n\r\nconst gridOptions = ref<VxeGridProps>({\r\n columns: [],\r\n seqConfig: {\r\n startIndex: 0,\r\n },\r\n exportConfig: {\r\n excludeFields: ['tableButtonOperate'],\r\n },\r\n});\r\n\r\nconst columns = ref<any[]>([]);\r\nconst queryConfig = ref<TableQueryFrame[]>([]);\r\nconst tableToolButtons = ref<KeButton[]>([]);\r\nconst tableRowButtons = ref<KeButton[]>([]);\r\nconst pagination = ref<Pagination>({\r\n /**\r\n * 当前页\r\n */\r\n currentPage: 1,\r\n /**\r\n * 分页大小\r\n */\r\n pageSize: 10,\r\n /**\r\n * 总数\r\n */\r\n total: 0,\r\n});\r\n\r\nconst queryTreeFilter = useTemplateRef('queryTreeFilter');\r\n\r\nconst { tableData, syncTableData, btnClickFunc, tableConfig } =\r\n useTableData({\r\n pageId,\r\n queryTreeFilter,\r\n pagination,\r\n appFormWindowRef,\r\n });\r\n\r\n/** 获取table渲染相关配置 */\r\nconst { runAsync: getTableRender, loading: renderLoading } = useRequest(\r\n () => getTableRenderApi(<number>pageId.value),\r\n {\r\n manual: true,\r\n cacheKey: `table-render-${pageId.value}`,\r\n onSuccess: async (result: ApiInterface<TableRenderApiDTO>) => {\r\n if (result.code === 0) {\r\n const { tableButtons: modules } = await import(\r\n `${BASE_URL.value}/app/js/table/${pageId.value}?time=${getRandomString(3)}`\r\n );\r\n const configCacheValue = useConfigurationProcess(\r\n result.data,\r\n <number>pageId.value,\r\n btnClickFunc,\r\n modules,\r\n treeLazyLoad,\r\n );\r\n\r\n tableConfig.value = result.data.tableConfig;\r\n tableConfig.value.pageId = pageId.value;\r\n queryConfig.value = result.data.queryFrameList;\r\n columns.value = configCacheValue.gridOptions.columns!;\r\n gridOptions.value = configCacheValue.gridOptions;\r\n gridOptions.value.columns = [];\r\n tableToolButtons.value = configCacheValue.tableToolButtons;\r\n tableRowButtons.value = configCacheValue.tableRowButtons;\r\n }\r\n\r\n syncTableData();\r\n },\r\n },\r\n);\r\n\r\nconst chartListRef = useTemplateRef('chartList');\r\n\r\n/**\r\n * 指定行数据更新\r\n * @param rowIndex\r\n */\r\nconst onDataChange = (rowIndex: number) => {\r\n if (rowIndex < 0 || !rowIndex) {\r\n syncTableData();\r\n return;\r\n }\r\n updateDataByRowIndex({\r\n rowIndex,\r\n tableConfig,\r\n tableData,\r\n });\r\n};\r\n\r\n/**\r\n * 懒加载tree数据\r\n */\r\nconst treeLazyLoad = async (\r\n treeNode: unknown,\r\n resolve: (data: any[]) => void,\r\n queryData: any,\r\n) => {\r\n await syncTableData(queryData, resolve, treeNode);\r\n};\r\n\r\n/**\r\n * 当检测到值改变\r\n * @param _fieldName\r\n * @param _newValue\r\n * @param _rowId\r\n */\r\nconst onValueChange = (\r\n _fieldName: string,\r\n _newValue: any,\r\n _rowId: string,\r\n) => {};\r\n\r\nconst chart = {\r\n open: () => {\r\n if (chartListRef.value) {\r\n chartListRef.value.openDialog(<number>pageId.value);\r\n }\r\n },\r\n};\r\n\r\nonMounted(async () => {\r\n tableConfig.value.pageId = pageId.value;\r\n\r\n await getTableRender();\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"app-table-render-container\" v-loading=\"renderLoading\">\r\n <el-splitter>\r\n <el-splitter-panel\r\n v-if=\"pageId && tableConfig.hasQueryTreeFilter\"\r\n collapsible\r\n size=\"240\"\r\n >\r\n <QueryTreeFilter ref=\"queryTreeFilter\" :page-id=\"pageId\" />\r\n </el-splitter-panel>\r\n <el-splitter-panel v-if=\"tableConfig.rowKey\">\r\n <component\r\n :is=\"componentMap[tableConfig.showType]\"\r\n ref=\"tableRef\"\r\n :columns=\"columns\"\r\n :query-config=\"queryConfig\"\r\n :table-config=\"tableConfig\"\r\n :table-data=\"tableData\"\r\n :table-id=\"pageId\"\r\n :table-pagination=\"pagination\"\r\n :table-row-buttons=\"tableRowButtons\"\r\n :table-tool-buttons=\"tableToolButtons\"\r\n :vxe-grid-options=\"gridOptions\"\r\n @query-click=\"syncTableData\"\r\n @value-change=\"onValueChange\"\r\n >\r\n <template #tool-bar>\r\n <el-button :icon=\"PieChart\" @click=\"chart.open\" />\r\n </template>\r\n </component>\r\n </el-splitter-panel>\r\n </el-splitter>\r\n <div class=\"drawer-container\">\r\n <DrawerForm\r\n v-if=\"\r\n !tableConfig.formWindow || tableConfig.formWindow === 'DrawerForm'\r\n \"\r\n ref=\"appFormWindowRef\"\r\n @data-change=\"onDataChange\"\r\n />\r\n <DialogForm v-else ref=\"appFormWindowRef\" @data-change=\"onDataChange\" />\r\n </div>\r\n <ChartList ref=\"chartList\" />\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.app-table-render-container {\r\n position: relative;\r\n display: flex;\r\n height: 100%;\r\n padding: 0 0.4rem;\r\n}\r\n.query-tree {\r\n width: 240px;\r\n}\r\n.page-root {\r\n flex: 1; /* 剩余空间 */\r\n //width: 100%;\r\n min-width: 0; /* 避免内容强制撑开 */\r\n max-width: 100%; /* 防止过大 */\r\n transition: width 0.1s linear; /* 平滑宽度变化,消除卡顿感 */\r\n}\r\n.drawer-container {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n z-index: 100;\r\n transform: translateZ(0);\r\n overflow: hidden;\r\n pointer-events: none;\r\n :deep(.el-drawer__container) {\r\n pointer-events: auto;\r\n }\r\n :deep(.el-overlay) {\r\n pointer-events: auto;\r\n }\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport type { VxeGridProps } from 'vxe-table';\r\n\r\nimport { ApiInterface, KeButton, TableQueryFrame, Pagination, TableRenderApiDTO } from '@/types';\r\n\r\nimport { onMounted, ref, useTemplateRef } from 'vue';\r\nimport { useRequest } from 'vue-hooks-plus';\r\n\r\nimport { PieChart } from '@element-plus/icons-vue';\r\n\r\nimport { getTableRenderApi } from '@/api';\r\nimport { ChartList } from '@/components/AppComponent/components/chartList/index';\r\nimport DialogForm from '@/components/AppComponent/components/DialogForm.vue';\r\nimport DrawerForm from '@/components/AppComponent/components/DrawerForm.vue';\r\nimport {\r\n updateDataByRowIndex,\r\n useConfigurationProcess,\r\n useTableData,\r\n} from '@/components/AppComponent/hooks/useTable.hook';\r\nimport { BASE_URL } from '@/config';\r\nimport { TableCardRender, TableRender } from '@/components/TableComponent';\r\nimport { getRandomString } from '@/utils';\r\n\r\nimport { QueryTreeFilter } from '@/components/QueryComponent/QueryTreeFilter';\r\n\r\ndefineOptions({\r\n name: 'AppTableRender',\r\n});\r\n\r\nconst componentMap: Record<string, any> = {\r\n TableRender,\r\n TableCardRender,\r\n};\r\n\r\ninterface Props {\r\n pageId: number;\r\n emPageId?: number | null;\r\n}\r\n\r\nwithDefaults(defineProps<Props>(), {\r\n emPageId: null,\r\n});\r\n\r\nconst pageId = defineModel<number>('pageId')\r\nconst appFormWindowRef = ref();\r\nconst tableRef = ref();\r\n\r\nconst gridOptions = ref<VxeGridProps>({\r\n columns: [],\r\n seqConfig: {\r\n startIndex: 0,\r\n },\r\n exportConfig: {\r\n excludeFields: ['tableButtonOperate'],\r\n },\r\n});\r\n\r\nconst columns = ref<any[]>([]);\r\nconst queryConfig = ref<TableQueryFrame[]>([]);\r\nconst tableToolButtons = ref<KeButton[]>([]);\r\nconst tableRowButtons = ref<KeButton[]>([]);\r\nconst pagination = ref<Pagination>({\r\n /**\r\n * 当前页\r\n */\r\n currentPage: 1,\r\n /**\r\n * 分页大小\r\n */\r\n pageSize: 10,\r\n /**\r\n * 总数\r\n */\r\n total: 0,\r\n});\r\n\r\nconst queryTreeFilter = useTemplateRef('queryTreeFilter');\r\n\r\nconst { tableData, syncTableData, btnClickFunc, tableConfig } =\r\n useTableData({\r\n pageId,\r\n queryTreeFilter,\r\n pagination,\r\n appFormWindowRef,\r\n });\r\n\r\n/** 获取table渲染相关配置 */\r\nconst { runAsync: getTableRender, loading: renderLoading } = useRequest(\r\n () => getTableRenderApi(<number>pageId.value),\r\n {\r\n manual: true,\r\n cacheKey: `table-render-${pageId.value}`,\r\n onSuccess: async (result: ApiInterface<TableRenderApiDTO>) => {\r\n if (result.code === 0) {\r\n const { tableButtons: modules } = await import(\r\n `${BASE_URL.value}/app/js/table/${pageId.value}?time=${getRandomString(3)}`\r\n );\r\n const configCacheValue = useConfigurationProcess(\r\n result.data,\r\n <number>pageId.value,\r\n btnClickFunc,\r\n modules,\r\n treeLazyLoad,\r\n );\r\n\r\n tableConfig.value = result.data.tableConfig;\r\n tableConfig.value.pageId = pageId.value;\r\n queryConfig.value = result.data.queryFrameList;\r\n columns.value = configCacheValue.gridOptions.columns!;\r\n gridOptions.value = configCacheValue.gridOptions;\r\n gridOptions.value.columns = [];\r\n tableToolButtons.value = configCacheValue.tableToolButtons;\r\n tableRowButtons.value = configCacheValue.tableRowButtons;\r\n }\r\n\r\n syncTableData();\r\n },\r\n },\r\n);\r\n\r\nconst chartListRef = useTemplateRef('chartList');\r\n\r\n/**\r\n * 指定行数据更新\r\n * @param rowIndex\r\n */\r\nconst onDataChange = (rowIndex: number) => {\r\n if (rowIndex < 0 || !rowIndex) {\r\n syncTableData();\r\n return;\r\n }\r\n updateDataByRowIndex({\r\n rowIndex,\r\n tableConfig,\r\n tableData,\r\n });\r\n};\r\n\r\n/**\r\n * 懒加载tree数据\r\n */\r\nconst treeLazyLoad = async (\r\n treeNode: unknown,\r\n resolve: (data: any[]) => void,\r\n queryData: any,\r\n) => {\r\n await syncTableData(queryData, resolve, treeNode);\r\n};\r\n\r\n/**\r\n * 当检测到值改变\r\n * @param _fieldName\r\n * @param _newValue\r\n * @param _rowId\r\n */\r\nconst onValueChange = (\r\n _fieldName: string,\r\n _newValue: any,\r\n _rowId: string,\r\n) => {};\r\n\r\nconst chart = {\r\n open: () => {\r\n if (chartListRef.value) {\r\n chartListRef.value.openDialog(<number>pageId.value);\r\n }\r\n },\r\n};\r\n\r\nonMounted(async () => {\r\n tableConfig.value.pageId = pageId.value;\r\n\r\n await getTableRender();\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"app-table-render-container\" v-loading=\"renderLoading\">\r\n <el-splitter>\r\n <el-splitter-panel\r\n v-if=\"pageId && tableConfig.hasQueryTreeFilter\"\r\n collapsible\r\n size=\"240\"\r\n >\r\n <QueryTreeFilter ref=\"queryTreeFilter\" :page-id=\"pageId\" />\r\n </el-splitter-panel>\r\n <el-splitter-panel v-if=\"tableConfig.rowKey\">\r\n <component\r\n :is=\"componentMap[tableConfig.showType]\"\r\n ref=\"tableRef\"\r\n :columns=\"columns\"\r\n :query-config=\"queryConfig\"\r\n :table-config=\"tableConfig\"\r\n :table-data=\"tableData\"\r\n :table-id=\"pageId\"\r\n :table-pagination=\"pagination\"\r\n :table-row-buttons=\"tableRowButtons\"\r\n :table-tool-buttons=\"tableToolButtons\"\r\n :vxe-grid-options=\"gridOptions\"\r\n @query-click=\"syncTableData\"\r\n @value-change=\"onValueChange\"\r\n >\r\n <template #tool-bar>\r\n <el-button :icon=\"PieChart\" @click=\"chart.open\" />\r\n </template>\r\n </component>\r\n </el-splitter-panel>\r\n </el-splitter>\r\n <div class=\"drawer-container\">\r\n <DrawerForm\r\n v-if=\"\r\n !tableConfig.formWindow || tableConfig.formWindow === 'DrawerForm'\r\n \"\r\n ref=\"appFormWindowRef\"\r\n @data-change=\"onDataChange\"\r\n />\r\n <DialogForm v-else ref=\"appFormWindowRef\" @data-change=\"onDataChange\" />\r\n </div>\r\n <ChartList ref=\"chartList\" />\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.app-table-render-container {\r\n position: relative;\r\n display: flex;\r\n height: 100%;\r\n padding: 0 0.4rem;\r\n}\r\n.query-tree {\r\n width: 240px;\r\n}\r\n.page-root {\r\n flex: 1; /* 剩余空间 */\r\n //width: 100%;\r\n min-width: 0; /* 避免内容强制撑开 */\r\n max-width: 100%; /* 防止过大 */\r\n transition: width 0.1s linear; /* 平滑宽度变化,消除卡顿感 */\r\n}\r\n.drawer-container {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n z-index: 100;\r\n transform: translateZ(0);\r\n overflow: hidden;\r\n pointer-events: none;\r\n :deep(.el-drawer__container) {\r\n pointer-events: auto;\r\n }\r\n :deep(.el-overlay) {\r\n pointer-events: auto;\r\n }\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport { computed, nextTick, onMounted, ref } from 'vue';\r\n\r\nconst props = defineProps<{\r\n componentName: any;\r\n componentProps?: Record<string, any>;\r\n onDestroy?: () => void;\r\n width?: string;\r\n}>();\r\n\r\nconst visible = ref(true);\r\nconst contentWrapperHeight = ref('80vh'); // 动态控制内容高度\r\n\r\n// 处理 componentProps,避免传递响应式对象给动态组件\r\nconst safeComponentProps = computed(() => {\r\n if (!props.componentProps) return {};\r\n // 浅拷贝 props,避免响应式传递问题\r\n return { ...props.componentProps };\r\n});\r\n\r\nconst name = computed(() => props.componentName);\r\n\r\nconst handleClosed = () => {\r\n // Dialog 关闭动画完成后,调用销毁函数\r\n if (props.onDestroy) {\r\n props.onDestroy();\r\n }\r\n};\r\n\r\n// 添加四角拖拽缩放功能\r\nonMounted(() => {\r\n nextTick(() => {\r\n const dialogElement = document.querySelector('.el-dialog') as HTMLElement;\r\n if (!dialogElement) return;\r\n\r\n // 创建四个角的拖拽手柄\r\n const corners = [\r\n { position: 'top-left', cursor: 'nwse-resize' },\r\n { position: 'top-right', cursor: 'nesw-resize' },\r\n { position: 'bottom-left', cursor: 'nesw-resize' },\r\n { position: 'bottom-right', cursor: 'nwse-resize' },\r\n ];\r\n\r\n corners.forEach(({ position, cursor }) => {\r\n const handle = document.createElement('div');\r\n handle.className = `resize-handle resize-handle-${position}`;\r\n handle.style.cssText = `\r\n position: absolute;\r\n width: 12px;\r\n height: 12px;\r\n cursor: ${cursor};\r\n z-index: 9999;\r\n `;\r\n\r\n // 设置手柄位置\r\n if (position.includes('top')) handle.style.top = '0';\r\n if (position.includes('bottom')) handle.style.bottom = '0';\r\n if (position.includes('left')) handle.style.left = '0';\r\n if (position.includes('right')) handle.style.right = '0';\r\n\r\n dialogElement.append(handle);\r\n\r\n // 添加拖拽事件\r\n let isResizing = false;\r\n let startX = 0;\r\n let startY = 0;\r\n let startWidth = 0;\r\n let startHeight = 0;\r\n let startLeft = 0;\r\n let startTop = 0;\r\n\r\n handle.addEventListener('mousedown', (e: MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n isResizing = true;\r\n\r\n startX = e.clientX;\r\n startY = e.clientY;\r\n startWidth = dialogElement.offsetWidth;\r\n startHeight = dialogElement.offsetHeight;\r\n startLeft = dialogElement.offsetLeft;\r\n startTop = dialogElement.offsetTop;\r\n\r\n const onMouseMove = (moveEvent: MouseEvent) => {\r\n if (!isResizing) return;\r\n\r\n const deltaX = moveEvent.clientX - startX;\r\n const deltaY = moveEvent.clientY - startY;\r\n\r\n let newWidth = startWidth;\r\n let newHeight = startHeight;\r\n let newLeft = startLeft;\r\n let newTop = startTop;\r\n\r\n // 根据不同的角落计算新的尺寸和位置\r\n if (position.includes('right')) {\r\n newWidth = startWidth + deltaX;\r\n }\r\n if (position.includes('left')) {\r\n newWidth = startWidth - deltaX;\r\n newLeft = startLeft + deltaX;\r\n }\r\n if (position.includes('bottom')) {\r\n newHeight = startHeight + deltaY;\r\n }\r\n if (position.includes('top')) {\r\n newHeight = startHeight - deltaY;\r\n newTop = startTop + deltaY;\r\n }\r\n\r\n // 设置最小尺寸\r\n const minWidth = 300;\r\n const minHeight = 200;\r\n\r\n if (newWidth >= minWidth) {\r\n dialogElement.style.width = `${newWidth}px`;\r\n if (position.includes('left')) {\r\n dialogElement.style.left = `${newLeft}px`;\r\n }\r\n }\r\n\r\n if (newHeight >= minHeight) {\r\n dialogElement.style.height = `${newHeight}px`;\r\n if (position.includes('top')) {\r\n dialogElement.style.top = `${newTop}px`;\r\n }\r\n\r\n // 动态更新内容区域高度\r\n updateContentHeight(dialogElement);\r\n }\r\n };\r\n\r\n const onMouseUp = () => {\r\n isResizing = false;\r\n document.removeEventListener('mousemove', onMouseMove);\r\n document.removeEventListener('mouseup', onMouseUp);\r\n };\r\n\r\n document.addEventListener('mousemove', onMouseMove);\r\n document.addEventListener('mouseup', onMouseUp);\r\n });\r\n });\r\n });\r\n});\r\n\r\n// 更新内容区域高度\r\nconst updateContentHeight = (dialogElement: HTMLElement) => {\r\n const dialogHeight = dialogElement.offsetHeight;\r\n const dialogHeader = dialogElement.querySelector(\r\n '.el-dialog__header',\r\n ) as HTMLElement;\r\n const dialogFooter = dialogElement.querySelector(\r\n '.el-dialog__footer',\r\n ) as HTMLElement;\r\n\r\n // 计算 header 和 footer 的高度\r\n const headerHeight = dialogHeader ? dialogHeader.offsetHeight : 0;\r\n const footerHeight = dialogFooter ? dialogFooter.offsetHeight : 0;\r\n\r\n // 减去 header、footer 和 padding\r\n const padding = 40; // dialog 的上下 padding\r\n const availableHeight = dialogHeight - headerHeight - footerHeight - padding;\r\n\r\n contentWrapperHeight.value = `${availableHeight}px`;\r\n};\r\n</script>\r\n\r\n<template>\r\n <el-dialog\r\n v-model=\"visible\"\r\n align-center\r\n append-to-body\r\n destroy-on-close\r\n draggable\r\n :width=\"width\"\r\n :close-on-click-modal=\"false\"\r\n :close-on-press-escape=\"false\"\r\n :modal=\"false\"\r\n @closed=\"handleClosed\"\r\n >\r\n <div\r\n class=\"dialog-content-wrapper\"\r\n :style=\"{ maxHeight: contentWrapperHeight }\"\r\n >\r\n <component :is=\"name\" v-bind=\"safeComponentProps\" />\r\n </div>\r\n </el-dialog>\r\n</template>\r\n<style lang=\"scss\" scoped>\r\n.dialog-content-wrapper {\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n padding: var(--el-dialog-padding-primary);\r\n transition: max-height 0.1s ease;\r\n}\r\n\r\n// 四角拖拽手柄样式\r\n:deep(.el-dialog) {\r\n position: relative;\r\n\r\n .resize-handle {\r\n &::after {\r\n content: '';\r\n position: absolute;\r\n width: 8px;\r\n height: 8px;\r\n background: transparent;\r\n border: 2px solid var(--el-color-primary);\r\n border-radius: 50%;\r\n opacity: 0;\r\n transition: opacity 0.2s;\r\n }\r\n\r\n &:hover::after {\r\n opacity: 0.6;\r\n }\r\n\r\n &.resize-handle-top-left::after {\r\n top: 2px;\r\n left: 2px;\r\n }\r\n\r\n &.resize-handle-top-right::after {\r\n top: 2px;\r\n right: 2px;\r\n }\r\n\r\n &.resize-handle-bottom-left::after {\r\n bottom: 2px;\r\n left: 2px;\r\n }\r\n\r\n &.resize-handle-bottom-right::after {\r\n bottom: 2px;\r\n right: 2px;\r\n }\r\n }\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport { computed, nextTick, onMounted, ref } from 'vue';\r\n\r\nconst props = defineProps<{\r\n componentName: any;\r\n componentProps?: Record<string, any>;\r\n onDestroy?: () => void;\r\n width?: string;\r\n}>();\r\n\r\nconst visible = ref(true);\r\nconst contentWrapperHeight = ref('80vh'); // 动态控制内容高度\r\n\r\n// 处理 componentProps,避免传递响应式对象给动态组件\r\nconst safeComponentProps = computed(() => {\r\n if (!props.componentProps) return {};\r\n // 浅拷贝 props,避免响应式传递问题\r\n return { ...props.componentProps };\r\n});\r\n\r\nconst name = computed(() => props.componentName);\r\n\r\nconst handleClosed = () => {\r\n // Dialog 关闭动画完成后,调用销毁函数\r\n if (props.onDestroy) {\r\n props.onDestroy();\r\n }\r\n};\r\n\r\n// 添加四角拖拽缩放功能\r\nonMounted(() => {\r\n nextTick(() => {\r\n const dialogElement = document.querySelector('.el-dialog') as HTMLElement;\r\n if (!dialogElement) return;\r\n\r\n // 创建四个角的拖拽手柄\r\n const corners = [\r\n { position: 'top-left', cursor: 'nwse-resize' },\r\n { position: 'top-right', cursor: 'nesw-resize' },\r\n { position: 'bottom-left', cursor: 'nesw-resize' },\r\n { position: 'bottom-right', cursor: 'nwse-resize' },\r\n ];\r\n\r\n corners.forEach(({ position, cursor }) => {\r\n const handle = document.createElement('div');\r\n handle.className = `resize-handle resize-handle-${position}`;\r\n handle.style.cssText = `\r\n position: absolute;\r\n width: 12px;\r\n height: 12px;\r\n cursor: ${cursor};\r\n z-index: 9999;\r\n `;\r\n\r\n // 设置手柄位置\r\n if (position.includes('top')) handle.style.top = '0';\r\n if (position.includes('bottom')) handle.style.bottom = '0';\r\n if (position.includes('left')) handle.style.left = '0';\r\n if (position.includes('right')) handle.style.right = '0';\r\n\r\n dialogElement.append(handle);\r\n\r\n // 添加拖拽事件\r\n let isResizing = false;\r\n let startX = 0;\r\n let startY = 0;\r\n let startWidth = 0;\r\n let startHeight = 0;\r\n let startLeft = 0;\r\n let startTop = 0;\r\n\r\n handle.addEventListener('mousedown', (e: MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n isResizing = true;\r\n\r\n startX = e.clientX;\r\n startY = e.clientY;\r\n startWidth = dialogElement.offsetWidth;\r\n startHeight = dialogElement.offsetHeight;\r\n startLeft = dialogElement.offsetLeft;\r\n startTop = dialogElement.offsetTop;\r\n\r\n const onMouseMove = (moveEvent: MouseEvent) => {\r\n if (!isResizing) return;\r\n\r\n const deltaX = moveEvent.clientX - startX;\r\n const deltaY = moveEvent.clientY - startY;\r\n\r\n let newWidth = startWidth;\r\n let newHeight = startHeight;\r\n let newLeft = startLeft;\r\n let newTop = startTop;\r\n\r\n // 根据不同的角落计算新的尺寸和位置\r\n if (position.includes('right')) {\r\n newWidth = startWidth + deltaX;\r\n }\r\n if (position.includes('left')) {\r\n newWidth = startWidth - deltaX;\r\n newLeft = startLeft + deltaX;\r\n }\r\n if (position.includes('bottom')) {\r\n newHeight = startHeight + deltaY;\r\n }\r\n if (position.includes('top')) {\r\n newHeight = startHeight - deltaY;\r\n newTop = startTop + deltaY;\r\n }\r\n\r\n // 设置最小尺寸\r\n const minWidth = 300;\r\n const minHeight = 200;\r\n\r\n if (newWidth >= minWidth) {\r\n dialogElement.style.width = `${newWidth}px`;\r\n if (position.includes('left')) {\r\n dialogElement.style.left = `${newLeft}px`;\r\n }\r\n }\r\n\r\n if (newHeight >= minHeight) {\r\n dialogElement.style.height = `${newHeight}px`;\r\n if (position.includes('top')) {\r\n dialogElement.style.top = `${newTop}px`;\r\n }\r\n\r\n // 动态更新内容区域高度\r\n updateContentHeight(dialogElement);\r\n }\r\n };\r\n\r\n const onMouseUp = () => {\r\n isResizing = false;\r\n document.removeEventListener('mousemove', onMouseMove);\r\n document.removeEventListener('mouseup', onMouseUp);\r\n };\r\n\r\n document.addEventListener('mousemove', onMouseMove);\r\n document.addEventListener('mouseup', onMouseUp);\r\n });\r\n });\r\n });\r\n});\r\n\r\n// 更新内容区域高度\r\nconst updateContentHeight = (dialogElement: HTMLElement) => {\r\n const dialogHeight = dialogElement.offsetHeight;\r\n const dialogHeader = dialogElement.querySelector(\r\n '.el-dialog__header',\r\n ) as HTMLElement;\r\n const dialogFooter = dialogElement.querySelector(\r\n '.el-dialog__footer',\r\n ) as HTMLElement;\r\n\r\n // 计算 header 和 footer 的高度\r\n const headerHeight = dialogHeader ? dialogHeader.offsetHeight : 0;\r\n const footerHeight = dialogFooter ? dialogFooter.offsetHeight : 0;\r\n\r\n // 减去 header、footer 和 padding\r\n const padding = 40; // dialog 的上下 padding\r\n const availableHeight = dialogHeight - headerHeight - footerHeight - padding;\r\n\r\n contentWrapperHeight.value = `${availableHeight}px`;\r\n};\r\n</script>\r\n\r\n<template>\r\n <el-dialog\r\n v-model=\"visible\"\r\n align-center\r\n append-to-body\r\n destroy-on-close\r\n draggable\r\n :width=\"width\"\r\n :close-on-click-modal=\"false\"\r\n :close-on-press-escape=\"false\"\r\n :modal=\"false\"\r\n @closed=\"handleClosed\"\r\n >\r\n <div\r\n class=\"dialog-content-wrapper\"\r\n :style=\"{ maxHeight: contentWrapperHeight }\"\r\n >\r\n <component :is=\"name\" v-bind=\"safeComponentProps\" />\r\n </div>\r\n </el-dialog>\r\n</template>\r\n<style lang=\"scss\" scoped>\r\n.dialog-content-wrapper {\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n padding: var(--el-dialog-padding-primary);\r\n transition: max-height 0.1s ease;\r\n}\r\n\r\n// 四角拖拽手柄样式\r\n:deep(.el-dialog) {\r\n position: relative;\r\n\r\n .resize-handle {\r\n &::after {\r\n content: '';\r\n position: absolute;\r\n width: 8px;\r\n height: 8px;\r\n background: transparent;\r\n border: 2px solid var(--el-color-primary);\r\n border-radius: 50%;\r\n opacity: 0;\r\n transition: opacity 0.2s;\r\n }\r\n\r\n &:hover::after {\r\n opacity: 0.6;\r\n }\r\n\r\n &.resize-handle-top-left::after {\r\n top: 2px;\r\n left: 2px;\r\n }\r\n\r\n &.resize-handle-top-right::after {\r\n top: 2px;\r\n right: 2px;\r\n }\r\n\r\n &.resize-handle-bottom-left::after {\r\n bottom: 2px;\r\n left: 2px;\r\n }\r\n\r\n &.resize-handle-bottom-right::after {\r\n bottom: 2px;\r\n right: 2px;\r\n }\r\n }\r\n}\r\n</style>\r\n","import AppFormRender from './AppFormRender.vue';\r\nimport AppTableRender from './AppTableRender.vue';\r\nimport DrawerForm from './components/DrawerForm.vue';\r\nimport DynamicDialogHost from './DynamicDialogHost.vue';\r\nimport type { App } from 'vue';\r\n\r\n(AppFormRender as any).name = 'AppFormRender';\r\n(AppTableRender as any).name = 'AppTableRender';\r\n(DrawerForm as any).name = 'DrawerForm';\r\n\r\nAppFormRender.install = (app: App) => {\r\n app.component('AppFormRender', AppFormRender);\r\n};\r\n\r\nAppTableRender.install = (app: App) => {\r\n app.component('AppTableRender', AppTableRender);\r\n};\r\n\r\nDrawerForm.install = (app: App) => {\r\n app.component('DrawerForm', DrawerForm);\r\n}\r\n\r\nexport { AppFormRender, AppTableRender, DrawerForm, DynamicDialogHost };\r\n","import { createVNode, markRaw, render } from 'vue';\r\n\r\nimport { getAppInstance, getRegisterComponent } from '@/config';\r\nimport { DynamicDialogHost } from \"@/components\";\r\n\r\nexport interface DialogOptions {\r\n name: string;\r\n componentProps?: Record<string, any>;\r\n width?: string;\r\n autoOpen?: boolean;\r\n}\r\n\r\nexport const createDynamicContentDialog = async ({\r\n name,\r\n componentProps = {},\r\n width = '80%',\r\n}: DialogOptions) => {\r\n const app = getAppInstance();\r\n const registerComponent = getRegisterComponent();\r\n\r\n if (registerComponent) {\r\n registerComponent(name);\r\n }\r\n\r\n // 为每个 dialog 创建独立的容器\r\n const container = document.createElement('div');\r\n container.className = 'dynamic-dialog-container';\r\n document.body.append(container);\r\n\r\n // 深度解除 componentProps 的响应式\r\n const rawProps = structuredClone({\r\n ...componentProps,\r\n });\r\n\r\n // 销毁函数\r\n const destroy = () => {\r\n render(null, container); // 卸载组件\r\n container.remove(); // 移除 DOM\r\n };\r\n\r\n // 增强 props,添加 close 事件监听\r\n const enhancedProps = {\r\n ...rawProps,\r\n onClose: () => {\r\n // 收到子组件的 close emit 后销毁实例\r\n destroy();\r\n },\r\n };\r\n\r\n // 创建 VNode\r\n const vnode = createVNode(markRaw(DynamicDialogHost), {\r\n componentName: name,\r\n componentProps: enhancedProps,\r\n width,\r\n onDestroy: destroy, // 传递销毁函数给 DynamicDialogHost\r\n });\r\n\r\n // 继承主应用的上下文(包含 Element Plus 全局组件)\r\n if (app) {\r\n vnode.appContext = (app as any)._context;\r\n }\r\n\r\n // 渲染到 DOM\r\n render(vnode, container);\r\n\r\n // 返回控制接口\r\n return {\r\n destroy,\r\n };\r\n};\r\n","/**\n * 睡眠\n *\n * @param time 秒\n */\nexport function sleep(time: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, time * 1000);\n });\n}\n","import { KeButton } from '@/types';\r\n\r\nimport { executeButtonProgramApi } from '@/api';\r\nimport { isEmpty, msgTips, createDynamicContentDialog, isNotEmpty } from '@/utils';\r\n\r\n/**\r\n * 单条数据上的按钮\r\n * @param data 数据\r\n * @param button 按钮配置\r\n * @param rowIndex 行索引\r\n */\r\nexport async function useButtonExec(\r\n data: any,\r\n button: KeButton,\r\n rowIndex?: number,\r\n) {\r\n // 前端按钮\r\n if (\r\n button.webTrigger && // 为空则停止运行\r\n isEmpty(button.webFunction)\r\n ) {\r\n return;\r\n }\r\n // 如果设置了触发前提示\r\n if (button.clickTips) {\r\n msgTips.alert({\r\n type: 'warning',\r\n msg: button.clickTips,\r\n callback: async () => {\r\n if (button.webTrigger) {\r\n // 执行前端函数\r\n execWebFunction(data, button, rowIndex);\r\n } else {\r\n // 后端方法\r\n await execServerButton(data, button);\r\n }\r\n },\r\n });\r\n } else if (button.webTrigger) {\r\n execWebFunction(data, button, rowIndex);\r\n // execWebFunction(data, button.params, rowIndex);\r\n } else {\r\n await execServerButton(data, button);\r\n }\r\n}\r\n\r\nfunction execWebFunction(data: any, button: KeButton, rowIndex?: number) {\r\n const toolPackage = {\r\n createDynamicContentDialog,\r\n };\r\n button.webFunction(data, button.params, rowIndex, toolPackage);\r\n}\r\n\r\n/**\r\n * 执行后端程序\r\n *\r\n * 直接暴力取data里面的pageId和dataId\r\n *\r\n * @param data\r\n * @param button\r\n */\r\nasync function execServerButton(data: any, button: KeButton) {\r\n console.error(button)\r\n let pageId = null;\r\n if (typeof button.params.pageId === 'number') {\r\n pageId = button.params.pageId;\r\n } else if (button.params[\"getPageId\"] && isNotEmpty(button.params[\"getPageId\"]())) {\r\n pageId = button.params[\"getPageId\"]()\r\n } else if (data.pageId?.value) {\r\n pageId = data.pageId.value;\r\n }\r\n const dataId = button.params.dataId || null;\r\n // 后端触发\r\n const result = await executeButtonProgramApi(pageId, dataId, button.id);\r\n if (\r\n result.code === 0 && // 如果有消息 则显示执行后的提示\r\n Array.isArray(result.data) &&\r\n result.data.length > 0\r\n ) {\r\n result.data.forEach((item: any) =>\r\n msgTips.tips({\r\n msg: item,\r\n type: 'info',\r\n duration: 5000,\r\n }),\r\n );\r\n }\r\n}\r\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { KeButton } from '../../types';\n\nimport { useButtonExec } from '../../hooks/useButtonExec.hook';\n\nimport { ElButtonPlus } from '../ElPlusComponent';\n\ndefineProps({\n toolButtons: {\n required: true,\n type: Array as PropType<KeButton[]>,\n },\n});\n\nconst btnClick = (data: any, button: any) => {\n useButtonExec(data, button);\n};\n</script>\n\n<template>\n <el-scrollbar class=\"tool-bar\">\n <div class=\"button-group\">\n <ElButtonPlus\n v-for=\"btn in toolButtons\"\n :key=\"btn.id\"\n :label=\"btn.label\"\n :icon=\"btn.icon\"\n :type=\"btn.type\"\n @click=\"btnClick(null, btn)\"\n />\n <slot name=\"custom-button\"></slot>\n </div>\n </el-scrollbar>\n</template>\n\n<style scoped lang=\"scss\">\n.tool-bar {\n padding: 8px;\n background: var(--el-fill-color-blank);\n\n :deep(.el-scrollbar__view) {\n display: flex;\n flex-direction: row-reverse;\n gap: 8px;\n justify-content: flex-start;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { KeButton } from '../../types';\n\nimport { useButtonExec } from '../../hooks/useButtonExec.hook';\n\nimport { ElButtonPlus } from '../ElPlusComponent';\n\ndefineProps({\n toolButtons: {\n required: true,\n type: Array as PropType<KeButton[]>,\n },\n});\n\nconst btnClick = (data: any, button: any) => {\n useButtonExec(data, button);\n};\n</script>\n\n<template>\n <el-scrollbar class=\"tool-bar\">\n <div class=\"button-group\">\n <ElButtonPlus\n v-for=\"btn in toolButtons\"\n :key=\"btn.id\"\n :label=\"btn.label\"\n :icon=\"btn.icon\"\n :type=\"btn.type\"\n @click=\"btnClick(null, btn)\"\n />\n <slot name=\"custom-button\"></slot>\n </div>\n </el-scrollbar>\n</template>\n\n<style scoped lang=\"scss\">\n.tool-bar {\n padding: 8px;\n background: var(--el-fill-color-blank);\n\n :deep(.el-scrollbar__view) {\n display: flex;\n flex-direction: row-reverse;\n gap: 8px;\n justify-content: flex-start;\n }\n}\n</style>\n","import ToolBar from './ToolBar.vue';\nimport type { App } from 'vue';\n\n(ToolBar as any).name = 'ToolBar';\n\nToolBar.install = (app: App) => {\n app.component('ToolBar', ToolBar);\n};\n\nexport { ToolBar };\n","/**\n * VXE Table/Grid 剪贴板插件\n * 支持拖动选中、复制粘贴、Shift/Ctrl多选功能\n * 基于视觉顺序(DOM顺序)进行选取,支持固定列和拖拽排序后的正确选取\n *\n * 使用方式:\n * <vxe-table v-clipboard=\"{ rowSelectColumn: 'seq', onCopy: handleCopy }\">\n * <vxe-grid v-clipboard=\"{ rowSelectColumn: 'seq', onCopy: handleCopy }\">\n */\n\nimport type { App, Ref } from 'vue'\n\n// 类型定义\nexport interface ClipboardOptions {\n /** 点击哪一列选中整行,支持列索引或字段名/类型,-1 禁用 */\n rowSelectColumn?: number | string\n /** 选中背景色 */\n selectedColor?: string\n /** 选区变化回调 */\n onSelectionChange?: (range: SelectedRange) => void\n /** 复制回调 */\n onCopy?: (data: CellValue[][]) => void\n /** 粘贴回调 */\n onPaste?: (data: PasteCellChange[]) => void\n /** 剪切回调 */\n onCut?: (data: CellValue[][]) => void\n}\n\nexport interface SelectedRange {\n startRow: number\n startCol: number\n endRow: number\n endCol: number\n cells: CellData[][]\n}\n\nexport interface CellData {\n row: number\n col: number\n field: string\n value: CellValue\n rowId: string\n colid: string\n}\n\n/** 粘贴单元格变更信息 */\nexport interface PasteCellChange {\n row: number\n col: number\n field: string\n oldValue: CellValue\n newValue: CellValue\n rowId: string\n rowData: Record<string, CellValue>\n}\n\nexport type CellValue = string | number | boolean | null | undefined\n\nexport interface ClipboardInstance {\n init: () => void\n destroy: () => void\n copy: () => CellValue[][]\n paste: () => Promise<PasteCellChange[]>\n cut: () => CellValue[][]\n clearSelection: () => void\n selectRow: (rowIndex: number) => void\n getSelectedRange: () => SelectedRange\n getClipboardData: () => CellValue[][]\n}\n\ninterface VxeTableInstance {\n getTableData: () => { fullData: Record<string, CellValue>[] }\n getTableColumn: () => { fullColumn: VxeColumn[]; visibleColumn: VxeColumn[] }\n reloadData: (data: Record<string, CellValue>[]) => void\n getRowById: (rowId: string) => Record<string, CellValue> | null\n}\n\ninterface VxeColumn {\n id?: string\n field?: string\n type?: string\n}\n\n// 插件默认配置\nconst defaultOptions: ClipboardOptions = {\n rowSelectColumn: -1,\n selectedColor: 'rgba(64, 158, 255, 0.25)',\n onSelectionChange: undefined,\n onCopy: undefined,\n onPaste: undefined,\n onCut: undefined\n}\n\n// 全局配置\nlet globalOptions: ClipboardOptions = { ...defaultOptions }\n\n// 存储实例映射\nconst instanceMap = new WeakMap<HTMLElement, ClipboardInstance>()\n\n// 解析剪贴板值,尝试还原原始类型\nconst parseClipboardValue = (value: string): CellValue => {\n const trimmed = value.trim()\n \n // 空值\n if (trimmed === '' || trimmed === 'null' || trimmed === 'undefined') {\n return trimmed === 'null' ? null : trimmed === 'undefined' ? undefined : ''\n }\n \n // 布尔值\n if (trimmed === 'true') return true\n if (trimmed === 'false') return false\n \n // 数值(整数或浮点数)\n if (/^-?\\d+(\\.\\d+)?$/.test(trimmed)) {\n const num = Number(trimmed)\n if (!Number.isNaN(num)) return num\n }\n \n // 默认返回字符串\n return value\n}\n\n// 注入样式\nconst STYLE_ID = 'vxe-table-clipboard-style'\nfunction injectStyles(options: ClipboardOptions): void {\n const oldStyle = document.getElementById(STYLE_ID)\n if (oldStyle) oldStyle.remove()\n\n const style = document.createElement('style')\n style.id = STYLE_ID\n style.textContent = `\n .cell-selected {\n background-color: ${options.selectedColor} !important;\n }\n .vxe-table-clipboard-enabled {\n user-select: none;\n -webkit-user-select: none;\n }\n .vxe-table-clipboard-enabled .vxe-cell--edit input,\n .vxe-table-clipboard-enabled .vxe-cell--edit textarea {\n user-select: text;\n -webkit-user-select: text;\n }\n `\n document.head.appendChild(style)\n}\n\n/**\n * 创建剪贴板实例\n */\nfunction createClipboardInstance(el: HTMLElement, options: ClipboardOptions = {}): ClipboardInstance {\n const config = { ...globalOptions, ...options }\n\n let isDragging = false\n let startCell: { visualRow: number; visualCol: number } | null = null\n let clipboardData: CellValue[][] = []\n let startFromRowSelectColumn = false\n\n // 当前选区(基于视觉索引)\n const selectedRange: SelectedRange = {\n startRow: -1,\n startCol: -1,\n endRow: -1,\n endCol: -1,\n cells: []\n }\n\n // 已选中的单元格集合 (key: \"visualRow-visualCol\")\n const selectedCellsSet = new Set<string>()\n\n // 锚点位置(视觉索引)\n let anchorRow = -1\n let anchorCol = -1\n\n // 获取 vxe-table/grid 实例\n const getTableInstance = (): VxeTableInstance | null => {\n const component = (el as any).__vueParentComponent\n return component?.exposed || component?.proxy || null\n }\n\n const preventDrag = (e: Event): void => {\n const target = e.target as Element\n if (target.closest('.vxe-row--drag-node, .vxe-column--drag-node, .sortable-handle, [draggable=\"true\"]')) {\n return\n }\n e.preventDefault()\n }\n\n const handleSelectStart = (e: Event): void => {\n if (isDragging) e.preventDefault()\n }\n\n // 获取所有可见行的 rowId 列表(按视觉顺序)\n const getVisualRowIds = (): string[] => {\n const tbody = el.querySelector('.vxe-table--body-wrapper tbody')\n if (!tbody) return []\n const rows = tbody.querySelectorAll('tr.vxe-body--row')\n return Array.from(rows).map(row => row.getAttribute('rowId') || '').filter(Boolean)\n }\n\n // 获取所有可见列的 colid 列表(按视觉顺序,合并固定列)\n const getVisualColIds = (): string[] => {\n const $table = getTableInstance()\n if ($table) {\n // 使用 visibleColumn 获取按视觉顺序排列的列\n const visibleColumns = $table.getTableColumn().visibleColumn || $table.getTableColumn().fullColumn\n return visibleColumns.map((col: VxeColumn) => col.id || '').filter(Boolean)\n }\n // 降级:从 DOM 获取\n const firstRow = el.querySelector('.vxe-table--body-wrapper tbody tr.vxe-body--row')\n if (!firstRow) return []\n const cells = firstRow.querySelectorAll('td.vxe-body--column')\n return Array.from(cells).map(cell => cell.getAttribute('colid') || '').filter(Boolean)\n }\n\n // 获取视觉行索引(基于 DOM 顺序)\n const getVisualRowIndex = (element: Element): number => {\n const row = element.closest('tr.vxe-body--row')\n if (!row) return -1\n const rowId = row.getAttribute('rowId')\n if (!rowId) return -1\n const visualRowIds = getVisualRowIds()\n return visualRowIds.indexOf(rowId)\n }\n\n // 获取视觉列索引(基于可见列顺序)\n const getVisualColIndex = (element: Element): number => {\n const cell = element.closest('td.vxe-body--column')\n if (!cell) return -1\n const colid = cell.getAttribute('colid')\n if (!colid) return -1\n const visualColIds = getVisualColIds()\n return visualColIds.indexOf(colid)\n }\n\n const getCellPosition = (target: EventTarget | null): { visualRow: number; visualCol: number } | null => {\n if (!(target instanceof Element)) return null\n const cell = target.closest('td.vxe-body--column')\n if (!cell) return null\n const visualRow = getVisualRowIndex(cell)\n const visualCol = getVisualColIndex(cell)\n if (visualRow === -1 || visualCol === -1) return null\n return { visualRow, visualCol }\n }\n\n const getTotalColumns = (): number => {\n return getVisualColIds().length\n }\n\n const getTotalRows = (): number => {\n return getVisualRowIds().length\n }\n\n const cellKey = (row: number, col: number): string => `${row}-${col}`\n\n const clearSelection = (): void => {\n el.querySelectorAll('.cell-selected').forEach((cell) => cell.classList.remove('cell-selected'))\n selectedRange.startRow = -1\n selectedRange.startCol = -1\n selectedRange.endRow = -1\n selectedRange.endCol = -1\n selectedRange.cells = []\n selectedCellsSet.clear()\n window.getSelection()?.removeAllRanges()\n }\n\n const addRangeToSet = (startRow: number, startCol: number, endRow: number, endCol: number): void => {\n const minRow = Math.min(startRow, endRow)\n const maxRow = Math.max(startRow, endRow)\n const minCol = Math.min(startCol, endCol)\n const maxCol = Math.max(startCol, endCol)\n\n for (let r = minRow; r <= maxRow; r++) {\n for (let c = minCol; c <= maxCol; c++) {\n selectedCellsSet.add(cellKey(r, c))\n }\n }\n }\n\n // 高亮所有选中的单元格\n const highlightAllSelected = (): void => {\n el.querySelectorAll('.cell-selected').forEach((cell) => cell.classList.remove('cell-selected'))\n\n const visualRowIds = getVisualRowIds()\n const visualColIds = getVisualColIds()\n\n // 遍历所有 body wrapper(包括固定列区域)\n const wrappers = el.querySelectorAll(\n '.vxe-table--body-wrapper tbody, .vxe-table--fixed-left-body-wrapper tbody, .vxe-table--fixed-right-body-wrapper tbody'\n )\n\n wrappers.forEach((tbody) => {\n tbody.querySelectorAll('tr.vxe-body--row').forEach((row) => {\n const rowId = row.getAttribute('rowId')\n if (!rowId) return\n const visualRowIndex = visualRowIds.indexOf(rowId)\n if (visualRowIndex === -1) return\n\n row.querySelectorAll('td.vxe-body--column').forEach((cell) => {\n const colid = cell.getAttribute('colid')\n if (!colid) return\n const visualColIndex = visualColIds.indexOf(colid)\n if (visualColIndex === -1) return\n\n if (selectedCellsSet.has(cellKey(visualRowIndex, visualColIndex))) {\n cell.classList.add('cell-selected')\n }\n })\n })\n })\n\n window.getSelection()?.removeAllRanges()\n }\n\n const highlightCurrentRange = (): void => {\n highlightAllSelected()\n\n const minRow = Math.min(selectedRange.startRow, selectedRange.endRow)\n const maxRow = Math.max(selectedRange.startRow, selectedRange.endRow)\n const minCol = Math.min(selectedRange.startCol, selectedRange.endCol)\n const maxCol = Math.max(selectedRange.startCol, selectedRange.endCol)\n\n const visualRowIds = getVisualRowIds()\n const visualColIds = getVisualColIds()\n\n const wrappers = el.querySelectorAll(\n '.vxe-table--body-wrapper tbody, .vxe-table--fixed-left-body-wrapper tbody, .vxe-table--fixed-right-body-wrapper tbody'\n )\n\n wrappers.forEach((tbody) => {\n tbody.querySelectorAll('tr.vxe-body--row').forEach((row) => {\n const rowId = row.getAttribute('rowId')\n if (!rowId) return\n const visualRowIndex = visualRowIds.indexOf(rowId)\n if (visualRowIndex === -1) return\n\n if (visualRowIndex >= minRow && visualRowIndex <= maxRow) {\n row.querySelectorAll('td.vxe-body--column').forEach((cell) => {\n const colid = cell.getAttribute('colid')\n if (!colid) return\n const visualColIndex = visualColIds.indexOf(colid)\n if (visualColIndex === -1) return\n\n if (visualColIndex >= minCol && visualColIndex <= maxCol) {\n cell.classList.add('cell-selected')\n }\n })\n }\n })\n })\n }\n\n // 收集选中的单元格数据\n const collectSelectedCells = (): void => {\n const $table = getTableInstance()\n if (!$table) return\n\n const tableData = $table.getTableData().fullData\n const visualRowIds = getVisualRowIds()\n const visualColIds = getVisualColIds()\n const allColumns = $table.getTableColumn().fullColumn\n\n const rowsMap = new Map<number, CellData[]>()\n\n selectedCellsSet.forEach((key) => {\n const parts = key.split('-').map(Number) as [number, number]\n const visualRow = parts[0]\n const visualCol = parts[1]\n\n const rowId = visualRowIds[visualRow]\n const colid = visualColIds[visualCol]\n if (!rowId || !colid) return\n\n // 通过 rowId 找到实际数据行(兼容 keyField 配置)\n let rowData: Record<string, CellValue> | null | undefined = $table.getRowById(rowId)\n if (!rowData) {\n // 降级:尝试用 _X_ROW_KEY 匹配\n rowData = tableData.find((item: any) => item._X_ROW_KEY === rowId || String(item._X_ROW_KEY) === rowId)\n }\n if (!rowData) return\n\n // 通过 colid 找到列配置\n const col = allColumns.find((c: VxeColumn) => c.id === colid)\n if (!col?.field) return\n\n if (!rowsMap.has(visualRow)) rowsMap.set(visualRow, [])\n rowsMap.get(visualRow)!.push({\n row: visualRow,\n col: visualCol,\n field: col.field,\n value: rowData[col.field],\n rowId,\n colid\n })\n })\n\n selectedRange.cells = Array.from(rowsMap.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([, cells]) => cells.sort((a, b) => a.col - b.col))\n }\n\n const copyToClipboard = (data: CellValue[][]): CellValue[][] => {\n clipboardData = data\n const text = data.map((row) => row.join('\\t')).join('\\n')\n navigator.clipboard.writeText(text).catch((err) => {\n console.warn('复制到剪贴板失败:', err)\n })\n return data\n }\n\n const pasteFromClipboard = async (): Promise<PasteCellChange[]> => {\n const $table = getTableInstance()\n if (!$table) return []\n\n let pasteData: CellValue[][] = clipboardData\n try {\n const text = await navigator.clipboard.readText()\n if (text) {\n // 统一处理换行符:Windows 使用 \\r\\n,Mac/Linux 使用 \\n\n const normalizedText = text.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n')\n pasteData = normalizedText.split('\\n').filter((r) => r.trim()).map((r) => \n r.split('\\t').map((cell) => parseClipboardValue(cell))\n )\n }\n } catch {}\n\n if (pasteData.length === 0) return []\n\n const tableData = $table.getTableData().fullData\n const visualRowIds = getVisualRowIds()\n const visualColIds = getVisualColIds()\n const allColumns = $table.getTableColumn().fullColumn\n\n // 找到选区的起始位置(视觉索引)\n let startVisualRow = Infinity\n let startVisualCol = Infinity\n selectedCellsSet.forEach((key) => {\n const parts = key.split('-').map(Number) as [number, number]\n startVisualRow = Math.min(startVisualRow, parts[0])\n startVisualCol = Math.min(startVisualCol, parts[1])\n })\n\n if (startVisualRow === Infinity) return []\n\n // 收集变更信息\n const changes: PasteCellChange[] = []\n\n pasteData.forEach((rowData, rowOffset) => {\n const targetVisualRow = startVisualRow + rowOffset\n const targetRowId = visualRowIds[targetVisualRow]\n if (!targetRowId) return\n\n // 通过 rowId 找到实际数据行(兼容 keyField 配置)\n let targetRowData: Record<string, CellValue> | null | undefined = $table.getRowById(targetRowId)\n if (!targetRowData) {\n targetRowData = tableData.find((item: any) => item._X_ROW_KEY === targetRowId || String(item._X_ROW_KEY) === targetRowId)\n }\n if (!targetRowData) return\n\n rowData.forEach((newValue, colOffset) => {\n const targetVisualCol = startVisualCol + colOffset\n const targetColId = visualColIds[targetVisualCol]\n if (!targetColId) return\n\n const col = allColumns.find((c: VxeColumn) => c.id === targetColId)\n if (col?.field) {\n const oldValue = targetRowData[col.field]\n targetRowData[col.field] = newValue\n \n changes.push({\n row: targetVisualRow,\n col: targetVisualCol,\n field: col.field,\n oldValue,\n newValue,\n rowId: targetRowId,\n rowData: { ...targetRowData },\n })\n }\n })\n })\n\n $table.reloadData(tableData)\n highlightAllSelected()\n \n return changes\n }\n\n const clearSelectedCellsData = (): void => {\n const $table = getTableInstance()\n if (!$table) return\n\n const tableData = $table.getTableData().fullData\n const visualRowIds = getVisualRowIds()\n const visualColIds = getVisualColIds()\n const allColumns = $table.getTableColumn().fullColumn\n\n selectedCellsSet.forEach((key) => {\n const parts = key.split('-').map(Number) as [number, number]\n const visualRow = parts[0]\n const visualCol = parts[1]\n\n const rowId = visualRowIds[visualRow]\n const colid = visualColIds[visualCol]\n if (!rowId || !colid) return\n\n // 通过 rowId 找到实际数据行(兼容 keyField 配置)\n let rowData: Record<string, CellValue> | null | undefined = $table.getRowById(rowId)\n if (!rowData) {\n rowData = tableData.find((item: any) => item._X_ROW_KEY === rowId || String(item._X_ROW_KEY) === rowId)\n }\n if (!rowData) return\n\n const col = allColumns.find((c: VxeColumn) => c.id === colid)\n if (col?.field) {\n rowData[col.field] = ''\n }\n })\n\n $table.reloadData(tableData)\n }\n\n const isRowSelectColumn = (visualColIndex: number): boolean => {\n const { rowSelectColumn } = config\n if (rowSelectColumn === -1 || rowSelectColumn === null || rowSelectColumn === undefined) {\n return false\n }\n\n if (typeof rowSelectColumn === 'number') {\n return visualColIndex === rowSelectColumn\n }\n\n if (typeof rowSelectColumn === 'string') {\n const $table = getTableInstance()\n if (!$table) return false\n\n const visualColIds = getVisualColIds()\n const allColumns = $table.getTableColumn().fullColumn\n\n const colid = visualColIds[visualColIndex]\n if (!colid) return false\n\n const col = allColumns.find((c: VxeColumn) => c.id === colid)\n return col?.field === rowSelectColumn || col?.type === rowSelectColumn\n }\n\n return false\n }\n\n const handleMouseDown = (e: MouseEvent): void => {\n if (e.button !== 0) return\n\n const target = e.target as Element\n if (target.closest('.vxe-row--drag-node, .vxe-column--drag-node, .sortable-handle, [draggable=\"true\"]')) {\n return\n }\n\n const cellPos = getCellPosition(e.target)\n if (!cellPos) return\n if (target.closest('.vxe-cell--edit, input, textarea, .vxe-checkbox--icon, .el-button')) return\n\n e.preventDefault()\n\n const isShift = e.shiftKey\n const isCtrl = e.ctrlKey || e.metaKey\n const totalCols = getTotalColumns()\n\n startFromRowSelectColumn = isRowSelectColumn(cellPos.visualCol)\n\n // Shift + 点击\n if (isShift && anchorRow >= 0) {\n selectedCellsSet.clear()\n\n if (startFromRowSelectColumn || isRowSelectColumn(anchorCol)) {\n selectedRange.startRow = anchorRow\n selectedRange.startCol = 0\n selectedRange.endRow = cellPos.visualRow\n selectedRange.endCol = totalCols - 1\n } else {\n selectedRange.startRow = anchorRow\n selectedRange.startCol = anchorCol\n selectedRange.endRow = cellPos.visualRow\n selectedRange.endCol = cellPos.visualCol\n }\n\n addRangeToSet(selectedRange.startRow, selectedRange.startCol, selectedRange.endRow, selectedRange.endCol)\n highlightAllSelected()\n collectSelectedCells()\n config.onSelectionChange?.(selectedRange)\n return\n }\n\n // Ctrl + 点击:保留之前选区\n if (!isCtrl) {\n clearSelection()\n }\n\n if (startFromRowSelectColumn) {\n selectedRange.startRow = cellPos.visualRow\n selectedRange.startCol = 0\n selectedRange.endRow = cellPos.visualRow\n selectedRange.endCol = totalCols - 1\n anchorRow = cellPos.visualRow\n anchorCol = 0\n } else {\n selectedRange.startRow = cellPos.visualRow\n selectedRange.startCol = cellPos.visualCol\n selectedRange.endRow = cellPos.visualRow\n selectedRange.endCol = cellPos.visualCol\n anchorRow = cellPos.visualRow\n anchorCol = cellPos.visualCol\n }\n\n isDragging = true\n startCell = cellPos\n highlightCurrentRange()\n }\n\n const handleMouseMove = (e: MouseEvent): void => {\n if (!isDragging || !startCell) return\n const cellPos = getCellPosition(e.target)\n if (!cellPos) return\n e.preventDefault()\n\n selectedRange.endRow = cellPos.visualRow\n\n if (startFromRowSelectColumn) {\n const totalCols = getTotalColumns()\n selectedRange.startCol = 0\n selectedRange.endCol = totalCols - 1\n } else {\n selectedRange.endCol = cellPos.visualCol\n }\n\n highlightCurrentRange()\n }\n\n const handleMouseUp = (): void => {\n if (isDragging) {\n isDragging = false\n addRangeToSet(selectedRange.startRow, selectedRange.startCol, selectedRange.endRow, selectedRange.endCol)\n collectSelectedCells()\n config.onSelectionChange?.(selectedRange)\n }\n }\n\n const handleKeyDown = (e: KeyboardEvent): void => {\n if ((e.target as Element).closest('input, textarea')) return\n\n // Ctrl+A 全选\n if ((e.ctrlKey || e.metaKey) && e.key === 'a') {\n const totalRows = getTotalRows()\n const totalCols = getTotalColumns()\n if (totalRows > 0 && totalCols > 0) {\n e.preventDefault()\n clearSelection()\n selectedRange.startRow = 0\n selectedRange.startCol = 0\n selectedRange.endRow = totalRows - 1\n selectedRange.endCol = totalCols - 1\n anchorRow = 0\n anchorCol = 0\n addRangeToSet(0, 0, totalRows - 1, totalCols - 1)\n highlightAllSelected()\n collectSelectedCells()\n config.onSelectionChange?.(selectedRange)\n }\n return\n }\n\n if ((e.ctrlKey || e.metaKey) && e.key === 'c' && selectedCellsSet.size > 0) {\n e.preventDefault()\n collectSelectedCells()\n const data = selectedRange.cells.map((row) => row.map((cell) => cell.value))\n copyToClipboard(data)\n config.onCopy?.(data)\n }\n\n if ((e.ctrlKey || e.metaKey) && e.key === 'v' && selectedCellsSet.size > 0) {\n e.preventDefault()\n pasteFromClipboard().then((data) => {\n config.onPaste?.(data)\n })\n }\n\n if ((e.ctrlKey || e.metaKey) && e.key === 'x' && selectedCellsSet.size > 0) {\n e.preventDefault()\n collectSelectedCells()\n const data = selectedRange.cells.map((row) => row.map((cell) => cell.value))\n copyToClipboard(data)\n clearSelectedCellsData()\n config.onCut?.(data)\n }\n\n if ((e.key === 'Delete' || e.key === 'Backspace') && selectedCellsSet.size > 0) {\n e.preventDefault()\n clearSelectedCellsData()\n }\n }\n\n const init = (): void => {\n el.classList.add('vxe-table-clipboard-enabled')\n el.addEventListener('mousedown', handleMouseDown as EventListener)\n el.addEventListener('dragstart', preventDrag)\n el.addEventListener('selectstart', handleSelectStart)\n document.addEventListener('mousemove', handleMouseMove as EventListener)\n document.addEventListener('mouseup', handleMouseUp)\n document.addEventListener('keydown', handleKeyDown as EventListener)\n }\n\n const destroy = (): void => {\n el.classList.remove('vxe-table-clipboard-enabled')\n el.removeEventListener('mousedown', handleMouseDown as EventListener)\n el.removeEventListener('dragstart', preventDrag)\n el.removeEventListener('selectstart', handleSelectStart)\n document.removeEventListener('mousemove', handleMouseMove as EventListener)\n document.removeEventListener('mouseup', handleMouseUp)\n document.removeEventListener('keydown', handleKeyDown as EventListener)\n clearSelection()\n }\n\n const instance: ClipboardInstance = {\n init,\n destroy,\n copy: () => {\n collectSelectedCells()\n if (selectedRange.cells.length > 0) {\n const data = selectedRange.cells.map((row) => row.map((cell) => cell.value))\n return copyToClipboard(data)\n }\n return []\n },\n paste: () => {\n if (selectedCellsSet.size > 0) {\n return pasteFromClipboard()\n }\n return Promise.resolve([])\n },\n cut: () => {\n collectSelectedCells()\n if (selectedRange.cells.length > 0) {\n const data = selectedRange.cells.map((row) => row.map((cell) => cell.value))\n copyToClipboard(data)\n clearSelectedCellsData()\n return data\n }\n return []\n },\n clearSelection,\n selectRow: (visualRowIndex: number) => {\n const totalCols = getTotalColumns()\n if (totalCols === 0) return\n clearSelection()\n selectedRange.startRow = visualRowIndex\n selectedRange.startCol = 0\n selectedRange.endRow = visualRowIndex\n selectedRange.endCol = totalCols - 1\n addRangeToSet(visualRowIndex, 0, visualRowIndex, totalCols - 1)\n highlightAllSelected()\n collectSelectedCells()\n },\n getSelectedRange: () => ({ ...selectedRange }),\n getClipboardData: () => [...clipboardData]\n }\n\n init()\n return instance\n}\n\n/**\n * Vue 插件\n */\nconst VXETableClipboard = {\n install(app: App, options: ClipboardOptions = {}): void {\n globalOptions = { ...defaultOptions, ...options }\n injectStyles(globalOptions)\n\n app.directive('clipboard', {\n mounted(el: HTMLElement, binding) {\n const opts = (binding.value || {}) as ClipboardOptions\n const instance = createClipboardInstance(el, opts)\n instanceMap.set(el, instance)\n },\n updated(el: HTMLElement, binding) {\n const oldInstance = instanceMap.get(el)\n if (oldInstance) oldInstance.destroy()\n const opts = (binding.value || {}) as ClipboardOptions\n const instance = createClipboardInstance(el, opts)\n instanceMap.set(el, instance)\n },\n unmounted(el: HTMLElement) {\n const instance = instanceMap.get(el)\n if (instance) {\n instance.destroy()\n instanceMap.delete(el)\n }\n }\n })\n\n app.config.globalProperties.$getClipboard = (el: HTMLElement) => instanceMap.get(el)\n }\n}\n\n// 组合式 API\nexport function useTableClipboard(\n tableRef: Ref<{ $el: HTMLElement } | null>,\n options: ClipboardOptions = {}\n): {\n init: () => void\n destroy: () => void\n copy: () => CellValue[][]\n paste: () => Promise<PasteCellChange[]>\n cut: () => CellValue[][]\n clearSelection: () => void\n selectRow: (index: number) => void\n getSelectedRange: () => SelectedRange | undefined\n getClipboardData: () => CellValue[][] | undefined\n} {\n let instance: ClipboardInstance | null = null\n\n return {\n init: () => {\n const el = tableRef.value?.$el\n if (el) instance = createClipboardInstance(el, options)\n },\n destroy: () => {\n instance?.destroy()\n instance = null\n },\n copy: () => instance?.copy() || [],\n paste: () => instance?.paste() || Promise.resolve([]),\n cut: () => instance?.cut() || [],\n clearSelection: () => instance?.clearSelection(),\n selectRow: (index: number) => instance?.selectRow(index),\n getSelectedRange: () => instance?.getSelectedRange(),\n getClipboardData: () => instance?.getClipboardData()\n }\n}\n\nexport default VXETableClipboard\n","/// <reference types=\"./types/global-components.d.ts\" />\nimport type { App } from 'vue';\n\nimport {\n ElButtonPlus,\n ElColPlus,\n ElRowPlus,\n} from './components/ElPlusComponent';\n\nimport { ToolBar } from './components/ToolBar';\n\nimport {\n QueryBar,\n QueryDateTime,\n QueryInput,\n QueryInputLike,\n QuerySelect,\n QueryTreeFilter,\n} from './components/QueryComponent';\n\nimport {\n TableInput,\n TableInputNumber,\n TableSelect,\n TableSelectAsync,\n TableSwitch,\n TableListSelect,\n TableListSelectAsync,\n TableCheckBoxAsync,\n TableRender,\n TableCardRender,\n} from './components/TableComponent';\n\nimport {\n FormInput,\n FormInputNumber,\n FormTextArea,\n FormText,\n FormSelect,\n FormSelectAsync,\n FormSelectRemote,\n FormRadio,\n FormCheckBox,\n FormCheckBoxAsync,\n FormSwitch,\n FormDatePicker,\n FormDateTimePicker,\n FormCascaderAsync,\n FormTableSelect,\n FormTableSelectAsync,\n FormDictSelector,\n FormIconPicker,\n FormImageUpload,\n FormCodeEditor,\n FormDivider,\n FormFieldset,\n FormDynamicTable,\n DynamicMapTable,\n FormRender,\n} from './components/FormComponent';\n\nimport {\n AppFormRender,\n AppTableRender,\n DrawerForm\n} from './components/AppComponent';\n\nimport VXETableClipboard from '@/components/TableComponent/TableRender/plugin/vxe-table-clipboard';\nimport { useTableFormats } from '@/hooks/useTableFormats.hook.ts';\nimport { dataFormatter } from '@/utils';\n\nexport * from './components';\nexport * from './types';\nexport * from './config';\nexport * from './utils'\nexport { convertAreaToFieldset } from '@/components/FormComponent/FormRender/hooks/formRender.hook'\n\nconst components = [\n ElButtonPlus,\n ElColPlus,\n ElRowPlus,\n ToolBar,\n QueryBar,\n QueryDateTime,\n QueryInput,\n QueryInputLike,\n QuerySelect,\n QueryTreeFilter,\n TableInput,\n TableInputNumber,\n TableSelect,\n TableSelectAsync,\n TableSwitch,\n TableListSelect,\n TableListSelectAsync,\n TableCheckBoxAsync,\n TableRender,\n TableCardRender,\n FormInput,\n FormInputNumber,\n FormTextArea,\n FormText,\n FormSelect,\n FormSelectAsync,\n FormSelectRemote,\n FormRadio,\n FormCheckBox,\n FormCheckBoxAsync,\n FormSwitch,\n FormDatePicker,\n FormDateTimePicker,\n FormCascaderAsync,\n FormTableSelect,\n FormTableSelectAsync,\n FormDictSelector,\n FormIconPicker,\n FormImageUpload,\n FormCodeEditor,\n FormDivider,\n FormFieldset,\n FormDynamicTable,\n DynamicMapTable,\n FormRender,\n AppFormRender,\n AppTableRender,\n DrawerForm\n] as const;\n\nconst { registerGeneralMethods } = useTableFormats();\n\nconst install = (app: App, ...options: any[]): void => {\n components.forEach((component) => {\n if (component.install) {\n app.use(component as any);\n } else if (component.name) {\n app.component(component.name, component);\n }\n });\n\n app.use(VXETableClipboard)\n\n setTimeout(() => {\n registerGeneralMethods('parseString', ({ cellValue }: any) => {\n return dataFormatter.toString(cellValue);\n });\n registerGeneralMethods('parseInt', ({ cellValue }: any) => {\n return dataFormatter.parseInt(cellValue);\n });\n registerGeneralMethods('timestamp', ({ cellValue }: any) => {\n return dataFormatter.timestamp(cellValue);\n });\n }, 50);\n};\n\n/**\n * 控制深浅色模式\n */\nexport function initVxeTableEl() {\n // VxeUI.setTheme(preferences.isDark.value ? 'dark' : 'light');\n // watch(preferences.isDark, (newVal) => {\n // VxeUI.setTheme(newVal ? 'dark' : 'light');\n // });\n}\n\nconst KeliUI = {\n install,\n};\n\nexport default KeliUI;\n\nexport {\n ElButtonPlus,\n ElColPlus,\n ElRowPlus,\n ToolBar,\n QueryBar,\n QueryDateTime,\n QueryInput,\n QueryInputLike,\n QuerySelect,\n QueryTreeFilter,\n TableInput,\n TableInputNumber,\n TableSelect,\n TableSelectAsync,\n TableSwitch,\n TableListSelect,\n TableListSelectAsync,\n TableCheckBoxAsync,\n TableRender,\n TableCardRender,\n FormInput,\n FormInputNumber,\n FormTextArea,\n FormText,\n FormSelect,\n FormSelectAsync,\n FormSelectRemote,\n FormRadio,\n FormCheckBox,\n FormCheckBoxAsync,\n FormSwitch,\n FormDatePicker,\n FormDateTimePicker,\n FormCascaderAsync,\n FormTableSelect,\n FormTableSelectAsync,\n FormDictSelector,\n FormIconPicker,\n FormImageUpload,\n FormCodeEditor,\n FormDivider,\n FormFieldset,\n FormDynamicTable,\n DynamicMapTable,\n FormRender,\n AppFormRender,\n AppTableRender,\n DrawerForm\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"keli-ui.js","names":["$slots"],"sources":["../src/components/ElPlusComponent/ElButtonPlus/ElButtonPlus.vue","../src/components/ElPlusComponent/ElButtonPlus/ElButtonPlus.vue","../src/components/ElPlusComponent/ElButtonPlus/index.ts","../src/components/ElPlusComponent/ElColPlus/ElColPlus.vue","../src/components/ElPlusComponent/ElColPlus/ElColPlus.vue","../src/components/ElPlusComponent/ElColPlus/index.ts","../src/components/ElPlusComponent/ElRowPlus/ElRowPlus.vue","../src/components/ElPlusComponent/ElRowPlus/ElRowPlus.vue","../src/components/ElPlusComponent/ElRowPlus/index.ts","../src/utils/arrayUtils.ts","../src/assets/avatar.svg","../src/assets/question.svg","../src/utils/baseFunction.ts","../src/utils/validate.ts","../src/utils/dataFormatter.ts","../src/utils/dateTime.ts","../src/utils/emitter.ts","../src/utils/formValidates.ts","../src/utils/msgTips.ts","../src/components/QueryComponent/QueryBar/hooks/index.ts","../src/components/QueryComponent/QueryBar/QueryBar.vue","../src/components/QueryComponent/QueryBar/QueryBar.vue","../src/components/QueryComponent/QueryBar/index.ts","../src/components/QueryComponent/QueryDateTime/QueryDateTime.vue","../src/components/QueryComponent/QueryDateTime/QueryDateTime.vue","../src/components/QueryComponent/QueryDateTime/index.ts","../src/components/QueryComponent/QueryInput/QueryInput.vue","../src/components/QueryComponent/QueryInput/QueryInput.vue","../src/components/QueryComponent/QueryInput/index.ts","../src/components/QueryComponent/QueryInputLike/QueryInputLike.vue","../src/components/QueryComponent/QueryInputLike/QueryInputLike.vue","../src/components/QueryComponent/QueryInputLike/index.ts","../src/components/QueryComponent/QuerySelect/QuerySelect.vue","../src/components/QueryComponent/QuerySelect/QuerySelect.vue","../src/components/QueryComponent/QuerySelect/index.ts","../src/components/QueryComponent/QueryTreeFilter/QueryTreeFilter.vue","../src/components/QueryComponent/QueryTreeFilter/QueryTreeFilter.vue","../src/components/QueryComponent/QueryTreeFilter/index.ts","../src/components/TableComponent/TableInput/TableInput.vue","../src/components/TableComponent/TableInput/TableInput.vue","../src/components/TableComponent/TableInput/index.ts","../src/components/TableComponent/TableInputNumber/TableInputNumber.vue","../src/components/TableComponent/TableInputNumber/TableInputNumber.vue","../src/components/TableComponent/TableInputNumber/index.ts","../src/components/TableComponent/TableSelect/TableSelect.vue","../src/components/TableComponent/TableSelect/TableSelect.vue","../src/components/TableComponent/TableSelect/index.ts","../src/components/TableComponent/TableSelectAsync/TableSelectAsync.vue","../src/components/TableComponent/TableSelectAsync/TableSelectAsync.vue","../src/components/TableComponent/TableSelectAsync/index.ts","../src/components/TableComponent/TableSwitch/TableSwitch.vue","../src/components/TableComponent/TableSwitch/TableSwitch.vue","../src/components/TableComponent/TableSwitch/index.ts","../src/components/TableComponent/TableListSelect/TableListSelect.vue","../src/components/TableComponent/TableListSelect/TableListSelect.vue","../src/components/TableComponent/TableListSelect/index.ts","../src/components/TableComponent/hooks/tableSelectAsync.hook.ts","../src/components/TableComponent/TableListSelectAsync/TableListSelectAsync.vue","../src/components/TableComponent/TableListSelectAsync/TableListSelectAsync.vue","../src/components/TableComponent/TableListSelectAsync/index.ts","../src/components/TableComponent/TableCheckBoxAsync/TableCheckBoxAsync.vue","../src/components/TableComponent/TableCheckBoxAsync/TableCheckBoxAsync.vue","../src/components/TableComponent/TableCheckBoxAsync/index.ts","../src/components/TableComponent/TableRender/hooks/useVxeGrid.hook.ts","../src/components/TableComponent/TableRender/TableRender.vue","../src/components/TableComponent/TableRender/TableRender.vue","../src/components/TableComponent/TableRender/index.ts","../src/components/TableComponent/TableCardRender/TableCardRender.vue","../src/components/TableComponent/TableCardRender/TableCardRender.vue","../src/components/TableComponent/TableCardRender/index.ts","../src/components/FormComponent/hooks/useMitt.hook.ts","../src/components/FormComponent/FormInput/FormInput.vue","../src/components/FormComponent/FormInput/FormInput.vue","../src/components/FormComponent/FormInput/index.ts","../src/components/FormComponent/FormInputNumber/FormInputNumber.vue","../src/components/FormComponent/FormInputNumber/FormInputNumber.vue","../src/components/FormComponent/FormInputNumber/index.ts","../src/components/FormComponent/FormTextArea/FormTextArea.vue","../src/components/FormComponent/FormTextArea/FormTextArea.vue","../src/components/FormComponent/FormTextArea/index.ts","../src/components/FormComponent/FormText/FormText.vue","../src/components/FormComponent/FormText/FormText.vue","../src/components/FormComponent/FormText/index.ts","../src/components/FormComponent/FormSelect/FormSelect.vue","../src/components/FormComponent/FormSelect/FormSelect.vue","../src/components/FormComponent/FormSelect/index.ts","../src/components/FormComponent/hooks/selectAsync.hook.ts","../src/components/FormComponent/FormSelectAsync/FormSelectAsync.vue","../src/components/FormComponent/FormSelectAsync/FormSelectAsync.vue","../src/components/FormComponent/FormSelectAsync/index.ts","../src/components/FormComponent/FormSelectRemote/FormSelectRemote.vue","../src/components/FormComponent/FormSelectRemote/FormSelectRemote.vue","../src/components/FormComponent/FormSelectRemote/index.ts","../src/components/FormComponent/FormRadio/FormRadio.vue","../src/components/FormComponent/FormRadio/FormRadio.vue","../src/components/FormComponent/FormRadio/index.ts","../src/components/FormComponent/FormCheckBox/FormCheckBox.vue","../src/components/FormComponent/FormCheckBox/FormCheckBox.vue","../src/components/FormComponent/FormCheckBox/index.ts","../src/components/FormComponent/FormCheckBoxAsync/FormCheckBoxAsync.vue","../src/components/FormComponent/FormCheckBoxAsync/FormCheckBoxAsync.vue","../src/components/FormComponent/FormCheckBoxAsync/index.ts","../src/components/FormComponent/FormSwitch/FormSwitch.vue","../src/components/FormComponent/FormSwitch/FormSwitch.vue","../src/components/FormComponent/FormSwitch/index.ts","../src/components/FormComponent/FormDatePicker/FormDatePicker.vue","../src/components/FormComponent/FormDatePicker/FormDatePicker.vue","../src/components/FormComponent/FormDatePicker/index.ts","../src/components/FormComponent/FormDateTimePicker/FormDateTimePicker.vue","../src/components/FormComponent/FormDateTimePicker/FormDateTimePicker.vue","../src/components/FormComponent/FormDateTimePicker/index.ts","../src/components/FormComponent/FormCascaderAsync/FormCascaderAsync.vue","../src/components/FormComponent/FormCascaderAsync/FormCascaderAsync.vue","../src/components/FormComponent/FormCascaderAsync/index.ts","../src/components/FormComponent/FormTableSelect/FormTableSelect.vue","../src/components/FormComponent/FormTableSelect/FormTableSelect.vue","../src/components/FormComponent/FormTableSelect/index.ts","../src/components/FormComponent/FormTableSelectAsync/FormTableSelectAsync.vue","../src/components/FormComponent/FormTableSelectAsync/FormTableSelectAsync.vue","../src/components/FormComponent/FormTableSelectAsync/index.ts","../src/components/FormComponent/FormDictSelector/FormDictSelector.vue","../src/components/FormComponent/FormDictSelector/FormDictSelector.vue","../src/components/FormComponent/FormDictSelector/index.ts","../src/components/FormComponent/FormIconPicker/FormIconPicker.vue","../src/components/FormComponent/FormIconPicker/FormIconPicker.vue","../src/components/FormComponent/FormIconPicker/index.ts","../src/components/FormComponent/FormImageUpload/FormImageUpload.vue","../src/components/FormComponent/FormImageUpload/FormImageUpload.vue","../src/components/FormComponent/FormImageUpload/index.ts","../src/components/FormComponent/FormCodeEditor/volar/setup.ts","../src/components/FormComponent/FormCodeEditor/FormCodeEditor.vue","../src/components/FormComponent/FormCodeEditor/FormCodeEditor.vue","../src/components/FormComponent/FormCodeEditor/language/index.ts","../src/components/FormComponent/FormCodeEditor/index.ts","../src/components/FormComponent/FormDivider/FormDivider.vue","../src/components/FormComponent/FormDivider/FormDivider.vue","../src/components/FormComponent/FormDivider/index.ts","../src/components/FormComponent/FormFieldset/FormFieldset.vue","../src/components/FormComponent/FormFieldset/FormFieldset.vue","../src/components/FormComponent/FormFieldset/index.ts","../src/components/FormComponent/FormDynamicTable/FormDynamicTable.vue","../src/components/FormComponent/FormDynamicTable/FormDynamicTable.vue","../src/components/FormComponent/FormDynamicTable/index.ts","../src/components/FormComponent/DynamicMapTable/DynamicMapTable.vue","../src/components/FormComponent/DynamicMapTable/DynamicMapTable.vue","../src/components/FormComponent/DynamicMapTable/index.ts","../src/components/FormComponent/FormRender/components/FormAreaRender.vue","../src/components/FormComponent/FormRender/components/FormAreaRender.vue","../src/components/FormComponent/FormRender/hooks/formRender.hook.ts","../src/components/FormComponent/FormRender/FormRender.vue","../src/components/FormComponent/FormRender/FormRender.vue","../src/components/FormComponent/FormRender/index.ts","../src/components/FormComponent/hooks/useColumnRender.hook.ts","../src/hooks/useTableFormats.hook.ts","../src/components/AppComponent/hooks/useSplitApiButton.ts","../src/components/AppComponent/hooks/useTable.hook.ts","../src/components/AppComponent/components/embedded/EmbeddedDialogForm.vue","../src/components/AppComponent/components/embedded/EmbeddedDialogForm.vue","../src/components/AppComponent/components/embedded/EmbeddedTable.vue","../src/components/AppComponent/components/embedded/EmbeddedTable.vue","../src/components/AppComponent/components/FileIsland.vue","../src/components/AppComponent/components/FileIsland.vue","../src/components/AppComponent/components/FlowUserDialog.vue","../src/components/AppComponent/components/FlowUserDialog.vue","../src/components/AppComponent/hooks/useAutoForm.hook.ts","../src/components/AppComponent/AppFormRender.vue","../src/components/AppComponent/AppFormRender.vue","../src/components/AppComponent/components/chartList/ChartRender.vue","../src/components/AppComponent/components/chartList/ChartRender.vue","../src/components/AppComponent/components/chartList/index.vue","../src/components/AppComponent/components/chartList/index.vue","../src/components/AppComponent/components/DialogForm.vue","../src/components/AppComponent/components/DialogForm.vue","../src/components/AppComponent/components/DrawerForm.vue","../src/components/AppComponent/components/DrawerForm.vue","../src/components/AppComponent/AppTableRender.vue","../src/components/AppComponent/AppTableRender.vue","../src/components/AppComponent/DynamicDialogHost.vue","../src/components/AppComponent/DynamicDialogHost.vue","../src/components/AppComponent/index.ts","../src/utils/openHostDialog.ts","../src/utils/sleep.ts","../src/hooks/useButtonExec.hook.ts","../src/components/ToolBar/ToolBar.vue","../src/components/ToolBar/ToolBar.vue","../src/components/ToolBar/index.ts","../src/components/TableComponent/TableRender/plugin/vxe-table-clipboard.ts","../src/index.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport { defineComponent, h, useAttrs } from 'vue';\n\nimport { Icon } from '@iconify/vue';\nimport { ElButton } from 'element-plus';\n\ninterface Props {\n icon?: object | string;\n label?: string | undefined;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n icon: undefined,\n label: undefined,\n});\n\nconst attrs = useAttrs();\n\n// 创建 Iconify 图标组件\nfunction createIconifyIcon(iconName: string) {\n return defineComponent({\n name: `Icon-${iconName}`,\n setup(iconProps, { attrs: iconAttrs }) {\n return () => h(Icon, { icon: iconName, ...iconProps, ...iconAttrs });\n },\n });\n}\n\nfunction getIconComponent() {\n if (!props.icon) return undefined;\n\n if (typeof props.icon === 'string' && props.icon.includes(':')) {\n return createIconifyIcon(props.icon);\n }\n\n return props.icon;\n}\n</script>\n\n<template>\n <component\n v-if=\"label\"\n :is=\"ElButton\"\n v-bind=\"attrs\"\n :icon=\"getIconComponent()\"\n >\n {{ label }}\n </component>\n <component v-else :is=\"ElButton\" v-bind=\"attrs\" :icon=\"getIconComponent()\" />\n</template>\n","<script setup lang=\"ts\">\nimport { defineComponent, h, useAttrs } from 'vue';\n\nimport { Icon } from '@iconify/vue';\nimport { ElButton } from 'element-plus';\n\ninterface Props {\n icon?: object | string;\n label?: string | undefined;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n icon: undefined,\n label: undefined,\n});\n\nconst attrs = useAttrs();\n\n// 创建 Iconify 图标组件\nfunction createIconifyIcon(iconName: string) {\n return defineComponent({\n name: `Icon-${iconName}`,\n setup(iconProps, { attrs: iconAttrs }) {\n return () => h(Icon, { icon: iconName, ...iconProps, ...iconAttrs });\n },\n });\n}\n\nfunction getIconComponent() {\n if (!props.icon) return undefined;\n\n if (typeof props.icon === 'string' && props.icon.includes(':')) {\n return createIconifyIcon(props.icon);\n }\n\n return props.icon;\n}\n</script>\n\n<template>\n <component\n v-if=\"label\"\n :is=\"ElButton\"\n v-bind=\"attrs\"\n :icon=\"getIconComponent()\"\n >\n {{ label }}\n </component>\n <component v-else :is=\"ElButton\" v-bind=\"attrs\" :icon=\"getIconComponent()\" />\n</template>\n","import ElButtonPlus from './ElButtonPlus.vue';\nimport type { App } from 'vue';\n\n(ElButtonPlus as any).name = 'ElButtonPlus';\n\nElButtonPlus.install = (app: App) => {\n app.component('ElButtonPlus', ElButtonPlus);\n};\n\nexport { ElButtonPlus };\n","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue';\n\ninterface Props {\n span?: number;\n offset?: number;\n break?: boolean;\n tag?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n span: 24,\n offset: 0,\n break: false,\n tag: 'div',\n});\n\nconst gridRef = inject<any>('elRowPlusGrid', computed(() => 24));\nconst gutterRef = inject<any>('elRowPlusGutter', computed(() => 0));\n\nconst grid = computed(() => gridRef?.value ?? 24);\nconst gutter = computed(() => gutterRef?.value ?? 0);\n\nconst isBreak = computed(() => props.break);\n\nconst colStyle = computed(() => {\n const style: any = {\n boxSizing: 'border-box',\n };\n\n const widthPercent = (props.span / grid.value) * 100;\n style.width = `${widthPercent}%`;\n style.flex = `0 0 ${widthPercent}%`;\n\n if (props.offset > 0) {\n const offsetPercent = (props.offset / grid.value) * 100;\n style.marginLeft = `${offsetPercent}%`;\n }\n\n if (gutter.value) {\n style.paddingLeft = `${gutter.value / 2}px`;\n style.paddingRight = `${gutter.value / 2}px`;\n }\n\n return style;\n});\n\nconst colClass = computed(() => {\n return ['el-col-plus'];\n});\n\nconst breakStyle = {\n flex: '1 0 100%',\n width: '100%',\n height: '0',\n visibility: 'hidden' as const,\n};\n</script>\n\n<template>\n <div v-if=\"isBreak\" :style=\"breakStyle\" aria-hidden=\"true\"></div>\n <component :is=\"tag\" :class=\"colClass\" :style=\"colStyle\">\n <slot></slot>\n </component>\n</template>\n\n<style scoped lang=\"scss\">\n.el-col-plus {\n box-sizing: border-box;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, inject } from 'vue';\n\ninterface Props {\n span?: number;\n offset?: number;\n break?: boolean;\n tag?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n span: 24,\n offset: 0,\n break: false,\n tag: 'div',\n});\n\nconst gridRef = inject<any>('elRowPlusGrid', computed(() => 24));\nconst gutterRef = inject<any>('elRowPlusGutter', computed(() => 0));\n\nconst grid = computed(() => gridRef?.value ?? 24);\nconst gutter = computed(() => gutterRef?.value ?? 0);\n\nconst isBreak = computed(() => props.break);\n\nconst colStyle = computed(() => {\n const style: any = {\n boxSizing: 'border-box',\n };\n\n const widthPercent = (props.span / grid.value) * 100;\n style.width = `${widthPercent}%`;\n style.flex = `0 0 ${widthPercent}%`;\n\n if (props.offset > 0) {\n const offsetPercent = (props.offset / grid.value) * 100;\n style.marginLeft = `${offsetPercent}%`;\n }\n\n if (gutter.value) {\n style.paddingLeft = `${gutter.value / 2}px`;\n style.paddingRight = `${gutter.value / 2}px`;\n }\n\n return style;\n});\n\nconst colClass = computed(() => {\n return ['el-col-plus'];\n});\n\nconst breakStyle = {\n flex: '1 0 100%',\n width: '100%',\n height: '0',\n visibility: 'hidden' as const,\n};\n</script>\n\n<template>\n <div v-if=\"isBreak\" :style=\"breakStyle\" aria-hidden=\"true\"></div>\n <component :is=\"tag\" :class=\"colClass\" :style=\"colStyle\">\n <slot></slot>\n </component>\n</template>\n\n<style scoped lang=\"scss\">\n.el-col-plus {\n box-sizing: border-box;\n}\n</style>\n","import ElColPlus from './ElColPlus.vue';\nimport type { App } from 'vue';\n\n(ElColPlus as any).name = 'ElColPlus';\n\nElColPlus.install = (app: App) => {\n app.component('ElColPlus', ElColPlus);\n};\n\nexport { ElColPlus };\n","<script setup lang=\"ts\">\nimport { computed, provide, useAttrs } from 'vue';\n\ninterface Props {\n grid?: number;\n gutter?: number;\n justify?:\n | 'center'\n | 'end'\n | 'space-around'\n | 'space-between'\n | 'space-evenly'\n | 'start';\n align?: 'bottom' | 'middle' | 'top';\n tag?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n grid: 24,\n gutter: 0,\n justify: 'start',\n align: 'top',\n tag: 'div',\n});\n\nconst attrs = useAttrs();\n\nprovide('elRowPlusGrid', computed(() => props.grid));\nprovide('elRowPlusGutter', computed(() => props.gutter));\n\nconst rowStyle = computed(() => {\n const style: any = {\n display: 'flex',\n flexWrap: 'wrap',\n };\n\n if (props.gutter) {\n style.marginLeft = `-${props.gutter / 2}px`;\n style.marginRight = `-${props.gutter / 2}px`;\n }\n\n const justifyMap = {\n start: 'flex-start',\n end: 'flex-end',\n center: 'center',\n 'space-around': 'space-around',\n 'space-between': 'space-between',\n 'space-evenly': 'space-evenly',\n };\n style.justifyContent = justifyMap[props.justify];\n\n const alignMap = {\n top: 'flex-start',\n middle: 'center',\n bottom: 'flex-end',\n };\n style.alignItems = alignMap[props.align];\n\n return style;\n});\n\nconst rowClass = computed(() => {\n return ['el-row-plus', attrs.class];\n});\n</script>\n\n<template>\n <component :is=\"tag\" :class=\"rowClass\" :style=\"rowStyle\">\n <slot></slot>\n </component>\n</template>\n\n<style scoped lang=\"scss\">\n.el-row-plus {\n box-sizing: border-box;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, provide, useAttrs } from 'vue';\n\ninterface Props {\n grid?: number;\n gutter?: number;\n justify?:\n | 'center'\n | 'end'\n | 'space-around'\n | 'space-between'\n | 'space-evenly'\n | 'start';\n align?: 'bottom' | 'middle' | 'top';\n tag?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n grid: 24,\n gutter: 0,\n justify: 'start',\n align: 'top',\n tag: 'div',\n});\n\nconst attrs = useAttrs();\n\nprovide('elRowPlusGrid', computed(() => props.grid));\nprovide('elRowPlusGutter', computed(() => props.gutter));\n\nconst rowStyle = computed(() => {\n const style: any = {\n display: 'flex',\n flexWrap: 'wrap',\n };\n\n if (props.gutter) {\n style.marginLeft = `-${props.gutter / 2}px`;\n style.marginRight = `-${props.gutter / 2}px`;\n }\n\n const justifyMap = {\n start: 'flex-start',\n end: 'flex-end',\n center: 'center',\n 'space-around': 'space-around',\n 'space-between': 'space-between',\n 'space-evenly': 'space-evenly',\n };\n style.justifyContent = justifyMap[props.justify];\n\n const alignMap = {\n top: 'flex-start',\n middle: 'center',\n bottom: 'flex-end',\n };\n style.alignItems = alignMap[props.align];\n\n return style;\n});\n\nconst rowClass = computed(() => {\n return ['el-row-plus', attrs.class];\n});\n</script>\n\n<template>\n <component :is=\"tag\" :class=\"rowClass\" :style=\"rowStyle\">\n <slot></slot>\n </component>\n</template>\n\n<style scoped lang=\"scss\">\n.el-row-plus {\n box-sizing: border-box;\n}\n</style>\n","import ElRowPlus from './ElRowPlus.vue';\nimport type { App } from 'vue';\n\n(ElRowPlus as any).name = 'ElRowPlus';\n\nElRowPlus.install = (app: App) => {\n app.component('ElRowPlus', ElRowPlus);\n};\n\nexport { ElRowPlus };\n","/**\n * 判断某个值是否存在与某个数组中\n * 如果key是字符串则直接取array的item[key] 数组则是取array的item[key0][key1][key2]... 留空则直接返回item是否等于value\n * @param value 值\n * @param array 数组\n * @param key 键\n */\nexport function isInArray(\n value: any,\n array: any[],\n key?: null | string | string[],\n): boolean {\n return array.some((item) => {\n if (typeof key === 'string') {\n return item[key] === value;\n } else if (Array.isArray(key)) {\n let v = item;\n for (const element of key) {\n if (!v) {\n return false;\n }\n v = v[element];\n }\n\n return (v = value);\n } else {\n return item === key;\n }\n });\n}\n\n/**\n * 获取valueArray还在array的值\n * @param valueArray\n * @param array\n * @param key\n */\nexport function valueArrayInArray(\n valueArray: any[],\n array: any[],\n key?: null | string | string[],\n): any[] {\n return valueArray.filter((v) => {\n const foundItem = array.find((opt) => {\n // 如果是字符串 则直接取下标值\n if (typeof key === 'string') {\n return opt[key] === v;\n } else if (Array.isArray(key)) {\n // 若是数组 则循环取得下标值\n let subscript = opt;\n for (const element of key) {\n if (!subscript) {\n return false;\n }\n\n subscript = subscript[element];\n }\n\n return v === subscript;\n } else {\n return v === opt;\n }\n });\n\n return !!foundItem;\n });\n}\n\n/**\n * 入参是一个数组和一个值,如果数组存在这个值,则移除掉里面所有的这个值并返回移除后的数组\n * @param array\n * @param value\n */\nexport function removeValueFromArray(array: any[], value: any): any[] {\n return array.filter((item) => item !== value);\n}\n\ninterface LabelFromArrayByValue {\n /**\n * 选项 类似于下拉框选项格式\n * [\n * {\n * value: 'option1',\n * label: '选项1',\n * },\n * {\n * value: 'option2',\n * label: '选项2',\n * },\n * {\n * value: 'option3',\n * label: '选项3',\n * }\n * ]\n */\n options: any[];\n /**\n * 查询值\n * 例如option1 或者 ['option1', 'option3']\n */\n value: number | number[] | string | string[];\n /**\n * value字段 对应例子里面的value\n */\n valueField: string;\n /**\n * label字段 对应例子里面的label\n */\n labelField: string;\n}\n\n/**\n * 在数组里面查询label\n * @param params\n */\nexport function getLabelFromArrayByValue(params: LabelFromArrayByValue): any {\n const { options, value, valueField, labelField } = params;\n\n // 构建一个Map,便于快速查找\n const valueLabelMap = new Map(\n options.map((item) => [item[valueField], item[labelField]]),\n );\n\n return Array.isArray(value)\n ? value\n .map((val) => valueLabelMap.get(val))\n .filter((label) => label !== undefined)\n : valueLabelMap.get(value);\n}\n\n/**\n * 去除数组对象中的某些字段\n * @param array\n * @param fieldsToOmit\n */\nexport function omitFieldsFromObjects(\n array: any[],\n fieldsToOmit: string | string[],\n) {\n // 确保 fieldsToOmit 是数组\n const fieldsSet = new Set(\n Array.isArray(fieldsToOmit) ? fieldsToOmit : [fieldsToOmit],\n );\n\n return array.map((obj) => {\n const newObj = { ...obj };\n fieldsSet.forEach((field) => {\n delete newObj[field];\n });\n return newObj;\n });\n}\n\n/**\n * 合并数组\n * @param array1 被更新的数组\n * @param array2 更新数组数据\n * @param keyField 主键字段\n */\nexport function mergeArraysByKey(\n array1: any[],\n array2: any[],\n keyField: string,\n) {\n // 将 array2 转为以 keyField 为键的 Map,便于快速查找\n const map2 = new Map(array2.map((item) => [item[keyField], item]));\n\n // 遍历 array1,合并对应项\n return array1.map((item) => {\n const match = map2.get(item[keyField]);\n if (match) {\n // 存在匹配项,合并对象(array2 覆盖 array1)\n return { ...item, ...match };\n }\n // 无匹配,直接返回 array1 的原始项\n return { ...item };\n });\n}\n","export default \"data:image/svg+xml,%3c?xml%20version='1.0'%20standalone='no'?%3e%3c!DOCTYPE%20svg%20PUBLIC%20'-//W3C//DTD%20SVG%201.1//EN'%20'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'%3e%3csvg%20t='1733885957959'%20class='icon'%20viewBox='0%200%201024%201024'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20p-id='2989'%20width='32'%20height='32'%20xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3cpath%20d='M1012.216%20466.752l-91.96-30.936%2050.56-82.808c-53.152-42.144-146.784-51.36-239.864-17.48a353.328%20353.328%200%200%200-36.904%2015.888c0.608-8.424%200.936-16.976%200.936-25.64%200-99.048-40.688-183.888-98.464-219.416L536%20182.192l-60.52-75.832c-57.776%2035.536-98.464%20120.368-98.464%20219.416%200%208.664%200.328%2017.216%200.936%2025.64a353.328%20353.328%200%200%200-36.904-15.888c-93.08-33.88-186.712-24.664-239.864%2017.48l50.56%2082.808-91.96%2030.936c13.632%2066.448%2079.432%20133.696%20172.512%20167.576%2011.088%204.032%2022.176%207.44%2033.208%2010.264-2.8%202.936-5.56%205.936-8.288%209-65.848%2073.992-91.856%20164.416-72.312%20229.368l95.624-16.416-5.2%2096.88c66.784%2011.864%20153.576-24.456%20219.424-98.456A346.672%20346.672%200%200%200%20536%20808.04a346.336%20346.336%200%200%200%2041.248%2056.928c65.848%2073.992%20152.64%20110.32%20219.424%2098.456l-5.2-96.88%2095.624%2016.416c19.544-64.96-6.464-155.376-72.312-229.368a372.976%20372.976%200%200%200-8.288-9%20355.84%20355.84%200%200%200%2033.208-10.264c93.08-33.88%20158.88-101.128%20172.512-167.576z'%20fill='%23E6E7E8'%20p-id='2990'%3e%3c/path%3e%3cpath%20d='M972.216%20426.752l-91.96-30.936%2050.56-82.808c-53.152-42.144-146.784-51.36-239.864-17.48a353.328%20353.328%200%200%200-36.904%2015.888c0.608-8.424%200.936-16.976%200.936-25.64%200-99.048-40.688-183.888-98.464-219.416L496%20142.192l-60.52-75.832c-57.776%2035.536-98.464%20120.368-98.464%20219.416%200%208.664%200.328%2017.216%200.936%2025.64a353.328%20353.328%200%200%200-36.904-15.888c-93.08-33.88-186.712-24.664-239.864%2017.48l50.56%2082.808-91.96%2030.936c13.632%2066.448%2079.432%20133.696%20172.512%20167.576%2011.088%204.032%2022.176%207.44%2033.208%2010.264-2.8%202.936-5.56%205.936-8.288%209-65.848%2073.992-91.856%20164.416-72.312%20229.368l95.624-16.416-5.2%2096.88c66.784%2011.864%20153.576-24.456%20219.424-98.456A346.672%20346.672%200%200%200%20496%20768.04a346.336%20346.336%200%200%200%2041.248%2056.928c65.848%2073.992%20152.64%20110.32%20219.424%2098.456l-5.2-96.88%2095.624%2016.416c19.544-64.96-6.464-155.376-72.312-229.368a372.976%20372.976%200%200%200-8.288-9%20355.84%20355.84%200%200%200%2033.208-10.264c93.08-33.88%20158.88-101.128%20172.512-167.576z'%20fill='%23FFFFFF'%20p-id='2991'%3e%3c/path%3e%3cpath%20d='M972.216%20450.752l-91.96-30.936%2050.56-82.808c-53.152-42.144-146.784-51.36-239.864-17.48a353.328%20353.328%200%200%200-36.904%2015.888c0.608-8.424%200.936-16.976%200.936-25.64%200-99.048-40.688-183.888-98.464-219.416L496%20166.192l-60.52-75.832c-57.776%2035.536-98.464%20120.368-98.464%20219.416%200%208.664%200.328%2017.216%200.936%2025.64a353.328%20353.328%200%200%200-36.904-15.888c-93.08-33.88-186.712-24.664-239.864%2017.48l50.56%2082.808-91.96%2030.936c13.632%2066.448%2079.432%20133.696%20172.512%20167.576%2011.088%204.032%2022.176%207.44%2033.208%2010.264-2.8%202.936-5.56%205.936-8.288%209-65.848%2073.992-91.856%20164.416-72.312%20229.368l95.624-16.416-5.2%2096.88c66.784%2011.864%20153.576-24.456%20219.424-98.456A346.672%20346.672%200%200%200%20496%20792.04a346.336%20346.336%200%200%200%2041.248%2056.928c65.848%2073.992%20152.64%20110.32%20219.424%2098.456l-5.2-96.88%2095.624%2016.416c19.544-64.96-6.464-155.376-72.312-229.368a372.976%20372.976%200%200%200-8.288-9%20355.84%20355.84%200%200%200%2033.208-10.264c93.08-33.88%20158.88-101.128%20172.512-167.576z'%20fill='%23FFD7E5'%20p-id='2992'%3e%3c/path%3e%3cpath%20d='M445.552%20823.232a340.816%20340.816%200%200%201-39.248%2036.696%208%208%200%200%200%209.952%2012.528%20355.864%20355.864%200%200%200%2041.096-38.424%208%208%200%201%200-11.8-10.8z'%20fill='%233A2C60'%20p-id='2993'%3e%3c/path%3e%3cpath%20d='M974.768%20419.168l-82.464-27.744%2045.336-74.248a8%208%200%200%200-1.856-10.44c-57.152-45.312-154.328-52.664-247.568-18.728-8.52%203.104-17.04%206.584-25.464%2010.4%200.152-4.24%200.224-8.464%200.224-12.632%200-99.224-40.144-188.024-102.272-226.24a8.024%208.024%200%200%200-10.448%201.832L496%20129.36l-54.272-68a8.008%208.008%200%200%200-10.448-1.824c-62.128%2038.208-102.272%20127.008-102.272%20226.232%200%204.16%200.08%208.376%200.224%2012.632a357.12%20357.12%200%200%200-25.456-10.392c-93.24-33.944-190.424-26.592-247.568%2018.728a8%208%200%200%200-1.856%2010.44l45.336%2074.248-82.456%2027.744a8%208%200%200%200-5.288%209.184C26.6%20499.808%2096.32%20567.904%20189.56%20601.84c6.928%202.52%2014.016%204.856%2021.192%206.976-65.624%2074.032-94.48%20166.776-73.512%20236.448a7.984%207.984%200%200%200%209.016%205.576L232%20836.128l-4.664%2086.872a8%208%200%200%200%206.592%208.304c46.632%208.304%20103.168-6.064%20155.12-39.368a7.992%207.992%200%200%200%202.416-11.048%207.976%207.976%200%200%200-11.048-2.416c-45.992%2029.472-95.384%2043.16-136.704%2038.128l4.656-86.816%2041.384-46.496a8%208%200%200%200-11.952-10.64l-41.384%2046.504-85.696%2014.712c-15.624-63.848%2012.296-147.312%2072.488-214.936%202.184-2.456%204.408-4.84%206.64-7.216l60.512-16.504a8%208%200%200%200-4.208-15.44l-60.608%2016.528a350.48%20350.48%200%200%201-30.504-9.48C109.96%20555.84%2045.776%20495.632%2029.224%20432.016l82.416-27.728%2058.496%2021.288a8%208%200%200%200%205.472-15.032l-58.48-21.288-45.328-74.216c53.568-38.096%20141.432-42.96%20226.52-11.992a345.72%20345.72%200%200%201%2034.56%2014.824l45.344%2045.304a8.008%208.008%200%200%200%2011.32-11.328l-43.744-43.704a348.424%20348.424%200%200%201-0.776-22.376c0-90.528%2034.624-171.44%2088.744-208.752L488%20144.992v62.24a8%208%200%200%200%2016%200v-62.248l54.24-67.968c54.12%2037.32%2088.744%20118.216%2088.744%20208.752%200%207.264-0.28%2014.688-0.76%2022.12l-43.84%2043.808a8%208%200%201%200%2011.32%2011.328l44.976-44.936a346.04%20346.04%200%200%201%2035.016-15.04c85.072-30.96%20172.944-26.096%20226.512%2012l-45.32%2074.224-58.48%2021.288a8%208%200%201%200%205.472%2015.032l58.496-21.288%2082.416%2027.728c-16.552%2063.616-80.736%20123.824-165.808%20154.792-9.896%203.6-20.16%206.76-30.512%209.48l-60.608-16.536a8%208%200%200%200-4.208%2015.44l60.528%2016.512c2.232%202.368%204.456%204.752%206.632%207.208%2060.184%2067.632%2088.112%20151.088%2072.488%20214.936l-85.696-14.712-41.384-46.504a8%208%200%200%200-11.952%2010.64l41.384%2046.496%204.656%2086.832c-65.208%208.096-144.88-29.312-205.064-96.952a338.216%20338.216%200%200%201-39.224-53.864V703.04a8%208%200%200%200-16%200v62.736a332.024%20332.024%200%200%201-22.12%2033.104%208%208%200%201%200%2012.736%209.68%20355.04%20355.04%200%200%200%2017.376-25.032%20358.056%20358.056%200%200%200%2035.272%2046.776c57.76%2064.912%20133.192%20103.384%20199.28%20103.376%209.384%200%2018.592-0.776%2027.52-2.36a8%208%200%200%200%206.592-8.304L760%20836.128l85.736%2014.712a7.96%207.96%200%200%200%209.016-5.576c20.968-69.672-7.888-162.408-73.512-236.448a362.76%20362.76%200%200%200%2021.192-6.976c93.24-33.944%20162.96-102.032%20177.616-173.488a7.984%207.984%200%200%200-5.28-9.184z'%20fill='%233A2C60'%20p-id='2994'%3e%3c/path%3e%3cpath%20d='M674.424%20463.856a28.72%2028.72%200%200%200-35.176-20.304%2028.624%2028.624%200%200%200-21.152%2027.12L531.632%20493.84c-5.424-10.8-15.448-18.896-27.632-21.368V375.12a28.624%2028.624%200%200%200%2020.72-27.448%2028.72%2028.72%200%201%200-57.44%200A28.624%2028.624%200%200%200%20488%20375.12v97.352c-12.184%202.472-22.208%2010.56-27.632%2021.368l-86.472-23.168a28.632%2028.632%200%200%200-21.152-27.12%2028.72%2028.72%200%200%200-14.872%2055.48c12.624%203.384%2025.424-2.28%2031.88-12.912l86.48%2023.168c-0.048%200.8-0.24%201.56-0.24%202.376%200%2010.16%203.904%2019.32%2010.144%2026.376l-53.816%2071.536a28.64%2028.64%200%200%200-33.056%209.48%2028.72%2028.72%200%201%200%2045.904%2034.528c7.856-10.44%207.392-24.432-0.056-34.392l53.792-71.504c5.2%202.472%2010.952%203.968%2017.096%203.968s11.896-1.496%2017.096-3.968l53.792%2071.504c-7.448%209.96-7.912%2023.952-0.056%2034.392a28.72%2028.72%200%200%200%2045.904-34.528%2028.64%2028.64%200%200%200-33.056-9.48l-53.816-71.536A39.68%2039.68%200%200%200%20536%20511.664c0-0.816-0.192-1.576-0.24-2.376l86.48-23.168a28.64%2028.64%200%200%200%2031.88%2012.912%2028.72%2028.72%200%200%200%2020.304-35.176z'%20fill='%23FA759E'%20p-id='2995'%3e%3c/path%3e%3c/svg%3e\"","export default \"data:image/svg+xml,%3c?xml%20version='1.0'%20standalone='no'?%3e%3c!DOCTYPE%20svg%20PUBLIC%20'-//W3C//DTD%20SVG%201.1//EN'%20'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'%3e%3csvg%20t='1735202912040'%20class='icon'%20viewBox='0%200%201024%201024'%20version='1.1'%20xmlns='http://www.w3.org/2000/svg'%20p-id='4284'%20width='16'%20height='16'%20xmlns:xlink='http://www.w3.org/1999/xlink'%3e%3cpath%20d='M517.119%20954.878c244.589%200%20442.879-198.289%20442.879-442.879%200-244.594-198.289-442.879-442.879-442.879C272.524%2069.12%2074.24%20267.404%2074.24%20511.999%2074.24%20756.588%20272.524%20954.878%20517.119%20954.878L517.119%20954.878zM517.119%20891.608c-209.654%200-379.612-169.955-379.612-379.609s169.957-379.612%20379.612-379.612%20379.609%20169.957%20379.609%20379.612S726.773%20891.608%20517.119%20891.608L517.119%20891.608zM523.949%20243.992c-54.662%200-97.177%2016.705-127.547%2050.112-30.367%2031.885-44.795%2074.402-44.795%20127.547l59.98%200c0-37.202%208.35-66.052%2025.055-87.31%2018.222-25.055%2046.312-37.202%2084.272-37.202%2031.885%200%2056.945%208.352%2074.405%2026.572%2016.705%2016.702%2025.81%2040.24%2025.81%2070.607%200%2021.26-7.59%2041-22.775%2059.98-4.55%206.072-13.665%2015.185-25.81%2027.33-41%2036.445-66.055%2065.295-76.685%2088.075-9.11%2018.98-13.665%2040.995-13.665%2066.05l0%2017.465%2060.735%200%200-17.465c0-20.5%204.56-38.725%2014.43-55.425%207.59-13.665%2018.98-27.335%2035.68-41.755%2033.405-29.612%2053.91-49.352%2061.5-58.462%2018.98-25.055%2028.85-54.665%2028.85-88.83%200-45.552-14.425-81.235-42.515-107.05C611.258%20256.902%20572.544%20243.992%20523.949%20243.992L523.949%20243.992zM512.564%20706.363c-12.907%200-23.535%203.795-32.647%2012.905-9.11%208.345-12.905%2018.98-12.905%2031.885s3.795%2023.54%2012.905%2032.65c9.112%208.345%2019.74%2012.905%2032.647%2012.905%2012.91%200%2023.535-4.56%2032.645-12.905%209.11-8.355%2013.665-18.985%2013.665-32.65%200-12.905-4.555-23.54-12.905-31.885C536.859%20710.158%20525.474%20706.363%20512.564%20706.363L512.564%20706.363z'%20fill='%23272636'%20p-id='4285'%3e%3c/path%3e%3c/svg%3e\"","import dayjs from 'dayjs';\n\nconst modules = import.meta.glob('../assets/**', {\n eager: true,\n import: 'default',\n});\n\n/**\n * 获取指定长度的随机字符串\n * @param length\n */\nexport function getRandomString(length: number): string {\n let result = '';\n const characters =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n const charactersLength = characters.length;\n for (let i = 0; i < length; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n return result;\n}\n\n/**\n * 获取资源目录下的文件\n * @param filePath components-image/chart/BarChart.jpg\n */\nexport const getAssetUrl = (filePath: string): any => {\n return modules[`../assets/${filePath}`];\n};\n","export function isEmpty<T>(val: '' | null | T | undefined): val is '' | null | undefined {\n return val === undefined || val === null || val === '';\n}\nexport function isNotEmpty<T>(val: '' | null | T | undefined): val is T {\n return val !== undefined && val !== null && val !== '';\n}\n\nconst patternList = {\n mail: /\\w[-\\w.+]*@([A-Z0-9][-A-Z0-9]+\\.)+[A-Z]{2,14}/i,\n // 密码强度:数字+非数字,或小写字母+非小写字母(即至少两类)\n CryptographicStrength:\n /(?:(?=.*\\d)(?=.*\\D)|(?=.*[a-z])(?=.*[^a-z]))(?!^[^\\n\\r\\u2028\\u2029\\u4E00-\\u9FA5]*[\\u4E00-\\u9FA5].*$)/i,\n};\n\n// 密码强度 数字 字母 符号至少包含两种\nexport function cryptographicStrength(password: string) {\n return patternList.CryptographicStrength.test(password);\n}\n\nexport function isImage(type: string): boolean {\n return ['image/gif', 'image/jpeg', 'image/png'].includes(type);\n}\nexport function isMail(mail: string): boolean {\n return patternList.mail.test(mail);\n}","import { dayjs } from 'element-plus';\n\nimport { isEmpty, isNotEmpty } from './validate';\nimport type { translateJSON, translateObj } from '@/types';\n\n/**\n * 格式化时间戳\n *\n * @param t\n * @param f\n */\nexport const timestamp = (t: string, f?: string) => {\n if (t === null) {\n return t;\n }\n return dayjs(t).format(f || 'YYYY-MM-DD HH:mm:ss');\n};\n\nexport const stringList = (s: any): string | null => {\n if (typeof s === 'object' && !Array.isArray(s)) {\n try {\n if (s !== '' && s !== null && s.type) return s.value;\n } catch (error) {\n // console.log(cellValue)\n console.error(error);\n }\n } else if (s.type) {\n const array: [string] = JSON.parse(s.value);\n return array.length > 0 ? array[array.length - 1] : '';\n }\n\n return s === null ? null : s.toString();\n};\n\ninterface FormatterArray {\n /**\n * cellValue\n */\n value: any;\n /**\n * 翻译的数组\n */\n array: { label: any; value: any }[];\n /**\n * 字段名\n */\n fieldName: string;\n /**\n * 已经循环过存放的数据\n * {\n * field1: {\n * value: label,\n * value2: label2\n * },\n * field2: {\n * value: label\n * }\n * }\n */\n translateObject: any;\n /**\n * 存放已循环过的索引\n */\n translateIndexArray: any;\n}\nexport const formatterData = {\n toString: (value: any) => {\n if (value === null || value === undefined) {\n return null;\n }\n return typeof value === 'string' ? value : value.toString();\n },\n parseInt: (value: any) => {\n return Number.parseInt(value, 10);\n },\n array: (params: FormatterArray) => {\n // 从translateData查找是否已经通过for循环获取 如果已经获取则直接返回\n if (\n params.translateObject[params.fieldName] &&\n isNotEmpty(params.translateObject[params.fieldName][params.value])\n )\n return params.translateObject[params.fieldName][params.value];\n\n if (!params.translateObject[params.fieldName]) {\n params.translateObject[params.fieldName] = {};\n params.translateIndexArray[params.fieldName] = {\n index: 0,\n };\n }\n\n for (\n let i = params.translateIndexArray[params.fieldName].index;\n i < params.array.length;\n i += 1\n ) {\n // 将循环的结果存到translateData\n params.translateObject[params.fieldName][params.array[i].value] =\n params.array[i].label;\n // 把当前索引存放 避免存放循环\n params.translateIndexArray[params.fieldName].index = i;\n if (params.array[i].value === params.value) {\n // 找到了则已经循环过的数据\n\n return params.array[i].label;\n }\n }\n\n // 如果循环完了也没找到 则直接返回原数据\n return params.value;\n },\n};\n\nconst dataFormatter: any = { timestamp, stringList, ...formatterData };\n\n\ninterface FormatterOptions {\n /** 表格数据 */\n cellValue: any;\n tabObj?: 'translate' | translateObj;\n translateJson: translateJSON;\n fieldName: string;\n /**\n * 翻译后的数据缓存 // 配合formatterData.array食用\n */\n translateObject?: any;\n /**\n * 循环索引\n */\n translateIndexArray?: { [propName: string]: any };\n}\n\nexport const customFormatter = (options: FormatterOptions): any => {\n if (isEmpty(options.cellValue) || isEmpty(options.tabObj))\n return options.cellValue;\n\n if (options.tabObj === 'translate') {\n return dataFormatter.array({\n value: options.cellValue,\n array: <{ label: any; value: any }[]>options.translateJson,\n fieldName: options.fieldName,\n translateObject: options.translateObject,\n translateIndexArray: options.translateIndexArray,\n });\n }\n\n if (options.tabObj) {\n return dataFormatter[options.tabObj](options.cellValue);\n }\n return options.cellValue;\n};\n\nexport { dataFormatter };\n","import { isNotEmpty } from './validate';\nimport solarday2lunarday from 'solarday2lunarday';\n\n/**\n * 获取n天后的时间戳\n * @param n\n */\nexport function getTimeStampAfterNDay(n: number) {\n const now = new Date();\n now.setDate(now.getDate() + n);\n return now;\n}\n\n/**\n * 获取农历\n * @param date\n */\nexport const getLunar = (date: any) => {\n const lunar: any = solarday2lunarday.solar2lunar(date.timestamp);\n\n if (isNotEmpty(lunar.festivalName)) {\n return lunar.festivalName;\n } else if (lunar.IDayCn === '初一') {\n return lunar.IMonthCn;\n }\n\n return lunar.IDayCn;\n};\n\n/**\n * 根据时间戳获取相差时间\n * @param startTimestamp 小的时间\n * @param endTimestamp 大的时间\n */\nexport const calculateTimeDifference = (\n startTimestamp: number,\n endTimestamp: number,\n) => {\n const diffInMilliseconds = endTimestamp - startTimestamp; // 获取时间差(毫秒)\n\n const days = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24)); // 计算天数\n const hours = Math.floor(\n (diffInMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60),\n ); // 计算小时\n const minutes = Math.floor(\n (diffInMilliseconds % (1000 * 60 * 60)) / (1000 * 60),\n ); // 计算分钟\n const seconds = Math.floor((diffInMilliseconds % (1000 * 60)) / 1000); // 计算秒数\n\n return `${days}天 ${hours}时 ${minutes}分 ${seconds}秒`;\n};\n\n/**\n * 获取显示时间\n * @param dateTimeStr\n * @param onlyOne 当非今天时 是否只显示日期\n */\nexport function getShowFormatDateTime(dateTimeStr: string, onlyOne?: boolean) {\n const inputDate = new Date(dateTimeStr);\n const today = new Date();\n\n // 判断是否为今天\n const isToday =\n inputDate.getFullYear() === today.getFullYear() &&\n inputDate.getMonth() === today.getMonth() &&\n inputDate.getDate() === today.getDate();\n\n if (isToday) {\n // 返回时间(格式:HH:mm:ss)\n return inputDate.toTimeString().split(' ')[0];\n } else {\n if (onlyOne) {\n return inputDate.toISOString().split('T')[0];\n }\n // 返回日期(格式:YYYY-MM-DD)\n return `${inputDate.toISOString().split('T')[0]} ${inputDate.toTimeString().split(' ')[0]}`;\n }\n}\n","import type { Emitter } from 'mitt';\n\nimport mitt from 'mitt';\n\ntype Events = {\n [key: string]: any; // 你可以具体定义事件和参数类型\n};\n\nexport const emitter: Emitter<Events> = mitt();\n","import type { FormInstance } from 'element-plus';\n\nimport { cryptographicStrength, isMail } from './validate';\n\n/** 表单验证 */\nconst formCheck = async (ref: FormInstance) => {\n if (!ref) return false;\n try {\n await ref.validate();\n return true;\n } catch (error) {\n console.error(error);\n return false;\n }\n};\n\n/** 表单rule验证 */\nconst formValidates = {\n isEmail: (_rule: any, value: string, callback: any) => {\n if (value === '' || isMail(value)) {\n callback();\n }\n callback(new Error('邮箱格式不正确!'));\n },\n /**\n * 判断值的长度或值的范围\n *\n * @param _rule\n * @param value\n * @param callback\n * @param l1 不能小于此参数 | 长度必须等于此\n * @param l2\n */\n length: (\n _rule: any,\n value: string,\n callback: any,\n l1: number,\n l2?: number,\n ) => {\n // 如果l2不存在 则表示是判断长度是否想等\n if (l2) {\n if (value.length <= l1) {\n callback(new Error(`长度不能小于${l1}`));\n return;\n }\n\n if (value.length > l2) {\n callback(new Error(`长度不能大于${l2}`));\n return;\n }\n\n callback();\n } else {\n if (value.length === l1) {\n callback();\n } else {\n callback(new Error(`该值不等于${l1}`));\n }\n }\n },\n /**\n * 判断密码是否包含了数字和字母\n *\n * @param _rule\n * @param value\n * @param callback\n */\n passwordVerify: (_rule: any, value: string, callback: any) => {\n if (cryptographicStrength(value)) {\n callback();\n } else {\n callback(\n new Error('密码需至少包含数字 字母 符号两种,且长度必须大于8小于16'),\n );\n }\n },\n same: (\n _rule: any,\n value: string,\n callback: any,\n value2: any,\n msg?: string,\n ) => {\n if (value === value2) {\n callback();\n } else {\n callback(new Error(msg ?? '两个值不相同'));\n }\n },\n};\n\nexport { formCheck, formValidates };\n","import { ElMessage, ElMessageBox, ElNotification } from 'element-plus';\n\nimport { isEmpty, isNotEmpty } from './validate';\n\ntype TipsType = 'error' | 'info' | 'success' | 'warning';\n\nconst getTitle = (type: TipsType = 'info'): string => {\n if (isEmpty(type)) {\n return '';\n }\n return type;\n // return $t(`tipsType.${type === 'error' ? 'danger' : type}`);\n};\n\ninterface MsgParams {\n title?: string;\n msg: string;\n /**\n * 确定回调\n */\n callback?: Function;\n /**\n * 取消回调\n */\n catch?: Function;\n /**\n * 消息持续时间\n */\n duration?: number;\n}\ninterface MsgParamsTips extends MsgParams {\n type?: TipsType;\n}\n\n/**\n * 弹窗提示\n * @param params\n */\nconst alert = (params: MsgParamsTips) => {\n // 当有一个不为空时 则需要确认\n if (isNotEmpty(params.callback) || isNotEmpty(params.catch)) {\n ElMessageBox.confirm(params.msg, getTitle(params.type), {\n confirmButtonText: 'OK',\n cancelButtonText: 'Cancel',\n type: params.type,\n })\n .then(() => {\n if (params.callback) params.callback();\n })\n .catch(() => {\n if (params.catch) params.catch();\n });\n } else {\n ElMessageBox.alert(params.msg, getTitle(params.type), {\n type: params.type,\n });\n }\n};\n\nconst tips = (params: MsgParamsTips) => {\n ElMessage({\n message: params.msg,\n type: params.type ?? undefined,\n duration: params.duration ?? 3000,\n showClose: true,\n });\n};\n\n/**\n * 通知提示框\n *\n * @param params params\n */\nconst elNotification = (params: MsgParamsTips) => {\n ElNotification({\n title: params.title,\n message: params.msg,\n type: params.type,\n duration:\n params.type === 'warning' ? 6000 : (params.type === 'error' ? 8000 : 3000),\n });\n};\n\nconst msgTips = { alert, elNotification, tips };\n\nexport { msgTips };\n","import { isNotEmpty } from '@/utils';\n\nexport const mergeObjects = (queryData: any, typeData: any) => {\n const mergedObj: { [key: string]: { queryType?: string; val: any } } = {};\n\n // 合并 queryData 中的数据\n for (const key in queryData) {\n if (Object.hasOwn(queryData, key) && isNotEmpty(queryData[key])) {\n mergedObj[key] = {\n val: queryData[key],\n queryType: '',\n };\n }\n }\n\n // 将 typeData 中对应的类型信息添加到 mergedObj 中\n for (const key in typeData) {\n if (Object.hasOwn(typeData, key) && mergedObj[key]?.val) {\n mergedObj[key].queryType = typeData[key];\n }\n }\n\n return mergedObj;\n};\n","<script setup lang=\"ts\">\nimport { computed, reactive, ref, useTemplateRef } from 'vue';\n\nimport type { TableQueryFrame } from '@/types';\n\nimport { mergeObjects } from './hooks';\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\ninterface Props {\n frame: TableQueryFrame[];\n}\n\nconst props = defineProps<Props>();\n\nconst emits = defineEmits(['queryClick']);\n\nconst queryDataState = reactive<any>({});\nconst queryDataTypeState = reactive<any>({});\nconst showAll = ref(false);\n\nconst queryBarRef = useTemplateRef<HTMLDivElement>('query-bar-ref');\nconst debouncedWidth = ref(0);\nuseResizeObserver(\n queryBarRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedWidth.value = entry.contentRect.width;\n }\n }, 300),\n);\n\nconst spanEl = computed(() => {\n if (props.frame.length < 1) {\n return 24;\n } else if (debouncedWidth.value > 1920) {\n return 6;\n } else if (debouncedWidth.value >= 1200) {\n return 6;\n } else if (debouncedWidth.value >= 992) {\n return 8;\n } else if (debouncedWidth.value >= 768) {\n return 12;\n } else if (debouncedWidth.value >= 600) {\n return 12;\n }\n\n return 24;\n});\n\nconst queryClick = () => {\n emits('queryClick', mergeObjects(queryDataState, queryDataTypeState));\n};\n\nconst resetQuery = () => {\n Object.keys(queryDataState).forEach((key) => {\n queryDataState[key] = undefined;\n });\n Object.assign(queryDataState, {});\n};\n</script>\n\n<template>\n <el-form ref=\"query-bar-ref\" :model=\"queryDataState\" class=\"query-bar-client\">\n <el-row :gutter=\"12\">\n <template v-for=\"(item, index) in frame\" :key=\"item.fieldName\">\n <el-col\n v-show=\"showAll === true || (index + 2) * spanEl <= 24\"\n :span=\"spanEl\"\n >\n <el-form-item :label=\"item.fieldTitle\" :prop=\"item.fieldName\">\n <component\n :is=\"item.queryEditor\"\n v-model:query-type=\"queryDataTypeState[item.fieldName]\"\n v-model:value=\"queryDataState[item.fieldName]\"\n :detail=\"item\"\n />\n </el-form-item>\n </el-col>\n </template>\n <el-col :span=\"spanEl\">\n <el-form-item>\n <div style=\"width: 100%; text-align: right\">\n <el-button type=\"primary\" @click=\"queryClick\">\n 搜索\n </el-button>\n <el-button type=\"warning\" @click=\"resetQuery\">\n 重置\n </el-button>\n <el-button\n v-if=\"(frame.length + 1) * spanEl > 24\"\n text\n type=\"success\"\n @click=\"showAll = !showAll\"\n >\n {{ showAll ? '折叠' : '展开' }}\n </el-button>\n </div>\n </el-form-item>\n </el-col>\n </el-row>\n </el-form>\n</template>\n\n<style>\n.query-bar-client {\n padding: 8px 8px 0 8px;\n background: var(--el-fill-color-blank);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, reactive, ref, useTemplateRef } from 'vue';\n\nimport type { TableQueryFrame } from '@/types';\n\nimport { mergeObjects } from './hooks';\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\ninterface Props {\n frame: TableQueryFrame[];\n}\n\nconst props = defineProps<Props>();\n\nconst emits = defineEmits(['queryClick']);\n\nconst queryDataState = reactive<any>({});\nconst queryDataTypeState = reactive<any>({});\nconst showAll = ref(false);\n\nconst queryBarRef = useTemplateRef<HTMLDivElement>('query-bar-ref');\nconst debouncedWidth = ref(0);\nuseResizeObserver(\n queryBarRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedWidth.value = entry.contentRect.width;\n }\n }, 300),\n);\n\nconst spanEl = computed(() => {\n if (props.frame.length < 1) {\n return 24;\n } else if (debouncedWidth.value > 1920) {\n return 6;\n } else if (debouncedWidth.value >= 1200) {\n return 6;\n } else if (debouncedWidth.value >= 992) {\n return 8;\n } else if (debouncedWidth.value >= 768) {\n return 12;\n } else if (debouncedWidth.value >= 600) {\n return 12;\n }\n\n return 24;\n});\n\nconst queryClick = () => {\n emits('queryClick', mergeObjects(queryDataState, queryDataTypeState));\n};\n\nconst resetQuery = () => {\n Object.keys(queryDataState).forEach((key) => {\n queryDataState[key] = undefined;\n });\n Object.assign(queryDataState, {});\n};\n</script>\n\n<template>\n <el-form ref=\"query-bar-ref\" :model=\"queryDataState\" class=\"query-bar-client\">\n <el-row :gutter=\"12\">\n <template v-for=\"(item, index) in frame\" :key=\"item.fieldName\">\n <el-col\n v-show=\"showAll === true || (index + 2) * spanEl <= 24\"\n :span=\"spanEl\"\n >\n <el-form-item :label=\"item.fieldTitle\" :prop=\"item.fieldName\">\n <component\n :is=\"item.queryEditor\"\n v-model:query-type=\"queryDataTypeState[item.fieldName]\"\n v-model:value=\"queryDataState[item.fieldName]\"\n :detail=\"item\"\n />\n </el-form-item>\n </el-col>\n </template>\n <el-col :span=\"spanEl\">\n <el-form-item>\n <div style=\"width: 100%; text-align: right\">\n <el-button type=\"primary\" @click=\"queryClick\">\n 搜索\n </el-button>\n <el-button type=\"warning\" @click=\"resetQuery\">\n 重置\n </el-button>\n <el-button\n v-if=\"(frame.length + 1) * spanEl > 24\"\n text\n type=\"success\"\n @click=\"showAll = !showAll\"\n >\n {{ showAll ? '折叠' : '展开' }}\n </el-button>\n </div>\n </el-form-item>\n </el-col>\n </el-row>\n </el-form>\n</template>\n\n<style>\n.query-bar-client {\n padding: 8px 8px 0 8px;\n background: var(--el-fill-color-blank);\n}\n</style>\n","import QueryBar from './QueryBar.vue';\nimport type { App } from 'vue';\n\n(QueryBar as any).name = 'QueryBar';\n\nQueryBar.install = (app: App) => {\n app.component('QueryBar', QueryBar);\n};\n\nexport { QueryBar };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: string[];\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [Array] as PropType<string[]>,\n});\n\nconst shortcuts = [\n {\n text: '上周',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - 7);\n return [start, end];\n },\n },\n {\n text: '上个月',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setMonth(start.getMonth() - 1);\n return [start, end];\n },\n },\n {\n text: '三个月前',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setMonth(start.getMonth() - 3);\n return [start, end];\n },\n },\n];\n\nonMounted(() => {\n emit('update:queryType', 'range');\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueModel\"\n :shortcuts=\"shortcuts\"\n end-placeholder=\"结束日期\"\n format=\"YYYY-MM-DD HH:mm:ss\"\n range-separator=\"至\"\n start-placeholder=\"开始日期\"\n type=\"datetimerange\"\n value-format=\"YYYY-MM-DD HH:mm:ss\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: string[];\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [Array] as PropType<string[]>,\n});\n\nconst shortcuts = [\n {\n text: '上周',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - 7);\n return [start, end];\n },\n },\n {\n text: '上个月',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setMonth(start.getMonth() - 1);\n return [start, end];\n },\n },\n {\n text: '三个月前',\n value: () => {\n const end = new Date();\n const start = new Date();\n start.setMonth(start.getMonth() - 3);\n return [start, end];\n },\n },\n];\n\nonMounted(() => {\n emit('update:queryType', 'range');\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueModel\"\n :shortcuts=\"shortcuts\"\n end-placeholder=\"结束日期\"\n format=\"YYYY-MM-DD HH:mm:ss\"\n range-separator=\"至\"\n start-placeholder=\"开始日期\"\n type=\"datetimerange\"\n value-format=\"YYYY-MM-DD HH:mm:ss\"\n />\n</template>\n","import QueryDateTime from './QueryDateTime.vue';\nimport type { App } from 'vue';\n\n(QueryDateTime as any).name = 'QueryDateTime';\n\nQueryDateTime.install = (app: App) => {\n app.component('QueryDateTime', QueryDateTime);\n};\n\nexport { QueryDateTime };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: number | string;\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [String, Number] as PropType<number | string>,\n});\n\nonMounted(() => {\n emit('update:queryType', 'equals');\n});\n</script>\n\n<template>\n <el-input v-model=\"valueModel\" clearable />\n</template>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: number | string;\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [String, Number] as PropType<number | string>,\n});\n\nonMounted(() => {\n emit('update:queryType', 'equals');\n});\n</script>\n\n<template>\n <el-input v-model=\"valueModel\" clearable />\n</template>\n","import QueryInput from './QueryInput.vue';\nimport type { App } from 'vue';\n\n(QueryInput as any).name = 'QueryInput';\n\nQueryInput.install = (app: App) => {\n app.component('QueryInput', QueryInput);\n};\n\nexport { QueryInput };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: string | number;\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [String, Number] as PropType<number | string>,\n});\n\nonMounted(() => {\n emit('update:queryType', 'like');\n});\n</script>\n\n<template>\n <el-input v-model=\"valueModel\" clearable />\n</template>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value: string | number;\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueModel = defineModel('value', {\n type: [String, Number] as PropType<number | string>,\n});\n\nonMounted(() => {\n emit('update:queryType', 'like');\n});\n</script>\n\n<template>\n <el-input v-model=\"valueModel\" clearable />\n</template>\n","import QueryInputLike from './QueryInputLike.vue';\nimport type { App } from 'vue';\n\n(QueryInputLike as any).name = 'QueryInputLike';\n\nQueryInputLike.install = (app: App) => {\n app.component('QueryInputLike', QueryInputLike);\n};\n\nexport { QueryInputLike };\n","<script setup lang=\"ts\">\nimport type { QuerySelector } from '../../../types';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value?: any;\n detail: QuerySelector;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: () => null,\n});\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueRef = defineModel('value');\n\nonMounted(() => {\n emit('update:queryType', 'equals');\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :options=\"detail?.options\"\n class=\"min-width\"\n clearable\n >\n <el-option\n v-for=\"item in detail?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped>\n.min-width {\n min-width: 120px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { QuerySelector } from '../../../types';\n\nimport { onMounted } from 'vue';\n\ninterface Props {\n value?: any;\n detail: QuerySelector;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: () => null,\n});\n\nconst emit = defineEmits(['update:value', 'update:queryType']);\n\nconst valueRef = defineModel('value');\n\nonMounted(() => {\n emit('update:queryType', 'equals');\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :options=\"detail?.options\"\n class=\"min-width\"\n clearable\n >\n <el-option\n v-for=\"item in detail?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped>\n.min-width {\n min-width: 120px;\n}\n</style>\n","import QuerySelect from './QuerySelect.vue';\nimport type { App } from 'vue';\n\n(QuerySelect as any).name = 'QuerySelect';\n\nQuerySelect.install = (app: App) => {\n app.component('QuerySelect', QuerySelect);\n};\n\nexport { QuerySelect };\n","<script setup lang=\"ts\">\nimport type { FilterData } from './QueryTreeFilter';\n\nimport { ref } from 'vue';\n\nimport { getQueryTreeFilterDataApi } from '@/api';\nimport { removeValueFromArray } from '@/utils';\nimport { LoadFunction } from 'element-plus';\n\ninterface Props {\n pageId: number;\n}\n\nconst props = defineProps<Props>();\nconst emits = defineEmits(['checkChange']);\n/**\n * 被选择的\n */\nconst checkboxes = ref<any[]>([]);\n\n/**\n * 当复选框被点击的时候触发\n * @param data 传递给 data 属性的数组中该节点所对应的对象\n * @param checked 节点本身是否被选中\n * @param _indeterminate 节点的子树中是否有被选中的节点\n */\nconst handleCheckChange = (\n data: FilterData,\n checked: boolean,\n _indeterminate: boolean,\n) => {\n checkboxes.value =\n checked\n ? [...checkboxes.value, data.value]\n : removeValueFromArray(checkboxes.value, data.value);\n emits('checkChange');\n};\n\n/**\n * 加载节点\n */\nconst loadNode: LoadFunction = async (node, resolve: (data: any[]) => void, reject) => {\n const pid = node.data.value ?? null;\n const result = await getQueryTreeFilterDataApi({\n pageId: props.pageId,\n pid,\n });\n if (\n result.code === 0 &&\n Array.isArray(result.data.filterData) &&\n result.data.filterData.length > 0\n ) {\n return resolve(result.data.filterData);\n }\n\n reject();\n};\n\nconst getCheckboxes = () => {\n return {\n val: checkboxes.value,\n };\n};\n\ndefineExpose({ getCheckboxes });\n</script>\n\n<template>\n <div class=\"filterBoard\">\n <el-button type=\"primary\">全选</el-button>\n <div class=\"tree-container\">\n <el-scrollbar>\n <el-tree\n :load=\"loadNode\"\n lazy\n show-checkbox\n @check-change=\"handleCheckChange\"\n >\n <template #default=\"{ node, data }\">\n <span\n :class=\"checkboxes.includes(data.value) ? 'is-checked' : ''\"\n class=\"custom-tree-node\"\n >\n <span>{{ node.label }}</span>\n </span>\n </template>\n </el-tree>\n </el-scrollbar>\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.filterBoard {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n background: var(--el-fill-color-blank);\n margin: 6px 6px 6px 0;\n padding: 12px 8px 8px;\n height: calc(100% - 12px);\n\n .tree-container {\n margin-top: 12px;\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n }\n}\n\n.custom-tree-node {\n display: flex;\n flex: 1;\n align-items: center;\n justify-content: space-between;\n padding: 4px 4px 4px 6px;\n font-size: 14px;\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\n.is-checked {\n color: white;\n background-color: var(--el-color-primary) !important; /* 自定义背景颜色 */\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FilterData } from './QueryTreeFilter';\n\nimport { ref } from 'vue';\n\nimport { getQueryTreeFilterDataApi } from '@/api';\nimport { removeValueFromArray } from '@/utils';\nimport { LoadFunction } from 'element-plus';\n\ninterface Props {\n pageId: number;\n}\n\nconst props = defineProps<Props>();\nconst emits = defineEmits(['checkChange']);\n/**\n * 被选择的\n */\nconst checkboxes = ref<any[]>([]);\n\n/**\n * 当复选框被点击的时候触发\n * @param data 传递给 data 属性的数组中该节点所对应的对象\n * @param checked 节点本身是否被选中\n * @param _indeterminate 节点的子树中是否有被选中的节点\n */\nconst handleCheckChange = (\n data: FilterData,\n checked: boolean,\n _indeterminate: boolean,\n) => {\n checkboxes.value =\n checked\n ? [...checkboxes.value, data.value]\n : removeValueFromArray(checkboxes.value, data.value);\n emits('checkChange');\n};\n\n/**\n * 加载节点\n */\nconst loadNode: LoadFunction = async (node, resolve: (data: any[]) => void, reject) => {\n const pid = node.data.value ?? null;\n const result = await getQueryTreeFilterDataApi({\n pageId: props.pageId,\n pid,\n });\n if (\n result.code === 0 &&\n Array.isArray(result.data.filterData) &&\n result.data.filterData.length > 0\n ) {\n return resolve(result.data.filterData);\n }\n\n reject();\n};\n\nconst getCheckboxes = () => {\n return {\n val: checkboxes.value,\n };\n};\n\ndefineExpose({ getCheckboxes });\n</script>\n\n<template>\n <div class=\"filterBoard\">\n <el-button type=\"primary\">全选</el-button>\n <div class=\"tree-container\">\n <el-scrollbar>\n <el-tree\n :load=\"loadNode\"\n lazy\n show-checkbox\n @check-change=\"handleCheckChange\"\n >\n <template #default=\"{ node, data }\">\n <span\n :class=\"checkboxes.includes(data.value) ? 'is-checked' : ''\"\n class=\"custom-tree-node\"\n >\n <span>{{ node.label }}</span>\n </span>\n </template>\n </el-tree>\n </el-scrollbar>\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.filterBoard {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n background: var(--el-fill-color-blank);\n margin: 6px 6px 6px 0;\n padding: 12px 8px 8px;\n height: calc(100% - 12px);\n\n .tree-container {\n margin-top: 12px;\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n }\n}\n\n.custom-tree-node {\n display: flex;\n flex: 1;\n align-items: center;\n justify-content: space-between;\n padding: 4px 4px 4px 6px;\n font-size: 14px;\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\n.is-checked {\n color: white;\n background-color: var(--el-color-primary) !important; /* 自定义背景颜色 */\n}\n</style>\n","import QueryTreeFilter from './QueryTreeFilter.vue';\nimport type { App } from 'vue';\n\n(QueryTreeFilter as any).name = 'QueryTreeFilter';\n\nQueryTreeFilter.install = (app: App) => {\n app.component('QueryTreeFilter', QueryTreeFilter);\n};\n\nexport { QueryTreeFilter };\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '@/types';\n\nimport { nextTick, ref, unref } from 'vue';\n\ninterface Props {\n value?: null | number | string;\n detail: TableComponentFrame;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange']);\n\nconst popoverRef = ref();\nconst buttonRef = ref();\nconst modelVal = defineModel('value', {\n required: false,\n default: null,\n});\nconst inputValue = ref(null);\n\nconst edit = () => {\n inputValue.value = modelVal.value;\n};\n\nconst confirm = async () => {\n if (modelVal.value !== inputValue.value) {\n modelVal.value = inputValue.value;\n await nextTick();\n unref(popoverRef).popperRef?.delayHide?.();\n emits('valueChange', props.detail?.field, modelVal.value, props.rowData);\n }\n};\n</script>\n\n<template>\n <div>\n <span ref=\"buttonRef\" class=\"text\" @click.stop=\"edit\">\n <template\n v-if=\"modelVal === null || modelVal === '' || modelVal === undefined\"\n >\n <el-skeleton :rows=\"0\" />\n </template>\n <template v-else>\n {{ modelVal }}\n </template>\n </span>\n <el-popover\n ref=\"popoverRef\"\n :virtual-ref=\"buttonRef\"\n :width=\"200\"\n trigger=\"click\"\n virtual-triggering\n @hide=\"confirm\"\n >\n <el-input\n v-model=\"inputValue\"\n :placeholder=\"detail.placeholder\"\n v-bind=\"detail.editRender?.props?.componentParams\"\n />\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.text {\n width: 100%;\n cursor: pointer;\n display: inline-block;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '@/types';\n\nimport { nextTick, ref, unref } from 'vue';\n\ninterface Props {\n value?: null | number | string;\n detail: TableComponentFrame;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange']);\n\nconst popoverRef = ref();\nconst buttonRef = ref();\nconst modelVal = defineModel('value', {\n required: false,\n default: null,\n});\nconst inputValue = ref(null);\n\nconst edit = () => {\n inputValue.value = modelVal.value;\n};\n\nconst confirm = async () => {\n if (modelVal.value !== inputValue.value) {\n modelVal.value = inputValue.value;\n await nextTick();\n unref(popoverRef).popperRef?.delayHide?.();\n emits('valueChange', props.detail?.field, modelVal.value, props.rowData);\n }\n};\n</script>\n\n<template>\n <div>\n <span ref=\"buttonRef\" class=\"text\" @click.stop=\"edit\">\n <template\n v-if=\"modelVal === null || modelVal === '' || modelVal === undefined\"\n >\n <el-skeleton :rows=\"0\" />\n </template>\n <template v-else>\n {{ modelVal }}\n </template>\n </span>\n <el-popover\n ref=\"popoverRef\"\n :virtual-ref=\"buttonRef\"\n :width=\"200\"\n trigger=\"click\"\n virtual-triggering\n @hide=\"confirm\"\n >\n <el-input\n v-model=\"inputValue\"\n :placeholder=\"detail.placeholder\"\n v-bind=\"detail.editRender?.props?.componentParams\"\n />\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.text {\n width: 100%;\n cursor: pointer;\n display: inline-block;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n</style>\n","import TableInput from './TableInput.vue';\nimport type { App } from 'vue';\n\n(TableInput as any).name = 'TableInput';\n\nTableInput.install = (app: App) => {\n app.component('TableInput', TableInput);\n};\n\nexport { TableInput };\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '@/types';\n\nimport { nextTick, ref, unref } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableComponentFrame;\n rowData?: any;\n disabled?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n rowData: () => ({}),\n disabled: true,\n});\n\nconst emits = defineEmits(['valueChange']);\n\nconst popoverRef = ref();\nconst buttonRef = ref();\nconst modelVal = defineModel<number | null>('value', {\n required: false,\n default: null,\n});\nconst inputValue = ref<null | number>(null);\n\nconst edit = () => {\n inputValue.value = modelVal.value;\n};\n\nconst confirm = async () => {\n if (inputValue.value !== modelVal.value) {\n modelVal.value = inputValue.value;\n await nextTick();\n emits('valueChange', props.detail?.field, inputValue.value, props.rowData);\n }\n unref(popoverRef).popperRef?.delayHide?.();\n};\n</script>\n\n<template>\n <div style=\"width: 100%\">\n <span ref=\"buttonRef\" class=\"text\" @click.stop=\"edit\">\n <template v-if=\"modelVal === null || modelVal === undefined\">\n <el-skeleton :rows=\"0\" />\n </template>\n <template v-else>\n {{ modelVal }}\n </template>\n </span>\n <el-popover\n ref=\"popoverRef\"\n :virtual-ref=\"buttonRef\"\n :width=\"210\"\n trigger=\"click\"\n virtual-triggering\n @hide=\"confirm\"\n >\n <el-input-number\n v-model=\"inputValue\"\n :placeholder=\"detail.placeholder\"\n style=\"width: 184px\"\n v-bind=\"detail.editRender?.props?.componentParams\"\n >\n <template\n v-if=\"\n detail.editRender?.props?.componentParams &&\n detail.editRender.props.componentParams.suffix\n \"\n #suffix\n >\n <span>{{ detail.editRender.props.componentParams.suffix }}</span>\n </template>\n </el-input-number>\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.text {\n width: 100%;\n cursor: pointer;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '@/types';\n\nimport { nextTick, ref, unref } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableComponentFrame;\n rowData?: any;\n disabled?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n rowData: () => ({}),\n disabled: true,\n});\n\nconst emits = defineEmits(['valueChange']);\n\nconst popoverRef = ref();\nconst buttonRef = ref();\nconst modelVal = defineModel<number | null>('value', {\n required: false,\n default: null,\n});\nconst inputValue = ref<null | number>(null);\n\nconst edit = () => {\n inputValue.value = modelVal.value;\n};\n\nconst confirm = async () => {\n if (inputValue.value !== modelVal.value) {\n modelVal.value = inputValue.value;\n await nextTick();\n emits('valueChange', props.detail?.field, inputValue.value, props.rowData);\n }\n unref(popoverRef).popperRef?.delayHide?.();\n};\n</script>\n\n<template>\n <div style=\"width: 100%\">\n <span ref=\"buttonRef\" class=\"text\" @click.stop=\"edit\">\n <template v-if=\"modelVal === null || modelVal === undefined\">\n <el-skeleton :rows=\"0\" />\n </template>\n <template v-else>\n {{ modelVal }}\n </template>\n </span>\n <el-popover\n ref=\"popoverRef\"\n :virtual-ref=\"buttonRef\"\n :width=\"210\"\n trigger=\"click\"\n virtual-triggering\n @hide=\"confirm\"\n >\n <el-input-number\n v-model=\"inputValue\"\n :placeholder=\"detail.placeholder\"\n style=\"width: 184px\"\n v-bind=\"detail.editRender?.props?.componentParams\"\n >\n <template\n v-if=\"\n detail.editRender?.props?.componentParams &&\n detail.editRender.props.componentParams.suffix\n \"\n #suffix\n >\n <span>{{ detail.editRender.props.componentParams.suffix }}</span>\n </template>\n </el-input-number>\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.text {\n width: 100%;\n cursor: pointer;\n}\n</style>\n","import TableInputNumber from './TableInputNumber.vue';\nimport type { App } from 'vue';\n\n(TableInputNumber as any).name = 'TableInputNumber';\n\nTableInputNumber.install = (app: App) => {\n app.component('TableInputNumber', TableInputNumber);\n};\n\nexport { TableInputNumber };\n","<script setup lang=\"ts\">\nimport type { TableSelectorProp } from '@/types';\n\nimport { onMounted, ref, watch } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = ref<any>(undefined);\n\nconst handleChange = () => {\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\n};\n\nwatch(\n () => props.value,\n (newValue) => {\n setValue(newValue);\n },\n);\n\nconst setValue = (v: any) => {\n if (props.detail?.editRender?.props?.multiple) {\n valueRef.value = Array.isArray(v) ? v : [];\n } else if (['number', 'string'].includes(typeof v) || v === null) {\n valueRef.value = v;\n }\n};\n\nonMounted(() => {\n setValue(props.value);\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.editRender?.props?.multiple === true\"\n filterable\n style=\"width: 100%\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail?.editRender.props.componentParams\n : {}\n \"\n :disabled=\"detail.disabled !== false\"\n :options=\"detail?.editRender?.props?.options\"\n :placeholder=\"detail?.placeholder\"\n @change=\"handleChange\"\n >\n <el-option\n v-for=\"item in detail?.editRender?.props?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { TableSelectorProp } from '@/types';\n\nimport { onMounted, ref, watch } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = ref<any>(undefined);\n\nconst handleChange = () => {\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\n};\n\nwatch(\n () => props.value,\n (newValue) => {\n setValue(newValue);\n },\n);\n\nconst setValue = (v: any) => {\n if (props.detail?.editRender?.props?.multiple) {\n valueRef.value = Array.isArray(v) ? v : [];\n } else if (['number', 'string'].includes(typeof v) || v === null) {\n valueRef.value = v;\n }\n};\n\nonMounted(() => {\n setValue(props.value);\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.editRender?.props?.multiple === true\"\n filterable\n style=\"width: 100%\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail?.editRender.props.componentParams\n : {}\n \"\n :disabled=\"detail.disabled !== false\"\n :options=\"detail?.editRender?.props?.options\"\n :placeholder=\"detail?.placeholder\"\n @change=\"handleChange\"\n >\n <el-option\n v-for=\"item in detail?.editRender?.props?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","import TableSelect from './TableSelect.vue';\nimport type { App } from 'vue';\n\n(TableSelect as any).name = 'TableSelect';\n\nTableSelect.install = (app: App) => {\n app.component('TableSelect', TableSelect);\n};\n\nexport { TableSelect };\n","<script setup lang=\"ts\">\nimport type { TableSelectorProp } from '@/types';\n\ninterface Props {\n value?: any;\n detail: TableSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value');\n\nconst handleChange = (value: any) => {\n emits('valueChange', props.detail?.field, value, props.rowData);\n};\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.editRender?.props.multiple === true\"\n filterable\n style=\"width: 100%\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail?.editRender.props.componentParams\n : {}\n \"\n :disabled=\"detail?.disabled !== false\"\n :placeholder=\"detail?.placeholder\"\n @change=\"handleChange\"\n >\n <el-option\n v-for=\"item in detail?.editRender?.props.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n","<script setup lang=\"ts\">\nimport type { TableSelectorProp } from '@/types';\n\ninterface Props {\n value?: any;\n detail: TableSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value');\n\nconst handleChange = (value: any) => {\n emits('valueChange', props.detail?.field, value, props.rowData);\n};\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.editRender?.props.multiple === true\"\n filterable\n style=\"width: 100%\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail?.editRender.props.componentParams\n : {}\n \"\n :disabled=\"detail?.disabled !== false\"\n :placeholder=\"detail?.placeholder\"\n @change=\"handleChange\"\n >\n <el-option\n v-for=\"item in detail?.editRender?.props.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n","import TableSelectAsync from './TableSelectAsync.vue';\nimport type { App } from 'vue';\n\n(TableSelectAsync as any).name = 'TableSelectAsync';\n\nTableSelectAsync.install = (app: App) => {\n app.component('TableSelectAsync', TableSelectAsync);\n};\n\nexport { TableSelectAsync };\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '../../../types';\n\ninterface Props {\n value?: boolean;\n detail: TableComponentFrame;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: false,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value', {\n type: Boolean,\n});\n\nconst send = (val: boolean) => {\n emits('valueChange', props.detail?.field, val, props.rowData);\n};\n</script>\n\n<template>\n <el-switch\n v-model=\"valueRef\"\n :disabled=\"detail?.disabled !== false\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail.editRender.props.componentParams\n : {}\n \"\n @change=\"send\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport type { TableComponentFrame } from '../../../types';\n\ninterface Props {\n value?: boolean;\n detail: TableComponentFrame;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: false,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value', {\n type: Boolean,\n});\n\nconst send = (val: boolean) => {\n emits('valueChange', props.detail?.field, val, props.rowData);\n};\n</script>\n\n<template>\n <el-switch\n v-model=\"valueRef\"\n :disabled=\"detail?.disabled !== false\"\n v-bind=\"\n detail.editRender?.props?.componentParams\n ? detail.editRender.props.componentParams\n : {}\n \"\n @change=\"send\"\n />\n</template>\n","import TableSwitch from './TableSwitch.vue';\nimport type { App } from 'vue';\n\n(TableSwitch as any).name = 'TableSwitch';\n\nTableSwitch.install = (app: App) => {\n app.component('TableSwitch', TableSwitch);\n};\n\nexport { TableSwitch };\n","<script setup lang=\"ts\">\nimport type { TableListSelectorProp } from '@/types';\n\nimport { nextTick } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableListSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value');\n\nconst handleChange = async () => {\n await nextTick();\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\n};\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"\n detail.editRender?.props.componentParams\n ? detail.editRender.props.componentParams\n : {}\n \"\n :multiple=\"detail?.editRender?.props?.multiple === true\"\n :placeholder=\"detail.placeholder\"\n :value-key=\"detail.editRender?.props.componentParams.keyField\"\n @change=\"handleChange\"\n clearable\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.editRender?.props.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in detail.editRender?.props.options\"\n :key=\"item[detail.editRender.props.componentParams.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.editRender.props.componentParams.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.editRender?.props.componentParams?.optionWidth\n ? `${detail.editRender?.props.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.editRender?.props.componentParams\n ?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n","<script setup lang=\"ts\">\nimport type { TableListSelectorProp } from '@/types';\n\nimport { nextTick } from 'vue';\n\ninterface Props {\n value?: any;\n detail: TableListSelectorProp;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['valueChange', 'update:value']);\n\nconst valueRef = defineModel('value');\n\nconst handleChange = async () => {\n await nextTick();\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\n};\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"\n detail.editRender?.props.componentParams\n ? detail.editRender.props.componentParams\n : {}\n \"\n :multiple=\"detail?.editRender?.props?.multiple === true\"\n :placeholder=\"detail.placeholder\"\n :value-key=\"detail.editRender?.props.componentParams.keyField\"\n @change=\"handleChange\"\n clearable\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.editRender?.props.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in detail.editRender?.props.options\"\n :key=\"item[detail.editRender.props.componentParams.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.editRender.props.componentParams.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.editRender?.props.componentParams?.optionWidth\n ? `${detail.editRender?.props.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.editRender?.props.componentParams\n ?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n","import TableListSelect from './TableListSelect.vue';\nimport type { App } from 'vue';\n\n(TableListSelect as any).name = 'TableListSelect';\n\nTableListSelect.install = (app: App) => {\n app.component('TableListSelect', TableListSelect);\n};\n\nexport { TableListSelect };\n","import type { Ref } from 'vue';\n\nimport type { OptionInterface } from '@/types';\n\nimport { ref } from 'vue';\n\nimport { isEmpty, msgTips, sleep } from '@/utils';\n\ninterface Props {\n detail: any;\n rowData?: any;\n}\n\ninterface TableSelectAsync<EE extends (...args: any) => void> {\n emits: EE;\n props: Props;\n valueRef: Ref;\n}\n\nexport const useTableSelectAsync = <EE extends (...args: any) => void>(\n params: TableSelectAsync<EE>,\n) => {\n const { emits, props } = params;\n\n const loading = ref<boolean>(false);\n let load = false;\n let isLoadFail = false;\n let oldComponentValueMap: any = {};\n\n // 选项\n const optionsData = ref<any[] | OptionInterface[]>([]);\n\n const init = async () => {\n await sleep(0.05 + Math.floor(Math.random() * 300) / 100);\n await getOptions();\n };\n\n /**\n * 验证从当前行数据中获取的其他参数是否有效\n * @param params\n * @param fieldNames\n */\n const verifyHttpOtherParams = (params: any, fieldNames: string[]) => {\n let result = true;\n if (fieldNames.length > 0 && !params) {\n return false;\n }\n fieldNames.forEach((fieldName) => {\n if (params[fieldName] === undefined || params[fieldName] === null) {\n result = false;\n }\n });\n\n return result;\n };\n\n /** 远程获取 */\n const getOptions = async () => {\n if (loading.value) return;\n const editProps = props.detail?.editRender?.props;\n if (!editProps || isEmpty(editProps.optionHttpUrl)) return;\n\n // 从当前行数据 rowData 中获取其他字段的值作为请求参数\n let componentValueMap: any = {};\n const fieldNames: string[] = editProps.optionHttpParamsValue || [];\n if (fieldNames.length > 0 && props.rowData) {\n fieldNames.forEach((fieldName: string) => {\n componentValueMap[fieldName] = props.rowData[fieldName];\n });\n }\n\n // 如果(已经加载 || 加载失败)且新获取的数据与旧数据一样,则不再重新请求\n if (\n (load || isLoadFail) &&\n JSON.stringify(componentValueMap) === JSON.stringify(oldComponentValueMap)\n )\n return;\n\n if (!verifyHttpOtherParams(componentValueMap, fieldNames)) {\n // 验证失败则不发http请求\n return;\n }\n\n loading.value = true;\n oldComponentValueMap = componentValueMap;\n\n const opt: any = {\n method: editProps.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (!['get', 'GET', 'head', 'HEAD'].includes(editProps.optionHttpMethod)) {\n opt.body = JSON.stringify({\n prop: props.detail.field,\n ...editProps.optionHttpParams,\n ...componentValueMap,\n });\n }\n const response = await fetch(editProps.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n load = true;\n optionsData.value = result.data;\n } else {\n msgTips.alert({\n msg: `${props.detail?.title || ''}数据获取失败!`,\n type: 'warning',\n });\n isLoadFail = true;\n }\n loading.value = false;\n };\n\n return {\n getOptions,\n optionsData,\n loading,\n init,\n };\n};\n","<script setup lang=\"ts\">\r\nimport { TableListSelectorAsyncProp } from '@/types';\r\n\r\nimport { nextTick, onMounted } from 'vue';\r\n\r\nimport { useTableSelectAsync } from '../hooks/tableSelectAsync.hook';\r\n\r\ninterface Props {\r\n value?: any;\r\n detail: TableListSelectorAsyncProp;\r\n rowData?: any;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n value: () => null,\r\n rowData: () => ({}),\r\n});\r\n\r\nconst emits = defineEmits(['valueChange', 'update:value']);\r\n\r\nconst valueRef = defineModel('value');\r\n\r\nconst { loading, getOptions, optionsData, init } = useTableSelectAsync({\r\n emits,\r\n props,\r\n valueRef,\r\n});\r\n\r\nconst handleChange = async () => {\r\n await nextTick();\r\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\r\n};\r\n\r\nonMounted(() => {\r\n init();\r\n});\r\n</script>\r\n\r\n<template>\r\n <el-select\r\n v-model=\"valueRef\"\r\n v-bind=\"\r\n detail.editRender?.props.componentParams\r\n ? detail.editRender.props.componentParams\r\n : {}\r\n \"\r\n v-loading=\"loading\"\r\n :multiple=\"detail?.editRender?.props?.multiple === true\"\r\n :loading=\"loading\"\r\n :placeholder=\"detail.placeholder\"\r\n :value-key=\"detail.editRender?.props.componentParams.keyField\"\r\n clearable\r\n @change=\"handleChange\"\r\n @focus=\"getOptions\"\r\n >\r\n <template #header>\r\n <el-row>\r\n <el-col\r\n v-for=\"item in detail.editRender?.props.componentParams?.optionSlots\"\r\n :key=\"item.field\"\r\n :span=\"item.span\"\r\n >\r\n <el-text truncated>\r\n {{ item.label }}\r\n </el-text>\r\n </el-col>\r\n </el-row>\r\n </template>\r\n <el-option\r\n v-for=\"item in optionsData\"\r\n :key=\"item[detail.editRender.props.componentParams.keyField]\"\r\n :disabled=\"item.disabled === true\"\r\n :label=\"item[detail.editRender.props.componentParams.labelField]\"\r\n :value=\"item\"\r\n :style=\"{\r\n width: detail.editRender?.props.componentParams?.optionWidth\r\n ? `${detail.editRender?.props.componentParams.optionWidth}px`\r\n : '100%',\r\n }\"\r\n >\r\n <el-row>\r\n <el-col\r\n v-for=\"optionSlot in detail.editRender?.props.componentParams\r\n ?.optionSlots\"\r\n :key=\"optionSlot.field\"\r\n :span=\"optionSlot.span\"\r\n >\r\n <el-text truncated>\r\n {{ item[optionSlot.field] }}\r\n </el-text>\r\n </el-col>\r\n </el-row>\r\n </el-option>\r\n </el-select>\r\n</template>\r\n\r\n<style scoped></style>\r\n","<script setup lang=\"ts\">\r\nimport { TableListSelectorAsyncProp } from '@/types';\r\n\r\nimport { nextTick, onMounted } from 'vue';\r\n\r\nimport { useTableSelectAsync } from '../hooks/tableSelectAsync.hook';\r\n\r\ninterface Props {\r\n value?: any;\r\n detail: TableListSelectorAsyncProp;\r\n rowData?: any;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n value: () => null,\r\n rowData: () => ({}),\r\n});\r\n\r\nconst emits = defineEmits(['valueChange', 'update:value']);\r\n\r\nconst valueRef = defineModel('value');\r\n\r\nconst { loading, getOptions, optionsData, init } = useTableSelectAsync({\r\n emits,\r\n props,\r\n valueRef,\r\n});\r\n\r\nconst handleChange = async () => {\r\n await nextTick();\r\n emits('valueChange', props.detail?.field, valueRef.value, props.rowData);\r\n};\r\n\r\nonMounted(() => {\r\n init();\r\n});\r\n</script>\r\n\r\n<template>\r\n <el-select\r\n v-model=\"valueRef\"\r\n v-bind=\"\r\n detail.editRender?.props.componentParams\r\n ? detail.editRender.props.componentParams\r\n : {}\r\n \"\r\n v-loading=\"loading\"\r\n :multiple=\"detail?.editRender?.props?.multiple === true\"\r\n :loading=\"loading\"\r\n :placeholder=\"detail.placeholder\"\r\n :value-key=\"detail.editRender?.props.componentParams.keyField\"\r\n clearable\r\n @change=\"handleChange\"\r\n @focus=\"getOptions\"\r\n >\r\n <template #header>\r\n <el-row>\r\n <el-col\r\n v-for=\"item in detail.editRender?.props.componentParams?.optionSlots\"\r\n :key=\"item.field\"\r\n :span=\"item.span\"\r\n >\r\n <el-text truncated>\r\n {{ item.label }}\r\n </el-text>\r\n </el-col>\r\n </el-row>\r\n </template>\r\n <el-option\r\n v-for=\"item in optionsData\"\r\n :key=\"item[detail.editRender.props.componentParams.keyField]\"\r\n :disabled=\"item.disabled === true\"\r\n :label=\"item[detail.editRender.props.componentParams.labelField]\"\r\n :value=\"item\"\r\n :style=\"{\r\n width: detail.editRender?.props.componentParams?.optionWidth\r\n ? `${detail.editRender?.props.componentParams.optionWidth}px`\r\n : '100%',\r\n }\"\r\n >\r\n <el-row>\r\n <el-col\r\n v-for=\"optionSlot in detail.editRender?.props.componentParams\r\n ?.optionSlots\"\r\n :key=\"optionSlot.field\"\r\n :span=\"optionSlot.span\"\r\n >\r\n <el-text truncated>\r\n {{ item[optionSlot.field] }}\r\n </el-text>\r\n </el-col>\r\n </el-row>\r\n </el-option>\r\n </el-select>\r\n</template>\r\n\r\n<style scoped></style>\r\n","import TableListSelectAsync from './TableListSelectAsync.vue';\nimport type { App } from 'vue';\n\n(TableListSelectAsync as any).name = 'TableListSelectAsync';\n\nTableListSelectAsync.install = (app: App) => {\n app.component('TableListSelectAsync', TableListSelectAsync);\n};\n\nexport { TableListSelectAsync };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { TableSelectorProp } from '@/types';\n\nimport { reactive, ref } from 'vue';\nimport { TableCheckBoxAsyncI18n } from '@/components/TableComponent/TableCheckBoxAsync/type';\n\ninterface Props {\n value?: any[];\n detail: TableSelectorProp;\n i18Text?: TableCheckBoxAsyncI18n;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => [],\n i18Text: () => ({\n save: '保存',\n cancel: '取消',\n close: '关闭',\n }),\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['update:value', 'valueChange', 'setShow']);\n\nconst valueRef = defineModel('value', {\n type: Array as PropType<any[]>,\n default: () => [],\n});\n\nconst state = reactive({\n dialogVisible: false,\n showText: '',\n});\n\nconst checkData = ref<any[]>([]);\n\nconst change = () => {\n valueRef.value = checkData.value;\n emits('valueChange', props.detail.field, checkData.value, props.rowData);\n state.dialogVisible = false;\n setShowText(checkData.value);\n};\n\nconst textCache: any = {};\n\nconst setShowText = (componentData: any[]) => {\n if (Array.isArray(props.detail?.editRender?.props?.options)) {\n props.detail.editRender.props.options.forEach((item) => {\n textCache[item.value] = item.label;\n });\n }\n let text = '';\n for (const componentDatum of componentData) {\n text = `${text} ${\n textCache[componentDatum] === undefined\n ? componentDatum\n : textCache[componentDatum]\n }`;\n }\n state.showText = text;\n};\n\nconst openDialog = () => {\n state.dialogVisible = true;\n checkData.value = valueRef.value;\n};\n</script>\n\n<template>\n <div class=\"table-check-box-async\">\n <span class=\"text\" @click.stop=\"openDialog\">\n {{ state.showText ? state.showText : '空' }}\n </span>\n <el-dialog\n v-model=\"state.dialogVisible\"\n :show-close=\"false\"\n append-to-body\n center\n >\n <template #header>\n <div class=\"dialog-header\">\n <div>\n <el-button size=\"small\" type=\"primary\" @click=\"change\">\n {{ i18Text.save }}\n </el-button>\n <el-button size=\"small\" @click=\"state.dialogVisible = false\">\n {{ i18Text.cancel }}\n </el-button>\n </div>\n <el-button\n size=\"small\"\n type=\"danger\"\n @click=\"state.dialogVisible = false\"\n >\n {{ i18Text.close }}\n </el-button>\n </div>\n </template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in detail?.editRender?.props?.options\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n </el-dialog>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.table-check-box-async {\n width: 100%;\n\n .text {\n cursor: pointer;\n }\n}\n\n.dialog-header {\n display: flex;\n flex-direction: row;\n gap: 16px;\n justify-content: space-between;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { TableSelectorProp } from '@/types';\n\nimport { reactive, ref } from 'vue';\nimport { TableCheckBoxAsyncI18n } from '@/components/TableComponent/TableCheckBoxAsync/type';\n\ninterface Props {\n value?: any[];\n detail: TableSelectorProp;\n i18Text?: TableCheckBoxAsyncI18n;\n rowData?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => [],\n i18Text: () => ({\n save: '保存',\n cancel: '取消',\n close: '关闭',\n }),\n rowData: () => ({}),\n});\n\nconst emits = defineEmits(['update:value', 'valueChange', 'setShow']);\n\nconst valueRef = defineModel('value', {\n type: Array as PropType<any[]>,\n default: () => [],\n});\n\nconst state = reactive({\n dialogVisible: false,\n showText: '',\n});\n\nconst checkData = ref<any[]>([]);\n\nconst change = () => {\n valueRef.value = checkData.value;\n emits('valueChange', props.detail.field, checkData.value, props.rowData);\n state.dialogVisible = false;\n setShowText(checkData.value);\n};\n\nconst textCache: any = {};\n\nconst setShowText = (componentData: any[]) => {\n if (Array.isArray(props.detail?.editRender?.props?.options)) {\n props.detail.editRender.props.options.forEach((item) => {\n textCache[item.value] = item.label;\n });\n }\n let text = '';\n for (const componentDatum of componentData) {\n text = `${text} ${\n textCache[componentDatum] === undefined\n ? componentDatum\n : textCache[componentDatum]\n }`;\n }\n state.showText = text;\n};\n\nconst openDialog = () => {\n state.dialogVisible = true;\n checkData.value = valueRef.value;\n};\n</script>\n\n<template>\n <div class=\"table-check-box-async\">\n <span class=\"text\" @click.stop=\"openDialog\">\n {{ state.showText ? state.showText : '空' }}\n </span>\n <el-dialog\n v-model=\"state.dialogVisible\"\n :show-close=\"false\"\n append-to-body\n center\n >\n <template #header>\n <div class=\"dialog-header\">\n <div>\n <el-button size=\"small\" type=\"primary\" @click=\"change\">\n {{ i18Text.save }}\n </el-button>\n <el-button size=\"small\" @click=\"state.dialogVisible = false\">\n {{ i18Text.cancel }}\n </el-button>\n </div>\n <el-button\n size=\"small\"\n type=\"danger\"\n @click=\"state.dialogVisible = false\"\n >\n {{ i18Text.close }}\n </el-button>\n </div>\n </template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in detail?.editRender?.props?.options\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n </el-dialog>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.table-check-box-async {\n width: 100%;\n\n .text {\n cursor: pointer;\n }\n}\n\n.dialog-header {\n display: flex;\n flex-direction: row;\n gap: 16px;\n justify-content: space-between;\n}\n</style>\n","import TableCheckBoxAsync from './TableCheckBoxAsync.vue';\nimport type { App } from 'vue';\n\n(TableCheckBoxAsync as any).name = 'TableCheckBoxAsync';\n\nTableCheckBoxAsync.install = (app: App) => {\n app.component('TableCheckBoxAsync', TableCheckBoxAsync);\n};\n\nexport { TableCheckBoxAsync };\n","import type { VxeGridListeners } from 'vxe-table';\n\nimport type { Ref } from 'vue';\n\nimport { msgTips } from '@/utils';\n\ninterface Props {\n xGrid: Ref;\n fieldValueChanged: Function;\n}\n\ninterface Paste {\n col: number;\n row: number;\n field: string;\n oldValue: any;\n newValue: any;\n rowData: any;\n rowId: string;\n}\n\nexport const useVxeGrid = (props: Props) => {\n const { xGrid, fieldValueChanged } = props;\n /**\n * 导出数据\n */\n const exportData = () => {\n xGrid.value.openExport();\n };\n\n /**\n * 自定义列\n */\n const openCustomColumn = () => {\n xGrid.value.openCustom();\n };\n\n const vxeClipboard = {\n rowSelectColumn: 'seq',\n onCopy: (e: any) => {\n msgTips.tips({\n msg: '复制成功!',\n type: 'success',\n });\n },\n onPaste: (e: Paste[]) => {\n e.forEach((item: Paste) => {\n if (item.oldValue !== item.newValue) {\n fieldValueChanged(item.field, item.newValue, item.rowData);\n }\n });\n },\n onCut: (e: any) => {\n console.log('cut', e);\n },\n onSelectionChange: (e: any) => {\n console.log('selectionChange', e);\n },\n };\n\n const gridEvents: VxeGridListeners<any> = {\n // ready() {\n // console.log('ready 表格准备就绪');\n // },\n // dataChange({ visibleData, visibleColumn, $event }) {\n // console.log('data-change 数据列表发生改变', visibleData, visibleColumn);\n // },\n // initRendered() {\n // console.log('init-rendered 数据列表被赋值并首次渲染完成');\n // },\n // dataRendered() {\n // console.log('data-rendered 数据列表被赋值并渲染完成');\n // },\n };\n\n return { exportData, openCustomColumn, vxeClipboard, gridEvents };\n};\n","<script setup lang=\"ts\">\nimport type { VxeGridProps } from 'vxe-table';\n\nimport type { PropType } from 'vue';\n\nimport type { KeButton, TableConfigInterface, TableQueryFrame, Pagination } from '@/types';\n\nimport { computed, ref, resolveComponent } from 'vue';\n\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\nimport { ToolBar } from '@/components/ToolBar';\nimport { useButtonExec } from '@/hooks/useButtonExec.hook';\n\nimport { useVxeGrid } from './hooks/useVxeGrid.hook';\n\nimport { QueryBar } from '@/components/QueryComponent/QueryBar'\n\ndefineOptions({\n name: 'TableRender',\n});\n\nconst VxeGrid = resolveComponent('VxeGrid') as any;\n\nconst props = withDefaults(\n defineProps<{\n columns: any[];\n queryConfig?: TableQueryFrame[];\n tableConfig: TableConfigInterface;\n tableData?: any[];\n tableId: number | string;\n tablePagination?: Pagination;\n tableRowButtons?: KeButton[];\n tableToolButtons?: KeButton[];\n vxeGridOptions?: VxeGridProps;\n }>(),\n {\n vxeGridOptions: undefined,\n queryConfig: () => [],\n tableToolButtons: () => [],\n tableRowButtons: () => [],\n tableData: () => [],\n tablePagination: () => ({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n }),\n },\n);\n\nconst emits = defineEmits([\n // 获取表格配置\n 'getTableConfig',\n 'btnClick', // 按钮\n 'queryClick', // 查询按钮点击事件\n 'valueChange', // 当某个单元格发生数据变化时\n 'treeLazyLoad', // 懒加载事件\n 'onSelection', // 当选择项发生变化时会触发该事件\n]);\n\n// 获取vxeTable表格节点\nconst xGrid = ref();\n\nconst pagination = defineModel('tablePagination', {\n required: false,\n type: Object as PropType<Pagination>,\n default: () => {\n return {\n currentPage: 1,\n /**\n * 页面大小\n */\n pageSize: 0,\n /**\n * 总数\n */\n total: 0,\n };\n },\n});\n\n/**\n * 字段值改动通知\n * @param fieldName 字段名\n * @param newValue 改动后的值\n * @param rowData\n */\nconst fieldValueChanged = (fieldName: string, newValue: any, rowData: any) => {\n emits('valueChange', fieldName, newValue, rowData[props.tableConfig?.rowKey]);\n};\n\nconst { exportData, openCustomColumn, vxeClipboard, gridEvents } =\n useVxeGrid({ xGrid, fieldValueChanged });\n\n/**\n * frame\n */\nconst tableColumns = computed(() => {\n if (\n props.tableRowButtons.length > 0 &&\n props.columns.length > 0 &&\n props.columns[props.columns.length - 1].field !== 'tableButtonOperate'\n ) {\n const newColumns = [...props.columns];\n newColumns.push({\n field: 'tableButtonOperate',\n title: '操作',\n width: props.tableRowButtons.length * 50 + 40,\n fixed: 'right',\n slots: {\n default: 'tableButtonOperate',\n },\n });\n return newColumns;\n }\n return props.columns;\n});\n\nconst vxeGridContainerRef = ref();\nconst debouncedHeight = ref(0);\nuseResizeObserver(\n vxeGridContainerRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedHeight.value = entry.contentRect.height;\n }\n }, 200),\n);\n\nlet queryData = {};\n\n/**\n * 列表按钮\n *\n * @param data\n * @param button\n * @param rowIndex\n */\nconst btnClick = (data: any, button: any, rowIndex: number) => {\n useButtonExec(data, button, rowIndex);\n};\n\nconst queryClick = (data: any) => {\n queryData = data;\n emits('queryClick', queryData);\n};\n\n/**\n * 翻页\n */\nconst paginationChange = () => {\n emits('queryClick', queryData);\n};\n</script>\n\n<template>\n <div class=\"ke-table-render-client\">\n <QueryBar\n v-if=\"queryConfig && queryConfig.length > 0\"\n :frame=\"queryConfig\"\n class=\"ke-query-bar-client\"\n @query-click=\"queryClick\"\n />\n <div\n v-if=\"tableToolButtons && tableToolButtons.length > 0\"\n class=\"ke-table-tool-button\"\n >\n <ToolBar :tool-buttons=\"tableToolButtons\">\n <template #custom-button>\n <slot name=\"tool-bar\"></slot>\n <ElButtonPlus @click=\"exportData\" icon=\"mingcute:download-line\" />\n <ElButtonPlus @click=\"openCustomColumn\" icon=\"lets-icons:setting-line\" />\n </template>\n </ToolBar>\n </div>\n <div ref=\"vxeGridContainerRef\" class=\"ke-vxe-grid-container\">\n <VxeGrid\n ref=\"xGrid\"\n v-clipboard=\"vxeClipboard\"\n v-on=\"gridEvents\"\n v-bind=\"{\n ...vxeGridOptions,\n showOverflow: 'title',\n columns: tableColumns,\n id: tableConfig.rowKey,\n rowConfig: {\n keyField: tableConfig?.rowKey,\n },\n seqConfig: {\n startIndex: tablePagination\n ? (tablePagination.currentPage - 1) * tablePagination.pageSize\n : 1,\n },\n data: tableData,\n height: debouncedHeight,\n }\"\n >\n <!-- 普通编辑器-->\n <template #renderCell=\"{ row, column }\">\n <component\n :is=\"column.editRender.name\"\n v-model:value=\"row[column.field]\"\n :detail=\"column\"\n :disabled=\"column.disabled !== false\"\n :row-data=\"row\"\n @value-change=\"fieldValueChanged\"\n />\n </template>\n <!-- 异步编辑器-->\n <template #renderAsyncCell=\"{ row, column }\">\n <component\n :is=\"column.editRender.name\"\n v-model:value=\"row[column.field]\"\n :detail=\"column\"\n :disabled=\"column.disabled !== false\"\n :row-data=\"row\"\n @value-change=\"fieldValueChanged\"\n />\n <!-- getTableColumnDetailData(column.editRender.props)-->\n </template>\n <!-- 操作列-->\n <template #tableButtonOperate=\"{ row, rowIndex }\">\n <ElButtonPlus\n v-for=\"btn in tableRowButtons\"\n :key=\"btn.id\"\n :class=\"btn.buttonClass\"\n :style=\"btn.buttonStyle\"\n :label=\"btn.label\"\n :icon=\"btn.icon\"\n :type=\"btn.type\"\n size=\"small\"\n @click.stop=\"btnClick(row, btn, rowIndex)\"\n />\n </template>\n </VxeGrid>\n </div>\n <div v-if=\"!tableConfig.tree && tablePagination\" class=\"ke-pagination-div\">\n <el-pagination\n v-model:current-page=\"pagination.currentPage\"\n v-model:page-size=\"pagination.pageSize\"\n :total=\"tablePagination.total\"\n background\n :layout=\"\n pagination.pageSize > 0 ? 'total, prev, pager, next, jumper' : 'total'\n \"\n size=\"small\"\n @current-change=\"paginationChange\"\n />\n </div>\n </div>\n</template>\n\n<style lang=\"scss\">\n.ke-table-render-client {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n background: var(--overlay-content);\n}\n.ke-query-bar-client {\n margin-top: 6px;\n}\n.ke-table-tool-button {\n margin: 6px 2px;\n}\n\n.ke-query-bar-client,\n.ke-table-tool-button,\n.ke-pagination-div {\n flex-shrink: 0;\n}\n\n.ke-vxe-grid-container {\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n overflow: hidden; /* 防止内容溢出 */\n}\n\n.ke-vxe-grid-container .vxe-grid {\n height: 100%; /* 让 VxeGrid 占满容器高度 */\n overflow: auto; /* 让 VxeGrid 内容滚动 */\n}\n\n.ke-pagination-div {\n padding: 6px;\n margin-top: 10px; /* 可选:分页与表格之间的间距 */\n border-radius: 4px;\n background: var(--el-fill-color-blank);\n}\n\n.vxe-grid {\n //禁用浏览器默认选中\n -webkit-user-select: none;\n /* Safari */\n -moz-user-select: none;\n /* Firefox */\n -ms-user-select: none;\n /* Internet Explorer/Edge */\n user-select: none;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { VxeGridProps } from 'vxe-table';\n\nimport type { PropType } from 'vue';\n\nimport type { KeButton, TableConfigInterface, TableQueryFrame, Pagination } from '@/types';\n\nimport { computed, ref, resolveComponent } from 'vue';\n\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\nimport { ToolBar } from '@/components/ToolBar';\nimport { useButtonExec } from '@/hooks/useButtonExec.hook';\n\nimport { useVxeGrid } from './hooks/useVxeGrid.hook';\n\nimport { QueryBar } from '@/components/QueryComponent/QueryBar'\n\ndefineOptions({\n name: 'TableRender',\n});\n\nconst VxeGrid = resolveComponent('VxeGrid') as any;\n\nconst props = withDefaults(\n defineProps<{\n columns: any[];\n queryConfig?: TableQueryFrame[];\n tableConfig: TableConfigInterface;\n tableData?: any[];\n tableId: number | string;\n tablePagination?: Pagination;\n tableRowButtons?: KeButton[];\n tableToolButtons?: KeButton[];\n vxeGridOptions?: VxeGridProps;\n }>(),\n {\n vxeGridOptions: undefined,\n queryConfig: () => [],\n tableToolButtons: () => [],\n tableRowButtons: () => [],\n tableData: () => [],\n tablePagination: () => ({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n }),\n },\n);\n\nconst emits = defineEmits([\n // 获取表格配置\n 'getTableConfig',\n 'btnClick', // 按钮\n 'queryClick', // 查询按钮点击事件\n 'valueChange', // 当某个单元格发生数据变化时\n 'treeLazyLoad', // 懒加载事件\n 'onSelection', // 当选择项发生变化时会触发该事件\n]);\n\n// 获取vxeTable表格节点\nconst xGrid = ref();\n\nconst pagination = defineModel('tablePagination', {\n required: false,\n type: Object as PropType<Pagination>,\n default: () => {\n return {\n currentPage: 1,\n /**\n * 页面大小\n */\n pageSize: 0,\n /**\n * 总数\n */\n total: 0,\n };\n },\n});\n\n/**\n * 字段值改动通知\n * @param fieldName 字段名\n * @param newValue 改动后的值\n * @param rowData\n */\nconst fieldValueChanged = (fieldName: string, newValue: any, rowData: any) => {\n emits('valueChange', fieldName, newValue, rowData[props.tableConfig?.rowKey]);\n};\n\nconst { exportData, openCustomColumn, vxeClipboard, gridEvents } =\n useVxeGrid({ xGrid, fieldValueChanged });\n\n/**\n * frame\n */\nconst tableColumns = computed(() => {\n if (\n props.tableRowButtons.length > 0 &&\n props.columns.length > 0 &&\n props.columns[props.columns.length - 1].field !== 'tableButtonOperate'\n ) {\n const newColumns = [...props.columns];\n newColumns.push({\n field: 'tableButtonOperate',\n title: '操作',\n width: props.tableRowButtons.length * 50 + 40,\n fixed: 'right',\n slots: {\n default: 'tableButtonOperate',\n },\n });\n return newColumns;\n }\n return props.columns;\n});\n\nconst vxeGridContainerRef = ref();\nconst debouncedHeight = ref(0);\nuseResizeObserver(\n vxeGridContainerRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedHeight.value = entry.contentRect.height;\n }\n }, 200),\n);\n\nlet queryData = {};\n\n/**\n * 列表按钮\n *\n * @param data\n * @param button\n * @param rowIndex\n */\nconst btnClick = (data: any, button: any, rowIndex: number) => {\n useButtonExec(data, button, rowIndex);\n};\n\nconst queryClick = (data: any) => {\n queryData = data;\n emits('queryClick', queryData);\n};\n\n/**\n * 翻页\n */\nconst paginationChange = () => {\n emits('queryClick', queryData);\n};\n</script>\n\n<template>\n <div class=\"ke-table-render-client\">\n <QueryBar\n v-if=\"queryConfig && queryConfig.length > 0\"\n :frame=\"queryConfig\"\n class=\"ke-query-bar-client\"\n @query-click=\"queryClick\"\n />\n <div\n v-if=\"tableToolButtons && tableToolButtons.length > 0\"\n class=\"ke-table-tool-button\"\n >\n <ToolBar :tool-buttons=\"tableToolButtons\">\n <template #custom-button>\n <slot name=\"tool-bar\"></slot>\n <ElButtonPlus @click=\"exportData\" icon=\"mingcute:download-line\" />\n <ElButtonPlus @click=\"openCustomColumn\" icon=\"lets-icons:setting-line\" />\n </template>\n </ToolBar>\n </div>\n <div ref=\"vxeGridContainerRef\" class=\"ke-vxe-grid-container\">\n <VxeGrid\n ref=\"xGrid\"\n v-clipboard=\"vxeClipboard\"\n v-on=\"gridEvents\"\n v-bind=\"{\n ...vxeGridOptions,\n showOverflow: 'title',\n columns: tableColumns,\n id: tableConfig.rowKey,\n rowConfig: {\n keyField: tableConfig?.rowKey,\n },\n seqConfig: {\n startIndex: tablePagination\n ? (tablePagination.currentPage - 1) * tablePagination.pageSize\n : 1,\n },\n data: tableData,\n height: debouncedHeight,\n }\"\n >\n <!-- 普通编辑器-->\n <template #renderCell=\"{ row, column }\">\n <component\n :is=\"column.editRender.name\"\n v-model:value=\"row[column.field]\"\n :detail=\"column\"\n :disabled=\"column.disabled !== false\"\n :row-data=\"row\"\n @value-change=\"fieldValueChanged\"\n />\n </template>\n <!-- 异步编辑器-->\n <template #renderAsyncCell=\"{ row, column }\">\n <component\n :is=\"column.editRender.name\"\n v-model:value=\"row[column.field]\"\n :detail=\"column\"\n :disabled=\"column.disabled !== false\"\n :row-data=\"row\"\n @value-change=\"fieldValueChanged\"\n />\n <!-- getTableColumnDetailData(column.editRender.props)-->\n </template>\n <!-- 操作列-->\n <template #tableButtonOperate=\"{ row, rowIndex }\">\n <ElButtonPlus\n v-for=\"btn in tableRowButtons\"\n :key=\"btn.id\"\n :class=\"btn.buttonClass\"\n :style=\"btn.buttonStyle\"\n :label=\"btn.label\"\n :icon=\"btn.icon\"\n :type=\"btn.type\"\n size=\"small\"\n @click.stop=\"btnClick(row, btn, rowIndex)\"\n />\n </template>\n </VxeGrid>\n </div>\n <div v-if=\"!tableConfig.tree && tablePagination\" class=\"ke-pagination-div\">\n <el-pagination\n v-model:current-page=\"pagination.currentPage\"\n v-model:page-size=\"pagination.pageSize\"\n :total=\"tablePagination.total\"\n background\n :layout=\"\n pagination.pageSize > 0 ? 'total, prev, pager, next, jumper' : 'total'\n \"\n size=\"small\"\n @current-change=\"paginationChange\"\n />\n </div>\n </div>\n</template>\n\n<style lang=\"scss\">\n.ke-table-render-client {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n background: var(--overlay-content);\n}\n.ke-query-bar-client {\n margin-top: 6px;\n}\n.ke-table-tool-button {\n margin: 6px 2px;\n}\n\n.ke-query-bar-client,\n.ke-table-tool-button,\n.ke-pagination-div {\n flex-shrink: 0;\n}\n\n.ke-vxe-grid-container {\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n overflow: hidden; /* 防止内容溢出 */\n}\n\n.ke-vxe-grid-container .vxe-grid {\n height: 100%; /* 让 VxeGrid 占满容器高度 */\n overflow: auto; /* 让 VxeGrid 内容滚动 */\n}\n\n.ke-pagination-div {\n padding: 6px;\n margin-top: 10px; /* 可选:分页与表格之间的间距 */\n border-radius: 4px;\n background: var(--el-fill-color-blank);\n}\n\n.vxe-grid {\n //禁用浏览器默认选中\n -webkit-user-select: none;\n /* Safari */\n -moz-user-select: none;\n /* Firefox */\n -ms-user-select: none;\n /* Internet Explorer/Edge */\n user-select: none;\n}\n</style>\n","import TableRender from './TableRender.vue';\nimport type { App } from 'vue';\n\n(TableRender as any).name = 'TableRender';\n\nTableRender.install = (app: App) => {\n app.component('TableRender', TableRender);\n};\n\nexport { TableRender };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type {\n KeButton,\n Pagination,\n TableConfigInterface,\n TableQueryFrame,\n} from '@/types';\n\nimport { ref } from 'vue';\n\nimport { More } from '@element-plus/icons-vue';\n\nimport { useButtonExec } from '@/hooks/useButtonExec.hook';\nimport { isNotEmpty } from '@/utils';\n\nimport { customFormatter } from '@/utils';\n\ninterface Props {\n tableId: number | string;\n tableConfig: TableConfigInterface;\n vxeGridOptions?: any;\n columns: any[];\n queryConfig?: TableQueryFrame[];\n tableToolButtons?: KeButton[];\n tableRowButtons?: KeButton[];\n tableData: any[];\n tablePagination?: Pagination;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n vxeGridOptions: undefined,\n queryConfig: () => [],\n tableToolButtons: () => [],\n tableRowButtons: () => [],\n tableData: () => [],\n tablePagination: () => ({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n }),\n});\n\nconst emits = defineEmits([\n 'btnClick', // 按钮\n 'queryClick', // 查询按钮点击事件\n 'valueChange', // 当某个单元格发生数据变化时\n 'treeLazyLoad', // 懒加载事件\n 'onSelection', // 当选择项发生变化时会触发该事件\n]);\n\nconst pagination = defineModel('tablePagination', {\n required: true,\n type: Object as PropType<Pagination>,\n});\n\n/**\n * 查询内容\n */\nconst queryData = {};\n\n/**\n * 查询\n * @param data\n */\nconst queryClick = (data: any) => {\n emits('queryClick', data);\n};\n\nlet titleField = '';\n/**\n * 获取标题\n * @param cardItem\n */\nconst getTitle = (cardItem: any) => {\n if (props.tableConfig.titleField) {\n return cardItem[props.tableConfig.titleField];\n } else if (isNotEmpty(titleField)) {\n return cardItem[titleField];\n }\n\n for (const key in cardItem) {\n if (typeof cardItem[key] === 'string' && isNotEmpty(cardItem[key])) {\n titleField = key;\n return cardItem[key];\n }\n }\n return '';\n};\n\nconst queryBarRef = ref();\n\n/**\n * 按钮事件\n *\n * @param data\n * @param button\n */\nconst btnClick = (data: any, button: any) => {\n useButtonExec(data, button);\n};\n\n/**\n * 已循环过的格式化对象\n */\nconst translateObject = {};\n/**\n * 循环到的索引\n */\nconst translateIndexArray: any[] = [];\n/**\n * 格式化方法\n */\nconst formatterCellValue = (value: any, cell: any) => {\n return customFormatter({\n cellValue: value,\n tabObj: cell.tabObj,\n translateJson: cell.translate,\n fieldName: cell.field,\n translateObject,\n translateIndexArray,\n });\n};\n\n/**\n * 字段值改动通知\n * @param fieldName 字段名\n * @param newValue 改动后的值\n * @param rowId\n */\nconst fieldValueChanged = (\n fieldName: string,\n newValue: any,\n rowId: number | string,\n) => {\n emits('valueChange', fieldName, newValue, rowId);\n};\n\n/**\n * 翻页\n */\nconst paginationChange = () => {\n emits('queryClick', queryData);\n};\n</script>\n\n<template>\n <div class=\"table-card-render-client\">\n <KeQueryBar\n v-if=\"queryConfig && queryConfig.length > 0\"\n ref=\"queryBarRef\"\n :frame=\"queryConfig\"\n @query-click=\"queryClick\"\n />\n <div v-if=\"tableToolButtons.length > 0\" class=\"table-tool-button\">\n <KeToolBar :tool-buttons=\"tableToolButtons\" />\n </div>\n <div class=\"card-container\">\n <el-scrollbar>\n <el-row :gutter=\"12\">\n <el-col\n v-for=\"cardItem in tableData\"\n :key=\"cardItem[tableConfig.rowKey]\"\n :lg=\"8\"\n :md=\"8\"\n :sm=\"12\"\n :xl=\"6\"\n :xs=\"24\"\n style=\"margin-top: 6px; margin-bottom: 6px\"\n >\n <el-card>\n <template v-if=\"tableConfig.coverField\">\n <!-- 封面图片-->\n <img :src=\"cardItem[tableConfig.coverField]\" alt=\"\" />\n </template>\n <h1 class=\"title-wrapper\">\n <span class=\"title-text\">{{ getTitle(cardItem) }}</span>\n <el-dropdown\n v-if=\"\n Array.isArray(tableRowButtons) && tableRowButtons.length > 0\n \"\n class=\"dropdown-wrapper\"\n >\n <el-button :icon=\"More\" text />\n <template #dropdown>\n <el-dropdown-menu>\n <el-dropdown-item\n v-for=\"btn in tableRowButtons\"\n :key=\"btn.id\"\n @click=\"btnClick(cardItem, btn)\"\n >\n <template #default>\n <span\n :style=\"{ color: `var(--el-color-${btn.type})` }\"\n >\n {{ btn.label }}\n </span>\n </template>\n </el-dropdown-item>\n </el-dropdown-menu>\n </template>\n </el-dropdown>\n </h1>\n <template v-for=\"cardCol in columns\" :key=\"cardCol.field\">\n <el-form-item\n v-if=\"cardCol.field !== tableConfig.coverField\"\n :label=\"cardCol.title\"\n >\n <template v-if=\"cardCol.cellRender || cardCol.editRender\">\n <!-- {{ dataFormatter({ })}}-->\n <component\n :is=\"cardCol.editRender.name\"\n v-model:value=\"cardItem[cardCol.field]\"\n :detail=\"cardCol\"\n :disabled=\"cardCol.editRender.enabled\"\n :row-data=\"cardItem\"\n @value-change=\"fieldValueChanged\"\n />\n </template>\n <template v-else>\n {{ formatterCellValue(cardItem[cardCol.field], cardCol) }}\n </template>\n </el-form-item>\n </template>\n </el-card>\n </el-col>\n </el-row>\n </el-scrollbar>\n </div>\n <div class=\"pagination-div\">\n <el-pagination\n v-model:current-page=\"pagination.currentPage\"\n v-model:page-size=\"pagination.pageSize\"\n :total=\"tablePagination.total\"\n background\n layout=\"total, prev, pager, next, jumper\"\n size=\"small\"\n @current-change=\"paginationChange\"\n />\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n/**\n禁用横向滚动条\n */\n:deep(.el-scrollbar__wrap) {\n overflow-x: hidden !important;\n}\n\n:deep(.el-scrollbar__bar.is-horizontal) {\n height: 0 !important;\n}\n\n:deep(.el-form-item) {\n margin-bottom: 0 !important;\n}\n\n.table-card-render-client {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n}\n\n.title-wrapper {\n display: flex;\n align-items: center;\n justify-content: space-between; /* 确保内容与按钮分布在两端 */\n\n .title-text {\n flex: 1; /* 确保文字部分可以占满剩余空间 */\n }\n\n .dropdown-wrapper {\n margin-left: auto; /* 确保按钮总是靠右对齐 */\n }\n}\n\n.table-tool-button {\n margin-top: 6px; /* 可选:给工具条加一些顶部间距 */\n}\n\n.card-container {\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n overflow: hidden; /* 防止内容溢出 */\n}\n\n.pagination-div {\n padding: 6px;\n margin-top: 10px; /* 可选:分页与表格之间的间距 */\n background: var(--el-fill-color-blank);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type {\n KeButton,\n Pagination,\n TableConfigInterface,\n TableQueryFrame,\n} from '@/types';\n\nimport { ref } from 'vue';\n\nimport { More } from '@element-plus/icons-vue';\n\nimport { useButtonExec } from '@/hooks/useButtonExec.hook';\nimport { isNotEmpty } from '@/utils';\n\nimport { customFormatter } from '@/utils';\n\ninterface Props {\n tableId: number | string;\n tableConfig: TableConfigInterface;\n vxeGridOptions?: any;\n columns: any[];\n queryConfig?: TableQueryFrame[];\n tableToolButtons?: KeButton[];\n tableRowButtons?: KeButton[];\n tableData: any[];\n tablePagination?: Pagination;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n vxeGridOptions: undefined,\n queryConfig: () => [],\n tableToolButtons: () => [],\n tableRowButtons: () => [],\n tableData: () => [],\n tablePagination: () => ({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n }),\n});\n\nconst emits = defineEmits([\n 'btnClick', // 按钮\n 'queryClick', // 查询按钮点击事件\n 'valueChange', // 当某个单元格发生数据变化时\n 'treeLazyLoad', // 懒加载事件\n 'onSelection', // 当选择项发生变化时会触发该事件\n]);\n\nconst pagination = defineModel('tablePagination', {\n required: true,\n type: Object as PropType<Pagination>,\n});\n\n/**\n * 查询内容\n */\nconst queryData = {};\n\n/**\n * 查询\n * @param data\n */\nconst queryClick = (data: any) => {\n emits('queryClick', data);\n};\n\nlet titleField = '';\n/**\n * 获取标题\n * @param cardItem\n */\nconst getTitle = (cardItem: any) => {\n if (props.tableConfig.titleField) {\n return cardItem[props.tableConfig.titleField];\n } else if (isNotEmpty(titleField)) {\n return cardItem[titleField];\n }\n\n for (const key in cardItem) {\n if (typeof cardItem[key] === 'string' && isNotEmpty(cardItem[key])) {\n titleField = key;\n return cardItem[key];\n }\n }\n return '';\n};\n\nconst queryBarRef = ref();\n\n/**\n * 按钮事件\n *\n * @param data\n * @param button\n */\nconst btnClick = (data: any, button: any) => {\n useButtonExec(data, button);\n};\n\n/**\n * 已循环过的格式化对象\n */\nconst translateObject = {};\n/**\n * 循环到的索引\n */\nconst translateIndexArray: any[] = [];\n/**\n * 格式化方法\n */\nconst formatterCellValue = (value: any, cell: any) => {\n return customFormatter({\n cellValue: value,\n tabObj: cell.tabObj,\n translateJson: cell.translate,\n fieldName: cell.field,\n translateObject,\n translateIndexArray,\n });\n};\n\n/**\n * 字段值改动通知\n * @param fieldName 字段名\n * @param newValue 改动后的值\n * @param rowId\n */\nconst fieldValueChanged = (\n fieldName: string,\n newValue: any,\n rowId: number | string,\n) => {\n emits('valueChange', fieldName, newValue, rowId);\n};\n\n/**\n * 翻页\n */\nconst paginationChange = () => {\n emits('queryClick', queryData);\n};\n</script>\n\n<template>\n <div class=\"table-card-render-client\">\n <KeQueryBar\n v-if=\"queryConfig && queryConfig.length > 0\"\n ref=\"queryBarRef\"\n :frame=\"queryConfig\"\n @query-click=\"queryClick\"\n />\n <div v-if=\"tableToolButtons.length > 0\" class=\"table-tool-button\">\n <KeToolBar :tool-buttons=\"tableToolButtons\" />\n </div>\n <div class=\"card-container\">\n <el-scrollbar>\n <el-row :gutter=\"12\">\n <el-col\n v-for=\"cardItem in tableData\"\n :key=\"cardItem[tableConfig.rowKey]\"\n :lg=\"8\"\n :md=\"8\"\n :sm=\"12\"\n :xl=\"6\"\n :xs=\"24\"\n style=\"margin-top: 6px; margin-bottom: 6px\"\n >\n <el-card>\n <template v-if=\"tableConfig.coverField\">\n <!-- 封面图片-->\n <img :src=\"cardItem[tableConfig.coverField]\" alt=\"\" />\n </template>\n <h1 class=\"title-wrapper\">\n <span class=\"title-text\">{{ getTitle(cardItem) }}</span>\n <el-dropdown\n v-if=\"\n Array.isArray(tableRowButtons) && tableRowButtons.length > 0\n \"\n class=\"dropdown-wrapper\"\n >\n <el-button :icon=\"More\" text />\n <template #dropdown>\n <el-dropdown-menu>\n <el-dropdown-item\n v-for=\"btn in tableRowButtons\"\n :key=\"btn.id\"\n @click=\"btnClick(cardItem, btn)\"\n >\n <template #default>\n <span\n :style=\"{ color: `var(--el-color-${btn.type})` }\"\n >\n {{ btn.label }}\n </span>\n </template>\n </el-dropdown-item>\n </el-dropdown-menu>\n </template>\n </el-dropdown>\n </h1>\n <template v-for=\"cardCol in columns\" :key=\"cardCol.field\">\n <el-form-item\n v-if=\"cardCol.field !== tableConfig.coverField\"\n :label=\"cardCol.title\"\n >\n <template v-if=\"cardCol.cellRender || cardCol.editRender\">\n <!-- {{ dataFormatter({ })}}-->\n <component\n :is=\"cardCol.editRender.name\"\n v-model:value=\"cardItem[cardCol.field]\"\n :detail=\"cardCol\"\n :disabled=\"cardCol.editRender.enabled\"\n :row-data=\"cardItem\"\n @value-change=\"fieldValueChanged\"\n />\n </template>\n <template v-else>\n {{ formatterCellValue(cardItem[cardCol.field], cardCol) }}\n </template>\n </el-form-item>\n </template>\n </el-card>\n </el-col>\n </el-row>\n </el-scrollbar>\n </div>\n <div class=\"pagination-div\">\n <el-pagination\n v-model:current-page=\"pagination.currentPage\"\n v-model:page-size=\"pagination.pageSize\"\n :total=\"tablePagination.total\"\n background\n layout=\"total, prev, pager, next, jumper\"\n size=\"small\"\n @current-change=\"paginationChange\"\n />\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n/**\n禁用横向滚动条\n */\n:deep(.el-scrollbar__wrap) {\n overflow-x: hidden !important;\n}\n\n:deep(.el-scrollbar__bar.is-horizontal) {\n height: 0 !important;\n}\n\n:deep(.el-form-item) {\n margin-bottom: 0 !important;\n}\n\n.table-card-render-client {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n}\n\n.title-wrapper {\n display: flex;\n align-items: center;\n justify-content: space-between; /* 确保内容与按钮分布在两端 */\n\n .title-text {\n flex: 1; /* 确保文字部分可以占满剩余空间 */\n }\n\n .dropdown-wrapper {\n margin-left: auto; /* 确保按钮总是靠右对齐 */\n }\n}\n\n.table-tool-button {\n margin-top: 6px; /* 可选:给工具条加一些顶部间距 */\n}\n\n.card-container {\n flex-grow: 1; /* 填充剩余空间 */\n height: 0; /* 初始为 0,稍后通过 flex 计算 */\n overflow: hidden; /* 防止内容溢出 */\n}\n\n.pagination-div {\n padding: 6px;\n margin-top: 10px; /* 可选:分页与表格之间的间距 */\n background: var(--el-fill-color-blank);\n}\n</style>\n","import TableCardRender from './TableCardRender.vue';\nimport type { App } from 'vue';\n\n(TableCardRender as any).name = 'TableCardRender';\n\nTableCardRender.install = (app: App) => {\n app.component('TableCardRender', TableCardRender);\n};\n\nexport { TableCardRender };\n","import { emitter } from '@/utils';\n\nexport const useMittHook = (\n fieldName: string,\n mittId: null | number | string,\n) => {\n if (!mittId) {\n return {\n registerMitt: () => {},\n offMitt: () => {},\n }\n }\n /**\n * 注册mitt广播事件\n */\n const registerMitt = (func?: Function) => {\n if (mittId && emitter) {\n emitter.on(fieldName + mittId, (_eventData) => {\n if (func) {\n func(_eventData);\n }\n });\n }\n };\n\n /**\n * 关闭mitt订阅\n */\n const offMitt = () => {\n if (mittId && emitter) {\n emitter.off(fieldName + mittId);\n }\n };\n\n return { registerMitt, offMitt };\n};\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\nconst inputValue = defineModel('value');\n\n/** 值发生变化时 */\n// const change = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// inputValue,\n// );\n// }\n// };\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n inputValue.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input\n v-model=\"inputValue\"\n :placeholder=\"props.detail?.placeholder\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n >\n <template\n v-if=\"detail.componentParams && detail.componentParams.prepend\"\n #prepend\n >\n <span>{{ detail.componentParams.prepend }}</span>\n </template>\n <template\n v-if=\"detail.componentParams && detail.componentParams.append\"\n #append\n >\n <span>{{ detail.componentParams.append }}</span>\n </template>\n </el-input>\n</template>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\nconst inputValue = defineModel('value');\n\n/** 值发生变化时 */\n// const change = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// inputValue,\n// );\n// }\n// };\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n inputValue.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input\n v-model=\"inputValue\"\n :placeholder=\"props.detail?.placeholder\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n >\n <template\n v-if=\"detail.componentParams && detail.componentParams.prepend\"\n #prepend\n >\n <span>{{ detail.componentParams.prepend }}</span>\n </template>\n <template\n v-if=\"detail.componentParams && detail.componentParams.append\"\n #append\n >\n <span>{{ detail.componentParams.append }}</span>\n </template>\n </el-input>\n</template>\n","import FormInput from './FormInput.vue';\nimport type { App } from 'vue';\n\n(FormInput as any).name = 'FormInput';\n\nFormInput.install = (app: App) => {\n app.component('FormInput', FormInput);\n};\n\nexport { FormInput };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: null | number;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n mittId: () => null,\n});\n\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input-number\n v-model=\"valueRef\"\n :placeholder=\"detail.placeholder\"\n class=\"full\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n >\n <template\n v-if=\"detail.componentParams && detail.componentParams.prefix\"\n #prefix\n >\n <span>{{ detail.componentParams.prefix }}</span>\n </template>\n <template\n v-if=\"detail.componentParams && detail.componentParams.suffix\"\n #suffix\n >\n <span>{{ detail.componentParams.suffix }}</span>\n </template>\n </el-input-number>\n</template>\n\n<style scoped>\n.full {\n width: 100%;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: null | number;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n mittId: () => null,\n});\n\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input-number\n v-model=\"valueRef\"\n :placeholder=\"detail.placeholder\"\n class=\"full\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n >\n <template\n v-if=\"detail.componentParams && detail.componentParams.prefix\"\n #prefix\n >\n <span>{{ detail.componentParams.prefix }}</span>\n </template>\n <template\n v-if=\"detail.componentParams && detail.componentParams.suffix\"\n #suffix\n >\n <span>{{ detail.componentParams.suffix }}</span>\n </template>\n </el-input-number>\n</template>\n\n<style scoped>\n.full {\n width: 100%;\n}\n</style>\n","import FormInputNumber from './FormInputNumber.vue';\nimport type { App } from 'vue';\n\n(FormInputNumber as any).name = 'FormInputNumber';\n\nFormInputNumber.install = (app: App) => {\n app.component('FormInputNumber', FormInputNumber);\n};\n\nexport { FormInputNumber };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 值发生变化时 */\n// const change = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// inputValue,\n// );\n// }\n// };\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input\n v-model=\"valueRef\"\n :autosize=\"{ minRows: 2 }\"\n :placeholder=\"\n props.detail?.placeholder\n ? props.detail.placeholder\n : `请输入${props.detail?.title}`\n \"\n type=\"textarea\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n />\n</template>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 值发生变化时 */\n// const change = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// inputValue,\n// );\n// }\n// };\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-input\n v-model=\"valueRef\"\n :autosize=\"{ minRows: 2 }\"\n :placeholder=\"\n props.detail?.placeholder\n ? props.detail.placeholder\n : `请输入${props.detail?.title}`\n \"\n type=\"textarea\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n />\n</template>\n","import FormTextArea from './FormTextArea.vue';\nimport type { App } from 'vue';\n\n(FormTextArea as any).name = 'FormTextArea';\n\nFormTextArea.install = (app: App) => {\n app.component('FormTextArea', FormTextArea);\n};\n\nexport { FormTextArea };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst valueRef = defineModel('value');\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-text\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n >\n {{ valueRef }}\n </el-text>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst valueRef = defineModel('value');\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-text\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n >\n {{ valueRef }}\n </el-text>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import FormText from './FormText.vue';\nimport type { App } from 'vue';\n\n(FormText as any).name = 'FormText';\n\nFormText.install = (app: App) => {\n app.component('FormText', FormText);\n};\n\nexport { FormText };\n","<script setup lang=\"ts\">\nimport type { FormSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits(['update:value', 'getComponentValue', 'valueChange']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 如果是多选 value位数组类型时, value就不能为null\n */\nconst multipleClear = async () => {\n await sleep(0.1);\n if (\n (props.detail.multiple || props.detail.componentParams?.mode === 'tags') &&\n valueRef.value === null\n ) {\n valueRef.value = [];\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n multipleClear();\n});\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.multiple\"\n :placeholder=\"detail.placeholder\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n clearable\n >\n <el-option\n v-for=\"item in props.detail?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits(['update:value', 'getComponentValue', 'valueChange']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 如果是多选 value位数组类型时, value就不能为null\n */\nconst multipleClear = async () => {\n await sleep(0.1);\n if (\n (props.detail.multiple || props.detail.componentParams?.mode === 'tags') &&\n valueRef.value === null\n ) {\n valueRef.value = [];\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n multipleClear();\n});\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"detail?.multiple\"\n :placeholder=\"detail.placeholder\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n clearable\n >\n <el-option\n v-for=\"item in props.detail?.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","import FormSelect from './FormSelect.vue';\nimport type { App } from 'vue';\n\n(FormSelect as any).name = 'FormSelect';\n\nFormSelect.install = (app: App) => {\n app.component('FormSelect', FormSelect);\n};\n\nexport { FormSelect };\n","import type { Ref } from 'vue';\n\nimport type { FormSelectAsyncProp, OptionInterface } from '@/types';\n\nimport { ref } from 'vue';\n\nimport { isEmpty, msgTips, sleep } from '@/utils';\n\ninterface Props {\n detail: FormSelectAsyncProp;\n fieldTitle: string;\n mittId?: number | string;\n}\n\n// 2. SelectAsync 接口绑定\ninterface SelectAsync<EE extends (...args: any) => void> {\n emits: EE;\n props: Readonly<Props>;\n valueRef: Ref;\n}\n\nexport const useSelectAsync = <EE extends (...args: any) => void>(\n params: SelectAsync<EE>,\n) => {\n const { emits, props } = params;\n\n const loading = ref<boolean>(false);\n let load = false;\n let isLoadFail = false;\n let oldComponentValueMap: any = {};\n\n // 选项\n const optionsData = ref<any[] | OptionInterface[]>([]);\n\n const init = async () => {\n await sleep(0.05 + Math.floor(Math.random() * 300) / 100);\n await getOptions();\n };\n\n /**\n * 验证获取的其他组件的参数是否有\n * @param params\n * @param fieldNames\n */\n const verifyHttpOtherParams = (params: any, fieldNames: string[]) => {\n let result = true;\n if (fieldNames.length > 0 && !params) {\n return false;\n }\n fieldNames.forEach((fieldName) => {\n if (params[fieldName] === undefined || params[fieldName] === null) {\n result = false;\n }\n });\n\n return result;\n };\n\n /** 远程获取 */\n const getOptions = async () => {\n if (loading.value) return;\n if (isEmpty(props.detail.optionHttpUrl)) return;\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n // 如果(已经加载 || 加载失败)且新获取的表单数据与旧数据一样,则不再重新请求\n if (\n (load || isLoadFail) &&\n JSON.stringify(componentValueMap) === JSON.stringify(oldComponentValueMap)\n )\n return;\n\n if (\n !verifyHttpOtherParams(\n componentValueMap,\n props.detail.optionHttpComponentValue,\n )\n ) {\n // 验证失败则不发http请求\n return;\n }\n\n loading.value = true;\n oldComponentValueMap = componentValueMap;\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (\n !['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)\n ) {\n opt.body = JSON.stringify({\n prop: props.detail.field,\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n load = true;\n optionsData.value = result.data;\n } else {\n msgTips.alert({\n msg: `${props.fieldTitle}数据获取失败!`,\n type: 'warning',\n });\n isLoadFail = true;\n }\n loading.value = false;\n };\n\n /** 当值发生变化时 */\n // const handleChange = async () => {\n // // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n // if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n // await nextTick();\n // emits(\n // 'valueChange',\n // props.detail?.noticeField,\n // props.detail?.field,\n // valueRef.value,\n // );\n // }\n // };\n\n return {\n getOptions,\n optionsData,\n loading,\n // handleChange,\n init,\n };\n};\n","<script setup lang=\"ts\">\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useSelectAsync } from '../hooks/selectAsync.hook';\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\n// 1. 定义 emits 类型(强类型)\nconst emits = defineEmits<{\n (event: 'update:value', value: any): void;\n (\n event: 'getComponentValue',\n componentValue: any,\n callback: (val: any) => void,\n ): void;\n (event: 'valueChange', value: any): void;\n (event: 'setShow', show: boolean): void;\n}>();\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst { loading, getOptions, optionsData, init } = useSelectAsync({\n emits,\n props,\n valueRef,\n});\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n init();\n registerMitt((_eventData: any) => {\n receiveBroadcasts(_eventData);\n getOptions();\n });\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"props.detail.multiple\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n :loading=\"loading\"\n :placeholder=\"props.detail?.placeholder\"\n v-loading=\"loading\"\n @focus=\"getOptions\"\n >\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useSelectAsync } from '../hooks/selectAsync.hook';\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\n// 1. 定义 emits 类型(强类型)\nconst emits = defineEmits<{\n (event: 'update:value', value: any): void;\n (\n event: 'getComponentValue',\n componentValue: any,\n callback: (val: any) => void,\n ): void;\n (event: 'valueChange', value: any): void;\n (event: 'setShow', show: boolean): void;\n}>();\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst { loading, getOptions, optionsData, init } = useSelectAsync({\n emits,\n props,\n valueRef,\n});\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n init();\n registerMitt((_eventData: any) => {\n receiveBroadcasts(_eventData);\n getOptions();\n });\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"props.detail.multiple\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n :loading=\"loading\"\n :placeholder=\"props.detail?.placeholder\"\n v-loading=\"loading\"\n @focus=\"getOptions\"\n >\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped></style>\n","import FormSelectAsync from './FormSelectAsync.vue';\nimport type { App } from 'vue';\n\n(FormSelectAsync as any).name = 'FormSelectAsync';\n\nFormSelectAsync.install = (app: App) => {\n app.component('FormSelectAsync', FormSelectAsync);\n};\n\nexport { FormSelectAsync };\n","<script setup lang=\"ts\">\nimport type { FormSelectAsyncProp, OptionInterface } from '@/types';\n\nimport { onMounted, onUnmounted, ref } from 'vue';\n\nimport { isEmpty } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst valueRef = defineModel('value');\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst optionsData = ref<OptionInterface[]>([]);\nconst loading = ref(false);\n\n/**\n * 远程搜索\n * @param queryStr\n */\nconst remoteMethod = async (queryStr: string) => {\n if (isEmpty(queryStr)) {\n return;\n }\n if (isEmpty(props.detail.optionHttpUrl)) return;\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n loading.value = true;\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (!['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n searchValue: queryStr,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n // 如果获取成功!\n optionsData.value = result.code === 0 ? result.data : [];\n loading.value = false;\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"props.detail.multiple\"\n filterable\n remote\n reserve-keyword\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n :loading=\"loading\"\n :placeholder=\"props.detail?.placeholder\"\n :remote-method=\"remoteMethod\"\n >\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport type { FormSelectAsyncProp, OptionInterface } from '@/types';\n\nimport { onMounted, onUnmounted, ref } from 'vue';\n\nimport { isEmpty } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst valueRef = defineModel('value');\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst optionsData = ref<OptionInterface[]>([]);\nconst loading = ref(false);\n\n/**\n * 远程搜索\n * @param queryStr\n */\nconst remoteMethod = async (queryStr: string) => {\n if (isEmpty(queryStr)) {\n return;\n }\n if (isEmpty(props.detail.optionHttpUrl)) return;\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n loading.value = true;\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (!['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n searchValue: queryStr,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n // 如果获取成功!\n optionsData.value = result.code === 0 ? result.data : [];\n loading.value = false;\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n :multiple=\"props.detail.multiple\"\n filterable\n remote\n reserve-keyword\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n :loading=\"loading\"\n :placeholder=\"props.detail?.placeholder\"\n :remote-method=\"remoteMethod\"\n >\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :label=\"item.label\"\n :value=\"item.value\"\n />\n </el-select>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import FormSelectRemote from './FormSelectRemote.vue';\nimport type { App } from 'vue';\n\n(FormSelectRemote as any).name = 'FormSelectRemote';\n\nFormSelectRemote.install = (app: App) => {\n app.component('FormSelectRemote', FormSelectRemote);\n};\n\nexport { FormSelectRemote };\n","<script setup lang=\"ts\">\nimport type { FormRadioProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormRadioProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\n\nconst valueRef = defineModel('value', {\n required: true,\n});\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-radio-group v-model=\"valueRef\">\n <el-radio\n v-for=\"item in detail.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :value=\"item.value\"\n >\n {{ item.label }}\n </el-radio>\n </el-radio-group>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport type { FormRadioProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormRadioProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\n\nconst valueRef = defineModel('value', {\n required: true,\n});\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-radio-group v-model=\"valueRef\">\n <el-radio\n v-for=\"item in detail.options\"\n :key=\"item.value\"\n :disabled=\"item.disabled === true\"\n :value=\"item.value\"\n >\n {{ item.label }}\n </el-radio>\n </el-radio-group>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import FormRadio from './FormRadio.vue';\nimport type { App } from 'vue';\n\n(FormRadio as any).name = 'FormRadio';\n\nFormRadio.install = (app: App) => {\n app.component('FormRadio', FormRadio);\n};\n\nexport { FormRadio };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst checkData = defineModel('value', {\n type: Array as PropType<any[]>,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n checkData.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in detail.options\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst checkData = defineModel('value', {\n type: Array as PropType<any[]>,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n checkData.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in detail.options\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n</template>\n\n<style scoped></style>\n","import FormCheckBox from './FormCheckBox.vue';\nimport type { App } from 'vue';\n\n(FormCheckBox as any).name = 'FormCheckBox';\n\nFormCheckBox.install = (app: App) => {\n app.component('FormCheckBox', FormCheckBox);\n};\n\nexport { FormCheckBox };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted, reactive } from 'vue';\n\nimport { isEmpty, msgTips } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectAsyncProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst checkData = defineModel('value', {\n type: Array as PropType<any[]>,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst options = reactive<any>({\n loading: false,\n load: false,\n data: [],\n});\n\nlet oldComponentValueMap: any = {};\nconst isLoadFail = false;\n/** 获取选项 */\nconst getOptions = async () => {\n // 如果url为空 则不进行加载\n if (isEmpty(props.detail?.optionHttpUrl)) return;\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n // 如果(已经加载 || 加载失败)且新获取的表单数据与旧数据一样,则不再重新请求\n if (\n (options.load || isLoadFail) &&\n JSON.stringify(componentValueMap) === JSON.stringify(oldComponentValueMap)\n )\n return;\n\n options.loading = true;\n oldComponentValueMap = componentValueMap;\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (!['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n prop: props.detail.field,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n options.load = true;\n options.data = result.data;\n } else {\n msgTips.tips({\n msg: `${result.msg}`,\n type: 'warning',\n });\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n checkData.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n getOptions();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in options.data\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted, reactive } from 'vue';\n\nimport { isEmpty, msgTips } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\nconst props = withDefaults(\n defineProps<{\n detail: FormSelectAsyncProp;\n mittId?: any;\n value?: any[] | null;\n }>(),\n {\n value: null,\n mittId: null,\n },\n);\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst checkData = defineModel('value', {\n type: Array as PropType<any[]>,\n});\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst options = reactive<any>({\n loading: false,\n load: false,\n data: [],\n});\n\nlet oldComponentValueMap: any = {};\nconst isLoadFail = false;\n/** 获取选项 */\nconst getOptions = async () => {\n // 如果url为空 则不进行加载\n if (isEmpty(props.detail?.optionHttpUrl)) return;\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n // 如果(已经加载 || 加载失败)且新获取的表单数据与旧数据一样,则不再重新请求\n if (\n (options.load || isLoadFail) &&\n JSON.stringify(componentValueMap) === JSON.stringify(oldComponentValueMap)\n )\n return;\n\n options.loading = true;\n oldComponentValueMap = componentValueMap;\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (!['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n prop: props.detail.field,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n options.load = true;\n options.data = result.data;\n } else {\n msgTips.tips({\n msg: `${result.msg}`,\n type: 'warning',\n });\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n checkData.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n getOptions();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-checkbox-group v-model=\"checkData\">\n <el-checkbox\n v-for=\"ops in options.data\"\n :key=\"ops.value\"\n :disabled=\"ops.disabled\"\n :label=\"ops.label\"\n :value=\"ops.value\"\n />\n </el-checkbox-group>\n</template>\n\n<style scoped></style>\n","import FormCheckBoxAsync from './FormCheckBoxAsync.vue';\nimport type { App } from 'vue';\n\n(FormCheckBoxAsync as any).name = 'FormCheckBoxAsync';\n\nFormCheckBoxAsync.install = (app: App) => {\n app.component('FormCheckBoxAsync', FormCheckBoxAsync);\n};\n\nexport { FormCheckBoxAsync };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value: boolean;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => false,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel<boolean>('value');\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst setDefaultValue = async () => {\n await sleep(0.1);\n if (!valueRef.value) {\n valueRef.value = false;\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: boolean) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n setDefaultValue();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-switch v-model=\"valueRef\" v-bind=\"detail.componentParams\" />\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value: boolean;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => false,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel<boolean>('value');\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst setDefaultValue = async () => {\n await sleep(0.1);\n if (!valueRef.value) {\n valueRef.value = false;\n }\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: boolean) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n setDefaultValue();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-switch v-model=\"valueRef\" v-bind=\"detail.componentParams\" />\n</template>\n\n<style scoped></style>\n","import FormSwitch from './FormSwitch.vue';\nimport type { App } from 'vue';\n\n(FormSwitch as any).name = 'FormSwitch';\n\nFormSwitch.install = (app: App) => {\n app.component('FormSwitch', FormSwitch);\n};\n\nexport { FormSwitch };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { getLunar } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'valueChange']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\nconst getShowText = (cell: any) => {\n if (cell.renderText) {\n return cell.renderText;\n }\n return cell.text;\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueRef\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n format=\"YYYY-MM-DD\"\n style=\"width: 100%\"\n value-format=\"YYYY-MM-DD\"\n >\n <template #default=\"cell\">\n <div class=\"dateCell\">\n <span class=\"solar_calendar\">\n {{ getShowText(cell) }}\n </span>\n <span class=\"lunar_calendar\">{{ getLunar(cell) }}</span>\n </div>\n </template>\n </el-date-picker>\n</template>\n\n<style scoped lang=\"scss\">\ntd.current .dateCell {\n color: #fff; /* 文本颜色变为白色 */\n background-color: var(--el-color-primary); /* 黄色背景,表示高亮 */\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\ntd.today .dateCell {\n color: var(--el-color-primary);\n}\n\n.dateCell {\n width: 48px;\n height: 42px;\n\n span {\n display: block;\n }\n\n .solar_calendar {\n font-size: 16px;\n font-weight: 400;\n }\n\n .lunar_calendar {\n margin-top: -14px;\n margin-bottom: -6px;\n overflow: hidden;\n font-size: 10px;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { getLunar } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'valueChange']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\nconst getShowText = (cell: any) => {\n if (cell.renderText) {\n return cell.renderText;\n }\n return cell.text;\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueRef\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n format=\"YYYY-MM-DD\"\n style=\"width: 100%\"\n value-format=\"YYYY-MM-DD\"\n >\n <template #default=\"cell\">\n <div class=\"dateCell\">\n <span class=\"solar_calendar\">\n {{ getShowText(cell) }}\n </span>\n <span class=\"lunar_calendar\">{{ getLunar(cell) }}</span>\n </div>\n </template>\n </el-date-picker>\n</template>\n\n<style scoped lang=\"scss\">\ntd.current .dateCell {\n color: #fff; /* 文本颜色变为白色 */\n background-color: var(--el-color-primary); /* 黄色背景,表示高亮 */\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\ntd.today .dateCell {\n color: var(--el-color-primary);\n}\n\n.dateCell {\n width: 48px;\n height: 42px;\n\n span {\n display: block;\n }\n\n .solar_calendar {\n font-size: 16px;\n font-weight: 400;\n }\n\n .lunar_calendar {\n margin-top: -14px;\n margin-bottom: -6px;\n overflow: hidden;\n font-size: 10px;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n}\n</style>\n","import FormDatePicker from './FormDatePicker.vue';\nimport type { App } from 'vue';\n\n(FormDatePicker as any).name = 'FormDatePicker';\n\nFormDatePicker.install = (app: App) => {\n app.component('FormDatePicker', FormDatePicker);\n};\n\nexport { FormDatePicker };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { getLunar } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\nconst getShowText = (cell: any) => {\n if (cell.renderText) {\n return cell.renderText;\n }\n return cell.text;\n};\n\n/**\n * 用于日期组件的shortcuts预设\n */\nconst elShortcuts = [\n {\n text: '昨天',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() - 3600 * 1000 * 24);\n return date;\n },\n },\n {\n text: '明天',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() + 3600 * 1000 * 24);\n return date;\n },\n },\n {\n text: '上周',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);\n return date;\n },\n },\n {\n text: '1周前',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() + 3600 * 1000 * 24 * 7);\n return date;\n },\n },\n];\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueRef\"\n :shortcuts=\"elShortcuts\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n format=\"YYYY-MM-DD HH:mm:ss\"\n style=\"width: 100%\"\n type=\"datetime\"\n value-format=\"YYYY-MM-DD HH:mm:ss\"\n >\n <template #default=\"cell\">\n <div class=\"dateCell\">\n <span class=\"solar_calendar\">\n {{ getShowText(cell) }}\n </span>\n <span class=\"lunar_calendar\">{{ getLunar(cell) }}</span>\n </div>\n </template>\n </el-date-picker>\n</template>\n\n<style scoped lang=\"scss\">\ntd.current .dateCell {\n color: #fff; /* 文本颜色变为白色 */\n background-color: var(--el-color-primary); /* 黄色背景,表示高亮 */\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\ntd.today .dateCell {\n color: var(--el-color-primary);\n}\n\n.dateCell {\n width: 48px;\n height: 42px;\n\n span {\n display: block;\n }\n\n .solar_calendar {\n font-size: 16px;\n font-weight: 400;\n }\n\n .lunar_calendar {\n margin-top: -14px;\n margin-bottom: -6px;\n overflow: hidden;\n font-size: 10px;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { getLunar } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormFrame;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits([\n 'update:value',\n 'getComponentValue',\n 'valueChange',\n 'setShow',\n]);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\nconst getShowText = (cell: any) => {\n if (cell.renderText) {\n return cell.renderText;\n }\n return cell.text;\n};\n\n/**\n * 用于日期组件的shortcuts预设\n */\nconst elShortcuts = [\n {\n text: '昨天',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() - 3600 * 1000 * 24);\n return date;\n },\n },\n {\n text: '明天',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() + 3600 * 1000 * 24);\n return date;\n },\n },\n {\n text: '上周',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);\n return date;\n },\n },\n {\n text: '1周前',\n value: () => {\n const date = new Date();\n date.setTime(date.getTime() + 3600 * 1000 * 24 * 7);\n return date;\n },\n },\n];\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-date-picker\n v-model=\"valueRef\"\n :shortcuts=\"elShortcuts\"\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\n format=\"YYYY-MM-DD HH:mm:ss\"\n style=\"width: 100%\"\n type=\"datetime\"\n value-format=\"YYYY-MM-DD HH:mm:ss\"\n >\n <template #default=\"cell\">\n <div class=\"dateCell\">\n <span class=\"solar_calendar\">\n {{ getShowText(cell) }}\n </span>\n <span class=\"lunar_calendar\">{{ getLunar(cell) }}</span>\n </div>\n </template>\n </el-date-picker>\n</template>\n\n<style scoped lang=\"scss\">\ntd.current .dateCell {\n color: #fff; /* 文本颜色变为白色 */\n background-color: var(--el-color-primary); /* 黄色背景,表示高亮 */\n border-radius: calc(var(--el-border-radius-base) - 1px);\n}\n\ntd.today .dateCell {\n color: var(--el-color-primary);\n}\n\n.dateCell {\n width: 48px;\n height: 42px;\n\n span {\n display: block;\n }\n\n .solar_calendar {\n font-size: 16px;\n font-weight: 400;\n }\n\n .lunar_calendar {\n margin-top: -14px;\n margin-bottom: -6px;\n overflow: hidden;\n font-size: 10px;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n}\n</style>\n","import FormDateTimePicker from './FormDateTimePicker.vue';\nimport type { App } from 'vue';\n\n(FormDateTimePicker as any).name = 'FormDateTimePicker';\n\nFormDateTimePicker.install = (app: App) => {\n app.component('FormDateTimePicker', FormDateTimePicker);\n};\n\nexport { FormDateTimePicker };\n","<script setup lang=\"ts\">\nimport type { CascaderProps } from 'element-plus';\n\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { isEmpty, msgTips } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: null | number[] | string[];\n detail: FormSelectAsyncProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst cascaderProps: CascaderProps = {\n lazy: true,\n lazyLoad: async (node, resolve) => {\n if (isEmpty(props.detail.optionHttpUrl)) resolve([]);\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n if (node.data && node.data.value) {\n componentValueMap.nodeValue = node.data.value;\n }\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (\n !['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)\n ) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n resolve(result.data);\n } else {\n msgTips.tips({\n msg: `${props.detail.title}数据获取失败!${result.msg}`,\n type: 'warning',\n });\n resolve([]);\n }\n },\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-cascader\n v-model=\"valueRef\"\n :props=\"{ ...cascaderProps, ...props.detail.componentParams }\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n />\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport type { CascaderProps } from 'element-plus';\n\nimport type { FormSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { isEmpty, msgTips } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: null | number[] | string[];\n detail: FormSelectAsyncProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: null,\n mittId: () => null,\n});\nconst emits = defineEmits(['update:value', 'getComponentValue', 'setShow']);\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst cascaderProps: CascaderProps = {\n lazy: true,\n lazyLoad: async (node, resolve) => {\n if (isEmpty(props.detail.optionHttpUrl)) resolve([]);\n\n let componentValueMap: any = {};\n emits(\n 'getComponentValue',\n props.detail.optionHttpComponentValue,\n (val: any) => {\n componentValueMap = val;\n },\n );\n\n if (node.data && node.data.value) {\n componentValueMap.nodeValue = node.data.value;\n }\n\n const opt: any = {\n method: props.detail.optionHttpMethod,\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n if (\n !['get', 'GET', 'head', 'HEAD'].includes(props.detail.optionHttpMethod)\n ) {\n opt.body = JSON.stringify({\n ...props.detail.optionHttpParams,\n ...componentValueMap,\n });\n }\n const response = await fetch(props.detail.optionHttpUrl, opt);\n\n let result: any = {\n code: -5,\n msg: '请求失败',\n data: {},\n };\n if (response.ok) {\n result = await response.json();\n }\n\n if (result.code === 0) {\n resolve(result.data);\n } else {\n msgTips.tips({\n msg: `${props.detail.title}数据获取失败!${result.msg}`,\n type: 'warning',\n });\n resolve([]);\n }\n },\n};\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-cascader\n v-model=\"valueRef\"\n :props=\"{ ...cascaderProps, ...props.detail.componentParams }\"\n v-bind=\"props.detail.componentParams ? props.detail.componentParams : {}\"\n />\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import FormCascaderAsync from './FormCascaderAsync.vue';\nimport type { App } from 'vue';\n\n(FormCascaderAsync as any).name = 'FormCascaderAsync';\n\nFormCascaderAsync.install = (app: App) => {\n app.component('FormCascaderAsync', FormCascaderAsync);\n};\n\nexport { FormCascaderAsync };\n","<script setup lang=\"ts\">\nimport type { FormTableSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormTableSelectProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits(['getComponentValue', 'valueChange']);\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\nconst valueRef = defineModel('value');\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\n/**\n * 如果是多选 value位数组类型时, value就不能为null\n */\nconst multipleClear = async () => {\n await sleep(0.1);\n if (\n (props.detail.multiple || props.detail.componentParams?.mode === 'tags') &&\n valueRef.value === null\n ) {\n valueRef.value = [];\n }\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n console.log('Receive event data', eventData);\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n multipleClear();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n :multiple=\"detail?.multiple\"\n :placeholder=\"detail.placeholder\"\n :value-key=\"detail.componentParams.keyField\"\n clearable\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in detail?.options\"\n :key=\"item[detail.componentParams?.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.componentParams?.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.componentParams?.optionWidth\n ? `${detail.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.componentParams?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormTableSelectProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { sleep } from '@/utils';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormTableSelectProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => undefined,\n mittId: () => null,\n});\nconst emits = defineEmits(['getComponentValue', 'valueChange']);\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\nconst valueRef = defineModel('value');\n\n/** 当值发生变化时 */\n// const handleChange = () => {\n// // 如果需要通知的字段数量大于0,则发送一个valueChange事件\n// if (props.detail?.noticeField && props.detail?.noticeField.length > 0) {\n// emits(\n// 'valueChange',\n// props.detail?.noticeField,\n// props.detail?.field,\n// valueRef,\n// );\n// }\n// };\n\n/**\n * 如果是多选 value位数组类型时, value就不能为null\n */\nconst multipleClear = async () => {\n await sleep(0.1);\n if (\n (props.detail.multiple || props.detail.componentParams?.mode === 'tags') &&\n valueRef.value === null\n ) {\n valueRef.value = [];\n }\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n console.log('Receive event data', eventData);\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n multipleClear();\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n :multiple=\"detail?.multiple\"\n :placeholder=\"detail.placeholder\"\n :value-key=\"detail.componentParams.keyField\"\n clearable\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in detail?.options\"\n :key=\"item[detail.componentParams?.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.componentParams?.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.componentParams?.optionWidth\n ? `${detail.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.componentParams?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n\n<style scoped></style>\n","import FormTableSelect from './FormTableSelect.vue';\nimport type { App } from 'vue';\n\n(FormTableSelect as any).name = 'FormTableSelect';\n\nFormTableSelect.install = (app: App) => {\n app.component('FormTableSelect', FormTableSelect);\n};\n\nexport { FormTableSelect };\n","<script setup lang=\"ts\">\nimport type { FormTableSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useSelectAsync } from '../hooks/selectAsync.hook';\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormTableSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\n// 1. 定义 emits 类型(强类型)\nconst emits = defineEmits<{\n (event: 'update:value', value: any): void;\n (\n event: 'getComponentValue',\n componentValue: any,\n callback: (val: any) => void,\n ): void;\n (event: 'valueChange', value: any): void;\n (event: 'setShow', show: boolean): void;\n}>();\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst { loading, getOptions, optionsData, init } = useSelectAsync({\n emits,\n props,\n valueRef,\n});\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n init();\n registerMitt((_eventData: any) => {\n receiveBroadcasts(_eventData);\n getOptions();\n });\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n v-loading=\"loading\"\n :multiple=\"detail.multiple\"\n :loading=\"loading\"\n :placeholder=\"detail?.placeholder\"\n :value-key=\"detail.componentParams.keyField\"\n @focus=\"getOptions\"\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item[detail.componentParams?.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.componentParams?.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.componentParams?.optionWidth\n ? `${detail.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.componentParams?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormTableSelectAsyncProp } from '@/types';\n\nimport { onMounted, onUnmounted } from 'vue';\n\nimport { useSelectAsync } from '../hooks/selectAsync.hook';\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any;\n detail: FormTableSelectAsyncProp;\n fieldTitle: string;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => null,\n mittId: () => null,\n});\n// 1. 定义 emits 类型(强类型)\nconst emits = defineEmits<{\n (event: 'update:value', value: any): void;\n (\n event: 'getComponentValue',\n componentValue: any,\n callback: (val: any) => void,\n ): void;\n (event: 'valueChange', value: any): void;\n (event: 'setShow', show: boolean): void;\n}>();\nconst valueRef = defineModel('value');\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\nconst { loading, getOptions, optionsData, init } = useSelectAsync({\n emits,\n props,\n valueRef,\n});\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: string) => {\n valueRef.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n init();\n registerMitt((_eventData: any) => {\n receiveBroadcasts(_eventData);\n getOptions();\n });\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <el-select\n v-model=\"valueRef\"\n v-bind=\"detail.componentParams ? detail.componentParams : {}\"\n v-loading=\"loading\"\n :multiple=\"detail.multiple\"\n :loading=\"loading\"\n :placeholder=\"detail?.placeholder\"\n :value-key=\"detail.componentParams.keyField\"\n @focus=\"getOptions\"\n >\n <template #header>\n <el-row>\n <el-col\n v-for=\"item in detail.componentParams?.optionSlots\"\n :key=\"item.field\"\n :span=\"item.span\"\n >\n <el-text truncated>\n {{ item.label }}\n </el-text>\n </el-col>\n </el-row>\n </template>\n <el-option\n v-for=\"item in optionsData\"\n :key=\"item[detail.componentParams?.keyField]\"\n :disabled=\"item.disabled === true\"\n :label=\"item[detail.componentParams?.labelField]\"\n :value=\"item\"\n :style=\"{\n width: detail.componentParams?.optionWidth\n ? `${detail.componentParams.optionWidth}px`\n : '100%',\n }\"\n >\n <el-row>\n <el-col\n v-for=\"optionSlot in detail.componentParams?.optionSlots\"\n :key=\"optionSlot.field\"\n :span=\"optionSlot.span\"\n >\n <el-text truncated>\n {{ item[optionSlot.field] }}\n </el-text>\n </el-col>\n </el-row>\n </el-option>\n </el-select>\n</template>\n\n<style scoped></style>\n","import FormTableSelectAsync from './FormTableSelectAsync.vue';\nimport type { App } from 'vue';\n\n(FormTableSelectAsync as any).name = 'FormTableSelectAsync';\n\nFormTableSelectAsync.install = (app: App) => {\n app.component('FormTableSelectAsync', FormTableSelectAsync);\n};\n\nexport { FormTableSelectAsync };\n","<script setup lang=\"ts\">\r\nimport type { FormFrame } from '@/types';\r\n\r\nimport { computed, onMounted, ref } from 'vue';\r\n\r\nimport { Search } from '@element-plus/icons-vue';\r\n\r\nimport { datasetApi } from '@/api';\r\n\r\ninterface Props {\r\n value?: string;\r\n detail: FormFrame;\r\n mittId?: any;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n value: '',\r\n mittId: () => null,\r\n});\r\n\r\nconst emits = defineEmits(['update:value', 'valueChange']);\r\nconst valueRef = defineModel('value');\r\n\r\n// 对话框控制\r\nconst dialogVisible = ref(false);\r\nconst dialogTitle = ref('');\r\nconst dialogMode = ref<'add' | 'edit' | 'preview'>('preview');\r\n\r\n// 当前选中的字典\r\nconst selectedDict = ref<any>(null);\r\n\r\n// 字典表列表\r\nconst dictTables = ref<any[]>([]);\r\n\r\n// 字典项列表\r\nconst dictItems = ref<any[]>([]);\r\n\r\n// 搜索关键词\r\nconst searchKeyword = ref('');\r\n\r\n// 加载状态\r\nconst loading = ref(false);\r\nconst itemsLoading = ref(false);\r\n\r\n// 表单数据\r\nconst formData = ref<any>({});\r\n\r\n// 获取字典表列表\r\nconst loadDictTables = async () => {\r\n loading.value = true;\r\n try {\r\n const res = await datasetApi('getDictionaryDataByFieldName', {\r\n fieldName: 'catalogue',\r\n });\r\n if (res.code === 0 && res.data) {\r\n dictTables.value = res.data.map((item: any) => ({\r\n id: item.id,\r\n code: item.dic_value, // dic_value 是字典编码\r\n name: item.dic_name, // dic_name 是字典名称\r\n description: item.remark || '',\r\n disabled: item.disabled,\r\n sort: item.sort,\r\n }));\r\n }\r\n } catch (error) {\r\n console.error('加载字典表列表失败:', error);\r\n } finally {\r\n loading.value = false;\r\n }\r\n};\r\n\r\n// 获取字典项列表\r\nconst loadDictItems = async (fieldName: string) => {\r\n itemsLoading.value = true;\r\n try {\r\n const res = await datasetApi('getDictionaryDataByFieldName', {\r\n fieldName,\r\n });\r\n\r\n if (res.code === 0 && res.data) {\r\n dictItems.value = res.data.map((item: any) => ({\r\n id: item.id,\r\n dictCode: fieldName,\r\n label: item.dic_name, // dic_name 是显示标签\r\n value: item.dic_value, // dic_value 是值\r\n sort: item.sort,\r\n disabled: item.disabled,\r\n remark: item.remark,\r\n }));\r\n }\r\n } catch (error) {\r\n console.error('加载字典项失败:', error);\r\n } finally {\r\n itemsLoading.value = false;\r\n }\r\n};\r\n\r\n// 打开选择器\r\nconst openSelector = async () => {\r\n dialogVisible.value = true;\r\n dialogTitle.value = '字典表选择器';\r\n dialogMode.value = 'preview';\r\n searchKeyword.value = '';\r\n await loadDictTables();\r\n};\r\n\r\n// 选择字典表\r\nconst selectDict = (dict: any) => {\r\n selectedDict.value = dict;\r\n valueRef.value = dict.code;\r\n dialogVisible.value = false; // 关闭对话框\r\n emits('valueChange', props.detail.field, dict.code);\r\n};\r\n\r\n// 查看字典详情\r\nconst viewDict = async (dict: any) => {\r\n selectedDict.value = dict;\r\n await loadDictItems(dict.code);\r\n};\r\n\r\n// 编辑字典表\r\nconst editDictTable = (dict: any) => {\r\n dialogMode.value = 'edit';\r\n formData.value = { ...dict };\r\n};\r\n\r\n// 获取当前字典的项\r\nconst getCurrentDictItems = () => {\r\n return dictItems.value;\r\n};\r\n\r\n// 获取显示的字典名称\r\nconst getDisplayName = () => {\r\n const dict = dictTables.value.find((d) => d.code === valueRef.value);\r\n return dict ? dict.name : valueRef.value || '请选择字典';\r\n};\r\n\r\n// 过滤字典表列表\r\nconst filteredDictTables = computed(() => {\r\n if (!searchKeyword.value) {\r\n return dictTables.value;\r\n }\r\n const keyword = searchKeyword.value.toLowerCase();\r\n return dictTables.value.filter(\r\n (dict) =>\r\n dict.name.toLowerCase().includes(keyword) ||\r\n dict.code.toLowerCase().includes(keyword) ||\r\n (dict.description && dict.description.toLowerCase().includes(keyword)),\r\n );\r\n});\r\n\r\n// 初始化时加载字典表列表(如果有初始值)\r\nonMounted(() => {\r\n if (valueRef.value) {\r\n loadDictTables();\r\n }\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"dict-selector\">\r\n <el-input\r\n :model-value=\"getDisplayName()\"\r\n :placeholder=\"detail.placeholder || '请选择字典'\"\r\n readonly\r\n @click=\"openSelector\"\r\n >\r\n <template #suffix>\r\n <el-icon class=\"cursor-pointer\">\r\n <Search />\r\n </el-icon>\r\n </template>\r\n </el-input>\r\n\r\n <el-dialog\r\n v-model=\"dialogVisible\"\r\n :title=\"dialogTitle\"\r\n width=\"80%\"\r\n top=\"5vh\"\r\n destroy-on-close\r\n class=\"dict-selector-dialog\"\r\n >\r\n <div class=\"dict-selector-content\">\r\n <!-- 左侧:字典表列表 -->\r\n <div class=\"dict-list\">\r\n <div class=\"dict-list-header\">\r\n <span class=\"title\">字典表列表</span>\r\n </div>\r\n <div class=\"dict-search\">\r\n <el-input\r\n v-model=\"searchKeyword\"\r\n placeholder=\"搜索字典名称或编码\"\r\n clearable\r\n size=\"small\"\r\n >\r\n <template #prefix>\r\n <el-icon>\r\n <Search />\r\n </el-icon>\r\n </template>\r\n </el-input>\r\n </div>\r\n <div v-loading=\"loading\" class=\"dict-list-body\">\r\n <div\r\n v-for=\"dict in filteredDictTables\"\r\n :key=\"dict.id\"\r\n class=\"dict-item\"\r\n :class=\"[{ active: selectedDict?.id === dict.id }]\"\r\n @click=\"viewDict(dict)\"\r\n >\r\n <div class=\"dict-item-content\">\r\n <div class=\"dict-name\">{{ dict.name }}</div>\r\n <div class=\"dict-code\">{{ dict.code }}</div>\r\n </div>\r\n <div class=\"dict-item-actions\">\r\n <el-button\r\n link\r\n size=\"small\"\r\n type=\"primary\"\r\n @click.stop=\"selectDict(dict)\"\r\n >\r\n 选择\r\n </el-button>\r\n <el-button\r\n link\r\n size=\"small\"\r\n type=\"primary\"\r\n @click.stop=\"editDictTable(dict)\"\r\n >\r\n 编辑\r\n </el-button>\r\n </div>\r\n </div>\r\n <div v-if=\"filteredDictTables.length === 0\" class=\"empty-result\">\r\n <el-empty description=\"未找到匹配的字典\" :image-size=\"80\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 右侧:字典详情/表单 -->\r\n <div class=\"dict-detail\">\r\n <!-- 预览模式 -->\r\n <template v-if=\"dialogMode === 'preview' && selectedDict\">\r\n <div class=\"dict-detail-header\">\r\n <span class=\"title\">字典详情</span>\r\n </div>\r\n <div class=\"dict-info\">\r\n <el-descriptions :column=\"1\" border>\r\n <el-descriptions-item label=\"字典编码\">\r\n {{ selectedDict.code }}\r\n </el-descriptions-item>\r\n <el-descriptions-item label=\"字典名称\">\r\n {{ selectedDict.name }}\r\n </el-descriptions-item>\r\n <el-descriptions-item label=\"描述\">\r\n {{ selectedDict.description }}\r\n </el-descriptions-item>\r\n </el-descriptions>\r\n </div>\r\n\r\n <div class=\"dict-items\">\r\n <div class=\"dict-items-header\">\r\n <span class=\"title\">字典项</span>\r\n </div>\r\n <el-table :data=\"getCurrentDictItems()\" border stripe>\r\n <el-table-column label=\"标签\" prop=\"label\" />\r\n <el-table-column label=\"值\" prop=\"value\" />\r\n <el-table-column label=\"排序\" prop=\"sort\" width=\"80\" />\r\n </el-table>\r\n </div>\r\n </template>\r\n\r\n <!-- 未选择状态 -->\r\n <template v-else>\r\n <div class=\"empty-state\">\r\n <el-empty description=\"请选择一个字典表查看详情\" />\r\n </div>\r\n </template>\r\n </div>\r\n </div>\r\n </el-dialog>\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.dict-selector {\r\n width: 100%;\r\n\r\n :deep(.el-input__inner) {\r\n cursor: pointer;\r\n }\r\n}\r\n\r\n:deep(.dict-selector-dialog) {\r\n .el-dialog {\r\n max-height: 90vh;\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n\r\n .el-dialog__body {\r\n height: 70vh;\r\n padding: 0;\r\n overflow: hidden;\r\n flex: 1;\r\n }\r\n}\r\n\r\n.dict-selector-content {\r\n display: flex;\r\n gap: 16px;\r\n height: 100%;\r\n padding: 16px;\r\n}\r\n\r\n.dict-list {\r\n flex: 0 0 300px;\r\n display: flex;\r\n flex-direction: column;\r\n border: 1px solid var(--el-border-color);\r\n border-radius: 4px;\r\n overflow: hidden;\r\n}\r\n\r\n.dict-list-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 12px 16px;\r\n background-color: var(--el-fill-color-light);\r\n border-bottom: 1px solid var(--el-border-color);\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n.dict-search {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid var(--el-border-color-lighter);\r\n}\r\n\r\n.dict-list-body {\r\n flex: 1;\r\n overflow-y: auto;\r\n}\r\n\r\n.empty-result {\r\n padding: 20px;\r\n text-align: center;\r\n}\r\n\r\n.dict-item {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid var(--el-border-color-lighter);\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n\r\n &:hover {\r\n background-color: var(--el-fill-color-light);\r\n }\r\n\r\n &.active {\r\n background-color: var(--el-color-primary-light-9);\r\n border-left: 3px solid var(--el-color-primary);\r\n }\r\n\r\n &:last-child {\r\n border-bottom: none;\r\n }\r\n}\r\n\r\n.dict-item-content {\r\n margin-bottom: 8px;\r\n\r\n .dict-name {\r\n font-weight: 500;\r\n font-size: 14px;\r\n margin-bottom: 4px;\r\n }\r\n\r\n .dict-code {\r\n font-size: 12px;\r\n color: var(--el-text-color-secondary);\r\n }\r\n}\r\n\r\n.dict-item-actions {\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.dict-detail {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n border: 1px solid var(--el-border-color);\r\n border-radius: 4px;\r\n overflow: hidden;\r\n}\r\n\r\n.dict-detail-header {\r\n padding: 12px 16px;\r\n background-color: var(--el-fill-color-light);\r\n border-bottom: 1px solid var(--el-border-color);\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n.dict-info {\r\n padding: 16px;\r\n}\r\n\r\n.dict-items {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n padding: 16px;\r\n overflow: hidden;\r\n\r\n .dict-items-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 12px;\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n }\r\n\r\n :deep(.el-table) {\r\n flex: 1;\r\n }\r\n}\r\n\r\n.empty-state {\r\n flex: 1;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.cursor-pointer {\r\n cursor: pointer;\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport type { FormFrame } from '@/types';\r\n\r\nimport { computed, onMounted, ref } from 'vue';\r\n\r\nimport { Search } from '@element-plus/icons-vue';\r\n\r\nimport { datasetApi } from '@/api';\r\n\r\ninterface Props {\r\n value?: string;\r\n detail: FormFrame;\r\n mittId?: any;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n value: '',\r\n mittId: () => null,\r\n});\r\n\r\nconst emits = defineEmits(['update:value', 'valueChange']);\r\nconst valueRef = defineModel('value');\r\n\r\n// 对话框控制\r\nconst dialogVisible = ref(false);\r\nconst dialogTitle = ref('');\r\nconst dialogMode = ref<'add' | 'edit' | 'preview'>('preview');\r\n\r\n// 当前选中的字典\r\nconst selectedDict = ref<any>(null);\r\n\r\n// 字典表列表\r\nconst dictTables = ref<any[]>([]);\r\n\r\n// 字典项列表\r\nconst dictItems = ref<any[]>([]);\r\n\r\n// 搜索关键词\r\nconst searchKeyword = ref('');\r\n\r\n// 加载状态\r\nconst loading = ref(false);\r\nconst itemsLoading = ref(false);\r\n\r\n// 表单数据\r\nconst formData = ref<any>({});\r\n\r\n// 获取字典表列表\r\nconst loadDictTables = async () => {\r\n loading.value = true;\r\n try {\r\n const res = await datasetApi('getDictionaryDataByFieldName', {\r\n fieldName: 'catalogue',\r\n });\r\n if (res.code === 0 && res.data) {\r\n dictTables.value = res.data.map((item: any) => ({\r\n id: item.id,\r\n code: item.dic_value, // dic_value 是字典编码\r\n name: item.dic_name, // dic_name 是字典名称\r\n description: item.remark || '',\r\n disabled: item.disabled,\r\n sort: item.sort,\r\n }));\r\n }\r\n } catch (error) {\r\n console.error('加载字典表列表失败:', error);\r\n } finally {\r\n loading.value = false;\r\n }\r\n};\r\n\r\n// 获取字典项列表\r\nconst loadDictItems = async (fieldName: string) => {\r\n itemsLoading.value = true;\r\n try {\r\n const res = await datasetApi('getDictionaryDataByFieldName', {\r\n fieldName,\r\n });\r\n\r\n if (res.code === 0 && res.data) {\r\n dictItems.value = res.data.map((item: any) => ({\r\n id: item.id,\r\n dictCode: fieldName,\r\n label: item.dic_name, // dic_name 是显示标签\r\n value: item.dic_value, // dic_value 是值\r\n sort: item.sort,\r\n disabled: item.disabled,\r\n remark: item.remark,\r\n }));\r\n }\r\n } catch (error) {\r\n console.error('加载字典项失败:', error);\r\n } finally {\r\n itemsLoading.value = false;\r\n }\r\n};\r\n\r\n// 打开选择器\r\nconst openSelector = async () => {\r\n dialogVisible.value = true;\r\n dialogTitle.value = '字典表选择器';\r\n dialogMode.value = 'preview';\r\n searchKeyword.value = '';\r\n await loadDictTables();\r\n};\r\n\r\n// 选择字典表\r\nconst selectDict = (dict: any) => {\r\n selectedDict.value = dict;\r\n valueRef.value = dict.code;\r\n dialogVisible.value = false; // 关闭对话框\r\n emits('valueChange', props.detail.field, dict.code);\r\n};\r\n\r\n// 查看字典详情\r\nconst viewDict = async (dict: any) => {\r\n selectedDict.value = dict;\r\n await loadDictItems(dict.code);\r\n};\r\n\r\n// 编辑字典表\r\nconst editDictTable = (dict: any) => {\r\n dialogMode.value = 'edit';\r\n formData.value = { ...dict };\r\n};\r\n\r\n// 获取当前字典的项\r\nconst getCurrentDictItems = () => {\r\n return dictItems.value;\r\n};\r\n\r\n// 获取显示的字典名称\r\nconst getDisplayName = () => {\r\n const dict = dictTables.value.find((d) => d.code === valueRef.value);\r\n return dict ? dict.name : valueRef.value || '请选择字典';\r\n};\r\n\r\n// 过滤字典表列表\r\nconst filteredDictTables = computed(() => {\r\n if (!searchKeyword.value) {\r\n return dictTables.value;\r\n }\r\n const keyword = searchKeyword.value.toLowerCase();\r\n return dictTables.value.filter(\r\n (dict) =>\r\n dict.name.toLowerCase().includes(keyword) ||\r\n dict.code.toLowerCase().includes(keyword) ||\r\n (dict.description && dict.description.toLowerCase().includes(keyword)),\r\n );\r\n});\r\n\r\n// 初始化时加载字典表列表(如果有初始值)\r\nonMounted(() => {\r\n if (valueRef.value) {\r\n loadDictTables();\r\n }\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"dict-selector\">\r\n <el-input\r\n :model-value=\"getDisplayName()\"\r\n :placeholder=\"detail.placeholder || '请选择字典'\"\r\n readonly\r\n @click=\"openSelector\"\r\n >\r\n <template #suffix>\r\n <el-icon class=\"cursor-pointer\">\r\n <Search />\r\n </el-icon>\r\n </template>\r\n </el-input>\r\n\r\n <el-dialog\r\n v-model=\"dialogVisible\"\r\n :title=\"dialogTitle\"\r\n width=\"80%\"\r\n top=\"5vh\"\r\n destroy-on-close\r\n class=\"dict-selector-dialog\"\r\n >\r\n <div class=\"dict-selector-content\">\r\n <!-- 左侧:字典表列表 -->\r\n <div class=\"dict-list\">\r\n <div class=\"dict-list-header\">\r\n <span class=\"title\">字典表列表</span>\r\n </div>\r\n <div class=\"dict-search\">\r\n <el-input\r\n v-model=\"searchKeyword\"\r\n placeholder=\"搜索字典名称或编码\"\r\n clearable\r\n size=\"small\"\r\n >\r\n <template #prefix>\r\n <el-icon>\r\n <Search />\r\n </el-icon>\r\n </template>\r\n </el-input>\r\n </div>\r\n <div v-loading=\"loading\" class=\"dict-list-body\">\r\n <div\r\n v-for=\"dict in filteredDictTables\"\r\n :key=\"dict.id\"\r\n class=\"dict-item\"\r\n :class=\"[{ active: selectedDict?.id === dict.id }]\"\r\n @click=\"viewDict(dict)\"\r\n >\r\n <div class=\"dict-item-content\">\r\n <div class=\"dict-name\">{{ dict.name }}</div>\r\n <div class=\"dict-code\">{{ dict.code }}</div>\r\n </div>\r\n <div class=\"dict-item-actions\">\r\n <el-button\r\n link\r\n size=\"small\"\r\n type=\"primary\"\r\n @click.stop=\"selectDict(dict)\"\r\n >\r\n 选择\r\n </el-button>\r\n <el-button\r\n link\r\n size=\"small\"\r\n type=\"primary\"\r\n @click.stop=\"editDictTable(dict)\"\r\n >\r\n 编辑\r\n </el-button>\r\n </div>\r\n </div>\r\n <div v-if=\"filteredDictTables.length === 0\" class=\"empty-result\">\r\n <el-empty description=\"未找到匹配的字典\" :image-size=\"80\" />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- 右侧:字典详情/表单 -->\r\n <div class=\"dict-detail\">\r\n <!-- 预览模式 -->\r\n <template v-if=\"dialogMode === 'preview' && selectedDict\">\r\n <div class=\"dict-detail-header\">\r\n <span class=\"title\">字典详情</span>\r\n </div>\r\n <div class=\"dict-info\">\r\n <el-descriptions :column=\"1\" border>\r\n <el-descriptions-item label=\"字典编码\">\r\n {{ selectedDict.code }}\r\n </el-descriptions-item>\r\n <el-descriptions-item label=\"字典名称\">\r\n {{ selectedDict.name }}\r\n </el-descriptions-item>\r\n <el-descriptions-item label=\"描述\">\r\n {{ selectedDict.description }}\r\n </el-descriptions-item>\r\n </el-descriptions>\r\n </div>\r\n\r\n <div class=\"dict-items\">\r\n <div class=\"dict-items-header\">\r\n <span class=\"title\">字典项</span>\r\n </div>\r\n <el-table :data=\"getCurrentDictItems()\" border stripe>\r\n <el-table-column label=\"标签\" prop=\"label\" />\r\n <el-table-column label=\"值\" prop=\"value\" />\r\n <el-table-column label=\"排序\" prop=\"sort\" width=\"80\" />\r\n </el-table>\r\n </div>\r\n </template>\r\n\r\n <!-- 未选择状态 -->\r\n <template v-else>\r\n <div class=\"empty-state\">\r\n <el-empty description=\"请选择一个字典表查看详情\" />\r\n </div>\r\n </template>\r\n </div>\r\n </div>\r\n </el-dialog>\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.dict-selector {\r\n width: 100%;\r\n\r\n :deep(.el-input__inner) {\r\n cursor: pointer;\r\n }\r\n}\r\n\r\n:deep(.dict-selector-dialog) {\r\n .el-dialog {\r\n max-height: 90vh;\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n\r\n .el-dialog__body {\r\n height: 70vh;\r\n padding: 0;\r\n overflow: hidden;\r\n flex: 1;\r\n }\r\n}\r\n\r\n.dict-selector-content {\r\n display: flex;\r\n gap: 16px;\r\n height: 100%;\r\n padding: 16px;\r\n}\r\n\r\n.dict-list {\r\n flex: 0 0 300px;\r\n display: flex;\r\n flex-direction: column;\r\n border: 1px solid var(--el-border-color);\r\n border-radius: 4px;\r\n overflow: hidden;\r\n}\r\n\r\n.dict-list-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: 12px 16px;\r\n background-color: var(--el-fill-color-light);\r\n border-bottom: 1px solid var(--el-border-color);\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n.dict-search {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid var(--el-border-color-lighter);\r\n}\r\n\r\n.dict-list-body {\r\n flex: 1;\r\n overflow-y: auto;\r\n}\r\n\r\n.empty-result {\r\n padding: 20px;\r\n text-align: center;\r\n}\r\n\r\n.dict-item {\r\n padding: 12px 16px;\r\n border-bottom: 1px solid var(--el-border-color-lighter);\r\n cursor: pointer;\r\n transition: all 0.2s;\r\n\r\n &:hover {\r\n background-color: var(--el-fill-color-light);\r\n }\r\n\r\n &.active {\r\n background-color: var(--el-color-primary-light-9);\r\n border-left: 3px solid var(--el-color-primary);\r\n }\r\n\r\n &:last-child {\r\n border-bottom: none;\r\n }\r\n}\r\n\r\n.dict-item-content {\r\n margin-bottom: 8px;\r\n\r\n .dict-name {\r\n font-weight: 500;\r\n font-size: 14px;\r\n margin-bottom: 4px;\r\n }\r\n\r\n .dict-code {\r\n font-size: 12px;\r\n color: var(--el-text-color-secondary);\r\n }\r\n}\r\n\r\n.dict-item-actions {\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.dict-detail {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n border: 1px solid var(--el-border-color);\r\n border-radius: 4px;\r\n overflow: hidden;\r\n}\r\n\r\n.dict-detail-header {\r\n padding: 12px 16px;\r\n background-color: var(--el-fill-color-light);\r\n border-bottom: 1px solid var(--el-border-color);\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n}\r\n\r\n.dict-info {\r\n padding: 16px;\r\n}\r\n\r\n.dict-items {\r\n flex: 1;\r\n display: flex;\r\n flex-direction: column;\r\n padding: 16px;\r\n overflow: hidden;\r\n\r\n .dict-items-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 12px;\r\n\r\n .title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n }\r\n }\r\n\r\n :deep(.el-table) {\r\n flex: 1;\r\n }\r\n}\r\n\r\n.empty-state {\r\n flex: 1;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.cursor-pointer {\r\n cursor: pointer;\r\n}\r\n</style>\r\n","import FormDictSelector from './FormDictSelector.vue';\nimport type { App } from 'vue';\n\n(FormDictSelector as any).name = 'FormDictSelector';\n\nFormDictSelector.install = (app: App) => {\n app.component('FormDictSelector', FormDictSelector);\n};\n\nexport { FormDictSelector };\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { computed, onMounted, ref, watch } from 'vue';\n\nimport { Icon } from '@iconify/vue';\n\nimport { getCollectionsApi, searchPageApi } from '@/api';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n}\n\ninterface IconCollection {\n prefix: string;\n name: string;\n total?: number;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: undefined,\n});\n\nconst valueRef = defineModel('value', { default: '', type: String });\n\n// 状态\nconst visible = ref(false);\nconst loading = ref(false);\nconst loadingMore = ref(false);\nconst collectionsLoading = ref(false);\nconst searchQuery = ref('');\nconst selectedPrefix = ref('all'); // 'all' 表示搜索所有图标集\nconst icons = ref<string[]>([]);\nconst collections = ref<IconCollection[]>([]);\nconst currentPage = ref(1);\nconst pageSize = ref(36);\nconst totalIcons = ref(0);\nconst hasMore = ref(true);\nconst iconGridRef = ref<HTMLElement | null>(null);\n\n// 计算属性\nconst currentIcon = computed({\n get: () => valueRef.value || '',\n set: (val) => {\n valueRef.value = val;\n },\n});\n\n// 方法\nconst getIconName = (fullIcon: string) => {\n if (fullIcon.includes(':')) {\n return fullIcon.split(':')[1];\n }\n return fullIcon;\n};\n\nconst loadCollections = async () => {\n collectionsLoading.value = true;\n try {\n // const response = await fetch(`${BASE_URL}/iconify/collections`);\n // const data = await response.json();\n\n const data = await getCollectionsApi();\n\n if (data) {\n collections.value = Object.entries(data).map(\n ([prefix, info]: [string, any]) => ({\n prefix,\n name: info.name || prefix,\n total: info.total,\n }),\n );\n\n // 如果当前有图标值,尝试从中提取 prefix\n if (currentIcon.value && currentIcon.value.includes(':')) {\n const prefix = currentIcon.value.split(':')[0];\n if (prefix && collections.value.some((c) => c.prefix === prefix)) {\n selectedPrefix.value = prefix;\n }\n }\n }\n } catch (error) {\n console.error('加载图标集失败:', error);\n collections.value = [];\n } finally {\n collectionsLoading.value = false;\n }\n};\n\nconst searchIcons = async (reset = false) => {\n if (reset) {\n currentPage.value = 1;\n icons.value = [];\n hasMore.value = true;\n }\n\n if (!hasMore.value || loading.value || loadingMore.value) return;\n\n if (currentPage.value === 1) {\n loading.value = true;\n } else {\n loadingMore.value = true;\n }\n\n try {\n const params: any = {\n query: searchQuery.value,\n page: String(currentPage.value),\n pageSize: String(pageSize.value),\n };\n\n // 只有选择了特定图标集时才传 prefix 参数\n if (selectedPrefix.value && selectedPrefix.value !== 'all') {\n params.prefix = selectedPrefix.value;\n }\n const data = await searchPageApi(params);\n\n if (data && data.icons) {\n icons.value = reset ? data.icons : [...icons.value, ...data.icons];\n totalIcons.value = data.total || 0;\n hasMore.value = data.hasMore !== false;\n currentPage.value++;\n }\n } catch (error) {\n console.error('搜索图标失败:', error);\n } finally {\n loading.value = false;\n loadingMore.value = false;\n }\n};\n\n// 检查是否需要加载更多数据来填满容器\nconst checkIfNeedLoadMore = () => {\n if (!iconGridRef.value) return;\n\n const { scrollHeight, clientHeight } = iconGridRef.value;\n\n if (\n scrollHeight <= clientHeight &&\n hasMore.value &&\n !loadingMore.value &&\n !loading.value\n ) {\n searchIcons();\n }\n};\n\n// 滚动加载更多\nconst handleScroll = (e: Event) => {\n const target = e.target as HTMLElement;\n const { scrollTop, scrollHeight, clientHeight } = target;\n\n const distanceToBottom = scrollHeight - scrollTop - clientHeight;\n\n // 距离底部 100px 时加载更多\n if (\n distanceToBottom < 100 &&\n !loadingMore.value &&\n !loading.value &&\n hasMore.value\n ) {\n searchIcons();\n }\n};\n\nconst selectIcon = (icon: string) => {\n currentIcon.value = icon;\n visible.value = false;\n};\n\nconst clearIcon = () => {\n currentIcon.value = '';\n};\n\nconst handleVisibleChange = async (show: boolean) => {\n if (show) {\n if (collections.value.length === 0) {\n await loadCollections();\n }\n if (icons.value.length === 0) {\n await searchIcons(true);\n // 加载完成后检查是否需要继续加载\n setTimeout(checkIfNeedLoadMore, 100);\n }\n }\n};\n\n// 监听搜索关键词变化 - 添加防抖\nlet searchTimer: null | ReturnType<typeof setTimeout> = null;\nwatch(searchQuery, () => {\n if (searchTimer) {\n clearTimeout(searchTimer);\n }\n searchTimer = setTimeout(() => {\n searchIcons(true);\n }, 300);\n});\n\n// 监听图标集变化\nwatch(selectedPrefix, () => {\n if (visible.value) {\n searchIcons(true);\n }\n});\n\n// 监听 value 变化,自动切换到对应的图标集\nwatch(currentIcon, (newVal) => {\n if (newVal && newVal.includes(':') && collections.value.length > 0) {\n const prefix = newVal.split(':')[0];\n if (\n prefix &&\n collections.value.some((c) => c.prefix === prefix) &&\n prefix !== selectedPrefix.value\n ) {\n selectedPrefix.value = prefix;\n }\n }\n});\n\nonMounted(() => {\n loadCollections();\n});\n</script>\n\n<template>\n <div class=\"icon-picker\">\n <el-popover\n v-model:visible=\"visible\"\n placement=\"bottom-start\"\n :width=\"600\"\n trigger=\"click\"\n :hide-after=\"0\"\n popper-class=\"icon-picker-popover\"\n @show=\"handleVisibleChange(true)\"\n >\n <template #reference>\n <el-input :model-value=\"currentIcon\" placeholder=\"选择图标\" readonly>\n <template #prefix>\n <Icon\n v-if=\"currentIcon\"\n :icon=\"currentIcon\"\n :width=\"20\"\n :height=\"20\"\n />\n <el-icon v-else>\n <component is=\"Grid\" />\n </el-icon>\n </template>\n <template #suffix>\n <el-icon\n v-if=\"currentIcon\"\n class=\"clear-icon\"\n @click.stop=\"clearIcon\"\n >\n <component is=\"CircleClose\" />\n </el-icon>\n </template>\n </el-input>\n </template>\n\n <!-- Popover 内容 -->\n <div class=\"picker-content\" @click.stop>\n <!-- 搜索和筛选 -->\n <div class=\"picker-header\">\n <el-select\n filterable\n v-model=\"selectedPrefix\"\n placeholder=\"选择图标集\"\n size=\"small\"\n style=\"width: 180px\"\n :loading=\"collectionsLoading\"\n :teleported=\"false\"\n >\n <el-option label=\"全部图标集\" value=\"all\" />\n <el-option\n v-for=\"collection in collections\"\n :key=\"collection.prefix\"\n :label=\"`${collection.name} (${collection.total || 0})`\"\n :value=\"collection.prefix\"\n />\n </el-select>\n\n <el-input\n v-model=\"searchQuery\"\n placeholder=\"搜索图标...\"\n size=\"small\"\n clearable\n style=\"flex: 1; margin-left: 8px\"\n >\n <template #prefix>\n <el-icon>\n <component is=\"Search\" />\n </el-icon>\n </template>\n </el-input>\n </div>\n\n <!-- 图标网格 -->\n <div\n ref=\"iconGridRef\"\n v-loading=\"loading && icons.length === 0\"\n class=\"icon-grid\"\n @scroll=\"handleScroll\"\n >\n <div\n v-for=\"icon in icons\"\n :key=\"icon\"\n class=\"icon-item\"\n :class=\"{ selected: currentIcon === icon }\"\n :title=\"icon\"\n @click=\"selectIcon(icon)\"\n >\n <div class=\"icon-wrapper\">\n <Icon :icon=\"icon\" :width=\"24\" :height=\"24\" />\n <span class=\"icon-name\">{{ getIconName(icon) }}</span>\n </div>\n </div>\n\n <!-- 加载更多提示 -->\n <div v-if=\"loadingMore\" class=\"loading-more\">\n <el-icon class=\"is-loading\"><component is=\"Loading\" /></el-icon>\n <span>加载更多...</span>\n </div>\n\n <div v-else-if=\"!hasMore && icons.length > 0\" class=\"no-more\">\n <el-text type=\"info\">已加载全部 {{ totalIcons }} 个图标</el-text>\n </div>\n\n <el-empty\n v-if=\"!loading && icons.length === 0\"\n description=\"未找到图标\"\n :image-size=\"60\"\n />\n </div>\n </div>\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.icon-picker {\n width: 100%;\n\n .clear-icon {\n cursor: pointer;\n &:hover {\n color: var(--el-color-primary);\n }\n }\n}\n\n.picker-content {\n padding: 8px;\n}\n\n.picker-header {\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.icon-grid {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 8px;\n max-height: 400px;\n overflow-y: auto;\n padding: 8px;\n border: 1px solid var(--el-border-color-lighter);\n border-radius: 4px;\n background: var(--el-fill-color-blank);\n position: relative;\n\n .icon-item {\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border: 1px solid transparent;\n border-radius: 4px;\n transition: all 0.2s;\n padding: 8px 4px;\n min-height: 70px;\n\n .icon-wrapper {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n width: 100%;\n\n .icon-name {\n font-size: 10px;\n color: var(--el-text-color-secondary);\n text-align: center;\n word-break: break-all;\n line-height: 1.2;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n }\n\n &:hover {\n background: var(--el-fill-color-light);\n border-color: var(--el-color-primary-light-5);\n transform: scale(1.05);\n\n .icon-name {\n color: var(--el-text-color-primary);\n }\n }\n\n &.selected {\n background: var(--el-color-primary-light-9);\n border-color: var(--el-color-primary);\n\n .icon-name {\n color: var(--el-color-primary);\n font-weight: 500;\n }\n }\n }\n\n .loading-more,\n .no-more {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 16px;\n color: var(--el-text-color-secondary);\n }\n\n // 当为空时,el-empty 需要占据整个网格区域并居中\n &:has(.el-empty) {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n}\n\n.picker-footer {\n display: flex;\n justify-content: center;\n margin-top: 8px;\n padding-top: 8px;\n}\n</style>\n\n<style lang=\"scss\">\n.icon-picker-popover {\n padding: 12px !important;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\nimport { computed, onMounted, ref, watch } from 'vue';\n\nimport { Icon } from '@iconify/vue';\n\nimport { getCollectionsApi, searchPageApi } from '@/api';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n}\n\ninterface IconCollection {\n prefix: string;\n name: string;\n total?: number;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: undefined,\n});\n\nconst valueRef = defineModel('value', { default: '', type: String });\n\n// 状态\nconst visible = ref(false);\nconst loading = ref(false);\nconst loadingMore = ref(false);\nconst collectionsLoading = ref(false);\nconst searchQuery = ref('');\nconst selectedPrefix = ref('all'); // 'all' 表示搜索所有图标集\nconst icons = ref<string[]>([]);\nconst collections = ref<IconCollection[]>([]);\nconst currentPage = ref(1);\nconst pageSize = ref(36);\nconst totalIcons = ref(0);\nconst hasMore = ref(true);\nconst iconGridRef = ref<HTMLElement | null>(null);\n\n// 计算属性\nconst currentIcon = computed({\n get: () => valueRef.value || '',\n set: (val) => {\n valueRef.value = val;\n },\n});\n\n// 方法\nconst getIconName = (fullIcon: string) => {\n if (fullIcon.includes(':')) {\n return fullIcon.split(':')[1];\n }\n return fullIcon;\n};\n\nconst loadCollections = async () => {\n collectionsLoading.value = true;\n try {\n // const response = await fetch(`${BASE_URL}/iconify/collections`);\n // const data = await response.json();\n\n const data = await getCollectionsApi();\n\n if (data) {\n collections.value = Object.entries(data).map(\n ([prefix, info]: [string, any]) => ({\n prefix,\n name: info.name || prefix,\n total: info.total,\n }),\n );\n\n // 如果当前有图标值,尝试从中提取 prefix\n if (currentIcon.value && currentIcon.value.includes(':')) {\n const prefix = currentIcon.value.split(':')[0];\n if (prefix && collections.value.some((c) => c.prefix === prefix)) {\n selectedPrefix.value = prefix;\n }\n }\n }\n } catch (error) {\n console.error('加载图标集失败:', error);\n collections.value = [];\n } finally {\n collectionsLoading.value = false;\n }\n};\n\nconst searchIcons = async (reset = false) => {\n if (reset) {\n currentPage.value = 1;\n icons.value = [];\n hasMore.value = true;\n }\n\n if (!hasMore.value || loading.value || loadingMore.value) return;\n\n if (currentPage.value === 1) {\n loading.value = true;\n } else {\n loadingMore.value = true;\n }\n\n try {\n const params: any = {\n query: searchQuery.value,\n page: String(currentPage.value),\n pageSize: String(pageSize.value),\n };\n\n // 只有选择了特定图标集时才传 prefix 参数\n if (selectedPrefix.value && selectedPrefix.value !== 'all') {\n params.prefix = selectedPrefix.value;\n }\n const data = await searchPageApi(params);\n\n if (data && data.icons) {\n icons.value = reset ? data.icons : [...icons.value, ...data.icons];\n totalIcons.value = data.total || 0;\n hasMore.value = data.hasMore !== false;\n currentPage.value++;\n }\n } catch (error) {\n console.error('搜索图标失败:', error);\n } finally {\n loading.value = false;\n loadingMore.value = false;\n }\n};\n\n// 检查是否需要加载更多数据来填满容器\nconst checkIfNeedLoadMore = () => {\n if (!iconGridRef.value) return;\n\n const { scrollHeight, clientHeight } = iconGridRef.value;\n\n if (\n scrollHeight <= clientHeight &&\n hasMore.value &&\n !loadingMore.value &&\n !loading.value\n ) {\n searchIcons();\n }\n};\n\n// 滚动加载更多\nconst handleScroll = (e: Event) => {\n const target = e.target as HTMLElement;\n const { scrollTop, scrollHeight, clientHeight } = target;\n\n const distanceToBottom = scrollHeight - scrollTop - clientHeight;\n\n // 距离底部 100px 时加载更多\n if (\n distanceToBottom < 100 &&\n !loadingMore.value &&\n !loading.value &&\n hasMore.value\n ) {\n searchIcons();\n }\n};\n\nconst selectIcon = (icon: string) => {\n currentIcon.value = icon;\n visible.value = false;\n};\n\nconst clearIcon = () => {\n currentIcon.value = '';\n};\n\nconst handleVisibleChange = async (show: boolean) => {\n if (show) {\n if (collections.value.length === 0) {\n await loadCollections();\n }\n if (icons.value.length === 0) {\n await searchIcons(true);\n // 加载完成后检查是否需要继续加载\n setTimeout(checkIfNeedLoadMore, 100);\n }\n }\n};\n\n// 监听搜索关键词变化 - 添加防抖\nlet searchTimer: null | ReturnType<typeof setTimeout> = null;\nwatch(searchQuery, () => {\n if (searchTimer) {\n clearTimeout(searchTimer);\n }\n searchTimer = setTimeout(() => {\n searchIcons(true);\n }, 300);\n});\n\n// 监听图标集变化\nwatch(selectedPrefix, () => {\n if (visible.value) {\n searchIcons(true);\n }\n});\n\n// 监听 value 变化,自动切换到对应的图标集\nwatch(currentIcon, (newVal) => {\n if (newVal && newVal.includes(':') && collections.value.length > 0) {\n const prefix = newVal.split(':')[0];\n if (\n prefix &&\n collections.value.some((c) => c.prefix === prefix) &&\n prefix !== selectedPrefix.value\n ) {\n selectedPrefix.value = prefix;\n }\n }\n});\n\nonMounted(() => {\n loadCollections();\n});\n</script>\n\n<template>\n <div class=\"icon-picker\">\n <el-popover\n v-model:visible=\"visible\"\n placement=\"bottom-start\"\n :width=\"600\"\n trigger=\"click\"\n :hide-after=\"0\"\n popper-class=\"icon-picker-popover\"\n @show=\"handleVisibleChange(true)\"\n >\n <template #reference>\n <el-input :model-value=\"currentIcon\" placeholder=\"选择图标\" readonly>\n <template #prefix>\n <Icon\n v-if=\"currentIcon\"\n :icon=\"currentIcon\"\n :width=\"20\"\n :height=\"20\"\n />\n <el-icon v-else>\n <component is=\"Grid\" />\n </el-icon>\n </template>\n <template #suffix>\n <el-icon\n v-if=\"currentIcon\"\n class=\"clear-icon\"\n @click.stop=\"clearIcon\"\n >\n <component is=\"CircleClose\" />\n </el-icon>\n </template>\n </el-input>\n </template>\n\n <!-- Popover 内容 -->\n <div class=\"picker-content\" @click.stop>\n <!-- 搜索和筛选 -->\n <div class=\"picker-header\">\n <el-select\n filterable\n v-model=\"selectedPrefix\"\n placeholder=\"选择图标集\"\n size=\"small\"\n style=\"width: 180px\"\n :loading=\"collectionsLoading\"\n :teleported=\"false\"\n >\n <el-option label=\"全部图标集\" value=\"all\" />\n <el-option\n v-for=\"collection in collections\"\n :key=\"collection.prefix\"\n :label=\"`${collection.name} (${collection.total || 0})`\"\n :value=\"collection.prefix\"\n />\n </el-select>\n\n <el-input\n v-model=\"searchQuery\"\n placeholder=\"搜索图标...\"\n size=\"small\"\n clearable\n style=\"flex: 1; margin-left: 8px\"\n >\n <template #prefix>\n <el-icon>\n <component is=\"Search\" />\n </el-icon>\n </template>\n </el-input>\n </div>\n\n <!-- 图标网格 -->\n <div\n ref=\"iconGridRef\"\n v-loading=\"loading && icons.length === 0\"\n class=\"icon-grid\"\n @scroll=\"handleScroll\"\n >\n <div\n v-for=\"icon in icons\"\n :key=\"icon\"\n class=\"icon-item\"\n :class=\"{ selected: currentIcon === icon }\"\n :title=\"icon\"\n @click=\"selectIcon(icon)\"\n >\n <div class=\"icon-wrapper\">\n <Icon :icon=\"icon\" :width=\"24\" :height=\"24\" />\n <span class=\"icon-name\">{{ getIconName(icon) }}</span>\n </div>\n </div>\n\n <!-- 加载更多提示 -->\n <div v-if=\"loadingMore\" class=\"loading-more\">\n <el-icon class=\"is-loading\"><component is=\"Loading\" /></el-icon>\n <span>加载更多...</span>\n </div>\n\n <div v-else-if=\"!hasMore && icons.length > 0\" class=\"no-more\">\n <el-text type=\"info\">已加载全部 {{ totalIcons }} 个图标</el-text>\n </div>\n\n <el-empty\n v-if=\"!loading && icons.length === 0\"\n description=\"未找到图标\"\n :image-size=\"60\"\n />\n </div>\n </div>\n </el-popover>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.icon-picker {\n width: 100%;\n\n .clear-icon {\n cursor: pointer;\n &:hover {\n color: var(--el-color-primary);\n }\n }\n}\n\n.picker-content {\n padding: 8px;\n}\n\n.picker-header {\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.icon-grid {\n display: grid;\n grid-template-columns: repeat(6, 1fr);\n gap: 8px;\n max-height: 400px;\n overflow-y: auto;\n padding: 8px;\n border: 1px solid var(--el-border-color-lighter);\n border-radius: 4px;\n background: var(--el-fill-color-blank);\n position: relative;\n\n .icon-item {\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border: 1px solid transparent;\n border-radius: 4px;\n transition: all 0.2s;\n padding: 8px 4px;\n min-height: 70px;\n\n .icon-wrapper {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 4px;\n width: 100%;\n\n .icon-name {\n font-size: 10px;\n color: var(--el-text-color-secondary);\n text-align: center;\n word-break: break-all;\n line-height: 1.2;\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n }\n\n &:hover {\n background: var(--el-fill-color-light);\n border-color: var(--el-color-primary-light-5);\n transform: scale(1.05);\n\n .icon-name {\n color: var(--el-text-color-primary);\n }\n }\n\n &.selected {\n background: var(--el-color-primary-light-9);\n border-color: var(--el-color-primary);\n\n .icon-name {\n color: var(--el-color-primary);\n font-weight: 500;\n }\n }\n }\n\n .loading-more,\n .no-more {\n grid-column: 1 / -1;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 16px;\n color: var(--el-text-color-secondary);\n }\n\n // 当为空时,el-empty 需要占据整个网格区域并居中\n &:has(.el-empty) {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n}\n\n.picker-footer {\n display: flex;\n justify-content: center;\n margin-top: 8px;\n padding-top: 8px;\n}\n</style>\n\n<style lang=\"scss\">\n.icon-picker-popover {\n padding: 12px !important;\n}\n</style>\n","import FormIconPicker from './FormIconPicker.vue';\nimport type { App } from 'vue';\n\n(FormIconPicker as any).name = 'FormIconPicker';\n\nFormIconPicker.install = (app: App) => {\n app.component('FormIconPicker', FormIconPicker);\n};\n\nexport { FormIconPicker };\n","<script setup lang=\"ts\">\r\nimport type { FormUploadProp } from '@/types';\r\nimport type { UploadFile, UploadRawFile } from 'element-plus';\r\n\r\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue';\r\n\r\nimport { Plus } from '@element-plus/icons-vue';\r\n\r\nimport { msgTips } from '@/utils';\r\n\r\nimport { useMittHook } from '../hooks/useMitt.hook';\r\n\r\ninterface Props {\r\n value?: string[];\r\n detail: FormUploadProp;\r\n mittId?: any;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n value: () => [],\r\n mittId: () => null,\r\n});\r\n\r\nconst emits = defineEmits([\r\n 'update:value',\r\n 'getComponentValue',\r\n 'valueChange',\r\n 'setShow',\r\n]);\r\n\r\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\r\nconst valueRef = defineModel<string[]>('value', { default: () => [] });\r\n\r\n/** 文件列表 */\r\nconst fileList = ref<UploadFile[]>([]);\r\n\r\n/** 图片预览 */\r\nconst previewVisible = ref(false);\r\nconst previewIndex = ref(0);\r\n\r\n/** 是否禁用 */\r\nconst isDisabled = computed(() => props.detail?.disabled ?? false);\r\n\r\n/** accept 属性,用于限制文件选择对话框的文件类型 */\r\nconst acceptTypes = computed(() => {\r\n if (props.detail?.fileType && props.detail.fileType.length > 0) {\r\n return props.detail.fileType.join(',');\r\n }\r\n return 'image/*';\r\n});\r\n\r\n/** 预览 URL 列表 */\r\nconst previewUrlList = computed(() => {\r\n return fileList.value\r\n .map((f) => f.url || '')\r\n .filter((url) => url.length > 0);\r\n});\r\n\r\n/** 将 URL 字符串数组转换为 UploadFile 数组 */\r\nconst urlsToFileList = (urls: string[]): UploadFile[] => {\r\n return urls\r\n .filter((url) => !!url)\r\n .map((url, index) => ({\r\n name: url.split('/').pop() || `image-${index}`,\r\n url,\r\n uid: Date.now() + index,\r\n status: 'success' as const,\r\n }));\r\n};\r\n\r\n/** 初始化:从 value 同步到 fileList */\r\nconst initFileList = () => {\r\n if (valueRef.value && valueRef.value.length > 0) {\r\n fileList.value = urlsToFileList(valueRef.value);\r\n }\r\n};\r\n\r\n/**\r\n * 从 fileList 同步到 value\r\n * 仅当数量发生变化时更新,避免与外部 watch 形成循环\r\n */\r\nconst syncValue = () => {\r\n const urls = fileList.value\r\n .filter((f) => f.status === 'success' || f.status === undefined)\r\n .map((f) => f.url || '')\r\n .filter((url) => url.length > 0);\r\n\r\n if (urls.length !== (valueRef.value?.length ?? 0)) {\r\n valueRef.value = urls;\r\n }\r\n};\r\n\r\n/** 文件上传前的校验 */\r\nconst beforeUpload = (rawFile: UploadRawFile): boolean => {\r\n // 校验文件类型\r\n if (props.detail?.fileType && props.detail.fileType.length > 0) {\r\n const isAllowed = props.detail.fileType.some((type) => {\r\n const ext = type.toLowerCase().replace('.', '');\r\n const fileName = rawFile.name.toLowerCase();\r\n const mimeType = rawFile.type.toLowerCase();\r\n return (\r\n fileName.endsWith(`.${ext}`) ||\r\n mimeType === type ||\r\n mimeType === `image/${ext}`\r\n );\r\n });\r\n\r\n if (!isAllowed) {\r\n const allowed = props.detail.fileType.join('、');\r\n msgTips.tips({ msg: `只能上传 ${allowed} 格式的文件`, type: 'warning' });\r\n return false;\r\n }\r\n }\r\n\r\n // 校验文件大小(通过 componentParams.maxSize 传入,单位 KB)\r\n if (props.detail?.componentParams?.maxSize) {\r\n const maxSize = props.detail.componentParams.maxSize * 1024;\r\n if (rawFile.size > maxSize) {\r\n msgTips.tips({\r\n msg: `文件大小不能超过 ${props.detail.componentParams.maxSize}KB`,\r\n type: 'warning',\r\n });\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n};\r\n\r\n/** 超出最大上传数量 */\r\nconst handleExceed = () => {\r\n msgTips.tips({ msg: `最多只能上传 ${props.detail.maxNumber} 张图片`, type: 'warning' });\r\n};\r\n\r\n/** 文件状态发生变化 */\r\nconst handleChange = () => {\r\n syncValue();\r\n};\r\n\r\n/** 移除文件 */\r\nconst handleRemove = () => {\r\n syncValue();\r\n};\r\n\r\n/** 上传成功回调 */\r\nconst handleSuccess = (response: any, uploadFile: UploadFile) => {\r\n // 尝试从响应中提取图片 URL\r\n let url = '';\r\n if (typeof response === 'string') {\r\n url = response;\r\n } else if (response?.data) {\r\n url = typeof response.data === 'string' ? response.data : response.data.url || '';\r\n } else if (response?.url) {\r\n url = response.url;\r\n }\r\n\r\n if (url) {\r\n uploadFile.url = url;\r\n }\r\n\r\n syncValue();\r\n};\r\n\r\n/** 上传失败回调 */\r\nconst handleError = () => {\r\n msgTips.tips({ msg: '图片上传失败', type: 'error' });\r\n syncValue();\r\n};\r\n\r\n/** 预览图片 */\r\nconst handlePreview = (uploadFile: UploadFile) => {\r\n const index = fileList.value.findIndex((f) => f.uid === uploadFile.uid);\r\n previewIndex.value = index >= 0 ? index : 0;\r\n previewVisible.value = true;\r\n};\r\n\r\n/** 设置值(mitt 广播回调使用) */\r\nconst setValue = (value: string[]) => {\r\n valueRef.value = value;\r\n fileList.value = urlsToFileList(value);\r\n};\r\n\r\n/** 接收广播消息 */\r\nconst receiveBroadcasts = (eventData: any) => {\r\n if (props.detail.noticeReceive) {\r\n props.detail.noticeReceive(eventData, setValue);\r\n }\r\n};\r\n\r\n/** 监听外部 value 变化(如表单重置) */\r\nwatch(\r\n () => valueRef.value,\r\n (newVal) => {\r\n if (!newVal || newVal.length === 0) {\r\n fileList.value = [];\r\n }\r\n },\r\n);\r\n\r\nonMounted(() => {\r\n registerMitt(receiveBroadcasts);\r\n initFileList();\r\n});\r\n\r\nonUnmounted(() => {\r\n offMitt();\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"form-image-upload\">\r\n <el-upload\r\n v-model:file-list=\"fileList\"\r\n :action=\"props.detail.uploadUrl\"\r\n :accept=\"acceptTypes\"\r\n list-type=\"picture-card\"\r\n :limit=\"props.detail.maxNumber\"\r\n :disabled=\"isDisabled\"\r\n :before-upload=\"beforeUpload\"\r\n :on-exceed=\"handleExceed\"\r\n :on-change=\"handleChange\"\r\n :on-remove=\"handleRemove\"\r\n :on-success=\"handleSuccess\"\r\n :on-error=\"handleError\"\r\n :on-preview=\"handlePreview\"\r\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\r\n >\r\n <el-icon><Plus /></el-icon>\r\n </el-upload>\r\n\r\n <el-image-viewer\r\n v-if=\"previewVisible\"\r\n :initial-index=\"previewIndex\"\r\n :url-list=\"previewUrlList\"\r\n @close=\"previewVisible = false\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.form-image-upload {\r\n :deep(.el-upload--picture-card) {\r\n width: 100px;\r\n height: 100px;\r\n }\r\n\r\n :deep(.el-upload-list--picture-card .el-upload-list__item) {\r\n width: 100px;\r\n height: 100px;\r\n }\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport type { FormUploadProp } from '@/types';\r\nimport type { UploadFile, UploadRawFile } from 'element-plus';\r\n\r\nimport { computed, onMounted, onUnmounted, ref, watch } from 'vue';\r\n\r\nimport { Plus } from '@element-plus/icons-vue';\r\n\r\nimport { msgTips } from '@/utils';\r\n\r\nimport { useMittHook } from '../hooks/useMitt.hook';\r\n\r\ninterface Props {\r\n value?: string[];\r\n detail: FormUploadProp;\r\n mittId?: any;\r\n}\r\n\r\nconst props = withDefaults(defineProps<Props>(), {\r\n value: () => [],\r\n mittId: () => null,\r\n});\r\n\r\nconst emits = defineEmits([\r\n 'update:value',\r\n 'getComponentValue',\r\n 'valueChange',\r\n 'setShow',\r\n]);\r\n\r\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\r\nconst valueRef = defineModel<string[]>('value', { default: () => [] });\r\n\r\n/** 文件列表 */\r\nconst fileList = ref<UploadFile[]>([]);\r\n\r\n/** 图片预览 */\r\nconst previewVisible = ref(false);\r\nconst previewIndex = ref(0);\r\n\r\n/** 是否禁用 */\r\nconst isDisabled = computed(() => props.detail?.disabled ?? false);\r\n\r\n/** accept 属性,用于限制文件选择对话框的文件类型 */\r\nconst acceptTypes = computed(() => {\r\n if (props.detail?.fileType && props.detail.fileType.length > 0) {\r\n return props.detail.fileType.join(',');\r\n }\r\n return 'image/*';\r\n});\r\n\r\n/** 预览 URL 列表 */\r\nconst previewUrlList = computed(() => {\r\n return fileList.value\r\n .map((f) => f.url || '')\r\n .filter((url) => url.length > 0);\r\n});\r\n\r\n/** 将 URL 字符串数组转换为 UploadFile 数组 */\r\nconst urlsToFileList = (urls: string[]): UploadFile[] => {\r\n return urls\r\n .filter((url) => !!url)\r\n .map((url, index) => ({\r\n name: url.split('/').pop() || `image-${index}`,\r\n url,\r\n uid: Date.now() + index,\r\n status: 'success' as const,\r\n }));\r\n};\r\n\r\n/** 初始化:从 value 同步到 fileList */\r\nconst initFileList = () => {\r\n if (valueRef.value && valueRef.value.length > 0) {\r\n fileList.value = urlsToFileList(valueRef.value);\r\n }\r\n};\r\n\r\n/**\r\n * 从 fileList 同步到 value\r\n * 仅当数量发生变化时更新,避免与外部 watch 形成循环\r\n */\r\nconst syncValue = () => {\r\n const urls = fileList.value\r\n .filter((f) => f.status === 'success' || f.status === undefined)\r\n .map((f) => f.url || '')\r\n .filter((url) => url.length > 0);\r\n\r\n if (urls.length !== (valueRef.value?.length ?? 0)) {\r\n valueRef.value = urls;\r\n }\r\n};\r\n\r\n/** 文件上传前的校验 */\r\nconst beforeUpload = (rawFile: UploadRawFile): boolean => {\r\n // 校验文件类型\r\n if (props.detail?.fileType && props.detail.fileType.length > 0) {\r\n const isAllowed = props.detail.fileType.some((type) => {\r\n const ext = type.toLowerCase().replace('.', '');\r\n const fileName = rawFile.name.toLowerCase();\r\n const mimeType = rawFile.type.toLowerCase();\r\n return (\r\n fileName.endsWith(`.${ext}`) ||\r\n mimeType === type ||\r\n mimeType === `image/${ext}`\r\n );\r\n });\r\n\r\n if (!isAllowed) {\r\n const allowed = props.detail.fileType.join('、');\r\n msgTips.tips({ msg: `只能上传 ${allowed} 格式的文件`, type: 'warning' });\r\n return false;\r\n }\r\n }\r\n\r\n // 校验文件大小(通过 componentParams.maxSize 传入,单位 KB)\r\n if (props.detail?.componentParams?.maxSize) {\r\n const maxSize = props.detail.componentParams.maxSize * 1024;\r\n if (rawFile.size > maxSize) {\r\n msgTips.tips({\r\n msg: `文件大小不能超过 ${props.detail.componentParams.maxSize}KB`,\r\n type: 'warning',\r\n });\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n};\r\n\r\n/** 超出最大上传数量 */\r\nconst handleExceed = () => {\r\n msgTips.tips({ msg: `最多只能上传 ${props.detail.maxNumber} 张图片`, type: 'warning' });\r\n};\r\n\r\n/** 文件状态发生变化 */\r\nconst handleChange = () => {\r\n syncValue();\r\n};\r\n\r\n/** 移除文件 */\r\nconst handleRemove = () => {\r\n syncValue();\r\n};\r\n\r\n/** 上传成功回调 */\r\nconst handleSuccess = (response: any, uploadFile: UploadFile) => {\r\n // 尝试从响应中提取图片 URL\r\n let url = '';\r\n if (typeof response === 'string') {\r\n url = response;\r\n } else if (response?.data) {\r\n url = typeof response.data === 'string' ? response.data : response.data.url || '';\r\n } else if (response?.url) {\r\n url = response.url;\r\n }\r\n\r\n if (url) {\r\n uploadFile.url = url;\r\n }\r\n\r\n syncValue();\r\n};\r\n\r\n/** 上传失败回调 */\r\nconst handleError = () => {\r\n msgTips.tips({ msg: '图片上传失败', type: 'error' });\r\n syncValue();\r\n};\r\n\r\n/** 预览图片 */\r\nconst handlePreview = (uploadFile: UploadFile) => {\r\n const index = fileList.value.findIndex((f) => f.uid === uploadFile.uid);\r\n previewIndex.value = index >= 0 ? index : 0;\r\n previewVisible.value = true;\r\n};\r\n\r\n/** 设置值(mitt 广播回调使用) */\r\nconst setValue = (value: string[]) => {\r\n valueRef.value = value;\r\n fileList.value = urlsToFileList(value);\r\n};\r\n\r\n/** 接收广播消息 */\r\nconst receiveBroadcasts = (eventData: any) => {\r\n if (props.detail.noticeReceive) {\r\n props.detail.noticeReceive(eventData, setValue);\r\n }\r\n};\r\n\r\n/** 监听外部 value 变化(如表单重置) */\r\nwatch(\r\n () => valueRef.value,\r\n (newVal) => {\r\n if (!newVal || newVal.length === 0) {\r\n fileList.value = [];\r\n }\r\n },\r\n);\r\n\r\nonMounted(() => {\r\n registerMitt(receiveBroadcasts);\r\n initFileList();\r\n});\r\n\r\nonUnmounted(() => {\r\n offMitt();\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"form-image-upload\">\r\n <el-upload\r\n v-model:file-list=\"fileList\"\r\n :action=\"props.detail.uploadUrl\"\r\n :accept=\"acceptTypes\"\r\n list-type=\"picture-card\"\r\n :limit=\"props.detail.maxNumber\"\r\n :disabled=\"isDisabled\"\r\n :before-upload=\"beforeUpload\"\r\n :on-exceed=\"handleExceed\"\r\n :on-change=\"handleChange\"\r\n :on-remove=\"handleRemove\"\r\n :on-success=\"handleSuccess\"\r\n :on-error=\"handleError\"\r\n :on-preview=\"handlePreview\"\r\n v-bind=\"props.detail?.componentParams ? props.detail.componentParams : {}\"\r\n >\r\n <el-icon><Plus /></el-icon>\r\n </el-upload>\r\n\r\n <el-image-viewer\r\n v-if=\"previewVisible\"\r\n :initial-index=\"previewIndex\"\r\n :url-list=\"previewUrlList\"\r\n @close=\"previewVisible = false\"\r\n />\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.form-image-upload {\r\n :deep(.el-upload--picture-card) {\r\n width: 100px;\r\n height: 100px;\r\n }\r\n\r\n :deep(.el-upload-list--picture-card .el-upload-list__item) {\r\n width: 100px;\r\n height: 100px;\r\n }\r\n}\r\n</style>\r\n","import FormImageUpload from './FormImageUpload.vue';\nimport type { App } from 'vue';\n\n(FormImageUpload as any).name = 'FormImageUpload';\n\nFormImageUpload.install = (app: App) => {\n app.component('FormImageUpload', FormImageUpload);\n};\n\nexport { FormImageUpload };\n","import * as monaco from 'monaco-editor';\n\nlet initialized = false;\nlet disposable: monaco.IDisposable | null = null;\n\nexport async function initVueLanguageSupport() {\n if (initialized) return;\n initialized = true;\n\n try {\n // 检查是否已注册\n const languages = monaco.languages.getLanguages();\n const vueRegistered = languages.some(l => l.id === 'vue');\n \n if (!vueRegistered) {\n monaco.languages.register({ id: 'vue', extensions: ['.vue'] });\n }\n\n monaco.languages.setLanguageConfiguration('vue', {\n comments: { blockComment: ['<!--', '-->'] },\n brackets: [['{', '}'], ['(', ')'], ['[', ']']],\n autoClosingPairs: [\n { open: '{', close: '}' }, { open: '[', close: ']' }, { open: '(', close: ')' },\n { open: '\"', close: '\"' }, { open: \"'\", close: \"'\" }, { open: '`', close: '`' },\n ],\n });\n\n monaco.languages.setMonarchTokensProvider('vue', createVueLanguage());\n \n // 先销毁旧的,再注册新的\n if (disposable) {\n disposable.dispose();\n }\n disposable = registerVueCompletion();\n \n defineVueThemes();\n } catch (e) {\n console.error('[Vue] init failed:', e);\n }\n}\n\nfunction defineVueThemes() {\n monaco.editor.defineTheme('vue-dark', {\n base: 'vs-dark',\n inherit: true,\n rules: [\n { token: 'tag', foreground: '569CD6', fontStyle: 'bold' },\n { token: 'attribute.name', foreground: '9CDCFE' },\n { token: 'attribute.value', foreground: 'CE9178' },\n { token: 'metatag', foreground: 'C586C0' },\n { token: 'delimiter.html', foreground: '808080' },\n { token: 'delimiter.bracket', foreground: 'FFD700' },\n { token: 'keyword', foreground: '569CD6' },\n { token: 'keyword.control', foreground: 'C586C0' },\n { token: 'string', foreground: 'CE9178' },\n { token: 'number', foreground: 'B5CEA8' },\n { token: 'comment', foreground: '6A9955' },\n { token: 'type', foreground: '4EC9B0' },\n { token: 'identifier', foreground: '9CDCFE' },\n { token: 'variable', foreground: '9CDCFE' },\n { token: 'function', foreground: 'DCDCAA' }, // 黄色 - 函数\n ],\n colors: {},\n });\n\n monaco.editor.defineTheme('vue-light', {\n base: 'vs',\n inherit: true,\n rules: [\n { token: 'tag', foreground: '800000', fontStyle: 'bold' },\n { token: 'attribute.name', foreground: 'E50000' },\n { token: 'attribute.value', foreground: '0000FF' },\n { token: 'metatag', foreground: 'AF00DB' },\n { token: 'delimiter.html', foreground: '800000' },\n { token: 'delimiter.bracket', foreground: 'AF00DB' },\n { token: 'keyword', foreground: '0000FF' },\n { token: 'keyword.control', foreground: 'AF00DB' },\n { token: 'string', foreground: 'A31515' },\n { token: 'number', foreground: '098658' },\n { token: 'comment', foreground: '008000' },\n { token: 'type', foreground: '267F99' },\n { token: 'identifier', foreground: '001080' },\n { token: 'variable', foreground: '001080' },\n { token: 'function', foreground: '795E26' }, // 棕黄色 - 函数\n ],\n colors: {},\n });\n}\n\n\nfunction createVueLanguage(): monaco.languages.IMonarchLanguage {\n return {\n defaultToken: '',\n ignoreCase: false,\n\n // 关键字定义\n keywords: ['import', 'export', 'from', 'default', 'const', 'let', 'var', 'function', 'class', 'extends', 'new', 'this', 'async', 'await', 'typeof', 'instanceof', 'interface', 'type', 'as'],\n controlKeywords: ['if', 'else', 'for', 'while', 'switch', 'case', 'break', 'continue', 'return', 'throw', 'try', 'catch', 'finally'],\n constants: ['true', 'false', 'null', 'undefined'],\n vueApis: [\n // 响应式核心\n 'ref', 'reactive', 'readonly', 'computed', 'shallowRef', 'shallowReactive', 'shallowReadonly',\n // 响应式工具\n 'toRef', 'toRefs', 'toValue', 'toRaw', 'unref', 'isRef', 'isReactive', 'isReadonly', 'isProxy',\n 'markRaw', 'triggerRef', 'customRef', 'effectScope', 'getCurrentScope', 'onScopeDispose',\n // 侦听器\n 'watch', 'watchEffect', 'watchPostEffect', 'watchSyncEffect',\n // 生命周期\n 'onMounted', 'onUpdated', 'onUnmounted', 'onBeforeMount', 'onBeforeUpdate', 'onBeforeUnmount',\n 'onActivated', 'onDeactivated', 'onErrorCaptured', 'onRenderTracked', 'onRenderTriggered', 'onServerPrefetch',\n // 依赖注入\n 'provide', 'inject', 'hasInjectionContext',\n // 组件定义\n 'defineProps', 'defineEmits', 'defineExpose', 'defineOptions', 'defineModel', 'defineSlots', 'withDefaults',\n // 其他\n 'nextTick', 'useSlots', 'useAttrs', 'useCssModule', 'useCssVars', 'useId', 'useModel', 'useTemplateRef',\n 'getCurrentInstance', 'h', 'createApp', 'defineComponent', 'defineAsyncComponent', 'resolveComponent',\n ],\n typeKeywords: ['any', 'boolean', 'number', 'string', 'void', 'never', 'Array', 'Object', 'Ref', 'PropType'],\n\n tokenizer: {\n // 根状态\n root: [\n [/<!--/, 'comment', '@comment'],\n [/(<)(script)/, ['delimiter.html', { token: 'tag', next: '@script' }]],\n [/(<)(style)/, ['delimiter.html', { token: 'tag', next: '@style' }]],\n [/(<)(template)/, ['delimiter.html', { token: 'tag', next: '@templateTag' }]],\n { include: '@templateContent' },\n ],\n\n comment: [[/-->/, 'comment', '@pop'], [/./, 'comment']],\n\n // script 标签\n script: [\n [/\\s+/, ''],\n [/setup/, 'metatag'],\n [/lang/, 'attribute.name'],\n [/=/, 'delimiter'],\n [/\"[^\"]*\"|'[^']*'/, 'attribute.value'],\n [/>/, { token: 'delimiter.html', next: '@scriptBody' }],\n ],\n scriptBody: [\n [/(<\\/)(script)\\s*(>)/, ['delimiter.html', 'tag', { token: 'delimiter.html', next: '@popall' }]],\n { include: '@jsCode' },\n ],\n\n // style 标签\n style: [\n [/\\s+/, ''],\n [/scoped|module/, 'metatag'],\n [/lang/, 'attribute.name'],\n [/=/, 'delimiter'],\n [/\"[^\"]*\"|'[^']*'/, 'attribute.value'],\n [/>/, { token: 'delimiter.html', next: '@styleBody' }],\n ],\n styleBody: [\n [/(<\\/)(style)\\s*(>)/, ['delimiter.html', 'tag', { token: 'delimiter.html', next: '@popall' }]],\n [/[^<]+/, ''],\n ],\n\n // template 标签属性\n templateTag: [\n [/\\s+/, ''],\n [/lang/, 'attribute.name'],\n [/=/, 'delimiter'],\n [/\"[^\"]*\"|'[^']*'/, 'attribute.value'],\n [/>/, { token: 'delimiter.html', next: '@templateBody' }],\n ],\n templateBody: [\n [/(<\\/)(template)\\s*(>)/, ['delimiter.html', 'tag', { token: 'delimiter.html', next: '@popall' }]],\n { include: '@templateContent' },\n ],\n\n // template 内容(HTML + Vue)\n templateContent: [\n [/<!--/, 'comment', '@comment'],\n // 开始标签\n [/<[\\w-]+/, { token: 'tag', next: '@tag' }],\n // 结束标签\n [/<\\/[\\w-]+\\s*>/, 'tag'],\n // 插值\n [/\\{\\{/, { token: 'delimiter.bracket', next: '@interpolation' }],\n // 文本\n [/[^<{]+/, ''],\n ],\n\n // HTML 标签属性\n tag: [\n [/\\s+/, ''],\n // Vue 指令(紫色)- v-bind:xxx, v-on:xxx 等\n [/(v-[\\w]+)(:)([\\w.-]+)/, ['metatag', 'delimiter', 'metatag']],\n [/v-[\\w-]+/, 'metatag'],\n // @ 事件简写(紫色)\n [/(@)([\\w.-]+)/, ['metatag', 'metatag']],\n // : 绑定简写(紫色)\n [/(:)([\\w.-]+)/, ['metatag', 'metatag']],\n // # 插槽简写(紫色)\n [/(#)([\\w.-]+)/, ['metatag', 'metatag']],\n // 普通属性\n [/[\\w-]+(?=\\s*=)/, 'attribute.name'],\n [/[\\w-]+/, 'attribute.name'],\n [/=/, 'delimiter'],\n // 属性值 - 绑定属性使用 JS 表达式高亮\n [/\"/, { token: 'string', next: '@attrValueDQ' }],\n [/'/, { token: 'string', next: '@attrValueSQ' }],\n // 标签结束\n [/\\/?>/, { token: 'delimiter.html', next: '@pop' }],\n ],\n\n // 双引号属性值(包含 JS 表达式)\n attrValueDQ: [\n [/\\{\\{/, { token: 'delimiter.bracket', next: '@interpolation' }],\n // JS 表达式内容\n [/[a-zA-Z_$][\\w$]*/, {\n cases: {\n '@controlKeywords': 'keyword.control',\n '@constants': 'keyword',\n '@vueApis': 'function',\n '@keywords': 'keyword',\n '@default': 'variable',\n },\n }],\n [/\\d+(\\.\\d+)?/, 'number'],\n [/[=!<>?:&|+\\-*/]+/, 'delimiter'],\n [/[()[\\].,]/, 'delimiter'],\n [/'[^']*'/, 'string'],\n [/\"/, { token: 'string', next: '@pop' }],\n [/[^\"]+/, 'variable'],\n ],\n // 单引号属性值\n attrValueSQ: [\n [/\\{\\{/, { token: 'delimiter.bracket', next: '@interpolation' }],\n [/[a-zA-Z_$][\\w$]*/, {\n cases: {\n '@controlKeywords': 'keyword.control',\n '@constants': 'keyword',\n '@vueApis': 'function',\n '@keywords': 'keyword',\n '@default': 'variable',\n },\n }],\n [/\\d+(\\.\\d+)?/, 'number'],\n [/[=!<>?:&|+\\-*/]+/, 'delimiter'],\n [/[()[\\].,]/, 'delimiter'],\n [/\"[^\"]*\"/, 'string'],\n [/'/, { token: 'string', next: '@pop' }],\n [/[^']+/, 'variable'],\n ],\n\n // 插值表达式\n interpolation: [\n [/\\}\\}/, { token: 'delimiter.bracket', next: '@pop' }],\n { include: '@jsExpr' },\n ],\n\n // JS 表达式(简化版)\n jsExpr: [\n [/\\s+/, ''],\n [/'[^']*'|\"[^\"]*\"/, 'string'],\n [/\\d+(\\.\\d+)?/, 'number'],\n [/[a-zA-Z_$][\\w$]*/, {\n cases: {\n '@controlKeywords': 'keyword.control',\n '@constants': 'keyword',\n '@vueApis': 'function',\n '@keywords': 'keyword',\n '@default': 'identifier',\n },\n }],\n [/[=!<>?:&|+\\-*/]+/, 'delimiter'],\n [/[{}()[\\].,;]/, 'delimiter'],\n ],\n\n // JS 完整代码\n jsCode: [\n [/\\s+/, ''],\n [/\\/\\/.*$/, 'comment'],\n [/\\/\\*/, 'comment', '@jsComment'],\n [/'([^'\\\\]|\\\\.)*'/, 'string'],\n [/\"([^\"\\\\]|\\\\.)*\"/, 'string'],\n [/`/, 'string', '@templateStr'],\n [/\\d+(\\.\\d+)?/, 'number'],\n [/[a-zA-Z_$][\\w$]*/, {\n cases: {\n '@controlKeywords': 'keyword.control',\n '@constants': 'keyword',\n '@vueApis': 'function',\n '@keywords': 'keyword',\n '@typeKeywords': 'type',\n '@default': 'identifier',\n },\n }],\n [/[=!<>?:&|+\\-*/]+/, 'delimiter'],\n [/[{}()[\\].,;]/, 'delimiter'],\n ],\n jsComment: [[/\\*\\//, 'comment', '@pop'], [/./, 'comment']],\n templateStr: [\n [/\\$\\{/, { token: 'delimiter', next: '@templateExpr' }],\n [/`/, 'string', '@pop'],\n [/./, 'string'],\n ],\n templateExpr: [[/\\}/, { token: 'delimiter', next: '@pop' }], { include: '@jsExpr' }],\n },\n };\n}\n\n\nfunction registerVueCompletion(): monaco.IDisposable {\n return monaco.languages.registerCompletionItemProvider('vue', {\n triggerCharacters: ['<', '.', '@', ':', '-', 'v'],\n provideCompletionItems: (model, position) => {\n const word = model.getWordUntilPosition(position);\n const line = model.getLineContent(position.lineNumber);\n const before = line.substring(0, position.column - 1);\n const suggestions: monaco.languages.CompletionItem[] = [];\n \n // 判断是否在 script 区域内\n const fullText = model.getValue();\n const offset = model.getOffsetAt(position);\n const textBefore = fullText.substring(0, offset);\n const scriptStart = textBefore.lastIndexOf('<script');\n const scriptEnd = textBefore.lastIndexOf('</script');\n const isInScript = scriptStart > -1 && (scriptEnd === -1 || scriptEnd < scriptStart);\n \n // 判断是否在 template 标签属性区域(在 < 之后,> 之前)\n const lastOpenTag = before.lastIndexOf('<');\n const lastCloseTag = before.lastIndexOf('>');\n const isInTagAttr = lastOpenTag > lastCloseTag && !before.substring(lastOpenTag).includes('</');\n \n // 当前输入的单词(用于过滤)\n const currentWord = word.word.toLowerCase();\n\n // Vue 指令 - 在标签属性区域输入 v 或 v- 时触发\n const vueDirectiveMatch = /\\s(v-?)([\\w-]*)$/.exec(before + word.word);\n if (isInTagAttr && vueDirectiveMatch) {\n const prefix = vueDirectiveMatch[1] || '';\n const typed = vueDirectiveMatch[2]?.toLowerCase() || '';\n // range 需要包含 v 或 v- 前缀\n const vIndex = before.lastIndexOf(prefix.startsWith('v-') ? 'v-' : ' v');\n const startCol = prefix.startsWith('v-') ? vIndex + 1 : vIndex + 2;\n const directiveRange = {\n startLineNumber: position.lineNumber,\n endLineNumber: position.lineNumber,\n startColumn: startCol,\n endColumn: position.column,\n };\n const items: [string, string, string][] = [\n ['v-if', '条件渲染', 'v-if=\"$1\"'],\n ['v-else-if', '条件渲染', 'v-else-if=\"$1\"'],\n ['v-else', '条件渲染', 'v-else'],\n ['v-for', '列表渲染', 'v-for=\"$1 in $2\" :key=\"$3\"'],\n ['v-show', '显示隐藏', 'v-show=\"$1\"'],\n ['v-model', '双向绑定', 'v-model=\"$1\"'],\n ['v-model.number', '数字双向绑定', 'v-model.number=\"$1\"'],\n ['v-model.trim', '去空格双向绑定', 'v-model.trim=\"$1\"'],\n ['v-model.lazy', '懒更新双向绑定', 'v-model.lazy=\"$1\"'],\n ['v-bind', '属性绑定', 'v-bind:$1=\"$2\"'],\n ['v-on', '事件绑定', 'v-on:$1=\"$2\"'],\n ['v-slot', '插槽', 'v-slot:$1'],\n ['v-html', 'HTML内容', 'v-html=\"$1\"'],\n ['v-text', '文本内容', 'v-text=\"$1\"'],\n ['v-pre', '跳过编译', 'v-pre'],\n ['v-once', '只渲染一次', 'v-once'],\n ['v-memo', '缓存模板', 'v-memo=\"[$1]\"'],\n ['v-cloak', '隐藏未编译', 'v-cloak'],\n ];\n const filterText = prefix + typed;\n items.filter(([label]) => label.toLowerCase().startsWith(filterText) || label.toLowerCase().includes(filterText)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range: directiveRange, kind: monaco.languages.CompletionItemKind.Keyword, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // 默认 range\n const range = {\n startLineNumber: position.lineNumber,\n endLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endColumn: word.endColumn,\n };\n\n // @ 事件简写 - 匹配 @ 开头\n const eventMatch = /@([\\w.-]*)$/.exec(before + word.word);\n if (eventMatch) {\n const typed = eventMatch[1]?.toLowerCase() || '';\n const atIndex = before.lastIndexOf('@');\n const eventRange = {\n startLineNumber: position.lineNumber,\n endLineNumber: position.lineNumber,\n startColumn: atIndex + 1,\n endColumn: position.column,\n };\n const events: [string, string, string][] = [\n ['@click', '点击事件', '@click=\"$1\"'],\n ['@click.stop', '点击(阻止冒泡)', '@click.stop=\"$1\"'],\n ['@click.prevent', '点击(阻止默认)', '@click.prevent=\"$1\"'],\n ['@dblclick', '双击事件', '@dblclick=\"$1\"'],\n ['@change', '变更事件', '@change=\"$1\"'],\n ['@input', '输入事件', '@input=\"$1\"'],\n ['@submit', '提交事件', '@submit.prevent=\"$1\"'],\n ['@keyup', '键盘抬起', '@keyup=\"$1\"'],\n ['@keyup.enter', '回车键', '@keyup.enter=\"$1\"'],\n ['@keydown', '键盘按下', '@keydown=\"$1\"'],\n ['@focus', '获得焦点', '@focus=\"$1\"'],\n ['@blur', '失去焦点', '@blur=\"$1\"'],\n ['@mouseenter', '鼠标进入', '@mouseenter=\"$1\"'],\n ['@mouseleave', '鼠标离开', '@mouseleave=\"$1\"'],\n ];\n events.filter(([label]) => typed.length === 0 || label.toLowerCase().includes('@' + typed)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range: eventRange, kind: monaco.languages.CompletionItemKind.Event, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // Vue 3 Composition API - 只在 script 区域,输入 1 个字符即可触发\n if (isInScript && currentWord.length >= 1) {\n const apis: [string, string, string][] = [\n // 响应式核心\n ['ref', '创建响应式引用', 'ref($1)'],\n ['reactive', '创建响应式对象', 'reactive({$1})'],\n ['readonly', '创建只读代理', 'readonly($1)'],\n ['computed', '创建计算属性', 'computed(() => $1)'],\n ['computed get/set', '可写计算属性', 'computed({\\n get: () => $1,\\n set: (val) => {\\n $2\\n }\\n})'],\n // 响应式工具\n ['toRef', '转换为ref', 'toRef($1, \"$2\")'],\n ['toRefs', '转换为refs', 'toRefs($1)'],\n ['toValue', '获取值', 'toValue($1)'],\n ['toRaw', '获取原始对象', 'toRaw($1)'],\n ['unref', '解包ref', 'unref($1)'],\n ['isRef', '判断是否ref', 'isRef($1)'],\n ['isReactive', '判断是否reactive', 'isReactive($1)'],\n ['isReadonly', '判断是否readonly', 'isReadonly($1)'],\n ['isProxy', '判断是否代理', 'isProxy($1)'],\n // 浅层响应式\n ['shallowRef', '浅层响应式引用', 'shallowRef($1)'],\n ['shallowReactive', '浅层响应式对象', 'shallowReactive({$1})'],\n ['shallowReadonly', '浅层只读', 'shallowReadonly($1)'],\n ['triggerRef', '手动触发ref', 'triggerRef($1)'],\n ['customRef', '自定义ref', 'customRef((track, trigger) => ({\\n get() {\\n track();\\n return $1;\\n },\\n set(val) {\\n $2\\n trigger();\\n }\\n}))'],\n // 侦听器\n ['watch', '侦听响应式数据', 'watch($1, (newVal, oldVal) => {\\n $2\\n})'],\n ['watch immediate', '立即执行侦听', 'watch($1, (newVal, oldVal) => {\\n $2\\n}, { immediate: true })'],\n ['watch deep', '深度侦听', 'watch($1, (newVal, oldVal) => {\\n $2\\n}, { deep: true })'],\n ['watchEffect', '副作用侦听', 'watchEffect(() => {\\n $1\\n})'],\n ['watchPostEffect', 'DOM更新后执行', 'watchPostEffect(() => {\\n $1\\n})'],\n ['watchSyncEffect', '同步执行', 'watchSyncEffect(() => {\\n $1\\n})'],\n // 生命周期\n ['onMounted', '挂载后', 'onMounted(() => {\\n $1\\n})'],\n ['onUpdated', '更新后', 'onUpdated(() => {\\n $1\\n})'],\n ['onUnmounted', '卸载后', 'onUnmounted(() => {\\n $1\\n})'],\n ['onBeforeMount', '挂载前', 'onBeforeMount(() => {\\n $1\\n})'],\n ['onBeforeUpdate', '更新前', 'onBeforeUpdate(() => {\\n $1\\n})'],\n ['onBeforeUnmount', '卸载前', 'onBeforeUnmount(() => {\\n $1\\n})'],\n ['onActivated', 'keep-alive激活', 'onActivated(() => {\\n $1\\n})'],\n ['onDeactivated', 'keep-alive停用', 'onDeactivated(() => {\\n $1\\n})'],\n ['onErrorCaptured', '错误捕获', 'onErrorCaptured((err, instance, info) => {\\n $1\\n})'],\n // 依赖注入\n ['provide', '提供依赖', \"provide('$1', $2)\"],\n ['inject', '注入依赖', \"inject('$1')\"],\n ['inject default', '带默认值注入', \"inject('$1', $2)\"],\n // 组件定义\n ['defineProps', '定义props', 'defineProps<{\\n $1\\n}>()'],\n ['defineProps runtime', '运行时props', 'defineProps({\\n $1: {\\n type: $2,\\n required: $3\\n }\\n})'],\n ['defineEmits', '定义emits', \"defineEmits<{\\n (e: '$1', $2): void\\n}>()\"],\n ['defineExpose', '暴露属性', 'defineExpose({\\n $1\\n})'],\n ['defineOptions', '定义选项', 'defineOptions({\\n name: \"$1\"\\n})'],\n ['defineModel', '定义model', 'defineModel<$1>()'],\n ['defineSlots', '定义slots类型', 'defineSlots<{\\n default(props: { $1 }): any\\n}>()'],\n ['withDefaults', '设置默认值', 'withDefaults(defineProps<{\\n $1\\n}>(), {\\n $2\\n})'],\n // 其他\n ['nextTick', '下一tick执行', 'nextTick(() => {\\n $1\\n})'],\n ['useSlots', '获取slots', 'useSlots()'],\n ['useAttrs', '获取attrs', 'useAttrs()'],\n ['useCssModule', '获取CSS模块', 'useCssModule()'],\n ['effectScope', '创建effect作用域', 'effectScope()'],\n ['getCurrentInstance', '获取组件实例', 'getCurrentInstance()'],\n ];\n apis.filter(([label]) => label.toLowerCase().includes(currentWord)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.Function, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // HTML 标签补全\n if (before.endsWith('<') || /^<\\w*$/.test(word.word)) {\n const htmlTags: [string, string, string][] = [\n ['div', 'div容器', 'div$1>$2</div>'],\n ['span', 'span行内', 'span$1>$2</span>'],\n ['p', '段落', 'p>$1</p>'],\n ['a', '链接', 'a href=\"$1\">$2</a>'],\n ['img', '图片', 'img src=\"$1\" alt=\"$2\" />'],\n ['ul', '无序列表', 'ul>\\n <li>$1</li>\\n</ul>'],\n ['ol', '有序列表', 'ol>\\n <li>$1</li>\\n</ol>'],\n ['li', '列表项', 'li>$1</li>'],\n ['table', '表格', 'table>\\n <thead>\\n <tr>\\n <th>$1</th>\\n </tr>\\n </thead>\\n <tbody>\\n <tr>\\n <td>$2</td>\\n </tr>\\n </tbody>\\n</table>'],\n ['form', '表单', 'form @submit.prevent=\"$1\">\\n $2\\n</form>'],\n ['input', '输入框', 'input type=\"$1\" v-model=\"$2\" />'],\n ['button', '按钮', 'button @click=\"$1\">$2</button>'],\n ['textarea', '文本域', 'textarea v-model=\"$1\"></textarea>'],\n ['select', '下拉框', 'select v-model=\"$1\">\\n <option value=\"$2\">$3</option>\\n</select>'],\n ['template', 'template块', 'template>\\n $1\\n</template>'],\n ['script setup', 'script setup', 'script setup lang=\"ts\">\\n$1\\n</script>'],\n ['style scoped', 'scoped样式', 'style scoped lang=\"scss\">\\n$1\\n</style>'],\n ];\n\n // Element Plus 组件\n const elComponents: [string, string, string][] = [\n ['el-button', 'Element按钮', 'el-button type=\"$1\">$2</el-button>'],\n ['el-input', 'Element输入框', 'el-input v-model=\"$1\" placeholder=\"$2\" />'],\n ['el-select', 'Element下拉框', 'el-select v-model=\"$1\">\\n <el-option label=\"$2\" value=\"$3\" />\\n</el-select>'],\n ['el-form', 'Element表单', 'el-form :model=\"$1\" :rules=\"$2\" ref=\"formRef\">\\n <el-form-item label=\"$3\" prop=\"$4\">\\n $5\\n </el-form-item>\\n</el-form>'],\n ['el-form-item', 'Element表单项', 'el-form-item label=\"$1\" prop=\"$2\">\\n $3\\n</el-form-item>'],\n ['el-table', 'Element表格', 'el-table :data=\"$1\">\\n <el-table-column prop=\"$2\" label=\"$3\" />\\n</el-table>'],\n ['el-table-column', 'Element表格列', 'el-table-column prop=\"$1\" label=\"$2\" />'],\n ['el-dialog', 'Element对话框', 'el-dialog v-model=\"$1\" title=\"$2\">\\n $3\\n</el-dialog>'],\n ['el-row', 'Element行', 'el-row :gutter=\"$1\">\\n <el-col :span=\"$2\">$3</el-col>\\n</el-row>'],\n ['el-col', 'Element列', 'el-col :span=\"$1\">$2</el-col>'],\n ['el-card', 'Element卡片', 'el-card>\\n <template #header>$1</template>\\n $2\\n</el-card>'],\n ['el-tabs', 'Element标签页', 'el-tabs v-model=\"$1\">\\n <el-tab-pane label=\"$2\" name=\"$3\">$4</el-tab-pane>\\n</el-tabs>'],\n ['el-pagination', 'Element分页', 'el-pagination\\n v-model:current-page=\"$1\"\\n v-model:page-size=\"$2\"\\n :total=\"$3\"\\n @current-change=\"$4\"\\n/>'],\n ['el-tag', 'Element标签', 'el-tag type=\"$1\">$2</el-tag>'],\n ['el-switch', 'Element开关', 'el-switch v-model=\"$1\" />'],\n ['el-checkbox', 'Element复选框', 'el-checkbox v-model=\"$1\">$2</el-checkbox>'],\n ['el-radio', 'Element单选框', 'el-radio v-model=\"$1\" label=\"$2\">$3</el-radio>'],\n ['el-date-picker', 'Element日期选择', 'el-date-picker v-model=\"$1\" type=\"$2\" placeholder=\"$3\" />'],\n ['el-upload', 'Element上传', 'el-upload\\n action=\"$1\"\\n :on-success=\"$2\"\\n>\\n <el-button>上传</el-button>\\n</el-upload>'],\n ['el-tree', 'Element树', 'el-tree :data=\"$1\" :props=\"$2\" />'],\n ['el-icon', 'Element图标', 'el-icon><$1 /></el-icon>'],\n ['el-tooltip', 'Element提示', 'el-tooltip content=\"$1\">\\n $2\\n</el-tooltip>'],\n ['el-popover', 'Element弹出框', 'el-popover trigger=\"$1\">\\n <template #reference>$2</template>\\n $3\\n</el-popover>'],\n ['el-drawer', 'Element抽屉', 'el-drawer v-model=\"$1\" title=\"$2\">\\n $3\\n</el-drawer>'],\n ['el-dropdown', 'Element下拉菜单', 'el-dropdown>\\n <span>$1</span>\\n <template #dropdown>\\n <el-dropdown-menu>\\n <el-dropdown-item>$2</el-dropdown-item>\\n </el-dropdown-menu>\\n </template>\\n</el-dropdown>'],\n ['el-menu', 'Element菜单', 'el-menu :default-active=\"$1\">\\n <el-menu-item index=\"$2\">$3</el-menu-item>\\n</el-menu>'],\n ['el-breadcrumb', 'Element面包屑', 'el-breadcrumb>\\n <el-breadcrumb-item :to=\"{ path: \\'$1\\' }\">$2</el-breadcrumb-item>\\n</el-breadcrumb>'],\n ['el-steps', 'Element步骤条', 'el-steps :active=\"$1\">\\n <el-step title=\"$2\" />\\n</el-steps>'],\n ['el-alert', 'Element警告', 'el-alert title=\"$1\" type=\"$2\" />'],\n ['el-loading', 'Element加载', 'el-loading v-loading=\"$1\" />'],\n ['el-empty', 'Element空状态', 'el-empty description=\"$1\" />'],\n ['el-result', 'Element结果', 'el-result icon=\"$1\" title=\"$2\" sub-title=\"$3\" />'],\n ['el-skeleton', 'Element骨架屏', 'el-skeleton :loading=\"$1\">\\n $2\\n</el-skeleton>'],\n ['el-image', 'Element图片', 'el-image :src=\"$1\" fit=\"$2\" />'],\n ['el-avatar', 'Element头像', 'el-avatar :src=\"$1\" />'],\n ['el-badge', 'Element徽章', 'el-badge :value=\"$1\">\\n $2\\n</el-badge>'],\n ['el-progress', 'Element进度条', 'el-progress :percentage=\"$1\" />'],\n ['el-divider', 'Element分割线', 'el-divider>$1</el-divider>'],\n ['el-space', 'Element间距', 'el-space>\\n $1\\n</el-space>'],\n ['el-scrollbar', 'Element滚动条', 'el-scrollbar height=\"$1\">\\n $2\\n</el-scrollbar>'],\n ];\n\n [...htmlTags, ...elComponents].forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.Snippet, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // import 语句\n if (/^import\\s*$/.test(before) || /^import\\s+\\{?\\s*$/.test(before)) {\n const imports: [string, string, string][] = [\n ['import vue', 'Vue核心导入', \"import { ref, reactive, computed, watch, onMounted } from 'vue';\"],\n ['import ref', '导入ref', \"import { ref } from 'vue';\"],\n ['import reactive', '导入reactive', \"import { reactive } from 'vue';\"],\n ['import computed', '导入computed', \"import { computed } from 'vue';\"],\n ['import watch', '导入watch', \"import { watch, watchEffect } from 'vue';\"],\n ['import lifecycle', '导入生命周期', \"import { onMounted, onUnmounted, onBeforeMount, onBeforeUnmount } from 'vue';\"],\n ['import router', '导入路由', \"import { useRouter, useRoute } from 'vue-router';\"],\n ['import axios', '导入axios', \"import axios from 'axios';\"],\n ['import element', '导入Element组件', \"import { ElMessage, ElMessageBox } from 'element-plus';\"],\n ];\n imports.forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.Module, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // TypeScript 类型 - 只在 script 区域,输入 1 个字符即可触发\n if (isInScript && currentWord.length >= 1) {\n const tsTypes: [string, string, string][] = [\n ['interface', '接口定义', 'interface $1 {\\n $2\\n}'],\n ['type', '类型别名', 'type $1 = $2;'],\n ['type union', '联合类型', \"type $1 = '$2' | '$3';\"],\n ['enum', '枚举', 'enum $1 {\\n $2\\n}'],\n ['Ref<T>', 'Ref类型', 'Ref<$1>'],\n ['ComputedRef<T>', 'ComputedRef类型', 'ComputedRef<$1>'],\n ['PropType<T>', 'PropType类型', 'PropType<$1>'],\n ['Partial<T>', 'Partial类型', 'Partial<$1>'],\n ['Required<T>', 'Required类型', 'Required<$1>'],\n ['Pick<T,K>', 'Pick类型', 'Pick<$1, $2>'],\n ['Omit<T,K>', 'Omit类型', 'Omit<$1, $2>'],\n ['Record<K,V>', 'Record类型', 'Record<$1, $2>'],\n ];\n tsTypes.filter(([label]) => label.toLowerCase().includes(currentWord)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.TypeParameter, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // JavaScript 关键字 - 只在 script 区域,输入 1 个字符即可触发\n if (isInScript && currentWord.length >= 1) {\n const jsKeywords: [string, string, string][] = [\n ['const', '常量声明', 'const $1 = $2;'],\n ['let', '变量声明', 'let $1 = $2;'],\n ['var', '变量声明(旧)', 'var $1 = $2;'],\n ['function', '函数声明', 'function $1($2) {\\n $3\\n}'],\n ['async function', '异步函数', 'async function $1($2) {\\n $3\\n}'],\n ['arrow function', '箭头函数', '($1) => {\\n $2\\n}'],\n ['arrow function short', '箭头函数简写', '($1) => $2'],\n ['class', '类声明', 'class $1 {\\n constructor($2) {\\n $3\\n }\\n}'],\n ['if', '条件语句', 'if ($1) {\\n $2\\n}'],\n ['if else', '条件分支', 'if ($1) {\\n $2\\n} else {\\n $3\\n}'],\n ['else if', '否则如果', 'else if ($1) {\\n $2\\n}'],\n ['switch', 'switch语句', 'switch ($1) {\\n case $2:\\n $3\\n break;\\n default:\\n $4\\n}'],\n ['for', 'for循环', 'for (let i = 0; i < $1; i++) {\\n $2\\n}'],\n ['for of', 'for...of循环', 'for (const $1 of $2) {\\n $3\\n}'],\n ['for in', 'for...in循环', 'for (const $1 in $2) {\\n $3\\n}'],\n ['while', 'while循环', 'while ($1) {\\n $2\\n}'],\n ['do while', 'do...while循环', 'do {\\n $1\\n} while ($2);'],\n ['try catch', 'try...catch', 'try {\\n $1\\n} catch (error) {\\n $2\\n}'],\n ['try catch finally', 'try...catch...finally', 'try {\\n $1\\n} catch (error) {\\n $2\\n} finally {\\n $3\\n}'],\n ['throw', '抛出错误', \"throw new Error('$1');\"],\n ['return', '返回', 'return $1;'],\n ['await', '等待Promise', 'await $1'],\n ['new Promise', '创建Promise', 'new Promise((resolve, reject) => {\\n $1\\n})'],\n ['async await', '异步等待', 'const $1 = await $2;'],\n ['export default', '默认导出', 'export default $1;'],\n ['export', '命名导出', 'export { $1 };'],\n ['import', '导入', \"import { $1 } from '$2';\"],\n ['import default', '默认导入', \"import $1 from '$2';\"],\n ['destructure object', '对象解构', 'const { $1 } = $2;'],\n ['destructure array', '数组解构', 'const [$1] = $2;'],\n ['spread object', '对象展开', '{ ...$1 }'],\n ['spread array', '数组展开', '[...$1]'],\n ['template literal', '模板字符串', '`$1${$2}$3`'],\n ['ternary', '三元表达式', '$1 ? $2 : $3'],\n ['nullish coalescing', '空值合并', '$1 ?? $2'],\n ['optional chaining', '可选链', '$1?.$2'],\n ];\n jsKeywords.filter(([label]) => label.toLowerCase().includes(currentWord)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.Keyword, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n // JavaScript 内置对象和方法 - 只在 script 区域,输入 . 或 1 个字符即可触发\n if (isInScript && (before.endsWith('.') || currentWord.length >= 1)) {\n const jsMethods: [string, string, string][] = [\n // Console\n ['console.log', '控制台输出', \"console.log($1);\"],\n ['console.error', '控制台错误', \"console.error($1);\"],\n ['console.warn', '控制台警告', \"console.warn($1);\"],\n ['console.info', '控制台信息', \"console.info($1);\"],\n ['console.table', '控制台表格', \"console.table($1);\"],\n ['console.time', '计时开始', \"console.time('$1');\"],\n ['console.timeEnd', '计时结束', \"console.timeEnd('$1');\"],\n ['console.group', '分组开始', \"console.group('$1');\"],\n ['console.groupEnd', '分组结束', \"console.groupEnd();\"],\n // Array\n ['array.map', '数组映射', '$1.map(($2) => $3)'],\n ['array.filter', '数组过滤', '$1.filter(($2) => $3)'],\n ['array.find', '数组查找', '$1.find(($2) => $3)'],\n ['array.findIndex', '数组查找索引', '$1.findIndex(($2) => $3)'],\n ['array.forEach', '数组遍历', '$1.forEach(($2) => {\\n $3\\n})'],\n ['array.reduce', '数组归约', '$1.reduce((acc, $2) => {\\n $3\\n return acc;\\n}, $4)'],\n ['array.some', '数组某些', '$1.some(($2) => $3)'],\n ['array.every', '数组每个', '$1.every(($2) => $3)'],\n ['array.includes', '数组包含', '$1.includes($2)'],\n ['array.indexOf', '数组索引', '$1.indexOf($2)'],\n ['array.push', '数组添加', '$1.push($2)'],\n ['array.pop', '数组弹出', '$1.pop()'],\n ['array.shift', '数组移除首个', '$1.shift()'],\n ['array.unshift', '数组添加到首', '$1.unshift($2)'],\n ['array.slice', '数组切片', '$1.slice($2, $3)'],\n ['array.splice', '数组拼接', '$1.splice($2, $3)'],\n ['array.concat', '数组连接', '$1.concat($2)'],\n ['array.join', '数组连接字符串', \"$1.join('$2')\"],\n ['array.reverse', '数组反转', '$1.reverse()'],\n ['array.sort', '数组排序', '$1.sort((a, b) => $2)'],\n ['array.flat', '数组扁平化', '$1.flat($2)'],\n ['array.flatMap', '数组扁平映射', '$1.flatMap(($2) => $3)'],\n ['Array.from', '从类数组创建', 'Array.from($1)'],\n ['Array.isArray', '判断是否数组', 'Array.isArray($1)'],\n // Object\n ['Object.keys', '对象键数组', 'Object.keys($1)'],\n ['Object.values', '对象值数组', 'Object.values($1)'],\n ['Object.entries', '对象键值对', 'Object.entries($1)'],\n ['Object.assign', '对象合并', 'Object.assign({}, $1, $2)'],\n ['Object.fromEntries', '从键值对创建', 'Object.fromEntries($1)'],\n ['Object.hasOwn', '判断自有属性', 'Object.hasOwn($1, \"$2\")'],\n ['Object.freeze', '冻结对象', 'Object.freeze($1)'],\n // String\n ['string.split', '字符串分割', \"$1.split('$2')\"],\n ['string.trim', '去除空格', '$1.trim()'],\n ['string.toLowerCase', '转小写', '$1.toLowerCase()'],\n ['string.toUpperCase', '转大写', '$1.toUpperCase()'],\n ['string.replace', '字符串替换', \"$1.replace('$2', '$3')\"],\n ['string.replaceAll', '全部替换', \"$1.replaceAll('$2', '$3')\"],\n ['string.includes', '字符串包含', \"$1.includes('$2')\"],\n ['string.startsWith', '以...开头', \"$1.startsWith('$2')\"],\n ['string.endsWith', '以...结尾', \"$1.endsWith('$2')\"],\n ['string.substring', '子字符串', '$1.substring($2, $3)'],\n ['string.slice', '字符串切片', '$1.slice($2, $3)'],\n ['string.padStart', '前填充', \"$1.padStart($2, '$3')\"],\n ['string.padEnd', '后填充', \"$1.padEnd($2, '$3')\"],\n // Number/Math\n ['parseInt', '解析整数', \"parseInt($1, 10)\"],\n ['parseFloat', '解析浮点数', 'parseFloat($1)'],\n ['Number.isNaN', '判断NaN', 'Number.isNaN($1)'],\n ['Number.isFinite', '判断有限', 'Number.isFinite($1)'],\n ['Math.floor', '向下取整', 'Math.floor($1)'],\n ['Math.ceil', '向上取整', 'Math.ceil($1)'],\n ['Math.round', '四舍五入', 'Math.round($1)'],\n ['Math.abs', '绝对值', 'Math.abs($1)'],\n ['Math.max', '最大值', 'Math.max($1, $2)'],\n ['Math.min', '最小值', 'Math.min($1, $2)'],\n ['Math.random', '随机数', 'Math.random()'],\n ['toFixed', '保留小数', '$1.toFixed($2)'],\n // JSON\n ['JSON.stringify', 'JSON序列化', 'JSON.stringify($1)'],\n ['JSON.stringify pretty', 'JSON格式化', 'JSON.stringify($1, null, 2)'],\n ['JSON.parse', 'JSON解析', 'JSON.parse($1)'],\n // Promise\n ['Promise.all', '等待所有', 'Promise.all([$1])'],\n ['Promise.race', '竞速', 'Promise.race([$1])'],\n ['Promise.allSettled', '等待所有完成', 'Promise.allSettled([$1])'],\n ['Promise.resolve', '解决Promise', 'Promise.resolve($1)'],\n ['Promise.reject', '拒绝Promise', 'Promise.reject($1)'],\n // setTimeout/setInterval\n ['setTimeout', '延时执行', 'setTimeout(() => {\\n $1\\n}, $2);'],\n ['setInterval', '定时执行', 'setInterval(() => {\\n $1\\n}, $2);'],\n ['clearTimeout', '清除延时', 'clearTimeout($1);'],\n ['clearInterval', '清除定时', 'clearInterval($1);'],\n // DOM\n ['document.getElementById', '通过ID获取', \"document.getElementById('$1')\"],\n ['document.querySelector', '选择器获取', \"document.querySelector('$1')\"],\n ['document.querySelectorAll', '选择器获取所有', \"document.querySelectorAll('$1')\"],\n ['addEventListener', '添加事件监听', \"$1.addEventListener('$2', ($3) => {\\n $4\\n});\"],\n ['removeEventListener', '移除事件监听', \"$1.removeEventListener('$2', $3);\"],\n // Fetch\n ['fetch', 'Fetch请求', \"fetch('$1')\\n .then(res => res.json())\\n .then(data => {\\n $2\\n });\"],\n ['fetch async', 'Fetch异步', \"const response = await fetch('$1');\\nconst data = await response.json();\"],\n // LocalStorage\n ['localStorage.getItem', '获取本地存储', \"localStorage.getItem('$1')\"],\n ['localStorage.setItem', '设置本地存储', \"localStorage.setItem('$1', $2);\"],\n ['localStorage.removeItem', '移除本地存储', \"localStorage.removeItem('$1');\"],\n // 其他\n ['typeof', '类型判断', \"typeof $1 === '$2'\"],\n ['instanceof', '实例判断', '$1 instanceof $2'],\n ['structuredClone', '深拷贝', 'structuredClone($1)'],\n ];\n jsMethods.filter(([label]) => currentWord.length === 0 || label.toLowerCase().includes(currentWord)).forEach(([label, detail, text]) => {\n suggestions.push({ label, detail, insertText: text, range, kind: monaco.languages.CompletionItemKind.Method, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet });\n });\n }\n\n return { suggestions };\n },\n });\n}\n\nexport function getVueTheme(isDark: boolean): string {\n return isDark ? 'vue-dark' : 'vue-light';\n}\n","<script setup lang=\"ts\">\nimport type { FormCodeEditorProp, SupportedLanguage } from '@/types';\n\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n shallowRef,\n watch,\n} from 'vue';\n\n\nimport { FullScreen } from '@element-plus/icons-vue';\nimport * as monaco from 'monaco-editor';\n\nimport { isEmpty, isNotEmpty } from '@/utils';\n\nimport { initVueLanguageSupport } from './volar/setup';\n\ninterface Props {\n detail: FormCodeEditorProp;\n value?: object | string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n});\n\n// ✅ 7. emit update\nconst emit = defineEmits<{\n (e: 'update:value', value: string): void;\n}>();\n\n// const { isDark } = usePreferences();\nconst isDark = ref(true);\n\nconst showDialog = ref(false);\nconst mainEditor = ref<HTMLElement | null>(null);\nconst dialogEditor = ref<HTMLElement | null>(null);\nconst mainEditorInstance =\n shallowRef<monaco.editor.IStandaloneCodeEditor | null>(null);\nconst dialogEditorInstance =\n shallowRef<monaco.editor.IStandaloneCodeEditor | null>(null);\nconst model = shallowRef<monaco.editor.ITextModel | null>(null);\n\n// 注册语言\nconst registerLanguage = async (langId: SupportedLanguage) => {\n if (['css', 'html', 'javascript', 'typescript'].includes(langId)) return;\n\n // Vue 使用 Volar 初始化\n if (langId === 'vue') {\n await initVueLanguageSupport();\n return;\n }\n\n const registered = monaco.languages\n .getLanguages()\n .some((l) => l.id === langId);\n\n let mod: any;\n try {\n switch (langId) {\n case 'java': {\n mod = await import('./language/java');\n // 先定义主题,再注册补全\n mod.defineJavaThemes?.();\n mod.registerJavaCompletion?.();\n if (registered) return;\n break;\n }\n case 'json': {\n if (registered) return;\n mod = {};\n break;\n }\n case 'mysql': {\n if (registered) return;\n mod = await import('./language/mysql');\n break;\n }\n case 'postgresql': {\n mod = await import('./language/postgresql');\n // 注册 PostgreSQL 代码提示和主题\n mod.definePgsqlThemes?.();\n mod.registerPgsqlCompletion?.();\n if (registered) return;\n break;\n }\n default: {\n return;\n }\n }\n } catch (error) {\n console.warn(\n `[Monaco] Language ${langId} may already be registered`,\n error,\n );\n return;\n }\n\n monaco.languages.register({ id: langId });\n monaco.languages.setMonarchTokensProvider(langId, mod.language);\n monaco.languages.setLanguageConfiguration(langId, mod.conf);\n};\n\nconst initCodeTips = () => {\n // 在 onMounted 中,create 之后添加\n monaco.languages.registerCompletionItemProvider('javascript', {\n // 触发字符\n triggerCharacters: ['.'],\n\n provideCompletionItems: (model, position) => {\n const word = model.getWordUntilPosition(position);\n const range = {\n startLineNumber: position.lineNumber,\n endLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endColumn: word.endColumn,\n };\n\n // 获取当前光标前的文本(用于判断上下文)\n const textUntilPosition = model.getValueInRange({\n startLineNumber: 1,\n startColumn: 1,\n endLineNumber: position.lineNumber,\n endColumn: position.column,\n });\n\n // 匹配 btnClick.\n const match = /btnClick\\.(\\w*)$/.exec(textUntilPosition);\n if (match) {\n return {\n suggestions: [\n {\n label: 'openForm',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '打开表单',\n insertText: 'openForm(data, rowIndex)',\n insertTextRules:\n monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,\n range,\n },\n {\n label: 'deleteData',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '删除数据',\n insertText: 'btnClick.deleteData(data)',\n range,\n },\n {\n label: 'refreshTableData',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '获取数据',\n insertText: 'btnClick.refreshTableData()',\n range,\n },\n {\n label: 'routerPush',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '获取数据',\n insertText:\n 'btnClick.routerPush(路由name, router.push除了name的参数)',\n range,\n },\n ],\n };\n }\n\n // 也可以为 data. 提示\n const dataMatch = /data\\.(\\w*)$/.exec(textUntilPosition);\n if (dataMatch) {\n return {\n suggestions: Object.keys((window as any).mockData || {}).map(\n (key) => ({\n label: key,\n kind: monaco.languages.CompletionItemKind.Property,\n documentation: 'data 的属性',\n insertText: key,\n range,\n }),\n ),\n };\n }\n\n return { suggestions: [] };\n },\n });\n};\n\n/**\n * 获取默认值\n */\nconst getDefaultValue = (): string => {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n if (newLang === 'json') {\n if (typeof props.detail.defaultValue === 'object') {\n return JSON.stringify(props.detail.defaultValue);\n }\n\n return props.detail.defaultValue || '';\n }\n\n return props.detail.defaultValue as string;\n};\n\nlet mainLoaded = false;\nlet dialogLoaded = false;\n\nconst initMainEditor = async () => {\n if (mainLoaded || !mainEditor.value) return;\n await initEditor(mainEditor.value, (instance) => {\n mainEditorInstance.value = instance;\n });\n mainLoaded = true;\n};\n\nconst openDialog = async () => {\n showDialog.value = true;\n if (dialogLoaded) return;\n await nextTick();\n await initEditor(dialogEditor.value!, (instance) => {\n dialogEditorInstance.value = instance;\n });\n dialogLoaded = true;\n};\n\nconst initEditor = async (\n container: HTMLElement,\n setInstance: (instance: monaco.editor.IStandaloneCodeEditor) => void,\n) => {\n const lang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n\n await registerLanguage(lang);\n\n if (!model.value) {\n let val: string = '';\n if (lang === 'json' && typeof props.value === 'object') {\n val = JSON.stringify(props.value, null, 2);\n } else if (typeof props.value === 'string') {\n val = props.value;\n }\n model.value = monaco.editor.createModel(val, lang);\n }\n\n if (lang === 'javascript') {\n monaco.languages.typescript.javascriptDefaults.addExtraLib(\n `\nconst data = {};\nconst rowIndex = 0;\nconst btnClick = {\n openForm: function(data, rowIndex) {},\n closeForm: function() {},\n getData: function() {}\n};\n`,\n 'extra:context.d.ts',\n );\n }\n\n const getEditorTheme = (lang: SupportedLanguage, dark: boolean): string => {\n if (lang === 'vue') {\n return dark ? 'vue-dark' : 'vue-light';\n }\n if (lang === 'java') {\n return dark ? 'java-dark' : 'java-light';\n }\n return dark ? 'vs-dark' : 'vs';\n };\n\n const instance = monaco.editor.create(container, {\n model: model.value,\n theme: getEditorTheme(lang, isDark.value),\n automaticLayout: true,\n readOnly: props.detail.disabled === true,\n suggest: {\n showKeywords: true,\n showFunctions: true,\n },\n quickSuggestions: {\n other: true,\n strings: true,\n },\n tabSize: 4,\n });\n\n setInstance(instance);\n\n instance.onDidChangeModelContent(() => {\n const value = model.value?.getValue();\n if (value !== undefined && value !== props.value) {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n try {\n if (newLang === 'json') {\n emit('update:value', JSON.parse(value));\n } else {\n emit('update:value', value);\n }\n } catch {\n // JSON 解析失败时不 emit\n }\n }\n });\n\n initCodeTips();\n};\n\n// 组件挂载后初始化主编辑器\nnextTick(() => {\n initMainEditor();\n});\n\n// 监听主题变化\nwatch(isDark, (dark) => {\n const lang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n let theme = dark ? 'vs-dark' : 'vs';\n if (lang === 'vue') {\n theme = dark ? 'vue-dark' : 'vue-light';\n } else if (lang === 'java') {\n theme = dark ? 'java-dark' : 'java-light';\n }\n if (mainEditorInstance.value) {\n monaco.editor.setTheme(theme);\n }\n});\n\n// ✅ 5. 监听语言切换(在 model 存在后才执行)\nwatch(\n () => props.detail,\n async () => {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n if (model.value) {\n await registerLanguage(newLang);\n monaco.editor.setModelLanguage(model.value, newLang);\n }\n },\n { deep: true },\n);\n\n// ✅ 6. 监听 value 变化(确保 model 已创建)\nwatch(\n () => props.value,\n (newVal) => {\n if (!model.value) return;\n\n if (isEmpty(newVal)) {\n if (isNotEmpty(model.value.getValue())) {\n model.value.setValue('');\n }\n if (isNotEmpty(props.detail.defaultValue)) {\n const defaultValue = getDefaultValue();\n model.value.setValue(defaultValue);\n }\n return;\n }\n\n const currentValue = model.value.getValue();\n\n let nextValue = '';\n\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n\n if (newLang === 'json' && typeof newVal === 'object') {\n try {\n nextValue = JSON.stringify(newVal, null, 2);\n } catch {\n return;\n }\n } else if (typeof newVal === 'string') {\n nextValue = newVal;\n }\n\n // ✅ 避免重复 setValue\n if (nextValue !== currentValue) {\n model.value.setValue(nextValue || '');\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (mainEditorInstance.value) {\n mainEditorInstance.value.dispose();\n mainEditorInstance.value = null;\n }\n if (dialogEditorInstance.value) {\n dialogEditorInstance.value.dispose();\n dialogEditorInstance.value = null;\n }\n if (model.value) {\n model.value.dispose();\n model.value = null;\n }\n});\n\nconst maxHeight = computed(() => {\n if (props.detail?.componentParams?.maxLine) {\n const em = props.detail?.componentParams?.maxLine * 1.4;\n return `${em}em`;\n }\n\n return '24em';\n});\n</script>\n<template>\n <div class=\"container\">\n <div class=\"code-preview\">\n <p v-if=\"detail.componentParams?.prefix\" class=\"code-prefix\">\n {{ detail.componentParams.prefix }}\n </p>\n <div\n ref=\"mainEditor\"\n class=\"main-editor\"\n :style=\"{ height: maxHeight }\"\n ></div>\n <p v-if=\"detail.componentParams?.suffix\" class=\"code-suffix\">\n {{ detail.componentParams.suffix }}\n </p>\n <el-button\n class=\"expand-btn\"\n :icon=\"FullScreen\"\n circle\n size=\"small\"\n @click=\"openDialog\"\n />\n </div>\n <el-dialog\n v-model=\"showDialog\"\n append-to-body\n align-center\n center\n width=\"80%\"\n class=\"code-editor-dialog\"\n >\n <div class=\"dialog-container\">\n <p v-if=\"detail.componentParams?.prefix\" class=\"code-prefix\">\n {{ detail.componentParams.prefix }}\n </p>\n <div ref=\"dialogEditor\" class=\"dialog-editor\"></div>\n <p v-if=\"detail.componentParams?.suffix\" class=\"code-suffix\">\n {{ detail.componentParams.suffix }}\n </p>\n </div>\n </el-dialog>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.container {\n width: 100%;\n height: 100%;\n padding: 0;\n}\n.code-preview {\n position: relative;\n width: 100%;\n height: 100%;\n}\n.code-prefix,\n.code-suffix {\n margin: 0;\n padding: 4px 8px;\n font-size: 12px;\n color: var(--el-text-color-secondary);\n background: var(--el-fill-color-light);\n border: 1px solid var(--el-border-color);\n font-family: monospace;\n white-space: pre-wrap;\n}\n.code-prefix {\n border-bottom: none;\n border-radius: var(--el-border-radius-base) var(--el-border-radius-base) 0 0;\n}\n.code-suffix {\n border-top: none;\n border-radius: 0 0 var(--el-border-radius-base) var(--el-border-radius-base);\n}\n.main-editor {\n width: 100%;\n border-radius: var(--el-border-radius-base);\n overflow: hidden;\n border: 1px solid var(--el-border-color);\n}\n.code-prefix + .main-editor {\n border-radius: 0;\n}\n.main-editor:has(+ .code-suffix) {\n border-radius: var(--el-border-radius-base) var(--el-border-radius-base) 0 0;\n}\n.code-prefix + .main-editor:has(+ .code-suffix) {\n border-radius: 0;\n}\n.expand-btn {\n position: absolute;\n top: 4px;\n right: 4px;\n z-index: 10;\n}\n.dialog-container {\n width: 100%;\n height: 100%;\n padding: 0;\n}\n.dialog-editor {\n width: 100%;\n border-radius: var(--el-border-radius-base);\n overflow: hidden;\n height: 80vh;\n border: 1px solid var(--el-border-color);\n}\n</style>\n\n<style lang=\"scss\">\n/* 弹窗样式覆盖 - 减少内边距 */\n.code-editor-dialog {\n .el-dialog__body {\n padding: 8px 12px 12px;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { FormCodeEditorProp, SupportedLanguage } from '@/types';\n\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n ref,\n shallowRef,\n watch,\n} from 'vue';\n\n\nimport { FullScreen } from '@element-plus/icons-vue';\nimport * as monaco from 'monaco-editor';\n\nimport { isEmpty, isNotEmpty } from '@/utils';\n\nimport { initVueLanguageSupport } from './volar/setup';\n\ninterface Props {\n detail: FormCodeEditorProp;\n value?: object | string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: '',\n});\n\n// ✅ 7. emit update\nconst emit = defineEmits<{\n (e: 'update:value', value: string): void;\n}>();\n\n// const { isDark } = usePreferences();\nconst isDark = ref(true);\n\nconst showDialog = ref(false);\nconst mainEditor = ref<HTMLElement | null>(null);\nconst dialogEditor = ref<HTMLElement | null>(null);\nconst mainEditorInstance =\n shallowRef<monaco.editor.IStandaloneCodeEditor | null>(null);\nconst dialogEditorInstance =\n shallowRef<monaco.editor.IStandaloneCodeEditor | null>(null);\nconst model = shallowRef<monaco.editor.ITextModel | null>(null);\n\n// 注册语言\nconst registerLanguage = async (langId: SupportedLanguage) => {\n if (['css', 'html', 'javascript', 'typescript'].includes(langId)) return;\n\n // Vue 使用 Volar 初始化\n if (langId === 'vue') {\n await initVueLanguageSupport();\n return;\n }\n\n const registered = monaco.languages\n .getLanguages()\n .some((l) => l.id === langId);\n\n let mod: any;\n try {\n switch (langId) {\n case 'java': {\n mod = await import('./language/java');\n // 先定义主题,再注册补全\n mod.defineJavaThemes?.();\n mod.registerJavaCompletion?.();\n if (registered) return;\n break;\n }\n case 'json': {\n if (registered) return;\n mod = {};\n break;\n }\n case 'mysql': {\n if (registered) return;\n mod = await import('./language/mysql');\n break;\n }\n case 'postgresql': {\n mod = await import('./language/postgresql');\n // 注册 PostgreSQL 代码提示和主题\n mod.definePgsqlThemes?.();\n mod.registerPgsqlCompletion?.();\n if (registered) return;\n break;\n }\n default: {\n return;\n }\n }\n } catch (error) {\n console.warn(\n `[Monaco] Language ${langId} may already be registered`,\n error,\n );\n return;\n }\n\n monaco.languages.register({ id: langId });\n monaco.languages.setMonarchTokensProvider(langId, mod.language);\n monaco.languages.setLanguageConfiguration(langId, mod.conf);\n};\n\nconst initCodeTips = () => {\n // 在 onMounted 中,create 之后添加\n monaco.languages.registerCompletionItemProvider('javascript', {\n // 触发字符\n triggerCharacters: ['.'],\n\n provideCompletionItems: (model, position) => {\n const word = model.getWordUntilPosition(position);\n const range = {\n startLineNumber: position.lineNumber,\n endLineNumber: position.lineNumber,\n startColumn: word.startColumn,\n endColumn: word.endColumn,\n };\n\n // 获取当前光标前的文本(用于判断上下文)\n const textUntilPosition = model.getValueInRange({\n startLineNumber: 1,\n startColumn: 1,\n endLineNumber: position.lineNumber,\n endColumn: position.column,\n });\n\n // 匹配 btnClick.\n const match = /btnClick\\.(\\w*)$/.exec(textUntilPosition);\n if (match) {\n return {\n suggestions: [\n {\n label: 'openForm',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '打开表单',\n insertText: 'openForm(data, rowIndex)',\n insertTextRules:\n monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,\n range,\n },\n {\n label: 'deleteData',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '删除数据',\n insertText: 'btnClick.deleteData(data)',\n range,\n },\n {\n label: 'refreshTableData',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '获取数据',\n insertText: 'btnClick.refreshTableData()',\n range,\n },\n {\n label: 'routerPush',\n kind: monaco.languages.CompletionItemKind.Method,\n documentation: '获取数据',\n insertText:\n 'btnClick.routerPush(路由name, router.push除了name的参数)',\n range,\n },\n ],\n };\n }\n\n // 也可以为 data. 提示\n const dataMatch = /data\\.(\\w*)$/.exec(textUntilPosition);\n if (dataMatch) {\n return {\n suggestions: Object.keys((window as any).mockData || {}).map(\n (key) => ({\n label: key,\n kind: monaco.languages.CompletionItemKind.Property,\n documentation: 'data 的属性',\n insertText: key,\n range,\n }),\n ),\n };\n }\n\n return { suggestions: [] };\n },\n });\n};\n\n/**\n * 获取默认值\n */\nconst getDefaultValue = (): string => {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n if (newLang === 'json') {\n if (typeof props.detail.defaultValue === 'object') {\n return JSON.stringify(props.detail.defaultValue);\n }\n\n return props.detail.defaultValue || '';\n }\n\n return props.detail.defaultValue as string;\n};\n\nlet mainLoaded = false;\nlet dialogLoaded = false;\n\nconst initMainEditor = async () => {\n if (mainLoaded || !mainEditor.value) return;\n await initEditor(mainEditor.value, (instance) => {\n mainEditorInstance.value = instance;\n });\n mainLoaded = true;\n};\n\nconst openDialog = async () => {\n showDialog.value = true;\n if (dialogLoaded) return;\n await nextTick();\n await initEditor(dialogEditor.value!, (instance) => {\n dialogEditorInstance.value = instance;\n });\n dialogLoaded = true;\n};\n\nconst initEditor = async (\n container: HTMLElement,\n setInstance: (instance: monaco.editor.IStandaloneCodeEditor) => void,\n) => {\n const lang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n\n await registerLanguage(lang);\n\n if (!model.value) {\n let val: string = '';\n if (lang === 'json' && typeof props.value === 'object') {\n val = JSON.stringify(props.value, null, 2);\n } else if (typeof props.value === 'string') {\n val = props.value;\n }\n model.value = monaco.editor.createModel(val, lang);\n }\n\n if (lang === 'javascript') {\n monaco.languages.typescript.javascriptDefaults.addExtraLib(\n `\nconst data = {};\nconst rowIndex = 0;\nconst btnClick = {\n openForm: function(data, rowIndex) {},\n closeForm: function() {},\n getData: function() {}\n};\n`,\n 'extra:context.d.ts',\n );\n }\n\n const getEditorTheme = (lang: SupportedLanguage, dark: boolean): string => {\n if (lang === 'vue') {\n return dark ? 'vue-dark' : 'vue-light';\n }\n if (lang === 'java') {\n return dark ? 'java-dark' : 'java-light';\n }\n return dark ? 'vs-dark' : 'vs';\n };\n\n const instance = monaco.editor.create(container, {\n model: model.value,\n theme: getEditorTheme(lang, isDark.value),\n automaticLayout: true,\n readOnly: props.detail.disabled === true,\n suggest: {\n showKeywords: true,\n showFunctions: true,\n },\n quickSuggestions: {\n other: true,\n strings: true,\n },\n tabSize: 4,\n });\n\n setInstance(instance);\n\n instance.onDidChangeModelContent(() => {\n const value = model.value?.getValue();\n if (value !== undefined && value !== props.value) {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n try {\n if (newLang === 'json') {\n emit('update:value', JSON.parse(value));\n } else {\n emit('update:value', value);\n }\n } catch {\n // JSON 解析失败时不 emit\n }\n }\n });\n\n initCodeTips();\n};\n\n// 组件挂载后初始化主编辑器\nnextTick(() => {\n initMainEditor();\n});\n\n// 监听主题变化\nwatch(isDark, (dark) => {\n const lang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n let theme = dark ? 'vs-dark' : 'vs';\n if (lang === 'vue') {\n theme = dark ? 'vue-dark' : 'vue-light';\n } else if (lang === 'java') {\n theme = dark ? 'java-dark' : 'java-light';\n }\n if (mainEditorInstance.value) {\n monaco.editor.setTheme(theme);\n }\n});\n\n// ✅ 5. 监听语言切换(在 model 存在后才执行)\nwatch(\n () => props.detail,\n async () => {\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n if (model.value) {\n await registerLanguage(newLang);\n monaco.editor.setModelLanguage(model.value, newLang);\n }\n },\n { deep: true },\n);\n\n// ✅ 6. 监听 value 变化(确保 model 已创建)\nwatch(\n () => props.value,\n (newVal) => {\n if (!model.value) return;\n\n if (isEmpty(newVal)) {\n if (isNotEmpty(model.value.getValue())) {\n model.value.setValue('');\n }\n if (isNotEmpty(props.detail.defaultValue)) {\n const defaultValue = getDefaultValue();\n model.value.setValue(defaultValue);\n }\n return;\n }\n\n const currentValue = model.value.getValue();\n\n let nextValue = '';\n\n const newLang: SupportedLanguage =\n props.detail.componentParams?.lang || 'javascript';\n\n if (newLang === 'json' && typeof newVal === 'object') {\n try {\n nextValue = JSON.stringify(newVal, null, 2);\n } catch {\n return;\n }\n } else if (typeof newVal === 'string') {\n nextValue = newVal;\n }\n\n // ✅ 避免重复 setValue\n if (nextValue !== currentValue) {\n model.value.setValue(nextValue || '');\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (mainEditorInstance.value) {\n mainEditorInstance.value.dispose();\n mainEditorInstance.value = null;\n }\n if (dialogEditorInstance.value) {\n dialogEditorInstance.value.dispose();\n dialogEditorInstance.value = null;\n }\n if (model.value) {\n model.value.dispose();\n model.value = null;\n }\n});\n\nconst maxHeight = computed(() => {\n if (props.detail?.componentParams?.maxLine) {\n const em = props.detail?.componentParams?.maxLine * 1.4;\n return `${em}em`;\n }\n\n return '24em';\n});\n</script>\n<template>\n <div class=\"container\">\n <div class=\"code-preview\">\n <p v-if=\"detail.componentParams?.prefix\" class=\"code-prefix\">\n {{ detail.componentParams.prefix }}\n </p>\n <div\n ref=\"mainEditor\"\n class=\"main-editor\"\n :style=\"{ height: maxHeight }\"\n ></div>\n <p v-if=\"detail.componentParams?.suffix\" class=\"code-suffix\">\n {{ detail.componentParams.suffix }}\n </p>\n <el-button\n class=\"expand-btn\"\n :icon=\"FullScreen\"\n circle\n size=\"small\"\n @click=\"openDialog\"\n />\n </div>\n <el-dialog\n v-model=\"showDialog\"\n append-to-body\n align-center\n center\n width=\"80%\"\n class=\"code-editor-dialog\"\n >\n <div class=\"dialog-container\">\n <p v-if=\"detail.componentParams?.prefix\" class=\"code-prefix\">\n {{ detail.componentParams.prefix }}\n </p>\n <div ref=\"dialogEditor\" class=\"dialog-editor\"></div>\n <p v-if=\"detail.componentParams?.suffix\" class=\"code-suffix\">\n {{ detail.componentParams.suffix }}\n </p>\n </div>\n </el-dialog>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.container {\n width: 100%;\n height: 100%;\n padding: 0;\n}\n.code-preview {\n position: relative;\n width: 100%;\n height: 100%;\n}\n.code-prefix,\n.code-suffix {\n margin: 0;\n padding: 4px 8px;\n font-size: 12px;\n color: var(--el-text-color-secondary);\n background: var(--el-fill-color-light);\n border: 1px solid var(--el-border-color);\n font-family: monospace;\n white-space: pre-wrap;\n}\n.code-prefix {\n border-bottom: none;\n border-radius: var(--el-border-radius-base) var(--el-border-radius-base) 0 0;\n}\n.code-suffix {\n border-top: none;\n border-radius: 0 0 var(--el-border-radius-base) var(--el-border-radius-base);\n}\n.main-editor {\n width: 100%;\n border-radius: var(--el-border-radius-base);\n overflow: hidden;\n border: 1px solid var(--el-border-color);\n}\n.code-prefix + .main-editor {\n border-radius: 0;\n}\n.main-editor:has(+ .code-suffix) {\n border-radius: var(--el-border-radius-base) var(--el-border-radius-base) 0 0;\n}\n.code-prefix + .main-editor:has(+ .code-suffix) {\n border-radius: 0;\n}\n.expand-btn {\n position: absolute;\n top: 4px;\n right: 4px;\n z-index: 10;\n}\n.dialog-container {\n width: 100%;\n height: 100%;\n padding: 0;\n}\n.dialog-editor {\n width: 100%;\n border-radius: var(--el-border-radius-base);\n overflow: hidden;\n height: 80vh;\n border: 1px solid var(--el-border-color);\n}\n</style>\n\n<style lang=\"scss\">\n/* 弹窗样式覆盖 - 减少内边距 */\n.code-editor-dialog {\n .el-dialog__body {\n padding: 8px 12px 12px;\n }\n}\n</style>\n","import * as Java from './java';\r\nimport * as Mysql from './mysql';\r\nimport * as Postgresql from './postgresql';\r\n\r\nexport const codeLanguages = {\r\n java: {\r\n conf: Java.conf,\r\n language: Java.language,\r\n registerCompletion: Java.registerJavaCompletion,\r\n defineThemes: Java.defineJavaThemes,\r\n },\r\n mysql: {\r\n conf: Mysql.conf,\r\n language: Mysql.conf,\r\n },\r\n postgresql: {\r\n conf: Postgresql.conf,\r\n language: Postgresql.conf,\r\n registerCompletion: Postgresql.registerPgsqlCompletion(),\r\n defineThemes: Postgresql.definePgsqlThemes(),\r\n }\r\n}","import type { App } from 'vue';\r\n\r\nimport FormCodeEditor from './FormCodeEditor.vue';\r\nimport { codeLanguages } from './language/index';\r\n\r\n(FormCodeEditor as any).name = 'FormCodeEditor';\r\n\r\nFormCodeEditor.install = (app: App) => {\r\n app.component('FormCodeEditor', FormCodeEditor);\r\n};\r\n\r\nexport { FormCodeEditor, codeLanguages };\r\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\n</script>\n\n<template>\n <el-divider v-bind=\"detail.componentParams\">\n {{ detail.placeholder }}\n </el-divider>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport type { FormFrame } from '@/types';\n\ninterface Props {\n value?: string;\n detail: FormFrame;\n mittId?: any;\n}\n\nwithDefaults(defineProps<Props>(), {\n value: '',\n mittId: () => null,\n});\n</script>\n\n<template>\n <el-divider v-bind=\"detail.componentParams\">\n {{ detail.placeholder }}\n </el-divider>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import FormDivider from './FormDivider.vue';\nimport type { App } from 'vue';\n\n(FormDivider as any).name = 'FormDivider';\n\nFormDivider.install = (app: App) => {\n app.component('FormDivider', FormDivider);\n};\n\nexport { FormDivider };\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\n\nimport { ArrowDown, ArrowRight } from '@element-plus/icons-vue';\n\nconst props = withDefaults(\n defineProps<{\n /** 是否显示边框 */\n bordered?: boolean;\n /** 是否可折叠 */\n collapsible?: boolean;\n /** 是否禁用 */\n disabled?: boolean;\n /** 是否展开(v-model) */\n modelValue?: boolean;\n /** 标题 */\n title?: string;\n }>(),\n {\n title: '',\n collapsible: false,\n modelValue: true,\n bordered: true,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void;\n (e: 'change', value: boolean): void;\n}>();\n\nconst internalExpanded = ref(true);\n\nconst isExpanded = computed({\n get: () => props.modelValue ?? internalExpanded.value,\n set: (val) => {\n internalExpanded.value = val;\n emit('update:modelValue', val);\n emit('change', val);\n },\n});\n\nconst toggle = () => {\n if (props.collapsible && !props.disabled) {\n isExpanded.value = !isExpanded.value;\n }\n};\n\nconst legendClass = computed(() => ({\n 'fieldset-legend': true,\n 'fieldset-legend--collapsible': props.collapsible && !props.disabled,\n 'fieldset-legend--disabled': props.disabled,\n}));\n</script>\n\n<template>\n <fieldset\n class=\"fieldset\"\n :class=\"{\n 'fieldset--bordered': bordered,\n 'fieldset--collapsed': !isExpanded,\n }\"\n >\n <legend v-if=\"title || $slots.title\" :class=\"legendClass\" @click=\"toggle\">\n <span v-if=\"collapsible\" class=\"fieldset-arrow\">\n <el-icon>\n <ArrowDown v-if=\"isExpanded\" />\n <ArrowRight v-else />\n </el-icon>\n </span>\n <slot name=\"title\">{{ title }}</slot>\n </legend>\n <el-collapse-transition>\n <div v-show=\"isExpanded\" class=\"fieldset-content\">\n <slot></slot>\n </div>\n </el-collapse-transition>\n </fieldset>\n</template>\n\n<style scoped lang=\"scss\">\n.fieldset {\n margin: 0;\n padding: 0;\n border: none;\n min-width: 0;\n\n &--bordered {\n border: 1px solid var(--el-border-color);\n border-radius: var(--el-border-radius-base);\n padding: 12px;\n }\n\n &--collapsed.fieldset--bordered {\n padding-bottom: 0;\n }\n}\n\n.fieldset-legend {\n padding: 0 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--el-text-color-primary);\n display: inline-flex;\n align-items: center;\n gap: 4px;\n\n &--collapsible {\n cursor: pointer;\n user-select: none;\n\n &:hover {\n color: var(--el-color-primary);\n }\n }\n\n &--disabled {\n cursor: not-allowed;\n color: var(--el-text-color-disabled);\n\n &:hover {\n color: var(--el-text-color-disabled);\n }\n }\n}\n\n.fieldset-arrow {\n display: inline-flex;\n align-items: center;\n transition: transform 0.3s;\n}\n\n.fieldset-content {\n overflow: hidden;\n}\nt-collapse-enter-active,\n.fieldset-collapse-leave-active {\n transition: all 0.3s ease;\n}\n\n.fieldset-collapse-enter-from,\n.fieldset-collapse-leave-to {\n opacity: 0;\n max-height: 0;\n}\n\n.fieldset-collapse-enter-to,\n.fieldset-collapse-leave-from {\n opacity: 1;\n max-height: 1000px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\n\nimport { ArrowDown, ArrowRight } from '@element-plus/icons-vue';\n\nconst props = withDefaults(\n defineProps<{\n /** 是否显示边框 */\n bordered?: boolean;\n /** 是否可折叠 */\n collapsible?: boolean;\n /** 是否禁用 */\n disabled?: boolean;\n /** 是否展开(v-model) */\n modelValue?: boolean;\n /** 标题 */\n title?: string;\n }>(),\n {\n title: '',\n collapsible: false,\n modelValue: true,\n bordered: true,\n disabled: false,\n },\n);\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', value: boolean): void;\n (e: 'change', value: boolean): void;\n}>();\n\nconst internalExpanded = ref(true);\n\nconst isExpanded = computed({\n get: () => props.modelValue ?? internalExpanded.value,\n set: (val) => {\n internalExpanded.value = val;\n emit('update:modelValue', val);\n emit('change', val);\n },\n});\n\nconst toggle = () => {\n if (props.collapsible && !props.disabled) {\n isExpanded.value = !isExpanded.value;\n }\n};\n\nconst legendClass = computed(() => ({\n 'fieldset-legend': true,\n 'fieldset-legend--collapsible': props.collapsible && !props.disabled,\n 'fieldset-legend--disabled': props.disabled,\n}));\n</script>\n\n<template>\n <fieldset\n class=\"fieldset\"\n :class=\"{\n 'fieldset--bordered': bordered,\n 'fieldset--collapsed': !isExpanded,\n }\"\n >\n <legend v-if=\"title || $slots.title\" :class=\"legendClass\" @click=\"toggle\">\n <span v-if=\"collapsible\" class=\"fieldset-arrow\">\n <el-icon>\n <ArrowDown v-if=\"isExpanded\" />\n <ArrowRight v-else />\n </el-icon>\n </span>\n <slot name=\"title\">{{ title }}</slot>\n </legend>\n <el-collapse-transition>\n <div v-show=\"isExpanded\" class=\"fieldset-content\">\n <slot></slot>\n </div>\n </el-collapse-transition>\n </fieldset>\n</template>\n\n<style scoped lang=\"scss\">\n.fieldset {\n margin: 0;\n padding: 0;\n border: none;\n min-width: 0;\n\n &--bordered {\n border: 1px solid var(--el-border-color);\n border-radius: var(--el-border-radius-base);\n padding: 12px;\n }\n\n &--collapsed.fieldset--bordered {\n padding-bottom: 0;\n }\n}\n\n.fieldset-legend {\n padding: 0 8px;\n font-size: 14px;\n font-weight: 500;\n color: var(--el-text-color-primary);\n display: inline-flex;\n align-items: center;\n gap: 4px;\n\n &--collapsible {\n cursor: pointer;\n user-select: none;\n\n &:hover {\n color: var(--el-color-primary);\n }\n }\n\n &--disabled {\n cursor: not-allowed;\n color: var(--el-text-color-disabled);\n\n &:hover {\n color: var(--el-text-color-disabled);\n }\n }\n}\n\n.fieldset-arrow {\n display: inline-flex;\n align-items: center;\n transition: transform 0.3s;\n}\n\n.fieldset-content {\n overflow: hidden;\n}\nt-collapse-enter-active,\n.fieldset-collapse-leave-active {\n transition: all 0.3s ease;\n}\n\n.fieldset-collapse-enter-from,\n.fieldset-collapse-leave-to {\n opacity: 0;\n max-height: 0;\n}\n\n.fieldset-collapse-enter-to,\n.fieldset-collapse-leave-from {\n opacity: 1;\n max-height: 1000px;\n}\n</style>\n","import FormFieldset from './FormFieldset.vue';\nimport type { App } from 'vue';\n\n(FormFieldset as any).name = 'FormFieldset';\n\nFormFieldset.install = (app: App) => {\n app.component('FormFieldset', FormFieldset);\n};\n\nexport { FormFieldset };\n","<script setup lang=\"ts\">\nimport type { FormDynamicTableProp } from '@/types';\n\nimport { onMounted, onUnmounted, reactive, ref } from 'vue';\nimport { VueDraggable } from 'vue-draggable-plus';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any[];\n detail: FormDynamicTableProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => [],\n mittId: () => null,\n});\n// const emits = defineEmits([\n// 'getComponentValue',\n// 'valueChange',\n// 'setShow',\n// ]);\n\nconst modelValue = defineModel('value');\n\nconst state = reactive<any>({\n value: [],\n visible: false,\n frame: {},\n length_: 0,\n tableData: [],\n});\n\nconst modalOpen = ref(false);\nlet oldValue = '';\n\nconst showModal = () => {\n modalOpen.value = true;\n if (Array.isArray(modelValue.value)) {\n oldValue = JSON.stringify(modelValue.value);\n state.value = modelValue.value;\n }\n};\n\n/** 增加行 */\nconst addX = () => {\n state.value.push({});\n};\n\n/**\n * 删除行\n *\n * @param index\n */\nconst deleteX = (index: number) => {\n state.value.splice(index, 1);\n};\n\n/** 当值发生变化时 */\nconst handleChange = () => {\n modelValue.value = state.value;\n modalOpen.value = false;\n};\n\n/** 取消数据修改 */\nconst handleCancel = () => {\n state.value = JSON.parse(oldValue);\n modalOpen.value = false;\n};\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n modelValue.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <div>\n <el-button @click=\"showModal\"> 编辑 </el-button>\n <el-dialog\n v-model=\"modalOpen\"\n :close-on-click-modal=\"false\"\n :show-close=\"false\"\n append-to-body\n :width=\"detail.componentParams?.width || '90%'\"\n >\n <template #footer>\n <el-button type=\"primary\" @click=\"handleChange\"> 确认 </el-button>\n <el-button danger @click=\"handleCancel\"> 取消 </el-button>\n </template>\n\n <VueDraggable\n v-model=\"state.value\"\n :animation=\"150\"\n target=\".el-table__body-wrapper tbody\"\n >\n <el-table\n v-if=\"\n detail.componentParams.column &&\n detail.componentParams.column.length > 0\n \"\n :data=\"state.value\"\n max-height=\"90vh\"\n style=\"width: 100%\"\n >\n <el-table-column\n v-for=\"(item, index) in detail.componentParams.column\"\n :key=\"index\"\n :label=\"item.title\"\n :min-width=\"item.width > 0 ? item.width : 60\"\n :prop=\"item.field\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </el-table-column>\n\n <el-table-column label=\"添加\" :width=\"72\" fixed=\"right\">\n <template #header>\n <el-button size=\"small\" type=\"primary\" @click=\"addX\">\n 添加\n </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button\n size=\"small\"\n type=\"danger\"\n @click=\"deleteX(scope.$index)\"\n >\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n <el-table\n v-else-if=\"\n props.detail.componentParams?.column &&\n Array.isArray(props.detail.componentParams?.column)\n \"\n :data=\"state.value\"\n max-height=\"380\"\n style=\"width: 100%\"\n >\n <el-table-column\n v-for=\"(item, index) in detail.componentParams?.column\"\n :key=\"index\"\n :label=\"item.title\"\n :prop=\"item.field\"\n :width=\"item.width > 0 ? item.width : 60\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </el-table-column>\n\n <el-table-column label=\"添加\" :width=\"72\" fixed=\"right\">\n <template #header>\n <el-button size=\"small\" @click=\"addX\"> 添加 </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n </VueDraggable>\n </el-dialog>\n </div>\n</template>\n\n<style scoped></style>\n","<script setup lang=\"ts\">\nimport type { FormDynamicTableProp } from '@/types';\n\nimport { onMounted, onUnmounted, reactive, ref } from 'vue';\nimport { VueDraggable } from 'vue-draggable-plus';\n\nimport { useMittHook } from '../hooks/useMitt.hook';\n\ninterface Props {\n value?: any[];\n detail: FormDynamicTableProp;\n mittId?: any;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n value: () => [],\n mittId: () => null,\n});\n// const emits = defineEmits([\n// 'getComponentValue',\n// 'valueChange',\n// 'setShow',\n// ]);\n\nconst modelValue = defineModel('value');\n\nconst state = reactive<any>({\n value: [],\n visible: false,\n frame: {},\n length_: 0,\n tableData: [],\n});\n\nconst modalOpen = ref(false);\nlet oldValue = '';\n\nconst showModal = () => {\n modalOpen.value = true;\n if (Array.isArray(modelValue.value)) {\n oldValue = JSON.stringify(modelValue.value);\n state.value = modelValue.value;\n }\n};\n\n/** 增加行 */\nconst addX = () => {\n state.value.push({});\n};\n\n/**\n * 删除行\n *\n * @param index\n */\nconst deleteX = (index: number) => {\n state.value.splice(index, 1);\n};\n\n/** 当值发生变化时 */\nconst handleChange = () => {\n modelValue.value = state.value;\n modalOpen.value = false;\n};\n\n/** 取消数据修改 */\nconst handleCancel = () => {\n state.value = JSON.parse(oldValue);\n modalOpen.value = false;\n};\n\nconst { registerMitt, offMitt } = useMittHook(props.detail.field, props.mittId);\n\n/**\n * 设置值\n * @param value\n */\nconst setValue = (value: any[]) => {\n modelValue.value = value;\n};\n\nconst receiveBroadcasts = (eventData: any) => {\n if (props.detail.noticeReceive) {\n props.detail.noticeReceive(eventData, setValue);\n }\n};\n\nonMounted(() => {\n registerMitt(receiveBroadcasts);\n});\n\nonUnmounted(() => {\n offMitt();\n});\n</script>\n\n<template>\n <div>\n <el-button @click=\"showModal\"> 编辑 </el-button>\n <el-dialog\n v-model=\"modalOpen\"\n :close-on-click-modal=\"false\"\n :show-close=\"false\"\n append-to-body\n :width=\"detail.componentParams?.width || '90%'\"\n >\n <template #footer>\n <el-button type=\"primary\" @click=\"handleChange\"> 确认 </el-button>\n <el-button danger @click=\"handleCancel\"> 取消 </el-button>\n </template>\n\n <VueDraggable\n v-model=\"state.value\"\n :animation=\"150\"\n target=\".el-table__body-wrapper tbody\"\n >\n <el-table\n v-if=\"\n detail.componentParams.column &&\n detail.componentParams.column.length > 0\n \"\n :data=\"state.value\"\n max-height=\"90vh\"\n style=\"width: 100%\"\n >\n <el-table-column\n v-for=\"(item, index) in detail.componentParams.column\"\n :key=\"index\"\n :label=\"item.title\"\n :min-width=\"item.width > 0 ? item.width : 60\"\n :prop=\"item.field\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </el-table-column>\n\n <el-table-column label=\"添加\" :width=\"72\" fixed=\"right\">\n <template #header>\n <el-button size=\"small\" type=\"primary\" @click=\"addX\">\n 添加\n </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button\n size=\"small\"\n type=\"danger\"\n @click=\"deleteX(scope.$index)\"\n >\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n <el-table\n v-else-if=\"\n props.detail.componentParams?.column &&\n Array.isArray(props.detail.componentParams?.column)\n \"\n :data=\"state.value\"\n max-height=\"380\"\n style=\"width: 100%\"\n >\n <el-table-column\n v-for=\"(item, index) in detail.componentParams?.column\"\n :key=\"index\"\n :label=\"item.title\"\n :prop=\"item.field\"\n :width=\"item.width > 0 ? item.width : 60\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </el-table-column>\n\n <el-table-column label=\"添加\" :width=\"72\" fixed=\"right\">\n <template #header>\n <el-button size=\"small\" @click=\"addX\"> 添加 </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n </VueDraggable>\n </el-dialog>\n </div>\n</template>\n\n<style scoped></style>\n","import FormDynamicTable from './FormDynamicTable.vue';\nimport type { App } from 'vue';\n\n(FormDynamicTable as any).name = 'FormDynamicTable';\n\nFormDynamicTable.install = (app: App) => {\n app.component('FormDynamicTable', FormDynamicTable);\n};\n\nexport { FormDynamicTable };\n","<script setup lang=\"ts\">\nimport { VueDraggable } from 'vue-draggable-plus';\n\ninterface TableColumn {\n field: string;\n title: string;\n width: number;\n editor: any;\n [key: string]: any;\n}\n\ninterface Props {\n value?: any[];\n column: TableColumn[];\n}\n\nwithDefaults(defineProps<Props>(), {\n value: () => [],\n});\n\nconst tableValue = defineModel('value', {\n required: false,\n default: (): any[] => [],\n type: Array,\n});\n\n/** 增加行 */\nconst addX = () => {\n tableValue.value = [...tableValue.value, {}];\n};\n/**\n * 删除行\n *\n * @param index\n */\nconst deleteX = (index: number) => {\n const data = tableValue.value;\n data.splice(index, 1);\n};\n</script>\n\n<template>\n <VueDraggable\n v-model=\"tableValue\"\n :animation=\"150\"\n target=\".el-table__body-wrapper tbody\"\n >\n <ElTable\n v-if=\"column && column.length > 0\"\n :data=\"tableValue\"\n max-height=\"90vh\"\n style=\"width: 100%\"\n >\n <ElTableColumn\n v-for=\"(item, index) in column\"\n :key=\"index\"\n :label=\"item.title\"\n :min-width=\"item.width > 0 ? item.width : 60\"\n :prop=\"item.field\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </ElTableColumn>\n\n <ElTableColumn :width=\"72\" fixed=\"right\" label=\"添加\">\n <template #header>\n <el-button size=\"small\" type=\"primary\" @click=\"addX\">\n 添加\n </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" type=\"danger\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </ElTableColumn>\n </ElTable>\n <ElTable\n v-else-if=\"column && Array.isArray(column)\"\n :data=\"value\"\n max-height=\"380\"\n style=\"width: 100%\"\n >\n <ElTableColumn\n v-for=\"(item, index) in column\"\n :key=\"index\"\n :label=\"item.title\"\n :prop=\"item.field\"\n :width=\"item.width > 0 ? item.width : 60\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </ElTableColumn>\n\n <ElTableColumn :width=\"72\" fixed=\"right\" label=\"添加\">\n <template #header>\n <el-button size=\"small\" @click=\"addX\"> 添加 </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </ElTableColumn>\n </ElTable>\n </VueDraggable>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport { VueDraggable } from 'vue-draggable-plus';\n\ninterface TableColumn {\n field: string;\n title: string;\n width: number;\n editor: any;\n [key: string]: any;\n}\n\ninterface Props {\n value?: any[];\n column: TableColumn[];\n}\n\nwithDefaults(defineProps<Props>(), {\n value: () => [],\n});\n\nconst tableValue = defineModel('value', {\n required: false,\n default: (): any[] => [],\n type: Array,\n});\n\n/** 增加行 */\nconst addX = () => {\n tableValue.value = [...tableValue.value, {}];\n};\n/**\n * 删除行\n *\n * @param index\n */\nconst deleteX = (index: number) => {\n const data = tableValue.value;\n data.splice(index, 1);\n};\n</script>\n\n<template>\n <VueDraggable\n v-model=\"tableValue\"\n :animation=\"150\"\n target=\".el-table__body-wrapper tbody\"\n >\n <ElTable\n v-if=\"column && column.length > 0\"\n :data=\"tableValue\"\n max-height=\"90vh\"\n style=\"width: 100%\"\n >\n <ElTableColumn\n v-for=\"(item, index) in column\"\n :key=\"index\"\n :label=\"item.title\"\n :min-width=\"item.width > 0 ? item.width : 60\"\n :prop=\"item.field\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </ElTableColumn>\n\n <ElTableColumn :width=\"72\" fixed=\"right\" label=\"添加\">\n <template #header>\n <el-button size=\"small\" type=\"primary\" @click=\"addX\">\n 添加\n </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" type=\"danger\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </ElTableColumn>\n </ElTable>\n <ElTable\n v-else-if=\"column && Array.isArray(column)\"\n :data=\"value\"\n max-height=\"380\"\n style=\"width: 100%\"\n >\n <ElTableColumn\n v-for=\"(item, index) in column\"\n :key=\"index\"\n :label=\"item.title\"\n :prop=\"item.field\"\n :width=\"item.width > 0 ? item.width : 60\"\n show-overflow-tooltip\n >\n <template #default=\"scope\">\n <component\n :is=\"item.editor\"\n v-model:value=\"scope.row[item.field]\"\n :detail=\"item\"\n />\n </template>\n </ElTableColumn>\n\n <ElTableColumn :width=\"72\" fixed=\"right\" label=\"添加\">\n <template #header>\n <el-button size=\"small\" @click=\"addX\"> 添加 </el-button>\n </template>\n\n <template #default=\"scope\">\n <el-button size=\"small\" @click=\"deleteX(scope.$index)\">\n 删除\n </el-button>\n </template>\n </ElTableColumn>\n </ElTable>\n </VueDraggable>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","import DynamicMapTable from './DynamicMapTable.vue';\nimport type { App } from 'vue';\n\n(DynamicMapTable as any).name = 'DynamicMapTable';\n\nDynamicMapTable.install = (app: App) => {\n app.component('DynamicMapTable', DynamicMapTable);\n};\n\nexport { DynamicMapTable };\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormFrame } from '@/types';\n\nimport { reactive } from 'vue';\n\nimport QuestionSVG from '@/assets/question.svg';\nimport { FormDivider } from '../../FormDivider';\nimport { FormFieldset } from '../../FormFieldset';\n\ninterface Props {\n frame: FormFrame;\n showComponents: any;\n formSpan: number;\n formRules?: any;\n data: any;\n mittId: number;\n getComponentValue: Function;\n setShow: Function;\n}\n\nwithDefaults(defineProps<Props>(), {\n formRules: {},\n});\n\nconst dataRef = defineModel('data', {\n type: Object as PropType<any>,\n default: () => {},\n});\n\nconst fieldsetModel = reactive<any>({});\n</script>\n\n<template>\n <FormFieldset\n :name=\"frame.field\"\n :title=\"frame.title\"\n :collapsible=\"true\"\n v-model:model-value=\"fieldsetModel[frame.field]\"\n >\n <ElRowPlus :gutter=\"6\">\n <template v-for=\"item in frame.children\" :key=\"item.field\">\n <template v-if=\"item.formEditor === 'FormFieldset'\">\n <ElColPlus\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <FormAreaRender\n v-model:data=\"dataRef\"\n :frame=\"item\"\n :show-components=\"showComponents\"\n :form-span=\"formSpan\"\n :mitt-id=\"mittId\"\n :get-component-value=\"getComponentValue\"\n :set-show=\"setShow\"\n />\n </ElColPlus>\n </template>\n <template v-else>\n <template v-if=\"showComponents[item.field] !== false\">\n <ElColPlus\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <template v-if=\"item.formEditor === 'KeFormDivider'\">\n <FormDivider :detail=\"item\" />\n </template>\n <template v-else>\n <el-form-item\n :label=\"item.title\"\n :prop=\"item.field\"\n :rules=\"formRules?.[item.field] ? formRules[item.field] : []\"\n :label-width=\"item.labelWidth ? item.labelWidth : undefined\"\n class=\"form-item-label\"\n >\n <template v-if=\"item.placeholder\" #label>\n {{ item.title }}\n <el-tooltip :content=\"item.placeholder\">\n <div class=\"label-question\">\n <img :src=\"QuestionSVG\" alt=\"\" />\n </div>\n </el-tooltip>\n </template>\n\n <component\n :is=\"item.formEditor\"\n v-model:value=\"dataRef[item.field]\"\n :detail=\"item\"\n :disabled=\"item.disabled\"\n :field-name=\"item.field\"\n :field-title=\"item.title\"\n :mitt-id=\"mittId\"\n style=\"width: 100%\"\n @get-component-value=\"getComponentValue\"\n @set-show=\"setShow\"\n />\n </el-form-item>\n </template>\n </ElColPlus>\n </template>\n </template>\n </template>\n </ElRowPlus>\n </FormFieldset>\n</template>\n\n<style scoped lang=\"scss\">\n.form-item-label {\n :deep(.el-form-item__label) {\n font-weight: normal;\n }\n}\n\n.label-question {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FormFrame } from '@/types';\n\nimport { reactive } from 'vue';\n\nimport QuestionSVG from '@/assets/question.svg';\nimport { FormDivider } from '../../FormDivider';\nimport { FormFieldset } from '../../FormFieldset';\n\ninterface Props {\n frame: FormFrame;\n showComponents: any;\n formSpan: number;\n formRules?: any;\n data: any;\n mittId: number;\n getComponentValue: Function;\n setShow: Function;\n}\n\nwithDefaults(defineProps<Props>(), {\n formRules: {},\n});\n\nconst dataRef = defineModel('data', {\n type: Object as PropType<any>,\n default: () => {},\n});\n\nconst fieldsetModel = reactive<any>({});\n</script>\n\n<template>\n <FormFieldset\n :name=\"frame.field\"\n :title=\"frame.title\"\n :collapsible=\"true\"\n v-model:model-value=\"fieldsetModel[frame.field]\"\n >\n <ElRowPlus :gutter=\"6\">\n <template v-for=\"item in frame.children\" :key=\"item.field\">\n <template v-if=\"item.formEditor === 'FormFieldset'\">\n <ElColPlus\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <FormAreaRender\n v-model:data=\"dataRef\"\n :frame=\"item\"\n :show-components=\"showComponents\"\n :form-span=\"formSpan\"\n :mitt-id=\"mittId\"\n :get-component-value=\"getComponentValue\"\n :set-show=\"setShow\"\n />\n </ElColPlus>\n </template>\n <template v-else>\n <template v-if=\"showComponents[item.field] !== false\">\n <ElColPlus\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <template v-if=\"item.formEditor === 'KeFormDivider'\">\n <FormDivider :detail=\"item\" />\n </template>\n <template v-else>\n <el-form-item\n :label=\"item.title\"\n :prop=\"item.field\"\n :rules=\"formRules?.[item.field] ? formRules[item.field] : []\"\n :label-width=\"item.labelWidth ? item.labelWidth : undefined\"\n class=\"form-item-label\"\n >\n <template v-if=\"item.placeholder\" #label>\n {{ item.title }}\n <el-tooltip :content=\"item.placeholder\">\n <div class=\"label-question\">\n <img :src=\"QuestionSVG\" alt=\"\" />\n </div>\n </el-tooltip>\n </template>\n\n <component\n :is=\"item.formEditor\"\n v-model:value=\"dataRef[item.field]\"\n :detail=\"item\"\n :disabled=\"item.disabled\"\n :field-name=\"item.field\"\n :field-title=\"item.title\"\n :mitt-id=\"mittId\"\n style=\"width: 100%\"\n @get-component-value=\"getComponentValue\"\n @set-show=\"setShow\"\n />\n </el-form-item>\n </template>\n </ElColPlus>\n </template>\n </template>\n </template>\n </ElRowPlus>\n </FormFieldset>\n</template>\n\n<style scoped lang=\"scss\">\n.form-item-label {\n :deep(.el-form-item__label) {\n font-weight: normal;\n }\n}\n\n.label-question {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n</style>\n","import type { ModelRef, Reactive, Ref } from 'vue';\n\nimport type { FormFrame } from '@/types';\n\nimport { computed, watch, watchEffect } from 'vue';\n\nimport { emitter, isNotEmpty } from '@/utils';\n\n/**\n * 把平摊的表单frame拆分成二级树结构\n * @param treeFrameData 格式化后的响应式对象\n */\nexport const useFrameFormat = (treeFrameData: Ref) => {\n const frameFormat = (data: any[]) => {\n treeFrameData.value = convertAreaToFieldset(data);\n };\n return { frameFormat };\n};\n\ninterface FormRenderParams {\n frame: Ref<FormFrame[]>;\n frameFormat: Function;\n data: Ref<any>;\n componentShowRule: Ref<any>;\n showComponents: Reactive<any>;\n mittId: number;\n pageId: ModelRef<number>;\n rowKey: string;\n}\n\nexport const useFormRender = (params: FormRenderParams) => {\n const {\n frame,\n frameFormat,\n data,\n componentShowRule,\n showComponents,\n mittId,\n pageId,\n rowKey,\n } = params;\n\n // 监听frame,要随时处理frame分解\n watch(\n () => frame.value,\n (newValue) => {\n frameFormat(newValue);\n },\n { deep: true },\n );\n\n /**\n * 设置显示\n * @param params\n */\n const setShow = (params: {\n fieldName: string;\n isShow: boolean | undefined;\n }) => {\n // 不为空且为布尔才配置\n if (isNotEmpty(params.fieldName) && typeof params.isShow === 'boolean') {\n showComponents[params.fieldName] = params.isShow;\n } else {\n console.warn(`参数异常${JSON.stringify(params)}`);\n }\n };\n\n /**\n * 广播字段映射表\n * {\n * a: [\"xx\", \"bb\"]\n * }\n * 当a字段变化时 就要通知xx和bb字段\n */\n const noticeFieldMap = computed(() => {\n const newMap: any = {};\n frame.value.forEach((frame: FormFrame) => {\n newMap[frame.field] = frame.noticeField;\n });\n return newMap;\n });\n\n /**\n * 广播那些字段\n * @param fieldName\n */\n const noticeFieldChange = (fieldName: string) => {\n const noticeFieldList = noticeFieldMap.value[fieldName];\n if (Array.isArray(noticeFieldList)) {\n noticeFieldList.forEach((field: string) => {\n emitter.emit(field + mittId, data.value);\n });\n }\n };\n\n // 执行显示规则方法\n const execShowFunc = (key: string) => {\n if (componentShowRule.value?.[key]) {\n componentShowRule.value[key](data.value, setShow);\n }\n noticeFieldChange(key);\n };\n\n // formData旧值缓存\n const oldValueCacheMap: any = {};\n\n /**\n * 初始化表单变量\n * @param formData\n */\n const initForm = (formData: any) => {\n // 先初始化执行一次watchEffect的内容\n for (const key in formData) {\n if (Object.prototype.hasOwnProperty.call(formData, key)) {\n const val = formData[key];\n execShowFunc(key);\n // 初始化缓存\n oldValueCacheMap[key] = val;\n }\n }\n };\n\n // 表单字段key的数量\n // let keyNum = 0;\n // 监听props.data变化触发显示内容\n watchEffect(() => {\n // if (keyNum !== Object.keys(data.value).length) {\n // // 当监听到表单字段key数量改变时,执行初始化表单变量\n // keyNum = Object.keys(data.value).length;\n // initForm(data.value);\n // return;\n // }\n for (const key in data.value) {\n if (Object.prototype.hasOwnProperty.call(data.value, key)) {\n const val = data.value[key];\n // 如果oldValueCacheMap\n if (oldValueCacheMap[key] !== val) {\n execShowFunc(key);\n oldValueCacheMap[key] = val;\n }\n }\n }\n });\n\n /**\n * 子组件通过父组件获取其他组件的值\n *\n * @param array\n * @param callback\n */\n const getComponentValue = (array: [string], callback: Function) => {\n const map: any = {};\n for (const element of array) {\n if (data.value) {\n if (Array.isArray(data.value[element])) {\n if (data.value[element].length === 0) {\n map[element] = null;\n } else {\n const arr = data.value[element];\n map[element] = arr[arr.length - 1];\n }\n } else {\n map[element] = data.value[element];\n }\n }\n }\n\n map.pageId = pageId.value;\n if (data.value[rowKey]) {\n map.dataId = data.value[rowKey];\n }\n\n callback(map);\n };\n\n return { setShow, initForm, getComponentValue };\n};\n\n/**\n * 将平面的 FormAreaStart 和 FormAreaEnd 结构转换成嵌套的 KeFormFieldset 树状结构\n * @param data 平面数据\n * @returns 树状嵌套数据\n */\nexport const convertAreaToFieldset = (data: any[]): any[] => {\n const result: any[] = [];\n const stack: any[] = [];\n\n for (const item of data) {\n // 跳过空值\n if (!item) continue;\n if (item.formEditor === 'FormAreaStart') {\n // 创建 KeFormFieldset 节点,保留原始属性\n const fieldsetNode = {\n ...item,\n formEditor: 'FormFieldset',\n children: [],\n };\n\n // 如果栈为空,添加到结果数组;否则添加到栈顶元素的 children\n if (stack.length === 0) {\n result.push(fieldsetNode);\n } else {\n stack[stack.length - 1].children.push(fieldsetNode);\n }\n\n // 将当前节点压入栈\n stack.push(fieldsetNode);\n } else if (item.formEditor === 'FormAreaEnd') {\n // 遇到结束标记,弹出栈顶元素\n stack.pop();\n } else {\n // 普通字段\n if (stack.length === 0) {\n // 不在任何区域内,直接添加到结果\n result.push({ ...item });\n } else {\n // 在区域内,添加到栈顶元素的 children\n stack[stack.length - 1].children.push({ ...item });\n }\n }\n }\n\n return result;\n};\n","<script setup lang=\"ts\">\n// import { htmlToPDF } from \"#/utils/html2Util\";\nimport type { FormInstance, FormRules } from 'element-plus';\n\nimport type { PropType } from 'vue';\n\nimport type {\n FormBasicInterface,\n FormEmbeddedTableProp,\n FormFrame,\n} from '@/types';\n\nimport { computed, onMounted, reactive, ref, useTemplateRef } from 'vue';\n\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\nimport QuestionSVG from '@/assets/question.svg';\nimport { FormDivider } from '../FormDivider';\nimport { msgTips, formCheck } from '@/utils';\n\nimport FormAreaRender from './components/FormAreaRender.vue';\nimport { useFormRender, useFrameFormat } from './hooks/formRender.hook';\nimport { ElColPlus, ElRowPlus } from '@/components';\n\ninterface Props {\n isLoading?: boolean;\n data?: Record<string, any>;\n config: FormBasicInterface; // 保持你的类型名\n frame: FormFrame[];\n formRules?: FormRules<any>;\n pageId?: any;\n embeddedTableList?: FormEmbeddedTableProp[];\n formSaveVerifyJs?: Function | null;\n componentShowRule?: Record<string, any>;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n isLoading: false,\n data: () => ({}),\n formRules: () => ({}),\n pageId: undefined,\n embeddedTableList: () => [],\n formSaveVerifyJs: null,\n componentShowRule: () => ({}),\n});\n\nconst ruleFormRef = useTemplateRef<FormInstance>('ruleFormRef');\n\nconst pageIdRef = defineModel('pageId', {\n type: Number,\n required: false,\n default: undefined,\n});\nconst dataRef = defineModel('data', {\n type: Object as PropType<any>,\n default: () => {},\n});\nconst frameRef = defineModel('frame', {\n required: true,\n type: Array as PropType<FormFrame[]>,\n});\nconst componentShowRuleModel = defineModel('componentShowRule', {\n required: false,\n type: Object as PropType<any>,\n default: () => {},\n});\n\n// 此表单广播ID\nconst mittId = Math.floor(Math.random() * (99_999 - 10_000 + 1)) + 10_000;\n\nconst formWrapperRef = useTemplateRef<HTMLDivElement>('formWrapperRef')\nconst debouncedWidth = ref(0);\nuseResizeObserver(\n formWrapperRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedWidth.value = entry.contentRect.width;\n }\n }, 150),\n);\n\nconst formSpan = computed(() => {\n if (props.config.span) {\n return props.config.span;\n }\n if (props.config.responsive === false) {\n return 24;\n }\n if (debouncedWidth.value >= 1920) {\n return 6;\n } else if (debouncedWidth.value >= 1200) {\n return 6;\n } else if (debouncedWidth.value >= 992) {\n return 8;\n } else if (debouncedWidth.value >= 768) {\n return 12;\n } else if (debouncedWidth.value >= 600) {\n return 12;\n }\n return 24;\n});\n\n/** 表单验证 通过返回true 没有验证通过返回false */\nconst validateForm = async (): Promise<boolean> => {\n if (ruleFormRef.value === undefined || ruleFormRef.value === null) return false;\n\n // 不为空 则执行表单验证js\n if (props.formSaveVerifyJs !== null && props.formSaveVerifyJs !== undefined) {\n const err = props.formSaveVerifyJs(props.data);\n if (err) {\n msgTips.alert({\n msg: err,\n type: 'warning',\n });\n return false;\n }\n }\n return await formCheck(ruleFormRef.value);\n};\n\n// 清除验证\nconst clearValidate = () => {};\n\n// 重置表单\nconst resetFields = () => {\n ruleFormRef.value?.resetFields();\n};\n\n/** 打印为PDF */\nconst exportPDF = () => {\n // htmlToPDF(\n // formRenderRef,\n // props.data.datatitle,\n // {\n // scale: 3,\n // useCORS: true,\n // allowTaint: true\n // },\n // true,\n // new Date().toDateString()\n // );\n};\n\n// formData旧值缓存\nconst showComponents = reactive<any>({});\n\n/**\n * 树形框架数据\n */\nconst treeFrameData = ref<FormFrame[]>([]);\n\nconst { frameFormat } = useFrameFormat(treeFrameData);\n\nconst { setShow, initForm, getComponentValue } = useFormRender({\n frame: frameRef,\n frameFormat,\n data: dataRef,\n componentShowRule: componentShowRuleModel,\n showComponents,\n mittId,\n pageId: pageIdRef,\n rowKey: props.config.rowKey,\n});\n\ndefineExpose({\n validateForm,\n clearValidate,\n resetFields,\n exportPDF,\n initForm,\n});\n\nonMounted(() => {\n frameFormat(props.frame);\n});\n</script>\n\n<template>\n <div ref=\"formWrapperRef\" class=\"w-full h-full\">\n <el-form\n ref=\"ruleFormRef\"\n :label-position=\"config.labelPosition ? config.labelPosition : 'right'\"\n :label-width=\"\n config.labelWidth && config.labelWidth > 0 ? config.labelWidth : undefined\n \"\n :model=\"data\"\n :rules=\"formRules\"\n :style=\"{\n height:\n props.embeddedTableList && props.embeddedTableList.length > 0\n ? '60%'\n : '100%',\n }\"\n v-loading=\"isLoading\"\n >\n <ElRowPlus :gutter=\"6\">\n <template v-for=\"item in treeFrameData\" :key=\"item.field\">\n <ElColPlus\n v-if=\"item.formEditor === 'FormFieldset'\"\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <FormAreaRender\n v-model:data=\"dataRef\"\n :frame=\"item\"\n :show-components=\"showComponents\"\n :form-span=\"formSpan\"\n :mitt-id=\"mittId\"\n :get-component-value=\"getComponentValue\"\n :set-show=\"setShow\"\n />\n </ElColPlus>\n <ElColPlus\n v-else-if=\"showComponents[item.field] !== false\"\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <template v-if=\"item.formEditor === 'KeFormDivider'\">\n <FormDivider :detail=\"item\" />\n </template>\n <template v-else>\n <el-form-item\n :label=\"item.title\"\n :prop=\"item.field\"\n :rules=\"formRules?.[item.field] ? formRules[item.field] : []\"\n :label-width=\"item.labelWidth ? item.labelWidth : undefined\"\n class=\"form-item-label\"\n >\n <template v-if=\"item.placeholder\" #label>\n {{ item.title }}\n <el-tooltip :content=\"item.placeholder\">\n <div class=\"label-question\">\n <img :src=\"QuestionSVG\" alt=\"\" />\n </div>\n </el-tooltip>\n </template>\n\n <component\n :is=\"item.formEditor\"\n v-model:value=\"dataRef[item.field]\"\n :detail=\"item\"\n :disabled=\"item.disabled\"\n :field-name=\"item.field\"\n :field-title=\"item.title\"\n :mitt-id=\"mittId\"\n style=\"width: 100%\"\n @get-component-value=\"getComponentValue\"\n @set-show=\"setShow\"\n />\n </el-form-item>\n </template>\n </ElColPlus>\n </template>\n </ElRowPlus>\n </el-form>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.form-item-label {\n :deep(.el-form-item__label) {\n font-weight: normal;\n }\n}\n\n.label-question {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n</style>\n","<script setup lang=\"ts\">\n// import { htmlToPDF } from \"#/utils/html2Util\";\nimport type { FormInstance, FormRules } from 'element-plus';\n\nimport type { PropType } from 'vue';\n\nimport type {\n FormBasicInterface,\n FormEmbeddedTableProp,\n FormFrame,\n} from '@/types';\n\nimport { computed, onMounted, reactive, ref, useTemplateRef } from 'vue';\n\nimport { useDebounceFn, useResizeObserver } from '@vueuse/core';\n\nimport QuestionSVG from '@/assets/question.svg';\nimport { FormDivider } from '../FormDivider';\nimport { msgTips, formCheck } from '@/utils';\n\nimport FormAreaRender from './components/FormAreaRender.vue';\nimport { useFormRender, useFrameFormat } from './hooks/formRender.hook';\nimport { ElColPlus, ElRowPlus } from '@/components';\n\ninterface Props {\n isLoading?: boolean;\n data?: Record<string, any>;\n config: FormBasicInterface; // 保持你的类型名\n frame: FormFrame[];\n formRules?: FormRules<any>;\n pageId?: any;\n embeddedTableList?: FormEmbeddedTableProp[];\n formSaveVerifyJs?: Function | null;\n componentShowRule?: Record<string, any>;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n isLoading: false,\n data: () => ({}),\n formRules: () => ({}),\n pageId: undefined,\n embeddedTableList: () => [],\n formSaveVerifyJs: null,\n componentShowRule: () => ({}),\n});\n\nconst ruleFormRef = useTemplateRef<FormInstance>('ruleFormRef');\n\nconst pageIdRef = defineModel('pageId', {\n type: Number,\n required: false,\n default: undefined,\n});\nconst dataRef = defineModel('data', {\n type: Object as PropType<any>,\n default: () => {},\n});\nconst frameRef = defineModel('frame', {\n required: true,\n type: Array as PropType<FormFrame[]>,\n});\nconst componentShowRuleModel = defineModel('componentShowRule', {\n required: false,\n type: Object as PropType<any>,\n default: () => {},\n});\n\n// 此表单广播ID\nconst mittId = Math.floor(Math.random() * (99_999 - 10_000 + 1)) + 10_000;\n\nconst formWrapperRef = useTemplateRef<HTMLDivElement>('formWrapperRef')\nconst debouncedWidth = ref(0);\nuseResizeObserver(\n formWrapperRef,\n useDebounceFn((entries: ResizeObserverEntry[]) => {\n const entry = entries[0];\n if (entry) {\n debouncedWidth.value = entry.contentRect.width;\n }\n }, 150),\n);\n\nconst formSpan = computed(() => {\n if (props.config.span) {\n return props.config.span;\n }\n if (props.config.responsive === false) {\n return 24;\n }\n if (debouncedWidth.value >= 1920) {\n return 6;\n } else if (debouncedWidth.value >= 1200) {\n return 6;\n } else if (debouncedWidth.value >= 992) {\n return 8;\n } else if (debouncedWidth.value >= 768) {\n return 12;\n } else if (debouncedWidth.value >= 600) {\n return 12;\n }\n return 24;\n});\n\n/** 表单验证 通过返回true 没有验证通过返回false */\nconst validateForm = async (): Promise<boolean> => {\n if (ruleFormRef.value === undefined || ruleFormRef.value === null) return false;\n\n // 不为空 则执行表单验证js\n if (props.formSaveVerifyJs !== null && props.formSaveVerifyJs !== undefined) {\n const err = props.formSaveVerifyJs(props.data);\n if (err) {\n msgTips.alert({\n msg: err,\n type: 'warning',\n });\n return false;\n }\n }\n return await formCheck(ruleFormRef.value);\n};\n\n// 清除验证\nconst clearValidate = () => {};\n\n// 重置表单\nconst resetFields = () => {\n ruleFormRef.value?.resetFields();\n};\n\n/** 打印为PDF */\nconst exportPDF = () => {\n // htmlToPDF(\n // formRenderRef,\n // props.data.datatitle,\n // {\n // scale: 3,\n // useCORS: true,\n // allowTaint: true\n // },\n // true,\n // new Date().toDateString()\n // );\n};\n\n// formData旧值缓存\nconst showComponents = reactive<any>({});\n\n/**\n * 树形框架数据\n */\nconst treeFrameData = ref<FormFrame[]>([]);\n\nconst { frameFormat } = useFrameFormat(treeFrameData);\n\nconst { setShow, initForm, getComponentValue } = useFormRender({\n frame: frameRef,\n frameFormat,\n data: dataRef,\n componentShowRule: componentShowRuleModel,\n showComponents,\n mittId,\n pageId: pageIdRef,\n rowKey: props.config.rowKey,\n});\n\ndefineExpose({\n validateForm,\n clearValidate,\n resetFields,\n exportPDF,\n initForm,\n});\n\nonMounted(() => {\n frameFormat(props.frame);\n});\n</script>\n\n<template>\n <div ref=\"formWrapperRef\" class=\"w-full h-full\">\n <el-form\n ref=\"ruleFormRef\"\n :label-position=\"config.labelPosition ? config.labelPosition : 'right'\"\n :label-width=\"\n config.labelWidth && config.labelWidth > 0 ? config.labelWidth : undefined\n \"\n :model=\"data\"\n :rules=\"formRules\"\n :style=\"{\n height:\n props.embeddedTableList && props.embeddedTableList.length > 0\n ? '60%'\n : '100%',\n }\"\n v-loading=\"isLoading\"\n >\n <ElRowPlus :gutter=\"6\">\n <template v-for=\"item in treeFrameData\" :key=\"item.field\">\n <ElColPlus\n v-if=\"item.formEditor === 'FormFieldset'\"\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <FormAreaRender\n v-model:data=\"dataRef\"\n :frame=\"item\"\n :show-components=\"showComponents\"\n :form-span=\"formSpan\"\n :mitt-id=\"mittId\"\n :get-component-value=\"getComponentValue\"\n :set-show=\"setShow\"\n />\n </ElColPlus>\n <ElColPlus\n v-else-if=\"showComponents[item.field] !== false\"\n :span=\"item.formSpan ? item.formSpan : formSpan\"\n :break=\"item.formBreak\"\n >\n <template v-if=\"item.formEditor === 'KeFormDivider'\">\n <FormDivider :detail=\"item\" />\n </template>\n <template v-else>\n <el-form-item\n :label=\"item.title\"\n :prop=\"item.field\"\n :rules=\"formRules?.[item.field] ? formRules[item.field] : []\"\n :label-width=\"item.labelWidth ? item.labelWidth : undefined\"\n class=\"form-item-label\"\n >\n <template v-if=\"item.placeholder\" #label>\n {{ item.title }}\n <el-tooltip :content=\"item.placeholder\">\n <div class=\"label-question\">\n <img :src=\"QuestionSVG\" alt=\"\" />\n </div>\n </el-tooltip>\n </template>\n\n <component\n :is=\"item.formEditor\"\n v-model:value=\"dataRef[item.field]\"\n :detail=\"item\"\n :disabled=\"item.disabled\"\n :field-name=\"item.field\"\n :field-title=\"item.title\"\n :mitt-id=\"mittId\"\n style=\"width: 100%\"\n @get-component-value=\"getComponentValue\"\n @set-show=\"setShow\"\n />\n </el-form-item>\n </template>\n </ElColPlus>\n </template>\n </ElRowPlus>\n </el-form>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.form-item-label {\n :deep(.el-form-item__label) {\n font-weight: normal;\n }\n}\n\n.label-question {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n}\n</style>\n","import FormRender from './FormRender.vue';\nimport type { App } from 'vue';\n\n(FormRender as any).name = 'FormRender';\n\nFormRender.install = (app: App) => {\n app.component('FormRender', FormRender);\n};\n\nexport { FormRender };\n","import type { translateJSON, translateObj } from '@/types';\n\nimport { isEmpty } from '@/utils';\n\ninterface FormatterOptions {\n /** 表格数据 */\n cellValue: any;\n tabObj?: translateObj;\n translateJson: translateJSON;\n fieldName: string;\n /**\n * 翻译后的数据缓存 // 配合formatterData.array食用\n */\n translateObject?: any;\n /**\n * 循环索引\n */\n translateIndexArray?: { [propName: string]: any };\n}\n\n/**\n * 格式化grid-table数据\n *\n * @param options\n */\nexport const tableDataFormatter = (options: FormatterOptions): any => {\n if (isEmpty(options.cellValue)) return options.cellValue;\n\n const { translateJson, cellValue, fieldName } = options;\n\n // 1. 空值检查\n if (!translateJson) return cellValue;\n\n // 2. 类型守卫:排除数组情况,确保它是对象结构\n if (!Array.isArray(translateJson)) {\n // 此时 TS 知道 translateJson 是 { [propName: string]: any }\n // 如果 cellValue 可能是对象/复杂类型,建议转为字符串作为 key\n const key = String(cellValue);\n return translateJson[key] ?? cellValue;\n }\n\n // 3. 如果是数组,按数组逻辑处理(如 find)\n // 这里根据你的业务需求决定如何处理数组类型的 translateJson\n const item = translateJson.find(i => i.value == cellValue);\n return item?.label ?? cellValue;\n};\n","// 存储已经注册的模式化id\nimport { VxeUI } from 'vxe-table';\n\nimport { tableDataFormatter } from '@/components/FormComponent/hooks/useColumnRender.hook';\n\nconst hasFormats: any[] = [];\n// 存储注册的方法\nconst formatsMethods: any = {};\n\nexport const useTableFormats = () => {\n /**\n * 注册全局格式化\n * @param id\n * @param options\n */\n const register = (id: string, options: any) => {\n // console.log(\"注册格式化ID:\" + id);\n // 如果已经存在则不注册\n if (hasFormats.includes(id)) {\n return;\n }\n\n let translateJson: any = {};\n if (Array.isArray(options.translateJson)) {\n options.translateJson.forEach((item: any) => {\n translateJson[item.value] = item.label;\n });\n } else {\n translateJson = options.translateJson;\n }\n\n VxeUI.formats.add(id, {\n tableCellFormatMethod({ cellValue, column }) {\n return tableDataFormatter({\n cellValue,\n fieldName: column.field,\n tabObj: options.tabObj,\n translateJson,\n });\n },\n });\n formatsMethods[id] = ({ cellValue, column }: any) => {\n return tableDataFormatter({\n cellValue,\n fieldName: column.field,\n tabObj: options.tabObj,\n translateJson: options.translate,\n });\n };\n // 添加进已注册列表\n hasFormats.push(id);\n };\n\n const registerGeneralMethods = (id: string, func: Function) => {\n formatsMethods[id] = func;\n VxeUI.formats.add(id, {\n tableCellFormatMethod: (c) => { return func(c) },\n });\n };\n\n return {\n register,\n registerGeneralMethods,\n };\n};\n","import type { KeButton } from '@/types';\n\n/**\n * 拆分成toolbar按钮和数据上的按钮\n *\n * @param buttonList\n * @param buttonParams\n * @param funcModule\n */\nexport const useSplitApiButton = (\n buttonList: KeButton[],\n buttonParams: any,\n funcModule: Record<string, Function>,\n) => {\n const toolButtons: KeButton[] = [];\n const rowButtons: KeButton[] = [];\n\n buttonList.forEach((button) => {\n button.params = buttonParams;\n if (button.webTrigger) {\n button.webFunction = funcModule[button.id];\n }\n if (button.tableRow === true) {\n rowButtons.push(button);\n } else {\n toolButtons.push(button);\n }\n });\n\n return { toolButtons, rowButtons };\n};\n","import type { ModelRef, Ref, ShallowRef } from 'vue';\n\nimport type { AnyFunction, AutoSortTableDTO, BtnFunction, PagePath, Pagination } from '@/types';\n\nimport type { TableConfigInterface } from '@/types';\nimport type { CacheValue } from '@/types';\n\nimport { ref } from 'vue';\n\nimport { VxeUI } from 'vxe-table';\n\nimport { getEmbeddedTableDataApi } from '@/api';\nimport {\n changTableSortApi,\n deleteTableDataApi,\n getTableDataApi,\n getTreeTableDataApi,\n} from '@/api';\nimport { defaultPageTableConfig } from '@/config';\nimport { useTableFormats } from '@/hooks/useTableFormats.hook';\nimport { getRegisterComponent } from '@/config';\nimport { isEmpty, isNotEmpty, msgTips } from '@/utils';\n\nimport { useSplitApiButton } from '../hooks/useSplitApiButton';\nimport { appRouter } from '@/config';\n\n// 已经注册的格式化列表\nlet formatterKeyList: any[] = [];\n\ntype TableFormatterType = {\n columns: any[];\n pageId: number;\n};\n\nconst { register } = useTableFormats();\n\nexport const initTableFormatter = (data: TableFormatterType) => {\n // 先清除此页面的格式化缓存\n if (formatterKeyList.length > 0) {\n formatterKeyList.forEach((key) => {\n VxeUI.formats.delete(key);\n });\n formatterKeyList = [];\n }\n const registerComponent = getRegisterComponent();\n\n data.columns.forEach((col) => {\n // 注册格式化\n columnFormatter(col, data.pageId);\n if (col.editRender && registerComponent) {\n registerComponent(col.editRender?.name);\n }\n });\n\n return data.columns;\n};\n\nconst columnFormatter = (column: any, pageId: number) => {\n if (isNotEmpty(column.tabObj)) {\n if (column.tabObj === 'translate') {\n register(pageId + column.field, {\n tabObj: column.tabObj,\n translateJson: column.translate,\n });\n column.formatter = pageId + column.field;\n } else {\n column.formatter = column.tabObj;\n }\n }\n\n if (column.children && column.children.length > 0) {\n for (let i = 0; i < column.children.length; ++i) {\n columnFormatter(column.children[i], pageId);\n }\n }\n};\n\n/**\n * 拖拽结束前回调\n * @param event\n * @param pageId\n * @param key\n */\nconst dragEndMethod = async (\n event: any,\n pageId: number,\n key: any,\n): Promise<boolean> => {\n if (event.dragPos === 'bottom') {\n msgTips.tips({\n msg: '只能向上拖拽哦!',\n type: 'warning',\n });\n return false;\n }\n\n const params: AutoSortTableDTO = {\n pageId,\n upData: event.oldRow[key].toString(),\n bottomData: event.newRow[key].toString(),\n };\n const result = await changTableSortApi(params);\n return result.code === 0;\n};\n/**\n * 处理从后端获取的tableRender\n * @param data\n * @param pageId\n * @param btnClickFunc\n * @param funcModule 方法对象\n * @param treeLazyLoad\n */\nexport const useConfigurationProcess = (\n data: any,\n pageId: number,\n btnClickFunc: Record<string, AnyFunction>,\n funcModule: BtnFunction,\n treeLazyLoad?: (...args: any) => void,\n): CacheValue => {\n const newTablePageConfig: CacheValue = { ...defaultPageTableConfig };\n\n // // 加工表格frame\n newTablePageConfig.gridOptions.columns = initTableFormatter({\n columns: data.tableFrame,\n pageId,\n });\n\n // 如果是tree 则需要设置树节点\n if (\n data.tableConfig.tree &&\n newTablePageConfig.gridOptions.columns.length >= 2\n ) {\n const col1 = newTablePageConfig.gridOptions.columns[1];\n if (col1 !== null && col1 !== undefined) {\n col1.treeNode = true;\n newTablePageConfig.gridOptions.columns[1] = col1;\n }\n\n // 配置表格的树配置\n newTablePageConfig.gridOptions.treeConfig = {\n transform: true,\n rowField: data.tableConfig.rowKey,\n parentField: data.tableConfig.parentField,\n lazy: true,\n hasChildField: 'has_tree_child',\n loadMethod({ row }) {\n return new Promise<any[]>((resolve) => {\n // 调用你的 treeLazyLoad,把 resolve 传进去\n if (treeLazyLoad) {\n treeLazyLoad(\n row,\n (data: any[]) => {\n // 当 syncTableData 内部调用 resolve(data) 时,\n // 这个 data 会作为 Promise 的结果返回给 vxe-table\n resolve(data || []);\n },\n {}, // 确保 queryData 有定义,比如来自外部 props 或变量\n );\n }\n });\n },\n };\n } else {\n newTablePageConfig.gridOptions.treeConfig = undefined;\n }\n\n // 设置拖拽排序相关\n if (data.tableConfig.dragSort) {\n // 设置允许拖拽\n newTablePageConfig.gridOptions.rowConfig = {\n drag: true,\n };\n // 设置拖拽回调\n newTablePageConfig.gridOptions.rowDragConfig = {\n dragEndMethod: async (event: any) =>\n dragEndMethod(event, pageId, data.tableConfig.rowKey),\n };\n }\n\n btnClickFunc[\"getPageId\"] = () => {\n return pageId;\n }\n // 对按钮分组\n const { toolButtons, rowButtons } = useSplitApiButton(\n data.tableButton,\n btnClickFunc,\n funcModule,\n );\n newTablePageConfig.tableToolButtons = toolButtons;\n newTablePageConfig.tableRowButtons = rowButtons;\n\n return newTablePageConfig;\n};\n\ninterface RequestTable {\n pageId: ModelRef<number | undefined>\n queryTreeFilter: ShallowRef;\n /**\n * 分页\n */\n pagination: Ref<Pagination>;\n /**\n * 弹窗实例\n */\n appFormWindowRef: Ref;\n /**\n * 嵌入页面ID\n */\n embeddedId?: number;\n /**\n * 页面嵌入路径\n */\n pagePath?: PagePath[];\n}\n\n/**\n * 获取/刷新表格数据\n * @param params\n */\nexport function useTableData(params: RequestTable) {\n const {\n queryTreeFilter,\n pagination,\n appFormWindowRef,\n embeddedId,\n pagePath,\n pageId,\n } = params;\n\n const tableConfig = ref<TableConfigInterface>({} as TableConfigInterface);\n const loading = ref(false);\n const tableData = ref<any[]>([]);\n let queryDataLib: any = {};\n\n const getTableData = async (queryData?: any, callback?: () => void) => {\n if (isEmpty(tableConfig.value.pageId)) {\n return;\n }\n loading.value = true;\n\n // 查询数据\n if (queryData) queryDataLib = queryData;\n\n /**\n * 若存在queryTreeFilter 则去获取queryTreeFilter的查询内容\n */\n if (queryTreeFilter.value && tableConfig.value.parentField) {\n const filterData = queryTreeFilter.value.getCheckboxes();\n queryDataLib[tableConfig.value.parentField] = {\n val: filterData.val,\n queryType: 'hasAny',\n };\n }\n\n const result = await getTableDataApi(\n tableConfig.value.pageId,\n pagination.value.currentPage,\n queryDataLib,\n );\n loading.value = false;\n if (result.code === 0) {\n if (callback) {\n callback();\n }\n return result.data;\n // tableData.value = result.data.tableData;\n // pagination.value.pageSize = result.data.pageSize;\n // pagination.value.total = result.data.total;\n }\n\n return null;\n };\n const getEmbeddedTableData = async (\n queryData?: any,\n callback?: () => void,\n ) => {\n if (isEmpty(tableConfig.value.pageId)) {\n return;\n }\n loading.value = true;\n // 查询数据\n if (queryData) queryDataLib = queryData;\n\n /**\n * 若存在queryTreeFilter 则去获取queryTreeFilter的查询内容\n */\n if (queryTreeFilter.value && tableConfig.value.parentField) {\n const filterData = queryTreeFilter.value.getCheckboxes();\n queryDataLib[tableConfig.value.parentField] = {\n val: filterData.val,\n queryType: 'hasAny',\n };\n }\n\n let result;\n if (embeddedId && Array.isArray(pagePath)) {\n result = await getEmbeddedTableDataApi({\n embeddedId,\n pageNum: pagination.value.currentPage,\n pagePaths: pagePath,\n queryData: queryDataLib,\n });\n } else {\n msgTips.alert({\n msg: !embeddedId ? '数据结构异常,未获取到嵌入表ID' : '渲染结构pagePath异常',\n type: 'error'\n });\n result = {\n code: 0,\n data: []\n };\n }\n\n\n\n loading.value = false;\n if (result.code === 0) {\n if (callback) {\n callback();\n }\n return result.data;\n }\n\n return null;\n };\n const getTableTreeData = async (\n queryData?: any,\n callback?: ((data: any) => void) | undefined,\n parentNodeData?: any,\n ) => {\n if (\n isEmpty(tableConfig.value.parentField) ||\n isEmpty(tableConfig.value.pageId)\n ) {\n return;\n }\n loading.value = true;\n // 查询数据\n if (queryData) queryDataLib = queryData;\n\n // 如果不存在父节点需要设置默认值\n if (!queryDataLib[tableConfig.value.parentField]) {\n queryDataLib[tableConfig.value.parentField] = {\n val: parentNodeData || tableConfig.value.treeDefault,\n queryType: 'equals',\n };\n }\n\n const parentId = parentNodeData || tableConfig.value.treeDefault;\n\n // 获取tree懒加载数据\n const result = await getTreeTableDataApi(\n tableConfig.value.pageId,\n parentId,\n queryDataLib,\n );\n if (result.code === 0) {\n if (callback) {\n callback(result.data);\n } else {\n tableData.value = result.data;\n }\n }\n\n loading.value = false;\n };\n\n /**\n * 刷新/获取数据\n */\n const syncTableData = async (\n queryData?: any,\n callback?: AnyFunction,\n parentNodeData?: any,\n ) => {\n if (tableConfig.value.tree) {\n if (\n parentNodeData &&\n parentNodeData[tableConfig.value.rowKey] &&\n tableConfig.value.parentField\n ) {\n if (!queryData) {\n queryData = {};\n }\n queryData[tableConfig.value.parentField] = {\n val: parentNodeData[tableConfig.value.rowKey],\n queryType: 'equals',\n };\n }\n await getTableTreeData(queryData, callback);\n } else {\n const result: any = await (embeddedId\n ? getEmbeddedTableData(queryData, callback)\n : getTableData(queryData, callback));\n tableData.value = result.tableData;\n pagination.value.pageSize = result.pageSize;\n pagination.value.total = result.total;\n }\n };\n\n const btnClickFunc = {\n getConfig: () => {\n return {\n pageId,\n tableConfig,\n pagePath,\n }\n },\n openForm: (data: any, rowIndex: number, render?: AnyFunction) => {\n // 默认传参\n const params = {\n dataId: data[tableConfig.value.rowKey],\n pageId: pageId.value,\n };\n\n // 如果是函数,则从次获取数据\n if (typeof render === 'function') {\n const renderData = render(data);\n\n // 若有数据ID 则赋值\n if (renderData.dataId) {\n params.dataId = renderData.dataId;\n }\n\n // 若有页面ID 则赋值\n if (renderData.pageId) {\n params.pageId = renderData.pageId;\n }\n }\n\n appFormWindowRef.value.openForm({\n rowKey: params.dataId,\n pageId: params.pageId,\n rowIndex,\n });\n },\n deleteData: async (data: any) => {\n if (!tableConfig.value.deleteBtn) {\n msgTips.tips({\n msg: '尚未开启删除功能!',\n type: 'warning',\n });\n return;\n }\n if (isEmpty(pageId.value)) {\n return;\n }\n loading.value = true;\n const result = await deleteTableDataApi(\n pageId.value,\n data[tableConfig.value.rowKey].toString(),\n );\n if (result.code === 0) {\n await syncTableData();\n }\n loading.value = false;\n },\n refreshTableData: async () => {\n await syncTableData();\n },\n routerPush: (key: any, options: any) => {\n appRouter.push(key, options);\n },\n };\n\n return {\n tableData,\n queryDataLib,\n syncTableData,\n btnClickFunc,\n tableConfig,\n pageId,\n };\n}\n\ntype UpdateDataByRow = {\n rowIndex: number;\n tableConfig: Ref<TableConfigInterface>;\n tableData: Ref<any[]>;\n};\n/**\n * 更新指定行的数据\n * @param params\n */\nexport async function updateDataByRowIndex(params: UpdateDataByRow) {\n const { rowIndex, tableConfig, tableData } = params;\n if (isEmpty(tableConfig.value.pageId)) {\n return;\n }\n\n /**\n * 获取主键\n */\n const rowKey: string = tableConfig.value.rowKey;\n const rowData = tableData.value[rowIndex];\n\n /**\n * 构建查询\n */\n const queryDataLib: any = {};\n queryDataLib[rowKey] = {\n val: rowData[rowKey],\n queryType: 'equals',\n };\n\n const result = await getTableDataApi(\n tableConfig.value.pageId,\n 1,\n queryDataLib,\n );\n if (result.code === 0) {\n tableData.value[rowIndex] = result.data.tableData[0];\n }\n}\n","<script setup lang=\"ts\">\nimport type { PagePath } from '@/types';\n\nimport { reactive, ref } from 'vue';\n\nimport AppFormRender from '../../AppFormRender.vue';\n\ninterface Props {\n pageId: number;\n embeddedId: number;\n pagePath: PagePath[];\n}\n\nwithDefaults(defineProps<Props>(), {});\n\nconst emits = defineEmits(['dataChange']);\n\nconst AppFormRenderRef = ref();\nconst dialogState = ref(false);\nconst pageState = reactive({\n embeddedId: 0,\n dataId: '',\n});\n\n/**\n * 当前数据在表格的索引\n */\nlet onDataRowIndex = -1;\n\nconst dataChange = () => {\n emits('dataChange', onDataRowIndex);\n};\n\ninterface OpenForm {\n /**\n * 主键\n */\n rowKey: any;\n /**\n * 页面ID\n */\n embeddedId: number;\n /**\n * 行数\n */\n rowIndex: number;\n}\n\n/**\n * 打开抽屉\n *\n * @param params\n */\nconst openForm = (params: OpenForm) => {\n const isAdd = typeof params.rowKey === 'boolean';\n pageState.dataId = isAdd ? 'new' : params.rowKey;\n pageState.embeddedId = params.embeddedId;\n dialogState.value = true;\n onDataRowIndex = params.rowIndex;\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\n};\n\nconst close = () => {\n dialogState.value = false;\n};\n\ndefineExpose({ openForm });\n</script>\n\n<template>\n <el-dialog\n v-model=\"dialogState\"\n :show-close=\"false\"\n width=\"78%\"\n append-to-body\n destroy-on-close\n draggable\n align-center\n >\n <div class=\"dia-container\">\n <AppFormRender\n ref=\"AppFormRenderRef\"\n v-model:data-id=\"pageState.dataId\"\n :embedded-id=\"embeddedId\"\n :page-id=\"pageId\"\n :page-path=\"pagePath\"\n :show-window-button=\"false\"\n @close=\"close\"\n @data-change=\"dataChange\"\n />\n </div>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.dia-container {\n height: calc(100vh - 220px);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PagePath } from '@/types';\n\nimport { reactive, ref } from 'vue';\n\nimport AppFormRender from '../../AppFormRender.vue';\n\ninterface Props {\n pageId: number;\n embeddedId: number;\n pagePath: PagePath[];\n}\n\nwithDefaults(defineProps<Props>(), {});\n\nconst emits = defineEmits(['dataChange']);\n\nconst AppFormRenderRef = ref();\nconst dialogState = ref(false);\nconst pageState = reactive({\n embeddedId: 0,\n dataId: '',\n});\n\n/**\n * 当前数据在表格的索引\n */\nlet onDataRowIndex = -1;\n\nconst dataChange = () => {\n emits('dataChange', onDataRowIndex);\n};\n\ninterface OpenForm {\n /**\n * 主键\n */\n rowKey: any;\n /**\n * 页面ID\n */\n embeddedId: number;\n /**\n * 行数\n */\n rowIndex: number;\n}\n\n/**\n * 打开抽屉\n *\n * @param params\n */\nconst openForm = (params: OpenForm) => {\n const isAdd = typeof params.rowKey === 'boolean';\n pageState.dataId = isAdd ? 'new' : params.rowKey;\n pageState.embeddedId = params.embeddedId;\n dialogState.value = true;\n onDataRowIndex = params.rowIndex;\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\n};\n\nconst close = () => {\n dialogState.value = false;\n};\n\ndefineExpose({ openForm });\n</script>\n\n<template>\n <el-dialog\n v-model=\"dialogState\"\n :show-close=\"false\"\n width=\"78%\"\n append-to-body\n destroy-on-close\n draggable\n align-center\n >\n <div class=\"dia-container\">\n <AppFormRender\n ref=\"AppFormRenderRef\"\n v-model:data-id=\"pageState.dataId\"\n :embedded-id=\"embeddedId\"\n :page-id=\"pageId\"\n :page-path=\"pagePath\"\n :show-window-button=\"false\"\n @close=\"close\"\n @data-change=\"dataChange\"\n />\n </div>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.dia-container {\n height: calc(100vh - 220px);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PagePath, Pagination, KeButton, TableQueryFrame } from '@/types';\n\nimport { onMounted, ref, useTemplateRef } from 'vue';\n\nimport {\n getEmbeddedTableDataApi,\n getEmbeddedTableRenderApi,\n onValueChangeApi,\n} from '@/api';\nimport { BASE_URL, defaultPageTableConfig } from '@/config';\nimport { getRandomString, msgTips } from '@/utils';\n\nimport {\n useConfigurationProcess,\n useTableData,\n} from '../../hooks/useTable.hook';\nimport EmbeddedDialogForm from './EmbeddedDialogForm.vue';\nimport { QueryTreeFilter } from '@/components/QueryComponent/QueryTreeFilter'\n\ninterface Props {\n embeddedId: number;\n pagePath: PagePath[];\n}\n\ninterface QueryTreeFilter {\n getCheckboxes: Function;\n}\n\nconst props = withDefaults(defineProps<Props>(), {});\n\nconst pageId = defineModel<number>('embeddedId')\n\nconst loading = ref(false);\nconst gridOptions = ref<any>({});\nconst queryTreeFilter = useTemplateRef<QueryTreeFilter>('queryTreeFilter');\nconst appFormWindowRef = useTemplateRef('appFormWindowRef');\n// 表格列\nconst columns = ref<any[]>([]);\nconst queryConfig = ref<TableQueryFrame[]>([]);\nconst tableToolButtons = ref<KeButton[]>([]);\nconst tableRowButtons = ref<KeButton[]>([]);\n\nconst tablePagination = ref<Pagination>({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n});\n\nconst { tableData, syncTableData, btnClickFunc, tableConfig } =\n useTableData({\n pageId,\n queryTreeFilter,\n pagination: tablePagination,\n appFormWindowRef,\n embeddedId: props.embeddedId,\n pagePath: props.pagePath,\n });\n\n/**\n * 指定行数据更新\n * @param rowIndex\n */\nconst onDataChange = async (rowIndex: number) => {\n if (rowIndex < 0 || !rowIndex) {\n await syncTableData();\n return;\n }\n loading.value = true;\n const data = tableData.value[rowIndex];\n\n const queryLib: any = {};\n queryLib[tableConfig.value.rowKey] = {\n val: data[tableConfig.value.rowKey],\n queryType: 'equals',\n };\n const result = await getEmbeddedTableDataApi({\n embeddedId: props.embeddedId,\n pageNum: tablePagination.value.currentPage,\n pagePaths: props.pagePath,\n queryData: queryLib,\n });\n if (result.code === 0 && result.data.tableData.length > 0) {\n tableData.value[rowIndex] = result.data.tableData[0];\n }\n loading.value = false;\n};\n\n/**\n * 当检测到值改变\n * @param fieldName\n * @param newValue\n * @param rowId\n */\nconst onValueChange = async (\n fieldName: string,\n newValue: any,\n rowId: string,\n) => {\n loading.value = true;\n const result = await onValueChangeApi({\n pagePaths: props.pagePath,\n tablePageId: tableConfig.value.pageId,\n fieldName,\n newValue,\n rowId,\n });\n if (result.code === 0) {\n msgTips.tips({\n type: 'success',\n msg: '修改成功!',\n });\n }\n loading.value = false;\n};\n\nconst getEmbeddedTableConfig = async () => {\n loading.value = true;\n const result = await getEmbeddedTableRenderApi(\n props.embeddedId,\n props.pagePath,\n );\n\n if (result.code === 0) {\n pageId.value = result.data.tableConfig.pageId;\n const { tableButtons: modules } = await import(\n `${BASE_URL.value}/app/js/table/${result.data.tableConfig.pageId}?time=${getRandomString(3)}`\n );\n const configCacheValue = useConfigurationProcess(\n result.data,\n result.data.tableConfig.pageId,\n btnClickFunc,\n modules,\n );\n\n tableConfig.value = result.data.tableConfig;\n queryConfig.value = result.data.queryFrameList;\n if (configCacheValue.gridOptions.columns) {\n columns.value = configCacheValue.gridOptions.columns;\n }\n gridOptions.value = configCacheValue.gridOptions;\n gridOptions.value.columns = [];\n tableToolButtons.value = configCacheValue.tableToolButtons;\n tableRowButtons.value = configCacheValue.tableRowButtons;\n await syncTableData();\n }\n loading.value = false;\n};\n\nonMounted(() => {\n gridOptions.value = { ...defaultPageTableConfig.gridOptions };\n getEmbeddedTableConfig();\n});\n</script>\n\n<template>\n <div class=\"board\" v-loading=\"loading\">\n <div\n v-if=\"tableConfig.pageId && tableConfig.hasQueryTreeFilter\"\n class=\"query-tree\"\n >\n <QueryTreeFilter ref=\"queryTreeFilter\" :page-id=\"tableConfig.pageId\" />\n </div>\n <div v-if=\"tableConfig.pageId\" class=\"page-root\">\n <component\n :is=\"tableConfig.showType\"\n :columns=\"columns\"\n :query-config=\"queryConfig\"\n :table-config=\"tableConfig\"\n :table-data=\"tableData\"\n :table-id=\"tableConfig.pageId\"\n :table-pagination=\"tablePagination\"\n :table-row-buttons=\"tableRowButtons\"\n :table-tool-buttons=\"tableToolButtons\"\n :vxe-grid-options=\"gridOptions\"\n @query-click=\"syncTableData\"\n @value-change=\"onValueChange\"\n />\n </div>\n <EmbeddedDialogForm\n v-if=\"tableConfig.pageId\"\n ref=\"appFormWindowRef\"\n :embedded-id=\"embeddedId\"\n :page-id=\"tableConfig.pageId\"\n :page-path=\"pagePath\"\n @data-change=\"onDataChange\"\n />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.board {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n background: var(--overlay-content);\n min-height: 0; /* 防止 flex 子元素在 shrink 时高度异常 */\n}\n.query-tree {\n width: 240px;\n}\n.page-root {\n flex: 1; /* 剩余空间 */\n //width: 100%;\n min-width: 0; /* 避免内容强制撑开 */\n max-width: 100%; /* 防止过大 */\n transition: width 0.1s linear; /* 平滑宽度变化,消除卡顿感 */\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PagePath, Pagination, KeButton, TableQueryFrame } from '@/types';\n\nimport { onMounted, ref, useTemplateRef } from 'vue';\n\nimport {\n getEmbeddedTableDataApi,\n getEmbeddedTableRenderApi,\n onValueChangeApi,\n} from '@/api';\nimport { BASE_URL, defaultPageTableConfig } from '@/config';\nimport { getRandomString, msgTips } from '@/utils';\n\nimport {\n useConfigurationProcess,\n useTableData,\n} from '../../hooks/useTable.hook';\nimport EmbeddedDialogForm from './EmbeddedDialogForm.vue';\nimport { QueryTreeFilter } from '@/components/QueryComponent/QueryTreeFilter'\n\ninterface Props {\n embeddedId: number;\n pagePath: PagePath[];\n}\n\ninterface QueryTreeFilter {\n getCheckboxes: Function;\n}\n\nconst props = withDefaults(defineProps<Props>(), {});\n\nconst pageId = defineModel<number>('embeddedId')\n\nconst loading = ref(false);\nconst gridOptions = ref<any>({});\nconst queryTreeFilter = useTemplateRef<QueryTreeFilter>('queryTreeFilter');\nconst appFormWindowRef = useTemplateRef('appFormWindowRef');\n// 表格列\nconst columns = ref<any[]>([]);\nconst queryConfig = ref<TableQueryFrame[]>([]);\nconst tableToolButtons = ref<KeButton[]>([]);\nconst tableRowButtons = ref<KeButton[]>([]);\n\nconst tablePagination = ref<Pagination>({\n currentPage: 1,\n pageSize: 0,\n total: 0,\n});\n\nconst { tableData, syncTableData, btnClickFunc, tableConfig } =\n useTableData({\n pageId,\n queryTreeFilter,\n pagination: tablePagination,\n appFormWindowRef,\n embeddedId: props.embeddedId,\n pagePath: props.pagePath,\n });\n\n/**\n * 指定行数据更新\n * @param rowIndex\n */\nconst onDataChange = async (rowIndex: number) => {\n if (rowIndex < 0 || !rowIndex) {\n await syncTableData();\n return;\n }\n loading.value = true;\n const data = tableData.value[rowIndex];\n\n const queryLib: any = {};\n queryLib[tableConfig.value.rowKey] = {\n val: data[tableConfig.value.rowKey],\n queryType: 'equals',\n };\n const result = await getEmbeddedTableDataApi({\n embeddedId: props.embeddedId,\n pageNum: tablePagination.value.currentPage,\n pagePaths: props.pagePath,\n queryData: queryLib,\n });\n if (result.code === 0 && result.data.tableData.length > 0) {\n tableData.value[rowIndex] = result.data.tableData[0];\n }\n loading.value = false;\n};\n\n/**\n * 当检测到值改变\n * @param fieldName\n * @param newValue\n * @param rowId\n */\nconst onValueChange = async (\n fieldName: string,\n newValue: any,\n rowId: string,\n) => {\n loading.value = true;\n const result = await onValueChangeApi({\n pagePaths: props.pagePath,\n tablePageId: tableConfig.value.pageId,\n fieldName,\n newValue,\n rowId,\n });\n if (result.code === 0) {\n msgTips.tips({\n type: 'success',\n msg: '修改成功!',\n });\n }\n loading.value = false;\n};\n\nconst getEmbeddedTableConfig = async () => {\n loading.value = true;\n const result = await getEmbeddedTableRenderApi(\n props.embeddedId,\n props.pagePath,\n );\n\n if (result.code === 0) {\n pageId.value = result.data.tableConfig.pageId;\n const { tableButtons: modules } = await import(\n `${BASE_URL.value}/app/js/table/${result.data.tableConfig.pageId}?time=${getRandomString(3)}`\n );\n const configCacheValue = useConfigurationProcess(\n result.data,\n result.data.tableConfig.pageId,\n btnClickFunc,\n modules,\n );\n\n tableConfig.value = result.data.tableConfig;\n queryConfig.value = result.data.queryFrameList;\n if (configCacheValue.gridOptions.columns) {\n columns.value = configCacheValue.gridOptions.columns;\n }\n gridOptions.value = configCacheValue.gridOptions;\n gridOptions.value.columns = [];\n tableToolButtons.value = configCacheValue.tableToolButtons;\n tableRowButtons.value = configCacheValue.tableRowButtons;\n await syncTableData();\n }\n loading.value = false;\n};\n\nonMounted(() => {\n gridOptions.value = { ...defaultPageTableConfig.gridOptions };\n getEmbeddedTableConfig();\n});\n</script>\n\n<template>\n <div class=\"board\" v-loading=\"loading\">\n <div\n v-if=\"tableConfig.pageId && tableConfig.hasQueryTreeFilter\"\n class=\"query-tree\"\n >\n <QueryTreeFilter ref=\"queryTreeFilter\" :page-id=\"tableConfig.pageId\" />\n </div>\n <div v-if=\"tableConfig.pageId\" class=\"page-root\">\n <component\n :is=\"tableConfig.showType\"\n :columns=\"columns\"\n :query-config=\"queryConfig\"\n :table-config=\"tableConfig\"\n :table-data=\"tableData\"\n :table-id=\"tableConfig.pageId\"\n :table-pagination=\"tablePagination\"\n :table-row-buttons=\"tableRowButtons\"\n :table-tool-buttons=\"tableToolButtons\"\n :vxe-grid-options=\"gridOptions\"\n @query-click=\"syncTableData\"\n @value-change=\"onValueChange\"\n />\n </div>\n <EmbeddedDialogForm\n v-if=\"tableConfig.pageId\"\n ref=\"appFormWindowRef\"\n :embedded-id=\"embeddedId\"\n :page-id=\"tableConfig.pageId\"\n :page-path=\"pagePath\"\n @data-change=\"onDataChange\"\n />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.board {\n display: flex;\n flex-direction: column; /* 垂直排列子元素 */\n height: 100%; /* 父容器占据100%高度 */\n background: var(--overlay-content);\n min-height: 0; /* 防止 flex 子元素在 shrink 时高度异常 */\n}\n.query-tree {\n width: 240px;\n}\n.page-root {\n flex: 1; /* 剩余空间 */\n //width: 100%;\n min-width: 0; /* 避免内容强制撑开 */\n max-width: 100%; /* 防止过大 */\n transition: width 0.1s linear; /* 平滑宽度变化,消除卡顿感 */\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FileUpload, FileUploadField } from '@/types';\n\nimport { computed, onMounted, reactive, ref } from 'vue';\n\nimport { Refresh, Upload } from '@element-plus/icons-vue';\n\nimport { getPageUploadFileApi, deletePageUploadFileApi } from '@/api';\nimport logoMini from '@/assets/avatar.svg';\nimport { UPLOAD_FILE_URL, FILE_URL } from '@/config';\nimport { dataFormatter, isEmpty, isImage, msgTips } from '@/utils';\n\nconst {\n dataId,\n pageId = null,\n fileKinds = [],\n} = defineProps<{\n dataId: any;\n fileKinds?: FileUploadField[];\n pageId?: number;\n}>();\n\nconst fileKindsArr = computed(() => {\n const newArr: string[] = [];\n fileKinds.forEach((fileKind) => {\n newArr.push(fileKind.fieldName);\n });\n return newArr;\n});\n\nconst loading = ref(false);\n\nconst tableState = reactive<any>({\n onField: '',\n tableData: [] as PropType<FileUpload[]>,\n uploadUrl: '',\n});\n\ninterface GalleryState {\n /**\n * 预览的图片地址\n */\n images: string[]\n /**\n * 当前预览下标\n */\n currentImageIndex: number\n showVisible: boolean\n}\nconst galleryState = reactive<GalleryState>({\n images: [],\n currentImageIndex: 0,\n showVisible: false,\n});\n\nconst viewFile = (index: number) => {\n galleryState.currentImageIndex = index;\n galleryState.showVisible = true;\n};\n\n/**\n * 是否图片\n *\n * @param file\n */\nconst getSrcUrl = (file: FileUpload): string => {\n if (isImage(file.fileType)) {\n return `${FILE_URL.value}/${file.id}/${file.fileOriginalName}`;\n }\n return logoMini;\n};\n\n/** 获取已上传文件列表 */\nconst getUploadFile = async () => {\n if (pageId === null) {\n return;\n }\n loading.value = true;\n const result = await getPageUploadFileApi(pageId, dataId);\n if (result.code === 0) {\n tableState.tableData = result.data;\n\n galleryState.images = [];\n for (let i = 0; i < result.data.length; i += 1) {\n galleryState.images.push(getSrcUrl(result.data[i]));\n }\n }\n\n loading.value = false;\n};\n\n/** 图片上传到服务器前执行程序 */\nconst beforeUpload = () => {\n if (isEmpty(tableState.onField)) {\n msgTips.tips({\n msg: '请先选择上传类型',\n type: 'warning',\n });\n return false;\n }\n tableState.uploadUrl = `${UPLOAD_FILE_URL.value}/${pageId}/${dataId}/${tableState.onField}`;\n};\n\n/**\n * 上传\n */\nconst uploadFileClick = () => {\n if (!beforeUpload()) {\n return;\n }\n let fileInput: any;\n // 创建文件选择输入框(如果尚未创建)\n if (!fileInput) {\n fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.style.display = 'none';\n fileInput.addEventListener('change', async () => {\n // 处理文件选择事件,如果需要的话\n console.log('文件已选择:', fileInput.files[0].name);\n\n // 创建文件的上传对象\n const file = fileInput.files[0];\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await fetch(tableState.uploadUrl, {\n method: 'POST',\n body: formData,\n });\n\n fileInput.value = '';\n\n if (response.ok) {\n const result = await response.json();\n msgTips.alert({\n msg: result.msg,\n type: 'success',\n });\n getUploadFile();\n } else {\n // 请求失败\n msgTips.alert({\n msg: `请求失败:${response.statusText}`,\n type: 'success',\n });\n }\n });\n document.body.append(fileInput);\n\n // 触发文件选择输入框的点击事件\n fileInput.click();\n }\n};\n\nconst deleteFile = async (fileId: number) => {\n await deletePageUploadFileApi(fileId);\n await getUploadFile();\n};\n\n/**\n * 打开dialog\n *\n */\nconst init = () => {\n getUploadFile();\n\n if (isEmpty(tableState.onField) && fileKinds.length > 0) {\n tableState.onField = fileKinds[0]!.fieldName;\n }\n};\n\nonMounted(() => {\n init();\n});\n</script>\n\n<template>\n <div>\n <div class=\"upload-container\">\n <el-select v-model=\"tableState.onField\">\n <el-option\n v-for=\"item in fileKinds\"\n :key=\"item.fieldName\"\n :label=\"item.fieldTitle\"\n :value=\"item.fieldName\"\n />\n </el-select>\n <div class=\"right-button\">\n <el-button @click=\"getUploadFile\" :loading=\"loading\">\n 刷新<el-icon><Refresh /></el-icon>\n </el-button>\n <el-button type=\"primary\" @click=\"uploadFileClick\">\n 上传<el-icon class=\"el-icon--right\"><Upload /></el-icon>\n </el-button>\n </div>\n </div>\n <div class=\"mt-2\" v-loading=\"loading\">\n <el-table :data=\"tableState.tableData\" border style=\"width: 100%\">\n <el-table-column label=\"文件名\" min-width=\"180\" prop=\"fileOriginalName\">\n <template #default=\"{ $index, row }\">\n <el-link type=\"primary\" @click=\"viewFile($index)\">\n {{ row.fileOriginalName }}\n </el-link>\n </template>\n </el-table-column>\n <el-table-column label=\"上传类型\" prop=\"type\">\n <template #default=\"scope\">\n <el-select v-model=\"scope.row.type\" disabled>\n <el-option\n v-for=\"item in fileKinds\"\n :key=\"item.fieldName\"\n :label=\"item.fieldTitle\"\n :value=\"item.fieldName\"\n />\n </el-select>\n </template>\n </el-table-column>\n <el-table-column label=\"文件类型\" prop=\"fileType\" />\n <el-table-column label=\"上传人\" prop=\"createBy\" />\n <el-table-column label=\"上传时间\" prop=\"createTime\" width=\"160\">\n <template #default=\"scope\">\n {{ dataFormatter.timestamp(scope.row.createTime) }}\n </template>\n </el-table-column>\n <el-table-column label=\"操作\" prop=\"options\">\n <template #default=\"{ row }\">\n <el-button\n v-if=\"fileKindsArr.includes(row.type)\"\n size=\"small\"\n type=\"danger\"\n @click=\"deleteFile(row.id)\"\n >\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n <el-image-viewer\n v-if=\"galleryState.showVisible\"\n :initial-index=\"galleryState.currentImageIndex\"\n :url-list=\"galleryState.images\"\n @close=\"galleryState.showVisible = false\"\n />\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.upload-container {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.upload-container .el-select {\n max-width: 300px;\n}\n\n.right-button {\n display: flex;\n justify-content: flex-end; /* 按钮右对齐 */\n align-items: center; /* 按钮垂直居中 */\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { FileUpload, FileUploadField } from '@/types';\n\nimport { computed, onMounted, reactive, ref } from 'vue';\n\nimport { Refresh, Upload } from '@element-plus/icons-vue';\n\nimport { getPageUploadFileApi, deletePageUploadFileApi } from '@/api';\nimport logoMini from '@/assets/avatar.svg';\nimport { UPLOAD_FILE_URL, FILE_URL } from '@/config';\nimport { dataFormatter, isEmpty, isImage, msgTips } from '@/utils';\n\nconst {\n dataId,\n pageId = null,\n fileKinds = [],\n} = defineProps<{\n dataId: any;\n fileKinds?: FileUploadField[];\n pageId?: number;\n}>();\n\nconst fileKindsArr = computed(() => {\n const newArr: string[] = [];\n fileKinds.forEach((fileKind) => {\n newArr.push(fileKind.fieldName);\n });\n return newArr;\n});\n\nconst loading = ref(false);\n\nconst tableState = reactive<any>({\n onField: '',\n tableData: [] as PropType<FileUpload[]>,\n uploadUrl: '',\n});\n\ninterface GalleryState {\n /**\n * 预览的图片地址\n */\n images: string[]\n /**\n * 当前预览下标\n */\n currentImageIndex: number\n showVisible: boolean\n}\nconst galleryState = reactive<GalleryState>({\n images: [],\n currentImageIndex: 0,\n showVisible: false,\n});\n\nconst viewFile = (index: number) => {\n galleryState.currentImageIndex = index;\n galleryState.showVisible = true;\n};\n\n/**\n * 是否图片\n *\n * @param file\n */\nconst getSrcUrl = (file: FileUpload): string => {\n if (isImage(file.fileType)) {\n return `${FILE_URL.value}/${file.id}/${file.fileOriginalName}`;\n }\n return logoMini;\n};\n\n/** 获取已上传文件列表 */\nconst getUploadFile = async () => {\n if (pageId === null) {\n return;\n }\n loading.value = true;\n const result = await getPageUploadFileApi(pageId, dataId);\n if (result.code === 0) {\n tableState.tableData = result.data;\n\n galleryState.images = [];\n for (let i = 0; i < result.data.length; i += 1) {\n galleryState.images.push(getSrcUrl(result.data[i]));\n }\n }\n\n loading.value = false;\n};\n\n/** 图片上传到服务器前执行程序 */\nconst beforeUpload = () => {\n if (isEmpty(tableState.onField)) {\n msgTips.tips({\n msg: '请先选择上传类型',\n type: 'warning',\n });\n return false;\n }\n tableState.uploadUrl = `${UPLOAD_FILE_URL.value}/${pageId}/${dataId}/${tableState.onField}`;\n};\n\n/**\n * 上传\n */\nconst uploadFileClick = () => {\n if (!beforeUpload()) {\n return;\n }\n let fileInput: any;\n // 创建文件选择输入框(如果尚未创建)\n if (!fileInput) {\n fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.style.display = 'none';\n fileInput.addEventListener('change', async () => {\n // 处理文件选择事件,如果需要的话\n console.log('文件已选择:', fileInput.files[0].name);\n\n // 创建文件的上传对象\n const file = fileInput.files[0];\n const formData = new FormData();\n formData.append('file', file);\n\n const response = await fetch(tableState.uploadUrl, {\n method: 'POST',\n body: formData,\n });\n\n fileInput.value = '';\n\n if (response.ok) {\n const result = await response.json();\n msgTips.alert({\n msg: result.msg,\n type: 'success',\n });\n getUploadFile();\n } else {\n // 请求失败\n msgTips.alert({\n msg: `请求失败:${response.statusText}`,\n type: 'success',\n });\n }\n });\n document.body.append(fileInput);\n\n // 触发文件选择输入框的点击事件\n fileInput.click();\n }\n};\n\nconst deleteFile = async (fileId: number) => {\n await deletePageUploadFileApi(fileId);\n await getUploadFile();\n};\n\n/**\n * 打开dialog\n *\n */\nconst init = () => {\n getUploadFile();\n\n if (isEmpty(tableState.onField) && fileKinds.length > 0) {\n tableState.onField = fileKinds[0]!.fieldName;\n }\n};\n\nonMounted(() => {\n init();\n});\n</script>\n\n<template>\n <div>\n <div class=\"upload-container\">\n <el-select v-model=\"tableState.onField\">\n <el-option\n v-for=\"item in fileKinds\"\n :key=\"item.fieldName\"\n :label=\"item.fieldTitle\"\n :value=\"item.fieldName\"\n />\n </el-select>\n <div class=\"right-button\">\n <el-button @click=\"getUploadFile\" :loading=\"loading\">\n 刷新<el-icon><Refresh /></el-icon>\n </el-button>\n <el-button type=\"primary\" @click=\"uploadFileClick\">\n 上传<el-icon class=\"el-icon--right\"><Upload /></el-icon>\n </el-button>\n </div>\n </div>\n <div class=\"mt-2\" v-loading=\"loading\">\n <el-table :data=\"tableState.tableData\" border style=\"width: 100%\">\n <el-table-column label=\"文件名\" min-width=\"180\" prop=\"fileOriginalName\">\n <template #default=\"{ $index, row }\">\n <el-link type=\"primary\" @click=\"viewFile($index)\">\n {{ row.fileOriginalName }}\n </el-link>\n </template>\n </el-table-column>\n <el-table-column label=\"上传类型\" prop=\"type\">\n <template #default=\"scope\">\n <el-select v-model=\"scope.row.type\" disabled>\n <el-option\n v-for=\"item in fileKinds\"\n :key=\"item.fieldName\"\n :label=\"item.fieldTitle\"\n :value=\"item.fieldName\"\n />\n </el-select>\n </template>\n </el-table-column>\n <el-table-column label=\"文件类型\" prop=\"fileType\" />\n <el-table-column label=\"上传人\" prop=\"createBy\" />\n <el-table-column label=\"上传时间\" prop=\"createTime\" width=\"160\">\n <template #default=\"scope\">\n {{ dataFormatter.timestamp(scope.row.createTime) }}\n </template>\n </el-table-column>\n <el-table-column label=\"操作\" prop=\"options\">\n <template #default=\"{ row }\">\n <el-button\n v-if=\"fileKindsArr.includes(row.type)\"\n size=\"small\"\n type=\"danger\"\n @click=\"deleteFile(row.id)\"\n >\n 删除\n </el-button>\n </template>\n </el-table-column>\n </el-table>\n <el-image-viewer\n v-if=\"galleryState.showVisible\"\n :initial-index=\"galleryState.currentImageIndex\"\n :url-list=\"galleryState.images\"\n @close=\"galleryState.showVisible = false\"\n />\n </div>\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.upload-container {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n.upload-container .el-select {\n max-width: 300px;\n}\n\n.right-button {\n display: flex;\n justify-content: flex-end; /* 按钮右对齐 */\n align-items: center; /* 按钮垂直居中 */\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { NodeFlowProcessor } from '@/types';\n\nimport { reactive, ref } from 'vue';\n\nimport { msgTips } from '@/utils';\n\nconst emits = defineEmits(['submit']);\nconst dialog = reactive({\n dialogTableVisible: false,\n loading: false,\n});\n\nlet isSubmit: boolean | null = null;\n\nconst tabsActiveName = ref<number | null>(null);\nconst transfer = reactive({\n value: [],\n suggestion: '',\n});\n\nconst nodeFlowProcessorRef = ref<NodeFlowProcessor[]>([]);\n\nconst tabChange = () => {\n transfer.value = [];\n};\n\n/**\n * 确认\n */\nconst confirm = () => {\n const onTabNode = nodeFlowProcessorRef.value.find(\n (node) => node.nodeId === tabsActiveName.value,\n );\n\n if (!onTabNode?.notTodo && transfer.value.length === 0) {\n msgTips.tips({ msg: '请选择提交的人员', type: 'warning' });\n return;\n }\n emits(\n 'submit',\n tabsActiveName.value,\n transfer.value,\n transfer.suggestion,\n isSubmit,\n );\n};\n\n/**\n * @param nodeFlows\n * @param submitOrBack true表示提交 false表示退回\n */\nconst openDialog = (\n nodeFlows: NodeFlowProcessor[],\n submitOrBack: boolean | null,\n) => {\n if (submitOrBack === null) {\n msgTips.tips({ msg: '参数异常', type: 'error' });\n return;\n }\n dialog.dialogTableVisible = true;\n nodeFlowProcessorRef.value = nodeFlows;\n tabsActiveName.value = nodeFlows[0].nodeId;\n isSubmit = submitOrBack;\n transfer.suggestion = '';\n};\n\nconst closeDialog = () => {\n dialog.dialogTableVisible = false;\n nodeFlowProcessorRef.value = [];\n tabsActiveName.value = null;\n};\n\n/** 是否提交 */\nconst openLoading = () => {\n dialog.loading = true;\n\n transfer.value = [];\n};\n\nconst closeLoading = () => {\n dialog.loading = false;\n};\n\ndefineExpose({ openDialog, closeDialog, openLoading, closeLoading });\n</script>\n<template>\n <el-dialog\n v-model=\"dialog.dialogTableVisible\"\n :show-close=\"false\"\n align-center\n append-to-body\n destroy-on-close\n width=\"632px\"\n >\n <template #header=\"{ titleId, titleClass }\">\n <div class=\"my-header\">\n <h3 :id=\"titleId\" :class=\"titleClass\">选择下一环节处理人</h3>\n </div>\n </template>\n <el-tabs v-model=\"tabsActiveName\" class=\"demo-tabs\" @tab-click=\"tabChange\">\n <el-tab-pane\n v-for=\"nodeFlow in nodeFlowProcessorRef\"\n :key=\"nodeFlow.nodeId\"\n :label=\"nodeFlow.nodeName\"\n :name=\"nodeFlow.nodeId\"\n >\n <el-transfer\n v-model=\"transfer.value\"\n :data=\"nodeFlow.users\"\n :props=\"{\n key: 'userId',\n label: 'realName',\n }\"\n :titles=\"['可选人员', '已选择']\"\n />\n </el-tab-pane>\n </el-tabs>\n <template #footer>\n <div>\n <el-input\n v-model=\"transfer.suggestion\"\n autosize\n placeholder=\"批阅建议\"\n type=\"textarea\"\n />\n <div style=\"right: 0; margin-top: 8px\">\n <el-button\n :loading=\"dialog.loading\"\n @click=\"dialog.dialogTableVisible = false\"\n >\n 取消\n </el-button>\n <el-button :loading=\"dialog.loading\" type=\"primary\" @click=\"confirm\">\n 确认\n </el-button>\n </div>\n </div>\n </template>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.my-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n gap: 16px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { NodeFlowProcessor } from '@/types';\n\nimport { reactive, ref } from 'vue';\n\nimport { msgTips } from '@/utils';\n\nconst emits = defineEmits(['submit']);\nconst dialog = reactive({\n dialogTableVisible: false,\n loading: false,\n});\n\nlet isSubmit: boolean | null = null;\n\nconst tabsActiveName = ref<number | null>(null);\nconst transfer = reactive({\n value: [],\n suggestion: '',\n});\n\nconst nodeFlowProcessorRef = ref<NodeFlowProcessor[]>([]);\n\nconst tabChange = () => {\n transfer.value = [];\n};\n\n/**\n * 确认\n */\nconst confirm = () => {\n const onTabNode = nodeFlowProcessorRef.value.find(\n (node) => node.nodeId === tabsActiveName.value,\n );\n\n if (!onTabNode?.notTodo && transfer.value.length === 0) {\n msgTips.tips({ msg: '请选择提交的人员', type: 'warning' });\n return;\n }\n emits(\n 'submit',\n tabsActiveName.value,\n transfer.value,\n transfer.suggestion,\n isSubmit,\n );\n};\n\n/**\n * @param nodeFlows\n * @param submitOrBack true表示提交 false表示退回\n */\nconst openDialog = (\n nodeFlows: NodeFlowProcessor[],\n submitOrBack: boolean | null,\n) => {\n if (submitOrBack === null) {\n msgTips.tips({ msg: '参数异常', type: 'error' });\n return;\n }\n dialog.dialogTableVisible = true;\n nodeFlowProcessorRef.value = nodeFlows;\n tabsActiveName.value = nodeFlows[0].nodeId;\n isSubmit = submitOrBack;\n transfer.suggestion = '';\n};\n\nconst closeDialog = () => {\n dialog.dialogTableVisible = false;\n nodeFlowProcessorRef.value = [];\n tabsActiveName.value = null;\n};\n\n/** 是否提交 */\nconst openLoading = () => {\n dialog.loading = true;\n\n transfer.value = [];\n};\n\nconst closeLoading = () => {\n dialog.loading = false;\n};\n\ndefineExpose({ openDialog, closeDialog, openLoading, closeLoading });\n</script>\n<template>\n <el-dialog\n v-model=\"dialog.dialogTableVisible\"\n :show-close=\"false\"\n align-center\n append-to-body\n destroy-on-close\n width=\"632px\"\n >\n <template #header=\"{ titleId, titleClass }\">\n <div class=\"my-header\">\n <h3 :id=\"titleId\" :class=\"titleClass\">选择下一环节处理人</h3>\n </div>\n </template>\n <el-tabs v-model=\"tabsActiveName\" class=\"demo-tabs\" @tab-click=\"tabChange\">\n <el-tab-pane\n v-for=\"nodeFlow in nodeFlowProcessorRef\"\n :key=\"nodeFlow.nodeId\"\n :label=\"nodeFlow.nodeName\"\n :name=\"nodeFlow.nodeId\"\n >\n <el-transfer\n v-model=\"transfer.value\"\n :data=\"nodeFlow.users\"\n :props=\"{\n key: 'userId',\n label: 'realName',\n }\"\n :titles=\"['可选人员', '已选择']\"\n />\n </el-tab-pane>\n </el-tabs>\n <template #footer>\n <div>\n <el-input\n v-model=\"transfer.suggestion\"\n autosize\n placeholder=\"批阅建议\"\n type=\"textarea\"\n />\n <div style=\"right: 0; margin-top: 8px\">\n <el-button\n :loading=\"dialog.loading\"\n @click=\"dialog.dialogTableVisible = false\"\n >\n 取消\n </el-button>\n <el-button :loading=\"dialog.loading\" type=\"primary\" @click=\"confirm\">\n 确认\n </el-button>\n </div>\n </div>\n </template>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.my-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n gap: 16px;\n}\n</style>\n","import type { FormSelectProp } from '@/types/index.ts';\n\n/**\n * 给表单设置默认值 (一般提交时使用)\n *\n * @param formData\n * @param formFrame\n */\nexport const useSetDefaultValue = (formData: any, formFrame: FormSelectProp[]) => {\n if (formFrame.length === 0) {\n return formData;\n }\n\n const newFormData = { ...formData };\n formFrame.forEach((item) => {\n if (newFormData[item.field] === undefined) {\n // 如果是多选 说明是数组\n if (item.multiple) {\n if (item.defaultValue) {\n newFormData[item.field] =\n typeof item.defaultValue === 'string'\n ? JSON.parse(item.defaultValue)\n : item.defaultValue;\n }\n } else {\n // 直接设置默认值\n newFormData[item.field] = item.defaultValue;\n }\n }\n });\n\n return newFormData;\n};\n","<script setup lang=\"ts\">\nimport type {\n PagePath,\n FormBasicInterface,\n FormEmbeddedTableProp,\n FormFrame,\n KeButton,\n FlowButton,\n} from '@/types/index.ts';\n\nimport {\n computed,\n defineAsyncComponent,\n nextTick,\n onBeforeUnmount,\n onMounted,\n reactive,\n ref,\n} from 'vue';\n\nimport {\n backBeforeCheckApi,\n backFlowApi,\n getFormRenderDataApi,\n saveFormDataApi,\n submitBeforeCheckApi,\n submitFlowApi,\n getEmbeddedFormRenderDataApi,\n saveEmbeddedTableFormDataApi,\n} from '@/api';\n\nimport EmbeddedTable from './components/embedded/EmbeddedTable.vue';\nimport FileIsland from './components/FileIsland.vue';\nimport FlowUserDialog from './components/FlowUserDialog.vue';\nimport { BASE_URL } from '@/config';\nimport { useSetDefaultValue } from './hooks/useAutoForm.hook.ts';\nimport { useButtonExec } from '@/hooks/useButtonExec.hook.ts';\n\nimport { getRandomString, isNotEmpty, msgTips, sleep } from '@/utils';\nimport { ElButtonPlus } from '@/components';\nimport { FormRender } from '@/components/FormComponent/FormRender';\n\ninterface Props {\n pageId: number;\n dataId: number | string;\n isFullScreen?: boolean;\n embeddedId?: null | number;\n pagePath: PagePath[];\n showWindowButton?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n embeddedId: null,\n showWindowButton: true,\n isFullScreen: false,\n});\n\nconst emits = defineEmits([\n 'close',\n 'fullScreenChange',\n 'update:dataId',\n 'dataChange',\n]);\n\nconst ApprovalRecord = defineAsyncComponent(\n () => import('./components/ApprovalRecord.vue'),\n);\n\nconst flowUserDialogRef = ref();\n\nconst formRenderRef = ref();\n\nconst configRef = ref<FormBasicInterface>({} as FormBasicInterface);\nconst frameRef = ref([]);\nconst dataIdRef = defineModel('dataId');\nconst formDataRef = ref({});\nconst formRuleRef = ref({});\nconst formButtonsRef = ref<KeButton[]>([]);\nconst flowButtonRef = ref<FlowButton>({} as FlowButton);\nconst formSaveVerifyJsRef = ref<Function | null>(null);\nconst embeddedTableListRef = ref<FormEmbeddedTableProp[]>([]);\n\nlet isAdd = false;\n\nconst newPagePaths = computed(() => {\n if (Array.isArray(props.pagePath)) {\n return [\n ...props.pagePath,\n {\n pageId: props.pageId,\n dataId: props.dataId,\n formData: formDataRef.value,\n },\n ];\n }\n return [\n {\n pageId: props.pageId,\n dataId: props.dataId,\n formData: formDataRef.value,\n },\n ];\n});\n\nconst activeName = ref('Form');\n/**\n * 组件显示规则\n */\nconst componentShowRuleRef = ref({});\n/**\n * 文件类别列表\n */\nconst fileUploadList = ref([]);\n\nconst pageState = reactive({\n // 表单是否加载中\n formLoading: false,\n isEdit: false,\n // 编辑ID\n editId: '',\n});\n\nconst onNodeState = reactive({\n nodeId: '',\n nodeName: '',\n});\n\nconst formTabName = computed(() => {\n if (onNodeState.nodeName && configRef.value.startOA) {\n return `表单-${onNodeState.nodeName}`;\n }\n return '表单';\n});\n\n/** 渲染数据 */\nconst initFormFrameAndData = async () => {\n configRef.value = {\n labelWidth: 120,\n rowKey: 'key',\n };\n frameRef.value = [];\n formDataRef.value = {};\n\n embeddedTableListRef.value = [];\n pageState.formLoading = true;\n formSaveVerifyJsRef.value = null;\n\n let result;\n if (newPagePaths.value.length === 1) {\n result = await getFormRenderDataApi(props.pageId, props.dataId ?? 'new', isAdd);\n } else {\n if (props.embeddedId === null) {\n msgTips.alert({\n msg: '数据结构异常',\n type: 'error'\n })\n console.error(props)\n return;\n }\n result = await getEmbeddedFormRenderDataApi(\n {\n embeddedId: props.embeddedId,\n pagePaths: newPagePaths.value,\n },\n props.dataId,\n isAdd,\n );\n }\n\n if (result.code === 0) {\n configRef.value = result.data.formConfig;\n formDataRef.value = JSON.parse(JSON.stringify(result.data.formData));\n\n // 流程按钮\n flowButtonRef.value = result.data.flowButton;\n /**\n * 表单功能按钮\n */\n formButtonsRef.value = Array.isArray(result.data.formButtons)\n ? JSON.parse(JSON.stringify(result.data.formButtons))\n : [];\n onNodeState.nodeId = result.data.editConfig.nodeId;\n onNodeState.nodeName = result.data.editConfig.nodeName;\n\n const {\n formRules,\n formSaveVerifyJs,\n componentShowRule,\n receiveBroadcasts,\n formButtons,\n } = await import(\n `${BASE_URL.value}/app/js/formRender/${props.pageId}/${props.dataId}?time=${getRandomString(3)}`\n );\n // 注入函数\n formButtonsRef.value.forEach((button) => {\n if (button.webTrigger && formButtons[button.id]) {\n button.webFunction = formButtons[button.id];\n }\n });\n\n formRuleRef.value = formRules;\n // 如果表单验证js不为空 则转换为js方法\n if (isNotEmpty(formSaveVerifyJs)) {\n formSaveVerifyJsRef.value = formSaveVerifyJs;\n }\n // 组件显示规则\n componentShowRuleRef.value = componentShowRule;\n\n const formFrameList = JSON.parse(JSON.stringify(result.data.formFrame));\n formFrameList.forEach((formFrame: FormFrame) => {\n formFrame.noticeReceive = receiveBroadcasts[formFrame.field];\n });\n frameRef.value = formFrameList;\n\n pageState.isEdit = result.data.editConfig.edit;\n pageState.editId = result.editId || '';\n\n await nextTick();\n // 初始化表单配置\n formRenderRef.value.initForm(formDataRef.value);\n\n fileUploadList.value = result.data.fileUploadList;\n\n await nextTick();\n embeddedTableListRef.value = result.data.embeddedTableList;\n } else {\n emits('close');\n }\n\n formDataRef.value = useSetDefaultValue(formDataRef.value, frameRef.value);\n pageState.formLoading = false;\n};\n\n/**\n * 表单数据保存\n */\nconst formDataSave = async () => {\n if (pageState.formLoading) {\n return;\n }\n if (!(await formRenderRef.value.validateForm())) return;\n pageState.formLoading = true;\n let result;\n if (newPagePaths.value.length === 1) {\n result = await saveFormDataApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n } else {\n if (props.embeddedId === null) {\n msgTips.alert({\n msg: '数据结构异常',\n type: 'error'\n })\n console.error(props)\n return\n }\n result = await saveEmbeddedTableFormDataApi(\n {\n embeddedId: props.embeddedId,\n pagePaths: props.pagePath,\n formData: formDataRef.value,\n },\n props.dataId,\n pageState.editId,\n isAdd,\n );\n }\n\n if (result.code === 0) {\n if (isAdd) {\n dataIdRef.value = result.data;\n isAdd = false;\n await nextTick();\n await initFormFrameAndData();\n }\n pageState.editId = result.editId || '';\n }\n pageState.formLoading = false;\n emits('dataChange');\n};\n\n/** 流程提交 */\nconst flowSubmitHandle = async () => {\n await formDataSave();\n if (pageState.formLoading) {\n return;\n }\n // 校验表单内容\n if (!(await formRenderRef.value.validateForm())) return;\n\n if (flowButtonRef.value.submitTips) {\n msgTips.alert({\n type: 'warning',\n title: '提示',\n msg: flowButtonRef.value.submitTips,\n callback: () => {\n submitCheck();\n },\n });\n } else {\n await submitCheck();\n }\n};\n/**\n * 提交前检查\n */\nconst submitCheck = async () => {\n pageState.formLoading = true;\n const result = await submitBeforeCheckApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n flowUserDialogRef.value.openDialog(result.data.nodeFlowProcessors, true);\n }\n pageState.formLoading = false;\n};\n\n/** 流程退回 */\nconst flowBackHandle = async () => {\n await formDataSave();\n if (pageState.formLoading) {\n return;\n }\n\n if (flowButtonRef.value.backTips) {\n msgTips.alert({\n type: 'warning',\n title: '提示',\n msg: flowButtonRef.value.backTips,\n callback: () => {\n backCheck();\n },\n });\n } else {\n await backCheck();\n }\n};\n\n/**\n * 退回前检查\n */\nconst backCheck = async () => {\n pageState.formLoading = true;\n const result = await backBeforeCheckApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n flowUserDialogRef.value.openDialog(result.data.nodeFlowProcessors, false);\n }\n pageState.formLoading = false;\n};\n\n/**\n * 提交流程\n *\n * @param submitNodeId\n * @param submitUsers\n * @param suggestion\n * @param submit\n */\nconst submitFlow = async (\n submitNodeId: string,\n submitUsers: string[],\n suggestion: string,\n submit: boolean,\n) => {\n if (pageState.formLoading) {\n return;\n }\n flowUserDialogRef.value.openLoading();\n pageState.formLoading = true;\n\n const result = await (submit\n ? submitFlowApi({\n pageId: props.pageId,\n dataId: props.dataId,\n nodeId: onNodeState.nodeId,\n toNodeId: submitNodeId,\n userId: submitUsers,\n suggestion,\n formData: formDataRef.value,\n })\n : backFlowApi({\n pageId: props.pageId,\n dataId: props.dataId,\n nodeId: onNodeState.nodeId,\n toNodeId: submitNodeId,\n userId: submitUsers,\n suggestion,\n formData: formDataRef.value,\n }));\n\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n await sleep(0.2);\n flowUserDialogRef.value.closeDialog();\n await initFormFrameAndData();\n }\n flowUserDialogRef.value.closeLoading();\n pageState.formLoading = false;\n};\n\n/**\n * 表单按钮\n *\n * @param button\n */\nconst formButtonClick = (button: KeButton) => {\n if (pageState.formLoading) {\n return;\n }\n\n executeFormButton(button);\n};\n\n/**\n * 执行按钮程序\n *\n * @param button\n */\nconst executeFormButton = async (button: KeButton) => {\n if (pageState.formLoading) {\n return;\n }\n pageState.formLoading = true;\n\n button.params = { pageId: props.pageId, dataId: props.dataId };\n // 调用执行按钮程序\n await useButtonExec(formDataRef.value, button);\n\n pageState.formLoading = false;\n};\n\n/**\n * 初始化\n */\nconst initForm = (isNew: boolean) => {\n isAdd = isNew;\n initFormFrameAndData();\n};\n/**\n * 刷新\n */\nconst refresh = () => {\n initFormFrameAndData();\n};\n/**\n * 改变全屏\n */\nconst fullScreenChange = () => {\n emits('fullScreenChange');\n};\n\n/**\n * 关闭表单\n */\nconst closeWindow = () => {\n emits('close');\n};\n\nonMounted(() => {\n const SCROLL_HIDE_DELAY = 300; // ms\n const scrollTimeoutMap = new Map<Element, ReturnType<typeof setTimeout>>();\n\n const panes = document.querySelectorAll('.el-tab-pane');\n panes.forEach((pane) => {\n const onScroll = () => {\n pane.classList.add('scrolling');\n if (scrollTimeoutMap.has(pane)) {\n clearTimeout(scrollTimeoutMap.get(pane));\n }\n const timeout = setTimeout(() => {\n pane.classList.remove('scrolling');\n }, SCROLL_HIDE_DELAY);\n scrollTimeoutMap.set(pane, timeout);\n };\n pane.addEventListener('scroll', onScroll);\n // 保存回收方法\n (pane as any).__onScrollHandler__ = onScroll;\n });\n});\n\nonBeforeUnmount(() => {\n const panes = document.querySelectorAll('.el-tab-pane');\n panes.forEach((pane) => {\n if ((pane as any).__onScrollHandler__) {\n pane.removeEventListener('scroll', (pane as any).__onScrollHandler__);\n delete (pane as any).__onScrollHandler__;\n }\n });\n});\n\ndefineExpose({ initForm, refresh });\n</script>\n\n<template>\n <div class=\"app-form-render\" v-loading=\"pageState.formLoading\">\n <div class=\"app-header\">\n <el-scrollbar class=\"left\">\n <el-tooltip\n effect=\"dark\"\n content=\"刷新\"\n placement=\"top-start\"\n >\n<!-- <el-button @click=\"refresh\" :icon=\"Refresh\" />-->\n <el-button-plus @click=\"refresh\" icon=\"tdesign:refresh\" />\n </el-tooltip>\n <el-tooltip\n v-if=\"pageState.isEdit\"\n effect=\"dark\"\n content=\"保存\"\n placement=\"top-start\"\n >\n<!-- <el-button type=\"primary\" @click=\"formDataSave\" :icon=\"Save\" />-->\n <el-button-plus type=\"primary\" @click=\"formDataSave\" icon=\"ci:save\" />\n </el-tooltip>\n <el-button\n v-if=\"flowButtonRef && isNotEmpty(flowButtonRef.submitLabel)\"\n type=\"primary\"\n @click=\"flowSubmitHandle\"\n >\n {{ flowButtonRef.submitLabel }}\n </el-button>\n <el-button\n v-if=\"flowButtonRef && isNotEmpty(flowButtonRef.backLabel)\"\n type=\"danger\"\n @click=\"flowBackHandle\"\n >\n {{ flowButtonRef.backLabel }}\n </el-button>\n <el-button\n v-for=\"btn in formButtonsRef\"\n :key=\"btn.id\"\n :type=\"btn.type\"\n @click=\"formButtonClick(btn)\"\n >\n {{ btn.label }}\n </el-button>\n </el-scrollbar>\n <div v-if=\"showWindowButton\" class=\"right\">\n <el-button @click=\"fullScreenChange\">\n {{ isFullScreen ? '缩小' : '全屏' }}\n </el-button>\n <el-button type=\"danger\" @click=\"closeWindow\">\n 关闭\n </el-button>\n </div>\n </div>\n <el-tabs v-model=\"activeName\" class=\"form-container\">\n <el-tab-pane :label=\"formTabName\" name=\"Form\">\n <FormRender\n ref=\"formRenderRef\"\n v-model:data=\"formDataRef\"\n :component-show-rule=\"componentShowRuleRef\"\n :config=\"configRef\"\n :form-rules=\"formRuleRef\"\n :form-save-verify-js=\"formSaveVerifyJsRef\"\n :frame=\"frameRef\"\n :page-id=\"pageId\"\n style=\"margin-top: 15px\"\n />\n </el-tab-pane>\n <slot name=\"default\"></slot>\n <el-tab-pane v-if=\"fileUploadList && fileUploadList.length > 0\" label=\"附件上传\" lazy>\n <FileIsland\n :page-id=\"pageId\"\n :data-id=\"dataId\"\n :file-kinds=\"fileUploadList\"\n />\n </el-tab-pane>\n <el-tab-pane\n v-for=\"em in embeddedTableListRef\"\n :key=\"em.embeddedId\"\n :label=\"em.tabTitle\"\n :lazy=\"true\"\n :name=\"em.embeddedId\"\n style=\"height: 100%\"\n >\n <EmbeddedTable :embedded-id=\"em.embeddedId\" :page-path=\"newPagePaths\" />\n </el-tab-pane>\n <el-tab-pane\n v-if=\"configRef.startOA && onNodeState.nodeId\"\n label=\"批阅记录\"\n lazy\n >\n <ApprovalRecord :page-id=\"pageId\" :data-id=\"dataId\" />\n </el-tab-pane>\n </el-tabs>\n <FlowUserDialog ref=\"flowUserDialogRef\" @submit=\"submitFlow\" />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.app-form-render {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden; // 防止它自己滚动\n}\n\n.app-header {\n display: flex;\n flex-wrap: wrap;\n padding-bottom: 6px;\n border-bottom: 2px solid var(--el-border-color);\n .left {\n flex-grow: 1; /* 占用剩余宽度 */\n }\n\n .right {\n flex-shrink: 0; /* 不收缩 */\n width: auto; /* 根据内容宽度撑开 */\n }\n}\n\n.form-buttons {\n //display: flex;\n margin-top: 8px;\n}\n.form-container {\n flex: 1 1 0;\n min-height: 0;\n overflow: hidden;\n\n :deep(.el-tabs__content) {\n height: 100%;\n }\n\n :deep(.el-tab-pane) {\n height: 100%;\n\n & > div {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n }\n\n :deep(.el-tabs__header) {\n margin: 0;\n }\n}\n/* 隐藏 .el-tab-pane 自身的滚动条 */\n:deep(.el-tab-pane) {\n height: 100%;\n overflow-y: auto;\n overflow-x: auto; /* 注意:你原本是 hidden,但设了 auto,建议统一 */\n // 隐藏滚动条但保留滚动功能\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE/Edge */\n}\n\n:deep(.el-tab-pane::-webkit-scrollbar) {\n //display: none; /* WebKit 浏览器隐藏滚动条 */\n}\n\n/* 👇 关键:恢复 el-table 内部滚动条的显示 */\n:deep(.el-table__body-wrapper) {\n scrollbar-width: auto;\n -ms-overflow-style: auto;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar) {\n display: block;\n width: 6px;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar-thumb) {\n background-color: rgba(0, 0, 0, 0.4);\n border-radius: 3px;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar-track) {\n background-color: transparent;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type {\n PagePath,\n FormBasicInterface,\n FormEmbeddedTableProp,\n FormFrame,\n KeButton,\n FlowButton,\n} from '@/types/index.ts';\n\nimport {\n computed,\n defineAsyncComponent,\n nextTick,\n onBeforeUnmount,\n onMounted,\n reactive,\n ref,\n} from 'vue';\n\nimport {\n backBeforeCheckApi,\n backFlowApi,\n getFormRenderDataApi,\n saveFormDataApi,\n submitBeforeCheckApi,\n submitFlowApi,\n getEmbeddedFormRenderDataApi,\n saveEmbeddedTableFormDataApi,\n} from '@/api';\n\nimport EmbeddedTable from './components/embedded/EmbeddedTable.vue';\nimport FileIsland from './components/FileIsland.vue';\nimport FlowUserDialog from './components/FlowUserDialog.vue';\nimport { BASE_URL } from '@/config';\nimport { useSetDefaultValue } from './hooks/useAutoForm.hook.ts';\nimport { useButtonExec } from '@/hooks/useButtonExec.hook.ts';\n\nimport { getRandomString, isNotEmpty, msgTips, sleep } from '@/utils';\nimport { ElButtonPlus } from '@/components';\nimport { FormRender } from '@/components/FormComponent/FormRender';\n\ninterface Props {\n pageId: number;\n dataId: number | string;\n isFullScreen?: boolean;\n embeddedId?: null | number;\n pagePath: PagePath[];\n showWindowButton?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n embeddedId: null,\n showWindowButton: true,\n isFullScreen: false,\n});\n\nconst emits = defineEmits([\n 'close',\n 'fullScreenChange',\n 'update:dataId',\n 'dataChange',\n]);\n\nconst ApprovalRecord = defineAsyncComponent(\n () => import('./components/ApprovalRecord.vue'),\n);\n\nconst flowUserDialogRef = ref();\n\nconst formRenderRef = ref();\n\nconst configRef = ref<FormBasicInterface>({} as FormBasicInterface);\nconst frameRef = ref([]);\nconst dataIdRef = defineModel('dataId');\nconst formDataRef = ref({});\nconst formRuleRef = ref({});\nconst formButtonsRef = ref<KeButton[]>([]);\nconst flowButtonRef = ref<FlowButton>({} as FlowButton);\nconst formSaveVerifyJsRef = ref<Function | null>(null);\nconst embeddedTableListRef = ref<FormEmbeddedTableProp[]>([]);\n\nlet isAdd = false;\n\nconst newPagePaths = computed(() => {\n if (Array.isArray(props.pagePath)) {\n return [\n ...props.pagePath,\n {\n pageId: props.pageId,\n dataId: props.dataId,\n formData: formDataRef.value,\n },\n ];\n }\n return [\n {\n pageId: props.pageId,\n dataId: props.dataId,\n formData: formDataRef.value,\n },\n ];\n});\n\nconst activeName = ref('Form');\n/**\n * 组件显示规则\n */\nconst componentShowRuleRef = ref({});\n/**\n * 文件类别列表\n */\nconst fileUploadList = ref([]);\n\nconst pageState = reactive({\n // 表单是否加载中\n formLoading: false,\n isEdit: false,\n // 编辑ID\n editId: '',\n});\n\nconst onNodeState = reactive({\n nodeId: '',\n nodeName: '',\n});\n\nconst formTabName = computed(() => {\n if (onNodeState.nodeName && configRef.value.startOA) {\n return `表单-${onNodeState.nodeName}`;\n }\n return '表单';\n});\n\n/** 渲染数据 */\nconst initFormFrameAndData = async () => {\n configRef.value = {\n labelWidth: 120,\n rowKey: 'key',\n };\n frameRef.value = [];\n formDataRef.value = {};\n\n embeddedTableListRef.value = [];\n pageState.formLoading = true;\n formSaveVerifyJsRef.value = null;\n\n let result;\n if (newPagePaths.value.length === 1) {\n result = await getFormRenderDataApi(props.pageId, props.dataId ?? 'new', isAdd);\n } else {\n if (props.embeddedId === null) {\n msgTips.alert({\n msg: '数据结构异常',\n type: 'error'\n })\n console.error(props)\n return;\n }\n result = await getEmbeddedFormRenderDataApi(\n {\n embeddedId: props.embeddedId,\n pagePaths: newPagePaths.value,\n },\n props.dataId,\n isAdd,\n );\n }\n\n if (result.code === 0) {\n configRef.value = result.data.formConfig;\n formDataRef.value = JSON.parse(JSON.stringify(result.data.formData));\n\n // 流程按钮\n flowButtonRef.value = result.data.flowButton;\n /**\n * 表单功能按钮\n */\n formButtonsRef.value = Array.isArray(result.data.formButtons)\n ? JSON.parse(JSON.stringify(result.data.formButtons))\n : [];\n onNodeState.nodeId = result.data.editConfig.nodeId;\n onNodeState.nodeName = result.data.editConfig.nodeName;\n\n const {\n formRules,\n formSaveVerifyJs,\n componentShowRule,\n receiveBroadcasts,\n formButtons,\n } = await import(\n `${BASE_URL.value}/app/js/formRender/${props.pageId}/${props.dataId}?time=${getRandomString(3)}`\n );\n // 注入函数\n formButtonsRef.value.forEach((button) => {\n if (button.webTrigger && formButtons[button.id]) {\n button.webFunction = formButtons[button.id];\n }\n });\n\n formRuleRef.value = formRules;\n // 如果表单验证js不为空 则转换为js方法\n if (isNotEmpty(formSaveVerifyJs)) {\n formSaveVerifyJsRef.value = formSaveVerifyJs;\n }\n // 组件显示规则\n componentShowRuleRef.value = componentShowRule;\n\n const formFrameList = JSON.parse(JSON.stringify(result.data.formFrame));\n formFrameList.forEach((formFrame: FormFrame) => {\n formFrame.noticeReceive = receiveBroadcasts[formFrame.field];\n });\n frameRef.value = formFrameList;\n\n pageState.isEdit = result.data.editConfig.edit;\n pageState.editId = result.editId || '';\n\n await nextTick();\n // 初始化表单配置\n formRenderRef.value.initForm(formDataRef.value);\n\n fileUploadList.value = result.data.fileUploadList;\n\n await nextTick();\n embeddedTableListRef.value = result.data.embeddedTableList;\n } else {\n emits('close');\n }\n\n formDataRef.value = useSetDefaultValue(formDataRef.value, frameRef.value);\n pageState.formLoading = false;\n};\n\n/**\n * 表单数据保存\n */\nconst formDataSave = async () => {\n if (pageState.formLoading) {\n return;\n }\n if (!(await formRenderRef.value.validateForm())) return;\n pageState.formLoading = true;\n let result;\n if (newPagePaths.value.length === 1) {\n result = await saveFormDataApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n } else {\n if (props.embeddedId === null) {\n msgTips.alert({\n msg: '数据结构异常',\n type: 'error'\n })\n console.error(props)\n return\n }\n result = await saveEmbeddedTableFormDataApi(\n {\n embeddedId: props.embeddedId,\n pagePaths: props.pagePath,\n formData: formDataRef.value,\n },\n props.dataId,\n pageState.editId,\n isAdd,\n );\n }\n\n if (result.code === 0) {\n if (isAdd) {\n dataIdRef.value = result.data;\n isAdd = false;\n await nextTick();\n await initFormFrameAndData();\n }\n pageState.editId = result.editId || '';\n }\n pageState.formLoading = false;\n emits('dataChange');\n};\n\n/** 流程提交 */\nconst flowSubmitHandle = async () => {\n await formDataSave();\n if (pageState.formLoading) {\n return;\n }\n // 校验表单内容\n if (!(await formRenderRef.value.validateForm())) return;\n\n if (flowButtonRef.value.submitTips) {\n msgTips.alert({\n type: 'warning',\n title: '提示',\n msg: flowButtonRef.value.submitTips,\n callback: () => {\n submitCheck();\n },\n });\n } else {\n await submitCheck();\n }\n};\n/**\n * 提交前检查\n */\nconst submitCheck = async () => {\n pageState.formLoading = true;\n const result = await submitBeforeCheckApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n flowUserDialogRef.value.openDialog(result.data.nodeFlowProcessors, true);\n }\n pageState.formLoading = false;\n};\n\n/** 流程退回 */\nconst flowBackHandle = async () => {\n await formDataSave();\n if (pageState.formLoading) {\n return;\n }\n\n if (flowButtonRef.value.backTips) {\n msgTips.alert({\n type: 'warning',\n title: '提示',\n msg: flowButtonRef.value.backTips,\n callback: () => {\n backCheck();\n },\n });\n } else {\n await backCheck();\n }\n};\n\n/**\n * 退回前检查\n */\nconst backCheck = async () => {\n pageState.formLoading = true;\n const result = await backBeforeCheckApi(\n {\n pageId: props.pageId,\n dataId: props.dataId,\n headers: { EditId: pageState.editId },\n },\n formDataRef.value,\n isAdd,\n );\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n flowUserDialogRef.value.openDialog(result.data.nodeFlowProcessors, false);\n }\n pageState.formLoading = false;\n};\n\n/**\n * 提交流程\n *\n * @param submitNodeId\n * @param submitUsers\n * @param suggestion\n * @param submit\n */\nconst submitFlow = async (\n submitNodeId: string,\n submitUsers: string[],\n suggestion: string,\n submit: boolean,\n) => {\n if (pageState.formLoading) {\n return;\n }\n flowUserDialogRef.value.openLoading();\n pageState.formLoading = true;\n\n const result = await (submit\n ? submitFlowApi({\n pageId: props.pageId,\n dataId: props.dataId,\n nodeId: onNodeState.nodeId,\n toNodeId: submitNodeId,\n userId: submitUsers,\n suggestion,\n formData: formDataRef.value,\n })\n : backFlowApi({\n pageId: props.pageId,\n dataId: props.dataId,\n nodeId: onNodeState.nodeId,\n toNodeId: submitNodeId,\n userId: submitUsers,\n suggestion,\n formData: formDataRef.value,\n }));\n\n if (result.code === 0) {\n pageState.editId = result.editId || '';\n await sleep(0.2);\n flowUserDialogRef.value.closeDialog();\n await initFormFrameAndData();\n }\n flowUserDialogRef.value.closeLoading();\n pageState.formLoading = false;\n};\n\n/**\n * 表单按钮\n *\n * @param button\n */\nconst formButtonClick = (button: KeButton) => {\n if (pageState.formLoading) {\n return;\n }\n\n executeFormButton(button);\n};\n\n/**\n * 执行按钮程序\n *\n * @param button\n */\nconst executeFormButton = async (button: KeButton) => {\n if (pageState.formLoading) {\n return;\n }\n pageState.formLoading = true;\n\n button.params = { pageId: props.pageId, dataId: props.dataId };\n // 调用执行按钮程序\n await useButtonExec(formDataRef.value, button);\n\n pageState.formLoading = false;\n};\n\n/**\n * 初始化\n */\nconst initForm = (isNew: boolean) => {\n isAdd = isNew;\n initFormFrameAndData();\n};\n/**\n * 刷新\n */\nconst refresh = () => {\n initFormFrameAndData();\n};\n/**\n * 改变全屏\n */\nconst fullScreenChange = () => {\n emits('fullScreenChange');\n};\n\n/**\n * 关闭表单\n */\nconst closeWindow = () => {\n emits('close');\n};\n\nonMounted(() => {\n const SCROLL_HIDE_DELAY = 300; // ms\n const scrollTimeoutMap = new Map<Element, ReturnType<typeof setTimeout>>();\n\n const panes = document.querySelectorAll('.el-tab-pane');\n panes.forEach((pane) => {\n const onScroll = () => {\n pane.classList.add('scrolling');\n if (scrollTimeoutMap.has(pane)) {\n clearTimeout(scrollTimeoutMap.get(pane));\n }\n const timeout = setTimeout(() => {\n pane.classList.remove('scrolling');\n }, SCROLL_HIDE_DELAY);\n scrollTimeoutMap.set(pane, timeout);\n };\n pane.addEventListener('scroll', onScroll);\n // 保存回收方法\n (pane as any).__onScrollHandler__ = onScroll;\n });\n});\n\nonBeforeUnmount(() => {\n const panes = document.querySelectorAll('.el-tab-pane');\n panes.forEach((pane) => {\n if ((pane as any).__onScrollHandler__) {\n pane.removeEventListener('scroll', (pane as any).__onScrollHandler__);\n delete (pane as any).__onScrollHandler__;\n }\n });\n});\n\ndefineExpose({ initForm, refresh });\n</script>\n\n<template>\n <div class=\"app-form-render\" v-loading=\"pageState.formLoading\">\n <div class=\"app-header\">\n <el-scrollbar class=\"left\">\n <el-tooltip\n effect=\"dark\"\n content=\"刷新\"\n placement=\"top-start\"\n >\n<!-- <el-button @click=\"refresh\" :icon=\"Refresh\" />-->\n <el-button-plus @click=\"refresh\" icon=\"tdesign:refresh\" />\n </el-tooltip>\n <el-tooltip\n v-if=\"pageState.isEdit\"\n effect=\"dark\"\n content=\"保存\"\n placement=\"top-start\"\n >\n<!-- <el-button type=\"primary\" @click=\"formDataSave\" :icon=\"Save\" />-->\n <el-button-plus type=\"primary\" @click=\"formDataSave\" icon=\"ci:save\" />\n </el-tooltip>\n <el-button\n v-if=\"flowButtonRef && isNotEmpty(flowButtonRef.submitLabel)\"\n type=\"primary\"\n @click=\"flowSubmitHandle\"\n >\n {{ flowButtonRef.submitLabel }}\n </el-button>\n <el-button\n v-if=\"flowButtonRef && isNotEmpty(flowButtonRef.backLabel)\"\n type=\"danger\"\n @click=\"flowBackHandle\"\n >\n {{ flowButtonRef.backLabel }}\n </el-button>\n <el-button\n v-for=\"btn in formButtonsRef\"\n :key=\"btn.id\"\n :type=\"btn.type\"\n @click=\"formButtonClick(btn)\"\n >\n {{ btn.label }}\n </el-button>\n </el-scrollbar>\n <div v-if=\"showWindowButton\" class=\"right\">\n <el-button @click=\"fullScreenChange\">\n {{ isFullScreen ? '缩小' : '全屏' }}\n </el-button>\n <el-button type=\"danger\" @click=\"closeWindow\">\n 关闭\n </el-button>\n </div>\n </div>\n <el-tabs v-model=\"activeName\" class=\"form-container\">\n <el-tab-pane :label=\"formTabName\" name=\"Form\">\n <FormRender\n ref=\"formRenderRef\"\n v-model:data=\"formDataRef\"\n :component-show-rule=\"componentShowRuleRef\"\n :config=\"configRef\"\n :form-rules=\"formRuleRef\"\n :form-save-verify-js=\"formSaveVerifyJsRef\"\n :frame=\"frameRef\"\n :page-id=\"pageId\"\n style=\"margin-top: 15px\"\n />\n </el-tab-pane>\n <slot name=\"default\"></slot>\n <el-tab-pane v-if=\"fileUploadList && fileUploadList.length > 0\" label=\"附件上传\" lazy>\n <FileIsland\n :page-id=\"pageId\"\n :data-id=\"dataId\"\n :file-kinds=\"fileUploadList\"\n />\n </el-tab-pane>\n <el-tab-pane\n v-for=\"em in embeddedTableListRef\"\n :key=\"em.embeddedId\"\n :label=\"em.tabTitle\"\n :lazy=\"true\"\n :name=\"em.embeddedId\"\n style=\"height: 100%\"\n >\n <EmbeddedTable :embedded-id=\"em.embeddedId\" :page-path=\"newPagePaths\" />\n </el-tab-pane>\n <el-tab-pane\n v-if=\"configRef.startOA && onNodeState.nodeId\"\n label=\"批阅记录\"\n lazy\n >\n <ApprovalRecord :page-id=\"pageId\" :data-id=\"dataId\" />\n </el-tab-pane>\n </el-tabs>\n <FlowUserDialog ref=\"flowUserDialogRef\" @submit=\"submitFlow\" />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.app-form-render {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden; // 防止它自己滚动\n}\n\n.app-header {\n display: flex;\n flex-wrap: wrap;\n padding-bottom: 6px;\n border-bottom: 2px solid var(--el-border-color);\n .left {\n flex-grow: 1; /* 占用剩余宽度 */\n }\n\n .right {\n flex-shrink: 0; /* 不收缩 */\n width: auto; /* 根据内容宽度撑开 */\n }\n}\n\n.form-buttons {\n //display: flex;\n margin-top: 8px;\n}\n.form-container {\n flex: 1 1 0;\n min-height: 0;\n overflow: hidden;\n\n :deep(.el-tabs__content) {\n height: 100%;\n }\n\n :deep(.el-tab-pane) {\n height: 100%;\n\n & > div {\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n }\n\n :deep(.el-tabs__header) {\n margin: 0;\n }\n}\n/* 隐藏 .el-tab-pane 自身的滚动条 */\n:deep(.el-tab-pane) {\n height: 100%;\n overflow-y: auto;\n overflow-x: auto; /* 注意:你原本是 hidden,但设了 auto,建议统一 */\n // 隐藏滚动条但保留滚动功能\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE/Edge */\n}\n\n:deep(.el-tab-pane::-webkit-scrollbar) {\n //display: none; /* WebKit 浏览器隐藏滚动条 */\n}\n\n/* 👇 关键:恢复 el-table 内部滚动条的显示 */\n:deep(.el-table__body-wrapper) {\n scrollbar-width: auto;\n -ms-overflow-style: auto;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar) {\n display: block;\n width: 6px;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar-thumb) {\n background-color: rgba(0, 0, 0, 0.4);\n border-radius: 3px;\n}\n\n:deep(.el-table__body-wrapper::-webkit-scrollbar-track) {\n background-color: transparent;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { ChartDataInterfaceDTO, ChartDTO } from '@/types';\n\nimport { onMounted, ref } from 'vue';\n\nimport { getAppChartContentApi } from '@/api';\nimport { BASE_URL } from '@/config';\nimport { getRandomString } from '@/utils';\n\nconst props = defineProps({\n chart: {\n type: Object as PropType<ChartDTO>,\n required: true,\n },\n});\n\nconst chartData = ref<ChartDataInterfaceDTO>({} as ChartDataInterfaceDTO);\nconst data = ref<any[]>([]);\nconst loading = ref(false);\n\nconst formattedData = async () => {\n if (chartData.value.formatterFunc) {\n const { formatterFunc } = await import(\n `${BASE_URL.value}/app/js/chart/${props.chart.id}?time=${getRandomString(3)}`\n );\n if (typeof formatterFunc === 'function') {\n data.value = formatterFunc(\n chartData.value.data,\n chartData.value.translationData,\n );\n }\n } else {\n data.value = chartData.value.data;\n }\n};\n\n/**\n * 初始化\n */\nconst init = async () => {\n loading.value = true;\n const result = await getAppChartContentApi(props.chart.id);\n if (result.code === 0) {\n chartData.value = result.data;\n await formattedData();\n }\n loading.value = false;\n};\n\nconst refresh = () => {\n init();\n};\n\ndefineExpose({\n refresh,\n});\n\nonMounted(() => {\n if (props.chart) {\n init();\n }\n});\n</script>\n\n<template>\n <div class=\"chart-container\" v-loading=\"loading\">\n <component :is=\"chart.chartType\" :data=\"data\" />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.chart-container {\n height: calc(100vh - 320px);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { ChartDataInterfaceDTO, ChartDTO } from '@/types';\n\nimport { onMounted, ref } from 'vue';\n\nimport { getAppChartContentApi } from '@/api';\nimport { BASE_URL } from '@/config';\nimport { getRandomString } from '@/utils';\n\nconst props = defineProps({\n chart: {\n type: Object as PropType<ChartDTO>,\n required: true,\n },\n});\n\nconst chartData = ref<ChartDataInterfaceDTO>({} as ChartDataInterfaceDTO);\nconst data = ref<any[]>([]);\nconst loading = ref(false);\n\nconst formattedData = async () => {\n if (chartData.value.formatterFunc) {\n const { formatterFunc } = await import(\n `${BASE_URL.value}/app/js/chart/${props.chart.id}?time=${getRandomString(3)}`\n );\n if (typeof formatterFunc === 'function') {\n data.value = formatterFunc(\n chartData.value.data,\n chartData.value.translationData,\n );\n }\n } else {\n data.value = chartData.value.data;\n }\n};\n\n/**\n * 初始化\n */\nconst init = async () => {\n loading.value = true;\n const result = await getAppChartContentApi(props.chart.id);\n if (result.code === 0) {\n chartData.value = result.data;\n await formattedData();\n }\n loading.value = false;\n};\n\nconst refresh = () => {\n init();\n};\n\ndefineExpose({\n refresh,\n});\n\nonMounted(() => {\n if (props.chart) {\n init();\n }\n});\n</script>\n\n<template>\n <div class=\"chart-container\" v-loading=\"loading\">\n <component :is=\"chart.chartType\" :data=\"data\" />\n </div>\n</template>\n\n<style scoped lang=\"scss\">\n.chart-container {\n height: calc(100vh - 320px);\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { ChartDTO } from '@/types';\n\nimport { ref } from 'vue';\n\nimport { CircleCloseFilled, Refresh } from '@element-plus/icons-vue';\nimport { isNotEmpty } from '@/utils';\n\nimport { getAppChartListApi } from '@/api';\n\nimport ChartRender from './ChartRender.vue';\n\nconst show = ref(false);\nlet isLoad = false;\nlet pageId: null | number = null;\nconst activeName = ref<null | number>(null);\nconst chartList = ref<ChartDTO[]>([]);\n\nconst chartRefs = ref<any>({});\n/**\n * 动态设置ref实例\n * @param el\n * @param c\n */\nconst setChartRef = (el: any, c: ChartDTO) => {\n chartRefs.value[`${c.id}ref`] = el;\n};\n\nconst refreshChart = () => {\n chartRefs.value[`${activeName.value}ref`].refresh();\n};\n\n/**\n * 加载数据\n */\nconst init = async () => {\n if (isNotEmpty(pageId)) {\n const result = await getAppChartListApi(pageId);\n if (result.code === 0) {\n chartList.value = result.data;\n isLoad = true;\n if (chartList.value.length > 0) {\n activeName.value = chartList.value[0].id;\n }\n }\n }\n};\n\nconst openDialog = (page: number) => {\n show.value = true;\n if (!isLoad) {\n pageId = page;\n init();\n }\n};\n\ndefineExpose({\n openDialog,\n});\n</script>\n\n<template>\n <el-dialog\n v-model=\"show\"\n :show-close=\"false\"\n align-center\n append-to-body\n width=\"80%\"\n >\n <template #header=\"{ close }\">\n <div class=\"my-header\">\n <div>\n <el-button :icon=\"Refresh\" @click=\"refreshChart\" />\n </div>\n <el-button :icon=\"CircleCloseFilled\" type=\"danger\" @click=\"close\" />\n </div>\n </template>\n <el-empty v-if=\"chartList.length === 0\" description=\"当前页面无图表\" />\n <el-tabs v-else v-model=\"activeName\" type=\"border-card\">\n <el-tab-pane\n v-for=\"chart in chartList\"\n :key=\"chart.id\"\n :label=\"chart.chartName\"\n :name=\"chart.id\"\n lazy\n >\n <ChartRender :ref=\"(el) => setChartRef(el, chart)\" :chart=\"chart\" />\n </el-tab-pane>\n </el-tabs>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.my-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n gap: 16px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { ChartDTO } from '@/types';\n\nimport { ref } from 'vue';\n\nimport { CircleCloseFilled, Refresh } from '@element-plus/icons-vue';\nimport { isNotEmpty } from '@/utils';\n\nimport { getAppChartListApi } from '@/api';\n\nimport ChartRender from './ChartRender.vue';\n\nconst show = ref(false);\nlet isLoad = false;\nlet pageId: null | number = null;\nconst activeName = ref<null | number>(null);\nconst chartList = ref<ChartDTO[]>([]);\n\nconst chartRefs = ref<any>({});\n/**\n * 动态设置ref实例\n * @param el\n * @param c\n */\nconst setChartRef = (el: any, c: ChartDTO) => {\n chartRefs.value[`${c.id}ref`] = el;\n};\n\nconst refreshChart = () => {\n chartRefs.value[`${activeName.value}ref`].refresh();\n};\n\n/**\n * 加载数据\n */\nconst init = async () => {\n if (isNotEmpty(pageId)) {\n const result = await getAppChartListApi(pageId);\n if (result.code === 0) {\n chartList.value = result.data;\n isLoad = true;\n if (chartList.value.length > 0) {\n activeName.value = chartList.value[0].id;\n }\n }\n }\n};\n\nconst openDialog = (page: number) => {\n show.value = true;\n if (!isLoad) {\n pageId = page;\n init();\n }\n};\n\ndefineExpose({\n openDialog,\n});\n</script>\n\n<template>\n <el-dialog\n v-model=\"show\"\n :show-close=\"false\"\n align-center\n append-to-body\n width=\"80%\"\n >\n <template #header=\"{ close }\">\n <div class=\"my-header\">\n <div>\n <el-button :icon=\"Refresh\" @click=\"refreshChart\" />\n </div>\n <el-button :icon=\"CircleCloseFilled\" type=\"danger\" @click=\"close\" />\n </div>\n </template>\n <el-empty v-if=\"chartList.length === 0\" description=\"当前页面无图表\" />\n <el-tabs v-else v-model=\"activeName\" type=\"border-card\">\n <el-tab-pane\n v-for=\"chart in chartList\"\n :key=\"chart.id\"\n :label=\"chart.chartName\"\n :name=\"chart.id\"\n lazy\n >\n <ChartRender :ref=\"(el) => setChartRef(el, chart)\" :chart=\"chart\" />\n </el-tab-pane>\n </el-tabs>\n </el-dialog>\n</template>\n\n<style scoped lang=\"scss\">\n.my-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n gap: 16px;\n}\n</style>\n","<script setup lang=\"ts\">\r\nimport { reactive, ref } from 'vue';\r\n\r\nimport AppFormRender from '../AppFormRender.vue';\r\n\r\nconst emits = defineEmits(['dataChange']);\r\n\r\nconst AppFormRenderRef = ref();\r\nconst drawerState = ref(false);\r\nconst pageState = reactive({\r\n isFullScreen: false,\r\n pageId: 0,\r\n dataId: '',\r\n});\r\n\r\n/**\r\n * 当前数据在表格的索引\r\n */\r\nlet onDataRowIndex = -1;\r\n\r\nconst dataChange = () => {\r\n emits('dataChange', onDataRowIndex);\r\n};\r\n\r\ninterface OpenForm {\r\n /**\r\n * 主键\r\n */\r\n rowKey: any;\r\n /**\r\n * 页面ID\r\n */\r\n pageId: number;\r\n /**\r\n * 行数\r\n */\r\n rowIndex: number;\r\n}\r\n/**\r\n * 打开抽屉\r\n *\r\n * @param params\r\n */\r\nconst openForm = (params: OpenForm) => {\r\n const isAdd = typeof params.rowKey === 'boolean';\r\n pageState.dataId = isAdd ? 'new' : params.rowKey;\r\n pageState.pageId = params.pageId;\r\n drawerState.value = true;\r\n onDataRowIndex = params.rowIndex;\r\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\r\n};\r\n\r\nconst close = () => {\r\n drawerState.value = false;\r\n};\r\n\r\ndefineExpose({ openForm });\r\n</script>\r\n\r\n<template>\r\n <el-dialog\r\n v-model=\"drawerState\"\r\n :close-on-click-modal=\"false\"\r\n :show-close=\"false\"\r\n :width=\"pageState.isFullScreen ? '100%' : '70%'\"\r\n append-to-body\r\n align-center\r\n >\r\n <div class=\"dialog-form-container\">\r\n <AppFormRender\r\n ref=\"AppFormRenderRef\"\r\n v-model:data-id=\"pageState.dataId\"\r\n :is-full-screen=\"pageState.isFullScreen\"\r\n :page-id=\"pageState.pageId\"\r\n :page-path=\"[]\"\r\n @close=\"close\"\r\n @data-change=\"dataChange\"\r\n @full-screen-change=\"pageState.isFullScreen = !pageState.isFullScreen\"\r\n />\r\n </div>\r\n </el-dialog>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.dialog-form-container {\r\n height: 80vh;\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport { reactive, ref } from 'vue';\r\n\r\nimport AppFormRender from '../AppFormRender.vue';\r\n\r\nconst emits = defineEmits(['dataChange']);\r\n\r\nconst AppFormRenderRef = ref();\r\nconst drawerState = ref(false);\r\nconst pageState = reactive({\r\n isFullScreen: false,\r\n pageId: 0,\r\n dataId: '',\r\n});\r\n\r\n/**\r\n * 当前数据在表格的索引\r\n */\r\nlet onDataRowIndex = -1;\r\n\r\nconst dataChange = () => {\r\n emits('dataChange', onDataRowIndex);\r\n};\r\n\r\ninterface OpenForm {\r\n /**\r\n * 主键\r\n */\r\n rowKey: any;\r\n /**\r\n * 页面ID\r\n */\r\n pageId: number;\r\n /**\r\n * 行数\r\n */\r\n rowIndex: number;\r\n}\r\n/**\r\n * 打开抽屉\r\n *\r\n * @param params\r\n */\r\nconst openForm = (params: OpenForm) => {\r\n const isAdd = typeof params.rowKey === 'boolean';\r\n pageState.dataId = isAdd ? 'new' : params.rowKey;\r\n pageState.pageId = params.pageId;\r\n drawerState.value = true;\r\n onDataRowIndex = params.rowIndex;\r\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\r\n};\r\n\r\nconst close = () => {\r\n drawerState.value = false;\r\n};\r\n\r\ndefineExpose({ openForm });\r\n</script>\r\n\r\n<template>\r\n <el-dialog\r\n v-model=\"drawerState\"\r\n :close-on-click-modal=\"false\"\r\n :show-close=\"false\"\r\n :width=\"pageState.isFullScreen ? '100%' : '70%'\"\r\n append-to-body\r\n align-center\r\n >\r\n <div class=\"dialog-form-container\">\r\n <AppFormRender\r\n ref=\"AppFormRenderRef\"\r\n v-model:data-id=\"pageState.dataId\"\r\n :is-full-screen=\"pageState.isFullScreen\"\r\n :page-id=\"pageState.pageId\"\r\n :page-path=\"[]\"\r\n @close=\"close\"\r\n @data-change=\"dataChange\"\r\n @full-screen-change=\"pageState.isFullScreen = !pageState.isFullScreen\"\r\n />\r\n </div>\r\n </el-dialog>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.dialog-form-container {\r\n height: 80vh;\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\nimport { reactive, ref } from 'vue';\n\nimport AppFormRender from '../AppFormRender.vue';\n\ninterface Props {\n appendToBody?: boolean;\n closeOnClickModal?: boolean;\n}\n\nwithDefaults(defineProps<Props>(), {\n appendToBody: false,\n closeOnClickModal: false,\n});\n\nconst emits = defineEmits(['dataChange']);\n\nconst AppFormRenderRef = ref();\nconst drawerState = ref(false);\nconst pageState = reactive({\n isFullScreen: false,\n pageId: 0,\n dataId: '',\n});\n\n/**\n * 当前数据在表格的索引\n */\nlet onDataRowIndex = -1;\n\nconst dataChange = () => {\n emits('dataChange', onDataRowIndex);\n};\n\ninterface OpenForm {\n /**\n * 主键\n */\n rowKey: any;\n /**\n * 页面ID\n */\n pageId: number;\n /**\n * 行数\n */\n rowIndex: number;\n}\n/**\n * 打开抽屉\n *\n * @param params\n */\nconst openForm = (params: OpenForm) => {\n const isAdd = typeof params.rowKey === 'boolean';\n pageState.dataId = isAdd ? 'new' : params.rowKey;\n pageState.pageId = params.pageId;\n drawerState.value = true;\n onDataRowIndex = params.rowIndex;\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\n};\n\nconst close = () => {\n drawerState.value = false;\n};\n\ndefineExpose({ openForm });\n</script>\n\n<template>\n <el-drawer\n v-model=\"drawerState\"\n :close-on-click-modal=\"closeOnClickModal\"\n :show-close=\"false\"\n :size=\"pageState.isFullScreen ? '100%' : '70%'\"\n :with-header=\"false\"\n resizable\n :append-to-body=\"appendToBody\"\n >\n <AppFormRender\n ref=\"AppFormRenderRef\"\n v-model:data-id=\"pageState.dataId\"\n :is-full-screen=\"pageState.isFullScreen\"\n :page-id=\"pageState.pageId\"\n :page-path=\"[]\"\n @close=\"close\"\n @data-change=\"dataChange\"\n @full-screen-change=\"pageState.isFullScreen = !pageState.isFullScreen\"\n />\n </el-drawer>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\nimport { reactive, ref } from 'vue';\n\nimport AppFormRender from '../AppFormRender.vue';\n\ninterface Props {\n appendToBody?: boolean;\n closeOnClickModal?: boolean;\n}\n\nwithDefaults(defineProps<Props>(), {\n appendToBody: false,\n closeOnClickModal: false,\n});\n\nconst emits = defineEmits(['dataChange']);\n\nconst AppFormRenderRef = ref();\nconst drawerState = ref(false);\nconst pageState = reactive({\n isFullScreen: false,\n pageId: 0,\n dataId: '',\n});\n\n/**\n * 当前数据在表格的索引\n */\nlet onDataRowIndex = -1;\n\nconst dataChange = () => {\n emits('dataChange', onDataRowIndex);\n};\n\ninterface OpenForm {\n /**\n * 主键\n */\n rowKey: any;\n /**\n * 页面ID\n */\n pageId: number;\n /**\n * 行数\n */\n rowIndex: number;\n}\n/**\n * 打开抽屉\n *\n * @param params\n */\nconst openForm = (params: OpenForm) => {\n const isAdd = typeof params.rowKey === 'boolean';\n pageState.dataId = isAdd ? 'new' : params.rowKey;\n pageState.pageId = params.pageId;\n drawerState.value = true;\n onDataRowIndex = params.rowIndex;\n setTimeout(() => AppFormRenderRef.value.initForm(isAdd), 50);\n};\n\nconst close = () => {\n drawerState.value = false;\n};\n\ndefineExpose({ openForm });\n</script>\n\n<template>\n <el-drawer\n v-model=\"drawerState\"\n :close-on-click-modal=\"closeOnClickModal\"\n :show-close=\"false\"\n :size=\"pageState.isFullScreen ? '100%' : '70%'\"\n :with-header=\"false\"\n resizable\n :append-to-body=\"appendToBody\"\n >\n <AppFormRender\n ref=\"AppFormRenderRef\"\n v-model:data-id=\"pageState.dataId\"\n :is-full-screen=\"pageState.isFullScreen\"\n :page-id=\"pageState.pageId\"\n :page-path=\"[]\"\n @close=\"close\"\n @data-change=\"dataChange\"\n @full-screen-change=\"pageState.isFullScreen = !pageState.isFullScreen\"\n />\n </el-drawer>\n</template>\n\n<style scoped lang=\"scss\"></style>\n","<script setup lang=\"ts\">\r\nimport type { VxeGridProps } from 'vxe-table';\r\n\r\nimport { ApiInterface, KeButton, TableQueryFrame, Pagination, TableRenderApiDTO } from '@/types';\r\n\r\nimport { onMounted, ref, useTemplateRef } from 'vue';\r\nimport { useRequest } from 'vue-hooks-plus';\r\n\r\nimport { PieChart } from '@element-plus/icons-vue';\r\n\r\nimport { getTableRenderApi } from '@/api';\r\nimport { ChartList } from '@/components/AppComponent/components/chartList/index';\r\nimport DialogForm from '@/components/AppComponent/components/DialogForm.vue';\r\nimport DrawerForm from '@/components/AppComponent/components/DrawerForm.vue';\r\nimport {\r\n updateDataByRowIndex,\r\n useConfigurationProcess,\r\n useTableData,\r\n} from '@/components/AppComponent/hooks/useTable.hook';\r\nimport { BASE_URL } from '@/config';\r\nimport { TableCardRender, TableRender } from '@/components/TableComponent';\r\nimport { getRandomString } from '@/utils';\r\n\r\nimport { QueryTreeFilter } from '@/components/QueryComponent/QueryTreeFilter';\r\n\r\ndefineOptions({\r\n name: 'AppTableRender',\r\n});\r\n\r\nconst componentMap: Record<string, any> = {\r\n TableRender,\r\n TableCardRender,\r\n};\r\n\r\ninterface Props {\r\n pageId: number;\r\n emPageId?: number | null;\r\n}\r\n\r\nwithDefaults(defineProps<Props>(), {\r\n emPageId: null,\r\n});\r\n\r\nconst pageId = defineModel<number>('pageId')\r\nconst appFormWindowRef = ref();\r\nconst tableRef = ref();\r\n\r\nconst gridOptions = ref<VxeGridProps>({\r\n columns: [],\r\n seqConfig: {\r\n startIndex: 0,\r\n },\r\n exportConfig: {\r\n excludeFields: ['tableButtonOperate'],\r\n },\r\n});\r\n\r\nconst columns = ref<any[]>([]);\r\nconst queryConfig = ref<TableQueryFrame[]>([]);\r\nconst tableToolButtons = ref<KeButton[]>([]);\r\nconst tableRowButtons = ref<KeButton[]>([]);\r\nconst pagination = ref<Pagination>({\r\n /**\r\n * 当前页\r\n */\r\n currentPage: 1,\r\n /**\r\n * 分页大小\r\n */\r\n pageSize: 10,\r\n /**\r\n * 总数\r\n */\r\n total: 0,\r\n});\r\n\r\nconst queryTreeFilter = useTemplateRef('queryTreeFilter');\r\n\r\nconst { tableData, syncTableData, btnClickFunc, tableConfig } =\r\n useTableData({\r\n pageId,\r\n queryTreeFilter,\r\n pagination,\r\n appFormWindowRef,\r\n });\r\n\r\n/** 获取table渲染相关配置 */\r\nconst { runAsync: getTableRender, loading: renderLoading } = useRequest(\r\n () => getTableRenderApi(<number>pageId.value),\r\n {\r\n manual: true,\r\n cacheKey: `table-render-${pageId.value}`,\r\n onSuccess: async (result: ApiInterface<TableRenderApiDTO>) => {\r\n if (result.code === 0) {\r\n const { tableButtons: modules } = await import(\r\n `${BASE_URL.value}/app/js/table/${pageId.value}?time=${getRandomString(3)}`\r\n );\r\n const configCacheValue = useConfigurationProcess(\r\n result.data,\r\n <number>pageId.value,\r\n btnClickFunc,\r\n modules,\r\n treeLazyLoad,\r\n );\r\n\r\n tableConfig.value = result.data.tableConfig;\r\n tableConfig.value.pageId = pageId.value;\r\n queryConfig.value = result.data.queryFrameList;\r\n columns.value = configCacheValue.gridOptions.columns!;\r\n gridOptions.value = configCacheValue.gridOptions;\r\n gridOptions.value.columns = [];\r\n tableToolButtons.value = configCacheValue.tableToolButtons;\r\n tableRowButtons.value = configCacheValue.tableRowButtons;\r\n }\r\n\r\n syncTableData();\r\n },\r\n },\r\n);\r\n\r\nconst chartListRef = useTemplateRef('chartList');\r\n\r\n/**\r\n * 指定行数据更新\r\n * @param rowIndex\r\n */\r\nconst onDataChange = (rowIndex: number) => {\r\n if (rowIndex < 0 || !rowIndex) {\r\n syncTableData();\r\n return;\r\n }\r\n updateDataByRowIndex({\r\n rowIndex,\r\n tableConfig,\r\n tableData,\r\n });\r\n};\r\n\r\n/**\r\n * 懒加载tree数据\r\n */\r\nconst treeLazyLoad = async (\r\n treeNode: unknown,\r\n resolve: (data: any[]) => void,\r\n queryData: any,\r\n) => {\r\n await syncTableData(queryData, resolve, treeNode);\r\n};\r\n\r\n/**\r\n * 当检测到值改变\r\n * @param _fieldName\r\n * @param _newValue\r\n * @param _rowId\r\n */\r\nconst onValueChange = (\r\n _fieldName: string,\r\n _newValue: any,\r\n _rowId: string,\r\n) => {};\r\n\r\nconst chart = {\r\n open: () => {\r\n if (chartListRef.value) {\r\n chartListRef.value.openDialog(<number>pageId.value);\r\n }\r\n },\r\n};\r\n\r\nonMounted(async () => {\r\n tableConfig.value.pageId = pageId.value;\r\n\r\n await getTableRender();\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"app-table-render-container\" v-loading=\"renderLoading\">\r\n <el-splitter>\r\n <el-splitter-panel\r\n v-if=\"pageId && tableConfig.hasQueryTreeFilter\"\r\n collapsible\r\n size=\"240\"\r\n >\r\n <QueryTreeFilter ref=\"queryTreeFilter\" :page-id=\"pageId\" />\r\n </el-splitter-panel>\r\n <el-splitter-panel v-if=\"tableConfig.rowKey\">\r\n <component\r\n :is=\"componentMap[tableConfig.showType]\"\r\n ref=\"tableRef\"\r\n :columns=\"columns\"\r\n :query-config=\"queryConfig\"\r\n :table-config=\"tableConfig\"\r\n :table-data=\"tableData\"\r\n :table-id=\"pageId\"\r\n :table-pagination=\"pagination\"\r\n :table-row-buttons=\"tableRowButtons\"\r\n :table-tool-buttons=\"tableToolButtons\"\r\n :vxe-grid-options=\"gridOptions\"\r\n @query-click=\"syncTableData\"\r\n @value-change=\"onValueChange\"\r\n >\r\n <template #tool-bar>\r\n <el-button :icon=\"PieChart\" @click=\"chart.open\" />\r\n </template>\r\n </component>\r\n </el-splitter-panel>\r\n </el-splitter>\r\n <div class=\"drawer-container\">\r\n <DrawerForm\r\n v-if=\"\r\n !tableConfig.formWindow || tableConfig.formWindow === 'DrawerForm'\r\n \"\r\n ref=\"appFormWindowRef\"\r\n @data-change=\"onDataChange\"\r\n />\r\n <DialogForm v-else ref=\"appFormWindowRef\" @data-change=\"onDataChange\" />\r\n </div>\r\n <ChartList ref=\"chartList\" />\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.app-table-render-container {\r\n position: relative;\r\n display: flex;\r\n height: 100%;\r\n padding: 0 0.4rem;\r\n}\r\n.query-tree {\r\n width: 240px;\r\n}\r\n.page-root {\r\n flex: 1; /* 剩余空间 */\r\n //width: 100%;\r\n min-width: 0; /* 避免内容强制撑开 */\r\n max-width: 100%; /* 防止过大 */\r\n transition: width 0.1s linear; /* 平滑宽度变化,消除卡顿感 */\r\n}\r\n.drawer-container {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n z-index: 100;\r\n transform: translateZ(0);\r\n overflow: hidden;\r\n pointer-events: none;\r\n :deep(.el-drawer__container) {\r\n pointer-events: auto;\r\n }\r\n :deep(.el-overlay) {\r\n pointer-events: auto;\r\n }\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport type { VxeGridProps } from 'vxe-table';\r\n\r\nimport { ApiInterface, KeButton, TableQueryFrame, Pagination, TableRenderApiDTO } from '@/types';\r\n\r\nimport { onMounted, ref, useTemplateRef } from 'vue';\r\nimport { useRequest } from 'vue-hooks-plus';\r\n\r\nimport { PieChart } from '@element-plus/icons-vue';\r\n\r\nimport { getTableRenderApi } from '@/api';\r\nimport { ChartList } from '@/components/AppComponent/components/chartList/index';\r\nimport DialogForm from '@/components/AppComponent/components/DialogForm.vue';\r\nimport DrawerForm from '@/components/AppComponent/components/DrawerForm.vue';\r\nimport {\r\n updateDataByRowIndex,\r\n useConfigurationProcess,\r\n useTableData,\r\n} from '@/components/AppComponent/hooks/useTable.hook';\r\nimport { BASE_URL } from '@/config';\r\nimport { TableCardRender, TableRender } from '@/components/TableComponent';\r\nimport { getRandomString } from '@/utils';\r\n\r\nimport { QueryTreeFilter } from '@/components/QueryComponent/QueryTreeFilter';\r\n\r\ndefineOptions({\r\n name: 'AppTableRender',\r\n});\r\n\r\nconst componentMap: Record<string, any> = {\r\n TableRender,\r\n TableCardRender,\r\n};\r\n\r\ninterface Props {\r\n pageId: number;\r\n emPageId?: number | null;\r\n}\r\n\r\nwithDefaults(defineProps<Props>(), {\r\n emPageId: null,\r\n});\r\n\r\nconst pageId = defineModel<number>('pageId')\r\nconst appFormWindowRef = ref();\r\nconst tableRef = ref();\r\n\r\nconst gridOptions = ref<VxeGridProps>({\r\n columns: [],\r\n seqConfig: {\r\n startIndex: 0,\r\n },\r\n exportConfig: {\r\n excludeFields: ['tableButtonOperate'],\r\n },\r\n});\r\n\r\nconst columns = ref<any[]>([]);\r\nconst queryConfig = ref<TableQueryFrame[]>([]);\r\nconst tableToolButtons = ref<KeButton[]>([]);\r\nconst tableRowButtons = ref<KeButton[]>([]);\r\nconst pagination = ref<Pagination>({\r\n /**\r\n * 当前页\r\n */\r\n currentPage: 1,\r\n /**\r\n * 分页大小\r\n */\r\n pageSize: 10,\r\n /**\r\n * 总数\r\n */\r\n total: 0,\r\n});\r\n\r\nconst queryTreeFilter = useTemplateRef('queryTreeFilter');\r\n\r\nconst { tableData, syncTableData, btnClickFunc, tableConfig } =\r\n useTableData({\r\n pageId,\r\n queryTreeFilter,\r\n pagination,\r\n appFormWindowRef,\r\n });\r\n\r\n/** 获取table渲染相关配置 */\r\nconst { runAsync: getTableRender, loading: renderLoading } = useRequest(\r\n () => getTableRenderApi(<number>pageId.value),\r\n {\r\n manual: true,\r\n cacheKey: `table-render-${pageId.value}`,\r\n onSuccess: async (result: ApiInterface<TableRenderApiDTO>) => {\r\n if (result.code === 0) {\r\n const { tableButtons: modules } = await import(\r\n `${BASE_URL.value}/app/js/table/${pageId.value}?time=${getRandomString(3)}`\r\n );\r\n const configCacheValue = useConfigurationProcess(\r\n result.data,\r\n <number>pageId.value,\r\n btnClickFunc,\r\n modules,\r\n treeLazyLoad,\r\n );\r\n\r\n tableConfig.value = result.data.tableConfig;\r\n tableConfig.value.pageId = pageId.value;\r\n queryConfig.value = result.data.queryFrameList;\r\n columns.value = configCacheValue.gridOptions.columns!;\r\n gridOptions.value = configCacheValue.gridOptions;\r\n gridOptions.value.columns = [];\r\n tableToolButtons.value = configCacheValue.tableToolButtons;\r\n tableRowButtons.value = configCacheValue.tableRowButtons;\r\n }\r\n\r\n syncTableData();\r\n },\r\n },\r\n);\r\n\r\nconst chartListRef = useTemplateRef('chartList');\r\n\r\n/**\r\n * 指定行数据更新\r\n * @param rowIndex\r\n */\r\nconst onDataChange = (rowIndex: number) => {\r\n if (rowIndex < 0 || !rowIndex) {\r\n syncTableData();\r\n return;\r\n }\r\n updateDataByRowIndex({\r\n rowIndex,\r\n tableConfig,\r\n tableData,\r\n });\r\n};\r\n\r\n/**\r\n * 懒加载tree数据\r\n */\r\nconst treeLazyLoad = async (\r\n treeNode: unknown,\r\n resolve: (data: any[]) => void,\r\n queryData: any,\r\n) => {\r\n await syncTableData(queryData, resolve, treeNode);\r\n};\r\n\r\n/**\r\n * 当检测到值改变\r\n * @param _fieldName\r\n * @param _newValue\r\n * @param _rowId\r\n */\r\nconst onValueChange = (\r\n _fieldName: string,\r\n _newValue: any,\r\n _rowId: string,\r\n) => {};\r\n\r\nconst chart = {\r\n open: () => {\r\n if (chartListRef.value) {\r\n chartListRef.value.openDialog(<number>pageId.value);\r\n }\r\n },\r\n};\r\n\r\nonMounted(async () => {\r\n tableConfig.value.pageId = pageId.value;\r\n\r\n await getTableRender();\r\n});\r\n</script>\r\n\r\n<template>\r\n <div class=\"app-table-render-container\" v-loading=\"renderLoading\">\r\n <el-splitter>\r\n <el-splitter-panel\r\n v-if=\"pageId && tableConfig.hasQueryTreeFilter\"\r\n collapsible\r\n size=\"240\"\r\n >\r\n <QueryTreeFilter ref=\"queryTreeFilter\" :page-id=\"pageId\" />\r\n </el-splitter-panel>\r\n <el-splitter-panel v-if=\"tableConfig.rowKey\">\r\n <component\r\n :is=\"componentMap[tableConfig.showType]\"\r\n ref=\"tableRef\"\r\n :columns=\"columns\"\r\n :query-config=\"queryConfig\"\r\n :table-config=\"tableConfig\"\r\n :table-data=\"tableData\"\r\n :table-id=\"pageId\"\r\n :table-pagination=\"pagination\"\r\n :table-row-buttons=\"tableRowButtons\"\r\n :table-tool-buttons=\"tableToolButtons\"\r\n :vxe-grid-options=\"gridOptions\"\r\n @query-click=\"syncTableData\"\r\n @value-change=\"onValueChange\"\r\n >\r\n <template #tool-bar>\r\n <el-button :icon=\"PieChart\" @click=\"chart.open\" />\r\n </template>\r\n </component>\r\n </el-splitter-panel>\r\n </el-splitter>\r\n <div class=\"drawer-container\">\r\n <DrawerForm\r\n v-if=\"\r\n !tableConfig.formWindow || tableConfig.formWindow === 'DrawerForm'\r\n \"\r\n ref=\"appFormWindowRef\"\r\n @data-change=\"onDataChange\"\r\n />\r\n <DialogForm v-else ref=\"appFormWindowRef\" @data-change=\"onDataChange\" />\r\n </div>\r\n <ChartList ref=\"chartList\" />\r\n </div>\r\n</template>\r\n\r\n<style scoped lang=\"scss\">\r\n.app-table-render-container {\r\n position: relative;\r\n display: flex;\r\n height: 100%;\r\n padding: 0 0.4rem;\r\n}\r\n.query-tree {\r\n width: 240px;\r\n}\r\n.page-root {\r\n flex: 1; /* 剩余空间 */\r\n //width: 100%;\r\n min-width: 0; /* 避免内容强制撑开 */\r\n max-width: 100%; /* 防止过大 */\r\n transition: width 0.1s linear; /* 平滑宽度变化,消除卡顿感 */\r\n}\r\n.drawer-container {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n z-index: 100;\r\n transform: translateZ(0);\r\n overflow: hidden;\r\n pointer-events: none;\r\n :deep(.el-drawer__container) {\r\n pointer-events: auto;\r\n }\r\n :deep(.el-overlay) {\r\n pointer-events: auto;\r\n }\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport { computed, nextTick, onMounted, ref } from 'vue';\r\n\r\nconst props = defineProps<{\r\n componentName: any;\r\n componentProps?: Record<string, any>;\r\n onDestroy?: () => void;\r\n width?: string;\r\n}>();\r\n\r\nconst visible = ref(true);\r\nconst contentWrapperHeight = ref('80vh'); // 动态控制内容高度\r\n\r\n// 处理 componentProps,避免传递响应式对象给动态组件\r\nconst safeComponentProps = computed(() => {\r\n if (!props.componentProps) return {};\r\n // 浅拷贝 props,避免响应式传递问题\r\n return { ...props.componentProps };\r\n});\r\n\r\nconst name = computed(() => props.componentName);\r\n\r\nconst handleClosed = () => {\r\n // Dialog 关闭动画完成后,调用销毁函数\r\n if (props.onDestroy) {\r\n props.onDestroy();\r\n }\r\n};\r\n\r\n// 添加四角拖拽缩放功能\r\nonMounted(() => {\r\n nextTick(() => {\r\n const dialogElement = document.querySelector('.el-dialog') as HTMLElement;\r\n if (!dialogElement) return;\r\n\r\n // 创建四个角的拖拽手柄\r\n const corners = [\r\n { position: 'top-left', cursor: 'nwse-resize' },\r\n { position: 'top-right', cursor: 'nesw-resize' },\r\n { position: 'bottom-left', cursor: 'nesw-resize' },\r\n { position: 'bottom-right', cursor: 'nwse-resize' },\r\n ];\r\n\r\n corners.forEach(({ position, cursor }) => {\r\n const handle = document.createElement('div');\r\n handle.className = `resize-handle resize-handle-${position}`;\r\n handle.style.cssText = `\r\n position: absolute;\r\n width: 12px;\r\n height: 12px;\r\n cursor: ${cursor};\r\n z-index: 9999;\r\n `;\r\n\r\n // 设置手柄位置\r\n if (position.includes('top')) handle.style.top = '0';\r\n if (position.includes('bottom')) handle.style.bottom = '0';\r\n if (position.includes('left')) handle.style.left = '0';\r\n if (position.includes('right')) handle.style.right = '0';\r\n\r\n dialogElement.append(handle);\r\n\r\n // 添加拖拽事件\r\n let isResizing = false;\r\n let startX = 0;\r\n let startY = 0;\r\n let startWidth = 0;\r\n let startHeight = 0;\r\n let startLeft = 0;\r\n let startTop = 0;\r\n\r\n handle.addEventListener('mousedown', (e: MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n isResizing = true;\r\n\r\n startX = e.clientX;\r\n startY = e.clientY;\r\n startWidth = dialogElement.offsetWidth;\r\n startHeight = dialogElement.offsetHeight;\r\n startLeft = dialogElement.offsetLeft;\r\n startTop = dialogElement.offsetTop;\r\n\r\n const onMouseMove = (moveEvent: MouseEvent) => {\r\n if (!isResizing) return;\r\n\r\n const deltaX = moveEvent.clientX - startX;\r\n const deltaY = moveEvent.clientY - startY;\r\n\r\n let newWidth = startWidth;\r\n let newHeight = startHeight;\r\n let newLeft = startLeft;\r\n let newTop = startTop;\r\n\r\n // 根据不同的角落计算新的尺寸和位置\r\n if (position.includes('right')) {\r\n newWidth = startWidth + deltaX;\r\n }\r\n if (position.includes('left')) {\r\n newWidth = startWidth - deltaX;\r\n newLeft = startLeft + deltaX;\r\n }\r\n if (position.includes('bottom')) {\r\n newHeight = startHeight + deltaY;\r\n }\r\n if (position.includes('top')) {\r\n newHeight = startHeight - deltaY;\r\n newTop = startTop + deltaY;\r\n }\r\n\r\n // 设置最小尺寸\r\n const minWidth = 300;\r\n const minHeight = 200;\r\n\r\n if (newWidth >= minWidth) {\r\n dialogElement.style.width = `${newWidth}px`;\r\n if (position.includes('left')) {\r\n dialogElement.style.left = `${newLeft}px`;\r\n }\r\n }\r\n\r\n if (newHeight >= minHeight) {\r\n dialogElement.style.height = `${newHeight}px`;\r\n if (position.includes('top')) {\r\n dialogElement.style.top = `${newTop}px`;\r\n }\r\n\r\n // 动态更新内容区域高度\r\n updateContentHeight(dialogElement);\r\n }\r\n };\r\n\r\n const onMouseUp = () => {\r\n isResizing = false;\r\n document.removeEventListener('mousemove', onMouseMove);\r\n document.removeEventListener('mouseup', onMouseUp);\r\n };\r\n\r\n document.addEventListener('mousemove', onMouseMove);\r\n document.addEventListener('mouseup', onMouseUp);\r\n });\r\n });\r\n });\r\n});\r\n\r\n// 更新内容区域高度\r\nconst updateContentHeight = (dialogElement: HTMLElement) => {\r\n const dialogHeight = dialogElement.offsetHeight;\r\n const dialogHeader = dialogElement.querySelector(\r\n '.el-dialog__header',\r\n ) as HTMLElement;\r\n const dialogFooter = dialogElement.querySelector(\r\n '.el-dialog__footer',\r\n ) as HTMLElement;\r\n\r\n // 计算 header 和 footer 的高度\r\n const headerHeight = dialogHeader ? dialogHeader.offsetHeight : 0;\r\n const footerHeight = dialogFooter ? dialogFooter.offsetHeight : 0;\r\n\r\n // 减去 header、footer 和 padding\r\n const padding = 40; // dialog 的上下 padding\r\n const availableHeight = dialogHeight - headerHeight - footerHeight - padding;\r\n\r\n contentWrapperHeight.value = `${availableHeight}px`;\r\n};\r\n</script>\r\n\r\n<template>\r\n <el-dialog\r\n v-model=\"visible\"\r\n align-center\r\n append-to-body\r\n destroy-on-close\r\n draggable\r\n :width=\"width\"\r\n :close-on-click-modal=\"false\"\r\n :close-on-press-escape=\"false\"\r\n :modal=\"false\"\r\n @closed=\"handleClosed\"\r\n >\r\n <div\r\n class=\"dialog-content-wrapper\"\r\n :style=\"{ maxHeight: contentWrapperHeight }\"\r\n >\r\n <component :is=\"name\" v-bind=\"safeComponentProps\" />\r\n </div>\r\n </el-dialog>\r\n</template>\r\n<style lang=\"scss\" scoped>\r\n.dialog-content-wrapper {\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n padding: var(--el-dialog-padding-primary);\r\n transition: max-height 0.1s ease;\r\n}\r\n\r\n// 四角拖拽手柄样式\r\n:deep(.el-dialog) {\r\n position: relative;\r\n\r\n .resize-handle {\r\n &::after {\r\n content: '';\r\n position: absolute;\r\n width: 8px;\r\n height: 8px;\r\n background: transparent;\r\n border: 2px solid var(--el-color-primary);\r\n border-radius: 50%;\r\n opacity: 0;\r\n transition: opacity 0.2s;\r\n }\r\n\r\n &:hover::after {\r\n opacity: 0.6;\r\n }\r\n\r\n &.resize-handle-top-left::after {\r\n top: 2px;\r\n left: 2px;\r\n }\r\n\r\n &.resize-handle-top-right::after {\r\n top: 2px;\r\n right: 2px;\r\n }\r\n\r\n &.resize-handle-bottom-left::after {\r\n bottom: 2px;\r\n left: 2px;\r\n }\r\n\r\n &.resize-handle-bottom-right::after {\r\n bottom: 2px;\r\n right: 2px;\r\n }\r\n }\r\n}\r\n</style>\r\n","<script setup lang=\"ts\">\r\nimport { computed, nextTick, onMounted, ref } from 'vue';\r\n\r\nconst props = defineProps<{\r\n componentName: any;\r\n componentProps?: Record<string, any>;\r\n onDestroy?: () => void;\r\n width?: string;\r\n}>();\r\n\r\nconst visible = ref(true);\r\nconst contentWrapperHeight = ref('80vh'); // 动态控制内容高度\r\n\r\n// 处理 componentProps,避免传递响应式对象给动态组件\r\nconst safeComponentProps = computed(() => {\r\n if (!props.componentProps) return {};\r\n // 浅拷贝 props,避免响应式传递问题\r\n return { ...props.componentProps };\r\n});\r\n\r\nconst name = computed(() => props.componentName);\r\n\r\nconst handleClosed = () => {\r\n // Dialog 关闭动画完成后,调用销毁函数\r\n if (props.onDestroy) {\r\n props.onDestroy();\r\n }\r\n};\r\n\r\n// 添加四角拖拽缩放功能\r\nonMounted(() => {\r\n nextTick(() => {\r\n const dialogElement = document.querySelector('.el-dialog') as HTMLElement;\r\n if (!dialogElement) return;\r\n\r\n // 创建四个角的拖拽手柄\r\n const corners = [\r\n { position: 'top-left', cursor: 'nwse-resize' },\r\n { position: 'top-right', cursor: 'nesw-resize' },\r\n { position: 'bottom-left', cursor: 'nesw-resize' },\r\n { position: 'bottom-right', cursor: 'nwse-resize' },\r\n ];\r\n\r\n corners.forEach(({ position, cursor }) => {\r\n const handle = document.createElement('div');\r\n handle.className = `resize-handle resize-handle-${position}`;\r\n handle.style.cssText = `\r\n position: absolute;\r\n width: 12px;\r\n height: 12px;\r\n cursor: ${cursor};\r\n z-index: 9999;\r\n `;\r\n\r\n // 设置手柄位置\r\n if (position.includes('top')) handle.style.top = '0';\r\n if (position.includes('bottom')) handle.style.bottom = '0';\r\n if (position.includes('left')) handle.style.left = '0';\r\n if (position.includes('right')) handle.style.right = '0';\r\n\r\n dialogElement.append(handle);\r\n\r\n // 添加拖拽事件\r\n let isResizing = false;\r\n let startX = 0;\r\n let startY = 0;\r\n let startWidth = 0;\r\n let startHeight = 0;\r\n let startLeft = 0;\r\n let startTop = 0;\r\n\r\n handle.addEventListener('mousedown', (e: MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n isResizing = true;\r\n\r\n startX = e.clientX;\r\n startY = e.clientY;\r\n startWidth = dialogElement.offsetWidth;\r\n startHeight = dialogElement.offsetHeight;\r\n startLeft = dialogElement.offsetLeft;\r\n startTop = dialogElement.offsetTop;\r\n\r\n const onMouseMove = (moveEvent: MouseEvent) => {\r\n if (!isResizing) return;\r\n\r\n const deltaX = moveEvent.clientX - startX;\r\n const deltaY = moveEvent.clientY - startY;\r\n\r\n let newWidth = startWidth;\r\n let newHeight = startHeight;\r\n let newLeft = startLeft;\r\n let newTop = startTop;\r\n\r\n // 根据不同的角落计算新的尺寸和位置\r\n if (position.includes('right')) {\r\n newWidth = startWidth + deltaX;\r\n }\r\n if (position.includes('left')) {\r\n newWidth = startWidth - deltaX;\r\n newLeft = startLeft + deltaX;\r\n }\r\n if (position.includes('bottom')) {\r\n newHeight = startHeight + deltaY;\r\n }\r\n if (position.includes('top')) {\r\n newHeight = startHeight - deltaY;\r\n newTop = startTop + deltaY;\r\n }\r\n\r\n // 设置最小尺寸\r\n const minWidth = 300;\r\n const minHeight = 200;\r\n\r\n if (newWidth >= minWidth) {\r\n dialogElement.style.width = `${newWidth}px`;\r\n if (position.includes('left')) {\r\n dialogElement.style.left = `${newLeft}px`;\r\n }\r\n }\r\n\r\n if (newHeight >= minHeight) {\r\n dialogElement.style.height = `${newHeight}px`;\r\n if (position.includes('top')) {\r\n dialogElement.style.top = `${newTop}px`;\r\n }\r\n\r\n // 动态更新内容区域高度\r\n updateContentHeight(dialogElement);\r\n }\r\n };\r\n\r\n const onMouseUp = () => {\r\n isResizing = false;\r\n document.removeEventListener('mousemove', onMouseMove);\r\n document.removeEventListener('mouseup', onMouseUp);\r\n };\r\n\r\n document.addEventListener('mousemove', onMouseMove);\r\n document.addEventListener('mouseup', onMouseUp);\r\n });\r\n });\r\n });\r\n});\r\n\r\n// 更新内容区域高度\r\nconst updateContentHeight = (dialogElement: HTMLElement) => {\r\n const dialogHeight = dialogElement.offsetHeight;\r\n const dialogHeader = dialogElement.querySelector(\r\n '.el-dialog__header',\r\n ) as HTMLElement;\r\n const dialogFooter = dialogElement.querySelector(\r\n '.el-dialog__footer',\r\n ) as HTMLElement;\r\n\r\n // 计算 header 和 footer 的高度\r\n const headerHeight = dialogHeader ? dialogHeader.offsetHeight : 0;\r\n const footerHeight = dialogFooter ? dialogFooter.offsetHeight : 0;\r\n\r\n // 减去 header、footer 和 padding\r\n const padding = 40; // dialog 的上下 padding\r\n const availableHeight = dialogHeight - headerHeight - footerHeight - padding;\r\n\r\n contentWrapperHeight.value = `${availableHeight}px`;\r\n};\r\n</script>\r\n\r\n<template>\r\n <el-dialog\r\n v-model=\"visible\"\r\n align-center\r\n append-to-body\r\n destroy-on-close\r\n draggable\r\n :width=\"width\"\r\n :close-on-click-modal=\"false\"\r\n :close-on-press-escape=\"false\"\r\n :modal=\"false\"\r\n @closed=\"handleClosed\"\r\n >\r\n <div\r\n class=\"dialog-content-wrapper\"\r\n :style=\"{ maxHeight: contentWrapperHeight }\"\r\n >\r\n <component :is=\"name\" v-bind=\"safeComponentProps\" />\r\n </div>\r\n </el-dialog>\r\n</template>\r\n<style lang=\"scss\" scoped>\r\n.dialog-content-wrapper {\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n padding: var(--el-dialog-padding-primary);\r\n transition: max-height 0.1s ease;\r\n}\r\n\r\n// 四角拖拽手柄样式\r\n:deep(.el-dialog) {\r\n position: relative;\r\n\r\n .resize-handle {\r\n &::after {\r\n content: '';\r\n position: absolute;\r\n width: 8px;\r\n height: 8px;\r\n background: transparent;\r\n border: 2px solid var(--el-color-primary);\r\n border-radius: 50%;\r\n opacity: 0;\r\n transition: opacity 0.2s;\r\n }\r\n\r\n &:hover::after {\r\n opacity: 0.6;\r\n }\r\n\r\n &.resize-handle-top-left::after {\r\n top: 2px;\r\n left: 2px;\r\n }\r\n\r\n &.resize-handle-top-right::after {\r\n top: 2px;\r\n right: 2px;\r\n }\r\n\r\n &.resize-handle-bottom-left::after {\r\n bottom: 2px;\r\n left: 2px;\r\n }\r\n\r\n &.resize-handle-bottom-right::after {\r\n bottom: 2px;\r\n right: 2px;\r\n }\r\n }\r\n}\r\n</style>\r\n","import AppFormRender from './AppFormRender.vue';\r\nimport AppTableRender from './AppTableRender.vue';\r\nimport DrawerForm from './components/DrawerForm.vue';\r\nimport DynamicDialogHost from './DynamicDialogHost.vue';\r\nimport type { App } from 'vue';\r\n\r\n(AppFormRender as any).name = 'AppFormRender';\r\n(AppTableRender as any).name = 'AppTableRender';\r\n(DrawerForm as any).name = 'DrawerForm';\r\n\r\nAppFormRender.install = (app: App) => {\r\n app.component('AppFormRender', AppFormRender);\r\n};\r\n\r\nAppTableRender.install = (app: App) => {\r\n app.component('AppTableRender', AppTableRender);\r\n};\r\n\r\nDrawerForm.install = (app: App) => {\r\n app.component('DrawerForm', DrawerForm);\r\n}\r\n\r\nexport { AppFormRender, AppTableRender, DrawerForm, DynamicDialogHost };\r\n","import { createVNode, markRaw, render } from 'vue';\r\n\r\nimport { getAppInstance, getRegisterComponent } from '@/config';\r\nimport { DynamicDialogHost } from \"@/components\";\r\n\r\nexport interface DialogOptions {\r\n name: string;\r\n componentProps?: Record<string, any>;\r\n width?: string;\r\n autoOpen?: boolean;\r\n}\r\n\r\nexport const createDynamicContentDialog = async ({\r\n name,\r\n componentProps = {},\r\n width = '80%',\r\n}: DialogOptions) => {\r\n const app = getAppInstance();\r\n const registerComponent = getRegisterComponent();\r\n\r\n if (registerComponent) {\r\n registerComponent(name);\r\n }\r\n\r\n // 为每个 dialog 创建独立的容器\r\n const container = document.createElement('div');\r\n container.className = 'dynamic-dialog-container';\r\n document.body.append(container);\r\n\r\n // 深度解除 componentProps 的响应式\r\n const rawProps = structuredClone({\r\n ...componentProps,\r\n });\r\n\r\n // 销毁函数\r\n const destroy = () => {\r\n render(null, container); // 卸载组件\r\n container.remove(); // 移除 DOM\r\n };\r\n\r\n // 增强 props,添加 close 事件监听\r\n const enhancedProps = {\r\n ...rawProps,\r\n onClose: () => {\r\n // 收到子组件的 close emit 后销毁实例\r\n destroy();\r\n },\r\n };\r\n\r\n // 创建 VNode\r\n const vnode = createVNode(markRaw(DynamicDialogHost), {\r\n componentName: name,\r\n componentProps: enhancedProps,\r\n width,\r\n onDestroy: destroy, // 传递销毁函数给 DynamicDialogHost\r\n });\r\n\r\n // 继承主应用的上下文(包含 Element Plus 全局组件)\r\n if (app) {\r\n vnode.appContext = (app as any)._context;\r\n }\r\n\r\n // 渲染到 DOM\r\n render(vnode, container);\r\n\r\n // 返回控制接口\r\n return {\r\n destroy,\r\n };\r\n};\r\n","/**\n * 睡眠\n *\n * @param time 秒\n */\nexport function sleep(time: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, time * 1000);\n });\n}\n","import { KeButton } from '@/types';\r\n\r\nimport { executeButtonProgramApi } from '@/api';\r\nimport { isEmpty, msgTips, createDynamicContentDialog, isNotEmpty } from '@/utils';\r\n\r\n/**\r\n * 单条数据上的按钮\r\n * @param data 数据\r\n * @param button 按钮配置\r\n * @param rowIndex 行索引\r\n */\r\nexport async function useButtonExec(\r\n data: any,\r\n button: KeButton,\r\n rowIndex?: number,\r\n) {\r\n // 前端按钮\r\n if (\r\n button.webTrigger && // 为空则停止运行\r\n isEmpty(button.webFunction)\r\n ) {\r\n return;\r\n }\r\n // 如果设置了触发前提示\r\n if (button.clickTips) {\r\n msgTips.alert({\r\n type: 'warning',\r\n msg: button.clickTips,\r\n callback: async () => {\r\n if (button.webTrigger) {\r\n // 执行前端函数\r\n execWebFunction(data, button, rowIndex);\r\n } else {\r\n // 后端方法\r\n await execServerButton(data, button);\r\n }\r\n },\r\n });\r\n } else if (button.webTrigger) {\r\n execWebFunction(data, button, rowIndex);\r\n // execWebFunction(data, button.params, rowIndex);\r\n } else {\r\n await execServerButton(data, button);\r\n }\r\n}\r\n\r\nfunction execWebFunction(data: any, button: KeButton, rowIndex?: number) {\r\n const toolPackage = {\r\n createDynamicContentDialog,\r\n };\r\n button.webFunction(data, button.params, rowIndex, toolPackage);\r\n}\r\n\r\n/**\r\n * 执行后端程序\r\n *\r\n * 直接暴力取data里面的pageId和dataId\r\n *\r\n * @param data\r\n * @param button\r\n */\r\nasync function execServerButton(data: any, button: KeButton) {\r\n console.error(button)\r\n let pageId = null;\r\n if (typeof button.params.pageId === 'number') {\r\n pageId = button.params.pageId;\r\n } else if (button.params[\"getPageId\"] && isNotEmpty(button.params[\"getPageId\"]())) {\r\n pageId = button.params[\"getPageId\"]()\r\n } else if (data.pageId?.value) {\r\n pageId = data.pageId.value;\r\n }\r\n const dataId = button.params.dataId || null;\r\n // 后端触发\r\n const result = await executeButtonProgramApi(pageId, dataId, button.id);\r\n if (\r\n result.code === 0 && // 如果有消息 则显示执行后的提示\r\n Array.isArray(result.data) &&\r\n result.data.length > 0\r\n ) {\r\n result.data.forEach((item: any) =>\r\n msgTips.tips({\r\n msg: item,\r\n type: 'info',\r\n duration: 5000,\r\n }),\r\n );\r\n }\r\n}\r\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { KeButton } from '../../types';\n\nimport { useButtonExec } from '../../hooks/useButtonExec.hook';\n\nimport { ElButtonPlus } from '../ElPlusComponent';\n\ndefineProps({\n toolButtons: {\n required: true,\n type: Array as PropType<KeButton[]>,\n },\n});\n\nconst btnClick = (data: any, button: any) => {\n useButtonExec(data, button);\n};\n</script>\n\n<template>\n <el-scrollbar class=\"tool-bar\">\n <div class=\"button-group\">\n <ElButtonPlus\n v-for=\"btn in toolButtons\"\n :key=\"btn.id\"\n :label=\"btn.label\"\n :icon=\"btn.icon\"\n :type=\"btn.type\"\n @click=\"btnClick(null, btn)\"\n />\n <slot name=\"custom-button\"></slot>\n </div>\n </el-scrollbar>\n</template>\n\n<style scoped lang=\"scss\">\n.tool-bar {\n padding: 8px;\n background: var(--el-fill-color-blank);\n\n :deep(.el-scrollbar__view) {\n display: flex;\n flex-direction: row-reverse;\n gap: 8px;\n justify-content: flex-start;\n }\n}\n</style>\n","<script setup lang=\"ts\">\nimport type { PropType } from 'vue';\n\nimport type { KeButton } from '../../types';\n\nimport { useButtonExec } from '../../hooks/useButtonExec.hook';\n\nimport { ElButtonPlus } from '../ElPlusComponent';\n\ndefineProps({\n toolButtons: {\n required: true,\n type: Array as PropType<KeButton[]>,\n },\n});\n\nconst btnClick = (data: any, button: any) => {\n useButtonExec(data, button);\n};\n</script>\n\n<template>\n <el-scrollbar class=\"tool-bar\">\n <div class=\"button-group\">\n <ElButtonPlus\n v-for=\"btn in toolButtons\"\n :key=\"btn.id\"\n :label=\"btn.label\"\n :icon=\"btn.icon\"\n :type=\"btn.type\"\n @click=\"btnClick(null, btn)\"\n />\n <slot name=\"custom-button\"></slot>\n </div>\n </el-scrollbar>\n</template>\n\n<style scoped lang=\"scss\">\n.tool-bar {\n padding: 8px;\n background: var(--el-fill-color-blank);\n\n :deep(.el-scrollbar__view) {\n display: flex;\n flex-direction: row-reverse;\n gap: 8px;\n justify-content: flex-start;\n }\n}\n</style>\n","import ToolBar from './ToolBar.vue';\nimport type { App } from 'vue';\n\n(ToolBar as any).name = 'ToolBar';\n\nToolBar.install = (app: App) => {\n app.component('ToolBar', ToolBar);\n};\n\nexport { ToolBar };\n","/**\n * VXE Table/Grid 剪贴板插件\n * 支持拖动选中、复制粘贴、Shift/Ctrl多选功能\n * 基于视觉顺序(DOM顺序)进行选取,支持固定列和拖拽排序后的正确选取\n *\n * 使用方式:\n * <vxe-table v-clipboard=\"{ rowSelectColumn: 'seq', onCopy: handleCopy }\">\n * <vxe-grid v-clipboard=\"{ rowSelectColumn: 'seq', onCopy: handleCopy }\">\n */\n\nimport type { App, Ref } from 'vue'\n\n// 类型定义\nexport interface ClipboardOptions {\n /** 点击哪一列选中整行,支持列索引或字段名/类型,-1 禁用 */\n rowSelectColumn?: number | string\n /** 选中背景色 */\n selectedColor?: string\n /** 选区变化回调 */\n onSelectionChange?: (range: SelectedRange) => void\n /** 复制回调 */\n onCopy?: (data: CellValue[][]) => void\n /** 粘贴回调 */\n onPaste?: (data: PasteCellChange[]) => void\n /** 剪切回调 */\n onCut?: (data: CellValue[][]) => void\n}\n\nexport interface SelectedRange {\n startRow: number\n startCol: number\n endRow: number\n endCol: number\n cells: CellData[][]\n}\n\nexport interface CellData {\n row: number\n col: number\n field: string\n value: CellValue\n rowId: string\n colid: string\n}\n\n/** 粘贴单元格变更信息 */\nexport interface PasteCellChange {\n row: number\n col: number\n field: string\n oldValue: CellValue\n newValue: CellValue\n rowId: string\n rowData: Record<string, CellValue>\n}\n\nexport type CellValue = string | number | boolean | null | undefined\n\nexport interface ClipboardInstance {\n init: () => void\n destroy: () => void\n copy: () => CellValue[][]\n paste: () => Promise<PasteCellChange[]>\n cut: () => CellValue[][]\n clearSelection: () => void\n selectRow: (rowIndex: number) => void\n getSelectedRange: () => SelectedRange\n getClipboardData: () => CellValue[][]\n}\n\ninterface VxeTableInstance {\n getTableData: () => { fullData: Record<string, CellValue>[] }\n getTableColumn: () => { fullColumn: VxeColumn[]; visibleColumn: VxeColumn[] }\n reloadData: (data: Record<string, CellValue>[]) => void\n getRowById: (rowId: string) => Record<string, CellValue> | null\n}\n\ninterface VxeColumn {\n id?: string\n field?: string\n type?: string\n}\n\n// 插件默认配置\nconst defaultOptions: ClipboardOptions = {\n rowSelectColumn: -1,\n selectedColor: 'rgba(64, 158, 255, 0.25)',\n onSelectionChange: undefined,\n onCopy: undefined,\n onPaste: undefined,\n onCut: undefined\n}\n\n// 全局配置\nlet globalOptions: ClipboardOptions = { ...defaultOptions }\n\n// 存储实例映射\nconst instanceMap = new WeakMap<HTMLElement, ClipboardInstance>()\n\n// 解析剪贴板值,尝试还原原始类型\nconst parseClipboardValue = (value: string): CellValue => {\n const trimmed = value.trim()\n \n // 空值\n if (trimmed === '' || trimmed === 'null' || trimmed === 'undefined') {\n return trimmed === 'null' ? null : trimmed === 'undefined' ? undefined : ''\n }\n \n // 布尔值\n if (trimmed === 'true') return true\n if (trimmed === 'false') return false\n \n // 数值(整数或浮点数)\n if (/^-?\\d+(\\.\\d+)?$/.test(trimmed)) {\n const num = Number(trimmed)\n if (!Number.isNaN(num)) return num\n }\n \n // 默认返回字符串\n return value\n}\n\n// 注入样式\nconst STYLE_ID = 'vxe-table-clipboard-style'\nfunction injectStyles(options: ClipboardOptions): void {\n const oldStyle = document.getElementById(STYLE_ID)\n if (oldStyle) oldStyle.remove()\n\n const style = document.createElement('style')\n style.id = STYLE_ID\n style.textContent = `\n .cell-selected {\n background-color: ${options.selectedColor} !important;\n }\n .vxe-table-clipboard-enabled {\n user-select: none;\n -webkit-user-select: none;\n }\n .vxe-table-clipboard-enabled .vxe-cell--edit input,\n .vxe-table-clipboard-enabled .vxe-cell--edit textarea {\n user-select: text;\n -webkit-user-select: text;\n }\n `\n document.head.appendChild(style)\n}\n\n/**\n * 创建剪贴板实例\n */\nfunction createClipboardInstance(el: HTMLElement, options: ClipboardOptions = {}): ClipboardInstance {\n const config = { ...globalOptions, ...options }\n\n let isDragging = false\n let startCell: { visualRow: number; visualCol: number } | null = null\n let clipboardData: CellValue[][] = []\n let startFromRowSelectColumn = false\n\n // 当前选区(基于视觉索引)\n const selectedRange: SelectedRange = {\n startRow: -1,\n startCol: -1,\n endRow: -1,\n endCol: -1,\n cells: []\n }\n\n // 已选中的单元格集合 (key: \"visualRow-visualCol\")\n const selectedCellsSet = new Set<string>()\n\n // 锚点位置(视觉索引)\n let anchorRow = -1\n let anchorCol = -1\n\n // 获取 vxe-table/grid 实例\n const getTableInstance = (): VxeTableInstance | null => {\n const component = (el as any).__vueParentComponent\n return component?.exposed || component?.proxy || null\n }\n\n const preventDrag = (e: Event): void => {\n const target = e.target as Element\n if (target.closest('.vxe-row--drag-node, .vxe-column--drag-node, .sortable-handle, [draggable=\"true\"]')) {\n return\n }\n e.preventDefault()\n }\n\n const handleSelectStart = (e: Event): void => {\n if (isDragging) e.preventDefault()\n }\n\n // 获取所有可见行的 rowId 列表(按视觉顺序)\n const getVisualRowIds = (): string[] => {\n const tbody = el.querySelector('.vxe-table--body-wrapper tbody')\n if (!tbody) return []\n const rows = tbody.querySelectorAll('tr.vxe-body--row')\n return Array.from(rows).map(row => row.getAttribute('rowId') || '').filter(Boolean)\n }\n\n // 获取所有可见列的 colid 列表(按视觉顺序,合并固定列)\n const getVisualColIds = (): string[] => {\n const $table = getTableInstance()\n if ($table) {\n // 使用 visibleColumn 获取按视觉顺序排列的列\n const visibleColumns = $table.getTableColumn().visibleColumn || $table.getTableColumn().fullColumn\n return visibleColumns.map((col: VxeColumn) => col.id || '').filter(Boolean)\n }\n // 降级:从 DOM 获取\n const firstRow = el.querySelector('.vxe-table--body-wrapper tbody tr.vxe-body--row')\n if (!firstRow) return []\n const cells = firstRow.querySelectorAll('td.vxe-body--column')\n return Array.from(cells).map(cell => cell.getAttribute('colid') || '').filter(Boolean)\n }\n\n // 获取视觉行索引(基于 DOM 顺序)\n const getVisualRowIndex = (element: Element): number => {\n const row = element.closest('tr.vxe-body--row')\n if (!row) return -1\n const rowId = row.getAttribute('rowId')\n if (!rowId) return -1\n const visualRowIds = getVisualRowIds()\n return visualRowIds.indexOf(rowId)\n }\n\n // 获取视觉列索引(基于可见列顺序)\n const getVisualColIndex = (element: Element): number => {\n const cell = element.closest('td.vxe-body--column')\n if (!cell) return -1\n const colid = cell.getAttribute('colid')\n if (!colid) return -1\n const visualColIds = getVisualColIds()\n return visualColIds.indexOf(colid)\n }\n\n const getCellPosition = (target: EventTarget | null): { visualRow: number; visualCol: number } | null => {\n if (!(target instanceof Element)) return null\n const cell = target.closest('td.vxe-body--column')\n if (!cell) return null\n const visualRow = getVisualRowIndex(cell)\n const visualCol = getVisualColIndex(cell)\n if (visualRow === -1 || visualCol === -1) return null\n return { visualRow, visualCol }\n }\n\n const getTotalColumns = (): number => {\n return getVisualColIds().length\n }\n\n const getTotalRows = (): number => {\n return getVisualRowIds().length\n }\n\n const cellKey = (row: number, col: number): string => `${row}-${col}`\n\n const clearSelection = (): void => {\n el.querySelectorAll('.cell-selected').forEach((cell) => cell.classList.remove('cell-selected'))\n selectedRange.startRow = -1\n selectedRange.startCol = -1\n selectedRange.endRow = -1\n selectedRange.endCol = -1\n selectedRange.cells = []\n selectedCellsSet.clear()\n window.getSelection()?.removeAllRanges()\n }\n\n const addRangeToSet = (startRow: number, startCol: number, endRow: number, endCol: number): void => {\n const minRow = Math.min(startRow, endRow)\n const maxRow = Math.max(startRow, endRow)\n const minCol = Math.min(startCol, endCol)\n const maxCol = Math.max(startCol, endCol)\n\n for (let r = minRow; r <= maxRow; r++) {\n for (let c = minCol; c <= maxCol; c++) {\n selectedCellsSet.add(cellKey(r, c))\n }\n }\n }\n\n // 高亮所有选中的单元格\n const highlightAllSelected = (): void => {\n el.querySelectorAll('.cell-selected').forEach((cell) => cell.classList.remove('cell-selected'))\n\n const visualRowIds = getVisualRowIds()\n const visualColIds = getVisualColIds()\n\n // 遍历所有 body wrapper(包括固定列区域)\n const wrappers = el.querySelectorAll(\n '.vxe-table--body-wrapper tbody, .vxe-table--fixed-left-body-wrapper tbody, .vxe-table--fixed-right-body-wrapper tbody'\n )\n\n wrappers.forEach((tbody) => {\n tbody.querySelectorAll('tr.vxe-body--row').forEach((row) => {\n const rowId = row.getAttribute('rowId')\n if (!rowId) return\n const visualRowIndex = visualRowIds.indexOf(rowId)\n if (visualRowIndex === -1) return\n\n row.querySelectorAll('td.vxe-body--column').forEach((cell) => {\n const colid = cell.getAttribute('colid')\n if (!colid) return\n const visualColIndex = visualColIds.indexOf(colid)\n if (visualColIndex === -1) return\n\n if (selectedCellsSet.has(cellKey(visualRowIndex, visualColIndex))) {\n cell.classList.add('cell-selected')\n }\n })\n })\n })\n\n window.getSelection()?.removeAllRanges()\n }\n\n const highlightCurrentRange = (): void => {\n highlightAllSelected()\n\n const minRow = Math.min(selectedRange.startRow, selectedRange.endRow)\n const maxRow = Math.max(selectedRange.startRow, selectedRange.endRow)\n const minCol = Math.min(selectedRange.startCol, selectedRange.endCol)\n const maxCol = Math.max(selectedRange.startCol, selectedRange.endCol)\n\n const visualRowIds = getVisualRowIds()\n const visualColIds = getVisualColIds()\n\n const wrappers = el.querySelectorAll(\n '.vxe-table--body-wrapper tbody, .vxe-table--fixed-left-body-wrapper tbody, .vxe-table--fixed-right-body-wrapper tbody'\n )\n\n wrappers.forEach((tbody) => {\n tbody.querySelectorAll('tr.vxe-body--row').forEach((row) => {\n const rowId = row.getAttribute('rowId')\n if (!rowId) return\n const visualRowIndex = visualRowIds.indexOf(rowId)\n if (visualRowIndex === -1) return\n\n if (visualRowIndex >= minRow && visualRowIndex <= maxRow) {\n row.querySelectorAll('td.vxe-body--column').forEach((cell) => {\n const colid = cell.getAttribute('colid')\n if (!colid) return\n const visualColIndex = visualColIds.indexOf(colid)\n if (visualColIndex === -1) return\n\n if (visualColIndex >= minCol && visualColIndex <= maxCol) {\n cell.classList.add('cell-selected')\n }\n })\n }\n })\n })\n }\n\n // 收集选中的单元格数据\n const collectSelectedCells = (): void => {\n const $table = getTableInstance()\n if (!$table) return\n\n const tableData = $table.getTableData().fullData\n const visualRowIds = getVisualRowIds()\n const visualColIds = getVisualColIds()\n const allColumns = $table.getTableColumn().fullColumn\n\n const rowsMap = new Map<number, CellData[]>()\n\n selectedCellsSet.forEach((key) => {\n const parts = key.split('-').map(Number) as [number, number]\n const visualRow = parts[0]\n const visualCol = parts[1]\n\n const rowId = visualRowIds[visualRow]\n const colid = visualColIds[visualCol]\n if (!rowId || !colid) return\n\n // 通过 rowId 找到实际数据行(兼容 keyField 配置)\n let rowData: Record<string, CellValue> | null | undefined = $table.getRowById(rowId)\n if (!rowData) {\n // 降级:尝试用 _X_ROW_KEY 匹配\n rowData = tableData.find((item: any) => item._X_ROW_KEY === rowId || String(item._X_ROW_KEY) === rowId)\n }\n if (!rowData) return\n\n // 通过 colid 找到列配置\n const col = allColumns.find((c: VxeColumn) => c.id === colid)\n if (!col?.field) return\n\n if (!rowsMap.has(visualRow)) rowsMap.set(visualRow, [])\n rowsMap.get(visualRow)!.push({\n row: visualRow,\n col: visualCol,\n field: col.field,\n value: rowData[col.field],\n rowId,\n colid\n })\n })\n\n selectedRange.cells = Array.from(rowsMap.entries())\n .sort((a, b) => a[0] - b[0])\n .map(([, cells]) => cells.sort((a, b) => a.col - b.col))\n }\n\n const copyToClipboard = (data: CellValue[][]): CellValue[][] => {\n clipboardData = data\n const text = data.map((row) => row.join('\\t')).join('\\n')\n navigator.clipboard.writeText(text).catch((err) => {\n console.warn('复制到剪贴板失败:', err)\n })\n return data\n }\n\n const pasteFromClipboard = async (): Promise<PasteCellChange[]> => {\n const $table = getTableInstance()\n if (!$table) return []\n\n let pasteData: CellValue[][] = clipboardData\n try {\n const text = await navigator.clipboard.readText()\n if (text) {\n // 统一处理换行符:Windows 使用 \\r\\n,Mac/Linux 使用 \\n\n const normalizedText = text.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n')\n pasteData = normalizedText.split('\\n').filter((r) => r.trim()).map((r) => \n r.split('\\t').map((cell) => parseClipboardValue(cell))\n )\n }\n } catch {}\n\n if (pasteData.length === 0) return []\n\n const tableData = $table.getTableData().fullData\n const visualRowIds = getVisualRowIds()\n const visualColIds = getVisualColIds()\n const allColumns = $table.getTableColumn().fullColumn\n\n // 找到选区的起始位置(视觉索引)\n let startVisualRow = Infinity\n let startVisualCol = Infinity\n selectedCellsSet.forEach((key) => {\n const parts = key.split('-').map(Number) as [number, number]\n startVisualRow = Math.min(startVisualRow, parts[0])\n startVisualCol = Math.min(startVisualCol, parts[1])\n })\n\n if (startVisualRow === Infinity) return []\n\n // 收集变更信息\n const changes: PasteCellChange[] = []\n\n pasteData.forEach((rowData, rowOffset) => {\n const targetVisualRow = startVisualRow + rowOffset\n const targetRowId = visualRowIds[targetVisualRow]\n if (!targetRowId) return\n\n // 通过 rowId 找到实际数据行(兼容 keyField 配置)\n let targetRowData: Record<string, CellValue> | null | undefined = $table.getRowById(targetRowId)\n if (!targetRowData) {\n targetRowData = tableData.find((item: any) => item._X_ROW_KEY === targetRowId || String(item._X_ROW_KEY) === targetRowId)\n }\n if (!targetRowData) return\n\n rowData.forEach((newValue, colOffset) => {\n const targetVisualCol = startVisualCol + colOffset\n const targetColId = visualColIds[targetVisualCol]\n if (!targetColId) return\n\n const col = allColumns.find((c: VxeColumn) => c.id === targetColId)\n if (col?.field) {\n const oldValue = targetRowData[col.field]\n targetRowData[col.field] = newValue\n \n changes.push({\n row: targetVisualRow,\n col: targetVisualCol,\n field: col.field,\n oldValue,\n newValue,\n rowId: targetRowId,\n rowData: { ...targetRowData },\n })\n }\n })\n })\n\n $table.reloadData(tableData)\n highlightAllSelected()\n \n return changes\n }\n\n const clearSelectedCellsData = (): void => {\n const $table = getTableInstance()\n if (!$table) return\n\n const tableData = $table.getTableData().fullData\n const visualRowIds = getVisualRowIds()\n const visualColIds = getVisualColIds()\n const allColumns = $table.getTableColumn().fullColumn\n\n selectedCellsSet.forEach((key) => {\n const parts = key.split('-').map(Number) as [number, number]\n const visualRow = parts[0]\n const visualCol = parts[1]\n\n const rowId = visualRowIds[visualRow]\n const colid = visualColIds[visualCol]\n if (!rowId || !colid) return\n\n // 通过 rowId 找到实际数据行(兼容 keyField 配置)\n let rowData: Record<string, CellValue> | null | undefined = $table.getRowById(rowId)\n if (!rowData) {\n rowData = tableData.find((item: any) => item._X_ROW_KEY === rowId || String(item._X_ROW_KEY) === rowId)\n }\n if (!rowData) return\n\n const col = allColumns.find((c: VxeColumn) => c.id === colid)\n if (col?.field) {\n rowData[col.field] = ''\n }\n })\n\n $table.reloadData(tableData)\n }\n\n const isRowSelectColumn = (visualColIndex: number): boolean => {\n const { rowSelectColumn } = config\n if (rowSelectColumn === -1 || rowSelectColumn === null || rowSelectColumn === undefined) {\n return false\n }\n\n if (typeof rowSelectColumn === 'number') {\n return visualColIndex === rowSelectColumn\n }\n\n if (typeof rowSelectColumn === 'string') {\n const $table = getTableInstance()\n if (!$table) return false\n\n const visualColIds = getVisualColIds()\n const allColumns = $table.getTableColumn().fullColumn\n\n const colid = visualColIds[visualColIndex]\n if (!colid) return false\n\n const col = allColumns.find((c: VxeColumn) => c.id === colid)\n return col?.field === rowSelectColumn || col?.type === rowSelectColumn\n }\n\n return false\n }\n\n const handleMouseDown = (e: MouseEvent): void => {\n if (e.button !== 0) return\n\n const target = e.target as Element\n if (target.closest('.vxe-row--drag-node, .vxe-column--drag-node, .sortable-handle, [draggable=\"true\"]')) {\n return\n }\n\n const cellPos = getCellPosition(e.target)\n if (!cellPos) return\n if (target.closest('.vxe-cell--edit, input, textarea, .vxe-checkbox--icon, .el-button')) return\n\n e.preventDefault()\n\n const isShift = e.shiftKey\n const isCtrl = e.ctrlKey || e.metaKey\n const totalCols = getTotalColumns()\n\n startFromRowSelectColumn = isRowSelectColumn(cellPos.visualCol)\n\n // Shift + 点击\n if (isShift && anchorRow >= 0) {\n selectedCellsSet.clear()\n\n if (startFromRowSelectColumn || isRowSelectColumn(anchorCol)) {\n selectedRange.startRow = anchorRow\n selectedRange.startCol = 0\n selectedRange.endRow = cellPos.visualRow\n selectedRange.endCol = totalCols - 1\n } else {\n selectedRange.startRow = anchorRow\n selectedRange.startCol = anchorCol\n selectedRange.endRow = cellPos.visualRow\n selectedRange.endCol = cellPos.visualCol\n }\n\n addRangeToSet(selectedRange.startRow, selectedRange.startCol, selectedRange.endRow, selectedRange.endCol)\n highlightAllSelected()\n collectSelectedCells()\n config.onSelectionChange?.(selectedRange)\n return\n }\n\n // Ctrl + 点击:保留之前选区\n if (!isCtrl) {\n clearSelection()\n }\n\n if (startFromRowSelectColumn) {\n selectedRange.startRow = cellPos.visualRow\n selectedRange.startCol = 0\n selectedRange.endRow = cellPos.visualRow\n selectedRange.endCol = totalCols - 1\n anchorRow = cellPos.visualRow\n anchorCol = 0\n } else {\n selectedRange.startRow = cellPos.visualRow\n selectedRange.startCol = cellPos.visualCol\n selectedRange.endRow = cellPos.visualRow\n selectedRange.endCol = cellPos.visualCol\n anchorRow = cellPos.visualRow\n anchorCol = cellPos.visualCol\n }\n\n isDragging = true\n startCell = cellPos\n highlightCurrentRange()\n }\n\n const handleMouseMove = (e: MouseEvent): void => {\n if (!isDragging || !startCell) return\n const cellPos = getCellPosition(e.target)\n if (!cellPos) return\n e.preventDefault()\n\n selectedRange.endRow = cellPos.visualRow\n\n if (startFromRowSelectColumn) {\n const totalCols = getTotalColumns()\n selectedRange.startCol = 0\n selectedRange.endCol = totalCols - 1\n } else {\n selectedRange.endCol = cellPos.visualCol\n }\n\n highlightCurrentRange()\n }\n\n const handleMouseUp = (): void => {\n if (isDragging) {\n isDragging = false\n addRangeToSet(selectedRange.startRow, selectedRange.startCol, selectedRange.endRow, selectedRange.endCol)\n collectSelectedCells()\n config.onSelectionChange?.(selectedRange)\n }\n }\n\n const handleKeyDown = (e: KeyboardEvent): void => {\n if ((e.target as Element).closest('input, textarea')) return\n\n // Ctrl+A 全选\n if ((e.ctrlKey || e.metaKey) && e.key === 'a') {\n const totalRows = getTotalRows()\n const totalCols = getTotalColumns()\n if (totalRows > 0 && totalCols > 0) {\n e.preventDefault()\n clearSelection()\n selectedRange.startRow = 0\n selectedRange.startCol = 0\n selectedRange.endRow = totalRows - 1\n selectedRange.endCol = totalCols - 1\n anchorRow = 0\n anchorCol = 0\n addRangeToSet(0, 0, totalRows - 1, totalCols - 1)\n highlightAllSelected()\n collectSelectedCells()\n config.onSelectionChange?.(selectedRange)\n }\n return\n }\n\n if ((e.ctrlKey || e.metaKey) && e.key === 'c' && selectedCellsSet.size > 0) {\n e.preventDefault()\n collectSelectedCells()\n const data = selectedRange.cells.map((row) => row.map((cell) => cell.value))\n copyToClipboard(data)\n config.onCopy?.(data)\n }\n\n if ((e.ctrlKey || e.metaKey) && e.key === 'v' && selectedCellsSet.size > 0) {\n e.preventDefault()\n pasteFromClipboard().then((data) => {\n config.onPaste?.(data)\n })\n }\n\n if ((e.ctrlKey || e.metaKey) && e.key === 'x' && selectedCellsSet.size > 0) {\n e.preventDefault()\n collectSelectedCells()\n const data = selectedRange.cells.map((row) => row.map((cell) => cell.value))\n copyToClipboard(data)\n clearSelectedCellsData()\n config.onCut?.(data)\n }\n\n if ((e.key === 'Delete' || e.key === 'Backspace') && selectedCellsSet.size > 0) {\n e.preventDefault()\n clearSelectedCellsData()\n }\n }\n\n const init = (): void => {\n el.classList.add('vxe-table-clipboard-enabled')\n el.addEventListener('mousedown', handleMouseDown as EventListener)\n el.addEventListener('dragstart', preventDrag)\n el.addEventListener('selectstart', handleSelectStart)\n document.addEventListener('mousemove', handleMouseMove as EventListener)\n document.addEventListener('mouseup', handleMouseUp)\n document.addEventListener('keydown', handleKeyDown as EventListener)\n }\n\n const destroy = (): void => {\n el.classList.remove('vxe-table-clipboard-enabled')\n el.removeEventListener('mousedown', handleMouseDown as EventListener)\n el.removeEventListener('dragstart', preventDrag)\n el.removeEventListener('selectstart', handleSelectStart)\n document.removeEventListener('mousemove', handleMouseMove as EventListener)\n document.removeEventListener('mouseup', handleMouseUp)\n document.removeEventListener('keydown', handleKeyDown as EventListener)\n clearSelection()\n }\n\n const instance: ClipboardInstance = {\n init,\n destroy,\n copy: () => {\n collectSelectedCells()\n if (selectedRange.cells.length > 0) {\n const data = selectedRange.cells.map((row) => row.map((cell) => cell.value))\n return copyToClipboard(data)\n }\n return []\n },\n paste: () => {\n if (selectedCellsSet.size > 0) {\n return pasteFromClipboard()\n }\n return Promise.resolve([])\n },\n cut: () => {\n collectSelectedCells()\n if (selectedRange.cells.length > 0) {\n const data = selectedRange.cells.map((row) => row.map((cell) => cell.value))\n copyToClipboard(data)\n clearSelectedCellsData()\n return data\n }\n return []\n },\n clearSelection,\n selectRow: (visualRowIndex: number) => {\n const totalCols = getTotalColumns()\n if (totalCols === 0) return\n clearSelection()\n selectedRange.startRow = visualRowIndex\n selectedRange.startCol = 0\n selectedRange.endRow = visualRowIndex\n selectedRange.endCol = totalCols - 1\n addRangeToSet(visualRowIndex, 0, visualRowIndex, totalCols - 1)\n highlightAllSelected()\n collectSelectedCells()\n },\n getSelectedRange: () => ({ ...selectedRange }),\n getClipboardData: () => [...clipboardData]\n }\n\n init()\n return instance\n}\n\n/**\n * Vue 插件\n */\nconst VXETableClipboard = {\n install(app: App, options: ClipboardOptions = {}): void {\n globalOptions = { ...defaultOptions, ...options }\n injectStyles(globalOptions)\n\n app.directive('clipboard', {\n mounted(el: HTMLElement, binding) {\n const opts = (binding.value || {}) as ClipboardOptions\n const instance = createClipboardInstance(el, opts)\n instanceMap.set(el, instance)\n },\n updated(el: HTMLElement, binding) {\n const oldInstance = instanceMap.get(el)\n if (oldInstance) oldInstance.destroy()\n const opts = (binding.value || {}) as ClipboardOptions\n const instance = createClipboardInstance(el, opts)\n instanceMap.set(el, instance)\n },\n unmounted(el: HTMLElement) {\n const instance = instanceMap.get(el)\n if (instance) {\n instance.destroy()\n instanceMap.delete(el)\n }\n }\n })\n\n app.config.globalProperties.$getClipboard = (el: HTMLElement) => instanceMap.get(el)\n }\n}\n\n// 组合式 API\nexport function useTableClipboard(\n tableRef: Ref<{ $el: HTMLElement } | null>,\n options: ClipboardOptions = {}\n): {\n init: () => void\n destroy: () => void\n copy: () => CellValue[][]\n paste: () => Promise<PasteCellChange[]>\n cut: () => CellValue[][]\n clearSelection: () => void\n selectRow: (index: number) => void\n getSelectedRange: () => SelectedRange | undefined\n getClipboardData: () => CellValue[][] | undefined\n} {\n let instance: ClipboardInstance | null = null\n\n return {\n init: () => {\n const el = tableRef.value?.$el\n if (el) instance = createClipboardInstance(el, options)\n },\n destroy: () => {\n instance?.destroy()\n instance = null\n },\n copy: () => instance?.copy() || [],\n paste: () => instance?.paste() || Promise.resolve([]),\n cut: () => instance?.cut() || [],\n clearSelection: () => instance?.clearSelection(),\n selectRow: (index: number) => instance?.selectRow(index),\n getSelectedRange: () => instance?.getSelectedRange(),\n getClipboardData: () => instance?.getClipboardData()\n }\n}\n\nexport default VXETableClipboard\n","/// <reference types=\"./types/global-components.d.ts\" />\r\nimport type { App } from 'vue';\r\n\r\nimport {\r\n ElButtonPlus,\r\n ElColPlus,\r\n ElRowPlus,\r\n} from './components/ElPlusComponent';\r\n\r\nimport { ToolBar } from './components/ToolBar';\r\n\r\nimport {\r\n QueryBar,\r\n QueryDateTime,\r\n QueryInput,\r\n QueryInputLike,\r\n QuerySelect,\r\n QueryTreeFilter,\r\n} from './components/QueryComponent';\r\n\r\nimport {\r\n TableInput,\r\n TableInputNumber,\r\n TableSelect,\r\n TableSelectAsync,\r\n TableSwitch,\r\n TableListSelect,\r\n TableListSelectAsync,\r\n TableCheckBoxAsync,\r\n TableRender,\r\n TableCardRender,\r\n} from './components/TableComponent';\r\n\r\nimport {\r\n FormInput,\r\n FormInputNumber,\r\n FormTextArea,\r\n FormText,\r\n FormSelect,\r\n FormSelectAsync,\r\n FormSelectRemote,\r\n FormRadio,\r\n FormCheckBox,\r\n FormCheckBoxAsync,\r\n FormSwitch,\r\n FormDatePicker,\r\n FormDateTimePicker,\r\n FormCascaderAsync,\r\n FormTableSelect,\r\n FormTableSelectAsync,\r\n FormDictSelector,\r\n FormIconPicker,\r\n FormImageUpload,\r\n FormCodeEditor,\r\n FormDivider,\r\n FormFieldset,\r\n FormDynamicTable,\r\n DynamicMapTable,\r\n FormRender,\r\n} from './components/FormComponent';\r\n\r\nimport {\r\n AppFormRender,\r\n AppTableRender,\r\n DrawerForm\r\n} from './components/AppComponent';\r\n\r\nimport VXETableClipboard from '@/components/TableComponent/TableRender/plugin/vxe-table-clipboard';\r\nimport { useTableFormats } from '@/hooks/useTableFormats.hook.ts';\r\nimport { dataFormatter } from '@/utils';\r\n\r\nexport * from './components';\r\nexport * from './types';\r\nexport * from './config';\r\nexport * from './utils'\r\nexport { convertAreaToFieldset } from '@/components/FormComponent/FormRender/hooks/formRender.hook';\r\nexport { codeLanguages } from '@/components/FormComponent/FormCodeEditor';\r\n\r\nconst components = [\r\n ElButtonPlus,\r\n ElColPlus,\r\n ElRowPlus,\r\n ToolBar,\r\n QueryBar,\r\n QueryDateTime,\r\n QueryInput,\r\n QueryInputLike,\r\n QuerySelect,\r\n QueryTreeFilter,\r\n TableInput,\r\n TableInputNumber,\r\n TableSelect,\r\n TableSelectAsync,\r\n TableSwitch,\r\n TableListSelect,\r\n TableListSelectAsync,\r\n TableCheckBoxAsync,\r\n TableRender,\r\n TableCardRender,\r\n FormInput,\r\n FormInputNumber,\r\n FormTextArea,\r\n FormText,\r\n FormSelect,\r\n FormSelectAsync,\r\n FormSelectRemote,\r\n FormRadio,\r\n FormCheckBox,\r\n FormCheckBoxAsync,\r\n FormSwitch,\r\n FormDatePicker,\r\n FormDateTimePicker,\r\n FormCascaderAsync,\r\n FormTableSelect,\r\n FormTableSelectAsync,\r\n FormDictSelector,\r\n FormIconPicker,\r\n FormImageUpload,\r\n FormCodeEditor,\r\n FormDivider,\r\n FormFieldset,\r\n FormDynamicTable,\r\n DynamicMapTable,\r\n FormRender,\r\n AppFormRender,\r\n AppTableRender,\r\n DrawerForm\r\n] as const;\r\n\r\nconst { registerGeneralMethods } = useTableFormats();\r\n\r\nconst install = (app: App, ...options: any[]): void => {\r\n components.forEach((component) => {\r\n if (component.install) {\r\n app.use(component as any);\r\n } else if (component.name) {\r\n app.component(component.name, component);\r\n }\r\n });\r\n\r\n app.use(VXETableClipboard)\r\n\r\n setTimeout(() => {\r\n registerGeneralMethods('parseString', ({ cellValue }: any) => {\r\n return dataFormatter.toString(cellValue);\r\n });\r\n registerGeneralMethods('parseInt', ({ cellValue }: any) => {\r\n return dataFormatter.parseInt(cellValue);\r\n });\r\n registerGeneralMethods('timestamp', ({ cellValue }: any) => {\r\n return dataFormatter.timestamp(cellValue);\r\n });\r\n }, 50);\r\n};\r\n\r\n/**\r\n * 控制深浅色模式\r\n */\r\nexport function initVxeTableEl() {\r\n // VxeUI.setTheme(preferences.isDark.value ? 'dark' : 'light');\r\n // watch(preferences.isDark, (newVal) => {\r\n // VxeUI.setTheme(newVal ? 'dark' : 'light');\r\n // });\r\n}\r\n\r\nconst KeliUI = {\r\n install,\r\n};\r\n\r\nexport default KeliUI;\r\n\r\nexport {\r\n ElButtonPlus,\r\n ElColPlus,\r\n ElRowPlus,\r\n ToolBar,\r\n QueryBar,\r\n QueryDateTime,\r\n QueryInput,\r\n QueryInputLike,\r\n QuerySelect,\r\n QueryTreeFilter,\r\n TableInput,\r\n TableInputNumber,\r\n TableSelect,\r\n TableSelectAsync,\r\n TableSwitch,\r\n TableListSelect,\r\n TableListSelectAsync,\r\n TableCheckBoxAsync,\r\n TableRender,\r\n TableCardRender,\r\n FormInput,\r\n FormInputNumber,\r\n FormTextArea,\r\n FormText,\r\n FormSelect,\r\n FormSelectAsync,\r\n FormSelectRemote,\r\n FormRadio,\r\n FormCheckBox,\r\n FormCheckBoxAsync,\r\n FormSwitch,\r\n FormDatePicker,\r\n FormDateTimePicker,\r\n FormCascaderAsync,\r\n FormTableSelect,\r\n FormTableSelectAsync,\r\n FormDictSelector,\r\n FormIconPicker,\r\n FormImageUpload,\r\n FormCodeEditor,\r\n FormDivider,\r\n FormFieldset,\r\n FormDynamicTable,\r\n DynamicMapTable,\r\n FormRender,\r\n AppFormRender,\r\n AppTableRender,\r\n DrawerForm\r\n};\r\n"],"mappings":"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"}
|