✨ 结算单业务模式运输方式与编辑体验优化
预结算/收付款结算支持业务模式与运输方式展示导出;完善结算调整、对账导入与变更记录;组织合同初始流水号未填不再显示-1。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -263,7 +263,7 @@
|
||||
<template v-else-if="isExternalRowEditing(row) && isExternalEditableColumn(column.prop)">
|
||||
<el-input-number
|
||||
v-if="column.feeItemName"
|
||||
v-model="row.feeItems[column.feeItemName]"
|
||||
v-model="externalEditTarget(row).feeItems[column.feeItemName]"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
@@ -271,7 +271,7 @@
|
||||
/>
|
||||
<el-date-picker
|
||||
v-else-if="isExternalDateColumn(column.prop)"
|
||||
v-model="row[column.prop]"
|
||||
v-model="externalEditTarget(row)[column.prop]"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
format="YYYY-MM-DD"
|
||||
@@ -280,7 +280,7 @@
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="isExternalNumberColumn(column.prop)"
|
||||
v-model="row[column.prop]"
|
||||
v-model="externalEditTarget(row)[column.prop]"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:controls="false"
|
||||
@@ -288,7 +288,7 @@
|
||||
/>
|
||||
<el-select
|
||||
v-else-if="column.prop === 'transportType'"
|
||||
v-model="row[column.prop]"
|
||||
v-model="externalEditTarget(row)[column.prop]"
|
||||
size="small"
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
@@ -300,7 +300,7 @@
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input v-else v-model="row[column.prop]" size="small" />
|
||||
<el-input v-else v-model="externalEditTarget(row)[column.prop]" size="small" />
|
||||
</template>
|
||||
<span v-else-if="column.prop === 'transportType'">
|
||||
{{ transportTypeLabel(row.transportType) }}
|
||||
@@ -630,6 +630,7 @@ import { getDictionary } from '@/api/system/dictbiz';
|
||||
import { Search } from '@element-plus/icons-vue';
|
||||
import { h } from 'vue';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { isExcelResponse, parseBlobJson } from '@/utils/import-excel';
|
||||
import { transportReconciliationFormFields } from '@/option/settlement/transportReconciliationForm';
|
||||
import {
|
||||
internalColumns,
|
||||
@@ -676,6 +677,8 @@ export default {
|
||||
completionDialog: { visible: false, loading: false },
|
||||
completionSummaryRowsData: null,
|
||||
externalEditing: {},
|
||||
// 调整中的草稿,输入只改草稿,点「完成」才写回列表
|
||||
externalEditDrafts: {},
|
||||
externalEditSnapshots: {},
|
||||
matchingStarted: false,
|
||||
rules: {
|
||||
@@ -932,6 +935,7 @@ export default {
|
||||
this.internalDetails = [];
|
||||
this.externalDetails = [];
|
||||
this.externalEditing = {};
|
||||
this.externalEditDrafts = {};
|
||||
this.externalEditSnapshots = {};
|
||||
this.completionSummaryRowsData = null;
|
||||
this.matchingStarted = false;
|
||||
@@ -1503,16 +1507,16 @@ export default {
|
||||
this.form.reconciliationMode === 'cargo'
|
||||
? await api.importCargo(this.currentId, file)
|
||||
: await api.importVehicle(this.currentId, file);
|
||||
const contentType = response.headers?.['content-type'] || response.data?.type || '';
|
||||
if (contentType.includes('spreadsheetml') || contentType.includes('ms-excel')) {
|
||||
// 成功时 axios 拦截器可能已把 JSON Blob 解析成对象,不能再调 .text()
|
||||
if (isExcelResponse(response)) {
|
||||
downloadXls(
|
||||
response.data,
|
||||
`运输对账导入失败明细${this.$dayjs().format('YYYY-MM-DD HH-mm-ss')}.xlsx`
|
||||
);
|
||||
this.$message.warning('部分数据导入失败,已下载失败明细');
|
||||
} else {
|
||||
const result = JSON.parse(await response.data.text());
|
||||
if (result.code !== 200) throw new Error(result.msg || '导入失败');
|
||||
const result = await parseBlobJson(response.data);
|
||||
if (Number(result.code) !== 200) throw new Error(result.msg || '导入失败');
|
||||
this.$message.success('外部账单导入成功');
|
||||
}
|
||||
this.matchingStarted = false;
|
||||
@@ -1661,6 +1665,28 @@ export default {
|
||||
isExternalRowEditing(row) {
|
||||
return Boolean(this.externalEditing[this.externalRowKey(row)]);
|
||||
},
|
||||
cloneExternalEditRow(row) {
|
||||
return {
|
||||
...row,
|
||||
feeItems: { ...(row.feeItems || this.parseFeeItems(row.feeItemsJson)) },
|
||||
};
|
||||
},
|
||||
/** 编辑态绑定草稿,避免输入时实时改写列表导致疑似重复 Tab 刷新 */
|
||||
externalEditTarget(row) {
|
||||
const key = this.externalRowKey(row);
|
||||
return this.externalEditDrafts[key] || row;
|
||||
},
|
||||
clearExternalEditState(key) {
|
||||
const editing = { ...this.externalEditing };
|
||||
const drafts = { ...this.externalEditDrafts };
|
||||
const snapshots = { ...this.externalEditSnapshots };
|
||||
delete editing[key];
|
||||
delete drafts[key];
|
||||
delete snapshots[key];
|
||||
this.externalEditing = editing;
|
||||
this.externalEditDrafts = drafts;
|
||||
this.externalEditSnapshots = snapshots;
|
||||
},
|
||||
isExternalEditableColumn(prop) {
|
||||
return !['externalLineNo', 'matchStatus'].includes(prop);
|
||||
},
|
||||
@@ -1672,34 +1698,30 @@ export default {
|
||||
},
|
||||
openExternalAdjust(row) {
|
||||
const key = this.externalRowKey(row);
|
||||
const draft = this.cloneExternalEditRow(row);
|
||||
this.externalEditSnapshots = {
|
||||
...this.externalEditSnapshots,
|
||||
[key]: { ...row },
|
||||
[key]: this.cloneExternalEditRow(row),
|
||||
};
|
||||
this.externalEditDrafts = { ...this.externalEditDrafts, [key]: draft };
|
||||
this.externalEditing = { ...this.externalEditing, [key]: true };
|
||||
},
|
||||
cancelExternalAdjust(row) {
|
||||
const key = this.externalRowKey(row);
|
||||
const snapshot = this.externalEditSnapshots[key];
|
||||
if (snapshot) Object.assign(row, snapshot);
|
||||
const editing = { ...this.externalEditing };
|
||||
const snapshots = { ...this.externalEditSnapshots };
|
||||
delete editing[key];
|
||||
delete snapshots[key];
|
||||
this.externalEditing = editing;
|
||||
this.externalEditSnapshots = snapshots;
|
||||
this.clearExternalEditState(this.externalRowKey(row));
|
||||
},
|
||||
async finishExternalAdjust(row) {
|
||||
row.feeItemsJson = JSON.stringify(row.feeItems || {});
|
||||
const key = this.externalRowKey(row);
|
||||
const editing = { ...this.externalEditing };
|
||||
const snapshots = { ...this.externalEditSnapshots };
|
||||
delete editing[key];
|
||||
delete snapshots[key];
|
||||
this.externalEditing = editing;
|
||||
this.externalEditSnapshots = snapshots;
|
||||
const draft = this.externalEditDrafts[key];
|
||||
if (draft) {
|
||||
const feeItems = { ...(draft.feeItems || {}) };
|
||||
Object.assign(row, draft, { feeItems });
|
||||
row.feeItemsJson = JSON.stringify(feeItems);
|
||||
} else {
|
||||
row.feeItemsJson = JSON.stringify(row.feeItems || {});
|
||||
}
|
||||
this.clearExternalEditState(key);
|
||||
this.refreshLocalStats();
|
||||
this.$message.success('调整已暂存');
|
||||
this.$message.success('调整已暂存,匹配或完成对账后生效');
|
||||
},
|
||||
normalizeExternalDateTime(value) {
|
||||
if (!value) return null;
|
||||
@@ -1743,7 +1765,8 @@ export default {
|
||||
differenceQuantity: Math.abs(internalQuantity - externalQuantity),
|
||||
differenceAmount: Math.abs(internalAmount - externalAmount),
|
||||
matchedCount,
|
||||
unmatchedCount: internalUnmatched + externalUnmatched,
|
||||
// 无法匹配按内部账单条数统计,不叠加外部未匹配数
|
||||
unmatchedCount: internalUnmatched,
|
||||
matchStatus:
|
||||
this.internalDetails.length > 0 &&
|
||||
this.internalDetails.length === this.externalDetails.length &&
|
||||
|
||||
Reference in New Issue
Block a user