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 @@
重试
+
+
-
+
-
+
@@ -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
}