修复编辑、删除无法操作的问题

This commit is contained in:
2026-01-14 09:56:19 +08:00
parent 1adf7de021
commit c3c3a8c3d1
2 changed files with 435 additions and 204 deletions

View File

@@ -212,15 +212,8 @@
>
<div class="flex justify-start items-center">
<a-space>
<a-button type="primary" @click.native="editRow(record, index)"
>编辑</a-button
>
<a-button
type="primary"
danger
@click.native="deleteRow(record, index)"
>删除</a-button
>
<a-button type="primary" @click.native="editRow(index)">编辑</a-button>
<a-button type="primary" danger @click.native="deleteRow(index)">删除</a-button>
<a-button>导出</a-button>
<a-button @click="openEvidenceModal(index)"
>导出取证单</a-button
@@ -264,6 +257,7 @@
:scroll="{ y: 500, x: 1000 }"
:pagination="false"
bordered
:row-key="(row) => row?.key ?? row?.id ?? row?.index"
:data-source="item.data"
>
<template #bodyCell="{ column, record }">
@@ -497,6 +491,7 @@
<EditModal
v-model:visible="editModalVisible"
:record="editingRecord"
:records="editingTargetRows"
:fields="editingFields"
@save="saveEdit"
/>
@@ -581,6 +576,7 @@
const editingSectionIndex = ref(0);
const editingTableKey = ref('');
const editingFields = ref<any[]>([]);
const editingTargetRows = ref<any[]>([]);
// ========== 文档选择相关 ==========
const fileModal = ref();
@@ -605,21 +601,21 @@
// ========== 表格选择 ==========
const selectedRowsMap = reactive<Record<number, any[]>>({});
const rowSelections = reactive<Record<number, TableProps['rowSelection']>>(
{}
);
const selectedRowKeysMap = reactive<Record<number, (string | number)[]>>({});
const getRowSelection = (
sectionIndex: number
): TableProps['rowSelection'] => {
if (!rowSelections[sectionIndex]) {
rowSelections[sectionIndex] = {
onChange: (selectedRowKeys: string[], selectedRows: any[]) => {
selectedRowsMap[sectionIndex] = selectedRows;
}
};
}
return rowSelections[sectionIndex];
return {
selectedRowKeys: selectedRowKeysMap[sectionIndex] || [],
onChange: (
selectedRowKeys: (string | number)[],
selectedRows: any[]
) => {
selectedRowsMap[sectionIndex] = selectedRows;
selectedRowKeysMap[sectionIndex] = selectedRowKeys;
}
};
};
// ========== 历史记录相关 ==========
const showHistory = ref(false);
@@ -718,6 +714,9 @@
section.data = [];
}
selectedRowsMap[sectionIndex] = [];
selectedRowKeysMap[sectionIndex] = [];
message.success(`已切换到:${tableOption.title}`);
};
@@ -1134,10 +1133,16 @@
};
/* 编辑行 */
const editRow = (record: any, sectionIndex: number) => {
const editRow = (sectionIndex: number) => {
const section: any = navigationItems.value[sectionIndex];
if (!section || !section.columns) return;
const selectedRows = selectedRowsMap[sectionIndex] || [];
if (!selectedRows.length) {
message.warning('请先选择要编辑的行');
return;
}
// 获取可编辑的字段(排除操作列)
editingFields.value = section.columns.filter(
(col) =>
@@ -1148,183 +1153,272 @@
col.key !== 'workPaperIndex'
);
editingRecord.value = { ...record };
// 将所有选中的行传递给编辑弹窗
editingRecord.value = { ...selectedRows[0] };
editingTargetRows.value = selectedRows.map((row: any) => ({ ...row }));
editingSectionIndex.value = sectionIndex;
// 记录当前编辑的表格key
const tableInfo = getTableInfo(sectionIndex);
if (tableInfo) {
editingTableKey.value = tableInfo.tableKey;
} else {
editingTableKey.value = '';
}
editModalVisible.value = true;
};
/* 保存编辑 */
const saveEdit = (updatedRecord: any) => {
const saveEdit = (updatedRecords: any | any[]) => {
const section: any = navigationItems.value[editingSectionIndex.value];
if (!section || !section.data) return;
const index = section.data.findIndex(
(item: any) => item.key === updatedRecord.key
);
if (index !== -1) {
// 保留原有数据的其他字段
const originalRecord = section.data[index];
section.data[index] = { ...originalRecord, ...updatedRecord };
const targets =
editingTargetRows.value && editingTargetRows.value.length
? editingTargetRows.value
: editingRecord.value
? [editingRecord.value]
: [];
// 更新对应的响应数据
if (editingTableKey.value && tableGenerationData[editingTableKey.value]) {
// 获取当前的响应数据
if (!targets.length) {
message.warning('未找到需要编辑的行');
return;
}
const updatesArray = Array.isArray(updatedRecords)
? updatedRecords
: [updatedRecords];
// 只提取允许编辑的字段,避免把首行的其他值覆盖到所有行
const allowedKeys = new Set<string>();
const collectKeys = (field: any) => {
if (field?.dataIndex) allowedKeys.add(field.dataIndex);
if (field?.children && Array.isArray(field.children)) {
field.children.forEach((child: any) => collectKeys(child));
}
};
editingFields.value.forEach((field: any) => collectKeys(field));
const buildApplyFields = (source: any) => {
const applied: Record<string, any> = {};
allowedKeys.forEach((key) => {
if (key === 'key' || key === 'index') return;
if (Object.prototype.hasOwnProperty.call(source, key)) {
applied[key] = source[key];
}
});
return applied;
};
const stripResponseFields = (data: any) => {
const { workPaperIndex, key, index, ...rest } = data;
return rest;
};
const findRawIndex = (
responseList: any[],
targetRow: any,
fallbackUiIndex: number
) => {
const hasValidId =
targetRow?.id !== undefined &&
targetRow?.id !== null &&
targetRow?.id !== '';
if (hasValidId) {
const byId = responseList.findIndex(
(item: any) => item.id === targetRow.id
);
if (byId !== -1) return byId;
}
if (
typeof targetRow?.key === 'number' &&
targetRow.key >= 0 &&
targetRow.key < responseList.length
) {
return targetRow.key;
}
if (targetRow?.key !== undefined && targetRow?.key !== null) {
const byKey = responseList.findIndex(
(item: any) => item.key !== undefined && item.key === targetRow.key
);
if (byKey !== -1) return byKey;
}
if (
fallbackUiIndex !== -1 &&
fallbackUiIndex >= 0 &&
fallbackUiIndex < responseList.length
) {
return fallbackUiIndex;
}
return -1;
};
let hasApplied = false;
targets.forEach((targetRow: any, idx: number) => {
const updateSource = updatesArray[idx] || updatesArray[0] || {};
const appliedFields = buildApplyFields(updateSource);
if (Object.keys(appliedFields).length === 0) {
return;
}
hasApplied = true;
const uiIndex = section.data.findIndex(
(item: any) => item.key === targetRow.key
);
if (uiIndex !== -1) {
const originalRecord = section.data[uiIndex];
const merged = { ...originalRecord, ...appliedFields };
merged.key = originalRecord.key;
if (Object.prototype.hasOwnProperty.call(originalRecord, 'index')) {
merged.index = originalRecord.index;
}
section.data.splice(uiIndex, 1, merged);
}
if (
editingTableKey.value &&
tableGenerationData[editingTableKey.value]
) {
const responseData =
tableGenerationData[editingTableKey.value].responseData;
// 如果响应数据存在且包含data数组
if (
responseData &&
responseData.data &&
Array.isArray(responseData.data)
) {
// 找到对应的原始数据索引
const dataIndex = (() => {
const hasValidId =
updatedRecord.id !== undefined &&
updatedRecord.id !== null &&
updatedRecord.id !== '';
if (responseData && responseData.data && Array.isArray(responseData.data)) {
const rawIndex = findRawIndex(
responseData.data,
targetRow,
uiIndex
);
if (hasValidId) {
const byId = responseData.data.findIndex(
(item: any) => item.id === updatedRecord.id
);
if (byId !== -1) return byId;
}
// 默认 key 由 mapper 使用 index 生成,后端原始数据通常没有 key
if (
typeof updatedRecord.key === 'number' &&
updatedRecord.key >= 0 &&
updatedRecord.key < responseData.data.length
) {
return updatedRecord.key;
}
const hasKey =
updatedRecord.key !== undefined && updatedRecord.key !== null;
if (hasKey) {
const byKey = responseData.data.findIndex(
(item: any) =>
item.key !== undefined && item.key === updatedRecord.key
);
if (byKey !== -1) return byKey;
}
return -1;
})();
if (dataIndex !== -1) {
// 更新原始响应数据中的对应记录
responseData.data[dataIndex] = {
...responseData.data[dataIndex],
...(() => {
const { workPaperIndex, key, index, ...rest } = updatedRecord;
return rest;
})()
if (rawIndex !== -1) {
responseData.data[rawIndex] = {
...responseData.data[rawIndex],
...stripResponseFields(appliedFields)
};
// 更新tableGenerationData中的响应数据
tableGenerationData[editingTableKey.value].responseData =
responseData;
} else {
// 如果没找到对应的原始数据,直接将编辑后的数据添加到响应数据中
// 这可能发生在手动添加行的情况下
responseData.data.push(
(() => {
const { workPaperIndex, key, index, ...rest } = updatedRecord;
return rest;
})()
);
tableGenerationData[editingTableKey.value].responseData =
responseData;
responseData.data.push(stripResponseFields(appliedFields));
}
tableGenerationData[editingTableKey.value].responseData =
responseData;
}
}
});
message.success('编辑成功');
if (editingTableKey.value) {
tableData[editingTableKey.value] = section.data;
}
const currentSelections = selectedRowsMap[editingSectionIndex.value] || [];
selectedRowsMap[editingSectionIndex.value] = currentSelections
.map(
(row: any) =>
section.data.find((item: any) => item.key === row.key) || row
);
if (!hasApplied) {
message.warning('没有可应用的字段');
return;
}
message.success('编辑成功');
editModalVisible.value = false;
editingTableKey.value = ''; // 清空编辑的表格key
editingTableKey.value = '';
editingTargetRows.value = [];
};
/* 删除行 */
const deleteRow = (record: any, sectionIndex: number) => {
/* 删除行(多选) */
const deleteRow = (sectionIndex: number) => {
const section: any = navigationItems.value[sectionIndex];
if (!section || !section.data) return;
const uiIndex = section.data.findIndex(
(item: any) => item.key === record.key
);
if (uiIndex === -1) return;
// 同步删除原始 responseData删除前就计算 rawIndex避免 key 重排导致错位)
const tableInfo = getTableInfo(sectionIndex);
if (
tableInfo &&
tableInfo.tableKey &&
tableGenerationData[tableInfo.tableKey]
) {
const responseData = tableGenerationData[tableInfo.tableKey].responseData;
if (
responseData &&
responseData.data &&
Array.isArray(responseData.data)
) {
const rawIndex = (() => {
const hasValidId =
record?.id !== undefined &&
record?.id !== null &&
record?.id !== '';
if (hasValidId) {
const byId = responseData.data.findIndex(
(item: any) => item.id === record.id
);
if (byId !== -1) return byId;
}
// 默认 key 由 mapper 使用 index 生成
if (
typeof record.key === 'number' &&
record.key >= 0 &&
record.key < responseData.data.length
) {
return record.key;
}
const hasKey = record?.key !== undefined && record?.key !== null;
if (hasKey) {
const byKey = responseData.data.findIndex(
(item: any) => item.key !== undefined && item.key === record.key
);
if (byKey !== -1) return byKey;
}
// 最后兜底:使用 UI 索引
if (uiIndex >= 0 && uiIndex < responseData.data.length)
return uiIndex;
return -1;
})();
if (rawIndex !== -1) {
responseData.data.splice(rawIndex, 1);
tableGenerationData[tableInfo.tableKey].responseData = responseData;
}
}
const selectedRows = selectedRowsMap[sectionIndex] || [];
if (!selectedRows.length) {
message.warning('请先选择要删除的行');
return;
}
// 删除 UI 行
section.data.splice(uiIndex, 1);
const tableInfo = getTableInfo(sectionIndex);
const responseData =
tableInfo &&
tableInfo.tableKey &&
tableGenerationData[tableInfo.tableKey] &&
tableGenerationData[tableInfo.tableKey].responseData &&
tableGenerationData[tableInfo.tableKey].responseData.data &&
Array.isArray(tableGenerationData[tableInfo.tableKey].responseData.data)
? tableGenerationData[tableInfo.tableKey].responseData
: null;
// 删除后重排 key/index保证后续编辑/保存按 key(索引) 能正确匹配
const findRawIndex = (
responseList: any[],
targetRow: any,
fallbackUiIndex: number
) => {
const hasValidId =
targetRow?.id !== undefined &&
targetRow?.id !== null &&
targetRow?.id !== '';
if (hasValidId) {
const byId = responseList.findIndex((item: any) => item.id === targetRow.id);
if (byId !== -1) return byId;
}
if (
typeof targetRow?.key === 'number' &&
targetRow.key >= 0 &&
targetRow.key < responseList.length
) {
return targetRow.key;
}
if (targetRow?.key !== undefined && targetRow?.key !== null) {
const byKey = responseList.findIndex(
(item: any) => item.key !== undefined && item.key === targetRow.key
);
if (byKey !== -1) return byKey;
}
if (
fallbackUiIndex !== -1 &&
fallbackUiIndex >= 0 &&
fallbackUiIndex < responseList.length
) {
return fallbackUiIndex;
}
return -1;
};
const uiIndexesToDelete: number[] = [];
const rawIndexesToDelete: number[] = [];
selectedRows.forEach((row: any) => {
const uiIndex = section.data.findIndex((item: any) => item.key === row.key);
if (uiIndex !== -1) uiIndexesToDelete.push(uiIndex);
if (responseData) {
const rawIndex = findRawIndex(responseData.data, row, uiIndex);
if (rawIndex !== -1) rawIndexesToDelete.push(rawIndex);
}
});
const uniqueUiIndexes = Array.from(new Set(uiIndexesToDelete)).sort(
(a, b) => b - a
);
uniqueUiIndexes.forEach((idx) => {
section.data.splice(idx, 1);
});
// 删除后重排 key/index保证后续操作按 key(索引) 能正确匹配
section.data = section.data.map((item: any, index: number) => {
const next: any = { ...item, key: index };
if (item && Object.prototype.hasOwnProperty.call(item, 'index')) {
@@ -1337,7 +1431,20 @@
tableData[tableInfo.tableKey] = section.data;
}
message.success('删除成功');
if (responseData && tableInfo && tableInfo.tableKey) {
const uniqueRawIndexes = Array.from(new Set(rawIndexesToDelete)).sort(
(a, b) => b - a
);
uniqueRawIndexes.forEach((idx) => {
responseData.data.splice(idx, 1);
});
tableGenerationData[tableInfo.tableKey].responseData = responseData;
}
selectedRowsMap[sectionIndex] = [];
selectedRowKeysMap[sectionIndex] = [];
message.success(`已删除${uniqueUiIndexes.length || selectedRows.length}条记录`);
};
/* 保存当前表格到历史记录 */
@@ -1471,6 +1578,9 @@
section.data = [];
message.success('已清空表格');
selectedRowsMap[sectionIndex] = [];
selectedRowKeysMap[sectionIndex] = [];
}
});
};
@@ -1609,6 +1719,13 @@
// 清空特殊数据
tripleOneData.value = null;
stateAssetsData.value = null;
// 清空选中行
Object.keys(selectedRowsMap).forEach((key) => {
delete selectedRowsMap[key as any];
});
Object.keys(selectedRowKeysMap).forEach((key) => {
delete selectedRowKeysMap[key as any];
});
}
}
);