From e6b9831da844946765ad3a43504ab322fd609393 Mon Sep 17 00:00:00 2001 From: b2894lxlx <517289602@qq.com> Date: Mon, 11 May 2026 18:13:33 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E6=96=87=E4=BB=B6=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E5=90=84=E4=B8=AA=E5=AE=A1=E8=AE=A1=E5=86=85=E5=AE=B9=E5=88=86?= =?UTF-8?q?=E7=A6=BB=E4=BF=9D=E5=AD=98=202=E3=80=81=E5=8B=BE=E9=80=89?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E5=90=8E=EF=BC=8C=E8=87=AA=E5=8A=A8=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/components/FileModal.vue | 121 +++++++++++++++--- .../pwlProject/components/reportContent.vue | 108 +++++++++++++--- 2 files changed, 193 insertions(+), 36 deletions(-) diff --git a/src/views/pwl/pwlProject/components/components/FileModal.vue b/src/views/pwl/pwlProject/components/components/FileModal.vue index 709b840..5ece9e5 100644 --- a/src/views/pwl/pwlProject/components/components/FileModal.vue +++ b/src/views/pwl/pwlProject/components/components/FileModal.vue @@ -106,6 +106,7 @@ const props = defineProps<{ currentCompanyId: number; + selectionKey?: string; }>(); const emit = defineEmits<{ @@ -169,29 +170,52 @@ return buildTree(0); }); - const lastSelectedDirKeys = ref<(string | number)[]>([]); - const lastSelectedFileKeys = ref<(string | number)[]>([]); + const selectionStateMap = ref< + Record< + string, + { + dirKeys: (string | number)[]; + fileKeys: (string | number)[]; + } + > + >({}); // const currentSectionIndex = ref(2); // 默认是审计内容3 const selectedDocList = ref([]); const selectedFileList = ref([]); const selectedFileKeys = ref<(string | number)[]>([]); const checkedDirKeys = ref<(string | number)[]>([]); // 新增:勾选的目录keys + const dirFileKeyCache = ref>({}); + const getSelectionStorageKey = () => props.selectionKey || '__default__'; + + const saveSelectionState = () => { + selectionStateMap.value[getSelectionStorageKey()] = { + dirKeys: [...checkedDirKeys.value], + fileKeys: [...selectedFileKeys.value] + }; + }; + + const restoreSelectionState = () => { + const state = selectionStateMap.value[getSelectionStorageKey()]; + checkedDirKeys.value = [...(state?.dirKeys || [])]; + selectedFileKeys.value = [...(state?.fileKeys || [])]; + selectedDocList.value = checkedDirKeys.value.map((key) => key.toString()); + selectedFileList.value = selectedFileKeys.value.map((key) => + key.toString() + ); + }; + const handleDocSelectCancel = () => { - // 保存当前选择状态 - lastSelectedDirKeys.value = [...checkedDirKeys.value]; - lastSelectedFileKeys.value = [...selectedFileKeys.value]; + saveSelectionState(); showDocSelect.value = false; }; const confirmSelection = () => { - // 保存当前选择状态 - lastSelectedDirKeys.value = [...checkedDirKeys.value]; - lastSelectedFileKeys.value = [...selectedFileKeys.value]; + saveSelectionState(); // 传递选择的数据给父组件 emit('confirm', { - dirKeys: lastSelectedDirKeys.value, - fileKeys: lastSelectedFileKeys.value + dirKeys: [...checkedDirKeys.value], + fileKeys: [...selectedFileKeys.value] }); message.success( @@ -240,10 +264,72 @@ loadCloudFiles(); }; - // 新增:目录勾选处理 - const onDirCheck = (checkedKeys: (string | number)[]) => { - checkedDirKeys.value = checkedKeys; - selectedDocList.value = checkedKeys.map((key) => key.toString()); + const getCheckedKeyList = (checkedKeys: any) => { + return Array.isArray(checkedKeys) + ? checkedKeys + : Array.isArray(checkedKeys?.checked) + ? checkedKeys.checked + : []; + }; + + const getDirFileKeys = async (dirKey: string | number) => { + const cacheKey = String(dirKey); + if (dirFileKeyCache.value[cacheKey]) { + return dirFileKeyCache.value[cacheKey]; + } + + const files = await listAiCloudFile({ + docId: Number(dirKey) + }); + const fileKeys = (files || []) + .map((item) => item.id) + .filter((id) => id !== undefined && id !== null) as (string | number)[]; + + dirFileKeyCache.value[cacheKey] = fileKeys; + return fileKeys; + }; + + // 目录勾选处理:勾选目录时全选该目录下文件,取消时反选 + const onDirCheck = async (checkedKeys: any) => { + const nextCheckedKeys = getCheckedKeyList(checkedKeys); + const prevCheckedKeys = [...checkedDirKeys.value]; + const addedKeys = nextCheckedKeys.filter( + (key) => !prevCheckedKeys.includes(key) + ); + const removedKeys = prevCheckedKeys.filter( + (key) => !nextCheckedKeys.includes(key) + ); + + checkedDirKeys.value = nextCheckedKeys; + selectedDocList.value = nextCheckedKeys.map((key) => key.toString()); + + if (!addedKeys.length && !removedKeys.length) { + saveSelectionState(); + return; + } + + try { + const addedFileGroups = await Promise.all( + addedKeys.map((key) => getDirFileKeys(key)) + ); + const removedFileGroups = await Promise.all( + removedKeys.map((key) => getDirFileKeys(key)) + ); + + const nextFileKeySet = new Set<(string | number)>(selectedFileKeys.value); + addedFileGroups.flat().forEach((key) => nextFileKeySet.add(key)); + removedFileGroups.flat().forEach((key) => nextFileKeySet.delete(key)); + + selectedFileKeys.value = Array.from(nextFileKeySet); + selectedFileList.value = selectedFileKeys.value.map((key) => + key.toString() + ); + } catch (error) { + message.error('目录文件联动选择失败'); + console.error('目录文件联动选择失败:', error); + } + + saveSelectionState(); }; // 异步加载子节点 @@ -276,7 +362,8 @@ selectedRows: AiCloudFile[] ) => { selectedFileKeys.value = selectedRowKeys; - selectedFileList.value = selectedRows.map((row) => row.id!.toString()); + selectedFileList.value = selectedRowKeys.map((key) => key.toString()); + saveSelectionState(); }; // 清空选择 @@ -291,6 +378,8 @@ selectedDocList.value = [selectedKeys.value[0].toString()]; checkedDirKeys.value = [selectedKeys.value[0]]; // 新增:重新勾选当前目录 } + + saveSelectionState(); }; const loadCloudFiles = async () => { @@ -334,6 +423,8 @@ const open = () => { showDocSelect.value = true; + restoreSelectionState(); + dirFileKeyCache.value = {}; loadAllCloudDocs(); }; diff --git a/src/views/pwl/pwlProject/components/reportContent.vue b/src/views/pwl/pwlProject/components/reportContent.vue index 031c775..00491af 100644 --- a/src/views/pwl/pwlProject/components/reportContent.vue +++ b/src/views/pwl/pwlProject/components/reportContent.vue @@ -491,6 +491,7 @@ ([]); const selectedFileList = ref([]); const selectedFileKeys = ref<(string | number)[]>([]); const checkedDirKeys = ref<(string | number)[]>([]); - const lastSelectedDirKeys = ref<(string | number)[]>([]); - const lastSelectedFileKeys = ref<(string | number)[]>([]); + const tableFileSelectionMap = reactive< + Record< + string, + { + dirKeys: (string | number)[]; + fileKeys: (string | number)[]; + } + > + >({}); // ========== 取证单相关 ========== const evidenceModalVisible = ref(false); @@ -694,6 +703,34 @@ }; }; + const getTableFileSelection = (tableKey: string) => { + return ( + tableFileSelectionMap[tableKey] || { + dirKeys: [], + fileKeys: [] + } + ); + }; + + const applyTableFileSelection = (tableKey: string) => { + const selection = getTableFileSelection(tableKey); + checkedDirKeys.value = [...selection.dirKeys]; + selectedFileKeys.value = [...selection.fileKeys]; + selectedDocList.value = selection.dirKeys.map((key) => key.toString()); + selectedFileList.value = selection.fileKeys.map((key) => key.toString()); + }; + + const saveTableFileSelection = ( + tableKey: string, + dirKeys: (string | number)[] = [], + fileKeys: (string | number)[] = [] + ) => { + tableFileSelectionMap[tableKey] = { + dirKeys: [...dirKeys], + fileKeys: [...fileKeys] + }; + }; + // ========== 通用方法 ========== /* 更新visible */ @@ -728,6 +765,11 @@ section.data = []; } + if (currentSectionIndex.value === sectionIndex) { + currentFileSelectionKey.value = tableKey; + applyTableFileSelection(tableKey); + } + selectedRowsMap[sectionIndex] = []; selectedRowKeysMap[sectionIndex] = []; @@ -736,10 +778,16 @@ /* 处理文件选择确认 */ const handleFileSelectConfirm = (data: { dirKeys: (string | number)[], fileKeys: (string | number)[] }) => { + if (currentFileSelectionKey.value) { + saveTableFileSelection( + currentFileSelectionKey.value, + data.dirKeys, + data.fileKeys + ); + } + checkedDirKeys.value = data.dirKeys; selectedFileKeys.value = data.fileKeys; - lastSelectedDirKeys.value = [...data.dirKeys]; - lastSelectedFileKeys.value = [...data.fileKeys]; selectedDocList.value = data.dirKeys.map((key) => key.toString()); selectedFileList.value = data.fileKeys.map((key) => key.toString()); }; @@ -751,14 +799,8 @@ const tableInfo = getTableInfo(sectionIndex); if (!tableInfo) return; - checkedDirKeys.value = [...lastSelectedDirKeys.value]; - selectedFileKeys.value = [...lastSelectedFileKeys.value]; - selectedDocList.value = lastSelectedDirKeys.value.map((key) => - key.toString() - ); - selectedFileList.value = lastSelectedFileKeys.value.map((key) => - key.toString() - ); + currentFileSelectionKey.value = tableInfo.tableKey; + applyTableFileSelection(tableInfo.tableKey); fileModal.value.open(); }; @@ -885,8 +927,8 @@ history: section.data?.length > 0 ? JSON.stringify(section.data, null, 2) : '', suggestion: section.suggestion || '', - docList: checkedDirKeys.value, - fileList: selectedFileKeys.value, + docList: getTableFileSelection(tableKey).dirKeys, + fileList: getTableFileSelection(tableKey).fileKeys, // 重大经济决策调查表需要三重一大数据 ...(currentTable.value === 'decisionTable' ? { data: tripleOneData.value } @@ -1067,8 +1109,8 @@ kbIds: props.data?.kbId || '', libraryIds: props.data?.libraryIds || '', projectLibrary: props.data?.projectLibrary || '', - docList: checkedDirKeys.value, - fileList: selectedFileKeys.value, + docList: getTableFileSelection(tableKey).dirKeys, + fileList: getTableFileSelection(tableKey).fileKeys, // 重大经济决策调查表需要三重一大数据 ...(currentTable.value === 'decisionTable' @@ -1288,8 +1330,8 @@ projectId: form.id, formCommit: section.formCommit || 0, chapterTitle: chapterTitle, - docList: checkedDirKeys.value, - fileList: selectedFileKeys.value + docList: getTableFileSelection(getTableKey(sectionIndex)).dirKeys, + fileList: getTableFileSelection(getTableKey(sectionIndex)).fileKeys }); } finally { section.generating = false; @@ -1394,6 +1436,11 @@ // 保存表格生成数据 const tableKey = `${section.tableType}_${tableValue}`; saveTableGenerationData(tableKey, requestData, responseData, interfaceName); + saveTableFileSelection( + tableKey, + Array.isArray(requestData?.docList) ? requestData.docList : [], + Array.isArray(requestData?.fileList) ? requestData.fileList : [] + ); // 使用数据映射函数 const dataMapper = createDataMapper(tableValue); @@ -1426,6 +1473,9 @@ } } + currentFileSelectionKey.value = tableKey; + applyTableFileSelection(tableKey); + // 特殊处理数据存储 if (tableValue === 'tripleOne') { tripleOneData.value = data; @@ -1823,12 +1873,17 @@ return cloned; })(); + const currentSelection = getTableFileSelection(tableKey); + const normalizedRequestData = { + ...(generationData.requestData || {}), + docList: [...currentSelection.dirKeys], + fileList: [...currentSelection.fileKeys] + }; + const aiHistory = { projectId: props.data?.id, interfaceName: correctInterfaceName, // 使用正确的接口名称 - requestData: generationData.requestData - ? JSON.stringify(generationData.requestData) - : '', + requestData: JSON.stringify(normalizedRequestData), responseData: JSON.stringify(normalizedResponseData) // 其他字段后端会自动设置 }; @@ -1871,6 +1926,9 @@ const next = { ...gen.responseData, data: [] }; tableGenerationData[tableKey].responseData = next; } + if (tableFileSelectionMap[tableKey] !== undefined) { + delete tableFileSelectionMap[tableKey]; + } if (exportStates[tableKey] !== undefined) delete exportStates[tableKey]; @@ -2041,6 +2099,14 @@ Object.keys(generatingEvidenceStates).forEach((key) => { delete generatingEvidenceStates[key as any]; }); + Object.keys(tableFileSelectionMap).forEach((key) => { + delete tableFileSelectionMap[key]; + }); + currentFileSelectionKey.value = ''; + selectedDocList.value = []; + selectedFileList.value = []; + selectedFileKeys.value = []; + checkedDirKeys.value = []; } } );