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/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/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/components/DesignForm/app/index.vue b/src/components/DesignForm/app/index.vue index e6c215f..b591429 100644 --- a/src/components/DesignForm/app/index.vue +++ b/src/components/DesignForm/app/index.vue @@ -45,6 +45,7 @@ import { import { formatNumber } from "@/api/DesignForm/utils"; import { formHasPower } from "@/directive/permission/button"; +import {printHtmlPage} from '../printHtmlRender.ts' //引入组件 import FormPageCont from "@/components/DesignForm/tableListPage/formPageCont.vue"; @@ -1186,17 +1187,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]]) @@ -1298,7 +1299,7 @@ async function doGainFormPageListCont(sendData: any) { } }); }); -console.log(data.data) +//console.log(data.data) return data.data; //tableDataList.value = data.data.list @@ -1619,90 +1620,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 @@ -2368,6 +2285,7 @@ const isObject = (obj: any) => { placement="top-end" > { } //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); } @@ -2828,6 +2831,1180 @@ function getAssociatedFormsCurrentFieldTree1() { } }); } + + +//选项批量编辑 liwenxuan 20251212 start + +// 初始选项数据 +const options = ref([]) + + + +// 弹窗显示状态 +const dialogVisible = ref(false) + +// 编辑时的文本内容(每行一个选项) +const editText = ref('') + +// 打开弹窗 +const openDialog = () => { + // 将选项数组转换为文本,每行一个 + editText.value = options.value.map(option => option.label).join('\n') + dialogVisible.value = true +} + +// 取消编辑 +const cancelEditing = () => { + dialogVisible.value = false + editText.value = '' +} + +// 保存更改 +const saveChanges = () => { + // 按行分割文本,过滤空行和空白字符 + const lines = editText.value + .split('\n') + .map(line => line.trim()) + .filter(line => line !== '') + + // 生成新的选项数组 + const newOptions = lines.map((label, index) => ({ + label, + value: (index + 1).toString() // 从1开始的正整数 + })) + + // 更新选项列表 + options.value = newOptions + + // 关闭弹窗 + dialogVisible.value = false + + // 清空编辑文本 + editText.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 + + + + +// 自动填充设置 liwenxuan 20251230 start + +let datapropsformList = JSON.parse(JSON.stringify(props.formList)) + +const zdtcszTree = computed(()=>{ + if(datapropsformList&&datapropsformList.length==0){ + datapropsformList = JSON.parse(JSON.stringify(props.formList)) + } + + if(associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf && associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children && associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children.length>0){ + let datab = JSON.parse(JSON.stringify(associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf.value[0].children)) + let currentCompId = controlData.value.name + const treeC = mergeAndFilterFormTrees(datapropsformList, datab,currentCompId); + return treeC + }else{ + return [] + } + +}) + +// 使用 ref 替代 computed,使其可写 +const zdtcszTableData = ref([]) + +// 获取当前正在设置自动填充的组件("结果"组件)的选项 +const currentComponentOptions = computed(() => { + return controlData.value.options +}) + +// 获取当前选择的索引列节点(用于获取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 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 || [] +}) + +const indexOptions = computed(() => { + return currentIndexColumnNode.value?.options || [] +}) + +// 表格列配置 +const zdtcszTableColumns = computed(() => { + return titleOptions.value.map(item => ({ + label: item.label, + value: item.value + })) +}) + +// 监听标题行和索引列的变化,重新生成表格数据 +watch([titleOptions, indexOptions], ([newTitleOptions, newIndexOptions]) => { + // 如果都没有选择,清空表格数据 + if (!newTitleOptions.length && !newIndexOptions.length) { + zdtcszTableData.value = [] + return + } + + // 从 controlData 中获取之前保存的数据 + const savedData = controlData.value?.control?.zdtcsz?.tableData || {} + + // 情况1:只有标题行,没有索引列 + if (newTitleOptions.length && !newIndexOptions.length) { + // 创建一行默认数据 + const defaultRowKey = 'default' + const rowObj = { + rowKey: defaultRowKey, + rowLabel: '默认' // 第一列显示"默认" + } + + // 为每个标题列生成值,如果有保存的数据则使用保存的数据 + newTitleOptions.forEach(colItem => { + const colKey = colItem.value + const savedValue = savedData[defaultRowKey]?.[colKey] || '' + rowObj[`col_${colKey}`] = savedValue + }) + + 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] = {} + + // 获取当前有效的列 + 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}`] || '' + }) + }) + + // 保存到 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('当前组件选项:', currentComponentOptions.value) + console.log('左上角标签:', leftTopLabel.value) */ +} + + + + + +/** + * 合并两个组件树,仅保留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 + +const glxxszTree = 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)) + + const treeC = mergeFormTrees(datapropsformList, datab); + console.log(treeC) + return treeC + }else{ + return null + } + +}) + + + +/** + * 合并两个组件树,以组件树a的结构为准,填充组件树b的数据 + * @param {Array} treeA - 组件树a,包含表单结构信息 + * @param {Array} treeB - 组件树b,包含字段数据信息 + * @returns {Array} - 合并后的组件树c + */ +function mergeFormTrees(treeA, treeB) { + // 构建b树的映射,key为name(从id中提取),value为b树节点 + const bMap = new Map(); + + // 从b树中提取通用的parentId(假设所有节点有相同的parentId) + let commonParentId = null; + + // 从id中提取name:formField:30540:upload1765154030446 -> upload1765154030446 + treeB.forEach(node => { + const id = node.id; + if (id) { + const parts = id.split(':'); + const name = parts[parts.length - 1]; // 取最后一部分作为name + bMap.set(name, node); + + // 设置通用的parentId + if (node.parentId && !commonParentId) { + commonParentId = node.parentId; + } + } + }); + + // 如果没有找到parentId,使用默认值 + if (!commonParentId) { + commonParentId = "formField:30540"; // 默认值,但最好从b树中获取 + } + + // 计数器 + let gridCount = 0; + let tabsCount = 0; + let divCount = 0; + let cardCount = 0; + + // 递归处理a树 + function processANode(node, parentId = commonParentId) { + // 获取当前节点的name + const nodeName = node.name; + + // 处理flex类型 + if (node.type === 'flex') { + // 查找b树中对应的节点 + let bNode = null; + if (nodeName && bMap.has(nodeName)) { + bNode = bMap.get(nodeName); + bMap.delete(nodeName); // 从map中删除,标记为已使用 + } + + let cNode; + let flexLabel = node.item?.label || nodeName || 'flex'; + + if (bNode) { + // 复制b节点的所有属性 + cNode = { ...bNode }; + // 确保children数组存在 + if (!cNode.children) { + cNode.children = []; + } + // 获取原来的label,如果没有则用name + const originalLabel = cNode.label || flexLabel; + // 在label左边拼接"弹性布局" + cNode.label = `弹性布局${originalLabel}`; + + // 如果treeAttrs.show存在,也更新 + if (cNode.treeAttrs && cNode.treeAttrs.show) { + cNode.treeAttrs.show = `弹性布局${cNode.treeAttrs.show}`; + } else if (cNode.treeAttrs) { + cNode.treeAttrs.show = `弹性布局${originalLabel}`; + } + + // 使用b节点的parentId + cNode.parentId = bNode.parentId || parentId; + } else { + // 如果b中不存在,则创建新节点 + cNode = { + id: nodeName ? `${commonParentId}:${nodeName}` : null, + label: `弹性布局${flexLabel}`, + parentId: parentId, + children: [], + value: nodeName ? `${commonParentId}:${nodeName}` : null, + treeAttrs: { + show: `弹性布局${flexLabel}` + }, + disabled: false, // flex类型即使叶子节点也可以选择,设为false + type: 'flex' + }; + } + + // 处理子组件 + let hasChildren = false; + if (node.list && Array.isArray(node.list)) { + const childNodes = []; + node.list.forEach(child => { + const processedChild = processANode(child, cNode.id); + if (processedChild) { + childNodes.push(processedChild); + hasChildren = true; + } + }); + cNode.children = childNodes; + } + + return cNode; + } + + // 处理table类型 + if (node.type === 'table') { + // 查找b树中对应的节点 + let bNode = null; + if (nodeName && bMap.has(nodeName)) { + bNode = bMap.get(nodeName); + bMap.delete(nodeName); // 从map中删除,标记为已使用 + } + + let cNode; + let tableLabel = node.item?.label || nodeName || 'table'; + + if (bNode) { + // 复制b节点的所有属性 + cNode = { ...bNode }; + // 确保children数组存在 + if (!cNode.children) { + cNode.children = []; + } + // 获取原来的label,如果没有则用name + const originalLabel = cNode.label || tableLabel; + // 在label左边拼接"子表" + cNode.label = `子表${originalLabel}`; + + // 如果treeAttrs.show存在,也更新 + if (cNode.treeAttrs && cNode.treeAttrs.show) { + cNode.treeAttrs.show = `子表${cNode.treeAttrs.show}`; + } else if (cNode.treeAttrs) { + cNode.treeAttrs.show = `子表${originalLabel}`; + } + + // 使用b节点的parentId + cNode.parentId = bNode.parentId || parentId; + } else { + // 如果b中不存在,则创建新节点 + cNode = { + id: nodeName ? `${commonParentId}:${nodeName}` : null, + label: `子表${tableLabel}`, + parentId: parentId, + children: [], + value: nodeName ? `${commonParentId}:${nodeName}` : null, + treeAttrs: { + show: `子表${tableLabel}` + }, + disabled: false, // table类型即使叶子节点也可以选择,设为false + type: 'table' + }; + } + + // 处理子组件 + let hasChildren = false; + if (node.list && Array.isArray(node.list)) { + const childNodes = []; + node.list.forEach(child => { + const processedChild = processANode(child, cNode.id); + if (processedChild) { + childNodes.push(processedChild); + hasChildren = true; + } + }); + cNode.children = childNodes; + } + + return cNode; + } + + // 处理grid类型 + if (node.type === 'grid') { + gridCount++; + const gridId = `格栅布局${gridCount}`; + const gridFullId = `${commonParentId}:${gridId}`; + + // 创建grid节点 + const cNode = { + id: gridFullId, + label: gridId, + parentId: parentId, + children: [], + value: gridFullId, + treeAttrs: { + show: gridId + }, + disabled: null, // 非叶子节点,设置为null + type: 'grid' + }; + + // 处理子组件(在columns.list中) + let hasChildren = false; + if (node.columns && Array.isArray(node.columns)) { + const childNodes = []; + node.columns.forEach(column => { + if (column.list && Array.isArray(column.list)) { + column.list.forEach(child => { + const processedChild = processANode(child, gridFullId); + if (processedChild) { + childNodes.push(processedChild); + hasChildren = true; + } + }); + } + }); + cNode.children = childNodes; + } + + // 如果没有子节点,设置disabled为true(容器类型叶子节点) + if (!hasChildren) { + cNode.disabled = true; + } + + return cNode; + } + + // 处理tabs类型 + if (node.type === 'tabs') { + tabsCount++; + const tabsId = `标签页${tabsCount}`; + const tabsFullId = `${commonParentId}:${tabsId}`; + + // 创建tabs节点 + const cNode = { + id: tabsFullId, + label: tabsId, + parentId: parentId, + children: [], + value: tabsFullId, + treeAttrs: { + show: tabsId + }, + disabled: null, // 非叶子节点,设置为null + type: 'tabs' + }; + + // 处理子组件(每个column作为一级) + let hasChildren = false; + if (node.columns && Array.isArray(node.columns)) { + const columnNodes = []; + node.columns.forEach((column, index) => { + // 为每个column创建一个节点 + const columnId = `${tabsFullId}:${column.label}`; + const columnNode = { + id: columnId, + label: column.label || `Tab${index + 1}`, + parentId: tabsFullId, + children: [], + value: columnId, + treeAttrs: { + show: column.label || `Tab${index + 1}` + }, + disabled: null, // 非叶子节点,设置为null + type: 'tab' + }; + + // 处理column中的子组件 + let columnHasChildren = false; + if (column.list && Array.isArray(column.list)) { + const childNodes = []; + column.list.forEach(child => { + const processedChild = processANode(child, columnId); + if (processedChild) { + childNodes.push(processedChild); + columnHasChildren = true; + hasChildren = true; + } + }); + columnNode.children = childNodes; + } + + // 如果column没有子节点,设置disabled为true(容器类型叶子节点) + if (!columnHasChildren) { + columnNode.disabled = true; + } + + columnNodes.push(columnNode); + }); + cNode.children = columnNodes; + } + + // 如果tabs没有子节点,设置disabled为true(容器类型叶子节点) + if (!hasChildren) { + cNode.disabled = true; + } + + return cNode; + } + + // 处理div类型 + if (node.type === 'div') { + divCount++; + const divId = `容器${divCount}`; + const divFullId = `${commonParentId}:${divId}`; + + // 创建div节点 + const cNode = { + id: divFullId, + label: divId, + parentId: parentId, + children: [], + value: divFullId, + treeAttrs: { + show: divId + }, + disabled: null, // 非叶子节点,设置为null + type: 'div' + }; + + // 处理子组件 + let hasChildren = false; + if (node.list && Array.isArray(node.list)) { + const childNodes = []; + node.list.forEach(child => { + const processedChild = processANode(child, divFullId); + if (processedChild) { + childNodes.push(processedChild); + hasChildren = true; + } + }); + cNode.children = childNodes; + } + + // 如果没有子节点,设置disabled为true(容器类型叶子节点) + if (!hasChildren) { + cNode.disabled = true; + } + + return cNode; + } + + // 处理card类型 + if (node.type === 'card') { + cardCount++; + const cardId = `卡片${cardCount}`; + const cardFullId = `${commonParentId}:${cardId}`; + + // 创建card节点 + const cNode = { + id: cardFullId, + label: cardId, + parentId: parentId, + children: [], + value: cardFullId, + treeAttrs: { + show: cardId + }, + disabled: null, // 非叶子节点,设置为null + type: 'card' + }; + + // 处理子组件 + let hasChildren = false; + if (node.list && Array.isArray(node.list)) { + const childNodes = []; + node.list.forEach(child => { + const processedChild = processANode(child, cardFullId); + if (processedChild) { + childNodes.push(processedChild); + hasChildren = true; + } + }); + cNode.children = childNodes; + } + + // 如果没有子节点,设置disabled为true(容器类型叶子节点) + if (!hasChildren) { + cNode.disabled = true; + } + + return cNode; + } + + // 处理其他类型 + // 查找b树中对应的节点 + let bNode = null; + if (nodeName && bMap.has(nodeName)) { + bNode = bMap.get(nodeName); + bMap.delete(nodeName); // 从map中删除,标记为已使用 + } + + // 创建c树节点 + let cNode; + if (bNode) { + // 复制b节点的所有属性 + cNode = { ...bNode }; + // 确保children数组存在 + if (!cNode.children) { + cNode.children = []; + } + // 使用b节点的parentId + cNode.parentId = bNode.parentId || parentId; + } else { + return null; // b中不存在且不是上述容器类型,则忽略 + } + + // 判断是否为叶子节点 + let hasChildren = false; + + // 对于非容器节点,判断是否有子节点 + // 从b节点中获取children信息 + hasChildren = cNode.children && cNode.children.length > 0; + + // 设置disabled属性 + // 容器类型列表 + const containerTypes = ['card', 'div', 'grid', 'tabs']; + + // 如果是容器类型 + if (containerTypes.includes(node.type)) { + // 如果有子节点,设置为null,否则设置为true + cNode.disabled = hasChildren ? null : true; + } else { + // 如果是非容器类型,叶子节点disabled为false + cNode.disabled = false; + } + + return cNode; + } + + // 处理a树的所有根节点 + const cTree = []; + treeA.forEach(rootNode => { + const processedNode = processANode(rootNode); + if (processedNode) { + cTree.push(processedNode); + } + }); + + // 将b树中剩余的元素(在a中不存在的)添加到c树中 + bMap.forEach(bNode => { + // 保留b节点的原始结构 + const newNode = { ...bNode }; + + // 确保children数组存在 + if (!newNode.children) { + newNode.children = []; + } + + // 判断是否为叶子节点 + const hasChildren = newNode.children && newNode.children.length > 0; + + // 容器类型列表(包括flex和table) + const containerTypes = ['card', 'div', 'grid', 'tabs', 'flex', 'table']; + // 判断节点是否是容器类型 + const isContainer = containerTypes.includes(newNode.type); + + // 设置disabled属性 + if (isContainer) { + // 对于flex和table,即使叶子节点也可以选择,设为false + if (newNode.type === 'flex' || newNode.type === 'table') { + newNode.disabled = false; + } else { + // 其他容器类型:有子节点为null,否则为true + newNode.disabled = hasChildren ? null : true; + } + } else { + // 非容器类型:叶子节点为false + newNode.disabled = false; + } + + cTree.push(newNode); + }); + + return cTree; +} + +// 使用示例 +// const treeC = mergeFormTrees(treeA, treeB); +//关联选项设置优化为树 liwenxuan 20251209 end + + + function removeTreeNode(tree: any, targetId: any) { // 深拷贝原始树结构避免污染原数据 const clonedTree = JSON.parse(JSON.stringify(tree)); @@ -3429,6 +4606,7 @@ function handleDetermineAssociatedFormsChooseDialog() { //liwenxuan20240426 单选多选下拉 关联选项设置 start +const ZdtcszDialogFlag = ref(false); const glxxszDialogFlag = ref(false); const glxxszDialogFlagCheckBox = ref(false); const glxxszDialogFlagSwitch = ref(false); @@ -3450,6 +4628,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; } @@ -5473,7 +6669,7 @@ const formatTooltip = (val: number) => { @@ -5534,7 +6730,7 @@ const formatTooltip = (val: number) => { -
+

选项配置

--> 选项配置 - { v-model="controlData.config.addAll" placeholder="请输入全部项文案" /> - + --> {
+ {{ controlData.type === "cascader" ? "编辑" : "新增" }} + + 批量导入 + +
+
+ 关联选项设置 +
+
+ 关联选项设置 +
+
+ 关联选项设置 +
+ +
+ 矩阵填充设置 +
+
+ + @@ -7190,8 +8423,14 @@ const formatTooltip = (val: number) => { @@ -7262,8 +8501,14 @@ const formatTooltip = (val: number) => { controlData.control.glxxszForCheckBox[fieldScope.$index].showFields " style="width: 100%" - :data="associatedFormsCurrentFormFieldTreeForGlxxszExceptSelf[0].children" + :data="glxxszTree" multiple + show-checkbox + collapse-tags + collapse-tags-tooltip + :max-collapse-tags="2" + clearable + filterable /> @@ -7310,8 +8555,14 @@ const formatTooltip = (val: number) => {
@@ -7321,8 +8572,14 @@ const formatTooltip = (val: number) => {
@@ -7339,9 +8596,142 @@ const formatTooltip = (val: number) => { + + + +
+ + 标题行 + + + + + + 索引列 + + + +
+ +
+ + + + + + + + +
+ + +
+ + + + - + + { + + + +
+ +
+ + 每行对应一个选项 +
+ + +
+ +
+
+ + +
+ + + + + @@ -7569,4 +9003,6 @@ li::before { .card-header { text-align: right; } + + diff --git a/src/components/DesignForm/printHtmlRender.ts b/src/components/DesignForm/printHtmlRender.ts new file mode 100644 index 0000000..9c0c126 --- /dev/null +++ b/src/components/DesignForm/printHtmlRender.ts @@ -0,0 +1,120 @@ +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"; +import { useOrgMemberStore } from "@/store/modules/orgMember"; + +const printRenderTree: Ref = ref([]); +const orgMembers = useOrgMemberStore() +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 + }) + } + + 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 + } + + if(resp.data.pageconfigjson!=""){ + _pageConfig=JSON.parse(resp.data.pageconfigjson) + if(_pageConfig.founder!=""){ + _pageConfig.founder=row[_pageConfig.founder] + _pageConfig.deptOrg=orgMembers.listMap[row.createrOrg] + } + + if(_pageConfig.founderTime!=""){ + _pageConfig.founderTime=row[_pageConfig.founderTime] + } + + _pageConfig.masters_key=row.masters_key + } + }) + + 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=>{ + 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, + flowList:flowlist, + 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.type=="tabs"&&node.child){ + node.child?.forEach(item=>{deepLoopForm(item,row)}) + return + } + + 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 diff --git a/src/components/DesignForm/printHtmlRender.vue b/src/components/DesignForm/printHtmlRender.vue index 866abc8..b5e2d11 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[] } @@ -23,7 +24,7 @@ export interface PageConfig{ founder:string; founderTime:string; deptOrg:string; - serialNumber:string; + masters_key:string; qrcode:boolean; } @@ -31,16 +32,26 @@ const props = withDefaults(defineProps<{ name:string, pageConfig:PageConfig, fieldTree:fieldTree[], + flowList:any[], qrcode?:string, }>(),{}) 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() - return str.slice(0,10)+" "+str.slice(11,16) +function parseDataPicker(val:string,vtype:string){ + let str:string; + if(typeof(val)=="number"){ + str=new Date(val).toLocaleString() + }else{//"";2025-12-17;sheng1chan3ri4qi1;三种值直接返回 + if(val==""|| val.match(/[a-z-:.]/) ) return val; + str=new Date(parseInt(val)).toLocaleString() + } + + if(vtype.startsWith("time")){ + return str.slice(11,16) + } + return str.slice(0,10) } const generateQrCode= ()=>{ @@ -61,19 +72,28 @@ const generateQrCode= ()=>{ }) } +const getStateText=(val:number)=>{ + if(val==1) return "未操作" + if(val==2) return "已同意" + if(val==3) return "已驳回" + if(val==4) return "已查看" + return "未操作" +} + @@ -92,29 +112,45 @@ const generateQrCode= ()=>{
{{ group.name }}
{{ group.field }}
-
-
{{ group.name }}
-
- - - -
+
+ + + + + + + + + + + + +
{{ group.name }}
{{ group.name }}
- +
{{ tabs.name }}
-
- - - -
+ + + + + + + + + + + +
-
+
{{tabs.name}} {{tabs.field}} - {{parseDataPicker(tabs.field??'')}} + {{parseDataPicker(tabs.field??'',tabs.type)}}
-
{{ group }}
- +
{{ group }}
-
+ +
+ + + + + + + + + + + + + + +
审批流程
审批节点处理人操作记录
+
+ +
{{ generateQrCode() }}
@@ -158,6 +258,7 @@ v-else-if="tabs.type=='divider'" v-if="tabs.checked!=2" class="title"
+
diff --git a/src/components/DesignForm/public/form/form.vue b/src/components/DesignForm/public/form/form.vue index 1afd0a1..d5772cf 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) @@ -899,6 +908,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 +927,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&&!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&&!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 if (props.formData.list[i].type == "checkbox") { checkboxShowConfigArr.push(props.formData.list[i].control.glxxszForCheckBox); @@ -939,6 +959,10 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(a[w].control.glxxsz); } + 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) + } //radioSelectShowConfigArr.push(a[w].control.glxxsz); } else if (a[w].type == "checkbox") { checkboxShowConfigArr.push(a[w].control.glxxszForCheckBox); @@ -960,6 +984,11 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(a.control.glxxsz); } + if(a.control.zdtcsz&&!isEmptyPlainObject(a.control.zdtcsz.tableData)){ + 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 +1013,10 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(a.control.glxxsz); } + if(a.control.zdtcsz&&!isEmptyPlainObject(a.control.zdtcsz.tableData)){ + 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 +1032,10 @@ function showOrHide(data: any) { } else { checkboxShowConfigArr.push(q.control.glxxsz); } + if(q.control.zdtcsz&&!isEmptyPlainObject(q.control.zdtcsz.tableData)){ + 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 +1056,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,8 +1275,377 @@ function showOrHide(data: any) { //props.formData.config?.hideField?.push("nin2yuan4yi4wei4wo3menda3fen1ma101939") //console.log("监听表单--constControlChange-->",key, value, data, tProp,type,attribute)//liwenxuan + + + +//console.log(radioSelectZdtcszConfigArr) +nextTick(()=>{ + //console.log(model.value)// + radioSelectZdtcszConfigArr.forEach(element => { + let tbx=getLastColonAfterString(element.tbx) + let tby=getLastColonAfterString(element.tby) + /* console.log(tbx) + console.log(tby) */ + + //console.log(element.name) + let rowValue = model.value[tbx] + //console.log(rowValue) + let columnValue = model.value[tby] + //console.log(columnValue) + if(tbx!=""&&tby!=""){ + + let cellValue = getTableCellValue(element.tableData, rowValue, columnValue) + model.value[element.name] = cellValue*1 + }else if(tbx!=""&&tby==""){ + //console.log("仅设置了标题行") + let cellValue = getTableCellValue(element.tableData, rowValue, 'default') + //console.log(cellValue) + model.value[element.name] = cellValue*1 + }else if(tbx==""&&tby!=""){ + //console.log("仅设置了索引列") + let cellValue = getTableCellValue(element.tableData, 'any', 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); +} + + + +/** + * 获取表格单元格值,兼容多种tableData结构 + * 支持三种结构: + * 1. 标准行列结构:{列号: {行号: 值, ...}, ...} + * 2. 仅一行结构:{default: {列号: 值, ...}} + * 3. 仅一列结构:{列号: {default: 值}, ...} + * + * @param {Object} tableData - 表格数据 + * @param {String|Number} rowValue - 行标识 + * @param {String|Number} columnValue - 列标识 + * @returns {String|undefined} - 返回对应的单元格值,如果未找到则返回undefined + */ +function getTableCellValueV3(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); + + // 1. 首先尝试检测是否为仅一行结构(有default行) + if (tableData.default && typeof tableData.default === 'object') { + // 这是仅一行结构:{default: {列号: 值, ...}} + // 忽略行值,直接使用列值 + return tableData.default?.[columnStr]; + } + + // 2. 尝试标准结构或仅一列结构 + const columnObj = tableData[columnStr]; + if (columnObj && typeof columnObj === 'object') { + // 2.1 尝试从列对象中获取行值 + const cellValue = columnObj[rowStr]; + if (cellValue !== undefined) { + return cellValue; // 找到标准结构的值 + } + + // 2.2 如果没找到标准结构的行值,检查是否是仅一列结构(有default值) + if (columnObj.default !== undefined) { + // 这是仅一列结构:{列号: {default: 值}, ...} + // 忽略行值,返回该列的default值 + return columnObj.default; + } + } + + // 3. 如果没有匹配任何结构,尝试其他可能的查找方式 + + // 3.1 如果列不存在,检查所有列是否有default值(用于仅一列结构) + if (!columnObj) { + // 遍历所有列,看是否有匹配的列号 + for (const colKey in tableData) { + if (String(colKey) === columnStr) { + const colData = tableData[colKey]; + if (colData && typeof colData === 'object' && colData.default !== undefined) { + return colData.default; + } + } + } + } + + // 3.2 检查是否有default行(可能列名不是字符串"default") + for (const key in tableData) { + const data = tableData[key]; + if (data && typeof data === 'object') { + // 检查这个对象是否是一个行数据(包含列号作为键) + if (data[columnStr] !== undefined) { + // 这可能是行数据,返回对应的列值 + return data[columnStr]; + } + } + } + + // 4. 所有尝试都失败,返回undefined + return undefined; + } catch (error) { + // 如果发生任何错误,返回undefined + console.error('获取表格单元格值时发生错误:', error); + return undefined; + } } +/** + * 增强版:自动检测tableData结构并获取值 + * 支持动态结构检测 + */ +function getTableCellValueEnhanced(tableData, rowValue, columnValue) { + try { + if (!tableData || typeof tableData !== 'object') { + return undefined; + } + + if (rowValue == null || columnValue == null) { + return undefined; + } + + const rowStr = String(rowValue); + const columnStr = String(columnValue); + + // 先尝试直接获取(标准结构) + const directValue = tableData?.[columnStr]?.[rowStr]; + if (directValue !== undefined) { + return directValue; + } + + // 检测表格结构 + const tableStructure = detectTableStructure(tableData); + + switch (tableStructure) { + case 'standard': + // 标准结构,已经尝试过直接获取 + break; + + case 'singleRow': + // 仅一行结构 + return getFromSingleRowStructure(tableData, columnStr); + + case 'singleColumn': + // 仅一列结构 + return getFromSingleColumnStructure(tableData, columnStr); + + case 'mixed': + // 混合结构,尝试多种方式 + return getFromMixedStructure(tableData, rowStr, columnStr); + + default: + // 未知结构,返回undefined + return undefined; + } + + return undefined; + } catch (error) { + console.error('获取表格单元格值时发生错误:', error); + return undefined; + } +} + +/** + * 检测tableData的结构 + * @returns {string} - 结构类型:'standard', 'singleRow', 'singleColumn', 'mixed', 'unknown' + */ +function detectTableStructure(tableData) { + if (!tableData || typeof tableData !== 'object') { + return 'unknown'; + } + + const keys = Object.keys(tableData); + if (keys.length === 0) { + return 'empty'; + } + + // 检查是否为仅一行结构(有default键) + if (keys.length === 1 && keys[0] === 'default') { + const defaultData = tableData.default; + if (defaultData && typeof defaultData === 'object') { + // 检查default对象的值是否都是简单值(不是对象) + const hasNestedObjects = Object.values(defaultData).some( + value => value && typeof value === 'object' + ); + if (!hasNestedObjects) { + return 'singleRow'; + } + } + } + + // 检查是否为仅一列结构 + let isSingleColumn = true; + for (const key of keys) { + const colData = tableData[key]; + if (!colData || typeof colData !== 'object') { + isSingleColumn = false; + break; + } + + // 检查是否只有default键或只有一个键 + const colKeys = Object.keys(colData); + if (colKeys.length !== 1 || (colKeys.length === 1 && colKeys[0] !== 'default')) { + // 如果有多个键,或者唯一的键不是default,则不是仅一列结构 + if (colKeys.length > 1 || (colKeys.length === 1 && !colKeys[0].match(/^\d+$/))) { + isSingleColumn = false; + break; + } + } + } + + if (isSingleColumn) { + return 'singleColumn'; + } + + // 检查是否为标准结构(所有值都是对象,且对象键是行号) + let isStandard = true; + for (const key of keys) { + const colData = tableData[key]; + if (!colData || typeof colData !== 'object') { + isStandard = false; + break; + } + + // 检查对象键是否都是数字字符串(表示行号) + const colKeys = Object.keys(colData); + if (colKeys.length === 0) { + isStandard = false; + break; + } + + // 允许有default键和其他键混合 + const hasNonNumericKeys = colKeys.some(k => k !== 'default' && !k.match(/^\d+$/)); + if (hasNonNumericKeys) { + isStandard = false; + break; + } + } + + if (isStandard) { + return 'standard'; + } + + // 混合结构 + return 'mixed'; +} + +/** + * 从仅一行结构中获取值 + */ +function getFromSingleRowStructure(tableData, columnStr) { + return tableData.default?.[columnStr]; +} + +/** + * 从仅一列结构中获取值 + */ +function getFromSingleColumnStructure(tableData, columnStr) { + const colData = tableData[columnStr]; + if (colData && typeof colData === 'object') { + // 优先返回default值,如果没有则返回第一个值 + return colData.default !== undefined ? colData.default : Object.values(colData)[0]; + } + return undefined; +} + +/** + * 从混合结构中获取值 + */ +function getFromMixedStructure(tableData, rowStr, columnStr) { + // 尝试多种方式 + + // 1. 尝试标准方式 + const standardValue = tableData?.[columnStr]?.[rowStr]; + if (standardValue !== undefined) { + return standardValue; + } + + // 2. 检查该列是否有default值 + const columnData = tableData[columnStr]; + if (columnData && typeof columnData === 'object') { + if (columnData.default !== undefined) { + return columnData.default; + } + } + + // 3. 检查是否有default行 + if (tableData.default && typeof tableData.default === 'object') { + return tableData.default[columnStr]; + } + + // 4. 遍历查找 + for (const key in tableData) { + const data = tableData[key]; + if (data && typeof data === 'object') { + // 如果这个对象有我们要找的列键 + if (data[columnStr] !== undefined) { + return data[columnStr]; + } + // 如果键名匹配列,并且有我们要找的行键 + if (key === columnStr && data[rowStr] !== undefined) { + return data[rowStr]; + } + } + } + + return undefined; +} + +/** + * 统一方法,推荐使用这个 + */ +function getTableCellValue(tableData, rowValue, columnValue) { + return getTableCellValueEnhanced(tableData, rowValue, columnValue); +} + + + + + + + function addStringIfNotExists(arr: string[], str: string) { if (!arr.includes(str)) { arr.push(str); diff --git a/src/components/DesignForm/public/form/formItem.vue b/src/components/DesignForm/public/form/formItem.vue index 87f03fd..40fb82c 100644 --- a/src/components/DesignForm/public/form/formItem.vue +++ b/src/components/DesignForm/public/form/formItem.vue @@ -144,8 +144,16 @@ function onValueChange(_type: string) { //select 组件特殊处理 function onSekectValueChange(news:number){ if(props.data.options){ + let _label=""; + for(const op of props.data.options){ + if(op.value==news.toString()){ + _label= op.label + break; + } + } + fieldChangeEnt && - fieldChangeEnt({key:props.data.name,value:props.data.options[news-1].label, field:props.data.item.label,rowdex:props.rowIndex}) + fieldChangeEnt({key:props.data.name,value:_label, field:props.data.item.label,rowdex:props.rowIndex}) } } diff --git a/src/components/DesignForm/tableListPage/formPageCont.vue b/src/components/DesignForm/tableListPage/formPageCont.vue index 54b3d76..9ceeffa 100644 --- a/src/components/DesignForm/tableListPage/formPageCont.vue +++ b/src/components/DesignForm/tableListPage/formPageCont.vue @@ -37,6 +37,7 @@ import RunFlowStep from "@/views/taskplatform/taskmanagement/runFlowStep.vue"; import { customerFormVersionCont } from "@/api/taskapi/types"; import { stringify } from "uuid"; import { nodePoweInfo } from "@/api/taskapi/types"; +import {printHtmlPage} from '../printHtmlRender.ts' const props = defineProps({ isShow: { @@ -231,6 +232,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) */ @@ -572,6 +584,7 @@ provide('currentNodeKey', nodeKey) + 打印 { 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 @@ -2109,6 +2029,7 @@ const isObject = (obj: any) => { placement="top-end" > { 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/doc/manage.vue b/src/views/doc/manage.vue index 638f139..f0fc0eb 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' @@ -22,12 +22,13 @@ import {ElSelect,ElOption, ElText,ElInput,TableInstance,ElMessage,UploadFile, UploadFiles,ElPagination,ElTree,TreeNode,ElDropdown,ElDropdownItem} from "element-plus"; import preview from './preview.vue'; import uploadlog from './uploadlog.vue'; -import space from './space.vue'; +import { useRoute } from 'vue-router' import spacePermission from './spacePermission.vue'; 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 ..................... @@ -60,7 +61,7 @@ const treeRef = ref(); const currentNode=ref({}) //打开的路径层次 const officeHost=import.meta.env.VITE_OFFICE_HOST const dynamicVNode = ref(null) //permission 组件的父组件 - +const route = useRoute() const multipleTableRef = ref() const paginInfo = ref({ page: 0, total: 0 }) @@ -69,7 +70,7 @@ const PRIVATESPACE = ref(true) //是空间状态的控制 2种:私有云盘和 const SpaceID= ref<{name:string,uuid:string,userUuid:string,manager:boolean,permits:matterPermit}>({}) //当前space的id const spaceEleRef = ref() //space组件的引用,它与spaceTreeRef没有父子关系,反而是为了处理spaceTree的操作而创建的该变量 const spaceTreeData=ref([])//{name:'个人空间',uuid:'root',children:[]} -const spaceTreeRef = ref(); //space的树树组件的引用 +const spaceTreeRef = ref(); //space的树组件的引用 let spaceNodeUid="" //用来判断树组件的展开和关闭,如何只是展开和关闭的点击事件不在刷新,通currentNode的作用 const modListOrGrild=ref(true) @@ -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 = { @@ -596,7 +621,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+"上传失败!
") @@ -661,7 +686,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 +" 上传失败!
") @@ -857,6 +882,15 @@ function onAiAgent(row:matterInfo){ }) } +//空间分享链接 +const onSpaceShareRequest=(spaceid:string,name:string)=>{ + spaceTreeRef.value.data.forEach(item=>{ + if(item.uuid==spaceid){ + onSpaceNodeClick(item,null,null,null) + } + }) +} + //设置智能体联网查询地址 async function onAgentQueryURL(row:matterInfo){ await getAgentQueryURL(row.uuid).then(resp=>{ @@ -892,7 +926,7 @@ async function onAgentQueryURL(row:matterInfo){ //------------------------------------------------------ //http://172.20.2.87:6010/api/alien/preview/5a10aaf6-396e-4d9a-7e87-3c5c8029d4db/123.png?ir=fill_100_100 //渲染完页面再执行 -onMounted(() => { +onMounted(async () => { // treeRef.value.append( // {name:'个人空间',uuid:'root',dir:false}, // currentNode.value.uuid @@ -900,7 +934,7 @@ onMounted(() => { currentNode.value={uuid:"root"} //加载我的空间列表 - getMySpaces(uid,{roles:Departs.value}).then((resp)=>{ + await getMySpaces(uid,{roles:Departs.value}).then((resp)=>{ resp.data.forEach((item)=>{ let ismanager=false if(item.userUuid==rawUid || item.managers.includes(rawUid)) ismanager=true; @@ -913,6 +947,14 @@ onMounted(() => { }else{ modListOrGrild.value=true } + + const query = route.query + if(query.s_token){ + const s_token=decodeURIComponent(atob(query.s_token as string)).split("|") + if(s_token.length==3){ + onSpaceShareRequest(s_token[0],s_token[2]) + } + } }); const handleSelectionChange = (val:matterInfo[]) => { @@ -1081,7 +1123,8 @@ v-if="modListOrGrild" - + +
@@ -1119,6 +1162,7 @@ v-if="modListOrGrild"
  • 分享
  • 下载
  • 编辑
  • +
  • 移动
  • 删除
  • 重命名
  • @@ -1238,6 +1282,7 @@ ref="spaceEleRef" :uid="uid" :raw-uid="rawUid" :list-or-grid="modListOrGrild" 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 d682a7e..126fd54 100644 --- a/src/views/doc/space.vue +++ b/src/views/doc/space.vue @@ -5,29 +5,30 @@ -->