From f94284193d6f0a27a402bbf861ef8edd842254d4 Mon Sep 17 00:00:00 2001 From: han2015 <1019850453@qq.com> Date: Thu, 13 Nov 2025 09:59:01 +0800 Subject: [PATCH 01/25] =?UTF-8?q?=E4=BA=91=E7=9B=98=EF=BC=9A=E6=89=93?= =?UTF-8?q?=E5=BC=80=E6=96=B0=E7=9B=AE=E5=BD=95=E8=A6=81=E9=87=8D=E7=BD=AE?= =?UTF-8?q?=E9=A1=B5=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/doc/manage.vue | 2 +- src/views/doc/space.vue | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/views/doc/manage.vue b/src/views/doc/manage.vue index 11cbe7a..ef58aa9 100644 --- a/src/views/doc/manage.vue +++ b/src/views/doc/manage.vue @@ -465,7 +465,7 @@ function onNodeClick(data:matterTree,node:TreeNode,self:any,env:any){ }else{ currentNode.value={uuid:"root"} } - + paginInfo.value.page=0, onLoadMatterList() return let _page: matterPage = { diff --git a/src/views/doc/space.vue b/src/views/doc/space.vue index 3893341..e1c44aa 100644 --- a/src/views/doc/space.vue +++ b/src/views/doc/space.vue @@ -192,7 +192,7 @@ function onLoadMatterList(name?:string){ if(name){ _page={ - pageSize: 50, + pageSize: 50, orderCreateTime: "DESC", orderDir: "DESC", deleted:false, @@ -340,6 +340,7 @@ function handleDoubleClick(row:matterInfo,ind?:number){ //2: 如果当前目录是当前空间根目录,没必要更新目录树 if(currentNode.value.puuid==row.uuid || row.uuid=="root") isNewNode=false currentNode.value=row + paginInfo.value.page=0, onLoadMatterList() /* 由于添加了父级树组件,breadcrumblis的功能废弃 From 16df952e63bd0792f396c21cfbecec0452762ab0 Mon Sep 17 00:00:00 2001 From: han2015 <1019850453@qq.com> Date: Thu, 4 Dec 2025 15:46:05 +0800 Subject: [PATCH 02/25] =?UTF-8?q?=E6=89=93=E5=8D=B0=EF=BC=9A=E5=88=86?= =?UTF-8?q?=E9=A1=B5=E5=8A=9F=E8=83=BD=E5=92=8C=E9=A1=B5=E7=9C=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DesignForm/app/index.vue | 92 +--- src/components/DesignForm/printHtmlRender.ts | 86 ++++ src/components/DesignForm/printHtmlRender.vue | 104 ++-- .../DesignForm/tableListPage/formPageCont.vue | 16 +- .../DesignForm/tableListPage/index.vue | 88 +--- src/main.ts | 6 +- .../appPage/appPageForm/printHtmlDom.js | 443 ++++++++++++++++-- .../appPage/appPageForm/printSetupPage2.vue | 4 +- 8 files changed, 577 insertions(+), 262 deletions(-) create mode 100644 src/components/DesignForm/printHtmlRender.ts diff --git a/src/components/DesignForm/app/index.vue b/src/components/DesignForm/app/index.vue index 19bbb36..1070dd7 100644 --- a/src/components/DesignForm/app/index.vue +++ b/src/components/DesignForm/app/index.vue @@ -43,10 +43,8 @@ import { } from "@/api/taskapi/management"; import { formatNumber } from "@/api/DesignForm/utils"; -import printHtmlRender from '../printHtmlRender.vue' -import {fieldTree,PageConfig} from '../printHtmlRender.vue' -import {printElement} from "@/views/sysworkflow/lowcodepage/appPage/appPageForm/printHtmlDom.js" -import {getPrintTemplate} from '@/api/DesignForm/requestapi' +import {printHtmlPage} from '../printHtmlRender.ts' + //引入组件 import FormPageCont from "@/components/DesignForm/tableListPage/formPageCont.vue"; import TableFlow from "@/views/sysworkflow/lowcodepage/pageFlow/appTableFlow.vue"; @@ -1556,90 +1554,6 @@ const lookPageInfo = (val: any) => { lookPageInfoIsShow.value = true; }; - -/****************表单打印功能************************/ -const printRenderMode = ref(false); -const printRenderTree: Ref = ref([]); -const printPage = async (row: any) => { - let data:any[]=[] - let _pageConfig:PageConfig - let title:string="表单"; - await getPrintTemplate({"versionid":props.versionid,"formkey":props.appKey}).then(resp=>{ - title=resp.data.title - if(resp.data.formtemplatejson!=""){ - data=JSON.parse(resp.data.formtemplatejson) - }else{ - alert("请先创建打印模板!") - return - } - - if(resp.data.pageconfigjson!=""){ - _pageConfig=JSON.parse(resp.data.pageconfigjson) - if(_pageConfig.founder!=""){ - _pageConfig.founder=row[_pageConfig.founder] - } - if(_pageConfig.founderTime!=""){ - _pageConfig.founderTime=row[_pageConfig.founderTime] - } - if(_pageConfig.deptOrg!=""){ - _pageConfig.deptOrg=row[_pageConfig.deptOrg] - } - if(_pageConfig.serialNumber!=""){ - _pageConfig.serialNumber=row[_pageConfig.serialNumber] - } - } - }) - - let qrstr=`https://wab.hxgk.group/#/form_table/taskInfo?id=${props.formId}&key=${props.appKey}& - formid=${props.versionid}&formKey=${props.formKey}&state=2` - data.forEach(node=>{ - deepLoopForm(node,row) - }) - printRenderTree.value=data - printRenderMode.value = true; - ElMessageBox({ - message: () => h('div',{style:{ width:'1200px',display:'flex','flex-direction':'column'}},[ - h(ElButton, { - type:"primary", - style: "margin:10px 10px 5px auto;", - onClick: () => { - printElement("printContainer") - } - },'打印表单'), - h('div',{style:{ border: '1px solid black', width: 'fit-content', margin: '5px','align-self': 'center'}},[ - h(printHtmlRender,{ - name:title, - fieldTree:printRenderTree.value, - pageConfig:_pageConfig, - qrcode:qrstr, - }) - ]) - ]), - showConfirmButton:false, - customStyle: { '--el-messagebox-width':'1300px',padding:'10px'}, - }).then(() => { - }) -}; - - -const deepLoopForm=(node:fieldTree, row: Record)=>{ - if(Array.isArray(node)){ - node.forEach(item=>{deepLoopForm(item,row)}) - return - } - - if(node.field!=""){ - let rnode:Object; - if (row.hasOwnProperty(node.field!)){// 有这个字段 - if (node.type=="table" || node.type=="tabs"){ - node.data=row[node.field!] - }else{ - node.field=row[node.field!] - } - } - } - } - /** @ 作者: 秦东 @ 时间: 2024-04-05 11:29:50 @@ -2300,7 +2214,7 @@ const isObject = (obj) => { placement="top-end" > = ref([]); +export const printHtmlPage = async (pformid:string,pappkey:string,pversionid:string,pformkey:string,row: any) => { + let data:any[]=[] + let _pageConfig:PageConfig + let title:string="表单"; + await getPrintTemplate({"versionid":pversionid,"formkey":pappkey}).then(resp=>{ + title=resp.data.title + if(resp.data.formtemplatejson!=""){ + data=JSON.parse(resp.data.formtemplatejson) + }else{ + alert("请先创建打印模板!") + return + } + + if(resp.data.pageconfigjson!=""){ + _pageConfig=JSON.parse(resp.data.pageconfigjson) + if(_pageConfig.founder!=""){ + _pageConfig.founder=row[_pageConfig.founder] + } + if(_pageConfig.founderTime!=""){ + _pageConfig.founderTime=row[_pageConfig.founderTime] + } + if(_pageConfig.deptOrg!=""){ + _pageConfig.deptOrg=row[_pageConfig.deptOrg] + } + _pageConfig.masters_key=row.masters_key + } + }) + + let qrstr=`https://wab.hxgk.group/#/form_table/taskInfo?id=${pformid}&key=${pappkey}& + formid=${pversionid}&formKey=${pformkey}&state=2` + data.forEach(node=>{ + deepLoopForm(node,row) + }) + printRenderTree.value=data + + ElMessageBox({ + message: () => h('div',{style:{ width:'1200px',display:'flex','flex-direction':'column'}},[ + h(ElButton, { + type:"primary", + style: "margin:10px 10px 5px auto;", + onClick: () => { + printWithSmartPagination("printPageAll",{ + paperSize: _pageConfig.pagesize, + landscape: _pageConfig.horizontal=="htal"? true : false , //默认竖向 + margin: 5, + }); + } + },'打印表单'), + h('div',{style:{ border: '1px solid black', width: 'fit-content', margin: '5px','align-self': 'center'}},[ + h(printHtmlRender,{ + name:title, + fieldTree:printRenderTree.value, + pageConfig:_pageConfig, + qrcode:qrstr, + }) + ]) + ]), + showConfirmButton:false, + customStyle: { '--el-messagebox-width':'1300px',padding:'10px'}, + }).then(() => { + }) +}; + +const deepLoopForm=(node:fieldTree, row: Record)=>{ + if(Array.isArray(node)){ + node.forEach(item=>{deepLoopForm(item,row)}) + return + } + + if(node.field!=""){ + let rnode:Object; + if (row.hasOwnProperty(node.field!)){// 有这个字段 + if (node.type=="table" || node.type=="tabs"){ + node.data=row[node.field!] + }else{ + node.field=row[node.field!] + } + } + } + } \ No newline at end of file diff --git a/src/components/DesignForm/printHtmlRender.vue b/src/components/DesignForm/printHtmlRender.vue index 0775997..0c8316b 100644 --- a/src/components/DesignForm/printHtmlRender.vue +++ b/src/components/DesignForm/printHtmlRender.vue @@ -23,7 +23,7 @@ export interface PageConfig{ founder:string; founderTime:string; deptOrg:string; - serialNumber:string; + masters_key:string; qrcode:boolean; } @@ -38,8 +38,14 @@ const qrdata=ref("") const userName=useUserStore().nickname; function parseDataPicker(val:string){ - if(val==""|| val.match(/[a-z]/) ) return val; - let str=new Date(parseInt(val)).toISOString() + let str:string; + if(typeof(val)=="number"){ + str=new Date(val).toISOString() + }else{ + if(val==""|| val.match(/[a-z]/) ) return val; + str=new Date(parseInt(val)).toISOString() + } + return str.slice(0,10)+" "+str.slice(11,16) } @@ -64,11 +70,12 @@ const generateQrCode= ()=>{ diff --git a/src/components/DesignForm/tableListPage/formPageCont.vue b/src/components/DesignForm/tableListPage/formPageCont.vue index 132a0c8..86d93dd 100644 --- a/src/components/DesignForm/tableListPage/formPageCont.vue +++ b/src/components/DesignForm/tableListPage/formPageCont.vue @@ -35,7 +35,7 @@ import { constFormBtnEvent, constFormProps } from "@/api/DesignForm/utils"; import RunFlowStep from "@/views/taskplatform/taskmanagement/runFlowStep.vue"; import { customerFormVersionCont } from "@/api/taskapi/types"; -import { stringify } from "uuid"; +import {printHtmlPage} from '../printHtmlRender.ts' const props = defineProps({ isShow: { @@ -59,7 +59,7 @@ const props = defineProps({ default() { return {}; }, - }, + } }); const formEl = ref(); const emits = defineEmits(["update:isShow", "getPageData", "optionsValue4Get4"]); @@ -221,6 +221,17 @@ interface TreeNode { children: TreeNode[]; } +function onPrintFrom(){ + printHtmlPage( + gainTaskFormInfoData.structure.cfid.toString(), + formState.formData.config.groupKey, + gainTaskFormInfoData.structure.id.toString(), + gainTaskFormInfoData.structure.tablekey, + gainTaskFormInfoData.tableData + ) +} + + function mapIdsToLabels(treeNodes: TreeNode[], ids1: string): string[] { /* console.log(treeNodes) console.log(ids1) */ @@ -526,6 +537,7 @@ function optionsValue3Get3(data: any, fieldName: any) { + 打印 { lookPageInfoIsShow.value = true; }; -/****************表单打印功能************************/ -const printRenderMode = ref(false); -const printRenderTree: Ref = ref([]); -const printPage = async (row: any) => { - let data:any[]=[] - let _pageConfig:PageConfig - let title:string="表单"; - //这里appkey和formkey 有些乱,由于历史遗留问题,不好区分。。。 - await getPrintTemplate({"versionid":props.versionid,"formkey":props.appKey}).then(resp=>{ - title=resp.data.title - if(resp.data.formtemplatejson!=""){ - data=JSON.parse(resp.data.formtemplatejson) - } - if(resp.data.pageconfigjson!=""){ - _pageConfig=JSON.parse(resp.data.pageconfigjson) - if(_pageConfig.founder!=""){ - _pageConfig.founder=row[_pageConfig.founder] - } - if(_pageConfig.founderTime!=""){ - _pageConfig.founderTime=row[_pageConfig.founderTime] - } - if(_pageConfig.deptOrg!=""){ - _pageConfig.deptOrg=row[_pageConfig.deptOrg] - } - if(_pageConfig.serialNumber!=""){ - _pageConfig.serialNumber=row[_pageConfig.serialNumber] - } - } - }) - - let qrstr=`https://wab.hxgk.group/#/form_table/taskInfo?id=${props.formId}&key=${props.appKey}& - formid=${props.versionid}&formKey=${props.formKey}&state=2` - - data.forEach(node=>{ - deepLoopForm(node,row) - }) - printRenderTree.value=data - printRenderMode.value = true; - ElMessageBox({ - message: () => h('div',{style:{ width:'1200px',display:'flex','flex-direction':'column'}},[ - h(ElButton, { - type:"primary", - style: "margin:10px 10px 5px auto;", - onClick: () => { - printElement("printContainer") - } - },'打印表单'), - h('div',{style:{ border: '1px solid black', width: 'fit-content', margin: '5px','align-self': 'center'}},[ - h(printHtmlRender,{ - name:title, - fieldTree:printRenderTree.value, - pageConfig:_pageConfig, - qrcode:qrstr - }) - ]) - ]), - showConfirmButton:false, - customStyle: { '--el-messagebox-width':'1300px',padding:'10px'}, - }).then(() => { - }) - -}; - - -const deepLoopForm=(node:fieldTree, row: Record)=>{ - if(Array.isArray(node)){ - node.forEach(item=>{deepLoopForm(item,row)}) - return - } - - if(node.field!=""){ - let rnode:Object; - if (row.hasOwnProperty(node.field!)){// 有这个字段 - if (node.type=="table" || node.type=="tabs"){ - node.data=row[node.field!] - }else{ - node.field=row[node.field!] - } - } - } - } - /** @ 作者: 秦东 @ 时间: 2024-04-05 11:29:50 @@ -2102,7 +2018,7 @@ const isObject = (obj: any) => { placement="top-end" > { + const childHeight = child.getBoundingClientRect().height; + const elementInfo = `${child.tagName}${child.className ? '.' + child.className.split(' ')[0] : ''}`; + const isTableContainer = child.querySelector('table'); + const remainingHeight = availableHeight - currentHeight; + + console.log(`\n🔍 [元素 ${index + 1}] ${elementInfo}`); + console.log(` 高度: ${childHeight.toFixed(1)}px, 累积: ${currentHeight.toFixed(1)}px`); + console.log(` 剩余空间: ${remainingHeight.toFixed(1)}px`); + + // ==================== 智能表格分割 ==================== + if (isTableContainer) { + if (currentHeight + childHeight <= availableHeight * 0.92) { + console.log(` ✅ 表格能完整放入当前页`); + currentPage.push(child.cloneNode(true)); + currentHeight += childHeight; + } else { + console.log(` ⚠️ 表格无法完整放入,剩余空间: ${remainingHeight.toFixed(1)}px`); + + // 对表格进行智能分页,第一页使用剩余空间 + const tablePages = paginateTableSmart(child, remainingHeight, availableHeight, options); + + if (tablePages.length > 0) { + // 第一页:部分表格 + 前面累积的普通元素(合并在一起) + const firstPageContent = tablePages[0]; + if (firstPageContent.length > 0) { + currentPage.push(...firstPageContent); + pages.push([...currentPage]); + console.log(` ✅ 创建混合页: ${currentPage.length}个元素 (含caption和部分表格)`); + } + + // 剩余的表格页(纯表格) + for (let i = 1; i < tablePages.length; i++) { + pages.push(tablePages[i]); + console.log(` 📊 添加纯表格页 ${i} (${tablePages[i].length}个元素)`); + } + } + + currentPage = []; + currentHeight = 0; + } + return; + } + // ============================================================ + + // 普通元素处理 + if (currentHeight + childHeight > availableHeight * 0.92) { + if (currentPage.length > 0) { + console.log(` 📄 推入当前页 (${currentPage.length}个元素)`); + pages.push([...currentPage]); + currentPage = []; + currentHeight = 0; + } + } + + currentPage.push(child.cloneNode(true)); + currentHeight += (childHeight+20); //20margin + }); + + // 处理剩余元素 + if (currentPage.length > 0) { + console.log(`\n📄 最后推入剩余元素 (${currentPage.length}个)`); + pages.push([...currentPage]); + } + + return pages; +} + +/** + * 智能表格分页函数(支持 caption) + * @returns {Array} 分页结果,每个元素是一个页面数组 + */ +function paginateTableSmart(tableContainer, firstPageHeight, subsequentPageHeight, options) { + const table = tableContainer.querySelector('table'); + const caption = table?.querySelector('caption'); // 获取 caption + const thead = table?.querySelector('thead'); + const tbody = table?.querySelector('tbody'); + + if (!thead || !tbody) { + console.warn('⚠️ 表格缺少 thead 或 tbody'); + return [[tableContainer.cloneNode(true)]]; + } + + const captionHeight = caption ? caption.getBoundingClientRect().height : 0; + const headerHeight = thead.getBoundingClientRect().height; + const rows = Array.from(tbody.querySelectorAll('tr')); + + console.log(` 📊 智能分页参数:`); + console.log(` caption高度: ${captionHeight.toFixed(1)}px, 表头高度: ${headerHeight.toFixed(1)}px`); + console.log(` 第一页可用: ${firstPageHeight.toFixed(1)}px, 后续页可用: ${subsequentPageHeight.toFixed(1)}px`); + console.log(` 总行数: ${rows.length}行`); + + // 如果整个表格能在第一页放下 + const totalTableHeight = tableContainer.getBoundingClientRect().height; + if (totalTableHeight <= firstPageHeight * 0.85) { + console.log(` ✅ 表格总高度 ${totalTableHeight.toFixed(1)}px 能放入第一页`); + // 包含 caption + return [[createTablePage(tableContainer, thead, rows, true)]]; + } + + const pages = []; + let currentRows = []; + let currentHeight = captionHeight + headerHeight; // 包含 caption 高度 + let isFirstPage = true; + + rows.forEach((row, rowIndex) => { + const rowHeight = row.getBoundingClientRect().height; + const pageHeight = isFirstPage ? firstPageHeight : subsequentPageHeight; + + // 检查是否需要分页 + if (currentHeight + rowHeight > pageHeight * 0.85 && currentRows.length > 0) { + // 创建当前页(只有第一页包含 caption) + pages.push([createTablePage(tableContainer, thead, currentRows, isFirstPage)]); + console.log(` 📊 分页${isFirstPage ? '(含caption)' : ''}: ${currentRows.length}行, ${currentHeight.toFixed(1)}px`); + + // 重置为新页面 + currentRows = [row]; + currentHeight = captionHeight + headerHeight + rowHeight; // 新页面也要包含 caption 高度 + isFirstPage = false; + } else { + currentRows.push(row); + currentHeight += rowHeight; + } + + // 最后一行 + if (rowIndex === rows.length - 1 && currentRows.length > 0) { + pages.push([createTablePage(tableContainer, thead, currentRows, isFirstPage)]); + console.log(` 📊 最后分页${isFirstPage ? '(含caption)' : ''}: ${currentRows.length}行, ${currentHeight.toFixed(1)}px`); + } + }); + + console.log(` 📊 表格总计分页: ${pages.length}页`); + return pages; +} + +/** + * 创建表格页 + * @param {boolean} includeCaption - 是否包含 caption(只有第一页为 true) + */ +function createTablePage(originalContainer, thead, rows, includeCaption = false) { + const container = originalContainer.cloneNode(false); + const table = document.createElement('table'); + + const originalTable = originalContainer.querySelector('table'); + table.className = originalTable.className; + table.style.cssText = originalTable.style.cssText; + + // 只在第一页添加 caption + if (includeCaption) { + const caption = originalTable.querySelector('caption'); + if (caption) { + table.appendChild(caption.cloneNode(true)); + } + } + + table.appendChild(thead.cloneNode(true)); + + const tbody = document.createElement('tbody'); + rows.forEach(row => tbody.appendChild(row.cloneNode(true))); + table.appendChild(tbody); + + container.appendChild(table); + return container; +} + +function buildPrintPages(pages, structure, options) { + const container = document.createElement('div'); + container.className = 'print-report-container'; + + pages.forEach((pageElements, index) => { + const pageDiv = document.createElement('div'); + pageDiv.className = 'print-page'; + + const elements = Array.isArray(pageElements) ? pageElements : [pageElements]; + + if (options.repeatLogo && structure.hasHeader) { + const headerClone = structure.header.cloneNode(true); + headerClone.style.borderBottom = '2px solid rgb(182, 181, 181)'; + headerClone.style.marginBottom = '20px'; + pageDiv.appendChild(headerClone); + } + + const contentDiv = document.createElement('div'); + contentDiv.className = 'print-page-content'; + + elements.forEach(el => { + if (el?.nodeType === Node.ELEMENT_NODE) { + contentDiv.appendChild(el); + } + }); + + pageDiv.appendChild(contentDiv); + + if (index === pages.length - 1 && structure.hasBottom) { + const bottomClone = structure.bottom.cloneNode(true); + bottomClone.style.marginTop = '30px'; + bottomClone.style.borderTop = '1px solid #ccc'; + bottomClone.style.paddingTop = '15px'; + pageDiv.appendChild(bottomClone); + } + + container.appendChild(pageDiv); + }); + + return container; +} + +function printViaIframe(content, options) { + const { paperSize, margin, debug,landscape } = options; const iframe = document.createElement('iframe'); iframe.style.display = 'none'; document.body.appendChild(iframe); - + const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; - // 写入样式和内容 + let originalStyles = ''; + try { + originalStyles = collectAllStyles(); + if (debug) console.log('📄 已收集原始样式,长度:', originalStyles.length); + } catch (e) { + console.warn('⚠️ 收集样式时出错:', e); + } + + const orientation = landscape ? 'landscape' : 'portrait'; + const printStyles = ` + @page { + size: ${paperSize.toLowerCase()} ${orientation}; + margin: ${margin}mm; + } + body { + margin: 0; + padding: 0; + font-family: "SimSun", "Microsoft YaHei", serif; + background: white; + } + .print-page { + page-break-after: always; + padding:${margin}mm ${margin+5}mm; + } + .print-page:last-child { + page-break-after: avoid; + } + table { + width: 100% !important; + border-collapse: collapse !important; + } + th, td { + border: 1px solid rgb(182, 181, 181) !important; + page-break-inside: avoid !important; + text-align: center; + line-height: 30px; + } + thead { + display: table-header-group !important; + } + table caption{ + text-align: center; + caption-side: top; + color: black; + font-weight: bold; + margin: 5px; + } + h3{ + width: 100%; + font-size: 25px; + font-weight: bold; + text-align:center; + } + + h5{ + font-weight: bold; + width: 100%; + margin: 5px; + text-align:center; + } + .page_brow{ + padding: 0 !important; + display: flex; + justify-content: space-between; + align-items: center; + } + `; + + const allStyles = `${originalStyles}\n${printStyles}`; + iframeDoc.open(); iframeDoc.write(` + - 打印 - + + 检验日报打印 + - - ${printContent.outerHTML} + + ${content.outerHTML} + ${debug ? '
🔍 调试模式
' : ''} `); iframeDoc.close(); - - // 触发打印 - iframe.onload = function() { - iframe.contentWindow.print(); - // 延迟移除iframe - setTimeout(() => document.body.removeChild(iframe), 1000); + + iframe.onload = () => { + setTimeout(() => { + if (debug) { + iframe.style.display = 'block'; + iframe.style.position = 'fixed'; + iframe.style.inset = '0'; + iframe.style.width = '100%'; + iframe.style.height = '100%'; + iframe.style.zIndex = '99999'; + iframe.style.background = 'white'; + console.log('✅ 调试模式已开启'); + } else { + iframe.contentWindow.print(); + setTimeout(() => iframe.remove(), 10000); + } + }, 300); }; +} + +function collectAllStyles() { + const styles = []; + Array.from(document.styleSheets).forEach(sheet => { + try { + const rules = Array.from(sheet.cssRules).map(r => r.cssText).join('\n'); + if (rules) styles.push(rules); + } catch (e) { + console.warn('⚠️ 无法读取样式表:', e); + } + }); + document.querySelectorAll('style').forEach(style => { + if (style.textContent) styles.push(style.textContent); + }); + return styles.join('\n'); } \ No newline at end of file diff --git a/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue b/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue index 8e6100e..dc4c1c5 100644 --- a/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue +++ b/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue @@ -27,7 +27,7 @@ const pageSize=ref('A4') const pageDret=ref('vtal') //定义页眉页脚的数据,取自pageConfig的字段 -const systemType:string[]=["founder","founderTime","deptOrg","serialNumber"] +const systemType:string[]=["founder","founderTime","deptOrg"] const props = defineProps({ @@ -321,7 +321,7 @@ const updateNodeData=(val:fieldTree,val2:boolean,val3:boolean)=>{ - + 业务字段 From 43a22239341755027cf61bad65ed57770250c6f0 Mon Sep 17 00:00:00 2001 From: han2015 <1019850453@qq.com> Date: Mon, 8 Dec 2025 13:54:13 +0800 Subject: [PATCH 03/25] =?UTF-8?q?=E6=89=93=E5=8D=B0=EF=BC=9A=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E4=BA=8C=E7=BB=B4=E7=A0=81=EF=BC=9B=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DesignForm/printHtmlRender.ts | 20 ++++++- src/components/DesignForm/printHtmlRender.vue | 54 ++++++++++++++++++- .../appPage/appPageForm/printSetupPage2.vue | 11 ++-- 3 files changed, 77 insertions(+), 8 deletions(-) diff --git a/src/components/DesignForm/printHtmlRender.ts b/src/components/DesignForm/printHtmlRender.ts index ec9a8a3..a09a6a2 100644 --- a/src/components/DesignForm/printHtmlRender.ts +++ b/src/components/DesignForm/printHtmlRender.ts @@ -2,12 +2,27 @@ import {getPrintTemplate} from '@/api/DesignForm/requestapi' import {fieldTree,PageConfig} from './printHtmlRender.vue' import printHtmlRender from './printHtmlRender.vue' import {printWithSmartPagination} from "@/views/sysworkflow/lowcodepage/appPage/appPageForm/printHtmlDom.js" +import {gainRunTaskFlow} from "@/api/DesignForm/requestapi"; const printRenderTree: Ref = ref([]); export const printHtmlPage = async (pformid:string,pappkey:string,pversionid:string,pformkey:string,row: any) => { let data:any[]=[] let _pageConfig:PageConfig let title:string="表单"; + let flowlist:any[]=[] + + if (row.flowIsOpens==1){ + let sendInfo = { + id:row.runFlowId + } + await gainRunTaskFlow(sendInfo) + .then((resp:any) =>{ + console.log("获取流程--werwerwerwer--->",resp.data) + flowlist=resp.data.flowList + }) + } + + await getPrintTemplate({"versionid":pversionid,"formkey":pappkey}).then(resp=>{ title=resp.data.title if(resp.data.formtemplatejson!=""){ @@ -32,8 +47,8 @@ export const printHtmlPage = async (pformid:string,pappkey:string,pversionid:str } }) - let qrstr=`https://wab.hxgk.group/#/form_table/taskInfo?id=${pformid}&key=${pappkey}& - formid=${pversionid}&formKey=${pformkey}&state=2` + let qrstr=`https://wab.hxgk.group/#/form_table/taskListPage?id=${pformid}&key=${pappkey}& + formid=${pversionid}&formKey=${pformkey}&qrDetailId=${row.id}` data.forEach(node=>{ deepLoopForm(node,row) }) @@ -57,6 +72,7 @@ export const printHtmlPage = async (pformid:string,pappkey:string,pversionid:str name:title, fieldTree:printRenderTree.value, pageConfig:_pageConfig, + flowList:flowlist, qrcode:qrstr, }) ]) diff --git a/src/components/DesignForm/printHtmlRender.vue b/src/components/DesignForm/printHtmlRender.vue index 0c8316b..b8ed07f 100644 --- a/src/components/DesignForm/printHtmlRender.vue +++ b/src/components/DesignForm/printHtmlRender.vue @@ -31,6 +31,7 @@ const props = withDefaults(defineProps<{ name:string, pageConfig:PageConfig, fieldTree:fieldTree[], + flowList:any[], qrcode?:string, }>(),{}) @@ -169,6 +170,50 @@ const generateQrCode= ()=>{
{{ group }}
+ + +
+ + + + + + + + + + + + + + +
审批流程
审批节点处理人操作记录
+
+
{{ generateQrCode() }}
@@ -208,9 +253,16 @@ div:empty { grid-template-columns: 1fr 1fr; border: 1px solid rgb(226, 226, 226); } +.operate_log{ + display: block; + border-bottom: 1px solid rgb(182, 181, 181); +} +td > .operate_log:last-child{ + border-bottom: none; +} h3{ width: 100%; - font-size: 25px; + font-size: 22px; font-weight: bold; } diff --git a/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue b/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue index dc4c1c5..0cfa39b 100644 --- a/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue +++ b/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue @@ -342,7 +342,7 @@ const updateNodeData=(val:fieldTree,val2:boolean,val3:boolean)=>{
-
+
@@ -354,17 +354,18 @@ const updateNodeData=(val:fieldTree,val2:boolean,val3:boolean)=>{
-
- +
+
- + From da461afa888769574c4083bb51b709d2b39192f5 Mon Sep 17 00:00:00 2001 From: liwenxuan <1298531568@qq.com> Date: Mon, 15 Dec 2025 11:11:01 +0800 Subject: [PATCH 10/25] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E9=A1=B5=E5=88=A0=E9=99=A4bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DesignForm/formControlPropertiNew.vue | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/DesignForm/formControlPropertiNew.vue b/src/components/DesignForm/formControlPropertiNew.vue index 2b81063..8853b90 100644 --- a/src/components/DesignForm/formControlPropertiNew.vue +++ b/src/components/DesignForm/formControlPropertiNew.vue @@ -1562,7 +1562,10 @@ const delSelectOption = (index: number, type?: string) => { } //liwenxuan 20240508 checkbox 删除选项时提醒 end if (type === "tabs") { - controlData.value.columns.splice(index, 1); + controlData.value.columns = controlData.value.columns.filter(item => { + //console.log(item.label); + return item.label !== index; // 保留不等于index的项 + }); } else { controlData.value.options.splice(index, 1); } @@ -6036,7 +6039,7 @@ const formatTooltip = (val: number) => { From 32eb542f94f460a9f13cfcab3187af6cd936a225 Mon Sep 17 00:00:00 2001 From: liwenxuan <1298531568@qq.com> Date: Mon, 15 Dec 2025 15:55:19 +0800 Subject: [PATCH 11/25] =?UTF-8?q?=E9=80=89=E9=A1=B9=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E5=AF=BC=E5=85=A5,=E6=8C=89=E9=92=AE=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DesignForm/formControlPropertiNew.vue | 55 +++++++++++++++---- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/src/components/DesignForm/formControlPropertiNew.vue b/src/components/DesignForm/formControlPropertiNew.vue index 8853b90..2c80d32 100644 --- a/src/components/DesignForm/formControlPropertiNew.vue +++ b/src/components/DesignForm/formControlPropertiNew.vue @@ -2838,8 +2838,7 @@ function getAssociatedFormsCurrentFieldTree1() { // 初始选项数据 const options = ref([]) -// 选中的值 -const selectedValues = ref(["1", "3"]) + // 弹窗显示状态 const dialogVisible = ref(false) @@ -2883,10 +2882,30 @@ const saveChanges = () => { // 清空编辑文本 editText.value = '' - console.log('选项已更新:', { - options: options.value, - selected: selectedValues.value - }) + + controlData.value.options = mergeArrays(controlData.value.options,options.value) + options.value = [] +} + + +function mergeArrays(a, b) { + // 1. 找出a中的最大value(转为数字比较) + let maxValue = 0; + a.forEach(item => { + const numValue = parseInt(item.value, 10); + if (numValue > maxValue) { + maxValue = numValue; + } + }); + + // 2. 创建b的副本并重新赋值value,从maxValue+1开始递增 + const newB = b.map((item, index) => ({ + ...item, + value: String(maxValue + 1 + index) + })); + + // 3. 合并数组,a在前,新的b在后 + return [...a, ...newB]; } //选项批量编辑 liwenxuan 20251212 end @@ -6100,7 +6119,7 @@ const formatTooltip = (val: number) => {
-
+
{{ controlData.type === "cascader" ? "编辑" : "新增" }} - - - - 批量编辑 + + 批量导入 +
+ 关联选项设置 +
+
+ 关联选项设置 +
+
+ 关联选项设置 +
+ @@ -8242,105 +8248,4 @@ li::before { } -.batch-edit-demo { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; - max-width: 600px; - margin: 20px auto; - padding: 20px; -} - -.display-mode { - border: 1px solid #DCDFE6; - border-radius: 4px; - padding: 20px; - margin-bottom: 20px; -} - -.display-mode h4 { - margin-top: 0; - margin-bottom: 15px; - color: #303133; -} - -.edit-header { - margin-bottom: 20px; -} - -.edit-title { - display: block; - font-weight: 500; - font-size: 14px; - color: #303133; - margin-bottom: 4px; -} - -.edit-hint { - font-size: 12px; - color: #909399; -} - -.textarea-container { - margin-bottom: 10px; -} - -.action-bar { - margin-top: 20px; - display: flex; - justify-content: flex-end; -} - -.el-checkbox { - display: block; - margin-bottom: 8px; -} - -.el-checkbox:last-child { - margin-bottom: 0; -} - -.dialog-content { - padding: 10px 0; -} - -:deep(.el-dialog__header) { - margin-right: 0; - padding-bottom: 10px; - border-bottom: 1px solid #F0F0F0; -} - -:deep(.el-dialog__title) { - font-size: 16px; - font-weight: 500; - color: #303133; -} - -:deep(.el-dialog__footer) { - padding-top: 20px; - border-top: 1px solid #F0F0F0; -} - -:deep(.el-textarea__inner) { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; - line-height: 1.5; - padding: 12px; -} - -.status-info { - padding: 15px; - background-color: #f5f7fa; - border-radius: 4px; - border: 1px solid #e4e7ed; -} - -.status-info h4 { - margin-top: 0; - margin-bottom: 10px; - color: #303133; -} - -.status-info p { - margin: 5px 0; - font-size: 14px; - color: #606266; -} From 087e03a697d378e20c77da46fb03eab00d7675f8 Mon Sep 17 00:00:00 2001 From: han2015 <1019850453@qq.com> Date: Tue, 16 Dec 2025 09:19:36 +0800 Subject: [PATCH 13/25] =?UTF-8?q?=E4=BA=91=E7=9B=98=EF=BC=9A=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0AI=E6=96=87=E6=A1=A3=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/doc/space.ts | 11 +++++++++++ src/views/doc/space.vue | 19 ++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/api/doc/space.ts b/src/api/doc/space.ts index 45a52ef..3c8297f 100644 --- a/src/api/doc/space.ts +++ b/src/api/doc/space.ts @@ -119,6 +119,17 @@ export function doAiTraining(_url:string,data?: any){ data: data }); } +//文档删除 +export function doAiDocDels(_url:string,data?: any){ + return request({ + url: '/aibot'+_url, + method: 'post', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + data: data + }); +} export interface aiChatData{ inputs:object; diff --git a/src/views/doc/space.vue b/src/views/doc/space.vue index f7e3e6f..e311744 100644 --- a/src/views/doc/space.vue +++ b/src/views/doc/space.vue @@ -10,7 +10,7 @@ import sharePermission from './sharePermission.vue'; import spacePermission from './spacePermission.vue'; import { matterPage,matterInfo,matterTree,doFileUpload,matterPermit} from "@/api/doc/type" import { doAccessManage,getSpaceMatterList,doCreateSpaceDir,doDelSpaceMatter, - doAiTraining ,spaceMatterRename} from "@/api/doc/space" + doAiTraining,doAiDocDels,spaceMatterRename} from "@/api/doc/space" import { h } from 'vue' import { Delete, @@ -159,6 +159,7 @@ function onDelMatter(row:matterInfo){ currentNode.value.uuid = row.puuid ?? "" onLoadMatterList() }) + handleAiDelete(row) }) } } @@ -530,6 +531,22 @@ function handleAiUpload(info:matterInfo){ } } +function handleAiDelete(info:matterInfo){ + //只有当前路径是智能体,删除才会同步大模型 + if (info.path?.startsWith(currentAgent.value.path)){ + doAiDocDels(`/agents/${currentAgent.value.uuid}/deldoc`,{ + "name":info.name, + "path":info.path, + }).then(resp=>{ + ElMessage({ + message: '已成功删除', + type: 'error', + plain: true, + }) + }) + } +} + //------------------------------------------------- //-------------------edit & preive file for space--------------------- From ce740bf805613a3ab1f0831f2e531469c7d83c7f Mon Sep 17 00:00:00 2001 From: han2015 <1019850453@qq.com> Date: Wed, 17 Dec 2025 10:02:39 +0800 Subject: [PATCH 14/25] =?UTF-8?q?=E6=89=93=E5=8D=B0=EF=BC=9A=E5=A4=84?= =?UTF-8?q?=E7=90=86select=E5=92=8Ccheckbox=E7=BB=84=E4=BB=B6=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DesignForm/printHtmlRender.ts | 44 +++++++++++++------ src/components/DesignForm/printHtmlRender.vue | 37 ++++++++-------- src/store/modules/orgMember.ts | 3 +- .../appPage/appPageForm/printSetupPage2.vue | 23 +++++++++- 4 files changed, 73 insertions(+), 34 deletions(-) diff --git a/src/components/DesignForm/printHtmlRender.ts b/src/components/DesignForm/printHtmlRender.ts index 246d7cd..9c0c126 100644 --- a/src/components/DesignForm/printHtmlRender.ts +++ b/src/components/DesignForm/printHtmlRender.ts @@ -24,12 +24,13 @@ export const printHtmlPage = async (pformid:string,pappkey:string,pversionid:str }) } - + let noTemplate:boolean=false await getPrintTemplate({"versionid":pversionid,"formkey":pappkey}).then(resp=>{ title=resp.data.title if(resp.data.formtemplatejson!=""){ data=JSON.parse(resp.data.formtemplatejson) }else{ + noTemplate=true alert("请先创建打印模板!") return } @@ -49,6 +50,8 @@ export const printHtmlPage = async (pformid:string,pappkey:string,pversionid:str } }) + if(noTemplate) return; + let qrstr=`https://wab.hxgk.group/#/form_table/taskListPage?id=${pformid}&key=${pappkey}& formid=${pversionid}&formKey=${pformkey}&qrDetailId=${row.id}` data.forEach(node=>{ @@ -85,20 +88,33 @@ export const printHtmlPage = async (pformid:string,pappkey:string,pversionid:str }) }; -const deepLoopForm=(node:fieldTree, row: Record)=>{ - if(Array.isArray(node)){ - node.forEach(item=>{deepLoopForm(item,row)}) - return - } +const deepLoopForm=(node:fieldTree, row: Record)=>{ + if(Array.isArray(node)){ + node.forEach(item=>{deepLoopForm(item,row)}) + return + } + + if(node.type=="tabs"&&node.child){ + node.child?.forEach(item=>{deepLoopForm(item,row)}) + return + } - if(node.field!=""){ - let rnode:Object; - if (row.hasOwnProperty(node.field!)){// 有这个字段 - if (node.type=="table" || node.type=="tabs"){ - node.data=row[node.field!] - }else{ - node.field=row[node.field!] + if(node.field!=""){ + if (row.hasOwnProperty(node.field!)){// 有这个字段 + if (node.type=="table"){ + node.data=row[node.field!] + }else if(node.type=="select"||node.type=="checkbox"){ + const val=row[node.field!] + node.field="" + for(let op of node.options!){ + if(op.value==val){ + node.field=op.label + break; + } } + }else{ + node.field=row[node.field!] } } - } \ No newline at end of file + } +} \ No newline at end of file diff --git a/src/components/DesignForm/printHtmlRender.vue b/src/components/DesignForm/printHtmlRender.vue index 156ec48..82512bf 100644 --- a/src/components/DesignForm/printHtmlRender.vue +++ b/src/components/DesignForm/printHtmlRender.vue @@ -9,6 +9,7 @@ export interface fieldTree{ type:string; checked?:number; data?:[]; + options?:[];//select, checkbox... options child?:fieldTree[] } @@ -41,12 +42,12 @@ const userName=useUserStore().nickname; function parseDataPicker(val:string){ let str:string; if(typeof(val)=="number"){ - str=new Date(val).toISOString() + str=new Date(val).toLocaleString() }else{ if(val==""|| val.match(/[a-z]/) ) return val; - str=new Date(parseInt(val)).toISOString() + str=new Date(parseInt(val)).toLocaleString() } - + return str.slice(0,10)+" "+str.slice(11,16) } @@ -131,15 +132,15 @@ const getStateText=(val:number)=>{
{{ group.name }}
- +
{{ tabs.name }}
@@ -166,7 +167,7 @@ const getStateText=(val:number)=>{
-
+
{{tabs.name}} @@ -176,10 +177,9 @@ const getStateText=(val:number)=>{
-
{{ group }}
+
{{ group }}
-
@@ -265,7 +265,7 @@ div:empty { .auto_table{ display: grid; grid-template-columns: 1fr 1fr; - border: 1px solid rgb(226, 226, 226); + border: 1px solid rgb(200, 200, 200); } .operate_log{ display: block; @@ -357,7 +357,7 @@ h5{ } /* 原有样式(稍作优化) */ -.cell_box, .tabs_cell_box { +.cell_box, .tabs_cell_box, .tabs_wide_box{ border: 1px solid rgb(182, 181, 181); margin-right: -1px; /* 水平排列时用右负margin */ margin-bottom: -1px; /* 垂直排列时用下负margin */ @@ -383,8 +383,9 @@ h5{ border-left: 1px solid rgb(182, 181, 181); } } -.tabs_cell_box{ +.tabs_cell_box, .tabs_wide_box{ width: 100%; + flex-direction: row; } diff --git a/src/store/modules/orgMember.ts b/src/store/modules/orgMember.ts index 0d1bdce..69709ab 100644 --- a/src/store/modules/orgMember.ts +++ b/src/store/modules/orgMember.ts @@ -9,11 +9,12 @@ export const useOrgMemberStore = defineStore('orgMember', () => { name: string; child?:OrgMemberItem[]; } - + const listMap = ref>({}) const dataTree = ref({ id: '', name: '', child: [] }) async function init() { + await request({ url: "/systemapi/app/get_org_everyone_people",//"172.20.2.87:39168", method: "post", diff --git a/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue b/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue index 728b92d..8d9e1ce 100644 --- a/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue +++ b/src/views/sysworkflow/lowcodepage/appPage/appPageForm/printSetupPage2.vue @@ -13,6 +13,7 @@ interface fieldTreeEx extends fieldTree{ unitName?:string; list?:fieldTreeEx[]; columns?:fieldTreeEx[]; + options?:[] } const printMode=ref("") @@ -104,6 +105,13 @@ const updatePageConfig=(cmd:string)=>{ } } +const onClearTreeData=()=>{ + fieldTreeData.value=[] + props.state.formData.list.forEach((item:fieldTreeEx)=>{ + fieldTreeData.value.push(deepLoop(item)) + }) +} + //保存模板 const onSaveTreeData=()=>{ let str:string=safeStringify(htmlRenderData.value) @@ -146,6 +154,15 @@ const deepLoop=(item:fieldTreeEx)=>{ child:[], } break; + case "select": + case "checkbox": + data={ + field:item.name?? "", + type:item.type, + name:item.item ? item.item.label : "", + options: item.options + } + break; default: data={ field:item.name?? "", @@ -270,14 +287,17 @@ onMounted(async ()=>{ }) /*********************为解决pageconfig字段的问题**************************/ + console.log(fieldTreeData.value.length,"length????") let newForm:boolean; if(fieldTreeData.value.length==0){ newForm=true; } + props.state.formData.list.forEach((item:fieldTreeEx)=>{ if(systemType.includes(item.type)) { //需要记录这种type的真实字段 objPageConfig.value[item.type as keyof PageConfig]=item.name??"" + } //无论新表单还是已保存过的表单,都要处理objPageConfig字段的问题,但是fieldTreeData只有在新表单的时候需要初始化 if(newForm){ @@ -352,7 +372,8 @@ const updateNodeData=(val:fieldTree,val2:boolean,val3:boolean)=>{ - + + 重置 保存模板
Date: Wed, 17 Dec 2025 10:47:33 +0800 Subject: [PATCH 15/25] =?UTF-8?q?=E6=89=93=E5=8D=B0=EF=BC=9A=E5=A4=84?= =?UTF-8?q?=E7=90=86=E6=97=B6=E9=97=B4=E5=AD=97=E6=AE=B5=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DesignForm/printHtmlRender.vue | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/components/DesignForm/printHtmlRender.vue b/src/components/DesignForm/printHtmlRender.vue index 82512bf..8d7520f 100644 --- a/src/components/DesignForm/printHtmlRender.vue +++ b/src/components/DesignForm/printHtmlRender.vue @@ -39,16 +39,19 @@ const props = withDefaults(defineProps<{ const qrdata=ref("") const userName=useUserStore().nickname; -function parseDataPicker(val:string){ +function parseDataPicker(val:string,vtype:string){ let str:string; if(typeof(val)=="number"){ str=new Date(val).toLocaleString() - }else{ - if(val==""|| val.match(/[a-z]/) ) return val; + }else{//"";2025-12-17;sheng1chan3ri4qi1;三种值直接返回 + if(val==""|| val.match(/[a-z-:.]/) ) return val; str=new Date(parseInt(val)).toLocaleString() } - return str.slice(0,10)+" "+str.slice(11,16) + if(vtype.startsWith("time")){ + return str.slice(11,16) + } + return str.slice(0,10) } const generateQrCode= ()=>{ @@ -100,7 +103,7 @@ const getStateText=(val:number)=>{ {{item.name}} {{item.field}} - {{parseDataPicker(item.field)}} + {{parseDataPicker(item.field,item.type)}}
@@ -122,7 +125,14 @@ const getStateText=(val:number)=>{
@@ -138,7 +148,7 @@ const getStateText=(val:number)=>{ {{item.name}} {{item.field}} - {{parseDataPicker(item.field)}} + {{parseDataPicker(item.field,item.type)}} @@ -161,7 +171,14 @@ const getStateText=(val:number)=>{ @@ -172,7 +189,7 @@ const getStateText=(val:number)=>{ {{tabs.name}} {{tabs.field}} - {{parseDataPicker(tabs.field??'')}} + {{parseDataPicker(tabs.field??'',tabs.type)}} From 2864cf1ccb00e8ab275b577e0eedde128472e5fc Mon Sep 17 00:00:00 2001 From: liwenxuan <1298531568@qq.com> Date: Thu, 18 Dec 2025 08:03:40 +0800 Subject: [PATCH 16/25] 1 --- src/components/DesignForm/app/index.vue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/DesignForm/app/index.vue b/src/components/DesignForm/app/index.vue index 4ea1f56..08f8751 100644 --- a/src/components/DesignForm/app/index.vue +++ b/src/components/DesignForm/app/index.vue @@ -1180,17 +1180,17 @@ async function doGainFormPageListCont(sendData: any) { //console.log(dataList) rangedDatePickerInTables.forEach(element => { let x = element.split('^^^*^^^') - console.log(x) + //console.log(x) rangedDatePickerInTables1.push(x) data.data.list.forEach((item: any) => { - console.log(item) - console.log(item[x[0]]) + /* console.log(item) + console.log(item[x[0]]) */ let tableValues = item[x[0]] tableValues.forEach((element1: any) => { let start = dateStringToTimestampLocal(element1[x[1]]) let end = element1[x[1]+"_end"] let arr = [start,end] - console.log(arr) + //console.log(arr) element1[x[1]] = arr }); /* let y = dateStringToTimestampLocal(item[x[0]][x[1]]) @@ -1292,7 +1292,7 @@ async function doGainFormPageListCont(sendData: any) { } }); }); -console.log(data.data) +//console.log(data.data) return data.data; //tableDataList.value = data.data.list From 9470bf89fec2a413fac3e276c571870b65f4ffda Mon Sep 17 00:00:00 2001 From: liwenxuan <1298531568@qq.com> Date: Fri, 19 Dec 2025 10:49:04 +0800 Subject: [PATCH 17/25] =?UTF-8?q?=E5=B1=8F=E8=94=BD=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=85=A8=E9=83=A8=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DesignForm/formControlPropertiNew.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/DesignForm/formControlPropertiNew.vue b/src/components/DesignForm/formControlPropertiNew.vue index 0e9b367..c1c5fdd 100644 --- a/src/components/DesignForm/formControlPropertiNew.vue +++ b/src/components/DesignForm/formControlPropertiNew.vue @@ -6142,7 +6142,7 @@ const formatTooltip = (val: number) => { > 选项配置 - { v-model="controlData.config.addAll" placeholder="请输入全部项文案" /> - + --> Date: Wed, 24 Dec 2025 09:02:14 +0800 Subject: [PATCH 18/25] =?UTF-8?q?=E4=BA=91=E7=9B=98=EF=BC=9A=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E4=B8=AA=E4=BA=BA=E5=92=8C=E7=A9=BA=E9=97=B4=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E6=96=87=E4=BB=B6=E7=A7=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/doc/index.ts | 15 ++ src/api/doc/type.ts | 4 +- src/views/doc/manage.vue | 36 +++- src/views/doc/movepanel.vue | 344 ++++++++++++++++++++++++++++++++++++ src/views/doc/space.vue | 4 +- 5 files changed, 396 insertions(+), 7 deletions(-) create mode 100644 src/views/doc/movepanel.vue diff --git a/src/api/doc/index.ts b/src/api/doc/index.ts index 52932c3..1316459 100644 --- a/src/api/doc/index.ts +++ b/src/api/doc/index.ts @@ -188,4 +188,19 @@ export function postMatterRename(uid:string,data?: {uuid:string;name:string}){ }, data: data }); +} + +/** + * 移动文件 + */ +export function postMatterMove(uid:string,data?: {srcUuids:string;destUuid:string}){ + return request({ + url: '/hxpan/api/matter/move', + method: 'post', + headers: { + 'Identifier':uid, + 'Content-Type': 'application/x-www-form-urlencoded' + }, + data: data + }); } \ No newline at end of file diff --git a/src/api/doc/type.ts b/src/api/doc/type.ts index aa1f1ba..f37ee28 100644 --- a/src/api/doc/type.ts +++ b/src/api/doc/type.ts @@ -15,6 +15,7 @@ export interface matterPage{ deleted?:boolean; orderDir?:string; name?:string; + dir?:string;// ‘true’ or ‘false’ 字符串,表示是否只查询文件夹或文件 space?:string; orderCreateTime?:string; } @@ -89,12 +90,13 @@ export interface respCreateShare{ /** * 文件上传 */ -export function doFileUpload(params:FormData,_url:string): AxiosPromise { +export function doFileUpload(uid:string,params:FormData,_url:string): AxiosPromise { return request({ url: _url, method: 'post', data: params, headers: { + 'Identifier':uid, 'Content-Type': 'multipart/form-data' } }); diff --git a/src/views/doc/manage.vue b/src/views/doc/manage.vue index 4bba109..a85f95c 100644 --- a/src/views/doc/manage.vue +++ b/src/views/doc/manage.vue @@ -7,7 +7,7 @@ import { getExpirTime, getFileIcon, readableSize,fileType} from "./tools" import sharePermission from './sharePermission.vue'; import { useUserStore } from "@/store/modules/user"; -import { getMatterList,postCreateDir,postDelMatter,postCreateShare,postMatterRename, +import { getMatterList,postCreateDir,postDelMatter,postCreateShare,postMatterRename,postMatterMove, postDelMatBatch,getMySpaces,doCreateSpace,getRecyclingList} from "@/api/doc/index" import { matterPage,matterInfo,respCreateShare,matterTree, doFileUpload,matterPermit} from "@/api/doc/type" import { h } from 'vue' @@ -28,6 +28,7 @@ import SvgIcon from "@/components/SvgIcon/index.vue"; import {doDelSpace,doAccessManage,doCreateAiagent,setAgentQueryURL,getAgentQueryURL} from "@/api/doc/space" import Space from "./space.vue"; import Logpanel from "./logpanel.vue"; +import Movepanel from "./movepanel.vue"; //TODO: add file icons done! //TODO: click on table-item, 1)preview on file ..................... @@ -279,6 +280,30 @@ function onMatterRename(row:matterInfo){ }) } +//文件移动 +function onMoveFile(row:matterInfo){ + const dstuuid=ref(row.puuid) + ElMessageBox({ + customStyle: { '--el-messagebox-width':'800px',padding:'40px'}, + message:() => h(Movepanel,{ + style: { width:'100%' }, + modelValue: dstuuid.value, + 'onUpdate:modelValue': (val) => { + dstuuid.value = val + }, + }), + }).then(() => { + if(dstuuid.value!=row.puuid){ + postMatterMove(uid,{ + srcUuids:row.uuid, + destUuid:dstuuid.value as string, + }).then(()=>onLoadMatterList()) + }else{ + alert("目录相同不需要移动") + } + }) +} + //加载文件列表 function onSearchFile(name?:string){ let _page: matterPage = { @@ -600,7 +625,7 @@ async function handleSingleFile(ff:File){ fields.append("puuid",uploadFormData.value.puuid) fields.append("file",ff) - const res = await doFileUpload(fields,'/hxpan/api/matter/upload') + const res = await doFileUpload(uid,fields,'/hxpan/api/matter/upload') if(res.code!=200){ console.log(ff.name+"上传失败! ") throw new Error(ff.name+"上传失败!
") @@ -665,7 +690,7 @@ async function handleFolderFile(option:File){ fields.append('file', option) fields.append("space",uploadFormData.value.space) fields.append("puuid",puuid) - const res = await doFileUpload(fields,'/hxpan/api/matter/upload') + const res = await doFileUpload(uid,fields,'/hxpan/api/matter/upload') if(res.code!=200){ console.log(_path+"上传失败! ") throw new Error(_path +" 上传失败!
") @@ -1099,7 +1124,8 @@ const handleSelectionChange = (val:matterInfo[]) => { - + + @@ -1137,6 +1163,7 @@ const handleSelectionChange = (val:matterInfo[]) => {
  • 分享
  • 下载
  • 编辑
  • +
  • 移动
  • 删除
  • 重命名
  • @@ -1255,6 +1282,7 @@ const handleSelectionChange = (val:matterInfo[]) => { display: flex; flex-wrap: wrap; /* 关键属性,允许子元素自动换行 */ align-content: flex-start; + min-height: 500px; .grid-item{ position: relative; width: 134px; diff --git a/src/views/doc/movepanel.vue b/src/views/doc/movepanel.vue new file mode 100644 index 0000000..98cbf54 --- /dev/null +++ b/src/views/doc/movepanel.vue @@ -0,0 +1,344 @@ + + + + + + + + \ No newline at end of file diff --git a/src/views/doc/space.vue b/src/views/doc/space.vue index e311744..8db7516 100644 --- a/src/views/doc/space.vue +++ b/src/views/doc/space.vue @@ -413,7 +413,7 @@ async function handleSingleFile(ff:File){ fields.append("puuid",uploadFormData.value.puuid) fields.append("file",ff) - const res = await doFileUpload(fields,'/hxpan/api/space/upload') + const res = await doFileUpload(props.uid,fields,'/hxpan/api/space/upload') if(res.code!=200){ console.log(ff.name+"上传失败! ") throw new Error(ff.name+"上传失败!
    ") @@ -479,7 +479,7 @@ async function handleFolderFile(option:File){ fields.append('file', option) fields.append("space",uploadFormData.value.space) fields.append("puuid",puuid) - const res = await doFileUpload(fields,'/hxpan/api/space/upload') + const res = await doFileUpload(props.uid,fields,'/hxpan/api/space/upload') if(res.code!=200){ console.log(_path+"上传失败! ") throw new Error(_path+"上传失败!
    ") From 287acfe3fbfaed145388b36d77f63b5a2a3b7fba Mon Sep 17 00:00:00 2001 From: liwenxuan <1298531568@qq.com> Date: Wed, 31 Dec 2025 13:23:05 +0800 Subject: [PATCH 19/25] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E8=AE=BE=E7=BD=AEv0.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DesignForm/assembly/index.ts | 8 + .../DesignForm/formControlPropertiNew.vue | 645 +++++++++++++++++- 2 files changed, 638 insertions(+), 15 deletions(-) diff --git a/src/components/DesignForm/assembly/index.ts b/src/components/DesignForm/assembly/index.ts index 67f885e..408fb92 100644 --- a/src/components/DesignForm/assembly/index.ts +++ b/src/components/DesignForm/assembly/index.ts @@ -262,6 +262,10 @@ export default [ control: { modelValue: '', glxxsz: [], + zdtcsz: { + tbx: '', + tby: '' + }, optionsValue3Formid:'', optionsValue3Field:'', }, @@ -312,6 +316,10 @@ export default [ modelValue: '', appendToBody: true, glxxsz: [], + zdtcsz: { + tbx: '', + tby: '' + }, optionsValue3Formid:'', optionsValue3Field:'', }, diff --git a/src/components/DesignForm/formControlPropertiNew.vue b/src/components/DesignForm/formControlPropertiNew.vue index c1c5fdd..2383905 100644 --- a/src/components/DesignForm/formControlPropertiNew.vue +++ b/src/components/DesignForm/formControlPropertiNew.vue @@ -2910,6 +2910,485 @@ function mergeArrays(a, b) { //选项批量编辑 liwenxuan 20251212 end +//自动填充设置 liwenxuan 20251230 start + + +/** + * 获取字符串最后一个英文冒号(:)后的字符 + * @param {string} str - 待处理的原始字符串 + * @returns {string} 最后一个冒号后的子串;无冒号/冒号在末尾时返回空字符串 + */ +function getLastColonAfterString(str) { + // 1. 输入校验:确保输入是字符串类型(处理非字符串入参) + if (typeof str !== 'string') { + console.warn('输入必须为字符串类型'); + return ''; + } + + // 2. 找到最后一个英文冒号的索引位置 + const lastColonIndex = str.lastIndexOf(':'); + + // 3. 边界判断:无冒号 或 冒号在最后一位 → 返回空字符串 + if (lastColonIndex === -1 || lastColonIndex === str.length - 1) { + return ''; + } + + // 4. 截取最后一个冒号后的所有字符并返回 + return str.slice(lastColonIndex + 1); +} + +// 原始选项数组(标题行=列,索引列=行) +const titleOptions = computed(() => { + let result = [] + if(controlData.value.control.zdtcsz.tbx){ + zdtcszTree.value.forEach(element => { + if(element.id==controlData.value.control.zdtcsz.tbx){ + result = element.options + } + }); + } + return result +}) +const indexOptions = computed(() => { // 原“索引列”数组 + let result = [] + if(controlData.value.control.zdtcsz.tby){ + zdtcszTree.value.forEach(element => { + if(element.id==controlData.value.control.zdtcsz.tby){ + result = element.options + } + }); + } + + + return result +}) + +// 表格列配置:基于“标题行”数组(作为表头) +const zdtcszTableColumns = computed(() => { + return titleOptions.value.map(item => ({ + label: item.label, + value: item.value + })) +}) + +// 表格行数据:基于“索引列”数组(作为行) +const zdtcszTableData = computed(() => { + return indexOptions.value.map(rowItem => { + const rowObj = { + rowKey: rowItem.value, + rowLabel: rowItem.label // 第一列显示索引列的数字 + } + // 为每个标题列生成空值 + titleOptions.value.forEach(colItem => { + rowObj[`col_${colItem.value}`] = '' + }) + return rowObj + }) +}) +const zdtcszTree = computed(()=>{ + if(datapropsformList.length==0){ + datapropsformList = JSON.parse(JSON.stringify(props.formList)) + } + + //console.log(datapropsformList) + 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 + const treeC = mergeAndFilterFormTrees(datapropsformList, datab,currentCompId); + //console.log(treeC) + return treeC + }else{ + return [] + } + +}) + +/** + * 合并两个组件树,仅保留type为radio和select的节点,并过滤掉指定compId的节点,同时保留options属性 + * @param {Array} treeA - 组件树a,包含表单结构信息 + * @param {Array} treeB - 组件树b,包含字段数据信息 + * @param {String} compId - 需要过滤掉的组件id的后一部分 + * @returns {Array} - 合并后仅包含radio和select节点的组件树c + */ +function mergeAndFilterFormTrees(treeA, treeB, compId) { + // 构建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 gridCount = 0; + let tabsCount = 0; + let divCount = 0; + let cardCount = 0; + + // 递归处理a树,仅保留radio和select节点,并过滤掉compId + function processANode(node, parentId = commonParentId) { + // 获取当前节点的name + const nodeName = node.name; + const nodeType = node.type; + + // 检查当前节点是否需要被过滤(如果compId与节点name相等,则过滤) + if (compId && nodeName === compId) { + // 从bMap中删除对应的节点(如果存在),避免后面被使用 + if (nodeName && bMap.has(nodeName)) { + bMap.delete(nodeName); + } + return null; + } + + // 如果是radio或select类型,直接处理 + if (nodeType === 'radio' || nodeType === 'select') { + // 检查是否需要过滤 + if (compId && nodeName === compId) { + return null; + } + + // 查找b树中对应的节点 + let bNode = null; + if (nodeName && bMap.has(nodeName)) { + bNode = bMap.get(nodeName); + bMap.delete(nodeName); // 从map中删除,标记为已使用 + } + + // 如果b节点存在,检查是否需要过滤 + if (bNode && compId) { + const bNodeId = bNode.id || ''; + const parts = bNodeId.split(':'); + const bNodeName = parts[parts.length - 1]; + if (bNodeName === compId) { + return null; + } + } + + let cNode; + if (bNode) { + // 复制b节点的所有属性 + cNode = { ...bNode }; + // 确保children数组存在 + if (!cNode.children) { + cNode.children = []; + } + // 使用b节点的parentId + cNode.parentId = bNode.parentId || parentId; + + // 保留a节点中的options属性到c节点中 + if (node.options && Array.isArray(node.options)) { + // 如果c节点中已经有options,可以合并,这里我们直接用a节点的options + // 因为a节点中的options通常是最新的配置 + cNode.options = node.options; + + // 如果a节点有control.glxxsz(关联选项设置),也保留 + if (node.control && node.control.glxxsz && Array.isArray(node.control.glxxsz)) { + if (!cNode.control) { + cNode.control = {}; + } + cNode.control.glxxsz = node.control.glxxsz; + } + } + } else { + // 如果b中不存在,则创建新节点 + const label = node.item?.label || nodeName || nodeType; + const id = nodeName ? `${commonParentId}:${nodeName}` : null; + cNode = { + id: id, + label: label, + parentId: parentId, + children: [], + value: id, + treeAttrs: { + show: label + }, + disabled: false, // radio和select类型,叶子节点disabled为false + type: nodeType + }; + + // 保留a节点中的options属性 + if (node.options && Array.isArray(node.options)) { + cNode.options = node.options; + } + + // 保留control.glxxsz(关联选项设置) + if (node.control && node.control.glxxsz && Array.isArray(node.control.glxxsz)) { + if (!cNode.control) { + cNode.control = {}; + } + cNode.control.glxxsz = node.control.glxxsz; + } + + // 保留config属性 + if (node.config) { + cNode.config = node.config; + } + } + + return cNode; + } + + // 如果不是radio或select,但可能是容器类型,需要处理其子节点 + // 检查是否是容器类型 + const containerTypes = ['table', 'card', 'flex', 'div', 'grid', 'tabs']; + if (containerTypes.includes(nodeType)) { + // 检查容器节点本身是否需要过滤 + if (compId && nodeName === compId) { + // 如果容器节点需要过滤,其所有子节点都不处理 + // 从bMap中删除对应的节点(如果存在) + if (nodeName && bMap.has(nodeName)) { + bMap.delete(nodeName); + } + return null; + } + + // 创建一个容器节点占位符 + let containerId; + let containerLabel; + let originalName = nodeName; // 保存原始name用于检查过滤 + + // 根据容器类型设置不同的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 'table': + case 'flex': + // 对于table和flex,查找b树中对应的节点 + let bNode = null; + if (nodeName && bMap.has(nodeName)) { + bNode = bMap.get(nodeName); + bMap.delete(nodeName); + } + + // 检查b节点是否需要过滤 + if (bNode && compId) { + const bNodeId = bNode.id || ''; + const parts = bNodeId.split(':'); + const bNodeName = parts[parts.length - 1]; + if (bNodeName === compId) { + return null; + } + } + + if (bNode) { + containerId = bNode.id || `${commonParentId}:${nodeName}`; + containerLabel = nodeType === 'table' ? `子表${bNode.label || nodeName}` : + `弹性布局${bNode.label || nodeName}`; + } else { + containerId = `${commonParentId}:${nodeName}`; + containerLabel = nodeType === 'table' ? `子表${node.item?.label || nodeName}` : + `弹性布局${node.item?.label || nodeName}`; + } + break; + default: + containerId = `${commonParentId}:${nodeName}`; + containerLabel = node.item?.label || nodeName || nodeType; + } + + // 创建容器节点 + const containerNode = { + id: containerId, + label: containerLabel, + parentId: parentId, + children: [], + value: containerId, + treeAttrs: { + show: containerLabel + }, + disabled: null, // 容器节点,非叶子节点 + type: nodeType + }; + + // 处理子组件 + let hasValidChildren = false; + + if (nodeType === 'table' || 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); + 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, + 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); + 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); + if (processedChild) { + childNodes.push(processedChild); + hasValidChildren = true; + } + }); + } + }); + containerNode.children = childNodes; + } + } + } + + // 如果容器没有有效的子节点(radio或select),则返回null + if (!hasValidChildren) { + // 对于table和flex,即使没有子节点也要保留(因为可以选择) + if (nodeType === 'table' || nodeType === 'flex') { + containerNode.disabled = false; + return containerNode; + } + return null; + } + + // 设置容器节点的disabled属性 + // 对于table和flex,即使有子节点也可以选择,disabled为false + if (nodeType === 'table' || nodeType === 'flex') { + containerNode.disabled = false; + } else { + // 其他容器类型,有子节点为null,没有子节点为true + containerNode.disabled = null; + } + + return containerNode; + } + + // 其他非radio/select类型,直接返回null + return null; + } + + // 处理a树的所有根节点 + const cTree = []; + treeA.forEach(rootNode => { + const processedNode = processANode(rootNode); + if (processedNode) { + cTree.push(processedNode); + } + }); + + // 将b树中剩余的radio和select元素(在a中不存在的)添加到c树中 + bMap.forEach((bNode, nodeName) => { + // 检查是否需要过滤 + if (compId) { + const bNodeId = bNode.id || ''; + const parts = bNodeId.split(':'); + const bNodeName = parts[parts.length - 1]; + if (bNodeName === compId) { + // 过滤掉这个节点 + return; + } + } + + // 只保留radio和select类型 + if (bNode.type === 'radio' || bNode.type === 'select') { + // 保留b节点的原始结构 + const newNode = { ...bNode }; + + // 确保children数组存在 + if (!newNode.children) { + newNode.children = []; + } + + // 设置disabled属性为false(叶子节点) + newNode.disabled = false; + + cTree.push(newNode); + } + }); + + return cTree; +} + +// 使用示例 +// const filteredTree = mergeAndFilterFormTrees(treeA, treeB, 'radio1763601215033'); + + +//自动填充设置 liwenxuan 20251230 end + //关联选项设置优化为树 liwenxuan 20251209 start @@ -2919,13 +3398,14 @@ const glxxszTree = computed(()=>{ datapropsformList = JSON.parse(JSON.stringify(props.formList)) } - //console.log(datapropsformList) + console.log(datapropsformList) if(associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf && associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children && associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children.length>0){ let datab = JSON.parse(JSON.stringify(associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children)) const treeC = mergeFormTrees(datapropsformList, datab); + console.log(treeC) return treeC }else{ return null @@ -4014,6 +4494,7 @@ function handleDetermineAssociatedFormsChooseDialog() { //liwenxuan20240426 单选多选下拉 关联选项设置 start +const ZdtcszDialogFlag = ref(false); const glxxszDialogFlag = ref(false); const glxxszDialogFlagCheckBox = ref(false); const glxxszDialogFlagSwitch = ref(false); @@ -4035,6 +4516,24 @@ function handelGlxxszDialog() { } } +function handelZdtcszDialog(){ + if (controlData.value.options.length === 0) { + alert("无可配置选项,请先添加。"); + } else { + + if(controlData.value.control.zdtcsz){ + + }else{ + controlData.value.control.zdtcsz = { + tbx: '', + tby: '' + } + } + ZdtcszDialogFlag.value = true; + + } +} + function handelGlxxszDialogCheckbox() { glxxszDialogFlagCheckBox.value = true; } @@ -4048,6 +4547,9 @@ function handleDetermineGlxxszDialogSwitch() { function handleDetermineGlxxszDialogCheckBox() { glxxszDialogFlagCheckBox.value = false; } +function handleDetermineZdtcszDialogFlag(){ + ZdtcszDialogFlag.value = false; +} //同步开关的设置值和开关关联选项设置的值 watch( () => controlData.value.control, @@ -6228,26 +6730,39 @@ const formatTooltip = (val: number) => { + {{ controlData.type === "cascader" ? "编辑" : "新增" }} - + 批量导入 -
    - 关联选项设置 -
    -
    - 关联选项设置 -
    -
    - 关联选项设置 +
    +
    + 关联选项设置 +
    +
    + 关联选项设置 +
    +
    + 关联选项设置 +
    + +
    + 自动填充设置 +
    @@ -7972,9 +8487,109 @@ const formatTooltip = (val: number) => { + + + + + +
    + + 标题行 + + + + + + 索引列 + + + +
    +{{zdtcszTableData}} + +
    + + + + + + + + +
    + + + + +
    + + + + + - + + Date: Wed, 31 Dec 2025 14:01:26 +0800 Subject: [PATCH 20/25] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E8=AE=BE=E7=BD=AEv0.25?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DesignForm/formControlPropertiNew.vue | 294 ++++++++++-------- 1 file changed, 166 insertions(+), 128 deletions(-) diff --git a/src/components/DesignForm/formControlPropertiNew.vue b/src/components/DesignForm/formControlPropertiNew.vue index 2383905..00506b8 100644 --- a/src/components/DesignForm/formControlPropertiNew.vue +++ b/src/components/DesignForm/formControlPropertiNew.vue @@ -2910,60 +2910,72 @@ function mergeArrays(a, b) { //选项批量编辑 liwenxuan 20251212 end -//自动填充设置 liwenxuan 20251230 start +//自动填充设置 liwenxuan 20251230 start +let datapropsformList = JSON.parse(JSON.stringify(props.formList)) -/** - * 获取字符串最后一个英文冒号(:)后的字符 - * @param {string} str - 待处理的原始字符串 - * @returns {string} 最后一个冒号后的子串;无冒号/冒号在末尾时返回空字符串 - */ -function getLastColonAfterString(str) { - // 1. 输入校验:确保输入是字符串类型(处理非字符串入参) - if (typeof str !== 'string') { - console.warn('输入必须为字符串类型'); - return ''; +const zdtcszTree = computed(()=>{ + if(datapropsformList&&datapropsformList.length==0){ + datapropsformList = JSON.parse(JSON.stringify(props.formList)) } + + //console.log(datapropsformList) + if(associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf && associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children && associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children.length>0){ - // 2. 找到最后一个英文冒号的索引位置 - const lastColonIndex = str.lastIndexOf(':'); - - // 3. 边界判断:无冒号 或 冒号在最后一位 → 返回空字符串 - if (lastColonIndex === -1 || lastColonIndex === str.length - 1) { - return ''; + + let datab = JSON.parse(JSON.stringify(associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children)) + let currentCompId = controlData.value.name + const treeC = mergeAndFilterFormTrees(datapropsformList, datab,currentCompId); + //console.log(treeC) + return treeC + }else{ + return [] } + +}) - // 4. 截取最后一个冒号后的所有字符并返回 - return str.slice(lastColonIndex + 1); -} +// 使用 ref 替代 computed,使其可写 +const zdtcszTableData = ref([]) + +// 获取当前选择的索引列节点(用于获取label) +const currentIndexColumnNode = computed(() => { + if (!controlData.value?.control?.zdtcsz?.tby) return null + return zdtcszTree.value.find(item => item.id == controlData.value.control.zdtcsz.tby) +}) + +// 获取当前选择的标题行节点(用于获取label) +const currentTitleColumnNode = computed(() => { + if (!controlData.value?.control?.zdtcsz?.tbx) return null + return zdtcszTree.value.find(item => item.id == controlData.value.control.zdtcsz.tbx) +}) + +//左上角 +const leftTopLabel = computed(()=>{ + return `${indexColumnLabel.value}\\${titleColumnLabel.value}` +}) + +// 索引列的标签(用于第一列的表头) +const indexColumnLabel = computed(() => { + if (!currentIndexColumnNode.value) return "索引列" + return currentIndexColumnNode.value.label +}) + +// 标题行的标签(如果需要,可以用于其他地方) +const titleColumnLabel = computed(() => { + if (!currentTitleColumnNode.value) return "标题行" + return currentTitleColumnNode.value.label +}) // 原始选项数组(标题行=列,索引列=行) -const titleOptions = computed(() => { - let result = [] - if(controlData.value.control.zdtcsz.tbx){ - zdtcszTree.value.forEach(element => { - if(element.id==controlData.value.control.zdtcsz.tbx){ - result = element.options - } - }); - } - return result +const titleOptions = computed(() => { + return currentTitleColumnNode.value?.options || [] }) -const indexOptions = computed(() => { // 原“索引列”数组 - let result = [] - if(controlData.value.control.zdtcsz.tby){ - zdtcszTree.value.forEach(element => { - if(element.id==controlData.value.control.zdtcsz.tby){ - result = element.options - } - }); - } - - - return result + +const indexOptions = computed(() => { + return currentIndexColumnNode.value?.options || [] }) -// 表格列配置:基于“标题行”数组(作为表头) +// 表格列配置 const zdtcszTableColumns = computed(() => { return titleOptions.value.map(item => ({ label: item.label, @@ -2971,39 +2983,71 @@ const zdtcszTableColumns = computed(() => { })) }) -// 表格行数据:基于“索引列”数组(作为行) -const zdtcszTableData = computed(() => { - return indexOptions.value.map(rowItem => { +// 监听标题行和索引列的变化,重新生成表格数据 +watch([titleOptions, indexOptions], ([newTitleOptions, newIndexOptions]) => { + // 如果没有标题行或索引列,清空表格数据 + if (!newTitleOptions.length || !newIndexOptions.length) { + zdtcszTableData.value = [] + return + } + + // 从 controlData 中获取之前保存的数据 + const savedData = controlData.value?.control?.zdtcsz?.tableData || {} + + // 生成新的表格数据 + const newTableData = newIndexOptions.map(rowItem => { + const rowKey = rowItem.value const rowObj = { - rowKey: rowItem.value, - rowLabel: rowItem.label // 第一列显示索引列的数字 + rowKey: rowKey, + rowLabel: rowItem.label // 使用选项的label作为第一列显示 } - // 为每个标题列生成空值 - titleOptions.value.forEach(colItem => { - rowObj[`col_${colItem.value}`] = '' + + // 为每个标题列生成值,如果有保存的数据则使用保存的数据 + newTitleOptions.forEach(colItem => { + const colKey = colItem.value + const savedValue = savedData[rowKey]?.[colKey] || '' + rowObj[`col_${colKey}`] = savedValue }) + return rowObj }) -}) -const zdtcszTree = computed(()=>{ - if(datapropsformList.length==0){ - datapropsformList = JSON.parse(JSON.stringify(props.formList)) - } - //console.log(datapropsformList) - 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 - const treeC = mergeAndFilterFormTrees(datapropsformList, datab,currentCompId); - //console.log(treeC) - return treeC - }else{ - return [] + zdtcszTableData.value = newTableData +}, { immediate: true }) + +// 监听表格数据变化,保存到临时存储 +const handleTableDataChange = () => { + // 将表格数据转换为更容易存储的格式 + const tableData = {} + zdtcszTableData.value.forEach(row => { + const rowKey = row.rowKey + tableData[rowKey] = {} + titleOptions.value.forEach(col => { + const colKey = col.value + tableData[rowKey][colKey] = row[`col_${colKey}`] || '' + }) + }) + + // 保存到 controlData 中 + if (!controlData.value.control.zdtcsz) { + controlData.value.control.zdtcsz = {} } + controlData.value.control.zdtcsz.tableData = tableData +} + +// 确定按钮的处理函数 +const handleDetermineZdtcszDialogFlag = () => { + // 保存数据 + handleTableDataChange() -}) + // 关闭弹窗 + ZdtcszDialogFlag.value = false + + // 可以在这里添加其他处理逻辑 + /* console.log('保存的数据:', controlData.value.control.zdtcsz.tableData) + console.log('索引列:', indexColumnLabel.value) + console.log('标题行:', titleColumnLabel.value) */ +} /** * 合并两个组件树,仅保留type为radio和select的节点,并过滤掉指定compId的节点,同时保留options属性 @@ -3392,7 +3436,7 @@ function mergeAndFilterFormTrees(treeA, treeB, compId) { //关联选项设置优化为树 liwenxuan 20251209 start -let datapropsformList = JSON.parse(JSON.stringify(props.formList)) + const glxxszTree = computed(()=>{ if(datapropsformList.length==0){ datapropsformList = JSON.parse(JSON.stringify(props.formList)) @@ -4547,9 +4591,6 @@ function handleDetermineGlxxszDialogSwitch() { function handleDetermineGlxxszDialogCheckBox() { glxxszDialogFlagCheckBox.value = false; } -function handleDetermineZdtcszDialogFlag(){ - ZdtcszDialogFlag.value = false; -} //同步开关的设置值和开关关联选项设置的值 watch( () => controlData.value.control, @@ -8490,51 +8531,49 @@ const formatTooltip = (val: number) => { + v-model="ZdtcszDialogFlag" + class="glxxsztc" + top="150px" + :close-on-click-modal="false" + :title="`自动填充设置--` + controlData.name" + :show-close="false" + style="margin-top: 70px" + width="50%" +> + +
    + + 标题行 - -
    - - 标题行 - - - - - - 索引列 - - - -
    -{{zdtcszTableData}} + + + + + 索引列 + + + +
    -
    +
    { :header-cell-style="{ textAlign: 'center' }" :cell-style="{ textAlign: 'center' }" > - + - + { v-model="scope.row[`col_${col.value}`]" size="small" placeholder="请输入" + @input="handleTableDataChange" />
    - - - - + + From 73d13f28d661a6384afe602229cf5cef41bc0b28 Mon Sep 17 00:00:00 2001 From: liwenxuan <1298531568@qq.com> Date: Wed, 31 Dec 2025 14:27:27 +0800 Subject: [PATCH 21/25] =?UTF-8?q?=E7=9F=A9=E9=98=B5=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E8=AE=BE=E7=BD=AEv0.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DesignForm/formControlPropertiNew.vue | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/components/DesignForm/formControlPropertiNew.vue b/src/components/DesignForm/formControlPropertiNew.vue index 00506b8..acf4afb 100644 --- a/src/components/DesignForm/formControlPropertiNew.vue +++ b/src/components/DesignForm/formControlPropertiNew.vue @@ -2933,10 +2933,16 @@ const zdtcszTree = computed(()=>{ } }) - // 使用 ref 替代 computed,使其可写 const zdtcszTableData = ref([]) +// 获取当前正在设置自动填充的组件("结果"组件)的选项 +const currentComponentOptions = computed(() => { + + return controlData.value.options + +}) + // 获取当前选择的索引列节点(用于获取label) const currentIndexColumnNode = computed(() => { if (!controlData.value?.control?.zdtcsz?.tby) return null @@ -2949,23 +2955,23 @@ const currentTitleColumnNode = computed(() => { return zdtcszTree.value.find(item => item.id == controlData.value.control.zdtcsz.tbx) }) -//左上角 -const leftTopLabel = computed(()=>{ - return `${indexColumnLabel.value}\\${titleColumnLabel.value}` -}) - -// 索引列的标签(用于第一列的表头) +// 索引列的标签 const indexColumnLabel = computed(() => { if (!currentIndexColumnNode.value) return "索引列" return currentIndexColumnNode.value.label }) -// 标题行的标签(如果需要,可以用于其他地方) +// 标题行的标签 const titleColumnLabel = computed(() => { if (!currentTitleColumnNode.value) return "标题行" return currentTitleColumnNode.value.label }) +// 左上角标签:格式为"索引列\标题行" +const leftTopLabel = computed(() => { + return `${indexColumnLabel.value}\\${titleColumnLabel.value}` +}) + // 原始选项数组(标题行=列,索引列=行) const titleOptions = computed(() => { return currentTitleColumnNode.value?.options || [] @@ -3045,8 +3051,8 @@ const handleDetermineZdtcszDialogFlag = () => { // 可以在这里添加其他处理逻辑 /* console.log('保存的数据:', controlData.value.control.zdtcsz.tableData) - console.log('索引列:', indexColumnLabel.value) - console.log('标题行:', titleColumnLabel.value) */ + console.log('当前组件选项:', currentComponentOptions.value) + console.log('左上角标签:', leftTopLabel.value) */ } /** @@ -6802,7 +6808,7 @@ const formatTooltip = (val: number) => { showHide(['radio', 'select'], true) && controlData.config.optionsType == 0 " > - 自动填充设置 + 矩阵填充设置
    @@ -8535,7 +8541,7 @@ const formatTooltip = (val: number) => { class="glxxsztc" top="150px" :close-on-click-modal="false" - :title="`自动填充设置--` + controlData.name" + :title="`矩阵填充设置--` + controlData.name" :show-close="false" style="margin-top: 70px" width="50%" @@ -8581,7 +8587,7 @@ const formatTooltip = (val: number) => { :header-cell-style="{ textAlign: 'center' }" :cell-style="{ textAlign: 'center' }" > - + { align="center" > From a540dd73c42103574983cbe482803db2ee85aace Mon Sep 17 00:00:00 2001 From: liwenxuan <1298531568@qq.com> Date: Wed, 7 Jan 2026 14:53:01 +0800 Subject: [PATCH 22/25] =?UTF-8?q?=E7=9F=A9=E9=98=B5=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E6=95=88=E6=9E=9C=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DesignForm/public/form/form.vue | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/src/components/DesignForm/public/form/form.vue b/src/components/DesignForm/public/form/form.vue index 1afd0a1..c8f4b3b 100644 --- a/src/components/DesignForm/public/form/form.vue +++ b/src/components/DesignForm/public/form/form.vue @@ -899,6 +899,9 @@ function showOrHide(data: any) { //以showFields的处理过冒号的每个元素为key,其对应的optionValue为value,新建一个数组radioselectArr2。----用于获取所有出现在配置中的字段。 const radioSelectArr2: any[] = []; + + const radioSelectZdtcszConfigArr = []; + //20240815 关联选项设置的隐藏效果嵌套在内时不生效的问题修复 liwenxuan start //console.log(props.formData.list) newModelKeyArr for (let i = 0; i < props.formData.list.length; i++) { @@ -915,8 +918,16 @@ function showOrHide(data: any) { ) { if (!props.formData.list[i].control.multiple) { radioSelectShowConfigArr.push(props.formData.list[i].control.glxxsz); + if(props.formData.list[i].control.zdtcsz){ + props.formData.list[i].control.zdtcsz.name = props.formData.list[i].name + radioSelectZdtcszConfigArr.push(props.formData.list[i].control.zdtcsz) + } } else { checkboxShowConfigArr.push(props.formData.list[i].control.glxxsz); + if(props.formData.list[i].control.zdtcsz){ + props.formData.list[i].control.zdtcsz.name = props.formData.list[i].name + radioSelectZdtcszConfigArr.push(props.formData.list[i].control.zdtcsz) + } } } else if (props.formData.list[i].type == "checkbox") { checkboxShowConfigArr.push(props.formData.list[i].control.glxxszForCheckBox); @@ -939,6 +950,10 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(a[w].control.glxxsz); } + if(a[w].control.zdtcsz){ + a[w].control.zdtcsz.name = a[w].name + radioSelectZdtcszConfigArr.push(a[w].control.zdtcsz) + } //radioSelectShowConfigArr.push(a[w].control.glxxsz); } else if (a[w].type == "checkbox") { checkboxShowConfigArr.push(a[w].control.glxxszForCheckBox); @@ -960,6 +975,11 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(a.control.glxxsz); } + if(a.control.zdtcsz){ + a.control.zdtcsz.name = a.name + radioSelectZdtcszConfigArr.push(a.control.zdtcsz) + } + //radioSelectShowConfigArr.push(a.control.glxxsz); } else if (a.type == "checkbox") { checkboxShowConfigArr.push(a.control.glxxszForCheckBox); @@ -984,6 +1004,10 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(a.control.glxxsz); } + if(a.control.zdtcsz){ + a.control.zdtcsz.name = a.name + radioSelectZdtcszConfigArr.push(a.control.zdtcsz) + } //radioSelectShowConfigArr.push(a.control.glxxsz); } else if (a.type == "checkbox") { checkboxShowConfigArr.push(a.control.glxxszForCheckBox); @@ -999,6 +1023,10 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(q.control.glxxsz); } + if(q.control.zdtcsz){ + q.control.zdtcsz.name = q.name + radioSelectZdtcszConfigArr.push(q.control.zdtcsz) + } //radioSelectShowConfigArr.push(q.control.glxxsz); } else if (q.type == "checkbox") { checkboxShowConfigArr.push(q.control.glxxszForCheckBox); @@ -1019,6 +1047,7 @@ function showOrHide(data: any) { newModelKeyArr = Array.from(new Set(newModelKeyArr)); //20240815 关联选项设置的隐藏效果嵌套在内时不生效的问题修复 liwenxuan end //console.log(radioSelectShowConfigArr) + //console.log(radioSelectZdtcszConfigArr) //数组深拷贝 const radioSelectShowConfigArr2 = JSON.parse(JSON.stringify(radioSelectShowConfigArr)); const checkboxShowConfigArr2 = JSON.parse(JSON.stringify(checkboxShowConfigArr)); @@ -1237,6 +1266,81 @@ function showOrHide(data: any) { //props.formData.config?.hideField?.push("nin2yuan4yi4wei4wo3menda3fen1ma101939") //console.log("监听表单--constControlChange-->",key, value, data, tProp,type,attribute)//liwenxuan + + + + +nextTick(()=>{ + //console.log(model.value)// + radioSelectZdtcszConfigArr.forEach(element => { + let tbx=getLastColonAfterString(element.tbx) + let tby=getLastColonAfterString(element.tby) + /* console.log(tbx) + console.log(tby) */ + let rowValue = model.value[tbx] + let columnValue = model.value[tby] + let cellValue = getTableCellValueV2(element.tableData, rowValue, columnValue) + //console.log(cellValue); + model.value[element.name] = cellValue*1 + + + //console.log(getTableCellValueV2(element.tableData, 3, 2)); + }); + + +}) + +} + +/** + * 获取字符串最后一个英文冒号(:)后的字符 + * @param {string} str - 待处理的原始字符串 + * @returns {string} 最后一个冒号后的子串;无冒号/冒号在末尾时返回空字符串 + */ +function getLastColonAfterString(str) { + // 1. 输入校验:确保输入是字符串类型(处理非字符串入参) + if (typeof str !== 'string') { + console.warn('输入必须为字符串类型'); + return ''; + } + + // 2. 找到最后一个英文冒号的索引位置 + const lastColonIndex = str.lastIndexOf(':'); + + // 3. 边界判断:无冒号 或 冒号在最后一位 → 返回空字符串 + if (lastColonIndex === -1 || lastColonIndex === str.length - 1) { + return ''; + } + + // 4. 截取最后一个冒号后的所有字符并返回 + return str.slice(lastColonIndex + 1); +} + + +// 根据自动填充表格行列数据确定单元格值 +function getTableCellValueV2(tableData, rowValue, columnValue) { + try { + // 检查输入参数 + if (!tableData || typeof tableData !== 'object' || Array.isArray(tableData)) { + return undefined; + } + + // 处理null或undefined值 + if (rowValue == null || columnValue == null) { + return undefined; + } + + // 转换为字符串 + const rowStr = String(rowValue); + const columnStr = String(columnValue); + + // 使用可选链操作符安全地访问嵌套属性 + return tableData?.[columnStr]?.[rowStr]; + } catch (error) { + // 如果发生任何错误,返回undefined + console.error('获取表格单元格值时发生错误:', error); + return undefined; + } } function addStringIfNotExists(arr: string[], str: string) { From 1f660efab62523700a940c7cb601d0b31784377c Mon Sep 17 00:00:00 2001 From: liwenxuan <1298531568@qq.com> Date: Wed, 7 Jan 2026 16:28:16 +0800 Subject: [PATCH 23/25] =?UTF-8?q?=E7=9F=A9=E9=98=B5=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E6=95=88=E6=9E=9C=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DesignForm/public/form/form.vue | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/components/DesignForm/public/form/form.vue b/src/components/DesignForm/public/form/form.vue index c8f4b3b..543d0ef 100644 --- a/src/components/DesignForm/public/form/form.vue +++ b/src/components/DesignForm/public/form/form.vue @@ -679,6 +679,15 @@ provide(constControlChange, ({ key, value, data, tProp, type, attribute }: any) let mustBeHidden: any = []; let newModelKeyArr: string[] = []; + +// 判断对象是否是“内容为空的纯对象” +function isEmptyPlainObject(obj) { + // 先确认是对象类型,再检查属性数量为0 + return Object.prototype.toString.call(obj) === '[object Object]' + && Object.keys(obj).length === 0; +} + + function showOrHide(data: any) { //console.log(data) @@ -918,13 +927,13 @@ function showOrHide(data: any) { ) { if (!props.formData.list[i].control.multiple) { radioSelectShowConfigArr.push(props.formData.list[i].control.glxxsz); - if(props.formData.list[i].control.zdtcsz){ + if(props.formData.list[i].control.zdtcsz&&!isEmptyPlainObject(props.formData.list[i].control.zdtcsz.tableData)){ props.formData.list[i].control.zdtcsz.name = props.formData.list[i].name radioSelectZdtcszConfigArr.push(props.formData.list[i].control.zdtcsz) } } else { checkboxShowConfigArr.push(props.formData.list[i].control.glxxsz); - if(props.formData.list[i].control.zdtcsz){ + if(props.formData.list[i].control.zdtcsz&&!isEmptyPlainObject(props.formData.list[i].control.zdtcsz.tableData)){ props.formData.list[i].control.zdtcsz.name = props.formData.list[i].name radioSelectZdtcszConfigArr.push(props.formData.list[i].control.zdtcsz) } @@ -950,7 +959,7 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(a[w].control.glxxsz); } - if(a[w].control.zdtcsz){ + if(a[w].control.zdtcsz&&!isEmptyPlainObject(a[w].control.zdtcsz.tableData)){ a[w].control.zdtcsz.name = a[w].name radioSelectZdtcszConfigArr.push(a[w].control.zdtcsz) } @@ -975,7 +984,7 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(a.control.glxxsz); } - if(a.control.zdtcsz){ + if(a.control.zdtcsz&&!isEmptyPlainObject(a.control.zdtcsz.tableData)){ a.control.zdtcsz.name = a.name radioSelectZdtcszConfigArr.push(a.control.zdtcsz) } @@ -1004,7 +1013,7 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(a.control.glxxsz); } - if(a.control.zdtcsz){ + if(a.control.zdtcsz&&!isEmptyPlainObject(a.control.zdtcsz.tableData)){ a.control.zdtcsz.name = a.name radioSelectZdtcszConfigArr.push(a.control.zdtcsz) } @@ -1023,7 +1032,7 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(q.control.glxxsz); } - if(q.control.zdtcsz){ + if(q.control.zdtcsz&&!isEmptyPlainObject(q.control.zdtcsz.tableData)){ q.control.zdtcsz.name = q.name radioSelectZdtcszConfigArr.push(q.control.zdtcsz) } From 17be23861c68685d8b3f459524bd62a94d3df95f Mon Sep 17 00:00:00 2001 From: liwenxuan <1298531568@qq.com> Date: Thu, 8 Jan 2026 13:18:30 +0800 Subject: [PATCH 24/25] =?UTF-8?q?=E7=9F=A9=E9=98=B5=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E6=95=88=E6=9E=9C=E5=AE=9E=E7=8E=B0,?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=B5=8C=E5=A5=97=E5=A1=AB=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DesignForm/public/form/form.vue | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/DesignForm/public/form/form.vue b/src/components/DesignForm/public/form/form.vue index 543d0ef..670b440 100644 --- a/src/components/DesignForm/public/form/form.vue +++ b/src/components/DesignForm/public/form/form.vue @@ -1278,7 +1278,7 @@ function showOrHide(data: any) { - +//console.log(radioSelectZdtcszConfigArr) nextTick(()=>{ //console.log(model.value)// radioSelectZdtcszConfigArr.forEach(element => { @@ -1290,7 +1290,11 @@ nextTick(()=>{ let columnValue = model.value[tby] let cellValue = getTableCellValueV2(element.tableData, rowValue, columnValue) //console.log(cellValue); - model.value[element.name] = cellValue*1 + //console.log(element.name) + if(tbx!=""&&tby!=""){ + model.value[element.name] = cellValue*1 + } + //console.log(getTableCellValueV2(element.tableData, 3, 2)); From 50ad03c02b17bb77ac0f05da4d63103aadd42853 Mon Sep 17 00:00:00 2001 From: liwenxuan <1298531568@qq.com> Date: Thu, 8 Jan 2026 15:44:01 +0800 Subject: [PATCH 25/25] =?UTF-8?q?=E7=9F=A9=E9=98=B5=E5=A1=AB=E5=85=85?= =?UTF-8?q?=E5=8F=AF=E4=BB=85=E9=80=89=E6=A0=87=E9=A2=98=E8=A1=8C=E6=88=96?= =?UTF-8?q?=E7=B4=A2=E5=BC=95=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DesignForm/formControlPropertiNew.vue | 191 ++++++++--- .../DesignForm/public/form/form.vue | 306 +++++++++++++++++- 2 files changed, 438 insertions(+), 59 deletions(-) diff --git a/src/components/DesignForm/formControlPropertiNew.vue b/src/components/DesignForm/formControlPropertiNew.vue index acf4afb..b8d63a8 100644 --- a/src/components/DesignForm/formControlPropertiNew.vue +++ b/src/components/DesignForm/formControlPropertiNew.vue @@ -2910,7 +2910,10 @@ function mergeArrays(a, b) { //选项批量编辑 liwenxuan 20251212 end -//自动填充设置 liwenxuan 20251230 start + + + +// 自动填充设置 liwenxuan 20251230 start let datapropsformList = JSON.parse(JSON.stringify(props.formList)) @@ -2919,28 +2922,23 @@ const zdtcszTree = computed(()=>{ datapropsformList = JSON.parse(JSON.stringify(props.formList)) } - //console.log(datapropsformList) 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 const treeC = mergeAndFilterFormTrees(datapropsformList, datab,currentCompId); - //console.log(treeC) return treeC }else{ return [] } }) + // 使用 ref 替代 computed,使其可写 const zdtcszTableData = ref([]) // 获取当前正在设置自动填充的组件("结果"组件)的选项 const currentComponentOptions = computed(() => { - return controlData.value.options - }) // 获取当前选择的索引列节点(用于获取label) @@ -2957,7 +2955,7 @@ const currentTitleColumnNode = computed(() => { // 索引列的标签 const indexColumnLabel = computed(() => { - if (!currentIndexColumnNode.value) return "索引列" + if (!currentIndexColumnNode.value) return "默认行" return currentIndexColumnNode.value.label }) @@ -2991,8 +2989,8 @@ const zdtcszTableColumns = computed(() => { // 监听标题行和索引列的变化,重新生成表格数据 watch([titleOptions, indexOptions], ([newTitleOptions, newIndexOptions]) => { - // 如果没有标题行或索引列,清空表格数据 - if (!newTitleOptions.length || !newIndexOptions.length) { + // 如果都没有选择,清空表格数据 + if (!newTitleOptions.length && !newIndexOptions.length) { zdtcszTableData.value = [] return } @@ -3000,35 +2998,95 @@ watch([titleOptions, indexOptions], ([newTitleOptions, newIndexOptions]) => { // 从 controlData 中获取之前保存的数据 const savedData = controlData.value?.control?.zdtcsz?.tableData || {} - // 生成新的表格数据 - const newTableData = newIndexOptions.map(rowItem => { - const rowKey = rowItem.value + // 情况1:只有标题行,没有索引列 + if (newTitleOptions.length && !newIndexOptions.length) { + // 创建一行默认数据 + const defaultRowKey = 'default' const rowObj = { - rowKey: rowKey, - rowLabel: rowItem.label // 使用选项的label作为第一列显示 + rowKey: defaultRowKey, + rowLabel: '默认' // 第一列显示"默认" } // 为每个标题列生成值,如果有保存的数据则使用保存的数据 newTitleOptions.forEach(colItem => { const colKey = colItem.value - const savedValue = savedData[rowKey]?.[colKey] || '' + const savedValue = savedData[defaultRowKey]?.[colKey] || '' rowObj[`col_${colKey}`] = savedValue }) - return rowObj - }) - - zdtcszTableData.value = newTableData + zdtcszTableData.value = [rowObj] + } + // 情况2:只有索引列,没有标题行 + else if (!newTitleOptions.length && newIndexOptions.length) { + // 创建一个默认列 + const newTableData = newIndexOptions.map(rowItem => { + const rowKey = rowItem.value + const rowObj = { + rowKey: rowKey, + rowLabel: rowItem.label + } + + // 创建一个默认列 + const defaultColKey = 'default' + const savedValue = savedData[rowKey]?.[defaultColKey] || '' + rowObj[`col_${defaultColKey}`] = savedValue + + return rowObj + }) + + zdtcszTableData.value = newTableData + } + // 情况3:标题行和索引列都有 + else if (newTitleOptions.length && newIndexOptions.length) { + // 生成新的表格数据 + const newTableData = newIndexOptions.map(rowItem => { + const rowKey = rowItem.value + const rowObj = { + rowKey: rowKey, + rowLabel: rowItem.label + } + + // 为每个标题列生成值,如果有保存的数据则使用保存的数据 + newTitleOptions.forEach(colItem => { + const colKey = colItem.value + const savedValue = savedData[rowKey]?.[colKey] || '' + rowObj[`col_${colKey}`] = savedValue + }) + + return rowObj + }) + + zdtcszTableData.value = newTableData + } }, { immediate: true }) // 监听表格数据变化,保存到临时存储 const handleTableDataChange = () => { // 将表格数据转换为更容易存储的格式 const tableData = {} + zdtcszTableData.value.forEach(row => { const rowKey = row.rowKey tableData[rowKey] = {} - titleOptions.value.forEach(col => { + + // 获取当前有效的列 + let currentColumns = [] + if (titleOptions.value.length > 0) { + // 有标题行,使用标题行的选项 + currentColumns = titleOptions.value + } else if (zdtcszTableData.value[0]) { + // 没有标题行,从第一行数据中提取所有col_开头的字段 + const firstRow = zdtcszTableData.value[0] + Object.keys(firstRow).forEach(key => { + if (key.startsWith('col_')) { + const colKey = key.replace('col_', '') + currentColumns.push({ value: colKey }) + } + }) + } + + // 保存每一列的值 + currentColumns.forEach(col => { const colKey = col.value tableData[rowKey][colKey] = row[`col_${colKey}`] || '' }) @@ -3055,6 +3113,10 @@ const handleDetermineZdtcszDialogFlag = () => { console.log('左上角标签:', leftTopLabel.value) */ } + + + + /** * 合并两个组件树,仅保留type为radio和select的节点,并过滤掉指定compId的节点,同时保留options属性 * @param {Array} treeA - 组件树a,包含表单结构信息 @@ -8534,9 +8596,8 @@ const formatTooltip = (val: number) => { - - - + { align="center" /> - - - + + + @@ -8632,7 +8722,6 @@ const formatTooltip = (val: number) => { -
    审批流程