From d0b4b582b99915548e5f0e6362c308307020fcf6 Mon Sep 17 00:00:00 2001 From: liwenxuan <1298531568@qq.com> Date: Fri, 6 Feb 2026 10:38:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=90=E8=A1=A8=E7=BB=93=E5=90=88=E5=85=B3?= =?UTF-8?q?=E8=81=94=E8=A1=A8=E5=8D=95=E9=A2=84=E5=A1=AB=E5=85=85=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DesignForm/assembly/index.ts | 6 +- .../DesignForm/formControlPropertiNew.vue | 561 ++++++++++++++++++ 2 files changed, 566 insertions(+), 1 deletion(-) diff --git a/src/components/DesignForm/assembly/index.ts b/src/components/DesignForm/assembly/index.ts index 098fc2d..36282c1 100644 --- a/src/components/DesignForm/assembly/index.ts +++ b/src/components/DesignForm/assembly/index.ts @@ -696,7 +696,11 @@ export default [ tableData: [], // 子表表格列表数据集合 control: { border: true, - defaultOne: '' + defaultOne: '', + preFill: { + asf: '', + ids: [] + } }, config: { addBtnText: '添加一行' diff --git a/src/components/DesignForm/formControlPropertiNew.vue b/src/components/DesignForm/formControlPropertiNew.vue index d7201fa..06b3610 100644 --- a/src/components/DesignForm/formControlPropertiNew.vue +++ b/src/components/DesignForm/formControlPropertiNew.vue @@ -14,6 +14,7 @@ import { ValidateTextTypes } from "@/components/DesignForm/validateText"; import { ElMessage } from "element-plus"; import { formatNumber } from "@/api/DesignForm/utils"; import { getOrgTreeList } from "@/api/hr/org/index"; +import AssociatedformsForCreate from "@/widget/associatedforms/associatedformsForCreate.vue"; import { orgInfo } from "@/api/hr/org/type"; @@ -831,6 +832,14 @@ const attrList = computed(() => { vIf: state.isSearch, vShow: ["table"], }, + { + label: "预填充设置", + value: config.table, + path: "config.table", + type: "table_preFill", + vIf: state.isSearch, + vShow: ["table"], + }, { label: "关联填充", value: config.orgCentent, @@ -2930,6 +2939,22 @@ const zdtcszTree = computed(()=>{ return [] } +})// + +const xTree = computed(()=>{ + if(datapropsformList&&datapropsformList.length==0){ + datapropsformList = JSON.parse(JSON.stringify(props.formList)) + } + + if(associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf && associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children && associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children.length>0){ + let datab = JSON.parse(JSON.stringify(associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children)) + let currentCompId = controlData.value.name + //console.log(currentCompId) + const treeC = mergeAndFilterAssociatedForms(datapropsformList, datab); + return treeC + }else{ + return [] + } }) // 使用 ref 替代 computed,使其可写 @@ -3154,6 +3179,408 @@ const handleDetermineZdtcszDialogFlag = () => { } +/** + * 合并两个组件树,仅保留type为table内的type为associatedForms的节点 + * @param {Array} treeA - 组件树a,包含表单结构信息 + * @param {Array} treeB - 组件树b,包含字段数据信息 + * @returns {Array} - 合并后仅包含table内的associatedForms节点的组件树c + */ +function mergeAndFilterAssociatedForms(treeA, treeB) { + // 构建b树的映射,key为name(从id中提取),value为b树节点 + const bMap = new Map(); + + // 从b树中提取通用的parentId(假设所有节点有相同的parentId) + let commonParentId = null; + + // 从id中提取name:formField:30540:upload1765154030446 -> upload1765154030446 + treeB.forEach(node => { + const id = node.id; + if (id) { + const parts = id.split(':'); + const name = parts[parts.length - 1]; // 取最后一部分作为name + bMap.set(name, node); + + // 设置通用的parentId + if (node.parentId && !commonParentId) { + commonParentId = node.parentId; + } + } + }); + + // 如果没有找到parentId,使用默认值 + if (!commonParentId) { + commonParentId = "formField:30540"; + } + + // 计数器 + let tableCount = 0; + let gridCount = 0; + let tabsCount = 0; + let divCount = 0; + let cardCount = 0; + + // 递归处理a树,仅保留table内的associatedForms节点 + function processANode(node, parentId = commonParentId, isInTable = false) { + // 获取当前节点的name和type + const nodeName = node.name; + const nodeType = node.type; + + // 如果是table类型 + if (nodeType === 'table') { + tableCount++; + + // 查找b树中对应的节点 + let bNode = null; + if (nodeName && bMap.has(nodeName)) { + bNode = bMap.get(nodeName); + bMap.delete(nodeName); + } + + let cNode; + const tableLabel = `子表${node.item?.label || nodeName || tableCount}`; + + if (bNode) { + // 复制b节点的所有属性 + cNode = { ...bNode }; + // 确保children数组存在 + if (!cNode.children) { + cNode.children = []; + } + // 使用b节点的parentId + cNode.parentId = bNode.parentId || parentId; + // 更新label + cNode.label = tableLabel; + // 更新treeAttrs.show + if (cNode.treeAttrs) { + cNode.treeAttrs.show = tableLabel; + } else { + cNode.treeAttrs = { show: tableLabel }; + } + // 保留treeA中的name属性 + cNode.name = nodeName; + } else { + // 如果b中不存在,则创建新节点 + const id = nodeName ? `${commonParentId}:${nodeName}` : null; + cNode = { + id: id, + name: nodeName, // 保留treeA中的name属性 + label: tableLabel, + parentId: parentId, + children: [], + value: id, + treeAttrs: { + show: tableLabel + }, + disabled: false, // table类型即使叶子节点也可以选择 + type: 'table' + }; + } + + // 处理子组件,只在table内寻找associatedForms类型 + let hasAssociatedForms = false; + if (node.list && Array.isArray(node.list)) { + const childNodes = []; + node.list.forEach(child => { + const processedChild = processANode(child, cNode.id, true); // 传递isInTable=true + if (processedChild) { + childNodes.push(processedChild); + hasAssociatedForms = true; + } + }); + cNode.children = childNodes; + } + + // 如果table没有associatedForms子节点,则不保留table节点 + if (!hasAssociatedForms) { + return null; + } + + return cNode; + } + + // 如果是associatedForms类型,且正在table内 + if (nodeType === 'associatedForms' && isInTable) { + // 查找b树中对应的节点 + let bNode = null; + if (nodeName && bMap.has(nodeName)) { + bNode = bMap.get(nodeName); + bMap.delete(nodeName); // 从map中删除,标记为已使用 + } + + let cNode; + if (bNode) { + // 复制b节点的所有属性 + cNode = { ...bNode }; + // 确保children数组存在 + if (!cNode.children) { + cNode.children = []; + } + // 使用b节点的parentId + cNode.parentId = bNode.parentId || parentId; + // 保留treeA中的name属性 + cNode.name = nodeName; + + // 保留a节点中的配置属性 + if (node.options && Array.isArray(node.options)) { + cNode.options = node.options; + } + + if (node.control) { + if (!cNode.control) { + cNode.control = {}; + } + // 保留control中的相关属性 + if (node.control.glxxsz) { + cNode.control.glxxsz = node.control.glxxsz; + } + if (node.control.modelValue !== undefined) { + cNode.control.modelValue = node.control.modelValue; + } + } + + if (node.config) { + cNode.config = node.config; + } + } else { + // 如果b中不存在,则创建新节点 + const label = node.item?.label || nodeName || 'associatedForms'; + const id = nodeName ? `${commonParentId}:${nodeName}` : null; + cNode = { + id: id, + name: nodeName, // 保留treeA中的name属性 + label: label, + parentId: parentId, + children: [], + value: id, + treeAttrs: { + show: label + }, + disabled: false, // associatedForms类型,叶子节点disabled为false + type: 'associatedForms' + }; + + // 保留a节点中的配置属性 + if (node.options && Array.isArray(node.options)) { + cNode.options = node.options; + } + + if (node.control) { + cNode.control = { ...node.control }; + } + + if (node.config) { + cNode.config = { ...node.config }; + } + } + + return cNode; + } + + // 其他容器类型,需要处理其子节点 + const containerTypes = ['card', 'flex', 'div', 'grid', 'tabs']; + if (containerTypes.includes(nodeType)) { + // 创建一个容器节点占位符 + let containerId; + let containerLabel; + + // 根据容器类型设置不同的id和label + switch(nodeType) { + case 'grid': + gridCount++; + containerId = `格栅布局${gridCount}`; + containerLabel = containerId; + break; + case 'tabs': + tabsCount++; + containerId = `标签页${tabsCount}`; + containerLabel = containerId; + break; + case 'div': + divCount++; + containerId = `容器${divCount}`; + containerLabel = containerId; + break; + case 'card': + cardCount++; + containerId = `卡片${cardCount}`; + containerLabel = containerId; + break; + case 'flex': + // 对于flex,查找b树中对应的节点 + let bNode = null; + if (nodeName && bMap.has(nodeName)) { + bNode = bMap.get(nodeName); + bMap.delete(nodeName); + } + + if (bNode) { + containerId = bNode.id || `${commonParentId}:${nodeName}`; + containerLabel = `弹性布局${bNode.label || nodeName}`; + } else { + containerId = `${commonParentId}:${nodeName}`; + containerLabel = `弹性布局${node.item?.label || nodeName}`; + } + break; + default: + containerId = `${commonParentId}:${nodeName}`; + containerLabel = node.item?.label || nodeName || nodeType; + } + + // 创建容器节点 + const containerNode = { + id: containerId, + name: nodeName, // 保留treeA中的name属性 + label: containerLabel, + parentId: parentId, + children: [], + value: containerId, + treeAttrs: { + show: containerLabel + }, + disabled: null, // 容器节点,非叶子节点 + type: nodeType + }; + + // 处理子组件 + let hasValidChildren = false; + + if (nodeType === 'card' || nodeType === 'flex' || nodeType === 'div') { + // 这些类型的子组件在list中 + if (node.list && Array.isArray(node.list)) { + const childNodes = []; + node.list.forEach(child => { + const processedChild = processANode(child, containerId, false); + if (processedChild) { + childNodes.push(processedChild); + hasValidChildren = true; + } + }); + containerNode.children = childNodes; + } + } else if (nodeType === 'grid' || nodeType === 'tabs') { + // 这些类型的子组件在columns.list中 + if (node.columns && Array.isArray(node.columns)) { + // 对于tabs,需要为每个column创建子节点 + if (nodeType === 'tabs') { + const tabNodes = []; + node.columns.forEach((column, index) => { + // 为每个column创建一个节点 + const columnId = `${containerId}:${column.label}`; + const columnNode = { + id: columnId, + name: column.label || `Tab${index + 1}`, // 使用column.label作为name + label: column.label || `Tab${index + 1}`, + parentId: containerId, + children: [], + value: columnId, + treeAttrs: { + show: column.label || `Tab${index + 1}` + }, + disabled: null, // 非叶子节点 + type: 'tab' + }; + + // 处理column中的子组件 + let columnHasValidChildren = false; + if (column.list && Array.isArray(column.list)) { + const childNodes = []; + column.list.forEach(child => { + const processedChild = processANode(child, columnId, false); + if (processedChild) { + childNodes.push(processedChild); + columnHasValidChildren = true; + hasValidChildren = true; + } + }); + columnNode.children = childNodes; + } + + // 如果column有子节点,添加到tabs节点下 + if (columnHasValidChildren) { + tabNodes.push(columnNode); + } + }); + containerNode.children = tabNodes; + } else { + // 对于grid,直接处理所有columns中的子组件 + const childNodes = []; + node.columns.forEach(column => { + if (column.list && Array.isArray(column.list)) { + column.list.forEach(child => { + const processedChild = processANode(child, containerId, false); + if (processedChild) { + childNodes.push(processedChild); + hasValidChildren = true; + } + }); + } + }); + containerNode.children = childNodes; + } + } + } + + // 如果容器没有有效的子节点,则返回null + if (!hasValidChildren) { + // 对于flex,即使没有子节点也要保留(因为可以选择) + if (nodeType === 'flex') { + containerNode.disabled = false; + return containerNode; + } + return null; + } + + // 设置容器节点的disabled属性 + // 对于flex,即使有子节点也可以选择,disabled为false + if (nodeType === 'flex') { + containerNode.disabled = false; + } else { + // 其他容器类型,有子节点为null,没有子节点为true + containerNode.disabled = null; + } + + return containerNode; + } + + // 其他非相关类型,直接返回null + return null; + } + + // 处理a树的所有根节点 + const cTree = []; + treeA.forEach(rootNode => { + const processedNode = processANode(rootNode); + if (processedNode) { + cTree.push(processedNode); + } + }); + + // 将b树中剩余的associatedForms元素(在a中不存在的)添加到c树中 + // 注意:我们不知道这些associatedForms节点是否在table内,所以只添加那些可能在table内的节点 + // 这里我们简单地从bMap中提取所有associatedForms类型的节点 + bMap.forEach((bNode, nodeName) => { + if (bNode.type === 'associatedForms') { + // 保留b节点的原始结构 + const newNode = { ...bNode }; + + // 确保children数组存在 + if (!newNode.children) { + newNode.children = []; + } + + // 设置disabled属性为false + newNode.disabled = false; + + // 添加name属性 + newNode.name = nodeName; + + cTree.push(newNode); + } + }); + + return cTree; +} + /** * 合并两个组件树,仅保留type为radio和select的节点,并过滤掉指定compId的节点,同时保留options属性 * @param {Array} treeA - 组件树a,包含表单结构信息 @@ -5187,6 +5614,80 @@ const requiredTextRadio = (val: any) => { } }; + + + +//子表预填充设置 liwenxuan 20260204 start +const preFillDialogFlag = ref(false) +function preFillDialogShow(){ + preFillDialogFlag.value = true +} + +function preFillDialogDetermine(){ + preFillDialogFlag.value = false +} + +const asfsCurrentTable = computed(()=>{ + let currentTable = [] + let count = 0 + let result = [] + xTree.value.forEach((element:any) => { + + if(getAfterLastColon(element.value) == controlData.value.name){ + currentTable.push(element) + count++ + } + }); + if(count>0){ + result = currentTable[0].children + }else{ + result = [] + } + + return result +}) + +const asfPropsData = computed(()=>{ + let result = {} + asfsCurrentTable.value.forEach((element:any) => { + if(element.id==controlData.value.control.preFill.asf){ + result = element + }else{ + result = {} + } + }); + return result +}) + +/** + * 提取字符串中最后一个英文冒号后的内容,无冒号则返回原字符串 + * @param {string} str - 输入的字符串 + * @returns {string} 最后一个冒号后的内容或原字符串 + */ +function getAfterLastColon(str:string) { + //console.log(str) + // 首先验证入参类型,确保是字符串(避免非字符串类型导致方法出错) + if (typeof str !== 'string') { + //console.warn('入参必须是字符串类型,当前已自动转为字符串'); + str = String(str); // 非字符串类型自动转为字符串 + } + + // 查找最后一个英文冒号的索引位置 + const lastColonIndex = str.lastIndexOf(':'); + + // 若未找到冒号(索引为 -1),或冒号在字符串最后一位(后面无内容),返回原字符串 + if (lastColonIndex === -1 || lastColonIndex === str.length - 1) { + return str; + } + + // 截取最后一个冒号后面的字符(索引+1 开始到字符串结尾) + return str.slice(lastColonIndex + 1); +} + +//子表预填充设置 liwenxuan 20260204 end + + + /** @ 作者: 秦东 @ 时间: 2024-08-14 13:21:43 @@ -6280,6 +6781,20 @@ const formatTooltip = (val: number) => { + + + + + 预填充设置 + + + @@ -8842,7 +9357,53 @@ const formatTooltip = (val: number) => { + + + + +{{ asfsCurrentTable }} +
+{{ controlData.control.preFill.asf }} +
+{{ asfPropsData }} + + +
+ 请选择关联表单 + +
+ + + + + +
+