From 2a0a2ef72a586fea052dcacea2f8a56babf82fa1 Mon Sep 17 00:00:00 2001 From: zlwu <704541015@qq.com> Date: Wed, 11 Nov 2026 10:02:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(web-admin):=20=E5=8E=86=E5=8F=B2=E5=BD=92?= =?UTF-8?q?=E5=B1=9E=E7=BB=B4=E6=8A=A4=E6=94=AF=E6=8C=81=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=BD=92=E5=B1=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在历史归属维护列表增加多选与工具栏批量「调整归属」,复用现有单条预览/保存接口逐条提交,便于一次将多条业务记录归属到同一项目。 Co-authored-by: Cursor --- .../views/project-management/RecordList.vue | 159 ++++++++++++++---- 1 file changed, 130 insertions(+), 29 deletions(-) diff --git a/web-admin/src/views/project-management/RecordList.vue b/web-admin/src/views/project-management/RecordList.vue index 78b4c6f4..cca57cae 100644 --- a/web-admin/src/views/project-management/RecordList.vue +++ b/web-admin/src/views/project-management/RecordList.vue @@ -78,15 +78,41 @@ 重试 +
+
+
+ 已选 {{ selectedRows.length }} 项 +
+ + 调整归属 + +
+
+ - + - + @@ -262,6 +288,7 @@ page: 1, pageSize: 20 }) + const tableRef = ref<{ clearSelection?: () => void } | null>(null) const rows = ref([]), total = ref(0), statusCounts = ref>({}), @@ -273,6 +300,8 @@ target = ref(''), reason = ref(''), selected = ref({}), + selectedRows = ref([]), + editTargets = ref([]), historyVisible = ref(false), historyRows = ref([]) const visibleColumns = computed(() => @@ -283,6 +312,39 @@ const keywordHint = computed(() => query.bizType === 'presign' ? '请输入单据编号' : assignmentKeywordHints[query.bizType] ) + const dialogBizType = computed( + () => + (editTargets.value[0]?.bizType || + selected.value.bizType || + query.bizType) as AssignmentBizType + ) + const dialogSelectKey = computed(() => { + if (editTargets.value.length <= 1) { + return String(editTargets.value[0]?.id || selected.value.id || 'empty') + } + const firstId = editTargets.value[0]?.id || '' + const lastId = editTargets.value[editTargets.value.length - 1]?.id || '' + return `batch-${editTargets.value.length}-${firstId}-${lastId}` + }) + const originalTeamLabel = computed(() => { + if (editTargets.value.length <= 1) { + return editTargets.value[0]?.teamName || selected.value.teamName || '未归属' + } + return `共 ${editTargets.value.length} 条` + }) + const originalProjectLabel = computed(() => { + if (editTargets.value.length <= 1) { + return editTargets.value[0]?.projectName || selected.value.projectName || '未归属' + } + return `共 ${editTargets.value.length} 条` + }) + function clearSelection() { + selectedRows.value = [] + tableRef.value?.clearSelection?.() + } + function handleSelectionChange(selection: ProjectRecord[]) { + selectedRows.value = selection + } let loadVersion = 0 function statusLabel(status: string) { return query.bizType === 'presign' @@ -307,6 +369,7 @@ loading.value = true loadError.value = false rows.value = [] + clearSelection() try { const fetchRecords = props.assignment ? fetchAssignmentRecords @@ -344,6 +407,7 @@ statusCounts.value = {} visible.value = false historyVisible.value = false + clearSelection() search() } function switchBusiness(kind: AssignmentBizType) { @@ -360,16 +424,41 @@ query.page = page load() } - function open(row: ProjectRecord) { - selected.value = row + function resetDialogForm(targets: ProjectRecord[]) { + editTargets.value = targets + selected.value = targets[0] || {} targetTeamId.value = '' target.value = '' reason.value = '' visible.value = true } + function open(row: ProjectRecord) { + resetDialogForm([row]) + } + function openBatch() { + if (!selectedRows.value.length) { + ElMessage.warning('请先选择要调整的记录') + return + } + resetDialogForm([...selectedRows.value]) + } function onTargetTeamChange() { target.value = '' } + async function assignOne(row: ProjectRecord, projectId: string, assignReason: string) { + const preview = await previewAssignment({ + bizType: row.bizType, + id: row.id, + projectId + }) + await saveAssignment({ + bizType: row.bizType, + id: row.id, + projectId, + reason: assignReason, + expectedAssignments: assignmentSnapshot(preview.records) + }) + } async function commit() { if (!targetTeamId.value) { ElMessage.warning('请选择新项目组') @@ -383,33 +472,45 @@ ElMessage.warning('请填写调整原因') return } + const targets = editTargets.value.length ? [...editTargets.value] : [selected.value] + if (!targets.length || !targets[0]?.id) { + ElMessage.warning('请选择要调整的记录') + return + } busy.value = true const commitTarget = target.value - const commitRecord = selected.value + const commitReason = reason.value.trim() + const commitTargets = targets + let successCount = 0 + let failCount = 0 try { - const preview = await previewAssignment({ - bizType: selected.value.bizType, - id: selected.value.id, - projectId: target.value - }) - if (selected.value !== commitRecord || target.value !== commitTarget || !visible.value) { + for (const row of commitTargets) { + if (target.value !== commitTarget || !visible.value) { + return + } + try { + await assignOne(row, commitTarget, commitReason) + successCount += 1 + } catch { + failCount += 1 + // API layer already surfaces the conflict / validation message. + } + } + if (target.value !== commitTarget || !visible.value) { return } - await saveAssignment({ - bizType: selected.value.bizType, - id: selected.value.id, - projectId: target.value, - reason: reason.value.trim(), - expectedAssignments: assignmentSnapshot(preview.records) - }) - if (selected.value !== commitRecord || target.value !== commitTarget || !visible.value) { - return + if (successCount > 0) { + visible.value = false + clearSelection() + if (failCount === 0) { + ElMessage.success( + commitTargets.length > 1 ? `已调整 ${successCount} 条归属` : '归属已调整' + ) + } else { + ElMessage.warning(`成功 ${successCount} 条,失败 ${failCount} 条`) + } + await load() } - visible.value = false - ElMessage.success('归属已调整') - await load() - } catch { - // API layer already surfaces the conflict / validation message. } finally { busy.value = false }