From abfd780bf4aea868aa51754f2c7565ee41edeae0 Mon Sep 17 00:00:00 2001 From: BianLzhaoMin <11485688+bianliangzhaomin123@user.noreply.gitee.com> Date: Mon, 12 Jan 2026 10:58:58 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A6=85=E9=81=93bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ComSearchForm/index.vue | 16 ++- src/views/personManage/Person/index.vue | 141 +++++++++++++++++++++++ src/views/planMange/dailyPlan/edit.vue | 81 +++++++++---- src/views/planMange/monthlyPlan/edit.vue | 56 ++++++--- 4 files changed, 250 insertions(+), 44 deletions(-) diff --git a/src/components/ComSearchForm/index.vue b/src/components/ComSearchForm/index.vue index 2f70e6e..2220758 100644 --- a/src/components/ComSearchForm/index.vue +++ b/src/components/ComSearchForm/index.vue @@ -16,7 +16,7 @@ 搜索 - 重置 + 重置 @@ -137,26 +137,30 @@ const getComponentProps = (item) => { // 处理表单数据,将 paramsList 配置的数组值转换为指定参数名 const processFormData = (data) => { const processedData = { ...data } - + props.formColumns.forEach((item) => { // 检查是否有 paramsList 配置 if (item.paramsList && Array.isArray(item.paramsList) && item.paramsList.length > 0) { const value = processedData[item.prop] - + // 如果值是数组且不为空,将其拆分为指定的参数名 if (Array.isArray(value) && value.length > 0) { item.paramsList.forEach((paramName, index) => { - if (value[index] !== undefined && value[index] !== null && value[index] !== '') { + if ( + value[index] !== undefined && + value[index] !== null && + value[index] !== '' + ) { processedData[paramName] = value[index] } }) } - + // 删除原来的数组字段,避免出现 month[0] 和 month[1] 的形式 delete processedData[item.prop] } }) - + return processedData } diff --git a/src/views/personManage/Person/index.vue b/src/views/personManage/Person/index.vue index af5b4c1..f8d3795 100644 --- a/src/views/personManage/Person/index.vue +++ b/src/views/personManage/Person/index.vue @@ -19,6 +19,16 @@ > 新建人员 + + + 导入人员 + + + + + + @@ -65,6 +116,7 @@ import { } from '@/api/common.js' import { useOptions } from '@/hooks/useOptions' import { bus, BUS_EVENTS } from '@/utils/bus' +import { getToken } from '@/utils/auth' import config from './config' import ComTable from '@/components/ComTable/index.vue' import ComButton from '@/components/ComButton/index.vue' @@ -86,6 +138,28 @@ const editId = ref(null) // {}, // ) +// 人员导入弹框配置 +const uploadDialogConfig = reactive({ + outerVisible: false, + outerTitle: '人员导入', + outerWidth: '400px', + minHeight: '300px', + maxHeight: '70vh', +}) + +// 人员导入参数 +const upload = reactive({ + // 是否禁用上传 + isUploading: false, + // 是否更新已经存在的人员数据 + updateSupport: 0, + // 设置上传的请求头部 + headers: { Authorization: 'Bearer ' + getToken() }, + // 上传的地址(接口稍后提供) + url: import.meta.env.VITE_APP_BASE_API + '/personnel/importPersonnel', + selectedFile: null, +}) + const { options: allPositionAndInspectionStationOptions } = useOptions( 'allPositionAndInspectionStationOptions', getInspectionStationSelectAPI, @@ -252,4 +326,71 @@ const onHandleLongTermSecondmentChange = (value, row) => { } }) } + +// 导入人员 +const onHandleImport = () => { + uploadDialogConfig.outerTitle = '人员导入' + uploadDialogConfig.outerVisible = true + upload.selectedFile = null + upload.updateSupport = 0 +} + +// 关闭导入弹框 +const onCloseUploadDialog = () => { + uploadDialogConfig.outerVisible = false + upload.selectedFile = null + upload.isUploading = false + if (uploadRef.value) { + uploadRef.value.clearFiles() + } +} + +// 文件上传中处理 +const handleFileUploadProgress = (event, file, fileList) => { + upload.isUploading = true +} + +// 文件选择处理 +const handleFileChange = (file, fileList) => { + upload.selectedFile = file +} + +// 文件删除处理 +const handleFileRemove = (file, fileList) => { + upload.selectedFile = null +} + +// 文件上传成功处理 +const handleFileSuccess = (response, file, fileList) => { + uploadDialogConfig.outerVisible = false + upload.isUploading = false + uploadRef.value?.handleRemove(file) + proxy.$alert( + "
" + + response.msg + + '
', + '导入结果', + { dangerouslyUseHTMLString: true }, + ) + comTableRef.value?.refresh() +} + +// 提交上传文件 +const submitFileForm = () => { + const file = upload.selectedFile + if ( + !file || + file.length === 0 || + (!file.name.toLowerCase().endsWith('.xls') && !file.name.toLowerCase().endsWith('.xlsx')) + ) { + proxy.$modal.msgError('请选择后缀为 "xls"或"xlsx"的文件。') + return + } + uploadRef.value?.submit() +} + +// 模板下载 +const onHandleDownloadTemplate = () => { + proxy.download('/personnel/downloadPersonnelExcel', {}, `人员模板.xlsx`) +} diff --git a/src/views/planMange/dailyPlan/edit.vue b/src/views/planMange/dailyPlan/edit.vue index b4a2a34..f01a29c 100644 --- a/src/views/planMange/dailyPlan/edit.vue +++ b/src/views/planMange/dailyPlan/edit.vue @@ -532,39 +532,70 @@ const selectedManagerNames = computed(() => { return (formData.value.planPersonnelList || []).map((item) => item.name).join('、') }) -const onOpenPersonPicker = async (type = 'plan') => { - managerDialog.type = type - managerDialogConfig.outerVisible = true - await nextTick() - if (personTableRef.value) { +// 同步表格选中状态:根据 managerDialog.selected 设置表格的选中状态 +const syncTableSelection = () => { + if (!personTableRef.value || !managerDialogConfig.outerVisible) return + nextTick(() => { + // 清空当前表格选中状态 personTableRef.value.clearSelection() - let currentList = [] - if (type === 'plan') { - currentList = formData.value.planPersonnelList || [] - } else if (type === 'actual') { - currentList = formData.value.actualPersonnelList || [] - } else if (type === 'highAltitude') { - currentList = formData.value.highAltitudePersonnelList || [] - } else if (type === 'ground') { - currentList = formData.value.groundPersonnelList || [] - } else if (type === 'actual_highAltitude') { - currentList = formData.value.actualHighAltitudePersonnelList || [] - } else if (type === 'actual_ground') { - currentList = formData.value.actualGroundPersonnelList || [] - } - - personList.value.forEach((row) => { - const exists = currentList.find((item) => item.id === row.id) - if (exists) { + // 根据 managerDialog.selected 重新设置选中状态 + const selectedIds = new Set(managerDialog.selected.map((item) => item.id)) + filteredPersons.value.forEach((row) => { + if (selectedIds.has(row.id)) { personTableRef.value.toggleRowSelection(row, true) } }) - managerDialog.selected = [...currentList] + }) +} + +// 监听 filteredPersons 变化,重新同步表格选中状态 +watch( + () => filteredPersons.value, + () => { + if (managerDialogConfig.outerVisible) { + syncTableSelection() + } + }, +) + +const onOpenPersonPicker = async (type = 'plan') => { + managerDialog.type = type + managerDialogConfig.outerVisible = true + + let currentList = [] + if (type === 'plan') { + currentList = formData.value.planPersonnelList || [] + } else if (type === 'actual') { + currentList = formData.value.actualPersonnelList || [] + } else if (type === 'highAltitude') { + currentList = formData.value.highAltitudePersonnelList || [] + } else if (type === 'ground') { + currentList = formData.value.groundPersonnelList || [] + } else if (type === 'actual_highAltitude') { + currentList = formData.value.actualHighAltitudePersonnelList || [] + } else if (type === 'actual_ground') { + currentList = formData.value.actualGroundPersonnelList || [] } + + managerDialog.selected = [...currentList] + await nextTick() + syncTableSelection() } const onManagerSelectionChange = (rows) => { - managerDialog.selected = [...rows] + // 获取当前过滤结果中所有行的 ID + const currentFilteredIds = new Set(filteredPersons.value.map((row) => row.id)) + + // 保留不在当前过滤结果中的已选人员(这些人员被过滤掉了,但仍然是已选状态) + const keptSelected = managerDialog.selected.filter( + (person) => !currentFilteredIds.has(person.id), + ) + + // 获取当前过滤结果中选中的人员对象 + const selectedInFiltered = rows + + // 合并:保留被过滤掉的已选人员 + 当前过滤结果中的选中人员 + managerDialog.selected = [...keptSelected, ...selectedInFiltered] } const onRemoveManager = (item) => { diff --git a/src/views/planMange/monthlyPlan/edit.vue b/src/views/planMange/monthlyPlan/edit.vue index 2382918..f0b46ed 100644 --- a/src/views/planMange/monthlyPlan/edit.vue +++ b/src/views/planMange/monthlyPlan/edit.vue @@ -488,10 +488,10 @@