lyflowchart 1.0.135 → 1.0.139

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.
Files changed (42) hide show
  1. package/dist/{ApprovalEditorModal-suKPJ-vN.js → ApprovalEditorModal-19j5zbe2.js} +1 -1
  2. package/dist/{Cell_click_approve-DoemsGnY.js → Cell_click_approve-BGDZUzTS.js} +1 -1
  3. package/dist/{approval-BaVHder3.js → approval-BaD4Bmw6.js} +1 -1
  4. package/dist/components/approval/utils.d.ts +1 -0
  5. package/dist/{core-BOc9ch_5.js → core-Cv0Erg9E.js} +10 -11
  6. package/dist/index.js +2 -2
  7. package/dist/lyflowchart.css +1 -1
  8. package/package.json +1 -1
  9. package/dist/ActionsConfig-BuvSvRbv.js.map +0 -1
  10. package/dist/ApprovalEditorModal-suKPJ-vN.js.map +0 -1
  11. package/dist/CancelModal-BUi3ieI8.js.map +0 -1
  12. package/dist/Cell_click_approve-DoemsGnY.js.map +0 -1
  13. package/dist/JsonTags-BbWLqghI.js.map +0 -1
  14. package/dist/MyProcess-FWGEwQcv.js.map +0 -1
  15. package/dist/approval-BW2WjPxY.js.map +0 -1
  16. package/dist/approval-BaVHder3.js.map +0 -1
  17. package/dist/approvalHistory-B2gpQbFC.js.map +0 -1
  18. package/dist/approvalHistoryViewModal-DgLpv2ot.js.map +0 -1
  19. package/dist/approvalPageConfig-D0zPXOUf.js.map +0 -1
  20. package/dist/approveLeftConfig-BOU_UgHp.js.map +0 -1
  21. package/dist/codeHistoryViewModal-BfSjIbEU.js.map +0 -1
  22. package/dist/columnTables-DLwtgcC7.js.map +0 -1
  23. package/dist/core-BOc9ch_5.js.map +0 -1
  24. package/dist/dataStoreSettingHistoryViewModal-D_so-KLp.js.map +0 -1
  25. package/dist/debugCode-Cm9-WiUG.js.map +0 -1
  26. package/dist/debugCode-dD1YnQSD.js.map +0 -1
  27. package/dist/default-VdDMlY4e.js.map +0 -1
  28. package/dist/example_code-C_xF8RRG.js.map +0 -1
  29. package/dist/flowHistoryViewModal-D8DJP7Te.js.map +0 -1
  30. package/dist/index.js.map +0 -1
  31. package/dist/init-plugin-fQTSQzui.js.map +0 -1
  32. package/dist/leftColumn-CsPjufue.js.map +0 -1
  33. package/dist/middleColumn-C7M6-eVo.js.map +0 -1
  34. package/dist/recordActions-BgFlNsGU.js.map +0 -1
  35. package/dist/settingsState-CI81PG-i.js.map +0 -1
  36. package/dist/tableConfig-uLXue-BS.js.map +0 -1
  37. package/dist/tableModal-BcYfVL02.js.map +0 -1
  38. package/dist/useApprovalRecordActions-BQ6MgV2L.js.map +0 -1
  39. package/dist/utils-CLet2gLV.js.map +0 -1
  40. package/dist/v0001-OaBeBCXI.js.map +0 -1
  41. package/dist/viewer-Dv3kQsMf.js.map +0 -1
  42. package/dist/vue-print-next-HRweUmNi.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"tableConfig-uLXue-BS.js","names":[],"sources":["../src/components/approval/components/approvalPageConfig/JsonInput.vue","../src/components/approval/components/approvalPageConfig/JsonInput.vue","../src/components/approval/components/approvalPageConfig/ConditionFieldMulType.vue","../src/components/approval/components/approvalPageConfig/ConditionFieldMulType.vue","../src/components/approval/components/approvalPageConfig/BaseConditions.vue","../src/components/approval/components/approvalPageConfig/BaseConditions.vue","../src/components/approval/components/approvalPageConfig/cellEdit.vue","../src/components/approval/components/approvalPageConfig/cellEdit.vue","../src/components/approval/components/approvalPageConfig/ColumnConfig.vue","../src/components/approval/components/approvalPageConfig/ColumnConfig.vue","../src/components/approval/components/approvalPageConfig/operatorSelect.vue","../src/components/approval/components/approvalPageConfig/operatorSelect.vue","../src/components/approval/components/approvalPageConfig/defaultOperatorSelect.vue","../src/components/approval/components/approvalPageConfig/defaultOperatorSelect.vue","../src/components/approval/components/approvalPageConfig/searchConfig.vue","../src/components/approval/components/approvalPageConfig/searchConfig.vue","../src/components/approval/components/approvalPageConfig/configSync.vue","../src/components/approval/components/approvalPageConfig/configSync.vue","../src/components/approval/components/approvalPageConfig/confirmInput.vue","../src/components/approval/components/approvalPageConfig/confirmInput.vue","../src/components/approval/components/approvalPageConfig/tableConfig.vue","../src/components/approval/components/approvalPageConfig/tableConfig.vue"],"sourcesContent":["<template>\n <a-input\n :value=\"displayValue\"\n :placeholder=\"placeholder\"\n :style=\"style\"\n @update:value=\"updateValue\"\n >\n <template #addonAfter>\n <span\n v-if=\"valueType\"\n class=\"json-type\"\n >\n {{ valueType }}\n </span>\n </template>\n </a-input>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent } from 'vue';\n\nexport default defineComponent({\n name: 'JsonInput',\n props: {\n value: {\n type: [String, Number, Boolean, Object, Array] as any,\n default: '',\n },\n placeholder: {\n type: String,\n default: '输入值',\n },\n style: {\n type: Object as any,\n default: () => ({}),\n },\n },\n emits: ['update:value'],\n setup(props, { emit }) {\n // 展示值:字符串原样显示,其余转 JSON 字符串\n const displayValue = computed(() => {\n const v = props.value;\n if (typeof v === 'string') {\n return v;\n }\n if (v === null || v === undefined) {\n return '';\n }\n try {\n return JSON.stringify(v);\n } catch (e) {\n return String(v);\n }\n });\n // 当前值的数据类型(参考 JsonTags 的 [type] 展示)\n const valueType = computed(() => {\n const v = props.value;\n if (v === null) {\n return 'null';\n }\n if (v === undefined || v === '') {\n return '';\n }\n return typeof v;\n });\n // 输入时先尝试 JSON 解析:成功则存解析后的值(数字/布尔/对象/数组等),失败按字符串\n const updateValue = value => {\n if (value === '' || value === undefined || value === null) {\n emit('update:value', '');\n return;\n }\n try {\n emit('update:value', JSON.parse(value));\n } catch (e) {\n emit('update:value', value);\n }\n };\n return { displayValue, valueType, updateValue };\n },\n});\n</script>\n\n<style scoped lang=\"less\">\n.json-type {\n color: #1890ff;\n}\n</style>\n","<template>\n <a-input\n :value=\"displayValue\"\n :placeholder=\"placeholder\"\n :style=\"style\"\n @update:value=\"updateValue\"\n >\n <template #addonAfter>\n <span\n v-if=\"valueType\"\n class=\"json-type\"\n >\n {{ valueType }}\n </span>\n </template>\n </a-input>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent } from 'vue';\n\nexport default defineComponent({\n name: 'JsonInput',\n props: {\n value: {\n type: [String, Number, Boolean, Object, Array] as any,\n default: '',\n },\n placeholder: {\n type: String,\n default: '输入值',\n },\n style: {\n type: Object as any,\n default: () => ({}),\n },\n },\n emits: ['update:value'],\n setup(props, { emit }) {\n // 展示值:字符串原样显示,其余转 JSON 字符串\n const displayValue = computed(() => {\n const v = props.value;\n if (typeof v === 'string') {\n return v;\n }\n if (v === null || v === undefined) {\n return '';\n }\n try {\n return JSON.stringify(v);\n } catch (e) {\n return String(v);\n }\n });\n // 当前值的数据类型(参考 JsonTags 的 [type] 展示)\n const valueType = computed(() => {\n const v = props.value;\n if (v === null) {\n return 'null';\n }\n if (v === undefined || v === '') {\n return '';\n }\n return typeof v;\n });\n // 输入时先尝试 JSON 解析:成功则存解析后的值(数字/布尔/对象/数组等),失败按字符串\n const updateValue = value => {\n if (value === '' || value === undefined || value === null) {\n emit('update:value', '');\n return;\n }\n try {\n emit('update:value', JSON.parse(value));\n } catch (e) {\n emit('update:value', value);\n }\n };\n return { displayValue, valueType, updateValue };\n },\n});\n</script>\n\n<style scoped lang=\"less\">\n.json-type {\n color: #1890ff;\n}\n</style>\n","<template>\n <a-cascader\n v-if=\"source_type && source_type !== 'fixed'\"\n :value=\"value\"\n :field-names=\"{ label: 'label', value: 'key', children: 'children' }\"\n :options=\"options\"\n placeholder=\"请选择字段\"\n @change=\"handleSelectChange\"\n @clear=\"handleSelectChange(null)\"\n :default-value=\"[]\"\n :style=\"style\"\n size=\"small\"\n />\n <JsonInput\n v-else-if=\"paramsCount === 1\"\n :value=\"value?.[0]\"\n @update:value=\"handleSingleChange\"\n :style=\"style\"\n size=\"small\"\n placeholder=\"输入值\"\n />\n <div\n v-else-if=\"paramsCount === 2\"\n class=\"between-inputs\"\n :style=\"style\"\n >\n <JsonInput\n :value=\"value?.[0]\"\n @update:value=\"v => handleBetweenChange(0, v)\"\n :style=\"halfStyle\"\n size=\"small\"\n placeholder=\"起始值\"\n />\n <span class=\"between-separator\">~</span>\n <JsonInput\n :value=\"value?.[1]\"\n @update:value=\"v => handleBetweenChange(1, v)\"\n :style=\"halfStyle\"\n size=\"small\"\n placeholder=\"结束值\"\n />\n </div>\n <JsonTags\n v-else\n :value=\"value || []\"\n @update:value=\"handleInputChange\"\n :style=\"style\"\n size=\"small\"\n placeholder=\"输入值\"\n ></JsonTags>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, PropType, watch } from 'vue';\nimport { DataStoreFieldType } from '../../typing';\nimport { globalOptions, getParamsCount } from '../../utils';\nimport JsonTags from './JsonTags.vue';\nimport JsonInput from './JsonInput.vue';\nexport default defineComponent({\n name: 'ConditionFieldMulType',\n components: { JsonTags, JsonInput },\n props: {\n value: {\n type: Array as PropType<string[]>,\n default: () => [],\n },\n batch_form_key_path: {\n type: Array as PropType<string[]>,\n default: [],\n },\n source_type: {\n type: String as PropType<DataStoreFieldType | null>,\n default: null,\n },\n operator: {\n type: String as PropType<string | null>,\n default: null,\n },\n formData: {\n type: Object,\n default: () => ({}),\n },\n style: {\n type: Object,\n default: () => ({}),\n },\n },\n emits: ['update:value'],\n\n setup(props, { emit }) {\n // 根据运算符获取取值个数:1 -> 单个输入框;2 -> 两个输入框用~分隔;0 -> 不限制个数(沿用 JsonTags)\n const paramsCount = computed(() => getParamsCount(props.operator) ?? 0);\n // 区间模式下每个输入框均分宽度\n const halfStyle = computed(() => {\n const { width, ...rest } = props.style || {};\n return { ...rest, flex: 1, minWidth: 0 };\n });\n // 单个值:包装成数组\n const handleSingleChange = value => {\n if (value === '' || value === undefined || value === null) {\n emit('update:value', []);\n return;\n }\n emit('update:value', [value]);\n };\n // 区间值:两个元素,缺省一侧为 null,两侧都为空则清空\n const handleBetweenChange = (index, value) => {\n const current = Array.isArray(props.value) ? props.value : [];\n const arr = [current[0], current[1]];\n const normalized = value === '' || value === undefined || value === null ? null : value;\n arr[index] = normalized;\n if (arr[0] === null && arr[1] === null) {\n emit('update:value', []);\n } else {\n emit('update:value', arr);\n }\n };\n const handleSelectChange = value => {\n if (value?.length > 0) {\n emit('update:value', value);\n } else {\n emit('update:value', null);\n }\n };\n const handleInputChange = value => {\n emit('update:value', value);\n };\n const getFieldLevel = (groups: any[], batch_key_path: string[]) => {\n if (!groups) {\n return [];\n }\n let groupIndex = 0;\n const res = [];\n for (const group of groups) {\n groupIndex += 1;\n\n const newGroup = {\n key: group.key,\n label: group.group_name || '分组' + groupIndex,\n children: [],\n };\n let groupLevelBatchKeyPath = null;\n if (batch_key_path[0] === group.key) {\n groupLevelBatchKeyPath = batch_key_path.slice(1);\n }\n\n for (const field of group.children) {\n if (!field.key) {\n continue;\n }\n const newField: any = {\n key: field.key,\n label: field.label,\n };\n if (field.type === 'remotetablepro') {\n if (groupLevelBatchKeyPath && groupLevelBatchKeyPath[0] === field.key) {\n const children = getFieldLevel(field.children, groupLevelBatchKeyPath.slice(1));\n if (children.length > 0) {\n newField.children = children;\n newGroup.children.push(newField);\n }\n }\n } else if (field.type === 'formtemplate') {\n if (groupLevelBatchKeyPath && groupLevelBatchKeyPath[0] === field.key) {\n const children = getFieldLevel(\n field.form?.dynamicFieldList,\n groupLevelBatchKeyPath.slice(1),\n );\n if (children.length > 0) {\n newField.children = children;\n newGroup.children.push(newField);\n }\n }\n } else {\n newGroup.children.push(newField);\n }\n }\n if (newGroup.children.length > 0) {\n res.push(newGroup);\n }\n }\n return res;\n };\n const options = computed(() => {\n if (props.source_type === 'global') {\n return globalOptions;\n } else if (props.source_type === 'form') {\n const dynamicFieldList = props.formData?.dynamicFieldList || [];\n return getFieldLevel(dynamicFieldList, props.batch_form_key_path || []);\n }\n });\n\n return {\n handleSelectChange,\n options,\n handleInputChange,\n paramsCount,\n halfStyle,\n handleSingleChange,\n handleBetweenChange,\n };\n },\n});\n</script>\n<style scoped lang=\"less\">\n.between-inputs {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.between-separator {\n color: #999;\n flex-shrink: 0;\n}\n</style>\n","<template>\n <a-cascader\n v-if=\"source_type && source_type !== 'fixed'\"\n :value=\"value\"\n :field-names=\"{ label: 'label', value: 'key', children: 'children' }\"\n :options=\"options\"\n placeholder=\"请选择字段\"\n @change=\"handleSelectChange\"\n @clear=\"handleSelectChange(null)\"\n :default-value=\"[]\"\n :style=\"style\"\n size=\"small\"\n />\n <JsonInput\n v-else-if=\"paramsCount === 1\"\n :value=\"value?.[0]\"\n @update:value=\"handleSingleChange\"\n :style=\"style\"\n size=\"small\"\n placeholder=\"输入值\"\n />\n <div\n v-else-if=\"paramsCount === 2\"\n class=\"between-inputs\"\n :style=\"style\"\n >\n <JsonInput\n :value=\"value?.[0]\"\n @update:value=\"v => handleBetweenChange(0, v)\"\n :style=\"halfStyle\"\n size=\"small\"\n placeholder=\"起始值\"\n />\n <span class=\"between-separator\">~</span>\n <JsonInput\n :value=\"value?.[1]\"\n @update:value=\"v => handleBetweenChange(1, v)\"\n :style=\"halfStyle\"\n size=\"small\"\n placeholder=\"结束值\"\n />\n </div>\n <JsonTags\n v-else\n :value=\"value || []\"\n @update:value=\"handleInputChange\"\n :style=\"style\"\n size=\"small\"\n placeholder=\"输入值\"\n ></JsonTags>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, PropType, watch } from 'vue';\nimport { DataStoreFieldType } from '../../typing';\nimport { globalOptions, getParamsCount } from '../../utils';\nimport JsonTags from './JsonTags.vue';\nimport JsonInput from './JsonInput.vue';\nexport default defineComponent({\n name: 'ConditionFieldMulType',\n components: { JsonTags, JsonInput },\n props: {\n value: {\n type: Array as PropType<string[]>,\n default: () => [],\n },\n batch_form_key_path: {\n type: Array as PropType<string[]>,\n default: [],\n },\n source_type: {\n type: String as PropType<DataStoreFieldType | null>,\n default: null,\n },\n operator: {\n type: String as PropType<string | null>,\n default: null,\n },\n formData: {\n type: Object,\n default: () => ({}),\n },\n style: {\n type: Object,\n default: () => ({}),\n },\n },\n emits: ['update:value'],\n\n setup(props, { emit }) {\n // 根据运算符获取取值个数:1 -> 单个输入框;2 -> 两个输入框用~分隔;0 -> 不限制个数(沿用 JsonTags)\n const paramsCount = computed(() => getParamsCount(props.operator) ?? 0);\n // 区间模式下每个输入框均分宽度\n const halfStyle = computed(() => {\n const { width, ...rest } = props.style || {};\n return { ...rest, flex: 1, minWidth: 0 };\n });\n // 单个值:包装成数组\n const handleSingleChange = value => {\n if (value === '' || value === undefined || value === null) {\n emit('update:value', []);\n return;\n }\n emit('update:value', [value]);\n };\n // 区间值:两个元素,缺省一侧为 null,两侧都为空则清空\n const handleBetweenChange = (index, value) => {\n const current = Array.isArray(props.value) ? props.value : [];\n const arr = [current[0], current[1]];\n const normalized = value === '' || value === undefined || value === null ? null : value;\n arr[index] = normalized;\n if (arr[0] === null && arr[1] === null) {\n emit('update:value', []);\n } else {\n emit('update:value', arr);\n }\n };\n const handleSelectChange = value => {\n if (value?.length > 0) {\n emit('update:value', value);\n } else {\n emit('update:value', null);\n }\n };\n const handleInputChange = value => {\n emit('update:value', value);\n };\n const getFieldLevel = (groups: any[], batch_key_path: string[]) => {\n if (!groups) {\n return [];\n }\n let groupIndex = 0;\n const res = [];\n for (const group of groups) {\n groupIndex += 1;\n\n const newGroup = {\n key: group.key,\n label: group.group_name || '分组' + groupIndex,\n children: [],\n };\n let groupLevelBatchKeyPath = null;\n if (batch_key_path[0] === group.key) {\n groupLevelBatchKeyPath = batch_key_path.slice(1);\n }\n\n for (const field of group.children) {\n if (!field.key) {\n continue;\n }\n const newField: any = {\n key: field.key,\n label: field.label,\n };\n if (field.type === 'remotetablepro') {\n if (groupLevelBatchKeyPath && groupLevelBatchKeyPath[0] === field.key) {\n const children = getFieldLevel(field.children, groupLevelBatchKeyPath.slice(1));\n if (children.length > 0) {\n newField.children = children;\n newGroup.children.push(newField);\n }\n }\n } else if (field.type === 'formtemplate') {\n if (groupLevelBatchKeyPath && groupLevelBatchKeyPath[0] === field.key) {\n const children = getFieldLevel(\n field.form?.dynamicFieldList,\n groupLevelBatchKeyPath.slice(1),\n );\n if (children.length > 0) {\n newField.children = children;\n newGroup.children.push(newField);\n }\n }\n } else {\n newGroup.children.push(newField);\n }\n }\n if (newGroup.children.length > 0) {\n res.push(newGroup);\n }\n }\n return res;\n };\n const options = computed(() => {\n if (props.source_type === 'global') {\n return globalOptions;\n } else if (props.source_type === 'form') {\n const dynamicFieldList = props.formData?.dynamicFieldList || [];\n return getFieldLevel(dynamicFieldList, props.batch_form_key_path || []);\n }\n });\n\n return {\n handleSelectChange,\n options,\n handleInputChange,\n paramsCount,\n halfStyle,\n handleSingleChange,\n handleBetweenChange,\n };\n },\n});\n</script>\n<style scoped lang=\"less\">\n.between-inputs {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.between-separator {\n color: #999;\n flex-shrink: 0;\n}\n</style>\n","<template>\n <div>\n <div\n v-for=\"(group, groupIndex) in dataSource\"\n :key=\"groupIndex\"\n class=\"condition-group\"\n >\n <div class=\"group-header\">\n <span class=\"group-title\">条件组 {{ groupIndex + 1 }}</span>\n <a-button\n type=\"link\"\n danger\n size=\"small\"\n @click=\"removeGroup(groupIndex)\"\n >\n 删除条件组\n </a-button>\n </div>\n <div\n v-for=\"(condition, index) in group\"\n :key=\"index\"\n class=\"condition-item\"\n >\n <div class=\"item-index\">({{ index + 1 }})</div>\n <div class=\"config-body\">\n <a-form layout=\"vertical\">\n <a-row :gutter=\"16\">\n <a-col :span=\"8\">\n <a-form-item label=\"字段\">\n <column-name-field\n v-model:value=\"condition.field_name\"\n :columnNameList=\"columnNameList\"\n />\n </a-form-item>\n </a-col>\n <a-col :span=\"8\">\n <a-form-item label=\"运算符\">\n <a-select\n show-search\n v-model:value=\"condition.operator\"\n placeholder=\"请选择运算符\"\n :options=\"operatorOptions\"\n ></a-select>\n </a-form-item>\n </a-col>\n <a-col :span=\"8\">\n <a-form-item label=\"数据类型\">\n <a-select\n show-search\n v-model:value=\"condition.class_name\"\n placeholder=\"请选择数据类型\"\n >\n <a-select-option value=\"int\">整数(int)</a-select-option>\n <a-select-option value=\"float\">浮点数(float)</a-select-option>\n <a-select-option value=\"str\">字符串(str)</a-select-option>\n <a-select-option value=\"bool\">布尔值(bool)</a-select-option>\n <a-select-option value=\"date\">日期(date)</a-select-option>\n <a-select-option value=\"datetime\">日期时间(datetime)</a-select-option>\n <a-select-option value=\"time\">时间(time)</a-select-option>\n </a-select>\n </a-form-item>\n </a-col>\n </a-row>\n <a-form-item label=\"比较值\">\n <div class=\"condition-value\">\n <div class=\"condition-value-type\">\n <a-select\n v-model:value=\"condition.value_type\"\n placeholder=\"请选择\"\n style=\"width: 100px\"\n size=\"small\"\n >\n <a-select-option value=\"global\">全局字段</a-select-option>\n <a-select-option value=\"fixed\">固定值</a-select-option>\n </a-select>\n </div>\n <div class=\"condition-value-input\">\n <ConditionFieldMulType\n v-model:value=\"condition.value\"\n :source_type=\"condition.value_type\"\n :operator=\"condition.operator\"\n :form-data=\"formData\"\n style=\"width: 480px\"\n />\n </div>\n </div>\n </a-form-item>\n </a-form>\n </div>\n <div class=\"config-actions\">\n <delete-outlined\n @click=\"removeCondition(groupIndex, index)\"\n class=\"delete-icon\"\n />\n </div>\n </div>\n <a-button\n type=\"link\"\n @click=\"addCondition(groupIndex)\"\n >\n 添加条件\n </a-button>\n <div\n v-if=\"groupIndex < dataSource.length - 1\"\n class=\"group-or\"\n >\n <span>或</span>\n </div>\n </div>\n <a-button\n type=\"dashed\"\n block\n @click=\"addGroup\"\n >\n <plus-outlined />\n 添加条件组(组与组之间为“或”关系,组内条件为“与”关系)\n </a-button>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, onMounted, PropType, ref, watch } from 'vue';\nimport { Condition } from '../../typing';\nimport { getColumnNameList } from '../../utils';\nimport { useConditionOperatorMap } from '@/init-plugin';\nimport JsonTags from './JsonTags.vue';\nimport formFieldMulType from '../dataStoreConfig/formFieldMulType.vue';\nimport ConditionFieldMulType from './ConditionFieldMulType.vue';\nimport { PlusOutlined } from '@ant-design/icons-vue';\n\nexport default defineComponent({\n name: 'BasicQueryConditions',\n components: {\n JsonTags,\n ConditionFieldMulType,\n PlusOutlined,\n },\n props: {\n dataSource: {\n type: Object as PropType<Array<Condition> | Array<Condition[]>>,\n required: true,\n },\n modelType: {\n type: String,\n required: true,\n },\n formData: {\n type: Object,\n default: () => ({}),\n },\n },\n emits: ['update:dataSource'],\n setup(props, { emit }) {\n const ConditionOperatorMap = useConditionOperatorMap();\n const columnNameList = ref([]);\n const createCondition = (): Condition => {\n return {\n field_name: '',\n operator: undefined,\n class_name: undefined,\n value_type: 'fixed',\n value: [],\n format: 'input',\n } as any;\n };\n // 兼容旧格式:一层条件数组 -> 包成单个条件组(组内 and)\n const normalizeToGroups = (data: any): any => {\n if (!Array.isArray(data) || data.length === 0) {\n return data;\n }\n if (!Array.isArray(data[0])) {\n return [data];\n }\n return data;\n };\n const addGroup = () => {\n const data = normalizeToGroups(props.dataSource) || [];\n emit('update:dataSource', [...data, [createCondition()]]);\n };\n const removeGroup = (groupIndex: number) => {\n props.dataSource.splice(groupIndex, 1);\n };\n const addCondition = (groupIndex: number) => {\n const group = props.dataSource?.[groupIndex];\n if (group) {\n group.push(createCondition());\n }\n };\n const removeCondition = (groupIndex: number, index: number) => {\n props.dataSource?.[groupIndex]?.splice(index, 1);\n };\n const operatorOptions = Object.entries(ConditionOperatorMap).map(([key, value]) => ({\n label: `${value} (${key})`,\n value: key,\n }));\n\n watch(\n () => props.modelType,\n async newValue => {\n columnNameList.value = await getColumnNameList(newValue);\n },\n { immediate: true },\n );\n onMounted(() => {\n if (props.dataSource?.length > 0) {\n // 兼容旧格式:一层条件数组 -> 包成单个条件组\n if (!Array.isArray(props.dataSource[0])) {\n const flat = [...props.dataSource];\n props.dataSource.splice(0, props.dataSource.length, flat);\n }\n for (const group of props.dataSource) {\n for (const item of group) {\n if (!item.value_type) {\n item.value_type = 'fixed';\n }\n }\n }\n }\n });\n\n return {\n addGroup,\n removeGroup,\n addCondition,\n removeCondition,\n columnNameList,\n operatorOptions,\n };\n },\n});\n</script>\n\n<style scoped lang=\"less\">\n.condition-group {\n border: 1px solid #f0f0f0;\n border-radius: 4px;\n padding: 12px;\n margin-bottom: 12px;\n}\n\n.group-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.group-title {\n font-weight: 600;\n}\n\n.group-or {\n display: flex;\n align-items: center;\n justify-content: center;\n color: #999;\n margin: 12px 0;\n\n &::before,\n &::after {\n content: '';\n flex: 1;\n height: 1px;\n background: #f0f0f0;\n margin: 0 12px;\n }\n}\n\n.condition-item {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 10px;\n border-bottom: 1px solid #f0f0f0;\n padding-bottom: 16px;\n margin-bottom: 16px;\n\n &:last-child {\n border-bottom: none;\n margin-bottom: 0;\n }\n}\n\n.config-body {\n flex: 1;\n}\n\n.delete-icon {\n font-size: 18px;\n color: #ff4d4f;\n cursor: pointer;\n}\n.condition-value {\n display: flex;\n gap: 8px;\n}\n</style>\n","<template>\n <div>\n <div\n v-for=\"(group, groupIndex) in dataSource\"\n :key=\"groupIndex\"\n class=\"condition-group\"\n >\n <div class=\"group-header\">\n <span class=\"group-title\">条件组 {{ groupIndex + 1 }}</span>\n <a-button\n type=\"link\"\n danger\n size=\"small\"\n @click=\"removeGroup(groupIndex)\"\n >\n 删除条件组\n </a-button>\n </div>\n <div\n v-for=\"(condition, index) in group\"\n :key=\"index\"\n class=\"condition-item\"\n >\n <div class=\"item-index\">({{ index + 1 }})</div>\n <div class=\"config-body\">\n <a-form layout=\"vertical\">\n <a-row :gutter=\"16\">\n <a-col :span=\"8\">\n <a-form-item label=\"字段\">\n <column-name-field\n v-model:value=\"condition.field_name\"\n :columnNameList=\"columnNameList\"\n />\n </a-form-item>\n </a-col>\n <a-col :span=\"8\">\n <a-form-item label=\"运算符\">\n <a-select\n show-search\n v-model:value=\"condition.operator\"\n placeholder=\"请选择运算符\"\n :options=\"operatorOptions\"\n ></a-select>\n </a-form-item>\n </a-col>\n <a-col :span=\"8\">\n <a-form-item label=\"数据类型\">\n <a-select\n show-search\n v-model:value=\"condition.class_name\"\n placeholder=\"请选择数据类型\"\n >\n <a-select-option value=\"int\">整数(int)</a-select-option>\n <a-select-option value=\"float\">浮点数(float)</a-select-option>\n <a-select-option value=\"str\">字符串(str)</a-select-option>\n <a-select-option value=\"bool\">布尔值(bool)</a-select-option>\n <a-select-option value=\"date\">日期(date)</a-select-option>\n <a-select-option value=\"datetime\">日期时间(datetime)</a-select-option>\n <a-select-option value=\"time\">时间(time)</a-select-option>\n </a-select>\n </a-form-item>\n </a-col>\n </a-row>\n <a-form-item label=\"比较值\">\n <div class=\"condition-value\">\n <div class=\"condition-value-type\">\n <a-select\n v-model:value=\"condition.value_type\"\n placeholder=\"请选择\"\n style=\"width: 100px\"\n size=\"small\"\n >\n <a-select-option value=\"global\">全局字段</a-select-option>\n <a-select-option value=\"fixed\">固定值</a-select-option>\n </a-select>\n </div>\n <div class=\"condition-value-input\">\n <ConditionFieldMulType\n v-model:value=\"condition.value\"\n :source_type=\"condition.value_type\"\n :operator=\"condition.operator\"\n :form-data=\"formData\"\n style=\"width: 480px\"\n />\n </div>\n </div>\n </a-form-item>\n </a-form>\n </div>\n <div class=\"config-actions\">\n <delete-outlined\n @click=\"removeCondition(groupIndex, index)\"\n class=\"delete-icon\"\n />\n </div>\n </div>\n <a-button\n type=\"link\"\n @click=\"addCondition(groupIndex)\"\n >\n 添加条件\n </a-button>\n <div\n v-if=\"groupIndex < dataSource.length - 1\"\n class=\"group-or\"\n >\n <span>或</span>\n </div>\n </div>\n <a-button\n type=\"dashed\"\n block\n @click=\"addGroup\"\n >\n <plus-outlined />\n 添加条件组(组与组之间为“或”关系,组内条件为“与”关系)\n </a-button>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, onMounted, PropType, ref, watch } from 'vue';\nimport { Condition } from '../../typing';\nimport { getColumnNameList } from '../../utils';\nimport { useConditionOperatorMap } from '@/init-plugin';\nimport JsonTags from './JsonTags.vue';\nimport formFieldMulType from '../dataStoreConfig/formFieldMulType.vue';\nimport ConditionFieldMulType from './ConditionFieldMulType.vue';\nimport { PlusOutlined } from '@ant-design/icons-vue';\n\nexport default defineComponent({\n name: 'BasicQueryConditions',\n components: {\n JsonTags,\n ConditionFieldMulType,\n PlusOutlined,\n },\n props: {\n dataSource: {\n type: Object as PropType<Array<Condition> | Array<Condition[]>>,\n required: true,\n },\n modelType: {\n type: String,\n required: true,\n },\n formData: {\n type: Object,\n default: () => ({}),\n },\n },\n emits: ['update:dataSource'],\n setup(props, { emit }) {\n const ConditionOperatorMap = useConditionOperatorMap();\n const columnNameList = ref([]);\n const createCondition = (): Condition => {\n return {\n field_name: '',\n operator: undefined,\n class_name: undefined,\n value_type: 'fixed',\n value: [],\n format: 'input',\n } as any;\n };\n // 兼容旧格式:一层条件数组 -> 包成单个条件组(组内 and)\n const normalizeToGroups = (data: any): any => {\n if (!Array.isArray(data) || data.length === 0) {\n return data;\n }\n if (!Array.isArray(data[0])) {\n return [data];\n }\n return data;\n };\n const addGroup = () => {\n const data = normalizeToGroups(props.dataSource) || [];\n emit('update:dataSource', [...data, [createCondition()]]);\n };\n const removeGroup = (groupIndex: number) => {\n props.dataSource.splice(groupIndex, 1);\n };\n const addCondition = (groupIndex: number) => {\n const group = props.dataSource?.[groupIndex];\n if (group) {\n group.push(createCondition());\n }\n };\n const removeCondition = (groupIndex: number, index: number) => {\n props.dataSource?.[groupIndex]?.splice(index, 1);\n };\n const operatorOptions = Object.entries(ConditionOperatorMap).map(([key, value]) => ({\n label: `${value} (${key})`,\n value: key,\n }));\n\n watch(\n () => props.modelType,\n async newValue => {\n columnNameList.value = await getColumnNameList(newValue);\n },\n { immediate: true },\n );\n onMounted(() => {\n if (props.dataSource?.length > 0) {\n // 兼容旧格式:一层条件数组 -> 包成单个条件组\n if (!Array.isArray(props.dataSource[0])) {\n const flat = [...props.dataSource];\n props.dataSource.splice(0, props.dataSource.length, flat);\n }\n for (const group of props.dataSource) {\n for (const item of group) {\n if (!item.value_type) {\n item.value_type = 'fixed';\n }\n }\n }\n }\n });\n\n return {\n addGroup,\n removeGroup,\n addCondition,\n removeCondition,\n columnNameList,\n operatorOptions,\n };\n },\n});\n</script>\n\n<style scoped lang=\"less\">\n.condition-group {\n border: 1px solid #f0f0f0;\n border-radius: 4px;\n padding: 12px;\n margin-bottom: 12px;\n}\n\n.group-header {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.group-title {\n font-weight: 600;\n}\n\n.group-or {\n display: flex;\n align-items: center;\n justify-content: center;\n color: #999;\n margin: 12px 0;\n\n &::before,\n &::after {\n content: '';\n flex: 1;\n height: 1px;\n background: #f0f0f0;\n margin: 0 12px;\n }\n}\n\n.condition-item {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 10px;\n border-bottom: 1px solid #f0f0f0;\n padding-bottom: 16px;\n margin-bottom: 16px;\n\n &:last-child {\n border-bottom: none;\n margin-bottom: 0;\n }\n}\n\n.config-body {\n flex: 1;\n}\n\n.delete-icon {\n font-size: 18px;\n color: #ff4d4f;\n cursor: pointer;\n}\n.condition-value {\n display: flex;\n gap: 8px;\n}\n</style>\n","<template>\n <div class=\"editable-cell\">\n <div\n v-if=\"onEdit\"\n class=\"editable-cell-input-wrapper\"\n >\n <a-input\n v-model:value=\"tmpValue\"\n :size=\"'small'\"\n @pressEnter=\"save()\"\n @keyup.esc=\"cancel()\"\n />\n <check-outlined\n class=\"editable-cell-icon-check\"\n @click=\"save()\"\n />\n </div>\n <div\n v-else\n class=\"editable-cell-text-wrapper\"\n >\n {{ value || ' ' }}\n <edit-outlined\n class=\"editable-cell-icon\"\n @click=\"edit()\"\n />\n </div>\n </div>\n</template>\n<script lang=\"ts\">\nimport { defineComponent, nextTick, ref } from 'vue';\n\nexport default defineComponent({\n name: 'BaseColumns',\n props: {\n value: {\n type: String,\n default: () => {},\n },\n },\n components: {},\n emits: ['update:value', 'change'],\n setup(props, { emit }) {\n const onEdit = ref(false);\n const tmpValue = ref(props.value);\n const edit = () => {\n tmpValue.value = props.value;\n onEdit.value = true;\n };\n const save = () => {\n emit('update:value', tmpValue.value);\n onEdit.value = false;\n nextTick(() => {\n emit('change', tmpValue.value);\n });\n };\n const cancel = () => {\n onEdit.value = false;\n };\n\n return {\n onEdit,\n tmpValue,\n edit,\n save,\n cancel,\n };\n },\n});\n</script>\n\n<style lang=\"less\" scoped>\n.editable-cell {\n border: solid 1px transparent;\n position: relative;\n\n .editable-cell-input-wrapper {\n padding-right: 24px;\n }\n\n .editable-cell-text-wrapper {\n padding: 5px 24px 5px 5px;\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .editable-cell-icon,\n .editable-cell-icon-check {\n position: absolute;\n right: 0;\n width: 20px;\n cursor: pointer;\n }\n\n .editable-cell-icon {\n margin-top: 4px;\n //display: inline-block;\n display: none;\n }\n\n .editable-cell-icon-check {\n margin-top: 8px;\n }\n\n .editable-cell-icon:hover,\n .editable-cell-icon-check:hover {\n color: #108ee9;\n }\n\n .editable-add-btn {\n margin-bottom: 8px;\n }\n}\n\n.editable-cell:hover .editable-cell-icon {\n display: inline-block;\n}\n</style>\n","<template>\n <div class=\"editable-cell\">\n <div\n v-if=\"onEdit\"\n class=\"editable-cell-input-wrapper\"\n >\n <a-input\n v-model:value=\"tmpValue\"\n :size=\"'small'\"\n @pressEnter=\"save()\"\n @keyup.esc=\"cancel()\"\n />\n <check-outlined\n class=\"editable-cell-icon-check\"\n @click=\"save()\"\n />\n </div>\n <div\n v-else\n class=\"editable-cell-text-wrapper\"\n >\n {{ value || ' ' }}\n <edit-outlined\n class=\"editable-cell-icon\"\n @click=\"edit()\"\n />\n </div>\n </div>\n</template>\n<script lang=\"ts\">\nimport { defineComponent, nextTick, ref } from 'vue';\n\nexport default defineComponent({\n name: 'BaseColumns',\n props: {\n value: {\n type: String,\n default: () => {},\n },\n },\n components: {},\n emits: ['update:value', 'change'],\n setup(props, { emit }) {\n const onEdit = ref(false);\n const tmpValue = ref(props.value);\n const edit = () => {\n tmpValue.value = props.value;\n onEdit.value = true;\n };\n const save = () => {\n emit('update:value', tmpValue.value);\n onEdit.value = false;\n nextTick(() => {\n emit('change', tmpValue.value);\n });\n };\n const cancel = () => {\n onEdit.value = false;\n };\n\n return {\n onEdit,\n tmpValue,\n edit,\n save,\n cancel,\n };\n },\n});\n</script>\n\n<style lang=\"less\" scoped>\n.editable-cell {\n border: solid 1px transparent;\n position: relative;\n\n .editable-cell-input-wrapper {\n padding-right: 24px;\n }\n\n .editable-cell-text-wrapper {\n padding: 5px 24px 5px 5px;\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .editable-cell-icon,\n .editable-cell-icon-check {\n position: absolute;\n right: 0;\n width: 20px;\n cursor: pointer;\n }\n\n .editable-cell-icon {\n margin-top: 4px;\n //display: inline-block;\n display: none;\n }\n\n .editable-cell-icon-check {\n margin-top: 8px;\n }\n\n .editable-cell-icon:hover,\n .editable-cell-icon-check:hover {\n color: #108ee9;\n }\n\n .editable-add-btn {\n margin-bottom: 8px;\n }\n}\n\n.editable-cell:hover .editable-cell-icon {\n display: inline-block;\n}\n</style>\n","<template>\n <a-layout class=\"antTabs\">\n <a-layout-sider\n width=\"100%\"\n :style=\"{ backgroundColor: 'white', overflowY: 'auto', height: height + 'px' }\"\n >\n <a-row style=\"height: 100%\">\n <a-col :span=\"6\">\n <div class=\"column-title-container\">\n <div class=\"column-title\">{{ $t('可选列') }}</div>\n </div>\n <s-table\n v-model:selectedRowKeys=\"selectedRowKeys\"\n :autoRowHeight=\"true\"\n :bordered=\"true\"\n :columns=\"columns\"\n :customCell=\"customCell\"\n :data-source=\"allColumnsData\"\n :scroll=\"{ y: height - 90 }\"\n :indentSize=\"0\"\n :pagination=\"false\"\n :row-selection=\"rowSelection\"\n :rowHeight=\"30\"\n :rowKey=\"'name'\"\n :size=\"'small'\"\n :wrapText=\"true\"\n sticky\n stripe\n summary-fixed\n >\n <template #bodyCell=\"{ column, index, text, record }\">\n <span>{{ text }}</span>\n </template>\n <template #contextmenuPopup=\"args\">\n <a-space-compact direction=\"vertical\">\n <a-button\n block\n size=\"small\"\n type=\"text\"\n @click=\"copyClick(args, 'cell')\"\n >\n <template #icon>\n <copy-outlined />\n </template>\n {{ $t('复制') }}\n </a-button>\n </a-space-compact>\n </template>\n </s-table>\n </a-col>\n <a-col :span=\"1\">\n <div\n :style=\"{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: height + 'px',\n }\"\n >\n <div style=\"width: 30px\">\n <left-square-outlined\n v-if=\"baseSelectKeys.length === 0\"\n style=\"color: #999999; font-size: 25px\"\n />\n <left-square-two-tone\n v-if=\"baseSelectKeys.length > 0\"\n style=\"font-size: 25px\"\n @click=\"goLeft\"\n />\n <right-square-outlined\n v-if=\"selectedRowKeys.length === 0\"\n style=\"color: #999999; font-size: 25px\"\n />\n <right-square-two-tone\n v-if=\"selectedRowKeys.length > 0\"\n style=\"font-size: 25px\"\n @click=\"goRight\"\n />\n </div>\n </div>\n </a-col>\n <a-col\n :span=\"17\"\n class=\"base-column-content\"\n >\n <div class=\"column-title-container\">\n <div class=\"column-title\">{{ $t('列设置') }}</div>\n <!-- <a-alert\n type=\"warning\"\n v-if=\"Object.keys(changedFields).length > 0\"\n >\n <template #description>\n 共有\n <span style=\"color: red\">{{ Object.keys(changedFields).length }}</span>\n 个字段配置有变更\n <a-button\n type=\"link\"\n @click=\"updateAllBaseColumn\"\n >\n 全部更新\n </a-button>\n </template>\n </a-alert> -->\n </div>\n <div class=\"base-column-table\">\n <s-table\n :bordered=\"true\"\n :columns=\"baseColumns\"\n :rowHeight=\"30\"\n :data-source=\"baseColumnList\"\n :row-selection=\"baseRowSelection\"\n v-model:selectedRowKeys=\"baseSelectKeys\"\n expand-row-by-click\n @row-drag-end=\"onRowDragEnd\"\n :row-key=\"'dataIndex'\"\n :pagination=\"false\"\n :size=\"'small'\"\n :scroll=\"{ y: height - 100, x: '100%' }\"\n >\n <template #bodyCell=\"{ column, index, text, record, recordIndexs }\">\n <template v-if=\"column.dataIndex === 'title'\">\n <cell-edit\n v-model:value=\"getRawRecord(baseColumnList, recordIndexs).title\"\n @change=\"emitData\"\n ></cell-edit>\n </template>\n <template v-if=\"column.dataIndex === 'dataIndex'\">\n {{ text }}\n <WarningOutlined\n title=\"列参数不存在\"\n v-if=\"fieldMap && !fieldMap[text]\"\n style=\"color: #faad14\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'defaultSort'\">\n <a-row\n :gutter=\"8\"\n v-if=\"record.sorter\"\n >\n <a-col :span=\"12\">\n <a-select\n v-model:value=\"record.defaultSortOrder\"\n @change=\"changeBaseColumnList\"\n style=\"width: 100%\"\n size=\"small\"\n allowClear\n >\n <a-select-option\n key=\"ascend\"\n value=\"ascend\"\n >\n {{ $t('升序') }}\n </a-select-option>\n <a-select-option\n key=\"descend\"\n value=\"descend\"\n >\n {{ $t('降序') }}\n </a-select-option>\n </a-select>\n </a-col>\n <a-col :span=\"12\">\n <a-input-number\n v-if=\"record.defaultSortOrder\"\n size=\"small\"\n v-model:value=\"record.defaultSortIndex\"\n :precision=\"0\"\n @click=\"changeBaseColumnList\"\n placeholder=\"序号\"\n style=\"width: 100%\"\n :min=\"1\"\n ></a-input-number>\n </a-col>\n </a-row>\n <div\n v-else\n class=\"default-sort-tip\"\n >\n 不支持排序\n </div>\n </template>\n <template v-if=\"column.dataIndex === 'fixed'\">\n <a-radio-group\n v-if=\"!record?.is_children\"\n v-model:value=\"record.fixed\"\n size=\"small\"\n @click=\"changeBaseColumnList\"\n >\n <a-radio-button value=\"left\">{{ '左' }}</a-radio-button>\n <a-radio-button :value=\"undefined\">{{ '不固定' }}</a-radio-button>\n <a-radio-button value=\"right\">{{ '右' }}</a-radio-button>\n </a-radio-group>\n </template>\n <template v-if=\"column.dataIndex === 'autoHeight'\">\n <a-switch\n v-if=\"!(record.children && record.children.length > 0)\"\n v-model:checked=\"record.autoHeight\"\n :checked-value=\"true\"\n :un-checked-value=\"false\"\n :checked-children=\"'自动'\"\n :un-checked-children=\"'固定'\"\n @click=\"changeBaseColumnList\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'autoWidth'\">\n <a-switch\n v-if=\"!(record.children && record.children.length > 0) && record?.resizable\"\n v-model:checked=\"record.autoWidth\"\n :checked-value=\"true\"\n :un-checked-value=\"false\"\n :checked-children=\"$t('自动')\"\n :un-checked-children=\"$t('固定')\"\n @click=\"changeBaseColumnList\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'approve_summary'\">\n <a-switch\n v-model:checked=\"record.approve_summary\"\n :checked-value=\"true\"\n :un-checked-value=\"false\"\n @click=\"changeBaseColumnList\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'ellipsis'\">\n <a-switch\n v-if=\"!(record.children && record.children.length > 0) && record?.resizable\"\n v-model:checked=\"record.ellipsis\"\n :checked-value=\"true\"\n :un-checked-value=\"false\"\n :checked-children=\"$t('开启')\"\n :un-checked-children=\"$t('关闭')\"\n @click=\"changeBaseColumnList\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'cellComponent'\">\n <a-select\n v-model:value=\"record.cellComponent\"\n :allow-clear=\"true\"\n :dropdownMatchSelectWidth=\"false\"\n :placeholder=\"$t('请选择')\"\n :show-search=\"true\"\n size=\"small\"\n style=\"width: 180px\"\n @change=\"changeCellComponent(record)\"\n >\n <a-select-option\n v-for=\"option in cellComponentList\"\n :key=\"option.cellComponent\"\n :value=\"option.cellComponent\"\n >\n {{ $t(option.name) + '(' + option.cellComponent + ')' }}\n </a-select-option>\n </a-select>\n </template>\n\n <template v-if=\"column.dataIndex === 'action'\">\n <a-button\n type=\"link\"\n v-if=\"changedFields[record.dataIndex]\"\n @click=\"handleUpdateBaseColumn(getRawRecord(baseColumnList, recordIndexs))\"\n >\n {{ $t('更新') }}\n </a-button>\n </template>\n </template>\n <template #contextmenuPopup=\"args\">\n <a-space-compact direction=\"vertical\">\n <a-button\n block\n size=\"small\"\n type=\"text\"\n @click=\"copyClick(args, 'cell')\"\n >\n <template #icon>\n <copy-outlined />\n </template>\n {{ $t('复制') }}\n </a-button>\n </a-space-compact>\n </template>\n </s-table>\n </div>\n </a-col>\n </a-row>\n </a-layout-sider>\n </a-layout>\n</template>\n<script lang=\"ts\">\nimport {\n CheckOutlined,\n EditOutlined,\n LeftSquareOutlined,\n LeftSquareTwoTone,\n RightSquareOutlined,\n RightSquareTwoTone,\n} from '@ant-design/icons-vue';\nimport { ContextmenuPopupArg } from '@surely-vue/table';\nimport { cellComponentList, getApiData, useUserStore } from '@/init-plugin';\nimport { copyValue, removeNestedDuplicates } from '@/utils/function';\nimport { cloneDeep, debounce, isEqual } from 'lodash';\nimport { defineComponent, onMounted, onUnmounted, reactive, ref } from 'vue';\nimport { useI18n } from 'vue-i18n';\nimport cellEdit from './cellEdit.vue';\n\nexport default defineComponent({\n name: 'BaseColumns',\n props: {\n dataSource: {\n type: Array,\n default: () => {},\n },\n modelType: {\n type: String,\n required: true,\n },\n },\n components: {\n LeftSquareOutlined,\n LeftSquareTwoTone,\n RightSquareOutlined,\n RightSquareTwoTone,\n CheckOutlined,\n EditOutlined,\n cellEdit,\n },\n emits: ['update:dataSource'],\n setup(props, { emit }) {\n const { t } = useI18n();\n const height = ref(0);\n const userStore = useUserStore();\n const current_org = userStore.currentOrg; // 当前组织org\n const selectedRowKeys = ref([]);\n const allColumnsData = ref([]);\n const baseColumnList = ref([]);\n const baseSelectKeys = ref([]);\n const fieldMap = ref({});\n const changedFields = ref({});\n const defaultColumns = [\n {\n title: t('列名称'),\n dataIndex: 'title',\n key: 'title',\n width: 200,\n },\n ];\n const columns = [\n {\n title: t('参数'),\n dataIndex: 'name',\n checked: true,\n width: 200,\n ellipsis: true,\n },\n {\n title: t('名称'),\n dataIndex: 'verbose_name',\n checked: true,\n width: 150,\n ellipsis: true,\n },\n ];\n const baseColumns = [\n {\n title: t('列名称'),\n dataIndex: 'title',\n key: 'title',\n rowDrag: true,\n width: 200,\n fixed: 'left',\n },\n {\n title: t('参数'),\n dataIndex: 'dataIndex',\n width: 200,\n fixed: 'left',\n ellipsis: true,\n },\n {\n title: t('默认排序'),\n dataIndex: 'defaultSort',\n width: 240,\n ellipsis: true,\n },\n {\n title: t('冻结列'),\n dataIndex: 'fixed',\n key: 'fixed',\n width: 150,\n },\n {\n title: '行高',\n dataIndex: 'autoHeight',\n width: 80,\n key: 'autoHeight',\n },\n {\n title: '列宽',\n dataIndex: 'autoWidth',\n width: 80,\n key: 'autoWidth',\n },\n {\n title: '合计',\n dataIndex: 'approve_summary',\n width: 80,\n key: 'approve_summary',\n },\n {\n title: '超宽省略',\n dataIndex: 'ellipsis',\n width: 80,\n key: 'ellipsis',\n },\n {\n title: '列组件',\n dataIndex: 'cellComponent',\n width: 200,\n key: 'cellComponent',\n },\n ];\n const onresize: any = debounce(() => {\n height.value = window.innerHeight - 165;\n }, 200);\n const emitData = () => {\n emit('update:dataSource', baseColumnList.value);\n };\n function markChecked(nodeB, idSetA) {\n nodeB.disabled = false;\n if (nodeB.name != null && idSetA.has(nodeB.name)) {\n nodeB.disabled = true;\n }\n if (nodeB.children && Array.isArray(nodeB.children)) {\n nodeB.children.forEach(childNodeB => {\n markChecked(childNodeB, idSetA);\n });\n }\n }\n const getFieldMap = (dataList: any) => {\n dataList.forEach(item => {\n fieldMap.value[item.name] = item;\n if (Array.isArray(item.children)) {\n getFieldMap(item.children);\n }\n });\n };\n const refreshData = () => {\n const allIdsInA = new Set();\n\n function collectAllIds(nodes) {\n nodes.forEach(node => {\n allIdsInA.add(node.dataIndex);\n if (node.children && Array.isArray(node.children)) {\n collectAllIds(node.children);\n }\n });\n }\n\n collectAllIds(baseColumnList.value);\n allColumnsData.value.forEach(nodeB => {\n markChecked(nodeB, allIdsInA);\n });\n allColumnsData.value = [].concat(allColumnsData.value);\n };\n\n onMounted(async () => {\n window.addEventListener('resize', onresize);\n onresize();\n baseColumnList.value = props.dataSource || [];\n if (props.modelType) {\n const args = props.modelType.split('-');\n const url = `${args[0]}/obtain_${args[1]}_column_data`;\n const res = await getApiData(\n { org_id: current_org?.id, is_base_column: true },\n url,\n false,\n {\n skip_error: true,\n },\n );\n allColumnsData.value = removeNestedDuplicates(res || []);\n getFieldMap(allColumnsData.value);\n }\n refreshChangedFields();\n refreshData();\n emitData();\n });\n onUnmounted(() => {\n window.removeEventListener('resize', onresize);\n });\n\n const customCell = (obj: any) => {\n if (obj.record.disabled) {\n return { style: { background: '#cbcbcb' } };\n }\n };\n const rowSelection = reactive({\n type: 'checkbox',\n onChange: (selectedKeys: string[]) => {\n selectedRowKeys.value = selectedKeys;\n },\n getCheckboxProps: (record: any) => ({\n disabled: record.disabled,\n name: record.name,\n }),\n });\n const baseRowSelection = reactive({\n type: 'checkbox',\n onChange: (selectedKeys: string[]) => {\n baseSelectKeys.value = selectedKeys;\n },\n getCheckboxProps: (record: any) => ({\n disabled: record.dataIndex === 'index' || record.dataIndex === 'action',\n name: record.dataIndex,\n }),\n });\n const getFieldConfig = (field: any, keys: Record<string, string>) => {\n const config: any = {};\n Object.keys(keys).forEach(key => {\n if (field[key] !== undefined) {\n config[keys[key]] = field[key];\n }\n });\n return config;\n };\n const setDisabledGoRight = (data: any) => {\n data.forEach(item => {\n if (selectedRowKeys.value.indexOf(item.name) > -1) {\n let obj: any = {};\n obj = getFieldConfig(item, {\n verbose_name: 'title',\n name: 'dataIndex',\n cell_component: 'cellComponent',\n filterMultiple: 'filterMultiple',\n contentMap: 'contentMap',\n colorMap: 'colorMap',\n filters: 'filters',\n sorter: 'sorter',\n summary: 'approve_summary',\n cellSummaryComponent: 'cellSummaryComponent',\n });\n obj.fixed = undefined;\n obj.autoHeight = false;\n obj.autoWidth = false;\n obj.width = 150;\n obj.resizable = true;\n item.disabled = true;\n if (item.cellComponent) {\n obj.ellipsis = false;\n } else {\n obj.ellipsis = true;\n }\n baseColumnList.value.push(obj);\n }\n // 如果当前节点有 children,则递归调用函数\n if (item.children && Array.isArray(item.children)) {\n setDisabledGoRight(item.children);\n }\n });\n };\n const goRight = () => {\n setDisabledGoRight(allColumnsData.value);\n selectedRowKeys.value.length = 0;\n allColumnsData.value = [].concat(allColumnsData.value);\n baseColumnList.value = [].concat(baseColumnList.value);\n emitData();\n };\n const setDisabledGoLeft = (data: any) => {\n data.forEach(item => {\n if (baseSelectKeys.value.indexOf(item.name) > -1) {\n item.disabled = false;\n }\n // 如果当前节点有 children,则递归调用函数\n if (item.children && Array.isArray(item.children)) {\n setDisabledGoLeft(item.children);\n }\n });\n };\n const goLeft = () => {\n baseColumnList.value = baseColumnList.value.filter((item: any) => {\n return baseSelectKeys.value.indexOf(item.dataIndex) == -1;\n });\n setDisabledGoLeft(allColumnsData.value);\n baseSelectKeys.value.length = 0;\n baseColumnList.value = [].concat(baseColumnList.value);\n allColumnsData.value = [].concat(allColumnsData.value);\n emitData();\n refreshChangedFields();\n };\n // 返回当前节点的父级节点\n const findParent = (data: any[], childKey: any) => {\n let foundParentKey: any;\n const searchParent = (id: any, keys: any[], childKeys: any) => {\n for (const key of keys) {\n if (key.dataIndex === childKeys) {\n foundParentKey = id;\n return foundParentKey;\n } else if (key.children && key.children.length > 0) {\n foundParentKey = searchParent(key.dataIndex, key.children, childKeys);\n if (foundParentKey !== undefined) return foundParentKey; // 如果找到,立即返回\n }\n }\n return undefined; // 如果没有找到\n };\n return searchParent(null, data, childKey);\n };\n const onRowDragEnd = ({ record, preTargetInfo, nextTargetInfo }) => {\n return new Promise((reslove, reject) => {\n if (preTargetInfo) {\n // 拖拽后上方的节点\n const parentID1 = findParent(baseColumnList.value, record.dataIndex); // 拖拽节点的父级节点\n if (preTargetInfo.record.dataIndex == parentID1) {\n // 拖拽节点的父级节点和拖拽后上方的节点的父级节点相同\n reslove(true);\n } else {\n const parentID2 = findParent(baseColumnList.value, preTargetInfo.record.dataIndex); // 拖拽后上方的节点的父级节点\n if (parentID1 == parentID2) {\n // 拖拽节点的父级节点和拖拽后上方的节点的父级节点相同\n reslove(true);\n } else {\n reject();\n }\n }\n } else {\n const parentID1 = findParent(baseColumnList.value, record.dataIndex); // 拖拽节点的父级节点\n const parentID2 = findParent(baseColumnList.value, nextTargetInfo.record.dataIndex); // 拖拽后下方的节点的父级节点\n if (parentID1 == parentID2) {\n // 拖拽节点的父级节点和拖拽后下方的节点的父级节点相同\n reslove(true);\n } else {\n reject();\n }\n }\n }).then(() => {\n setTimeout(() => {\n emitData();\n }, 200);\n });\n };\n\n const changeBaseColumnList = () => {\n baseColumnList.value = [].concat(baseColumnList.value);\n emitData();\n };\n const changeCellComponent = (record: any) => {\n changeBaseColumnList();\n };\n\n const getRawRecord = (dataList: any[], recordIndexs: number[]) => {\n let currentSource: any = dataList;\n recordIndexs.forEach(index => {\n if (!Array.isArray(currentSource) && currentSource.children) {\n currentSource = currentSource.children;\n }\n currentSource = currentSource[index];\n });\n return currentSource;\n };\n const compareField = (baseColumnRecord: any) => {\n const field = fieldMap.value[baseColumnRecord.dataIndex];\n if (field) {\n const keys = {\n filters: 'filters',\n sorter: 'sorter',\n summary: 'summary',\n cellSummaryComponent: 'cellSummaryComponent',\n };\n const data1 = getFieldConfig(field, keys);\n const keys2 = Object.values(keys).reduce((acc, key) => {\n acc[key] = key;\n return acc;\n }, {});\n const data2 = getFieldConfig(baseColumnRecord, keys2);\n const res = isEqual(data1, data2);\n if (!res) {\n console.log(`${baseColumnRecord.dataIndex} 字段配置不一致`, data1, data2);\n }\n return res;\n }\n return true;\n };\n\n const getChangedFields = (list: any[]) => {\n const changedFields: any = {};\n list.forEach(item => {\n if (!compareField(item)) {\n changedFields[item.dataIndex] = item;\n }\n if (item.children && Array.isArray(item.children)) {\n Object.assign(changedFields, getChangedFields(item.children));\n }\n });\n return changedFields;\n };\n const refreshChangedFields = () => {\n changedFields.value = getChangedFields(baseColumnList.value);\n };\n const handleUpdateBaseColumn = (record: any) => {\n updateBaseColumn(record);\n emitData();\n refreshChangedFields();\n };\n const updateBaseColumn = (record: any) => {\n const field = fieldMap.value[record.dataIndex];\n if (field) {\n const keys = {\n filterMultiple: 'filterMultiple',\n contentMap: 'contentMap',\n colorMap: 'colorMap',\n filters: 'filters',\n sorter: 'sorter',\n summary: 'summary',\n cellSummaryComponent: 'cellSummaryComponent',\n };\n const data = getFieldConfig(field, keys);\n Object.assign(record, data);\n }\n };\n const updateAllBaseColumn = () => {\n Object.values(changedFields.value).forEach((item: any) => {\n updateBaseColumn(item);\n });\n emitData();\n refreshChangedFields();\n };\n const copyClick = (args: ContextmenuPopupArg<any, any>) => {\n if (args.column.key === 'operation') return;\n copyValue(args.text);\n // 3.0.1 新增\n args.hidePopup();\n };\n return {\n selectedRowKeys,\n allColumnsData,\n columns,\n rowSelection,\n baseColumns,\n baseColumnList,\n baseRowSelection,\n baseSelectKeys,\n defaultColumns,\n cellComponentList: cellComponentList(),\n customCell,\n goRight,\n goLeft,\n onRowDragEnd,\n changeBaseColumnList,\n updateBaseColumn,\n getRawRecord,\n changedFields,\n updateAllBaseColumn,\n handleUpdateBaseColumn,\n copyClick,\n changeCellComponent,\n height,\n emitData,\n fieldMap,\n };\n },\n});\n</script>\n\n<style lang=\"less\" scoped>\n.antTabs {\n ::v-deep(.ant-tabs) {\n overflow-y: auto;\n overflow-x: hidden;\n }\n\n ::v-deep(.ant-layout-sider) {\n overflow-y: auto;\n overflow-x: hidden;\n }\n}\n\n.editable-cell {\n position: relative;\n\n .editable-cell-input-wrapper {\n padding-right: 24px;\n }\n\n .editable-cell-text-wrapper {\n padding: 5px 24px 5px 5px;\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .editable-cell-icon,\n .editable-cell-icon-check {\n position: absolute;\n right: 0;\n width: 20px;\n cursor: pointer;\n }\n\n .editable-cell-icon {\n margin-top: 4px;\n //display: inline-block;\n display: none;\n }\n\n .editable-cell-icon-check {\n margin-top: 8px;\n }\n\n .editable-cell-icon:hover,\n .editable-cell-icon-check:hover {\n color: #108ee9;\n }\n\n .editable-add-btn {\n margin-bottom: 8px;\n }\n}\n\n.editable-cell:hover .editable-cell-icon {\n display: inline-block;\n}\n.base-column-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: flex-start;\n padding-right: 20px;\n .base-column-table {\n flex: 1;\n overflow: hidden;\n width: 100%;\n }\n}\n.column-title-container {\n width: 100%;\n display: flex;\n height: 40px;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n gap: 10px;\n .column-title {\n font-size: 14px;\n font-weight: 600;\n }\n ::v-deep(.ant-alert) {\n padding: 0 10px;\n }\n}\n.default-sort-tip {\n font-size: 12px;\n color: #c4c2c2;\n}\n</style>\n","<template>\n <a-layout class=\"antTabs\">\n <a-layout-sider\n width=\"100%\"\n :style=\"{ backgroundColor: 'white', overflowY: 'auto', height: height + 'px' }\"\n >\n <a-row style=\"height: 100%\">\n <a-col :span=\"6\">\n <div class=\"column-title-container\">\n <div class=\"column-title\">{{ $t('可选列') }}</div>\n </div>\n <s-table\n v-model:selectedRowKeys=\"selectedRowKeys\"\n :autoRowHeight=\"true\"\n :bordered=\"true\"\n :columns=\"columns\"\n :customCell=\"customCell\"\n :data-source=\"allColumnsData\"\n :scroll=\"{ y: height - 90 }\"\n :indentSize=\"0\"\n :pagination=\"false\"\n :row-selection=\"rowSelection\"\n :rowHeight=\"30\"\n :rowKey=\"'name'\"\n :size=\"'small'\"\n :wrapText=\"true\"\n sticky\n stripe\n summary-fixed\n >\n <template #bodyCell=\"{ column, index, text, record }\">\n <span>{{ text }}</span>\n </template>\n <template #contextmenuPopup=\"args\">\n <a-space-compact direction=\"vertical\">\n <a-button\n block\n size=\"small\"\n type=\"text\"\n @click=\"copyClick(args, 'cell')\"\n >\n <template #icon>\n <copy-outlined />\n </template>\n {{ $t('复制') }}\n </a-button>\n </a-space-compact>\n </template>\n </s-table>\n </a-col>\n <a-col :span=\"1\">\n <div\n :style=\"{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: height + 'px',\n }\"\n >\n <div style=\"width: 30px\">\n <left-square-outlined\n v-if=\"baseSelectKeys.length === 0\"\n style=\"color: #999999; font-size: 25px\"\n />\n <left-square-two-tone\n v-if=\"baseSelectKeys.length > 0\"\n style=\"font-size: 25px\"\n @click=\"goLeft\"\n />\n <right-square-outlined\n v-if=\"selectedRowKeys.length === 0\"\n style=\"color: #999999; font-size: 25px\"\n />\n <right-square-two-tone\n v-if=\"selectedRowKeys.length > 0\"\n style=\"font-size: 25px\"\n @click=\"goRight\"\n />\n </div>\n </div>\n </a-col>\n <a-col\n :span=\"17\"\n class=\"base-column-content\"\n >\n <div class=\"column-title-container\">\n <div class=\"column-title\">{{ $t('列设置') }}</div>\n <!-- <a-alert\n type=\"warning\"\n v-if=\"Object.keys(changedFields).length > 0\"\n >\n <template #description>\n 共有\n <span style=\"color: red\">{{ Object.keys(changedFields).length }}</span>\n 个字段配置有变更\n <a-button\n type=\"link\"\n @click=\"updateAllBaseColumn\"\n >\n 全部更新\n </a-button>\n </template>\n </a-alert> -->\n </div>\n <div class=\"base-column-table\">\n <s-table\n :bordered=\"true\"\n :columns=\"baseColumns\"\n :rowHeight=\"30\"\n :data-source=\"baseColumnList\"\n :row-selection=\"baseRowSelection\"\n v-model:selectedRowKeys=\"baseSelectKeys\"\n expand-row-by-click\n @row-drag-end=\"onRowDragEnd\"\n :row-key=\"'dataIndex'\"\n :pagination=\"false\"\n :size=\"'small'\"\n :scroll=\"{ y: height - 100, x: '100%' }\"\n >\n <template #bodyCell=\"{ column, index, text, record, recordIndexs }\">\n <template v-if=\"column.dataIndex === 'title'\">\n <cell-edit\n v-model:value=\"getRawRecord(baseColumnList, recordIndexs).title\"\n @change=\"emitData\"\n ></cell-edit>\n </template>\n <template v-if=\"column.dataIndex === 'dataIndex'\">\n {{ text }}\n <WarningOutlined\n title=\"列参数不存在\"\n v-if=\"fieldMap && !fieldMap[text]\"\n style=\"color: #faad14\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'defaultSort'\">\n <a-row\n :gutter=\"8\"\n v-if=\"record.sorter\"\n >\n <a-col :span=\"12\">\n <a-select\n v-model:value=\"record.defaultSortOrder\"\n @change=\"changeBaseColumnList\"\n style=\"width: 100%\"\n size=\"small\"\n allowClear\n >\n <a-select-option\n key=\"ascend\"\n value=\"ascend\"\n >\n {{ $t('升序') }}\n </a-select-option>\n <a-select-option\n key=\"descend\"\n value=\"descend\"\n >\n {{ $t('降序') }}\n </a-select-option>\n </a-select>\n </a-col>\n <a-col :span=\"12\">\n <a-input-number\n v-if=\"record.defaultSortOrder\"\n size=\"small\"\n v-model:value=\"record.defaultSortIndex\"\n :precision=\"0\"\n @click=\"changeBaseColumnList\"\n placeholder=\"序号\"\n style=\"width: 100%\"\n :min=\"1\"\n ></a-input-number>\n </a-col>\n </a-row>\n <div\n v-else\n class=\"default-sort-tip\"\n >\n 不支持排序\n </div>\n </template>\n <template v-if=\"column.dataIndex === 'fixed'\">\n <a-radio-group\n v-if=\"!record?.is_children\"\n v-model:value=\"record.fixed\"\n size=\"small\"\n @click=\"changeBaseColumnList\"\n >\n <a-radio-button value=\"left\">{{ '左' }}</a-radio-button>\n <a-radio-button :value=\"undefined\">{{ '不固定' }}</a-radio-button>\n <a-radio-button value=\"right\">{{ '右' }}</a-radio-button>\n </a-radio-group>\n </template>\n <template v-if=\"column.dataIndex === 'autoHeight'\">\n <a-switch\n v-if=\"!(record.children && record.children.length > 0)\"\n v-model:checked=\"record.autoHeight\"\n :checked-value=\"true\"\n :un-checked-value=\"false\"\n :checked-children=\"'自动'\"\n :un-checked-children=\"'固定'\"\n @click=\"changeBaseColumnList\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'autoWidth'\">\n <a-switch\n v-if=\"!(record.children && record.children.length > 0) && record?.resizable\"\n v-model:checked=\"record.autoWidth\"\n :checked-value=\"true\"\n :un-checked-value=\"false\"\n :checked-children=\"$t('自动')\"\n :un-checked-children=\"$t('固定')\"\n @click=\"changeBaseColumnList\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'approve_summary'\">\n <a-switch\n v-model:checked=\"record.approve_summary\"\n :checked-value=\"true\"\n :un-checked-value=\"false\"\n @click=\"changeBaseColumnList\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'ellipsis'\">\n <a-switch\n v-if=\"!(record.children && record.children.length > 0) && record?.resizable\"\n v-model:checked=\"record.ellipsis\"\n :checked-value=\"true\"\n :un-checked-value=\"false\"\n :checked-children=\"$t('开启')\"\n :un-checked-children=\"$t('关闭')\"\n @click=\"changeBaseColumnList\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'cellComponent'\">\n <a-select\n v-model:value=\"record.cellComponent\"\n :allow-clear=\"true\"\n :dropdownMatchSelectWidth=\"false\"\n :placeholder=\"$t('请选择')\"\n :show-search=\"true\"\n size=\"small\"\n style=\"width: 180px\"\n @change=\"changeCellComponent(record)\"\n >\n <a-select-option\n v-for=\"option in cellComponentList\"\n :key=\"option.cellComponent\"\n :value=\"option.cellComponent\"\n >\n {{ $t(option.name) + '(' + option.cellComponent + ')' }}\n </a-select-option>\n </a-select>\n </template>\n\n <template v-if=\"column.dataIndex === 'action'\">\n <a-button\n type=\"link\"\n v-if=\"changedFields[record.dataIndex]\"\n @click=\"handleUpdateBaseColumn(getRawRecord(baseColumnList, recordIndexs))\"\n >\n {{ $t('更新') }}\n </a-button>\n </template>\n </template>\n <template #contextmenuPopup=\"args\">\n <a-space-compact direction=\"vertical\">\n <a-button\n block\n size=\"small\"\n type=\"text\"\n @click=\"copyClick(args, 'cell')\"\n >\n <template #icon>\n <copy-outlined />\n </template>\n {{ $t('复制') }}\n </a-button>\n </a-space-compact>\n </template>\n </s-table>\n </div>\n </a-col>\n </a-row>\n </a-layout-sider>\n </a-layout>\n</template>\n<script lang=\"ts\">\nimport {\n CheckOutlined,\n EditOutlined,\n LeftSquareOutlined,\n LeftSquareTwoTone,\n RightSquareOutlined,\n RightSquareTwoTone,\n} from '@ant-design/icons-vue';\nimport { ContextmenuPopupArg } from '@surely-vue/table';\nimport { cellComponentList, getApiData, useUserStore } from '@/init-plugin';\nimport { copyValue, removeNestedDuplicates } from '@/utils/function';\nimport { cloneDeep, debounce, isEqual } from 'lodash';\nimport { defineComponent, onMounted, onUnmounted, reactive, ref } from 'vue';\nimport { useI18n } from 'vue-i18n';\nimport cellEdit from './cellEdit.vue';\n\nexport default defineComponent({\n name: 'BaseColumns',\n props: {\n dataSource: {\n type: Array,\n default: () => {},\n },\n modelType: {\n type: String,\n required: true,\n },\n },\n components: {\n LeftSquareOutlined,\n LeftSquareTwoTone,\n RightSquareOutlined,\n RightSquareTwoTone,\n CheckOutlined,\n EditOutlined,\n cellEdit,\n },\n emits: ['update:dataSource'],\n setup(props, { emit }) {\n const { t } = useI18n();\n const height = ref(0);\n const userStore = useUserStore();\n const current_org = userStore.currentOrg; // 当前组织org\n const selectedRowKeys = ref([]);\n const allColumnsData = ref([]);\n const baseColumnList = ref([]);\n const baseSelectKeys = ref([]);\n const fieldMap = ref({});\n const changedFields = ref({});\n const defaultColumns = [\n {\n title: t('列名称'),\n dataIndex: 'title',\n key: 'title',\n width: 200,\n },\n ];\n const columns = [\n {\n title: t('参数'),\n dataIndex: 'name',\n checked: true,\n width: 200,\n ellipsis: true,\n },\n {\n title: t('名称'),\n dataIndex: 'verbose_name',\n checked: true,\n width: 150,\n ellipsis: true,\n },\n ];\n const baseColumns = [\n {\n title: t('列名称'),\n dataIndex: 'title',\n key: 'title',\n rowDrag: true,\n width: 200,\n fixed: 'left',\n },\n {\n title: t('参数'),\n dataIndex: 'dataIndex',\n width: 200,\n fixed: 'left',\n ellipsis: true,\n },\n {\n title: t('默认排序'),\n dataIndex: 'defaultSort',\n width: 240,\n ellipsis: true,\n },\n {\n title: t('冻结列'),\n dataIndex: 'fixed',\n key: 'fixed',\n width: 150,\n },\n {\n title: '行高',\n dataIndex: 'autoHeight',\n width: 80,\n key: 'autoHeight',\n },\n {\n title: '列宽',\n dataIndex: 'autoWidth',\n width: 80,\n key: 'autoWidth',\n },\n {\n title: '合计',\n dataIndex: 'approve_summary',\n width: 80,\n key: 'approve_summary',\n },\n {\n title: '超宽省略',\n dataIndex: 'ellipsis',\n width: 80,\n key: 'ellipsis',\n },\n {\n title: '列组件',\n dataIndex: 'cellComponent',\n width: 200,\n key: 'cellComponent',\n },\n ];\n const onresize: any = debounce(() => {\n height.value = window.innerHeight - 165;\n }, 200);\n const emitData = () => {\n emit('update:dataSource', baseColumnList.value);\n };\n function markChecked(nodeB, idSetA) {\n nodeB.disabled = false;\n if (nodeB.name != null && idSetA.has(nodeB.name)) {\n nodeB.disabled = true;\n }\n if (nodeB.children && Array.isArray(nodeB.children)) {\n nodeB.children.forEach(childNodeB => {\n markChecked(childNodeB, idSetA);\n });\n }\n }\n const getFieldMap = (dataList: any) => {\n dataList.forEach(item => {\n fieldMap.value[item.name] = item;\n if (Array.isArray(item.children)) {\n getFieldMap(item.children);\n }\n });\n };\n const refreshData = () => {\n const allIdsInA = new Set();\n\n function collectAllIds(nodes) {\n nodes.forEach(node => {\n allIdsInA.add(node.dataIndex);\n if (node.children && Array.isArray(node.children)) {\n collectAllIds(node.children);\n }\n });\n }\n\n collectAllIds(baseColumnList.value);\n allColumnsData.value.forEach(nodeB => {\n markChecked(nodeB, allIdsInA);\n });\n allColumnsData.value = [].concat(allColumnsData.value);\n };\n\n onMounted(async () => {\n window.addEventListener('resize', onresize);\n onresize();\n baseColumnList.value = props.dataSource || [];\n if (props.modelType) {\n const args = props.modelType.split('-');\n const url = `${args[0]}/obtain_${args[1]}_column_data`;\n const res = await getApiData(\n { org_id: current_org?.id, is_base_column: true },\n url,\n false,\n {\n skip_error: true,\n },\n );\n allColumnsData.value = removeNestedDuplicates(res || []);\n getFieldMap(allColumnsData.value);\n }\n refreshChangedFields();\n refreshData();\n emitData();\n });\n onUnmounted(() => {\n window.removeEventListener('resize', onresize);\n });\n\n const customCell = (obj: any) => {\n if (obj.record.disabled) {\n return { style: { background: '#cbcbcb' } };\n }\n };\n const rowSelection = reactive({\n type: 'checkbox',\n onChange: (selectedKeys: string[]) => {\n selectedRowKeys.value = selectedKeys;\n },\n getCheckboxProps: (record: any) => ({\n disabled: record.disabled,\n name: record.name,\n }),\n });\n const baseRowSelection = reactive({\n type: 'checkbox',\n onChange: (selectedKeys: string[]) => {\n baseSelectKeys.value = selectedKeys;\n },\n getCheckboxProps: (record: any) => ({\n disabled: record.dataIndex === 'index' || record.dataIndex === 'action',\n name: record.dataIndex,\n }),\n });\n const getFieldConfig = (field: any, keys: Record<string, string>) => {\n const config: any = {};\n Object.keys(keys).forEach(key => {\n if (field[key] !== undefined) {\n config[keys[key]] = field[key];\n }\n });\n return config;\n };\n const setDisabledGoRight = (data: any) => {\n data.forEach(item => {\n if (selectedRowKeys.value.indexOf(item.name) > -1) {\n let obj: any = {};\n obj = getFieldConfig(item, {\n verbose_name: 'title',\n name: 'dataIndex',\n cell_component: 'cellComponent',\n filterMultiple: 'filterMultiple',\n contentMap: 'contentMap',\n colorMap: 'colorMap',\n filters: 'filters',\n sorter: 'sorter',\n summary: 'approve_summary',\n cellSummaryComponent: 'cellSummaryComponent',\n });\n obj.fixed = undefined;\n obj.autoHeight = false;\n obj.autoWidth = false;\n obj.width = 150;\n obj.resizable = true;\n item.disabled = true;\n if (item.cellComponent) {\n obj.ellipsis = false;\n } else {\n obj.ellipsis = true;\n }\n baseColumnList.value.push(obj);\n }\n // 如果当前节点有 children,则递归调用函数\n if (item.children && Array.isArray(item.children)) {\n setDisabledGoRight(item.children);\n }\n });\n };\n const goRight = () => {\n setDisabledGoRight(allColumnsData.value);\n selectedRowKeys.value.length = 0;\n allColumnsData.value = [].concat(allColumnsData.value);\n baseColumnList.value = [].concat(baseColumnList.value);\n emitData();\n };\n const setDisabledGoLeft = (data: any) => {\n data.forEach(item => {\n if (baseSelectKeys.value.indexOf(item.name) > -1) {\n item.disabled = false;\n }\n // 如果当前节点有 children,则递归调用函数\n if (item.children && Array.isArray(item.children)) {\n setDisabledGoLeft(item.children);\n }\n });\n };\n const goLeft = () => {\n baseColumnList.value = baseColumnList.value.filter((item: any) => {\n return baseSelectKeys.value.indexOf(item.dataIndex) == -1;\n });\n setDisabledGoLeft(allColumnsData.value);\n baseSelectKeys.value.length = 0;\n baseColumnList.value = [].concat(baseColumnList.value);\n allColumnsData.value = [].concat(allColumnsData.value);\n emitData();\n refreshChangedFields();\n };\n // 返回当前节点的父级节点\n const findParent = (data: any[], childKey: any) => {\n let foundParentKey: any;\n const searchParent = (id: any, keys: any[], childKeys: any) => {\n for (const key of keys) {\n if (key.dataIndex === childKeys) {\n foundParentKey = id;\n return foundParentKey;\n } else if (key.children && key.children.length > 0) {\n foundParentKey = searchParent(key.dataIndex, key.children, childKeys);\n if (foundParentKey !== undefined) return foundParentKey; // 如果找到,立即返回\n }\n }\n return undefined; // 如果没有找到\n };\n return searchParent(null, data, childKey);\n };\n const onRowDragEnd = ({ record, preTargetInfo, nextTargetInfo }) => {\n return new Promise((reslove, reject) => {\n if (preTargetInfo) {\n // 拖拽后上方的节点\n const parentID1 = findParent(baseColumnList.value, record.dataIndex); // 拖拽节点的父级节点\n if (preTargetInfo.record.dataIndex == parentID1) {\n // 拖拽节点的父级节点和拖拽后上方的节点的父级节点相同\n reslove(true);\n } else {\n const parentID2 = findParent(baseColumnList.value, preTargetInfo.record.dataIndex); // 拖拽后上方的节点的父级节点\n if (parentID1 == parentID2) {\n // 拖拽节点的父级节点和拖拽后上方的节点的父级节点相同\n reslove(true);\n } else {\n reject();\n }\n }\n } else {\n const parentID1 = findParent(baseColumnList.value, record.dataIndex); // 拖拽节点的父级节点\n const parentID2 = findParent(baseColumnList.value, nextTargetInfo.record.dataIndex); // 拖拽后下方的节点的父级节点\n if (parentID1 == parentID2) {\n // 拖拽节点的父级节点和拖拽后下方的节点的父级节点相同\n reslove(true);\n } else {\n reject();\n }\n }\n }).then(() => {\n setTimeout(() => {\n emitData();\n }, 200);\n });\n };\n\n const changeBaseColumnList = () => {\n baseColumnList.value = [].concat(baseColumnList.value);\n emitData();\n };\n const changeCellComponent = (record: any) => {\n changeBaseColumnList();\n };\n\n const getRawRecord = (dataList: any[], recordIndexs: number[]) => {\n let currentSource: any = dataList;\n recordIndexs.forEach(index => {\n if (!Array.isArray(currentSource) && currentSource.children) {\n currentSource = currentSource.children;\n }\n currentSource = currentSource[index];\n });\n return currentSource;\n };\n const compareField = (baseColumnRecord: any) => {\n const field = fieldMap.value[baseColumnRecord.dataIndex];\n if (field) {\n const keys = {\n filters: 'filters',\n sorter: 'sorter',\n summary: 'summary',\n cellSummaryComponent: 'cellSummaryComponent',\n };\n const data1 = getFieldConfig(field, keys);\n const keys2 = Object.values(keys).reduce((acc, key) => {\n acc[key] = key;\n return acc;\n }, {});\n const data2 = getFieldConfig(baseColumnRecord, keys2);\n const res = isEqual(data1, data2);\n if (!res) {\n console.log(`${baseColumnRecord.dataIndex} 字段配置不一致`, data1, data2);\n }\n return res;\n }\n return true;\n };\n\n const getChangedFields = (list: any[]) => {\n const changedFields: any = {};\n list.forEach(item => {\n if (!compareField(item)) {\n changedFields[item.dataIndex] = item;\n }\n if (item.children && Array.isArray(item.children)) {\n Object.assign(changedFields, getChangedFields(item.children));\n }\n });\n return changedFields;\n };\n const refreshChangedFields = () => {\n changedFields.value = getChangedFields(baseColumnList.value);\n };\n const handleUpdateBaseColumn = (record: any) => {\n updateBaseColumn(record);\n emitData();\n refreshChangedFields();\n };\n const updateBaseColumn = (record: any) => {\n const field = fieldMap.value[record.dataIndex];\n if (field) {\n const keys = {\n filterMultiple: 'filterMultiple',\n contentMap: 'contentMap',\n colorMap: 'colorMap',\n filters: 'filters',\n sorter: 'sorter',\n summary: 'summary',\n cellSummaryComponent: 'cellSummaryComponent',\n };\n const data = getFieldConfig(field, keys);\n Object.assign(record, data);\n }\n };\n const updateAllBaseColumn = () => {\n Object.values(changedFields.value).forEach((item: any) => {\n updateBaseColumn(item);\n });\n emitData();\n refreshChangedFields();\n };\n const copyClick = (args: ContextmenuPopupArg<any, any>) => {\n if (args.column.key === 'operation') return;\n copyValue(args.text);\n // 3.0.1 新增\n args.hidePopup();\n };\n return {\n selectedRowKeys,\n allColumnsData,\n columns,\n rowSelection,\n baseColumns,\n baseColumnList,\n baseRowSelection,\n baseSelectKeys,\n defaultColumns,\n cellComponentList: cellComponentList(),\n customCell,\n goRight,\n goLeft,\n onRowDragEnd,\n changeBaseColumnList,\n updateBaseColumn,\n getRawRecord,\n changedFields,\n updateAllBaseColumn,\n handleUpdateBaseColumn,\n copyClick,\n changeCellComponent,\n height,\n emitData,\n fieldMap,\n };\n },\n});\n</script>\n\n<style lang=\"less\" scoped>\n.antTabs {\n ::v-deep(.ant-tabs) {\n overflow-y: auto;\n overflow-x: hidden;\n }\n\n ::v-deep(.ant-layout-sider) {\n overflow-y: auto;\n overflow-x: hidden;\n }\n}\n\n.editable-cell {\n position: relative;\n\n .editable-cell-input-wrapper {\n padding-right: 24px;\n }\n\n .editable-cell-text-wrapper {\n padding: 5px 24px 5px 5px;\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .editable-cell-icon,\n .editable-cell-icon-check {\n position: absolute;\n right: 0;\n width: 20px;\n cursor: pointer;\n }\n\n .editable-cell-icon {\n margin-top: 4px;\n //display: inline-block;\n display: none;\n }\n\n .editable-cell-icon-check {\n margin-top: 8px;\n }\n\n .editable-cell-icon:hover,\n .editable-cell-icon-check:hover {\n color: #108ee9;\n }\n\n .editable-add-btn {\n margin-bottom: 8px;\n }\n}\n\n.editable-cell:hover .editable-cell-icon {\n display: inline-block;\n}\n.base-column-content {\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: flex-start;\n padding-right: 20px;\n .base-column-table {\n flex: 1;\n overflow: hidden;\n width: 100%;\n }\n}\n.column-title-container {\n width: 100%;\n display: flex;\n height: 40px;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n gap: 10px;\n .column-title {\n font-size: 14px;\n font-weight: 600;\n }\n ::v-deep(.ant-alert) {\n padding: 0 10px;\n }\n}\n.default-sort-tip {\n font-size: 12px;\n color: #c4c2c2;\n}\n</style>\n","<template>\n <a-select\n v-model:value=\"record.operator_list\"\n :allow-clear=\"true\"\n :dropdownMatchSelectWidth=\"false\"\n :placeholder=\"'请选择'\"\n :show-search=\"true\"\n size=\"small\"\n mode=\"tags\"\n :maxTagCount=\"'responsive'\"\n style=\"width: 100%\"\n @change=\"changeOperatorList(record)\"\n >\n <a-select-option\n v-for=\"option in operator_list\"\n :value=\"option\"\n >\n {{ get_operator_type_map(record.format, option) }}({{ option }})\n </a-select-option>\n </a-select>\n</template>\n<script lang=\"ts\">\nimport { useModelOperator } from '@/init-plugin';\nimport { computed, defineComponent } from 'vue';\nimport { get_operator_type_map } from '@/utils/function';\n\nexport default defineComponent({\n name: 'OperatorSelect',\n props: {\n record: {\n type: Object,\n required: true,\n },\n },\n emits: ['change'],\n setup(props, { emit }) {\n const modelOperator = useModelOperator();\n const changeOperatorList = (record: any) => {\n emit('change', record);\n };\n const operator_list = computed(() => {\n let operator_list = [];\n if (props.record.options && props.record.options.length > 0) {\n operator_list = ['in', 'notin', 'eq', 'not_eq'];\n if (props.record.class_name == 'str') {\n operator_list.push('is_or_not_blank_or_null');\n } else {\n operator_list.push('is_or_not_null');\n }\n } else if (props.record.type == 'remoteselectpro') {\n operator_list = modelOperator['remote'];\n } else {\n operator_list = modelOperator[props.record.class_name] || [];\n }\n return operator_list;\n });\n return {\n changeOperatorList,\n operator_list,\n get_operator_type_map,\n };\n },\n});\n</script>\n","<template>\n <a-select\n v-model:value=\"record.operator_list\"\n :allow-clear=\"true\"\n :dropdownMatchSelectWidth=\"false\"\n :placeholder=\"'请选择'\"\n :show-search=\"true\"\n size=\"small\"\n mode=\"tags\"\n :maxTagCount=\"'responsive'\"\n style=\"width: 100%\"\n @change=\"changeOperatorList(record)\"\n >\n <a-select-option\n v-for=\"option in operator_list\"\n :value=\"option\"\n >\n {{ get_operator_type_map(record.format, option) }}({{ option }})\n </a-select-option>\n </a-select>\n</template>\n<script lang=\"ts\">\nimport { useModelOperator } from '@/init-plugin';\nimport { computed, defineComponent } from 'vue';\nimport { get_operator_type_map } from '@/utils/function';\n\nexport default defineComponent({\n name: 'OperatorSelect',\n props: {\n record: {\n type: Object,\n required: true,\n },\n },\n emits: ['change'],\n setup(props, { emit }) {\n const modelOperator = useModelOperator();\n const changeOperatorList = (record: any) => {\n emit('change', record);\n };\n const operator_list = computed(() => {\n let operator_list = [];\n if (props.record.options && props.record.options.length > 0) {\n operator_list = ['in', 'notin', 'eq', 'not_eq'];\n if (props.record.class_name == 'str') {\n operator_list.push('is_or_not_blank_or_null');\n } else {\n operator_list.push('is_or_not_null');\n }\n } else if (props.record.type == 'remoteselectpro') {\n operator_list = modelOperator['remote'];\n } else {\n operator_list = modelOperator[props.record.class_name] || [];\n }\n return operator_list;\n });\n return {\n changeOperatorList,\n operator_list,\n get_operator_type_map,\n };\n },\n});\n</script>\n","<template>\n <a-select\n v-model:value=\"record.default_operator\"\n :allow-clear=\"true\"\n :dropdownMatchSelectWidth=\"false\"\n :placeholder=\"'请选择'\"\n :show-search=\"true\"\n size=\"small\"\n style=\"width: 100%\"\n @change=\"changeDefaultOperator(record)\"\n >\n <a-select-option\n v-for=\"option in record.operator_list\"\n :value=\"option\"\n >\n {{ get_operator_type_map(record.format, option) }}({{ option }})\n </a-select-option>\n </a-select>\n</template>\n<script lang=\"ts\">\nimport { computed, defineComponent } from 'vue';\nimport { get_operator_type_map } from '@/utils/function';\n\nexport default defineComponent({\n name: 'DefaultOperatorSelect',\n props: {\n record: {\n type: Object,\n required: true,\n },\n },\n emits: ['change'],\n setup(props, { emit }) {\n const changeDefaultOperator = (record: any) => {\n emit('change', record);\n };\n const operator_list = computed(() => {\n return props.record.operator_list;\n });\n return {\n changeDefaultOperator,\n operator_list,\n get_operator_type_map,\n };\n },\n});\n</script>\n","<template>\n <a-select\n v-model:value=\"record.default_operator\"\n :allow-clear=\"true\"\n :dropdownMatchSelectWidth=\"false\"\n :placeholder=\"'请选择'\"\n :show-search=\"true\"\n size=\"small\"\n style=\"width: 100%\"\n @change=\"changeDefaultOperator(record)\"\n >\n <a-select-option\n v-for=\"option in record.operator_list\"\n :value=\"option\"\n >\n {{ get_operator_type_map(record.format, option) }}({{ option }})\n </a-select-option>\n </a-select>\n</template>\n<script lang=\"ts\">\nimport { computed, defineComponent } from 'vue';\nimport { get_operator_type_map } from '@/utils/function';\n\nexport default defineComponent({\n name: 'DefaultOperatorSelect',\n props: {\n record: {\n type: Object,\n required: true,\n },\n },\n emits: ['change'],\n setup(props, { emit }) {\n const changeDefaultOperator = (record: any) => {\n emit('change', record);\n };\n const operator_list = computed(() => {\n return props.record.operator_list;\n });\n return {\n changeDefaultOperator,\n operator_list,\n get_operator_type_map,\n };\n },\n});\n</script>\n","<template>\n <a-row\n class=\"antTabs\"\n :style=\"{ height: height + 'px' }\"\n >\n <a-col\n :span=\"7\"\n style=\"height: 100%\"\n >\n <div class=\"column-title-container\">\n <div class=\"column-title\">基础数据</div>\n </div>\n <s-table\n v-model:selectedRowKeys=\"selectedRowKeys\"\n :autoRowHeight=\"true\"\n :bordered=\"true\"\n :columns=\"columns\"\n :customCell=\"customCell\"\n :data-source=\"dataSource\"\n :scroll=\"{ y: height - 90 }\"\n :indentSize=\"0\"\n :pagination=\"false\"\n :row-selection=\"rowSelection\"\n :rowHeight=\"30\"\n :rowKey=\"'name'\"\n :size=\"'small'\"\n :wrapText=\"true\"\n sticky\n stripe\n summary-fixed\n >\n <template #bodyCell=\"{ column, index, text, record }\">\n <span>\n {{ text }}\n </span>\n </template>\n </s-table>\n </a-col>\n <a-col :span=\"1\">\n <div\n :style=\"{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: height + 'px',\n }\"\n >\n <div style=\"width: 30px\">\n <left-square-outlined\n v-if=\"baseSelectedRowKeys.length === 0\"\n style=\"color: #999999; font-size: 25px\"\n />\n <left-square-two-tone\n v-if=\"baseSelectedRowKeys.length > 0\"\n style=\"font-size: 25px\"\n @click=\"toLeft\"\n />\n <right-square-outlined\n v-if=\"selectedRowKeys.length === 0\"\n style=\"color: #999999; font-size: 25px\"\n />\n <right-square-two-tone\n v-if=\"selectedRowKeys.length > 0\"\n style=\"font-size: 25px\"\n @click=\"toRight\"\n />\n </div>\n </div>\n </a-col>\n <a-col :span=\"16\">\n <div class=\"column-title-container\">\n <div class=\"column-title\">基础列设置</div>\n </div>\n\n <s-table\n :bordered=\"true\"\n :columns=\"baseColumns\"\n :rowHeight=\"30\"\n :data-source=\"baseDataSource\"\n :row-selection=\"baseRowSelection\"\n v-model:selectedRowKeys=\"baseSelectedRowKeys\"\n expand-row-by-click\n @row-drag-end=\"baseRowDragEnd\"\n :row-key=\"'dataIndex'\"\n :pagination=\"false\"\n v-model:expandedRowKeys=\"baseExpandedRowKeys\"\n :default-expand-all-rows=\"true\"\n :scroll=\"{ y: height - 90 }\"\n :size=\"'small'\"\n >\n <template #bodyCell=\"{ column, index, text, record, recordIndexs }\">\n <template v-if=\"column.dataIndex === 'label'\">\n <cell-edit\n v-model:value=\"getRawRecord(baseDataSource, recordIndexs).label\"\n @change=\"emitData\"\n ></cell-edit>\n </template>\n <template v-if=\"column.dataIndex === 'field_name'\">\n {{ text }}\n <WarningOutlined\n title=\"查询参数不存在\"\n v-if=\"fieldMap && !fieldMap[text]\"\n style=\"color: #faad14\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'type'\">\n <a-select\n v-model:value=\"record.type\"\n :allow-clear=\"true\"\n :dropdownMatchSelectWidth=\"false\"\n :placeholder=\"'请选择'\"\n :show-search=\"true\"\n size=\"small\"\n style=\"width: 100%\"\n @change=\"changeBase\"\n >\n <a-select-option\n v-for=\"option in getType(record)\"\n :key=\"option.value\"\n :value=\"option.value\"\n >\n {{ option.name }}\n </a-select-option>\n </a-select>\n </template>\n <template v-if=\"column.dataIndex === 'operator_list'\">\n <OperatorSelect\n v-if=\"!record.children || record.children.length === 0\"\n :record=\"record\"\n @change=\"changeOperatorList\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'default_operator'\">\n <DefaultOperatorSelect\n v-if=\"!record.children || record.children.length === 0\"\n :record=\"record\"\n @change=\"changeDefaultOperator\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'action'\">\n <a-button\n type=\"link\"\n v-if=\"changedFields[record.field_name]\"\n @click=\"handleUpdateBaseColumn(getRawRecord(baseDataSource, recordIndexs))\"\n >\n 更新\n </a-button>\n </template>\n </template>\n </s-table>\n </a-col>\n </a-row>\n</template>\n<script lang=\"ts\">\nimport { defineComponent, onMounted, onUnmounted, reactive, ref, watch } from 'vue';\nimport {\n CheckOutlined,\n CloseCircleOutlined,\n EditOutlined,\n LeftSquareOutlined,\n LeftSquareTwoTone,\n RightSquareOutlined,\n RightSquareTwoTone,\n} from '@ant-design/icons-vue';\nimport { getApiData, useModelOperator, useModelTypeList, useUserStore } from '@/init-plugin';\nimport { cloneDeep, debounce, isEqual } from 'lodash';\nimport OperatorSelect from './operatorSelect.vue';\nimport DefaultOperatorSelect from './defaultOperatorSelect.vue';\nimport cellEdit from './cellEdit.vue';\n\nconst columns = [\n {\n title: '参数',\n dataIndex: 'name',\n checked: true,\n width: 250,\n ellipsis: true,\n },\n {\n title: '名称',\n dataIndex: 'verbose_name',\n checked: true,\n width: 100,\n ellipsis: true,\n },\n];\nconst baseColumns = [\n {\n title: '列名称',\n dataIndex: 'label',\n key: 'label',\n rowDrag: true,\n width: 100,\n },\n {\n title: '查询参数',\n dataIndex: 'field_name',\n key: 'field_name',\n width: 20,\n ellipsis: true,\n },\n {\n title: '数值类型',\n dataIndex: 'class_name',\n key: 'class_name',\n width: 10,\n },\n {\n title: '表单类型',\n dataIndex: 'type',\n key: 'type',\n width: 100,\n },\n {\n title: '可选比较操作符',\n dataIndex: 'operator_list',\n key: 'operator_list',\n width: 250,\n },\n {\n title: '默认比较操作符',\n dataIndex: 'default_operator',\n key: 'default_operator',\n width: 100,\n },\n];\nexport default defineComponent({\n name: 'BaseSearch',\n props: {\n record: {\n type: Object,\n default: () => {},\n },\n modelType: {\n type: String,\n default: () => '',\n },\n },\n components: {\n CloseCircleOutlined,\n LeftSquareOutlined,\n LeftSquareTwoTone,\n RightSquareOutlined,\n RightSquareTwoTone,\n CheckOutlined,\n EditOutlined,\n OperatorSelect,\n DefaultOperatorSelect,\n cellEdit,\n },\n emits: ['update:record'],\n setup(props, { emit }) {\n const modelOperator = useModelOperator();\n const modelTypeList = useModelTypeList();\n const height = ref(0);\n const userStore = useUserStore();\n const current_org = userStore.currentOrg; // 当前组织org\n const selectedRowKeys: any = ref([]);\n const open: any = reactive({});\n const dataSource: any = ref([]);\n const baseDataSource: any = ref([]);\n const baseSelectedRowKeys: any = ref([]);\n const baseExpandedRowKeys: any = ref([]);\n const fieldMap = ref({});\n const changedFields: any = ref({});\n const emitData = () => {\n let data: any = [];\n data = cloneDeep(baseDataSource.value);\n data.forEach((item: any) => {\n delete item.dataIndex;\n });\n emit('update:record', data);\n };\n const onresize: any = debounce(() => {\n height.value = window.innerHeight - 165;\n }, 200);\n\n function markChecked(nodeB, idSetA) {\n if (nodeB.name != null && idSetA.has(nodeB.name)) {\n nodeB.disabled = true;\n } else {\n nodeB.disabled = false;\n }\n if (nodeB.children && Array.isArray(nodeB.children)) {\n nodeB.children.forEach(childNodeB => {\n markChecked(childNodeB, idSetA);\n });\n }\n }\n\n // 接口返回数据去重\n function removeNestedDuplicates(nodes, seenIds = new Set(), parentPath = []) {\n const result = [];\n\n nodes.forEach((node, index) => {\n const currentPath = [...parentPath, index]; // 记录当前节点的路径\n const nodeId = node.name;\n const type = node.type;\n // 同时去除 json 类型的字段\n if (!seenIds.has(nodeId) && type !== 'json') {\n seenIds.add(nodeId);\n const newNode = { ...node };\n\n if (newNode.children && Array.isArray(newNode.children)) {\n newNode.children = removeNestedDuplicates(newNode.children, seenIds, currentPath);\n }\n\n result.push(newNode);\n } else {\n // 如果需要处理子对象(即使父对象被忽略了),则递归调用\n if (node.children && Array.isArray(node.children)) {\n // 注意:这里我们不将子对象添加到结果数组中,只是处理它们以避免丢失新的 id\n removeNestedDuplicates(node.children, seenIds, currentPath);\n }\n }\n });\n\n return result;\n }\n\n const refreshData = () => {\n const allIdsInA = new Set();\n baseExpandedRowKeys.value.length = 0;\n baseDataSource.value.forEach((item: any) => {\n allIdsInA.add(item.field_name);\n });\n dataSource.value.forEach(nodeB => {\n markChecked(nodeB, allIdsInA);\n });\n dataSource.value = [].concat(dataSource.value);\n baseDataSource.value = [].concat(baseDataSource.value);\n };\n\n onMounted(async () => {\n window.addEventListener('resize', onresize);\n onresize();\n const res = cloneDeep(props.record) || [];\n res.forEach((item: any) => {\n if (!item.operator_list) {\n item.operator_list = [];\n }\n // Add dataIndex if it doesn't exist, using field_name as the key\n if (!item.dataIndex && item.field_name) {\n item.dataIndex = item.field_name;\n }\n });\n baseDataSource.value = res;\n console.log(baseDataSource.value);\n if (props.modelType) {\n const args = props.modelType.split('-');\n const url = `${args[0]}/obtain_${args[1]}_column_data`;\n const res = await getApiData({ org_id: current_org?.id }, url, false, {\n skip_error: true,\n });\n dataSource.value = removeNestedDuplicates(res || []);\n getFieldMap(dataSource.value);\n }\n\n refreshChangedFields();\n refreshData();\n });\n onUnmounted(() => {\n window.removeEventListener('resize', onresize);\n });\n const customCell = (obj: any) => {\n if (obj.record.disabled) {\n return { style: { background: '#cbcbcb' } };\n }\n };\n const baseRowSelection = reactive({\n type: 'checkbox',\n onChange: (selectedKeys: string[]) => {\n baseSelectedRowKeys.value = selectedKeys;\n },\n getCheckboxProps: (record: any) => ({\n disabled: record.children !== undefined,\n name: record.dataIndex,\n }),\n });\n const rowSelection = reactive({\n type: 'checkbox',\n onChange: (selectedKeys: string[]) => {\n selectedRowKeys.value = selectedKeys;\n },\n getCheckboxProps: (record: any) => ({\n disabled: record.disabled,\n name: record.name,\n }),\n });\n // 返回当前节点的父级节点\n const findParent = (data: any[], childKey: any) => {\n let foundParentKey: any;\n const searchParent = (id: any, keys: any[], childKeys: any) => {\n for (const key of keys) {\n if (key.dataIndex === childKeys) {\n foundParentKey = id;\n return foundParentKey;\n } else if (key.children && key.children.length > 0) {\n foundParentKey = searchParent(key.dataIndex, key.children, childKeys);\n if (foundParentKey !== undefined) return foundParentKey; // 如果找到,立即返回\n }\n }\n return undefined; // 如果没有找到\n };\n return searchParent(null, data, childKey);\n };\n const baseRowDragEnd = ({ record, insertToRowKey }) => {\n return new Promise((reslove, reject) => {\n const parentID = findParent(baseDataSource.value, record.dataIndex); // 拖拽节点的父级节点\n // 注意后面的判断不能使用绝对比较 === 或 !==,因为会出现 null 和 undefined 两种值\n if (parentID != null && insertToRowKey != null) {\n reslove(true);\n } else if (parentID == null && insertToRowKey == null) {\n reslove(true);\n } else {\n reject();\n }\n }).then(() => {\n setTimeout(() => {\n emitData();\n }, 200);\n });\n };\n const setDisabledGoLeft = (data: any) => {\n data.forEach(item => {\n if (baseSelectedRowKeys.value.indexOf(item.name) > -1) {\n item.disabled = false;\n }\n // 如果当前节点有 children,则递归调用函数\n if (item.children && Array.isArray(item.children)) {\n setDisabledGoLeft(item.children);\n }\n });\n };\n const toLeft = () => {\n const list = baseDataSource.value.filter((item1: any) => {\n return baseSelectedRowKeys.value.indexOf(item1.dataIndex) == -1;\n });\n\n setDisabledGoLeft(dataSource.value);\n baseSelectedRowKeys.value.length = 0;\n baseDataSource.value = [].concat(list);\n dataSource.value = [].concat(dataSource.value);\n emitData();\n refreshChangedFields();\n };\n const setGoRightSearch = (data: any) => {\n data.forEach(item => {\n if (selectedRowKeys.value.indexOf(item.name) > -1) {\n item.disabled = true;\n let obj: any = {};\n obj.field_name = item.name;\n obj.label = item.verbose_name;\n obj.dataIndex = item.name;\n obj.required_condition = item.required_condition;\n obj.allowClear = true;\n Object.assign(obj, item.advanced_search_component);\n if (item?.options && item.options.length > 0) {\n obj.options = item.options;\n obj.operator_list = ['eq', 'in', 'notin'];\n if (item.type === 'boolean') {\n obj.class_name = 'bool';\n } else {\n obj.class_name = item.type;\n }\n obj.format = 'choices';\n } else if (item.type == 'int') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'int';\n } else if (item.type == 'float') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'float';\n } else if (item.type == 'str') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'str';\n } else if (item.type == 'remote') {\n obj.format = 'remote';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'int';\n obj.postUrl = item.postUrl;\n } else if (item.type == 'datetime') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'datetime';\n } else if (item.type == 'date') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'date';\n } else if (item.type == 'time') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'time';\n } else {\n obj.format = 'input';\n obj.operator_list = modelOperator['str'];\n obj.class_name = 'str';\n }\n baseDataSource.value.push(obj);\n }\n // 如果当前节点有 children,则递归调用函数\n if (item.children && Array.isArray(item.children)) {\n setGoRightSearch(item.children);\n }\n });\n };\n const toRight = () => {\n setGoRightSearch(dataSource.value);\n selectedRowKeys.value.length = 0;\n dataSource.value = [].concat(dataSource.value);\n baseDataSource.value = [].concat(baseDataSource.value);\n emitData();\n };\n const cancel = (key: any) => {\n delete open[key];\n };\n const handleDelete = (key: any) => {\n open[key] = key;\n };\n\n const deleteRecord = (key: any) => {\n delete open[key];\n let child: any = [];\n baseDataSource.value.forEach((item: any) => {\n if (key == item.dataIndex) {\n child = item.children;\n }\n });\n baseDataSource.value = baseDataSource.value.filter(item => item.dataIndex !== key);\n if (baseDataSource.value.length > 0) {\n baseDataSource.value[baseDataSource.value.length - 1].children.push(...child);\n }\n baseDataSource.value = [].concat(baseDataSource.value);\n emitData();\n };\n\n const changeBase = () => {\n baseDataSource.value = [].concat(baseDataSource.value);\n emitData();\n };\n const getType = (record: any) => {\n if (record?.children && record.children.length >= 0) {\n return [];\n } else if (record?.options && record.options.length > 0) {\n return [{ name: '下拉选框', value: 'select' }];\n }\n return modelTypeList[record.class_name] ? modelTypeList[record.class_name].type : [];\n };\n const changeOperatorList = (record: any) => {\n if (!record.operator_list.includes(record.default_operator)) {\n record.default_operator = null;\n }\n if (!record.default_operator) {\n record.default_operator = record.operator_list?.[0];\n }\n emitData();\n };\n const changeDefaultOperator = (record: any) => {\n emitData();\n };\n const getRawRecord = (dataSource: any[], recordIndexs: number[]) => {\n let currentSource: any = dataSource;\n recordIndexs.forEach(index => {\n if (!Array.isArray(currentSource) && currentSource.children) {\n currentSource = currentSource.children;\n }\n currentSource = currentSource[index];\n });\n return currentSource;\n };\n const getFieldConfig = (field: any, keys: Record<string, string>) => {\n const config: any = {};\n Object.keys(keys).forEach(key => {\n if (field[key] !== undefined) {\n config[keys[key]] = field[key];\n }\n });\n return config;\n };\n const getFieldMap = (dataSource: any) => {\n dataSource.forEach(item => {\n fieldMap.value[item.name] = item;\n if (Array.isArray(item.children)) {\n getFieldMap(item.children);\n }\n });\n };\n const compareField = (baseColumnRecord: any) => {\n const field = fieldMap.value[baseColumnRecord.field_name];\n if (field) {\n const keys = {\n options: 'options',\n required_condition: 'required_condition',\n };\n const data1 = getFieldConfig(field, keys);\n const keys2 = Object.values(keys).reduce((acc, key) => {\n acc[key] = key;\n return acc;\n }, {});\n const data2 = getFieldConfig(baseColumnRecord, keys2);\n const res = isEqual(data1, data2);\n if (!res) {\n console.log(`${baseColumnRecord.field_name} 字段配置不一致`, data1, data2);\n }\n return res;\n }\n return true;\n };\n const getChangedFields = (list: any[]) => {\n const changedFields: any = {};\n list.forEach(item => {\n if (!compareField(item)) {\n changedFields[item.field_name] = item;\n }\n const children = item.children || item.group;\n if (Array.isArray(children)) {\n Object.assign(changedFields, getChangedFields(children));\n }\n });\n return changedFields;\n };\n const refreshChangedFields = () => {\n changedFields.value = getChangedFields(baseDataSource.value);\n };\n const handleUpdateBaseColumn = (record: any) => {\n updateBaseColumn(record);\n emitData();\n refreshChangedFields();\n };\n const updateBaseColumn = (record: any) => {\n const field = fieldMap.value[record.field_name];\n if (field) {\n const keys = {\n options: 'options',\n required_condition: 'required_condition',\n };\n const data = getFieldConfig(field, keys);\n Object.assign(record, data);\n }\n };\n const updateAllBaseSearch = () => {\n Object.values(changedFields.value).forEach((item: any) => {\n updateBaseColumn(item);\n });\n emitData();\n refreshChangedFields();\n };\n return {\n selectedRowKeys,\n dataSource,\n columns,\n baseColumns,\n baseDataSource,\n open,\n rowSelection,\n baseRowSelection,\n baseSelectedRowKeys,\n baseExpandedRowKeys,\n emitData,\n customCell,\n toLeft,\n toRight,\n baseRowDragEnd,\n cancel,\n handleDelete,\n deleteRecord,\n changeBase,\n getType,\n changeOperatorList,\n changeDefaultOperator,\n changedFields,\n updateAllBaseSearch,\n handleUpdateBaseColumn,\n getRawRecord,\n height,\n fieldMap,\n };\n },\n});\n</script>\n\n<style lang=\"less\" scoped>\n.divHover {\n position: relative;\n\n .editable-cell-wrapper {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n padding-right: 25px;\n }\n\n .editable-cell-input {\n flex-grow: 1;\n }\n\n .editable-cell-check-icon {\n position: absolute;\n right: 0;\n width: 20px;\n cursor: pointer;\n }\n\n .display-cell-wrapper {\n padding: 5px 24px 5px 5px;\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .icon {\n position: absolute;\n right: 0;\n width: 20px;\n cursor: pointer;\n margin-top: 5px;\n display: none;\n }\n\n .icon1 {\n position: absolute;\n right: 20px;\n width: 20px;\n cursor: pointer;\n margin-top: 5px;\n display: none;\n }\n}\n\n.divHover:hover .icon {\n display: inline-block;\n}\n\n.divHover:hover .icon1 {\n display: inline-block;\n}\n\n.column-title-container {\n width: 100%;\n display: flex;\n height: 40px;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n gap: 10px;\n .column-title {\n font-size: 14px;\n font-weight: 600;\n }\n ::v-deep(.ant-alert) {\n padding: 0 10px;\n }\n}\n</style>\n","<template>\n <a-row\n class=\"antTabs\"\n :style=\"{ height: height + 'px' }\"\n >\n <a-col\n :span=\"7\"\n style=\"height: 100%\"\n >\n <div class=\"column-title-container\">\n <div class=\"column-title\">基础数据</div>\n </div>\n <s-table\n v-model:selectedRowKeys=\"selectedRowKeys\"\n :autoRowHeight=\"true\"\n :bordered=\"true\"\n :columns=\"columns\"\n :customCell=\"customCell\"\n :data-source=\"dataSource\"\n :scroll=\"{ y: height - 90 }\"\n :indentSize=\"0\"\n :pagination=\"false\"\n :row-selection=\"rowSelection\"\n :rowHeight=\"30\"\n :rowKey=\"'name'\"\n :size=\"'small'\"\n :wrapText=\"true\"\n sticky\n stripe\n summary-fixed\n >\n <template #bodyCell=\"{ column, index, text, record }\">\n <span>\n {{ text }}\n </span>\n </template>\n </s-table>\n </a-col>\n <a-col :span=\"1\">\n <div\n :style=\"{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: height + 'px',\n }\"\n >\n <div style=\"width: 30px\">\n <left-square-outlined\n v-if=\"baseSelectedRowKeys.length === 0\"\n style=\"color: #999999; font-size: 25px\"\n />\n <left-square-two-tone\n v-if=\"baseSelectedRowKeys.length > 0\"\n style=\"font-size: 25px\"\n @click=\"toLeft\"\n />\n <right-square-outlined\n v-if=\"selectedRowKeys.length === 0\"\n style=\"color: #999999; font-size: 25px\"\n />\n <right-square-two-tone\n v-if=\"selectedRowKeys.length > 0\"\n style=\"font-size: 25px\"\n @click=\"toRight\"\n />\n </div>\n </div>\n </a-col>\n <a-col :span=\"16\">\n <div class=\"column-title-container\">\n <div class=\"column-title\">基础列设置</div>\n </div>\n\n <s-table\n :bordered=\"true\"\n :columns=\"baseColumns\"\n :rowHeight=\"30\"\n :data-source=\"baseDataSource\"\n :row-selection=\"baseRowSelection\"\n v-model:selectedRowKeys=\"baseSelectedRowKeys\"\n expand-row-by-click\n @row-drag-end=\"baseRowDragEnd\"\n :row-key=\"'dataIndex'\"\n :pagination=\"false\"\n v-model:expandedRowKeys=\"baseExpandedRowKeys\"\n :default-expand-all-rows=\"true\"\n :scroll=\"{ y: height - 90 }\"\n :size=\"'small'\"\n >\n <template #bodyCell=\"{ column, index, text, record, recordIndexs }\">\n <template v-if=\"column.dataIndex === 'label'\">\n <cell-edit\n v-model:value=\"getRawRecord(baseDataSource, recordIndexs).label\"\n @change=\"emitData\"\n ></cell-edit>\n </template>\n <template v-if=\"column.dataIndex === 'field_name'\">\n {{ text }}\n <WarningOutlined\n title=\"查询参数不存在\"\n v-if=\"fieldMap && !fieldMap[text]\"\n style=\"color: #faad14\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'type'\">\n <a-select\n v-model:value=\"record.type\"\n :allow-clear=\"true\"\n :dropdownMatchSelectWidth=\"false\"\n :placeholder=\"'请选择'\"\n :show-search=\"true\"\n size=\"small\"\n style=\"width: 100%\"\n @change=\"changeBase\"\n >\n <a-select-option\n v-for=\"option in getType(record)\"\n :key=\"option.value\"\n :value=\"option.value\"\n >\n {{ option.name }}\n </a-select-option>\n </a-select>\n </template>\n <template v-if=\"column.dataIndex === 'operator_list'\">\n <OperatorSelect\n v-if=\"!record.children || record.children.length === 0\"\n :record=\"record\"\n @change=\"changeOperatorList\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'default_operator'\">\n <DefaultOperatorSelect\n v-if=\"!record.children || record.children.length === 0\"\n :record=\"record\"\n @change=\"changeDefaultOperator\"\n />\n </template>\n <template v-if=\"column.dataIndex === 'action'\">\n <a-button\n type=\"link\"\n v-if=\"changedFields[record.field_name]\"\n @click=\"handleUpdateBaseColumn(getRawRecord(baseDataSource, recordIndexs))\"\n >\n 更新\n </a-button>\n </template>\n </template>\n </s-table>\n </a-col>\n </a-row>\n</template>\n<script lang=\"ts\">\nimport { defineComponent, onMounted, onUnmounted, reactive, ref, watch } from 'vue';\nimport {\n CheckOutlined,\n CloseCircleOutlined,\n EditOutlined,\n LeftSquareOutlined,\n LeftSquareTwoTone,\n RightSquareOutlined,\n RightSquareTwoTone,\n} from '@ant-design/icons-vue';\nimport { getApiData, useModelOperator, useModelTypeList, useUserStore } from '@/init-plugin';\nimport { cloneDeep, debounce, isEqual } from 'lodash';\nimport OperatorSelect from './operatorSelect.vue';\nimport DefaultOperatorSelect from './defaultOperatorSelect.vue';\nimport cellEdit from './cellEdit.vue';\n\nconst columns = [\n {\n title: '参数',\n dataIndex: 'name',\n checked: true,\n width: 250,\n ellipsis: true,\n },\n {\n title: '名称',\n dataIndex: 'verbose_name',\n checked: true,\n width: 100,\n ellipsis: true,\n },\n];\nconst baseColumns = [\n {\n title: '列名称',\n dataIndex: 'label',\n key: 'label',\n rowDrag: true,\n width: 100,\n },\n {\n title: '查询参数',\n dataIndex: 'field_name',\n key: 'field_name',\n width: 20,\n ellipsis: true,\n },\n {\n title: '数值类型',\n dataIndex: 'class_name',\n key: 'class_name',\n width: 10,\n },\n {\n title: '表单类型',\n dataIndex: 'type',\n key: 'type',\n width: 100,\n },\n {\n title: '可选比较操作符',\n dataIndex: 'operator_list',\n key: 'operator_list',\n width: 250,\n },\n {\n title: '默认比较操作符',\n dataIndex: 'default_operator',\n key: 'default_operator',\n width: 100,\n },\n];\nexport default defineComponent({\n name: 'BaseSearch',\n props: {\n record: {\n type: Object,\n default: () => {},\n },\n modelType: {\n type: String,\n default: () => '',\n },\n },\n components: {\n CloseCircleOutlined,\n LeftSquareOutlined,\n LeftSquareTwoTone,\n RightSquareOutlined,\n RightSquareTwoTone,\n CheckOutlined,\n EditOutlined,\n OperatorSelect,\n DefaultOperatorSelect,\n cellEdit,\n },\n emits: ['update:record'],\n setup(props, { emit }) {\n const modelOperator = useModelOperator();\n const modelTypeList = useModelTypeList();\n const height = ref(0);\n const userStore = useUserStore();\n const current_org = userStore.currentOrg; // 当前组织org\n const selectedRowKeys: any = ref([]);\n const open: any = reactive({});\n const dataSource: any = ref([]);\n const baseDataSource: any = ref([]);\n const baseSelectedRowKeys: any = ref([]);\n const baseExpandedRowKeys: any = ref([]);\n const fieldMap = ref({});\n const changedFields: any = ref({});\n const emitData = () => {\n let data: any = [];\n data = cloneDeep(baseDataSource.value);\n data.forEach((item: any) => {\n delete item.dataIndex;\n });\n emit('update:record', data);\n };\n const onresize: any = debounce(() => {\n height.value = window.innerHeight - 165;\n }, 200);\n\n function markChecked(nodeB, idSetA) {\n if (nodeB.name != null && idSetA.has(nodeB.name)) {\n nodeB.disabled = true;\n } else {\n nodeB.disabled = false;\n }\n if (nodeB.children && Array.isArray(nodeB.children)) {\n nodeB.children.forEach(childNodeB => {\n markChecked(childNodeB, idSetA);\n });\n }\n }\n\n // 接口返回数据去重\n function removeNestedDuplicates(nodes, seenIds = new Set(), parentPath = []) {\n const result = [];\n\n nodes.forEach((node, index) => {\n const currentPath = [...parentPath, index]; // 记录当前节点的路径\n const nodeId = node.name;\n const type = node.type;\n // 同时去除 json 类型的字段\n if (!seenIds.has(nodeId) && type !== 'json') {\n seenIds.add(nodeId);\n const newNode = { ...node };\n\n if (newNode.children && Array.isArray(newNode.children)) {\n newNode.children = removeNestedDuplicates(newNode.children, seenIds, currentPath);\n }\n\n result.push(newNode);\n } else {\n // 如果需要处理子对象(即使父对象被忽略了),则递归调用\n if (node.children && Array.isArray(node.children)) {\n // 注意:这里我们不将子对象添加到结果数组中,只是处理它们以避免丢失新的 id\n removeNestedDuplicates(node.children, seenIds, currentPath);\n }\n }\n });\n\n return result;\n }\n\n const refreshData = () => {\n const allIdsInA = new Set();\n baseExpandedRowKeys.value.length = 0;\n baseDataSource.value.forEach((item: any) => {\n allIdsInA.add(item.field_name);\n });\n dataSource.value.forEach(nodeB => {\n markChecked(nodeB, allIdsInA);\n });\n dataSource.value = [].concat(dataSource.value);\n baseDataSource.value = [].concat(baseDataSource.value);\n };\n\n onMounted(async () => {\n window.addEventListener('resize', onresize);\n onresize();\n const res = cloneDeep(props.record) || [];\n res.forEach((item: any) => {\n if (!item.operator_list) {\n item.operator_list = [];\n }\n // Add dataIndex if it doesn't exist, using field_name as the key\n if (!item.dataIndex && item.field_name) {\n item.dataIndex = item.field_name;\n }\n });\n baseDataSource.value = res;\n console.log(baseDataSource.value);\n if (props.modelType) {\n const args = props.modelType.split('-');\n const url = `${args[0]}/obtain_${args[1]}_column_data`;\n const res = await getApiData({ org_id: current_org?.id }, url, false, {\n skip_error: true,\n });\n dataSource.value = removeNestedDuplicates(res || []);\n getFieldMap(dataSource.value);\n }\n\n refreshChangedFields();\n refreshData();\n });\n onUnmounted(() => {\n window.removeEventListener('resize', onresize);\n });\n const customCell = (obj: any) => {\n if (obj.record.disabled) {\n return { style: { background: '#cbcbcb' } };\n }\n };\n const baseRowSelection = reactive({\n type: 'checkbox',\n onChange: (selectedKeys: string[]) => {\n baseSelectedRowKeys.value = selectedKeys;\n },\n getCheckboxProps: (record: any) => ({\n disabled: record.children !== undefined,\n name: record.dataIndex,\n }),\n });\n const rowSelection = reactive({\n type: 'checkbox',\n onChange: (selectedKeys: string[]) => {\n selectedRowKeys.value = selectedKeys;\n },\n getCheckboxProps: (record: any) => ({\n disabled: record.disabled,\n name: record.name,\n }),\n });\n // 返回当前节点的父级节点\n const findParent = (data: any[], childKey: any) => {\n let foundParentKey: any;\n const searchParent = (id: any, keys: any[], childKeys: any) => {\n for (const key of keys) {\n if (key.dataIndex === childKeys) {\n foundParentKey = id;\n return foundParentKey;\n } else if (key.children && key.children.length > 0) {\n foundParentKey = searchParent(key.dataIndex, key.children, childKeys);\n if (foundParentKey !== undefined) return foundParentKey; // 如果找到,立即返回\n }\n }\n return undefined; // 如果没有找到\n };\n return searchParent(null, data, childKey);\n };\n const baseRowDragEnd = ({ record, insertToRowKey }) => {\n return new Promise((reslove, reject) => {\n const parentID = findParent(baseDataSource.value, record.dataIndex); // 拖拽节点的父级节点\n // 注意后面的判断不能使用绝对比较 === 或 !==,因为会出现 null 和 undefined 两种值\n if (parentID != null && insertToRowKey != null) {\n reslove(true);\n } else if (parentID == null && insertToRowKey == null) {\n reslove(true);\n } else {\n reject();\n }\n }).then(() => {\n setTimeout(() => {\n emitData();\n }, 200);\n });\n };\n const setDisabledGoLeft = (data: any) => {\n data.forEach(item => {\n if (baseSelectedRowKeys.value.indexOf(item.name) > -1) {\n item.disabled = false;\n }\n // 如果当前节点有 children,则递归调用函数\n if (item.children && Array.isArray(item.children)) {\n setDisabledGoLeft(item.children);\n }\n });\n };\n const toLeft = () => {\n const list = baseDataSource.value.filter((item1: any) => {\n return baseSelectedRowKeys.value.indexOf(item1.dataIndex) == -1;\n });\n\n setDisabledGoLeft(dataSource.value);\n baseSelectedRowKeys.value.length = 0;\n baseDataSource.value = [].concat(list);\n dataSource.value = [].concat(dataSource.value);\n emitData();\n refreshChangedFields();\n };\n const setGoRightSearch = (data: any) => {\n data.forEach(item => {\n if (selectedRowKeys.value.indexOf(item.name) > -1) {\n item.disabled = true;\n let obj: any = {};\n obj.field_name = item.name;\n obj.label = item.verbose_name;\n obj.dataIndex = item.name;\n obj.required_condition = item.required_condition;\n obj.allowClear = true;\n Object.assign(obj, item.advanced_search_component);\n if (item?.options && item.options.length > 0) {\n obj.options = item.options;\n obj.operator_list = ['eq', 'in', 'notin'];\n if (item.type === 'boolean') {\n obj.class_name = 'bool';\n } else {\n obj.class_name = item.type;\n }\n obj.format = 'choices';\n } else if (item.type == 'int') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'int';\n } else if (item.type == 'float') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'float';\n } else if (item.type == 'str') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'str';\n } else if (item.type == 'remote') {\n obj.format = 'remote';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'int';\n obj.postUrl = item.postUrl;\n } else if (item.type == 'datetime') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'datetime';\n } else if (item.type == 'date') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'date';\n } else if (item.type == 'time') {\n obj.format = 'input';\n obj.operator_list = modelOperator[item.type];\n obj.class_name = 'time';\n } else {\n obj.format = 'input';\n obj.operator_list = modelOperator['str'];\n obj.class_name = 'str';\n }\n baseDataSource.value.push(obj);\n }\n // 如果当前节点有 children,则递归调用函数\n if (item.children && Array.isArray(item.children)) {\n setGoRightSearch(item.children);\n }\n });\n };\n const toRight = () => {\n setGoRightSearch(dataSource.value);\n selectedRowKeys.value.length = 0;\n dataSource.value = [].concat(dataSource.value);\n baseDataSource.value = [].concat(baseDataSource.value);\n emitData();\n };\n const cancel = (key: any) => {\n delete open[key];\n };\n const handleDelete = (key: any) => {\n open[key] = key;\n };\n\n const deleteRecord = (key: any) => {\n delete open[key];\n let child: any = [];\n baseDataSource.value.forEach((item: any) => {\n if (key == item.dataIndex) {\n child = item.children;\n }\n });\n baseDataSource.value = baseDataSource.value.filter(item => item.dataIndex !== key);\n if (baseDataSource.value.length > 0) {\n baseDataSource.value[baseDataSource.value.length - 1].children.push(...child);\n }\n baseDataSource.value = [].concat(baseDataSource.value);\n emitData();\n };\n\n const changeBase = () => {\n baseDataSource.value = [].concat(baseDataSource.value);\n emitData();\n };\n const getType = (record: any) => {\n if (record?.children && record.children.length >= 0) {\n return [];\n } else if (record?.options && record.options.length > 0) {\n return [{ name: '下拉选框', value: 'select' }];\n }\n return modelTypeList[record.class_name] ? modelTypeList[record.class_name].type : [];\n };\n const changeOperatorList = (record: any) => {\n if (!record.operator_list.includes(record.default_operator)) {\n record.default_operator = null;\n }\n if (!record.default_operator) {\n record.default_operator = record.operator_list?.[0];\n }\n emitData();\n };\n const changeDefaultOperator = (record: any) => {\n emitData();\n };\n const getRawRecord = (dataSource: any[], recordIndexs: number[]) => {\n let currentSource: any = dataSource;\n recordIndexs.forEach(index => {\n if (!Array.isArray(currentSource) && currentSource.children) {\n currentSource = currentSource.children;\n }\n currentSource = currentSource[index];\n });\n return currentSource;\n };\n const getFieldConfig = (field: any, keys: Record<string, string>) => {\n const config: any = {};\n Object.keys(keys).forEach(key => {\n if (field[key] !== undefined) {\n config[keys[key]] = field[key];\n }\n });\n return config;\n };\n const getFieldMap = (dataSource: any) => {\n dataSource.forEach(item => {\n fieldMap.value[item.name] = item;\n if (Array.isArray(item.children)) {\n getFieldMap(item.children);\n }\n });\n };\n const compareField = (baseColumnRecord: any) => {\n const field = fieldMap.value[baseColumnRecord.field_name];\n if (field) {\n const keys = {\n options: 'options',\n required_condition: 'required_condition',\n };\n const data1 = getFieldConfig(field, keys);\n const keys2 = Object.values(keys).reduce((acc, key) => {\n acc[key] = key;\n return acc;\n }, {});\n const data2 = getFieldConfig(baseColumnRecord, keys2);\n const res = isEqual(data1, data2);\n if (!res) {\n console.log(`${baseColumnRecord.field_name} 字段配置不一致`, data1, data2);\n }\n return res;\n }\n return true;\n };\n const getChangedFields = (list: any[]) => {\n const changedFields: any = {};\n list.forEach(item => {\n if (!compareField(item)) {\n changedFields[item.field_name] = item;\n }\n const children = item.children || item.group;\n if (Array.isArray(children)) {\n Object.assign(changedFields, getChangedFields(children));\n }\n });\n return changedFields;\n };\n const refreshChangedFields = () => {\n changedFields.value = getChangedFields(baseDataSource.value);\n };\n const handleUpdateBaseColumn = (record: any) => {\n updateBaseColumn(record);\n emitData();\n refreshChangedFields();\n };\n const updateBaseColumn = (record: any) => {\n const field = fieldMap.value[record.field_name];\n if (field) {\n const keys = {\n options: 'options',\n required_condition: 'required_condition',\n };\n const data = getFieldConfig(field, keys);\n Object.assign(record, data);\n }\n };\n const updateAllBaseSearch = () => {\n Object.values(changedFields.value).forEach((item: any) => {\n updateBaseColumn(item);\n });\n emitData();\n refreshChangedFields();\n };\n return {\n selectedRowKeys,\n dataSource,\n columns,\n baseColumns,\n baseDataSource,\n open,\n rowSelection,\n baseRowSelection,\n baseSelectedRowKeys,\n baseExpandedRowKeys,\n emitData,\n customCell,\n toLeft,\n toRight,\n baseRowDragEnd,\n cancel,\n handleDelete,\n deleteRecord,\n changeBase,\n getType,\n changeOperatorList,\n changeDefaultOperator,\n changedFields,\n updateAllBaseSearch,\n handleUpdateBaseColumn,\n getRawRecord,\n height,\n fieldMap,\n };\n },\n});\n</script>\n\n<style lang=\"less\" scoped>\n.divHover {\n position: relative;\n\n .editable-cell-wrapper {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n padding-right: 25px;\n }\n\n .editable-cell-input {\n flex-grow: 1;\n }\n\n .editable-cell-check-icon {\n position: absolute;\n right: 0;\n width: 20px;\n cursor: pointer;\n }\n\n .display-cell-wrapper {\n padding: 5px 24px 5px 5px;\n width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .icon {\n position: absolute;\n right: 0;\n width: 20px;\n cursor: pointer;\n margin-top: 5px;\n display: none;\n }\n\n .icon1 {\n position: absolute;\n right: 20px;\n width: 20px;\n cursor: pointer;\n margin-top: 5px;\n display: none;\n }\n}\n\n.divHover:hover .icon {\n display: inline-block;\n}\n\n.divHover:hover .icon1 {\n display: inline-block;\n}\n\n.column-title-container {\n width: 100%;\n display: flex;\n height: 40px;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n gap: 10px;\n .column-title {\n font-size: 14px;\n font-weight: 600;\n }\n ::v-deep(.ant-alert) {\n padding: 0 10px;\n }\n}\n</style>\n","<template>\n <div class=\"config-sync\">\n <div class=\"sync-body\">\n <!-- 左:目标流程节点(流程组织 + 流程节点) -->\n <div class=\"sync-panel sync-panel-tree\">\n <div class=\"sync-panel-header\">\n <span class=\"sync-panel-title\">目标流程节点</span>\n <span class=\"sync-panel-tip\">\n 勾选组织/流程组织即选中其下全部流程节点;未保存页面配置的节点置灰不可选\n </span>\n </div>\n <a-spin :spinning=\"treeLoading\">\n <div class=\"sync-tree-wrap\">\n <a-tree\n v-if=\"treeData.length > 0\"\n checkable\n :selectable=\"false\"\n :show-line=\"{ showLeafIcon: false }\"\n :checked-keys=\"checkedKeys\"\n :expanded-keys=\"expandedKeys\"\n :tree-data=\"treeData\"\n @check=\"handleCheck\"\n @expand=\"handleExpand\"\n >\n <template #title=\"{ title, dataRef }\">\n <span>{{ title }}</span>\n <a-tooltip\n v-if=\"dataRef.unsaved\"\n :title=\"UNSAVED_HINT\"\n >\n <exclamation-circle-outlined\n class=\"sync-unsaved-icon\"\n @click.stop\n />\n </a-tooltip>\n </template>\n </a-tree>\n <a-empty\n v-else-if=\"!treeLoading\"\n description=\"没有可同步的流程节点\"\n />\n </div>\n </a-spin>\n </div>\n\n <!-- 右:同步项 -->\n <div class=\"sync-panel sync-panel-field\">\n <div class=\"sync-panel-header\">\n <span class=\"sync-panel-title\">同步项</span>\n <span class=\"sync-panel-tip\">勾选需要同步过去的配置块</span>\n </div>\n\n <div class=\"sync-source\">\n <div>来源:{{ tableTypeText }}「{{ dataSource?.title || '-' }}」</div>\n <div>\n 类型:{{ tableType }} 表格标识:\n <span :class=\"{ 'sync-error-text': !dataSource?.id }\">\n {{ dataSource?.id || '未设置' }}\n </span>\n </div>\n <div>\n 来源节点:\n <span :class=\"{ 'sync-error-text': !sourceInfo }\">\n {{\n sourceInfo\n ? `${sourceInfo.name}(组织 ${sourceInfo.org_id} / 节点 ${sourceInfo.node_id})`\n : '未识别,请先在左侧重新选择流程节点'\n }}\n </span>\n </div>\n </div>\n\n <div class=\"sync-section\">\n <div class=\"sync-section-title\">同步类型</div>\n <a-radio-group v-model:value=\"syncMode\">\n <a-radio value=\"standard\">标准同步</a-radio>\n <a-radio value=\"append\">自动追加配置</a-radio>\n </a-radio-group>\n <div class=\"sync-mode-tip\">{{ syncModeTip }}</div>\n </div>\n\n <div class=\"sync-section\">\n <div class=\"sync-section-title\">基础配置</div>\n <a-checkbox\n :checked=\"baseChecked\"\n :indeterminate=\"baseIndeterminate\"\n @update:checked=\"toggleBase\"\n >\n 随同步写入基础配置\n </a-checkbox>\n <div class=\"sync-mode-tip\">含:名称、是否为标准模型查询、列表URL、模型、查询参数</div>\n </div>\n\n <div class=\"sync-section\">\n <div class=\"sync-section-title\">表格配置块</div>\n <a-checkbox-group\n v-model:value=\"fields\"\n :options=\"tableFieldOptions\"\n class=\"sync-options\"\n />\n </div>\n\n <div class=\"sync-targets\">\n <div class=\"sync-targets-title\">已选目标:{{ targets.length }} 个节点</div>\n <div\n v-if=\"targets.length > 0\"\n class=\"sync-targets-list\"\n >\n <a-tag\n v-for=\"item in targets\"\n :key=\"item.key\"\n closable\n @close=\"removeTarget(item.key)\"\n >\n {{ item.org_name }} / {{ item.name }}\n </a-tag>\n </div>\n </div>\n\n <div class=\"sync-actions\">\n <a-button\n type=\"primary\"\n :loading=\"syncing\"\n :disabled=\"!canSync\"\n @click=\"handleSync\"\n >\n 同步\n </a-button>\n <span class=\"sync-actions-tip\">\n 同步只写入目标节点,当前节点不会被修改,同步后需在目标节点重新进入页面查看\n </span>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, onMounted, PropType, ref, watch } from 'vue';\nimport { message } from 'ant-design-vue';\nimport { getApiData, get_org_id } from '@/init-plugin';\nimport {\n buildSyncTableData,\n SYNC_BASE_FIELDS,\n SYNC_BASE_FIELD_TITLES,\n SYNC_MODE_TITLES,\n SYNC_OPTION_FIELDS,\n SYNC_OPTION_FIELD_TITLES,\n SyncMode,\n} from '../../utils';\nimport { useSettingsStateStore } from '../../store/settingsState';\n\n/** 目标流程节点:org_id + node_id 才是节点身份(FlowNode 分库后 id 会跨组织重复) */\n/** 必须导出:引用方组件(leftColumn.vue / tableConfig.vue)的默认导出类型引用了它,不导出会让那些文件产不出 .d.ts(TS4082) */\nexport interface SyncTargetItem {\n key: string;\n org_id: number;\n org_name: string;\n node_id: number;\n menu_flag: string;\n name: string;\n /** 页面配置是否保存过(PageSetting.content 非空对象);未保存的节点置灰禁选 */\n page_setting_saved: boolean;\n}\n\n/** 源流程节点(当前正在配置的节点),字段与目标一致 */\nexport interface SyncSourceItem {\n org_id: number;\n node_id: number;\n menu_flag: string;\n name: string;\n}\n\nconst TABLE_TYPE_TITLES: Record<string, string> = {\n tables: '左侧栏表格',\n data_list: '右侧栏表格',\n};\n\n/** 未保存页面配置的节点在树上的提示后缀(同步过去没有落点,置灰禁选) */\nconst UNSAVED_HINT = '未保存页面配置,需保存后才能同步';\n\nexport default defineComponent({\n name: 'configSync',\n props: {\n /** 当前正在配置的表格对象(tables 里的某一张表 / data_list 的那张表) */\n dataSource: {\n type: Object as PropType<any>,\n required: true,\n },\n /** 表格所在的配置块类型:tables(左侧栏) / data_list(右侧栏) */\n tableType: {\n type: String as PropType<'tables' | 'data_list'>,\n default: 'tables',\n },\n },\n setup(props) {\n const settingsState = useSettingsStateStore();\n\n const treeLoading = ref(false);\n const syncing = ref(false);\n const treeData = ref<any[]>([]);\n const checkedKeys = ref<string[]>([]);\n const expandedKeys = ref<string[]>([]);\n /** key → 目标节点,只有流程节点会进这里,勾选结果按它过滤 */\n const targetMap = ref<Record<string, SyncTargetItem>>({});\n\n /** 表格配置块逐项勾选;基础配置整体一个开关(不逐项选) */\n const tableFieldOptions = SYNC_OPTION_FIELDS.map(key => ({\n label: SYNC_OPTION_FIELD_TITLES[key] || key,\n value: key,\n }));\n // 默认全选:贴近旧行为(基础配置原来就是自动随附的),用户可整体取消\n const fields = ref<string[]>([...SYNC_BASE_FIELDS, ...SYNC_OPTION_FIELDS]);\n\n /** 基础配置统一开关:勾上 = 5 项全带上,取消 = 全不带 */\n const baseChecked = computed(() => SYNC_BASE_FIELDS.every(key => fields.value.includes(key)));\n const baseIndeterminate = computed(\n () => !baseChecked.value && SYNC_BASE_FIELDS.some(key => fields.value.includes(key)),\n );\n const toggleBase = (checked: any) => {\n if (checked) {\n fields.value = [...new Set([...fields.value, ...SYNC_BASE_FIELDS])];\n } else {\n fields.value = fields.value.filter(key => !SYNC_BASE_FIELDS.includes(key));\n }\n };\n\n /** 同步类型:standard = 目标没有该表格时忽略;append = 目标没有该表格时整表完整追加 */\n const syncMode = ref<SyncMode>('standard');\n const syncModeOptions: { label: string; value: SyncMode }[] = (\n Object.keys(SYNC_MODE_TITLES) as SyncMode[]\n ).map(value => ({ label: SYNC_MODE_TITLES[value], value }));\n const syncModeTip = computed(() =>\n syncMode.value === 'append'\n ? '目标节点没有该表格时,把该表的全部配置完整追加进去(未勾选的配置块也会一并写入)'\n : '目标节点没有该表格时,忽略这个同步项',\n );\n\n const tableTypeText = computed(() => {\n return TABLE_TYPE_TITLES[props.tableType] || props.tableType;\n });\n\n const targets = computed<SyncTargetItem[]>(() => {\n return checkedKeys.value\n .map(key => targetMap.value[key])\n .filter((item): item is SyncTargetItem => !!item);\n });\n\n /**\n * 源流程节点:界面上的配置是按节点(menu_flag)组织的,所以同步时要显式告诉\n * 服务端「这份配置属于哪个节点」。节点身份用 org_id + node_id ——\n * FlowNode 按组织分库,id 只在各分库内自增、跨组织会重复,单靠 id 定位不到节点。\n * 组织取当前登录组织(与请求拦截器自动注入的 org_id 同源)。\n */\n const resolveSource = (): SyncSourceItem | null => {\n const node = settingsState.selectNode;\n const orgId = get_org_id();\n if (!node?.id || !node?.state || !orgId) {\n return null;\n }\n return {\n org_id: Number(orgId),\n node_id: Number(node.id),\n menu_flag: node.state,\n name: node.name || node.state,\n };\n };\n const sourceInfo = computed<SyncSourceItem | null>(() => resolveSource());\n\n const canSync = computed(() => {\n return (\n !!props.dataSource?.id &&\n !!sourceInfo.value &&\n targets.value.length > 0 &&\n fields.value.length > 0\n );\n });\n\n /* 树改异步加载后拆成两套数据:组织层一次拉全(query_sync_org_list);\n 每个组织下的流程组织 + 流程节点按需加载(query_org_flow_tree)——\n 展开、勾选组织时才请求,加载一次后缓存。\n FlowOrg / FlowNode 的 id 都是各分库内自增,跨组织会重复,直接拿来当 key 会串节点,\n 因此统一用「类型 + 组织id + 自身id」组成全树唯一的 key;\n 同时把节点所属的 org_id / node_id 一起记下来,提交时按这一对回传后端。 */\n const orgListRaw = ref<any[]>([]);\n /** orgId → 该组织的流程组织+节点原始树(加载一次后缓存,切节点时重建不再请求) */\n const orgChildrenRaw = ref<Record<string, any[]>>({});\n /** 正在加载的组织 key(防并发重复请求) */\n const loadingOrgMap = ref<Record<string, boolean>>({});\n const currentNodeKey = ref<string>('');\n\n /** 归一化某个组织下的「流程组织 → 流程节点」子树(组织层不经过这里) */\n const normalizeOrgSubTree = (list: any[], orgId: string, orgName: string): any[] => {\n const result: any[] = [];\n for (const item of list || []) {\n const key = item.is_flow_node\n ? `flow_node_${orgId}_${item.id}`\n : `flow_org_${orgId}_${item.id}`;\n const isCurrentNode =\n !!item.is_flow_node &&\n item.menu_flag === settingsState.selectNode?.state &&\n // 判定「当前节点」也要带组织:流程节点 id 只在各分库内自增、跨组织会重复,\n // 只比 menu_flag 的话,别的组织里同标识的节点会被误当成当前节点\n `${item.org_id ?? orgId}` === `${get_org_id() ?? ''}`;\n if (isCurrentNode) {\n currentNodeKey.value = key;\n }\n if (item.is_flow_node && isCurrentNode) {\n // 当前节点直接不渲染(同步给自己没有意义,后端也会自动忽略),\n // 只记下 key,默认展开时用来定位\n continue;\n }\n const children = normalizeOrgSubTree(item.children || [], orgId, orgName);\n if (item.is_flow_node) {\n // 节点「从未保存过页面配置」(后端 PageSetting.content 是空对象)时,\n // 后端会带 page_setting_saved=false —— 这类节点同步过去没有落点,\n // 置灰禁选(disabled);提示文案挂在名称旁的感叹号图标 tooltip 上\n // (见模板 #title slot),不直接追加到名称里;老版本后端不回该字段时按已保存处理\n const saved = item.page_setting_saved !== false;\n const nodeItem: any = {\n key,\n title: item.name,\n selectable: false,\n unsaved: !saved,\n };\n if (!saved) {\n nodeItem.disabled = true;\n }\n // 流程节点也支持多级嵌套(FlowNode 自带 parent 层级),子流程节点\n // 已经在上面的递归里归一化并注册进 targetMap,这里必须一起挂上,\n // 否则二级及以下的子节点会被静默丢弃 —— 不显示也无法作为同步目标\n if (children.length > 0) {\n nodeItem.children = children;\n }\n result.push(nodeItem);\n targetMap.value[key] = {\n key,\n // 后端在流程节点上回了 org_id(分库内自增的 id 必须配组织才唯一),\n // 兜底用遍历下来的组织 id,避免后端版本较老时拿不到\n org_id: Number(item.org_id ?? orgId),\n org_name: orgName,\n node_id: Number(item.id),\n menu_flag: item.menu_flag,\n name: item.name,\n page_setting_saved: saved,\n };\n continue;\n }\n // 流程组织:勾选 = 选中其下全部流程节点(级联交给 a-tree,\n // handleCheck 只保留流程节点,发送时不会把流程组织发出去);\n // 底下已经没有可勾的节点了(比如只剩当前节点)就整棵剪掉\n if (children.length === 0) {\n continue;\n }\n result.push({ key, title: item.name, selectable: false, children });\n }\n return result;\n };\n /** 找到某节点的所有祖先 key(用于默认展开到当前节点) */\n const findAncestorKeys = (\n list: any[],\n key: string,\n ancestors: string[] = [],\n ): string[] | null => {\n for (const node of list) {\n if (node.key === key) {\n return ancestors;\n }\n if (node.children?.length) {\n const res = findAncestorKeys(node.children, key, [...ancestors, node.key]);\n if (res) {\n return res;\n }\n }\n }\n return null;\n };\n /** 收集树上某容器节点子树内全部「已保存」流程节点的 key;没找到该容器返回 null */\n const collectSavedKeysUnder = (list: any[], key: string): string[] | null => {\n for (const node of list) {\n if (node.key === key) {\n const found: string[] = [];\n const walk = (nodes: any[]) => {\n for (const item of nodes) {\n const target = targetMap.value[item.key];\n if (target?.page_setting_saved) {\n found.push(item.key);\n }\n if (item.children?.length) {\n walk(item.children);\n }\n }\n };\n walk(node.children || []);\n return found;\n }\n if (node.children?.length) {\n const res = collectSavedKeysUnder(node.children, key);\n if (res !== null) {\n return res;\n }\n }\n }\n return null;\n };\n\n /** 组织层 → 树节点;已加载的组织用缓存原始树归一化出子层,未加载的留空待异步展开 */\n const buildOrgTree = () => {\n targetMap.value = {};\n currentNodeKey.value = '';\n treeData.value = orgListRaw.value.map((item: any) => {\n const orgId = `${item.id}`.replace('org_', '');\n const key = `org_${orgId}`;\n const raw = orgChildrenRaw.value[orgId];\n const children = raw ? normalizeOrgSubTree(raw, orgId, item.name) : [];\n return {\n key,\n title: item.name,\n selectable: false,\n // 已加载且剪枝后没有可勾节点的组织显示为叶子(不出现空箭头);未加载保持可展开\n isLeaf: !!raw && children.length === 0,\n children,\n };\n });\n // targetMap 重建后,勾选里可能混入已不存在的 key(比如切换节点后原当前节点不再渲染)\n checkedKeys.value = checkedKeys.value.filter(key => !!targetMap.value[key]);\n };\n\n /** 异步加载某组织下的流程组织 + 流程节点(展开 / 勾选组织时触发,一次加载后缓存) */\n const loadOrgChildren = async (key: string) => {\n const orgId = key.replace('org_', '');\n if (orgChildrenRaw.value[orgId] || loadingOrgMap.value[key]) {\n return;\n }\n loadingOrgMap.value = { ...loadingOrgMap.value, [key]: true };\n try {\n const res = await getApiData({ org_id: orgId }, '/approve/query_org_flow_tree');\n orgChildrenRaw.value = { ...orgChildrenRaw.value, [orgId]: res?.data || [] };\n buildOrgTree();\n } catch (e: any) {\n message.error(e?.message || '加载该组织下的流程节点失败');\n } finally {\n const next = { ...loadingOrgMap.value };\n delete next[key];\n loadingOrgMap.value = next;\n }\n };\n\n const querySyncOrgList = async () => {\n treeLoading.value = true;\n try {\n // 只拉组织层(不碰各组织分库);子层按组织异步加载,见 loadOrgChildren\n const res = await getApiData({}, '/approve/query_sync_org_list');\n orgListRaw.value = res?.data || [];\n buildOrgTree();\n await applyDefaultSelection();\n } catch (e: any) {\n message.error(e?.message || '加载组织列表失败');\n } finally {\n treeLoading.value = false;\n }\n };\n\n /**\n * 默认展开并勾选「当前组织」——异步流程:先展开组织触发加载,\n * 加载完成后把该组织下所有已保存流程节点勾上(当前节点除外,它不渲染)。\n * 组织取当前登录组织,和 source 用同一个来源;拿不到组织时什么都不勾,\n * 反正 canSync 会拦住同步(不会出现「看起来选了、其实发不出去」)。\n */\n const applyDefaultSelection = async () => {\n const orgId = `${get_org_id() ?? ''}`;\n if (!orgId) {\n return;\n }\n const key = `org_${orgId}`;\n if (!orgListRaw.value.some(item => `${item.id}` === key)) {\n return;\n }\n expandedKeys.value = [...new Set([...expandedKeys.value, key])];\n await loadOrgChildren(key);\n // 未保存页面配置的节点不进默认勾选(树上已置灰禁选)\n const defaults = Object.values(targetMap.value).filter(\n item => `${item.org_id}` === orgId && item.page_setting_saved,\n );\n if (defaults.length > 0) {\n const extra = defaults.map(item => item.key);\n checkedKeys.value = [...new Set([...checkedKeys.value, ...extra])];\n // 展开到这些默认节点所在的流程组织,免得默认勾了一堆却看不见勾在哪\n const ancestors = new Set<string>(expandedKeys.value);\n for (const item of defaults) {\n for (const ancestor of findAncestorKeys(treeData.value, item.key) || []) {\n ancestors.add(ancestor);\n }\n }\n expandedKeys.value = [...ancestors];\n }\n };\n\n // 左侧切换流程节点时,当前节点标记与默认勾选都要跟着变\n // (用已缓存的组织原始树重建,不重新请求)\n watch(\n () => settingsState.selectNode?.state,\n () => {\n if (orgListRaw.value.length > 0) {\n buildOrgTree();\n }\n },\n );\n\n /** 每次 check 递增;异步级联回调只应用最新一次 check 的意图(防取消勾选后的竞态误勾) */\n let checkGeneration = 0;\n const handleCheck = (keys: any) => {\n const list: string[] = Array.isArray(keys) ? keys : keys?.checked || [];\n // checkable 树会把父节点(组织/流程组织)也算进 checkedKeys,这里只保留流程节点\n checkedKeys.value = list.filter(key => !!targetMap.value[key]);\n // 勾选尚未加载的组织:antd 的级联只作用于已渲染的 children,\n // 这里先异步加载该组织子树,加载完成后把新出现的已保存节点级联勾上\n const generation = ++checkGeneration;\n const pendingOrgKeys = list.filter(\n key => key.startsWith('org_') && !orgChildrenRaw.value[key.replace('org_', '')],\n );\n if (pendingOrgKeys.length === 0) {\n return;\n }\n void Promise.all(pendingOrgKeys.map(key => loadOrgChildren(key))).then(() => {\n if (generation !== checkGeneration) {\n return; // 加载期间用户又操作了勾选,放弃这次旧意图\n }\n const extra: string[] = [];\n for (const key of pendingOrgKeys) {\n // 只有该组织在勾选快照里仍然被勾着才级联(半选也算)\n if (!list.includes(key)) {\n continue;\n }\n const savedKeys = collectSavedKeysUnder(treeData.value, key) || [];\n extra.push(...savedKeys);\n }\n if (extra.length > 0) {\n checkedKeys.value = [...new Set([...checkedKeys.value, ...extra])];\n }\n });\n };\n const handleExpand = (keys: any) => {\n const list = Array.isArray(keys) ? keys : [];\n expandedKeys.value = list;\n // 展开组织 → 异步加载该组织下的流程组织 + 流程节点(已加载的跳过)\n for (const key of list) {\n if (key.startsWith('org_')) {\n void loadOrgChildren(key);\n }\n }\n };\n const removeTarget = (key: string) => {\n checkedKeys.value = checkedKeys.value.filter(item => item !== key);\n };\n\n const handleSync = async () => {\n if (!props.dataSource?.id) {\n message.warning('当前表格没有「表格标识」,请先在「基础属性」里设置后再同步');\n return;\n }\n const source = resolveSource();\n if (!source) {\n message.warning('未识别当前流程节点,请先在左侧重新选择流程节点');\n return;\n }\n if (targets.value.length === 0) {\n message.warning('请选择目标流程节点');\n return;\n }\n // 兜底拦截(树上已置灰禁选,正常走不到):目标里混进了未保存页面配置的节点\n const unsavedNames = targets.value\n .filter(item => !item.page_setting_saved)\n .map(item => item.name);\n if (unsavedNames.length > 0) {\n message.warning(`${unsavedNames.join('、')} 未保存页面配置,需保存后才能同步`);\n return;\n }\n if (fields.value.length === 0) {\n message.warning('请选择要同步的配置项');\n return;\n }\n // 前端先按 exportConfig 的规则处理配置(保留 code、剥离 action_code_id),\n // 服务端只负责按 type + table_id 合并进目标节点\n const {\n data,\n fields: effectiveFields,\n skipped,\n } = buildSyncTableData(props.dataSource, fields.value, syncMode.value);\n if (skipped.length > 0) {\n message.warning(\n `当前表格没有配置:${skipped\n .map(key => SYNC_OPTION_FIELD_TITLES[key] || SYNC_BASE_FIELD_TITLES[key] || key)\n .join('、')},已跳过`,\n );\n }\n if (effectiveFields.length === 0) {\n message.warning('所选配置项在当前表格中都不存在,没有可同步的内容');\n return;\n }\n syncing.value = true;\n try {\n const res = await getApiData(\n {\n // 源/目标都带 org_id + node_id:FlowNode 分库后 id 会跨组织重复,\n // 只有这一对才能唯一确定节点(服务端会按 org_id 回源分库核对)\n sync_mode: syncMode.value,\n source,\n targets: targets.value.map(item => ({\n org_id: item.org_id,\n node_id: item.node_id,\n menu_flag: item.menu_flag,\n name: item.name,\n })),\n items: [\n {\n type: props.tableType,\n table_id: props.dataSource.id,\n fields: effectiveFields,\n data,\n },\n ],\n },\n '/approve/sync_page_setting',\n );\n // getApiData 的响应拦截器返回的是响应体里的 result 字段,\n // 后端 get_result(..., {\"targets\": ...}) ⇒ 这里拿到的就是 { targets: [...] }\n const resultTargets: any[] = res?.targets || [];\n // 标准同步下,目标节点没有该表格的同步项会被后端忽略(回执里标 skipped)\n const ignoredNames = resultTargets\n .filter(item => (item.detail || []).some((detailItem: any) => detailItem.skipped))\n .map(item => item.name);\n if (ignoredNames.length > 0) {\n message.warning(`${ignoredNames.join('、')} 没有该表格,已忽略`);\n }\n const syncedCount = resultTargets.length - ignoredNames.length;\n if (syncedCount > 0) {\n message.success(`已同步到 ${syncedCount} 个流程节点`);\n }\n // 没有任何节点实际写入(targets 为空或全被忽略)时不提示成功:\n // 后端「没有可同步节点」走的是 success=false 报错路径,这里只会剩 warning\n } catch (e: any) {\n // 业务校验失败(success=false)响应拦截器已经提示过,这里不重复弹\n if (!e || e.success !== false) {\n message.error(e?.message || '同步失败');\n }\n } finally {\n syncing.value = false;\n }\n };\n\n onMounted(() => {\n querySyncOrgList();\n });\n\n return {\n treeLoading,\n syncing,\n treeData,\n checkedKeys,\n expandedKeys,\n tableFieldOptions,\n fields,\n baseChecked,\n baseIndeterminate,\n toggleBase,\n syncMode,\n syncModeOptions,\n syncModeTip,\n tableTypeText,\n sourceInfo,\n targets,\n canSync,\n handleCheck,\n handleExpand,\n removeTarget,\n handleSync,\n UNSAVED_HINT,\n };\n },\n});\n</script>\n\n<style scoped lang=\"less\">\n.config-sync {\n height: 100%;\n}\n\n.sync-body {\n display: flex;\n gap: 12px;\n align-items: stretch;\n}\n\n.sync-panel {\n border: 1px solid #f0f0f0;\n border-radius: 4px;\n padding: 8px 12px;\n min-width: 0;\n}\n\n.sync-panel-tree {\n flex: 0 0 320px;\n display: flex;\n flex-direction: column;\n}\n\n.sync-panel-field {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.sync-panel-header {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding-bottom: 8px;\n border-bottom: 1px solid #f0f0f0;\n margin-bottom: 8px;\n}\n\n.sync-panel-title {\n font-weight: 600;\n}\n\n.sync-panel-tip {\n font-size: 12px;\n color: #999;\n}\n\n.sync-tree-wrap {\n max-height: 460px;\n min-height: 200px;\n overflow: auto;\n}\n\n.sync-unsaved-icon {\n color: #faad14;\n margin-left: 4px;\n}\n\n.sync-source {\n font-size: 12px;\n color: #666;\n line-height: 20px;\n margin-bottom: 8px;\n word-break: break-all;\n}\n\n.sync-error-text {\n color: #ff4d4f;\n}\n\n.sync-options {\n display: flex;\n flex-direction: column;\n gap: 4px;\n\n :deep(.ant-checkbox-group-item) {\n margin-right: 0;\n }\n}\n\n.sync-section {\n margin-top: 12px;\n}\n\n.sync-section-title {\n font-weight: 600;\n color: #333;\n margin-bottom: 4px;\n}\n\n.sync-mode-tip {\n margin-top: 4px;\n font-size: 12px;\n color: #999;\n line-height: 18px;\n}\n\n.sync-targets {\n margin-top: 12px;\n font-size: 12px;\n}\n\n.sync-targets-title {\n color: #999;\n margin-bottom: 4px;\n}\n\n.sync-targets-list {\n max-height: 96px;\n overflow: auto;\n}\n\n.sync-actions {\n margin-top: 16px;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.sync-actions-tip {\n font-size: 12px;\n color: #999;\n}\n</style>\n","<template>\n <div class=\"config-sync\">\n <div class=\"sync-body\">\n <!-- 左:目标流程节点(流程组织 + 流程节点) -->\n <div class=\"sync-panel sync-panel-tree\">\n <div class=\"sync-panel-header\">\n <span class=\"sync-panel-title\">目标流程节点</span>\n <span class=\"sync-panel-tip\">\n 勾选组织/流程组织即选中其下全部流程节点;未保存页面配置的节点置灰不可选\n </span>\n </div>\n <a-spin :spinning=\"treeLoading\">\n <div class=\"sync-tree-wrap\">\n <a-tree\n v-if=\"treeData.length > 0\"\n checkable\n :selectable=\"false\"\n :show-line=\"{ showLeafIcon: false }\"\n :checked-keys=\"checkedKeys\"\n :expanded-keys=\"expandedKeys\"\n :tree-data=\"treeData\"\n @check=\"handleCheck\"\n @expand=\"handleExpand\"\n >\n <template #title=\"{ title, dataRef }\">\n <span>{{ title }}</span>\n <a-tooltip\n v-if=\"dataRef.unsaved\"\n :title=\"UNSAVED_HINT\"\n >\n <exclamation-circle-outlined\n class=\"sync-unsaved-icon\"\n @click.stop\n />\n </a-tooltip>\n </template>\n </a-tree>\n <a-empty\n v-else-if=\"!treeLoading\"\n description=\"没有可同步的流程节点\"\n />\n </div>\n </a-spin>\n </div>\n\n <!-- 右:同步项 -->\n <div class=\"sync-panel sync-panel-field\">\n <div class=\"sync-panel-header\">\n <span class=\"sync-panel-title\">同步项</span>\n <span class=\"sync-panel-tip\">勾选需要同步过去的配置块</span>\n </div>\n\n <div class=\"sync-source\">\n <div>来源:{{ tableTypeText }}「{{ dataSource?.title || '-' }}」</div>\n <div>\n 类型:{{ tableType }} 表格标识:\n <span :class=\"{ 'sync-error-text': !dataSource?.id }\">\n {{ dataSource?.id || '未设置' }}\n </span>\n </div>\n <div>\n 来源节点:\n <span :class=\"{ 'sync-error-text': !sourceInfo }\">\n {{\n sourceInfo\n ? `${sourceInfo.name}(组织 ${sourceInfo.org_id} / 节点 ${sourceInfo.node_id})`\n : '未识别,请先在左侧重新选择流程节点'\n }}\n </span>\n </div>\n </div>\n\n <div class=\"sync-section\">\n <div class=\"sync-section-title\">同步类型</div>\n <a-radio-group v-model:value=\"syncMode\">\n <a-radio value=\"standard\">标准同步</a-radio>\n <a-radio value=\"append\">自动追加配置</a-radio>\n </a-radio-group>\n <div class=\"sync-mode-tip\">{{ syncModeTip }}</div>\n </div>\n\n <div class=\"sync-section\">\n <div class=\"sync-section-title\">基础配置</div>\n <a-checkbox\n :checked=\"baseChecked\"\n :indeterminate=\"baseIndeterminate\"\n @update:checked=\"toggleBase\"\n >\n 随同步写入基础配置\n </a-checkbox>\n <div class=\"sync-mode-tip\">含:名称、是否为标准模型查询、列表URL、模型、查询参数</div>\n </div>\n\n <div class=\"sync-section\">\n <div class=\"sync-section-title\">表格配置块</div>\n <a-checkbox-group\n v-model:value=\"fields\"\n :options=\"tableFieldOptions\"\n class=\"sync-options\"\n />\n </div>\n\n <div class=\"sync-targets\">\n <div class=\"sync-targets-title\">已选目标:{{ targets.length }} 个节点</div>\n <div\n v-if=\"targets.length > 0\"\n class=\"sync-targets-list\"\n >\n <a-tag\n v-for=\"item in targets\"\n :key=\"item.key\"\n closable\n @close=\"removeTarget(item.key)\"\n >\n {{ item.org_name }} / {{ item.name }}\n </a-tag>\n </div>\n </div>\n\n <div class=\"sync-actions\">\n <a-button\n type=\"primary\"\n :loading=\"syncing\"\n :disabled=\"!canSync\"\n @click=\"handleSync\"\n >\n 同步\n </a-button>\n <span class=\"sync-actions-tip\">\n 同步只写入目标节点,当前节点不会被修改,同步后需在目标节点重新进入页面查看\n </span>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { computed, defineComponent, onMounted, PropType, ref, watch } from 'vue';\nimport { message } from 'ant-design-vue';\nimport { getApiData, get_org_id } from '@/init-plugin';\nimport {\n buildSyncTableData,\n SYNC_BASE_FIELDS,\n SYNC_BASE_FIELD_TITLES,\n SYNC_MODE_TITLES,\n SYNC_OPTION_FIELDS,\n SYNC_OPTION_FIELD_TITLES,\n SyncMode,\n} from '../../utils';\nimport { useSettingsStateStore } from '../../store/settingsState';\n\n/** 目标流程节点:org_id + node_id 才是节点身份(FlowNode 分库后 id 会跨组织重复) */\n/** 必须导出:引用方组件(leftColumn.vue / tableConfig.vue)的默认导出类型引用了它,不导出会让那些文件产不出 .d.ts(TS4082) */\nexport interface SyncTargetItem {\n key: string;\n org_id: number;\n org_name: string;\n node_id: number;\n menu_flag: string;\n name: string;\n /** 页面配置是否保存过(PageSetting.content 非空对象);未保存的节点置灰禁选 */\n page_setting_saved: boolean;\n}\n\n/** 源流程节点(当前正在配置的节点),字段与目标一致 */\nexport interface SyncSourceItem {\n org_id: number;\n node_id: number;\n menu_flag: string;\n name: string;\n}\n\nconst TABLE_TYPE_TITLES: Record<string, string> = {\n tables: '左侧栏表格',\n data_list: '右侧栏表格',\n};\n\n/** 未保存页面配置的节点在树上的提示后缀(同步过去没有落点,置灰禁选) */\nconst UNSAVED_HINT = '未保存页面配置,需保存后才能同步';\n\nexport default defineComponent({\n name: 'configSync',\n props: {\n /** 当前正在配置的表格对象(tables 里的某一张表 / data_list 的那张表) */\n dataSource: {\n type: Object as PropType<any>,\n required: true,\n },\n /** 表格所在的配置块类型:tables(左侧栏) / data_list(右侧栏) */\n tableType: {\n type: String as PropType<'tables' | 'data_list'>,\n default: 'tables',\n },\n },\n setup(props) {\n const settingsState = useSettingsStateStore();\n\n const treeLoading = ref(false);\n const syncing = ref(false);\n const treeData = ref<any[]>([]);\n const checkedKeys = ref<string[]>([]);\n const expandedKeys = ref<string[]>([]);\n /** key → 目标节点,只有流程节点会进这里,勾选结果按它过滤 */\n const targetMap = ref<Record<string, SyncTargetItem>>({});\n\n /** 表格配置块逐项勾选;基础配置整体一个开关(不逐项选) */\n const tableFieldOptions = SYNC_OPTION_FIELDS.map(key => ({\n label: SYNC_OPTION_FIELD_TITLES[key] || key,\n value: key,\n }));\n // 默认全选:贴近旧行为(基础配置原来就是自动随附的),用户可整体取消\n const fields = ref<string[]>([...SYNC_BASE_FIELDS, ...SYNC_OPTION_FIELDS]);\n\n /** 基础配置统一开关:勾上 = 5 项全带上,取消 = 全不带 */\n const baseChecked = computed(() => SYNC_BASE_FIELDS.every(key => fields.value.includes(key)));\n const baseIndeterminate = computed(\n () => !baseChecked.value && SYNC_BASE_FIELDS.some(key => fields.value.includes(key)),\n );\n const toggleBase = (checked: any) => {\n if (checked) {\n fields.value = [...new Set([...fields.value, ...SYNC_BASE_FIELDS])];\n } else {\n fields.value = fields.value.filter(key => !SYNC_BASE_FIELDS.includes(key));\n }\n };\n\n /** 同步类型:standard = 目标没有该表格时忽略;append = 目标没有该表格时整表完整追加 */\n const syncMode = ref<SyncMode>('standard');\n const syncModeOptions: { label: string; value: SyncMode }[] = (\n Object.keys(SYNC_MODE_TITLES) as SyncMode[]\n ).map(value => ({ label: SYNC_MODE_TITLES[value], value }));\n const syncModeTip = computed(() =>\n syncMode.value === 'append'\n ? '目标节点没有该表格时,把该表的全部配置完整追加进去(未勾选的配置块也会一并写入)'\n : '目标节点没有该表格时,忽略这个同步项',\n );\n\n const tableTypeText = computed(() => {\n return TABLE_TYPE_TITLES[props.tableType] || props.tableType;\n });\n\n const targets = computed<SyncTargetItem[]>(() => {\n return checkedKeys.value\n .map(key => targetMap.value[key])\n .filter((item): item is SyncTargetItem => !!item);\n });\n\n /**\n * 源流程节点:界面上的配置是按节点(menu_flag)组织的,所以同步时要显式告诉\n * 服务端「这份配置属于哪个节点」。节点身份用 org_id + node_id ——\n * FlowNode 按组织分库,id 只在各分库内自增、跨组织会重复,单靠 id 定位不到节点。\n * 组织取当前登录组织(与请求拦截器自动注入的 org_id 同源)。\n */\n const resolveSource = (): SyncSourceItem | null => {\n const node = settingsState.selectNode;\n const orgId = get_org_id();\n if (!node?.id || !node?.state || !orgId) {\n return null;\n }\n return {\n org_id: Number(orgId),\n node_id: Number(node.id),\n menu_flag: node.state,\n name: node.name || node.state,\n };\n };\n const sourceInfo = computed<SyncSourceItem | null>(() => resolveSource());\n\n const canSync = computed(() => {\n return (\n !!props.dataSource?.id &&\n !!sourceInfo.value &&\n targets.value.length > 0 &&\n fields.value.length > 0\n );\n });\n\n /* 树改异步加载后拆成两套数据:组织层一次拉全(query_sync_org_list);\n 每个组织下的流程组织 + 流程节点按需加载(query_org_flow_tree)——\n 展开、勾选组织时才请求,加载一次后缓存。\n FlowOrg / FlowNode 的 id 都是各分库内自增,跨组织会重复,直接拿来当 key 会串节点,\n 因此统一用「类型 + 组织id + 自身id」组成全树唯一的 key;\n 同时把节点所属的 org_id / node_id 一起记下来,提交时按这一对回传后端。 */\n const orgListRaw = ref<any[]>([]);\n /** orgId → 该组织的流程组织+节点原始树(加载一次后缓存,切节点时重建不再请求) */\n const orgChildrenRaw = ref<Record<string, any[]>>({});\n /** 正在加载的组织 key(防并发重复请求) */\n const loadingOrgMap = ref<Record<string, boolean>>({});\n const currentNodeKey = ref<string>('');\n\n /** 归一化某个组织下的「流程组织 → 流程节点」子树(组织层不经过这里) */\n const normalizeOrgSubTree = (list: any[], orgId: string, orgName: string): any[] => {\n const result: any[] = [];\n for (const item of list || []) {\n const key = item.is_flow_node\n ? `flow_node_${orgId}_${item.id}`\n : `flow_org_${orgId}_${item.id}`;\n const isCurrentNode =\n !!item.is_flow_node &&\n item.menu_flag === settingsState.selectNode?.state &&\n // 判定「当前节点」也要带组织:流程节点 id 只在各分库内自增、跨组织会重复,\n // 只比 menu_flag 的话,别的组织里同标识的节点会被误当成当前节点\n `${item.org_id ?? orgId}` === `${get_org_id() ?? ''}`;\n if (isCurrentNode) {\n currentNodeKey.value = key;\n }\n if (item.is_flow_node && isCurrentNode) {\n // 当前节点直接不渲染(同步给自己没有意义,后端也会自动忽略),\n // 只记下 key,默认展开时用来定位\n continue;\n }\n const children = normalizeOrgSubTree(item.children || [], orgId, orgName);\n if (item.is_flow_node) {\n // 节点「从未保存过页面配置」(后端 PageSetting.content 是空对象)时,\n // 后端会带 page_setting_saved=false —— 这类节点同步过去没有落点,\n // 置灰禁选(disabled);提示文案挂在名称旁的感叹号图标 tooltip 上\n // (见模板 #title slot),不直接追加到名称里;老版本后端不回该字段时按已保存处理\n const saved = item.page_setting_saved !== false;\n const nodeItem: any = {\n key,\n title: item.name,\n selectable: false,\n unsaved: !saved,\n };\n if (!saved) {\n nodeItem.disabled = true;\n }\n // 流程节点也支持多级嵌套(FlowNode 自带 parent 层级),子流程节点\n // 已经在上面的递归里归一化并注册进 targetMap,这里必须一起挂上,\n // 否则二级及以下的子节点会被静默丢弃 —— 不显示也无法作为同步目标\n if (children.length > 0) {\n nodeItem.children = children;\n }\n result.push(nodeItem);\n targetMap.value[key] = {\n key,\n // 后端在流程节点上回了 org_id(分库内自增的 id 必须配组织才唯一),\n // 兜底用遍历下来的组织 id,避免后端版本较老时拿不到\n org_id: Number(item.org_id ?? orgId),\n org_name: orgName,\n node_id: Number(item.id),\n menu_flag: item.menu_flag,\n name: item.name,\n page_setting_saved: saved,\n };\n continue;\n }\n // 流程组织:勾选 = 选中其下全部流程节点(级联交给 a-tree,\n // handleCheck 只保留流程节点,发送时不会把流程组织发出去);\n // 底下已经没有可勾的节点了(比如只剩当前节点)就整棵剪掉\n if (children.length === 0) {\n continue;\n }\n result.push({ key, title: item.name, selectable: false, children });\n }\n return result;\n };\n /** 找到某节点的所有祖先 key(用于默认展开到当前节点) */\n const findAncestorKeys = (\n list: any[],\n key: string,\n ancestors: string[] = [],\n ): string[] | null => {\n for (const node of list) {\n if (node.key === key) {\n return ancestors;\n }\n if (node.children?.length) {\n const res = findAncestorKeys(node.children, key, [...ancestors, node.key]);\n if (res) {\n return res;\n }\n }\n }\n return null;\n };\n /** 收集树上某容器节点子树内全部「已保存」流程节点的 key;没找到该容器返回 null */\n const collectSavedKeysUnder = (list: any[], key: string): string[] | null => {\n for (const node of list) {\n if (node.key === key) {\n const found: string[] = [];\n const walk = (nodes: any[]) => {\n for (const item of nodes) {\n const target = targetMap.value[item.key];\n if (target?.page_setting_saved) {\n found.push(item.key);\n }\n if (item.children?.length) {\n walk(item.children);\n }\n }\n };\n walk(node.children || []);\n return found;\n }\n if (node.children?.length) {\n const res = collectSavedKeysUnder(node.children, key);\n if (res !== null) {\n return res;\n }\n }\n }\n return null;\n };\n\n /** 组织层 → 树节点;已加载的组织用缓存原始树归一化出子层,未加载的留空待异步展开 */\n const buildOrgTree = () => {\n targetMap.value = {};\n currentNodeKey.value = '';\n treeData.value = orgListRaw.value.map((item: any) => {\n const orgId = `${item.id}`.replace('org_', '');\n const key = `org_${orgId}`;\n const raw = orgChildrenRaw.value[orgId];\n const children = raw ? normalizeOrgSubTree(raw, orgId, item.name) : [];\n return {\n key,\n title: item.name,\n selectable: false,\n // 已加载且剪枝后没有可勾节点的组织显示为叶子(不出现空箭头);未加载保持可展开\n isLeaf: !!raw && children.length === 0,\n children,\n };\n });\n // targetMap 重建后,勾选里可能混入已不存在的 key(比如切换节点后原当前节点不再渲染)\n checkedKeys.value = checkedKeys.value.filter(key => !!targetMap.value[key]);\n };\n\n /** 异步加载某组织下的流程组织 + 流程节点(展开 / 勾选组织时触发,一次加载后缓存) */\n const loadOrgChildren = async (key: string) => {\n const orgId = key.replace('org_', '');\n if (orgChildrenRaw.value[orgId] || loadingOrgMap.value[key]) {\n return;\n }\n loadingOrgMap.value = { ...loadingOrgMap.value, [key]: true };\n try {\n const res = await getApiData({ org_id: orgId }, '/approve/query_org_flow_tree');\n orgChildrenRaw.value = { ...orgChildrenRaw.value, [orgId]: res?.data || [] };\n buildOrgTree();\n } catch (e: any) {\n message.error(e?.message || '加载该组织下的流程节点失败');\n } finally {\n const next = { ...loadingOrgMap.value };\n delete next[key];\n loadingOrgMap.value = next;\n }\n };\n\n const querySyncOrgList = async () => {\n treeLoading.value = true;\n try {\n // 只拉组织层(不碰各组织分库);子层按组织异步加载,见 loadOrgChildren\n const res = await getApiData({}, '/approve/query_sync_org_list');\n orgListRaw.value = res?.data || [];\n buildOrgTree();\n await applyDefaultSelection();\n } catch (e: any) {\n message.error(e?.message || '加载组织列表失败');\n } finally {\n treeLoading.value = false;\n }\n };\n\n /**\n * 默认展开并勾选「当前组织」——异步流程:先展开组织触发加载,\n * 加载完成后把该组织下所有已保存流程节点勾上(当前节点除外,它不渲染)。\n * 组织取当前登录组织,和 source 用同一个来源;拿不到组织时什么都不勾,\n * 反正 canSync 会拦住同步(不会出现「看起来选了、其实发不出去」)。\n */\n const applyDefaultSelection = async () => {\n const orgId = `${get_org_id() ?? ''}`;\n if (!orgId) {\n return;\n }\n const key = `org_${orgId}`;\n if (!orgListRaw.value.some(item => `${item.id}` === key)) {\n return;\n }\n expandedKeys.value = [...new Set([...expandedKeys.value, key])];\n await loadOrgChildren(key);\n // 未保存页面配置的节点不进默认勾选(树上已置灰禁选)\n const defaults = Object.values(targetMap.value).filter(\n item => `${item.org_id}` === orgId && item.page_setting_saved,\n );\n if (defaults.length > 0) {\n const extra = defaults.map(item => item.key);\n checkedKeys.value = [...new Set([...checkedKeys.value, ...extra])];\n // 展开到这些默认节点所在的流程组织,免得默认勾了一堆却看不见勾在哪\n const ancestors = new Set<string>(expandedKeys.value);\n for (const item of defaults) {\n for (const ancestor of findAncestorKeys(treeData.value, item.key) || []) {\n ancestors.add(ancestor);\n }\n }\n expandedKeys.value = [...ancestors];\n }\n };\n\n // 左侧切换流程节点时,当前节点标记与默认勾选都要跟着变\n // (用已缓存的组织原始树重建,不重新请求)\n watch(\n () => settingsState.selectNode?.state,\n () => {\n if (orgListRaw.value.length > 0) {\n buildOrgTree();\n }\n },\n );\n\n /** 每次 check 递增;异步级联回调只应用最新一次 check 的意图(防取消勾选后的竞态误勾) */\n let checkGeneration = 0;\n const handleCheck = (keys: any) => {\n const list: string[] = Array.isArray(keys) ? keys : keys?.checked || [];\n // checkable 树会把父节点(组织/流程组织)也算进 checkedKeys,这里只保留流程节点\n checkedKeys.value = list.filter(key => !!targetMap.value[key]);\n // 勾选尚未加载的组织:antd 的级联只作用于已渲染的 children,\n // 这里先异步加载该组织子树,加载完成后把新出现的已保存节点级联勾上\n const generation = ++checkGeneration;\n const pendingOrgKeys = list.filter(\n key => key.startsWith('org_') && !orgChildrenRaw.value[key.replace('org_', '')],\n );\n if (pendingOrgKeys.length === 0) {\n return;\n }\n void Promise.all(pendingOrgKeys.map(key => loadOrgChildren(key))).then(() => {\n if (generation !== checkGeneration) {\n return; // 加载期间用户又操作了勾选,放弃这次旧意图\n }\n const extra: string[] = [];\n for (const key of pendingOrgKeys) {\n // 只有该组织在勾选快照里仍然被勾着才级联(半选也算)\n if (!list.includes(key)) {\n continue;\n }\n const savedKeys = collectSavedKeysUnder(treeData.value, key) || [];\n extra.push(...savedKeys);\n }\n if (extra.length > 0) {\n checkedKeys.value = [...new Set([...checkedKeys.value, ...extra])];\n }\n });\n };\n const handleExpand = (keys: any) => {\n const list = Array.isArray(keys) ? keys : [];\n expandedKeys.value = list;\n // 展开组织 → 异步加载该组织下的流程组织 + 流程节点(已加载的跳过)\n for (const key of list) {\n if (key.startsWith('org_')) {\n void loadOrgChildren(key);\n }\n }\n };\n const removeTarget = (key: string) => {\n checkedKeys.value = checkedKeys.value.filter(item => item !== key);\n };\n\n const handleSync = async () => {\n if (!props.dataSource?.id) {\n message.warning('当前表格没有「表格标识」,请先在「基础属性」里设置后再同步');\n return;\n }\n const source = resolveSource();\n if (!source) {\n message.warning('未识别当前流程节点,请先在左侧重新选择流程节点');\n return;\n }\n if (targets.value.length === 0) {\n message.warning('请选择目标流程节点');\n return;\n }\n // 兜底拦截(树上已置灰禁选,正常走不到):目标里混进了未保存页面配置的节点\n const unsavedNames = targets.value\n .filter(item => !item.page_setting_saved)\n .map(item => item.name);\n if (unsavedNames.length > 0) {\n message.warning(`${unsavedNames.join('、')} 未保存页面配置,需保存后才能同步`);\n return;\n }\n if (fields.value.length === 0) {\n message.warning('请选择要同步的配置项');\n return;\n }\n // 前端先按 exportConfig 的规则处理配置(保留 code、剥离 action_code_id),\n // 服务端只负责按 type + table_id 合并进目标节点\n const {\n data,\n fields: effectiveFields,\n skipped,\n } = buildSyncTableData(props.dataSource, fields.value, syncMode.value);\n if (skipped.length > 0) {\n message.warning(\n `当前表格没有配置:${skipped\n .map(key => SYNC_OPTION_FIELD_TITLES[key] || SYNC_BASE_FIELD_TITLES[key] || key)\n .join('、')},已跳过`,\n );\n }\n if (effectiveFields.length === 0) {\n message.warning('所选配置项在当前表格中都不存在,没有可同步的内容');\n return;\n }\n syncing.value = true;\n try {\n const res = await getApiData(\n {\n // 源/目标都带 org_id + node_id:FlowNode 分库后 id 会跨组织重复,\n // 只有这一对才能唯一确定节点(服务端会按 org_id 回源分库核对)\n sync_mode: syncMode.value,\n source,\n targets: targets.value.map(item => ({\n org_id: item.org_id,\n node_id: item.node_id,\n menu_flag: item.menu_flag,\n name: item.name,\n })),\n items: [\n {\n type: props.tableType,\n table_id: props.dataSource.id,\n fields: effectiveFields,\n data,\n },\n ],\n },\n '/approve/sync_page_setting',\n );\n // getApiData 的响应拦截器返回的是响应体里的 result 字段,\n // 后端 get_result(..., {\"targets\": ...}) ⇒ 这里拿到的就是 { targets: [...] }\n const resultTargets: any[] = res?.targets || [];\n // 标准同步下,目标节点没有该表格的同步项会被后端忽略(回执里标 skipped)\n const ignoredNames = resultTargets\n .filter(item => (item.detail || []).some((detailItem: any) => detailItem.skipped))\n .map(item => item.name);\n if (ignoredNames.length > 0) {\n message.warning(`${ignoredNames.join('、')} 没有该表格,已忽略`);\n }\n const syncedCount = resultTargets.length - ignoredNames.length;\n if (syncedCount > 0) {\n message.success(`已同步到 ${syncedCount} 个流程节点`);\n }\n // 没有任何节点实际写入(targets 为空或全被忽略)时不提示成功:\n // 后端「没有可同步节点」走的是 success=false 报错路径,这里只会剩 warning\n } catch (e: any) {\n // 业务校验失败(success=false)响应拦截器已经提示过,这里不重复弹\n if (!e || e.success !== false) {\n message.error(e?.message || '同步失败');\n }\n } finally {\n syncing.value = false;\n }\n };\n\n onMounted(() => {\n querySyncOrgList();\n });\n\n return {\n treeLoading,\n syncing,\n treeData,\n checkedKeys,\n expandedKeys,\n tableFieldOptions,\n fields,\n baseChecked,\n baseIndeterminate,\n toggleBase,\n syncMode,\n syncModeOptions,\n syncModeTip,\n tableTypeText,\n sourceInfo,\n targets,\n canSync,\n handleCheck,\n handleExpand,\n removeTarget,\n handleSync,\n UNSAVED_HINT,\n };\n },\n});\n</script>\n\n<style scoped lang=\"less\">\n.config-sync {\n height: 100%;\n}\n\n.sync-body {\n display: flex;\n gap: 12px;\n align-items: stretch;\n}\n\n.sync-panel {\n border: 1px solid #f0f0f0;\n border-radius: 4px;\n padding: 8px 12px;\n min-width: 0;\n}\n\n.sync-panel-tree {\n flex: 0 0 320px;\n display: flex;\n flex-direction: column;\n}\n\n.sync-panel-field {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.sync-panel-header {\n display: flex;\n align-items: baseline;\n gap: 8px;\n padding-bottom: 8px;\n border-bottom: 1px solid #f0f0f0;\n margin-bottom: 8px;\n}\n\n.sync-panel-title {\n font-weight: 600;\n}\n\n.sync-panel-tip {\n font-size: 12px;\n color: #999;\n}\n\n.sync-tree-wrap {\n max-height: 460px;\n min-height: 200px;\n overflow: auto;\n}\n\n.sync-unsaved-icon {\n color: #faad14;\n margin-left: 4px;\n}\n\n.sync-source {\n font-size: 12px;\n color: #666;\n line-height: 20px;\n margin-bottom: 8px;\n word-break: break-all;\n}\n\n.sync-error-text {\n color: #ff4d4f;\n}\n\n.sync-options {\n display: flex;\n flex-direction: column;\n gap: 4px;\n\n :deep(.ant-checkbox-group-item) {\n margin-right: 0;\n }\n}\n\n.sync-section {\n margin-top: 12px;\n}\n\n.sync-section-title {\n font-weight: 600;\n color: #333;\n margin-bottom: 4px;\n}\n\n.sync-mode-tip {\n margin-top: 4px;\n font-size: 12px;\n color: #999;\n line-height: 18px;\n}\n\n.sync-targets {\n margin-top: 12px;\n font-size: 12px;\n}\n\n.sync-targets-title {\n color: #999;\n margin-bottom: 4px;\n}\n\n.sync-targets-list {\n max-height: 96px;\n overflow: auto;\n}\n\n.sync-actions {\n margin-top: 16px;\n display: flex;\n align-items: center;\n gap: 12px;\n}\n\n.sync-actions-tip {\n font-size: 12px;\n color: #999;\n}\n</style>\n","<template>\n <div class=\"confirm-input-wrapper\">\n <template v-if=\"!isEditing\">\n <span class=\"display-span\">\n {{ value || '&nbsp;' }}\n </span>\n <edit-outlined\n class=\"edit-icon\"\n @click=\"handleEdit\"\n />\n </template>\n <template v-else>\n <a-input\n ref=\"inputRef\"\n v-model:value=\"editedValue\"\n size=\"small\"\n style=\"flex-grow: 1\"\n @pressEnter=\"handleConfirm\"\n />\n <check-outlined\n class=\"action-icon\"\n @click=\"handleConfirm\"\n />\n <close-outlined\n class=\"action-icon\"\n @click=\"handleCancel\"\n />\n </template>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, ref, nextTick, watch } from 'vue';\nimport { EditOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';\n\nexport default defineComponent({\n name: 'ConfirmInput',\n components: {\n EditOutlined,\n CheckOutlined,\n CloseOutlined,\n },\n props: {\n value: {\n type: String,\n required: true,\n },\n },\n emits: ['update:value', 'change'],\n setup(props, { emit }) {\n const isEditing = ref(false);\n const editedValue = ref('');\n const inputRef = ref<any>(null);\n\n const handleEdit = async () => {\n isEditing.value = true;\n editedValue.value = props.value;\n await nextTick();\n inputRef.value?.focus();\n };\n\n const handleConfirm = () => {\n if (editedValue.value !== props.value) {\n emit('update:value', editedValue.value);\n }\n isEditing.value = false;\n nextTick(() => {\n emit('change', editedValue.value);\n });\n };\n\n const handleCancel = () => {\n isEditing.value = false;\n };\n watch(\n () => props.value,\n () => {\n isEditing.value = false;\n },\n );\n\n return {\n isEditing,\n editedValue,\n inputRef,\n handleEdit,\n handleConfirm,\n handleCancel,\n };\n },\n});\n</script>\n\n<style scoped lang=\"less\">\n.confirm-input-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 7px;\n border: 1px solid transparent;\n border-radius: 4px;\n transition: border-color 0.3s;\n min-height: 32px;\n\n &:hover {\n border-color: #d9d9d9;\n .edit-icon {\n opacity: 1;\n }\n }\n}\n\n.display-span {\n cursor: text;\n flex-grow: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.edit-icon {\n cursor: pointer;\n color: #1890ff;\n opacity: 0;\n transition: opacity 0.3s;\n}\n\n.action-icon {\n cursor: pointer;\n color: #1890ff;\n}\n</style>\n","<template>\n <div class=\"confirm-input-wrapper\">\n <template v-if=\"!isEditing\">\n <span class=\"display-span\">\n {{ value || '&nbsp;' }}\n </span>\n <edit-outlined\n class=\"edit-icon\"\n @click=\"handleEdit\"\n />\n </template>\n <template v-else>\n <a-input\n ref=\"inputRef\"\n v-model:value=\"editedValue\"\n size=\"small\"\n style=\"flex-grow: 1\"\n @pressEnter=\"handleConfirm\"\n />\n <check-outlined\n class=\"action-icon\"\n @click=\"handleConfirm\"\n />\n <close-outlined\n class=\"action-icon\"\n @click=\"handleCancel\"\n />\n </template>\n </div>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, ref, nextTick, watch } from 'vue';\nimport { EditOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';\n\nexport default defineComponent({\n name: 'ConfirmInput',\n components: {\n EditOutlined,\n CheckOutlined,\n CloseOutlined,\n },\n props: {\n value: {\n type: String,\n required: true,\n },\n },\n emits: ['update:value', 'change'],\n setup(props, { emit }) {\n const isEditing = ref(false);\n const editedValue = ref('');\n const inputRef = ref<any>(null);\n\n const handleEdit = async () => {\n isEditing.value = true;\n editedValue.value = props.value;\n await nextTick();\n inputRef.value?.focus();\n };\n\n const handleConfirm = () => {\n if (editedValue.value !== props.value) {\n emit('update:value', editedValue.value);\n }\n isEditing.value = false;\n nextTick(() => {\n emit('change', editedValue.value);\n });\n };\n\n const handleCancel = () => {\n isEditing.value = false;\n };\n watch(\n () => props.value,\n () => {\n isEditing.value = false;\n },\n );\n\n return {\n isEditing,\n editedValue,\n inputRef,\n handleEdit,\n handleConfirm,\n handleCancel,\n };\n },\n});\n</script>\n\n<style scoped lang=\"less\">\n.confirm-input-wrapper {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 7px;\n border: 1px solid transparent;\n border-radius: 4px;\n transition: border-color 0.3s;\n min-height: 32px;\n\n &:hover {\n border-color: #d9d9d9;\n .edit-icon {\n opacity: 1;\n }\n }\n}\n\n.display-span {\n cursor: text;\n flex-grow: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.edit-icon {\n cursor: pointer;\n color: #1890ff;\n opacity: 0;\n transition: opacity 0.3s;\n}\n\n.action-icon {\n cursor: pointer;\n color: #1890ff;\n}\n</style>\n","<template>\n <a-tabs v-model:activeKey=\"activeKey\">\n <template #rightExtra>\n <a-space :size=\"20\">\n <a-button\n type=\"primary\"\n @click=\"openColumnConfig\"\n >\n 列配置\n </a-button>\n <a-button\n type=\"primary\"\n @click=\"openSearchConfig\"\n >\n 查询配置\n </a-button>\n </a-space>\n </template>\n <a-tab-pane\n key=\"1\"\n tab=\"基础属性\"\n >\n <a-form :model=\"dataSource\">\n <a-form-item label=\"表格标识\">\n <confirm-input\n :value=\"dataSource.id\"\n @update:value=\"handleChangeId\"\n ></confirm-input>\n </a-form-item>\n <a-form-item label=\"名称\">\n <a-input v-model:value=\"dataSource.title\" />\n </a-form-item>\n <a-form-item label=\"组名\">\n <a-input v-model:value=\"dataSource.group_title\" />\n </a-form-item>\n <a-form-item label=\"是否隐藏\">\n <a-switch v-model:checked=\"dataSource.is_hidden\" />\n </a-form-item>\n\n <a-form-item label=\"是否为标准模型查询\">\n <a-switch v-model:checked=\"dataSource.is_normal_model\" />\n </a-form-item>\n <a-form-item label=\"是否为多选\">\n <a-switch\n :checked=\"dataSource.rowSelectionType || 'checkbox'\"\n @update:checked=\"dataSource.rowSelectionType = $event as 'checkbox' | 'radio'\"\n checkedValue=\"checkbox\"\n un-checked-value=\"radio\"\n >\n <template #checkedChildren>多选</template>\n <template #unCheckedChildren>单选</template>\n </a-switch>\n </a-form-item>\n <a-form-item\n label=\"模型\"\n v-if=\"dataSource.is_normal_model\"\n >\n <a-select\n :value=\"dataSource.modelType\"\n @change=\"handleModelTypeChange\"\n show-search\n :options=\"modelTypeOptions\"\n :filter-option=\"filterOption\"\n ></a-select>\n </a-form-item>\n <a-form-item label=\"列表URL\">\n <a-input\n v-model:value=\"dataSource.list_url\"\n @change=\"handleListUrlChange\"\n v-if=\"!dataSource.is_normal_model\"\n />\n <span v-else>{{ dataSource.list_url }}</span>\n </a-form-item>\n <a-form-item label=\"查询参数\">\n <a-form-item label=\"我发起的审批\">\n <a-switch\n :checked=\"dataSource.query_params?.is_my_send\"\n @change=\"isMySendChange\"\n ></a-switch>\n </a-form-item>\n <json-text\n v-model:value=\"dataSource.query_params\"\n :rows=\"3\"\n />\n </a-form-item>\n </a-form>\n </a-tab-pane>\n\n <a-tab-pane\n key=\"3\"\n tab=\"基础查询条件\"\n >\n <BaseConditions\n :model-type=\"dataSource.modelType\"\n v-model:data-source=\"dataSource.base_conditions\"\n :formData=\"formData\"\n />\n </a-tab-pane>\n\n <a-tab-pane\n key=\"5\"\n tab=\"底部按钮配置\"\n >\n <ButtonConfig v-model:data-source=\"dataSource.actions\" />\n </a-tab-pane>\n <a-tab-pane\n key=\"6\"\n tab=\"行按钮配置\"\n >\n <ButtonConfig v-model:data-source=\"dataSource.row_actions\" />\n </a-tab-pane>\n <a-tab-pane\n key=\"7\"\n tab=\"配置同步\"\n >\n <config-sync\n v-if=\"activeKey === '7'\"\n :data-source=\"dataSource\"\n :table-type=\"tableType\"\n />\n </a-tab-pane>\n </a-tabs>\n\n <a-modal\n v-model:visible=\"showColumnConfig\"\n title=\"列配置\"\n width=\"100%\"\n wrap-class-name=\"full-modal\"\n :destroyOnClose=\"true\"\n @ok=\"confirmColumnConfig\"\n >\n <ColumnConfig\n v-if=\"showColumnConfig\"\n v-model:data-source=\"ColumnConfigDataSource\"\n :model-type=\"dataSource.modelType\"\n />\n </a-modal>\n\n <a-modal\n v-model:visible=\"showSearchConfig\"\n title=\"查询配置\"\n width=\"100%\"\n wrap-class-name=\"full-modal\"\n :destroyOnClose=\"true\"\n @ok=\"confirmSearchConfig\"\n >\n <search-config\n v-if=\"showSearchConfig\"\n v-model:record=\"SearchConfigDataSource\"\n :model-type=\"dataSource.modelType\"\n />\n </a-modal>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, onMounted, PropType, reactive, ref, watch } from 'vue';\nimport BaseConditions from './BaseConditions.vue';\nimport ButtonConfig from './ActionsConfig.vue';\nimport ColumnConfig from './ColumnConfig.vue';\nimport searchConfig from './searchConfig.vue';\nimport configSync from './configSync.vue';\nimport { TablesSection } from '../../typing';\nimport { getApiData } from '@/init-plugin';\nimport { cloneDeep } from 'lodash';\nimport confirmInput from './confirmInput.vue';\nimport JsonText from './JsonText.vue';\n\ntype Table = TablesSection['tables'][0];\n\nexport default defineComponent({\n name: 'tableConfig',\n components: {\n BaseConditions,\n ButtonConfig,\n ColumnConfig,\n searchConfig,\n configSync,\n confirmInput,\n JsonText,\n },\n props: {\n dataSource: {\n type: Object as PropType<Table>,\n required: true,\n },\n hasId: {\n type: Boolean,\n default: false,\n },\n /** 当前表格所属配置块类型:tables(左侧栏表格)/ data_list(右侧栏表格),「配置同步」用 */\n tableType: {\n type: String as PropType<'tables' | 'data_list'>,\n default: 'tables',\n },\n formData: {\n type: Object,\n default: () => ({}),\n },\n eventBus: {\n type: Object as any,\n },\n },\n emits: ['update:dataSource', 'change_id'],\n setup(props, { emit }) {\n const activeKey = ref('1');\n const showColumnConfig = ref(false);\n const ColumnConfigDataSource = ref(null);\n const showSearchConfig = ref(false);\n const SearchConfigDataSource = ref(null);\n\n const handleIsNormalModelChange = value => {\n props.dataSource.is_normal_model = value;\n };\n const modelTypeOptions = ref([]);\n const getAllModel = async () => {\n const url = 'sys/base_model_list';\n const res = await getApiData({}, url, false, { skip_error: true });\n const data = res?.data;\n if (data && data.length > 0) {\n modelTypeOptions.value = data.map(item => {\n return {\n label: `${item.name}(${item.value})`,\n value: item.value,\n };\n });\n }\n };\n const openColumnConfig = () => {\n ColumnConfigDataSource.value = cloneDeep(props.dataSource.columns || []);\n showColumnConfig.value = true;\n };\n const openSearchConfig = () => {\n SearchConfigDataSource.value = cloneDeep(props.dataSource.search_config || []);\n showSearchConfig.value = true;\n };\n\n const handleModelTypeChange = value => {\n props.dataSource.modelType = value;\n const args = value.split('-');\n const app = args[0];\n const model = args[1];\n props.dataSource.list_url = `/${app}/query_${model}_list`;\n props.dataSource.id = value;\n emit('change_id', props.dataSource);\n };\n const confirmColumnConfig = () => {\n emit('update:dataSource', { ...props.dataSource, columns: ColumnConfigDataSource.value });\n showColumnConfig.value = false;\n if (props.eventBus) {\n props.eventBus.emit('saveConfig');\n }\n };\n const confirmSearchConfig = () => {\n emit('update:dataSource', {\n ...props.dataSource,\n search_config: SearchConfigDataSource.value,\n });\n showSearchConfig.value = false;\n if (props.eventBus) {\n props.eventBus.emit('saveConfig');\n }\n };\n const handleListUrlChange = e => {\n props.dataSource.modelType = null;\n };\n\n // 自定义过滤函数,支持对value和label进行模糊搜索\n const filterOption = (input, option) => {\n const searchText = input.toLowerCase();\n const label = option.label?.toLowerCase() || '';\n const value = option.value?.toLowerCase() || '';\n return label.includes(searchText) || value.includes(searchText);\n };\n const isMySendChange = checked => {\n if (typeof props.dataSource.query_params !== 'object') {\n props.dataSource.query_params = {};\n }\n if (checked) {\n props.dataSource.query_params.is_my_send = true;\n } else {\n delete props.dataSource.query_params.is_my_send;\n }\n };\n const handleChangeId = value => {\n props.dataSource.id = value;\n emit('change_id', props.dataSource);\n };\n\n onMounted(() => {\n getAllModel();\n });\n\n return {\n activeKey,\n showColumnConfig,\n handleIsNormalModelChange,\n handleModelTypeChange,\n handleListUrlChange,\n modelTypeOptions,\n ColumnConfigDataSource,\n openColumnConfig,\n confirmColumnConfig,\n showSearchConfig,\n SearchConfigDataSource,\n openSearchConfig,\n confirmSearchConfig,\n filterOption,\n isMySendChange,\n handleChangeId,\n };\n },\n});\n</script>\n\n<style scoped lang=\"less\">\n.full-modal {\n .ant-modal {\n max-width: 100%;\n top: 0;\n padding-bottom: 0;\n margin: 0;\n }\n\n .ant-modal-content {\n display: flex;\n flex-direction: column;\n height: calc(100vh);\n }\n\n .ant-modal-body {\n flex: 1;\n }\n}\n</style>\n","<template>\n <a-tabs v-model:activeKey=\"activeKey\">\n <template #rightExtra>\n <a-space :size=\"20\">\n <a-button\n type=\"primary\"\n @click=\"openColumnConfig\"\n >\n 列配置\n </a-button>\n <a-button\n type=\"primary\"\n @click=\"openSearchConfig\"\n >\n 查询配置\n </a-button>\n </a-space>\n </template>\n <a-tab-pane\n key=\"1\"\n tab=\"基础属性\"\n >\n <a-form :model=\"dataSource\">\n <a-form-item label=\"表格标识\">\n <confirm-input\n :value=\"dataSource.id\"\n @update:value=\"handleChangeId\"\n ></confirm-input>\n </a-form-item>\n <a-form-item label=\"名称\">\n <a-input v-model:value=\"dataSource.title\" />\n </a-form-item>\n <a-form-item label=\"组名\">\n <a-input v-model:value=\"dataSource.group_title\" />\n </a-form-item>\n <a-form-item label=\"是否隐藏\">\n <a-switch v-model:checked=\"dataSource.is_hidden\" />\n </a-form-item>\n\n <a-form-item label=\"是否为标准模型查询\">\n <a-switch v-model:checked=\"dataSource.is_normal_model\" />\n </a-form-item>\n <a-form-item label=\"是否为多选\">\n <a-switch\n :checked=\"dataSource.rowSelectionType || 'checkbox'\"\n @update:checked=\"dataSource.rowSelectionType = $event as 'checkbox' | 'radio'\"\n checkedValue=\"checkbox\"\n un-checked-value=\"radio\"\n >\n <template #checkedChildren>多选</template>\n <template #unCheckedChildren>单选</template>\n </a-switch>\n </a-form-item>\n <a-form-item\n label=\"模型\"\n v-if=\"dataSource.is_normal_model\"\n >\n <a-select\n :value=\"dataSource.modelType\"\n @change=\"handleModelTypeChange\"\n show-search\n :options=\"modelTypeOptions\"\n :filter-option=\"filterOption\"\n ></a-select>\n </a-form-item>\n <a-form-item label=\"列表URL\">\n <a-input\n v-model:value=\"dataSource.list_url\"\n @change=\"handleListUrlChange\"\n v-if=\"!dataSource.is_normal_model\"\n />\n <span v-else>{{ dataSource.list_url }}</span>\n </a-form-item>\n <a-form-item label=\"查询参数\">\n <a-form-item label=\"我发起的审批\">\n <a-switch\n :checked=\"dataSource.query_params?.is_my_send\"\n @change=\"isMySendChange\"\n ></a-switch>\n </a-form-item>\n <json-text\n v-model:value=\"dataSource.query_params\"\n :rows=\"3\"\n />\n </a-form-item>\n </a-form>\n </a-tab-pane>\n\n <a-tab-pane\n key=\"3\"\n tab=\"基础查询条件\"\n >\n <BaseConditions\n :model-type=\"dataSource.modelType\"\n v-model:data-source=\"dataSource.base_conditions\"\n :formData=\"formData\"\n />\n </a-tab-pane>\n\n <a-tab-pane\n key=\"5\"\n tab=\"底部按钮配置\"\n >\n <ButtonConfig v-model:data-source=\"dataSource.actions\" />\n </a-tab-pane>\n <a-tab-pane\n key=\"6\"\n tab=\"行按钮配置\"\n >\n <ButtonConfig v-model:data-source=\"dataSource.row_actions\" />\n </a-tab-pane>\n <a-tab-pane\n key=\"7\"\n tab=\"配置同步\"\n >\n <config-sync\n v-if=\"activeKey === '7'\"\n :data-source=\"dataSource\"\n :table-type=\"tableType\"\n />\n </a-tab-pane>\n </a-tabs>\n\n <a-modal\n v-model:visible=\"showColumnConfig\"\n title=\"列配置\"\n width=\"100%\"\n wrap-class-name=\"full-modal\"\n :destroyOnClose=\"true\"\n @ok=\"confirmColumnConfig\"\n >\n <ColumnConfig\n v-if=\"showColumnConfig\"\n v-model:data-source=\"ColumnConfigDataSource\"\n :model-type=\"dataSource.modelType\"\n />\n </a-modal>\n\n <a-modal\n v-model:visible=\"showSearchConfig\"\n title=\"查询配置\"\n width=\"100%\"\n wrap-class-name=\"full-modal\"\n :destroyOnClose=\"true\"\n @ok=\"confirmSearchConfig\"\n >\n <search-config\n v-if=\"showSearchConfig\"\n v-model:record=\"SearchConfigDataSource\"\n :model-type=\"dataSource.modelType\"\n />\n </a-modal>\n</template>\n\n<script lang=\"ts\">\nimport { defineComponent, onMounted, PropType, reactive, ref, watch } from 'vue';\nimport BaseConditions from './BaseConditions.vue';\nimport ButtonConfig from './ActionsConfig.vue';\nimport ColumnConfig from './ColumnConfig.vue';\nimport searchConfig from './searchConfig.vue';\nimport configSync from './configSync.vue';\nimport { TablesSection } from '../../typing';\nimport { getApiData } from '@/init-plugin';\nimport { cloneDeep } from 'lodash';\nimport confirmInput from './confirmInput.vue';\nimport JsonText from './JsonText.vue';\n\ntype Table = TablesSection['tables'][0];\n\nexport default defineComponent({\n name: 'tableConfig',\n components: {\n BaseConditions,\n ButtonConfig,\n ColumnConfig,\n searchConfig,\n configSync,\n confirmInput,\n JsonText,\n },\n props: {\n dataSource: {\n type: Object as PropType<Table>,\n required: true,\n },\n hasId: {\n type: Boolean,\n default: false,\n },\n /** 当前表格所属配置块类型:tables(左侧栏表格)/ data_list(右侧栏表格),「配置同步」用 */\n tableType: {\n type: String as PropType<'tables' | 'data_list'>,\n default: 'tables',\n },\n formData: {\n type: Object,\n default: () => ({}),\n },\n eventBus: {\n type: Object as any,\n },\n },\n emits: ['update:dataSource', 'change_id'],\n setup(props, { emit }) {\n const activeKey = ref('1');\n const showColumnConfig = ref(false);\n const ColumnConfigDataSource = ref(null);\n const showSearchConfig = ref(false);\n const SearchConfigDataSource = ref(null);\n\n const handleIsNormalModelChange = value => {\n props.dataSource.is_normal_model = value;\n };\n const modelTypeOptions = ref([]);\n const getAllModel = async () => {\n const url = 'sys/base_model_list';\n const res = await getApiData({}, url, false, { skip_error: true });\n const data = res?.data;\n if (data && data.length > 0) {\n modelTypeOptions.value = data.map(item => {\n return {\n label: `${item.name}(${item.value})`,\n value: item.value,\n };\n });\n }\n };\n const openColumnConfig = () => {\n ColumnConfigDataSource.value = cloneDeep(props.dataSource.columns || []);\n showColumnConfig.value = true;\n };\n const openSearchConfig = () => {\n SearchConfigDataSource.value = cloneDeep(props.dataSource.search_config || []);\n showSearchConfig.value = true;\n };\n\n const handleModelTypeChange = value => {\n props.dataSource.modelType = value;\n const args = value.split('-');\n const app = args[0];\n const model = args[1];\n props.dataSource.list_url = `/${app}/query_${model}_list`;\n props.dataSource.id = value;\n emit('change_id', props.dataSource);\n };\n const confirmColumnConfig = () => {\n emit('update:dataSource', { ...props.dataSource, columns: ColumnConfigDataSource.value });\n showColumnConfig.value = false;\n if (props.eventBus) {\n props.eventBus.emit('saveConfig');\n }\n };\n const confirmSearchConfig = () => {\n emit('update:dataSource', {\n ...props.dataSource,\n search_config: SearchConfigDataSource.value,\n });\n showSearchConfig.value = false;\n if (props.eventBus) {\n props.eventBus.emit('saveConfig');\n }\n };\n const handleListUrlChange = e => {\n props.dataSource.modelType = null;\n };\n\n // 自定义过滤函数,支持对value和label进行模糊搜索\n const filterOption = (input, option) => {\n const searchText = input.toLowerCase();\n const label = option.label?.toLowerCase() || '';\n const value = option.value?.toLowerCase() || '';\n return label.includes(searchText) || value.includes(searchText);\n };\n const isMySendChange = checked => {\n if (typeof props.dataSource.query_params !== 'object') {\n props.dataSource.query_params = {};\n }\n if (checked) {\n props.dataSource.query_params.is_my_send = true;\n } else {\n delete props.dataSource.query_params.is_my_send;\n }\n };\n const handleChangeId = value => {\n props.dataSource.id = value;\n emit('change_id', props.dataSource);\n };\n\n onMounted(() => {\n getAllModel();\n });\n\n return {\n activeKey,\n showColumnConfig,\n handleIsNormalModelChange,\n handleModelTypeChange,\n handleListUrlChange,\n modelTypeOptions,\n ColumnConfigDataSource,\n openColumnConfig,\n confirmColumnConfig,\n showSearchConfig,\n SearchConfigDataSource,\n openSearchConfig,\n confirmSearchConfig,\n filterOption,\n isMySendChange,\n handleChangeId,\n };\n },\n});\n</script>\n\n<style scoped lang=\"less\">\n.full-modal {\n .ant-modal {\n max-width: 100%;\n top: 0;\n padding-bottom: 0;\n margin: 0;\n }\n\n .ant-modal-content {\n display: flex;\n flex-direction: column;\n height: calc(100vh);\n }\n\n .ant-modal-body {\n flex: 1;\n }\n}\n</style>\n"],"mappings":"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"}