修复编辑、删除无法操作的问题
This commit is contained in:
@@ -7,26 +7,59 @@
|
||||
:confirm-loading="loading"
|
||||
width="600px"
|
||||
>
|
||||
<template #title>
|
||||
<div class="modal-title">
|
||||
<span>编辑行数据</span>
|
||||
<a-tag v-if="displayRecords.length > 1" color="blue" class="ml-2">
|
||||
同步编辑 {{ displayRecords.length }} 条
|
||||
</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<a-alert
|
||||
v-if="displayRecords.length > 1"
|
||||
type="info"
|
||||
show-icon
|
||||
style="margin-bottom: 12px"
|
||||
:message="`已选择 ${displayRecords.length} 条记录,将把当前修改同步到这些记录`"
|
||||
/>
|
||||
<a-list
|
||||
v-if="displayRecords.length > 1"
|
||||
size="small"
|
||||
bordered
|
||||
:data-source="displayRecords"
|
||||
style="margin-bottom: 12px; max-height: 160px; overflow-y: auto"
|
||||
>
|
||||
<template #renderItem="{ item, index }">
|
||||
<a-list-item
|
||||
:class="['record-item', { active: index === selectedRecordIndex }]"
|
||||
@click="selectRecord(index)"
|
||||
>
|
||||
<span class="record-label">#{{ index + 1 }}</span>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
|
||||
<a-form layout="vertical">
|
||||
<template v-for="field in processedFields" :key="field.key">
|
||||
<a-form-item :label="field.title" v-if="!field.children">
|
||||
<template v-if="field.type === 'textarea'">
|
||||
<a-textarea
|
||||
v-model:value="formData[field.dataIndex]"
|
||||
v-model:value="activeFormData[field.dataIndex]"
|
||||
:rows="4"
|
||||
:placeholder="`请输入${field.title}`"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="field.dataIndex === 'workPaperIndex'">
|
||||
<a-textarea
|
||||
v-model:value="formData[field.dataIndex]"
|
||||
v-model:value="activeFormData[field.dataIndex]"
|
||||
:rows="4"
|
||||
:placeholder="'每行一个文件,格式为:file_id||文件名||url'"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-input
|
||||
v-model:value="formData[field.dataIndex]"
|
||||
v-model:value="activeFormData[field.dataIndex]"
|
||||
:placeholder="`请输入${field.title}`"
|
||||
/>
|
||||
</template>
|
||||
@@ -44,7 +77,7 @@
|
||||
class="nested-field-item"
|
||||
>
|
||||
<a-input
|
||||
v-model:value="formData[childField.dataIndex]"
|
||||
v-model:value="activeFormData[childField.dataIndex]"
|
||||
:placeholder="`请输入${childField.title}`"
|
||||
/>
|
||||
</a-form-item>
|
||||
@@ -64,12 +97,44 @@ const props = defineProps<{
|
||||
visible: boolean;
|
||||
record: any;
|
||||
fields: any[];
|
||||
records?: any[];
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['update:visible', 'save']);
|
||||
|
||||
const loading = ref(false);
|
||||
const formData = ref({});
|
||||
const formDataList = ref<any[]>([]);
|
||||
const selectedRecordIndex = ref(0);
|
||||
|
||||
const displayRecords = computed(() => {
|
||||
if (props.records && Array.isArray(props.records) && props.records.length) {
|
||||
return props.records;
|
||||
}
|
||||
if (props.record) return [props.record];
|
||||
return [];
|
||||
});
|
||||
|
||||
const transformRecordToFormData = (record: any) => {
|
||||
if (!record) return {};
|
||||
const recordCopy = JSON.parse(JSON.stringify(record));
|
||||
|
||||
if (
|
||||
hasWorkPaperIndexField.value &&
|
||||
recordCopy.workPaperIndex &&
|
||||
Array.isArray(recordCopy.workPaperIndex)
|
||||
) {
|
||||
recordCopy.workPaperIndex = recordCopy.workPaperIndex
|
||||
.map((item: any) => {
|
||||
if (typeof item === 'object') {
|
||||
return `${item.fileId || ''}||${item.fileName || ''}||${item.fileUrl || ''}`;
|
||||
}
|
||||
return item;
|
||||
})
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
return recordCopy;
|
||||
};
|
||||
|
||||
const hasWorkPaperIndexField = computed(() => {
|
||||
return (props.fields || []).some((field) => {
|
||||
@@ -81,7 +146,7 @@ const hasWorkPaperIndexField = computed(() => {
|
||||
const processedFields = computed(() => {
|
||||
const processed: any[] = [];
|
||||
|
||||
props.fields.forEach(field => {
|
||||
(props.fields || []).forEach(field => {
|
||||
if (field.children && Array.isArray(field.children)) {
|
||||
// 处理有子字段的情况(如职务)
|
||||
processed.push({
|
||||
@@ -100,38 +165,31 @@ const processedFields = computed(() => {
|
||||
return processed;
|
||||
});
|
||||
|
||||
watch(() => props.visible, (visible) => {
|
||||
if (visible && props.record) {
|
||||
// 深拷贝记录数据
|
||||
const recordCopy = JSON.parse(JSON.stringify(props.record));
|
||||
|
||||
// 特殊处理workPaperIndex:如果是对象数组,转换为字符串数组
|
||||
if (hasWorkPaperIndexField.value && recordCopy.workPaperIndex && Array.isArray(recordCopy.workPaperIndex)) {
|
||||
recordCopy.workPaperIndex = recordCopy.workPaperIndex.map(item => {
|
||||
if (typeof item === 'object') {
|
||||
// 如果是对象,转换为字符串格式:file_id||文件名||url
|
||||
return `${item.fileId || ''}||${item.fileName || ''}||${item.fileUrl || ''}`;
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
selectedRecordIndex.value = 0;
|
||||
formDataList.value = displayRecords.value.map((rec) =>
|
||||
transformRecordToFormData(rec)
|
||||
);
|
||||
}
|
||||
return item;
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
formData.value = recordCopy;
|
||||
}
|
||||
}, { immediate: true });
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const handleOk = () => {
|
||||
if (!formData.value) {
|
||||
if (!formDataList.value || formDataList.value.length === 0) {
|
||||
message.warning('没有数据可保存');
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理workPaperIndex:将字符串转换回对象数组
|
||||
const dataToSave = JSON.parse(JSON.stringify(formData.value));
|
||||
|
||||
if (hasWorkPaperIndexField.value && dataToSave.workPaperIndex && typeof dataToSave.workPaperIndex === 'string') {
|
||||
const lines = dataToSave.workPaperIndex.split('\n').filter(line => line.trim() !== '');
|
||||
dataToSave.workPaperIndex = lines.map(line => {
|
||||
const dataToSave = formDataList.value.map((item) => {
|
||||
const cloned = JSON.parse(JSON.stringify(item || {}));
|
||||
if (hasWorkPaperIndexField.value && cloned.workPaperIndex && typeof cloned.workPaperIndex === 'string') {
|
||||
const lines = cloned.workPaperIndex.split('\n').filter((line: string) => line.trim() !== '');
|
||||
cloned.workPaperIndex = lines.map((line: string) => {
|
||||
const parts = line.split('||');
|
||||
if (parts.length >= 3) {
|
||||
return {
|
||||
@@ -143,6 +201,8 @@ const handleOk = () => {
|
||||
return line;
|
||||
});
|
||||
}
|
||||
return cloned;
|
||||
});
|
||||
|
||||
loading.value = true;
|
||||
emit('save', dataToSave);
|
||||
@@ -153,6 +213,32 @@ const handleOk = () => {
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
const selectRecord = (index: number) => {
|
||||
if (index < 0 || index >= displayRecords.value.length) return;
|
||||
selectedRecordIndex.value = index;
|
||||
if (!formDataList.value[index]) {
|
||||
formDataList.value[index] = transformRecordToFormData(
|
||||
displayRecords.value[index]
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const activeFormData = computed({
|
||||
get() {
|
||||
if (!displayRecords.value.length) return {};
|
||||
if (!formDataList.value[selectedRecordIndex.value]) {
|
||||
formDataList.value[selectedRecordIndex.value] = transformRecordToFormData(
|
||||
displayRecords.value[selectedRecordIndex.value]
|
||||
);
|
||||
}
|
||||
return formDataList.value[selectedRecordIndex.value] || {};
|
||||
},
|
||||
set(val) {
|
||||
if (!displayRecords.value.length) return;
|
||||
formDataList.value[selectedRecordIndex.value] = val || {};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -179,4 +265,32 @@ const handleCancel = () => {
|
||||
.nested-field-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.record-label {
|
||||
display: inline-block;
|
||||
width: 36px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.record-text {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.record-item {
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.record-item:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.record-item.active {
|
||||
background-color: #e6f7ff;
|
||||
}
|
||||
</style>
|
||||
@@ -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[]) => {
|
||||
return {
|
||||
selectedRowKeys: selectedRowKeysMap[sectionIndex] || [],
|
||||
onChange: (
|
||||
selectedRowKeys: (string | number)[],
|
||||
selectedRows: any[]
|
||||
) => {
|
||||
selectedRowsMap[sectionIndex] = selectedRows;
|
||||
selectedRowKeysMap[sectionIndex] = selectedRowKeys;
|
||||
}
|
||||
};
|
||||
}
|
||||
return rowSelections[sectionIndex];
|
||||
};
|
||||
// ========== 历史记录相关 ==========
|
||||
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 (hasValidId) {
|
||||
const byId = responseData.data.findIndex(
|
||||
(item: any) => item.id === updatedRecord.id
|
||||
if (responseData && responseData.data && Array.isArray(responseData.data)) {
|
||||
const rawIndex = findRawIndex(
|
||||
responseData.data,
|
||||
targetRow,
|
||||
uiIndex
|
||||
);
|
||||
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;
|
||||
})()
|
||||
);
|
||||
responseData.data.push(stripResponseFields(appliedFields));
|
||||
}
|
||||
|
||||
tableGenerationData[editingTableKey.value].responseData =
|
||||
responseData;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
const selectedRows = selectedRowsMap[sectionIndex] || [];
|
||||
if (!selectedRows.length) {
|
||||
message.warning('请先选择要删除的行');
|
||||
return;
|
||||
}
|
||||
|
||||
// 同步删除原始 responseData(删除前就计算 rawIndex,避免 key 重排导致错位)
|
||||
const tableInfo = getTableInfo(sectionIndex);
|
||||
if (
|
||||
const responseData =
|
||||
tableInfo &&
|
||||
tableInfo.tableKey &&
|
||||
tableGenerationData[tableInfo.tableKey]
|
||||
) {
|
||||
const responseData = tableGenerationData[tableInfo.tableKey].responseData;
|
||||
if (
|
||||
responseData &&
|
||||
responseData.data &&
|
||||
Array.isArray(responseData.data)
|
||||
) {
|
||||
const rawIndex = (() => {
|
||||
tableGenerationData[tableInfo.tableKey] &&
|
||||
tableGenerationData[tableInfo.tableKey].responseData &&
|
||||
tableGenerationData[tableInfo.tableKey].responseData.data &&
|
||||
Array.isArray(tableGenerationData[tableInfo.tableKey].responseData.data)
|
||||
? tableGenerationData[tableInfo.tableKey].responseData
|
||||
: null;
|
||||
|
||||
const findRawIndex = (
|
||||
responseList: any[],
|
||||
targetRow: any,
|
||||
fallbackUiIndex: number
|
||||
) => {
|
||||
const hasValidId =
|
||||
record?.id !== undefined &&
|
||||
record?.id !== null &&
|
||||
record?.id !== '';
|
||||
targetRow?.id !== undefined &&
|
||||
targetRow?.id !== null &&
|
||||
targetRow?.id !== '';
|
||||
if (hasValidId) {
|
||||
const byId = responseData.data.findIndex(
|
||||
(item: any) => item.id === record.id
|
||||
);
|
||||
const byId = responseList.findIndex((item: any) => item.id === targetRow.id);
|
||||
if (byId !== -1) return byId;
|
||||
}
|
||||
|
||||
// 默认 key 由 mapper 使用 index 生成
|
||||
if (
|
||||
typeof record.key === 'number' &&
|
||||
record.key >= 0 &&
|
||||
record.key < responseData.data.length
|
||||
typeof targetRow?.key === 'number' &&
|
||||
targetRow.key >= 0 &&
|
||||
targetRow.key < responseList.length
|
||||
) {
|
||||
return record.key;
|
||||
return targetRow.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 (targetRow?.key !== undefined && targetRow?.key !== null) {
|
||||
const byKey = responseList.findIndex(
|
||||
(item: any) => item.key !== undefined && item.key === targetRow.key
|
||||
);
|
||||
if (byKey !== -1) return byKey;
|
||||
}
|
||||
|
||||
// 最后兜底:使用 UI 索引
|
||||
if (uiIndex >= 0 && uiIndex < responseData.data.length)
|
||||
return uiIndex;
|
||||
if (
|
||||
fallbackUiIndex !== -1 &&
|
||||
fallbackUiIndex >= 0 &&
|
||||
fallbackUiIndex < responseList.length
|
||||
) {
|
||||
return fallbackUiIndex;
|
||||
}
|
||||
|
||||
return -1;
|
||||
})();
|
||||
};
|
||||
|
||||
if (rawIndex !== -1) {
|
||||
responseData.data.splice(rawIndex, 1);
|
||||
tableGenerationData[tableInfo.tableKey].responseData = responseData;
|
||||
}
|
||||
}
|
||||
}
|
||||
const uiIndexesToDelete: number[] = [];
|
||||
const rawIndexesToDelete: number[] = [];
|
||||
|
||||
// 删除 UI 行
|
||||
section.data.splice(uiIndex, 1);
|
||||
selectedRows.forEach((row: any) => {
|
||||
const uiIndex = section.data.findIndex((item: any) => item.key === row.key);
|
||||
if (uiIndex !== -1) uiIndexesToDelete.push(uiIndex);
|
||||
|
||||
// 删除后重排 key/index,保证后续编辑/保存按 key(索引) 能正确匹配
|
||||
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];
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user