🐛 修复列表二次搜索与结算导入回列表,并完善付款申请多结算单展示

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-16 16:03:26 +08:00
parent 4287133f84
commit 6067d24e3b
25 changed files with 276 additions and 106 deletions
+32
View File
@@ -1,3 +1,35 @@
/**
* 合并列表搜索条件:新条件覆盖旧条件,本次显式清空的字段从查询中移除。
*/
export const applyIncomingSearch = (current = {}, incoming = {}) => {
const merged = { ...current, ...incoming };
Object.keys(incoming || {}).forEach(key => {
const value = incoming[key];
if (
value === '' ||
value === null ||
value === undefined ||
(Array.isArray(value) && value.length === 0)
) {
delete merged[key];
}
});
return merged;
};
/**
* 启停状态下拉「全部」在数字类型下会被转成 0/-1,不能当作查询条件。
* 状态 0 表示草稿等有效值的页面不要调用。
*/
export const omitInvalidListStatus = (params = {}) => {
const values = { ...params };
const status = values.status;
if (status === 0 || status === '0' || status === -1 || status === '-1') {
delete values.status;
}
return values;
};
export const normalizeSearchRangeParams = (params = {}, rangeMap = {}) => {
const values = { ...params };
+2 -1
View File
@@ -150,6 +150,7 @@ import { mapGetters } from 'vuex';
import { downloadXls } from '@/utils/util';
import { openImportDialog } from '@/utils/import-excel';
import { formatUpdateUserName } from '@/utils/audit';
import { omitInvalidListStatus } from '@/utils/search-range';
import { getToken, isAdministrator } from '@/utils/auth';
import { getCoordinateValidationMessage, normalizeCoordinateInput } from '@/utils/coordinate';
import AddressMapPicker from '@/components/address-map-picker/main.vue';
@@ -1182,7 +1183,7 @@ export default {
},
onLoad(page, params = {}) {
this.loading = true;
getList(page.currentPage, page.pageSize, { ...params, ...this.query })
getList(page.currentPage, page.pageSize, omitInvalidListStatus({ ...params, ...this.query }))
.then(res => {
const data = res.data.data;
this.page.total = data.total;
+2 -1
View File
@@ -104,6 +104,7 @@ import { mapGetters } from 'vuex';
import { downloadXls } from '@/utils/util';
import { openImportDialog } from '@/utils/import-excel';
import { formatUpdateUserName } from '@/utils/audit';
import { omitInvalidListStatus } from '@/utils/search-range';
import { getToken } from '@/utils/auth';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
@@ -507,7 +508,7 @@ export default {
this.onLoad(this.page, this.query);
},
buildQuery(params = {}) {
const values = { ...params, ...this.query };
const values = omitInvalidListStatus({ ...params, ...this.query });
const rangeMap = {
effectiveDateRange: ['effectiveDateStart', 'effectiveDateEnd'],
expiryDateRange: ['expiryDateStart', 'expiryDateEnd'],
+2 -1
View File
@@ -63,6 +63,7 @@
<script>
import { getList, getDetail, submit, remove, changeStatus } from '@/api/base/customer-type';
import { omitInvalidListStatus } from '@/utils/search-range';
import { mapGetters } from 'vuex';
export default {
@@ -290,7 +291,7 @@ export default {
},
onLoad(page, params = {}) {
this.loading = true;
getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
getList(page.currentPage, page.pageSize, omitInvalidListStatus(Object.assign(params, this.query))).then(res => {
const data = res.data.data;
this.page.total = data.total;
this.data = data.records;
+2 -1
View File
@@ -97,6 +97,7 @@ import { exportBlob } from '@/api/common';
import { getDictionaryAll } from '@/api/system/dictbiz';
import { getDeptTree } from '@/api/system/dept';
import { downloadXls } from '@/utils/util';
import { omitInvalidListStatus } from '@/utils/search-range';
import { getToken } from '@/utils/auth';
import { Download } from '@element-plus/icons-vue';
import { mapGetters } from 'vuex';
@@ -569,7 +570,7 @@ export default {
},
onLoad(page, params = {}) {
this.loading = true;
getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
getList(page.currentPage, page.pageSize, omitInvalidListStatus(Object.assign(params, this.query))).then(res => {
const data = res.data.data;
this.page.total = data.total;
this.data = data.records;
+2 -1
View File
@@ -82,6 +82,7 @@
import { mapGetters } from 'vuex';
import { changeStatus, getDetail, getList, remove, submit } from '@/api/base/measurement-unit';
import { createOption } from '@/option/base/measurement-unit';
import { omitInvalidListStatus } from '@/utils/search-range';
import { isAdministrator } from '@/utils/auth';
export default {
@@ -218,7 +219,7 @@ export default {
},
onLoad(page = this.page, params = this.query) {
this.loading = true;
return getList(page.currentPage, page.pageSize, params)
return getList(page.currentPage, page.pageSize, omitInvalidListStatus(params))
.then(res => {
const pageData = res.data.data || {};
this.data = pageData.records || [];
+2 -1
View File
@@ -270,6 +270,7 @@ import { mapGetters } from 'vuex';
import { downloadXls } from '@/utils/util';
import { openImportDialog } from '@/utils/import-excel';
import { formatUpdateUserName } from '@/utils/audit';
import { omitInvalidListStatus } from '@/utils/search-range';
import { getToken, isAdministrator } from '@/utils/auth';
import { getCoordinateValidationMessage, normalizeCoordinateInput } from '@/utils/coordinate';
import AddressMapPicker from '@/components/address-map-picker/main.vue';
@@ -1636,7 +1637,7 @@ export default {
},
onLoad(page, params = {}) {
this.loading = true;
getList(page.currentPage, page.pageSize, { ...params, ...this.query })
getList(page.currentPage, page.pageSize, omitInvalidListStatus({ ...params, ...this.query }))
.then(res => {
const data = res.data.data;
this.page.total = data.total;
+2 -1
View File
@@ -150,6 +150,7 @@ import { mapGetters } from 'vuex';
import { downloadXls } from '@/utils/util';
import { openImportDialog } from '@/utils/import-excel';
import { formatUpdateUserName } from '@/utils/audit';
import { omitInvalidListStatus } from '@/utils/search-range';
import { getToken, isAdministrator } from '@/utils/auth';
import { getCoordinateValidationMessage, normalizeCoordinateInput } from '@/utils/coordinate';
import AddressMapPicker from '@/components/address-map-picker/main.vue';
@@ -1157,7 +1158,7 @@ export default {
},
onLoad(page, params = {}) {
this.loading = true;
getList(page.currentPage, page.pageSize, { ...params, ...this.query })
getList(page.currentPage, page.pageSize, omitInvalidListStatus({ ...params, ...this.query }))
.then(res => {
const data = res.data.data;
this.page.total = data.total;
+3 -1
View File
@@ -416,6 +416,7 @@ import { getList as getProjectList } from '@/api/business/project-apply';
import { getDeptTree } from '@/api/system/dept';
import { exportBlob } from '@/api/common';
import { config, option } from '@/option/business/process-config';
import { applyIncomingSearch } from '@/utils/search-range';
import { getToken, isAdministrator } from '@/utils/auth';
import { downloadXls } from '@/utils/util';
import { mapGetters } from 'vuex';
@@ -603,7 +604,8 @@ export default {
});
},
normalizeListQuery(params = {}) {
const query = { ...params, ...this.query };
// 新条件覆盖旧条件,清空的筛选项不再沿用上一次的值。
const query = applyIncomingSearch(this.query, params);
const rawDeptId = query.deptId ?? query.searchDeptId;
delete query.searchDeptId;
if (rawDeptId !== undefined && rawDeptId !== null && String(rawDeptId).trim() !== '') {
+52 -10
View File
@@ -1233,7 +1233,7 @@ export default {
];
}
const referenceRow = this.createReferenceRow(data);
this.referenceRows = referenceRow.settlementNo ? [referenceRow] : [];
this.referenceRows = this.restoreReferenceRows(data, referenceRow);
this.paymentRecords = data.paymentRecords || [];
},
async initialize() {
@@ -1256,7 +1256,7 @@ export default {
invoices: data.invoices || [],
};
const referenceRow = this.createReferenceRow(data);
this.referenceRows = referenceRow.settlementNo ? [referenceRow] : [];
this.referenceRows = this.restoreReferenceRows(data, referenceRow);
this.paymentRecords = data.paymentRecords || [];
if (this.form.paymentType === 'project_advance') {
await this.loadProjectOptions();
@@ -1474,6 +1474,33 @@ export default {
this.$refs.formRef?.clearValidate();
});
},
restoreReferenceRows(data, fallbackRow) {
const relations = Array.isArray(data?.settlements) ? data.settlements : [];
const rows = relations
.map(item => {
const isPre = item.preSettlementId !== undefined && item.preSettlementId !== null && item.preSettlementId !== '';
const settlementNo = item.preSettlementNo || item.formalSettlementNo || '';
if (!settlementNo) return null;
return {
id: isPre ? item.preSettlementId : item.formalSettlementId,
settlementNo,
referenceType: isPre ? 'pre' : 'formal',
settlementAmount: Number(Number(item.settlementAmount || 0).toFixed(2)),
payableAmount: Number(Number(item.payableAmount ?? item.settlementAmount ?? 0).toFixed(2)),
appliedAmount: Number(Number(item.appliedAmount || 0).toFixed(2)),
fixedAppliedAmount: this.readonly,
};
})
.filter(Boolean);
if (rows.length > 1) {
this.form.preSettlementIds = rows.filter(item => item.referenceType === 'pre').map(item => item.id);
this.form.settlementIds = rows.filter(item => item.referenceType === 'formal').map(item => item.id);
if (this.form.preSettlementIds.length) this.form.preSettlementId = this.form.preSettlementIds[0];
if (this.form.settlementIds.length) this.form.settlementId = this.form.settlementIds[0];
return rows;
}
return fallbackRow?.settlementNo ? [fallbackRow] : [];
},
createReferenceRow(row) {
const settlementAmount = Number(row.settlementAmount || 0);
const appliedAmount = Number(row.advanceAppliedAmount || row.appliedPaymentAmount || 0);
@@ -1482,11 +1509,13 @@ export default {
id: row.preSettlementId || row.settlementId || row.id,
settlementNo: row.preSettlementNo || row.formalSettlementNo || row.settlementNo || '',
referenceType: isPre ? 'pre' : 'formal',
settlementAmount,
payableAmount:
row.payableAmount === undefined || row.payableAmount === null
settlementAmount: Number(Number(settlementAmount || 0).toFixed(2)),
payableAmount: Number(
(row.payableAmount === undefined || row.payableAmount === null
? Math.max(0, settlementAmount - appliedAmount)
: Number(row.payableAmount || 0),
: Number(row.payableAmount || 0)
).toFixed(2)
),
};
},
createInvoiceRows(invoices = [], settlementNo = '') {
@@ -1544,9 +1573,24 @@ export default {
}
const first = rows[0];
this.form.invoices = [];
this.referenceRows = rows.map(item =>
this.createReferenceRow({ ...item, referenceType: 'pre' })
const paymentType =
this.form.paymentType === 'settlement_payment' ? 'settlement_payment' : 'progress_advance';
const amountResponses = await Promise.all(
rows.map(item => {
const referenceId = item.preSettlementId || item.id;
if (!this.isValidReferenceId(referenceId)) return Promise.resolve(null);
return api.getReferenceAmount(paymentType, referenceId, this.form.id).catch(() => null);
})
);
this.referenceRows = rows.map((item, index) => {
const amount = this.unwrapData(amountResponses[index]) || {};
return this.createReferenceRow({
...item,
referenceType: 'pre',
settlementAmount: amount.settlementAmount ?? item.settlementAmount,
payableAmount: amount.payableAmount,
});
});
const settlementAmount = this.referenceRows.reduce(
(total, item) => total + Number(item.settlementAmount || 0),
0
@@ -1557,8 +1601,6 @@ export default {
);
const paymentRatio = Number(this.form.paymentRatio || 0);
// 尾款付款场景下选择预结算单时保留尾款付款类型,不强制改为进度预付
const paymentType =
this.form.paymentType === 'settlement_payment' ? 'settlement_payment' : 'progress_advance';
this.amountSyncing = true;
Object.assign(this.form, {
paymentType,
@@ -252,31 +252,36 @@
:index="detailIndexMethod"
/>
<el-table-column
v-for="column in detailTableColumns"
:key="column.prop"
v-bind="column"
v-for="item in detailDisplayColumns"
:key="item.key"
:label="item.kind === 'fee' ? item.name : item.column.label"
:prop="item.kind === 'fee' ? undefined : item.column.prop"
:min-width="item.kind === 'fee' ? 130 : item.column.minWidth"
align="center"
show-overflow-tooltip
>
<template #default="{ row }">
<span v-if="item.kind === 'fee'">
{{ formatMoney(parseFeeItems(row.feeItemsJson || row.feeItems)[item.name]) }}
</span>
<el-link
v-if="column.link && row[column.prop] && !publicMode"
v-else-if="item.column.link && row[item.column.prop] && !publicMode"
type="primary"
@click.stop="handleDetailLink(row, column)"
@click.stop="handleDetailLink(row, item.column)"
>
{{ row[column.prop] }}
{{ row[item.column.prop] }}
</el-link>
<span v-else-if="column.money">{{ formatMoney(row[column.prop]) }}</span>
<span v-else-if="column.prop === 'transportQuantity'">
{{ formatDetailTransportQuantity(row[column.prop]) }}
<span v-else-if="item.column.money">{{ formatMoney(row[item.column.prop]) }}</span>
<span v-else-if="item.column.prop === 'transportQuantity'">
{{ formatDetailTransportQuantity(row[item.column.prop]) }}
</span>
<span v-else-if="column.prop === 'mileage'">
{{ formatDetailMileage(row[column.prop]) }}
<span v-else-if="item.column.prop === 'mileage'">
{{ formatDetailMileage(row[item.column.prop]) }}
</span>
<span v-else-if="column.prop === 'transportType'">
{{ transportTypeName(row[column.prop]) }}
<span v-else-if="item.column.prop === 'transportType'">
{{ transportTypeName(row[item.column.prop]) }}
</span>
<span v-else>{{ displayValue(row[column.prop]) }}</span>
<span v-else>{{ displayValue(row[item.column.prop]) }}</span>
</template>
</el-table-column>
<el-table-column v-if="editable" label="操作" width="150" fixed="right" align="center">
@@ -1217,6 +1222,26 @@ export default {
title() {
return this.readonly ? '查看正式结算单' : this.recordId ? '编辑正式结算单' : '新增正式结算单';
},
detailFeeItemNames() {
const names = new Set();
this.details.forEach(row => {
Object.keys(this.parseFeeItems(row.feeItemsJson || row.feeItems)).forEach(name =>
names.add(name)
);
});
return Array.from(names);
},
detailDisplayColumns() {
const columns = this.detailTableColumns;
const unitPriceIndex = columns.findIndex(column => column.prop === 'unitPrice');
const beforeColumns = unitPriceIndex < 0 ? columns : columns.slice(0, unitPriceIndex + 1);
const afterColumns = unitPriceIndex < 0 ? [] : columns.slice(unitPriceIndex + 1);
return [
...beforeColumns.map(column => ({ kind: 'field', key: column.prop, column })),
...this.detailFeeItemNames.map(name => ({ kind: 'fee', key: `fee-${name}`, name })),
...afterColumns.map(column => ({ kind: 'field', key: column.prop, column })),
];
},
// 币种为空按人民币处理,与后端预结算/正式结算对空币种的默认取值一致
isLocalCurrencySettlement() {
return normalizeCurrencyCode(this.form.currency) === 'RMB';
@@ -247,60 +247,52 @@
:index="detailIndexMethod"
/>
<el-table-column
v-for="column in visibleDetailColumns"
:key="column.prop"
:label="column.label"
:prop="column.prop"
:min-width="column.minWidth"
v-for="item in detailDisplayColumns"
:key="item.key"
:label="item.kind === 'fee' ? item.name : item.column.label"
:prop="item.kind === 'fee' ? undefined : item.column.prop"
:min-width="item.kind === 'fee' ? 130 : item.column.minWidth"
align="center"
show-overflow-tooltip
>
<template #default="{ row }">
<span v-if="item.kind === 'fee'">
{{
formatMoney(
parseFeeItems(row.feeItemsJson)[item.name],
row.currency || form.currency
)
}}
</span>
<el-link
v-if="column.link && row[column.prop] && !publicMode"
v-else-if="item.column.link && row[item.column.prop] && !publicMode"
type="primary"
@click.stop="handleDetailLink(row, column)"
@click.stop="handleDetailLink(row, item.column)"
>
{{ row[column.prop] }}
{{ row[item.column.prop] }}
</el-link>
<span v-else-if="column.money && column.prop === 'unitPrice'">
<span v-else-if="item.column.money && item.column.prop === 'unitPrice'">
{{ formatUnitPrice(row) }}
</span>
<span v-else-if="column.money">
{{ formatMoney(row[column.prop], row.currency || form.currency) }}
<span v-else-if="item.column.money">
{{ formatMoney(row[item.column.prop], row.currency || form.currency) }}
</span>
<span v-else-if="column.prop === 'transportQuantityText'">
<span v-else-if="item.column.prop === 'transportQuantityText'">
{{ formatQuantity(row) }}
</span>
<span v-else-if="pageMode && column.prop === 'mileage'">
{{ formatDetailMileage(row[column.prop]) }}
<span v-else-if="item.column.prop === 'mileage'">
{{ formatDetailMileage(row[item.column.prop]) }}
</span>
<span v-else-if="column.prop === 'transportType'">
{{ transportTypeName(row[column.prop]) }}
<span v-else-if="item.column.prop === 'transportType'">
{{ transportTypeName(row[item.column.prop]) }}
</span>
<span v-else-if="column.prop === 'cargoName'">
<span v-else-if="item.column.prop === 'cargoName'">
{{ formatCargoNames(row) }}
</span>
<span v-else-if="column.prop === 'cargoType'">
<span v-else-if="item.column.prop === 'cargoType'">
{{ formatCargoTypes(row) }}
</span>
<span v-else>{{ displayValue(row[column.prop]) }}</span>
</template>
</el-table-column>
<el-table-column
v-for="feeItem in detailFeeItemNames"
:key="`fee-${feeItem}`"
:label="feeItem"
min-width="130"
align="center"
>
<template #default="{ row }">
{{
formatMoney(
parseFeeItems(row.feeItemsJson)[feeItem],
row.currency || form.currency
)
}}
<span v-else>{{ displayValue(row[item.column.prop]) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" :width="editable ? 150 : 90" fixed="right" align="center">
@@ -790,12 +782,13 @@
</el-table-column>
<el-table-column label="里程(KM)" min-width="140" align="center">
<template #default="{ row }">
<span v-if="adjustDialog.readonly">{{ formatDetailMileage(row.mileage) }}</span>
<el-input-number
v-else
v-model="row.mileage"
:min="0"
:precision="2"
:controls="false"
:disabled="adjustDialog.readonly"
@change="recalculateAdjustRow(row, 'mileage')"
/>
</template>
@@ -1244,6 +1237,17 @@ export default {
});
return Array.from(names);
},
detailDisplayColumns() {
const columns = this.visibleDetailColumns;
const unitPriceIndex = columns.findIndex(column => column.prop === 'unitPrice');
const beforeColumns = unitPriceIndex < 0 ? columns : columns.slice(0, unitPriceIndex + 1);
const afterColumns = unitPriceIndex < 0 ? [] : columns.slice(unitPriceIndex + 1);
return [
...beforeColumns.map(column => ({ kind: 'field', key: column.prop, column })),
...this.detailFeeItemNames.map(name => ({ kind: 'fee', key: `fee-${name}`, name })),
...afterColumns.map(column => ({ kind: 'field', key: column.prop, column })),
];
},
// 按 preSettlementDetailId 分组的明细数据(用于拼接货物名称和类型)
groupedDetails() {
const groups = {};
@@ -1792,7 +1796,7 @@ export default {
return option?.dictValue || value;
},
formatDetailMileage(value) {
if (value === undefined || value === null || value === '' || Number(value) === -1) return '';
if (value === undefined || value === null || value === '' || Number(value) === -1) return '-';
return value;
},
removeSummaryFee(index) {
@@ -272,7 +272,7 @@
</template>
<script setup>
import { computed, onMounted, reactive, ref } from 'vue';
import { computed, getCurrentInstance, onMounted, reactive, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { ElMessage, ElMessageBox } from 'element-plus';
import { QuestionFilled } from '@element-plus/icons-vue';
@@ -284,6 +284,8 @@ import { downloadXls } from '@/utils/util';
const route = useRoute();
const router = useRouter();
const instance = getCurrentInstance();
const settlementImportListRefreshKey = 'settlement-import-list-refresh';
const formRef = ref();
const uploadRef = ref();
@@ -859,6 +861,12 @@ const goBack = () => {
router.push({ path: '/settlement/settlement-import' });
};
const leaveAfterConfirm = () => {
sessionStorage.setItem(settlementImportListRefreshKey, '1');
instance?.proxy?.$router?.$avueRouter?.closeTag?.();
router.push({ path: '/settlement/settlement-import' });
};
const downloadFailureExcel = async failureRows => {
const response = await api.exportFailures({
feeItemNames: [...feeItemNames.value],
@@ -942,7 +950,7 @@ const confirmImport = async () => {
const batch = unwrapData(response) || {};
if (batch.batchNo) form.batchNo = batch.batchNo;
ElMessage.success('确认导入成功');
goBack();
leaveAfterConfirm();
} catch (error) {
if (error === 'cancel' || error === 'close') return;
ElMessage.error(error?.message || '确认导入失败');
@@ -2691,12 +2691,12 @@ export default {
return `${Number(value).toFixed(2)} ${currency}`;
},
formatDetailCell(row, prop) {
if (prop === 'mileage' && Number(row?.[prop]) === -1) {
return '-';
}
if (
prop === 'mileage' &&
(row?.[prop] === null ||
row?.[prop] === undefined ||
row?.[prop] === '' ||
Number(row[prop]) === -1)
(row?.[prop] === null || row?.[prop] === undefined || row?.[prop] === '')
) {
return '';
}
@@ -211,6 +211,8 @@ const SETTLEMENT_TYPE_OPTIONS = [
{ label: '应付正式结算单', value: 'payable' },
];
const SETTLEMENT_IMPORT_LIST_REFRESH_KEY = 'settlement-import-list-refresh';
export default {
name: 'SettlementImport',
data() {
@@ -270,7 +272,29 @@ export default {
this.loadOptions();
this.loadTable();
},
activated() {
this.consumeListRefresh();
},
watch: {
$route(to, from) {
if (
to.path === '/settlement/settlement-import' &&
from?.path === '/settlement/settlement-import/form'
) {
this.consumeListRefresh();
}
},
},
methods: {
consumeListRefresh() {
if (sessionStorage.getItem(SETTLEMENT_IMPORT_LIST_REFRESH_KEY) !== '1') {
return;
}
sessionStorage.removeItem(SETTLEMENT_IMPORT_LIST_REFRESH_KEY);
this.page.current = 1;
this.loadOptions();
this.loadTable();
},
hasPermission(code) {
return this.isAdmin || this.validData(this.permission?.[code], false);
},
+2 -2
View File
@@ -158,7 +158,7 @@ import { exportBlob } from '@/api/common';
import { downloadXls } from '@/utils/util';
import { openImportDialog } from '@/utils/import-excel';
import { getToken, isAdministrator } from '@/utils/auth';
import { normalizeSearchRangeParams } from '@/utils/search-range';
import { applyIncomingSearch, normalizeSearchRangeParams } from '@/utils/search-range';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
import { mapGetters } from 'vuex';
import { excelOption, exportColumns, option } from '@/option/vehicle/accident-record';
@@ -550,7 +550,7 @@ export default {
};
},
buildQuery(params = {}) {
return normalizeSearchRangeParams({ ...params, ...this.query }, createTimeRangeMap);
return normalizeSearchRangeParams(applyIncomingSearch(this.query, params), createTimeRangeMap);
},
handleTemplate() {
exportBlob(
@@ -468,7 +468,11 @@ import {
publish,
changeStatus,
} from '@/api/vehicle/credit-score-quantification';
import { normalizeSearchRangeParams } from '@/utils/search-range';
import {
applyIncomingSearch,
normalizeSearchRangeParams,
omitInvalidListStatus,
} from '@/utils/search-range';
import { mapGetters } from 'vuex';
import { isAdministrator } from '@/utils/auth';
@@ -1324,7 +1328,9 @@ export default {
});
},
buildQuery(params = {}) {
return normalizeSearchRangeParams({ ...params, ...this.query }, createTimeRangeMap);
return omitInvalidListStatus(
normalizeSearchRangeParams(applyIncomingSearch(this.query, params), createTimeRangeMap)
);
},
},
};
+33 -13
View File
@@ -2043,7 +2043,6 @@ export default {
search: true,
searchOrder: 6,
searchValue: '',
dataType: 'number',
minWidth: 100,
dicData: [
{ label: '全部', value: '' },
@@ -5297,19 +5296,9 @@ export default {
this.onLoad(this.page);
},
searchChange(params, done) {
// 搜索区所属组织级联返回的是 ID 路径数组,取末级 ID 转成部门名称传给后端(与列表接口 deptName 字段一致)
if (Array.isArray(params.deptName)) {
const path = params.deptName.filter(
item => item !== undefined && item !== null && item !== ''
);
const deptId = path.length ? path[path.length - 1] : '';
params.deptName = deptId
? this.deptOptions.find(item => String(item.value) === String(deptId))?.rawLabel || ''
: '';
}
this.query = this.buildQuery(params);
this.page.currentPage = 1;
this.onLoad(this.page);
this.onLoad(this.page, this.query);
done();
},
selectionChange(list) {
@@ -5370,7 +5359,38 @@ export default {
};
},
buildQuery(params = {}) {
return normalizeSearchRangeParams({ ...params, ...this.query }, createTimeRangeMap);
// 新条件覆盖旧条件;本次显式清空的字段必须从查询里去掉,避免第二次搜索仍带着上一次的客商名称。
const merged = { ...this.query, ...params };
Object.keys(params).forEach(key => {
const value = params[key];
if (
value === '' ||
value === null ||
value === undefined ||
(Array.isArray(value) && value.length === 0)
) {
delete merged[key];
}
});
if (Array.isArray(merged.deptName)) {
const path = merged.deptName.filter(
item => item !== undefined && item !== null && item !== ''
);
const deptId = path.length ? path[path.length - 1] : '';
merged.deptName = deptId
? this.deptOptions.find(item => String(item.value) === String(deptId))?.rawLabel || ''
: '';
if (!merged.deptName) {
delete merged.deptName;
}
}
const values = normalizeSearchRangeParams(merged, createTimeRangeMap);
// 状态下拉「全部」会被数字类型转成 0/-1,二次搜索会把列表滤空。
const status = values.status;
if (status === 0 || status === '0' || status === -1 || status === '-1') {
delete values.status;
}
return values;
},
},
};
+2 -2
View File
@@ -220,7 +220,7 @@ import { downloadXls } from '@/utils/util';
import { handleImportExcel } from '@/utils/import-excel';
import { getToken, isAdministrator } from '@/utils/auth';
import { getUploadHeaders } from '@/utils/upload';
import { normalizeSearchRangeParams } from '@/utils/search-range';
import { applyIncomingSearch, normalizeSearchRangeParams } from '@/utils/search-range';
import { mapGetters } from 'vuex';
import { ElLoading } from 'element-plus';
import { excelOption, exportColumns, option } from '@/option/vehicle/insurance-record';
@@ -409,7 +409,7 @@ export default {
: integerPart;
},
buildQuery(params = {}) {
return normalizeSearchRangeParams({ ...params, ...this.query }, createTimeRangeMap);
return normalizeSearchRangeParams(applyIncomingSearch(this.query, params), createTimeRangeMap);
},
validateRow(row) {
if (row.startDate && row.endDate && row.endDate < row.startDate) {
+2 -2
View File
@@ -195,7 +195,7 @@ import { downloadXls } from '@/utils/util';
import { openImportDialog } from '@/utils/import-excel';
import { formatUpdateUserName } from '@/utils/audit';
import { getToken, isAdministrator } from '@/utils/auth';
import { normalizeSearchRangeParams } from '@/utils/search-range';
import { applyIncomingSearch, normalizeSearchRangeParams } from '@/utils/search-range';
import AddressMapPicker from '@/components/address-map-picker/main.vue';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
import { mapGetters } from 'vuex';
@@ -903,7 +903,7 @@ export default {
};
},
buildQuery(params = {}) {
return normalizeSearchRangeParams({ ...params, ...this.query }, createTimeRangeMap);
return normalizeSearchRangeParams(applyIncomingSearch(this.query, params), createTimeRangeMap);
},
handleTemplate() {
exportBlob(
+2 -2
View File
@@ -168,7 +168,7 @@ import { downloadXls } from '@/utils/util';
import { openImportDialog } from '@/utils/import-excel';
import { formatUpdateUserName } from '@/utils/audit';
import { getToken, isAdministrator } from '@/utils/auth';
import { normalizeSearchRangeParams } from '@/utils/search-range';
import { applyIncomingSearch, normalizeSearchRangeParams } from '@/utils/search-range';
import AddressMapPicker from '@/components/address-map-picker/main.vue';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
import { mapGetters } from 'vuex';
@@ -831,7 +831,7 @@ export default {
};
},
buildQuery(params = {}) {
return normalizeSearchRangeParams({ ...params, ...this.query }, createTimeRangeMap);
return normalizeSearchRangeParams(applyIncomingSearch(this.query, params), createTimeRangeMap);
},
handleTemplate() {
exportBlob(
+2 -2
View File
@@ -210,7 +210,7 @@ import { exportBlob } from '@/api/common';
import { downloadXls } from '@/utils/util';
import { openImportDialog } from '@/utils/import-excel';
import { getToken, isAdministrator } from '@/utils/auth';
import { normalizeSearchRangeParams } from '@/utils/search-range';
import { applyIncomingSearch, normalizeSearchRangeParams } from '@/utils/search-range';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
import { mapGetters } from 'vuex';
import { excelOption, exportColumns, option } from '@/option/vehicle/mileage-record';
@@ -607,7 +607,7 @@ export default {
},
buildQuery(params = {}) {
return normalizeSearchRangeParams(
{ ...params, ...this.query, vehicleType: '车辆' },
{ ...applyIncomingSearch(this.query, params), vehicleType: '车辆' },
createTimeRangeMap
);
},
@@ -155,7 +155,7 @@ import { exportBlob } from '@/api/common';
import { downloadXls } from '@/utils/util';
import { openImportDialog } from '@/utils/import-excel';
import { getToken, isAdministrator } from '@/utils/auth';
import { normalizeSearchRangeParams } from '@/utils/search-range';
import { applyIncomingSearch, normalizeSearchRangeParams } from '@/utils/search-range';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
import { mapGetters } from 'vuex';
import { excelOption, exportColumns, option } from '@/option/vehicle/tire-replacement-record';
@@ -500,7 +500,7 @@ export default {
};
},
buildQuery(params = {}) {
return normalizeSearchRangeParams({ ...params, ...this.query }, createTimeRangeMap);
return normalizeSearchRangeParams(applyIncomingSearch(this.query, params), createTimeRangeMap);
},
handleTemplate() {
exportBlob(
@@ -130,7 +130,7 @@ import { exportBlob } from '@/api/common';
import { downloadXls } from '@/utils/util';
import { openImportDialog } from '@/utils/import-excel';
import { getToken, isAdministrator } from '@/utils/auth';
import { normalizeSearchRangeParams } from '@/utils/search-range';
import { applyIncomingSearch, normalizeSearchRangeParams } from '@/utils/search-range';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
import { mapGetters } from 'vuex';
import { excelOption, exportColumns, option } from '@/option/vehicle/transport-change-record';
@@ -478,7 +478,7 @@ export default {
};
},
buildQuery(params = {}) {
return normalizeSearchRangeParams({ ...params, ...this.query }, createTimeRangeMap);
return normalizeSearchRangeParams(applyIncomingSearch(this.query, params), createTimeRangeMap);
},
handleTemplate() {
exportBlob(
+2 -2
View File
@@ -197,7 +197,7 @@ import { exportBlob } from '@/api/common';
import { downloadXls } from '@/utils/util';
import { openImportDialog } from '@/utils/import-excel';
import { getToken, isAdministrator } from '@/utils/auth';
import { normalizeSearchRangeParams } from '@/utils/search-range';
import { applyIncomingSearch, normalizeSearchRangeParams } from '@/utils/search-range';
import AddressMapPicker from '@/components/address-map-picker/main.vue';
import VehicleAttachmentTable from '@/components/vehicle-attachment-table/main.vue';
import { mapGetters } from 'vuex';
@@ -673,7 +673,7 @@ export default {
};
},
buildQuery(params = {}) {
return normalizeSearchRangeParams({ ...params, ...this.query }, createTimeRangeMap);
return normalizeSearchRangeParams(applyIncomingSearch(this.query, params), createTimeRangeMap);
},
handleTemplate() {
exportBlob(