🐛 修复总单地址回填、结算费用英文项与项目部门提示
常用地址级联回填不再误清空;预结算/正式结算过滤 freightJson 杂项;项目查看态业务部门/平台公司支持悬停完整信息。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -652,6 +652,8 @@ export default {
|
||||
addressQuery: {},
|
||||
addressPage: { current: 1, size: 10, total: 0 },
|
||||
addressRegionPaths: { departure: [], arrival: [] },
|
||||
// 程序回填省市区时抑制 cascader @change,避免空值回调把已填地址清空
|
||||
suppressAddressRegionChange: false,
|
||||
regionOptions: [],
|
||||
regionLoading: false,
|
||||
regionRequest: null,
|
||||
@@ -889,26 +891,63 @@ export default {
|
||||
findRegionPathByName(options = [], regionName = '', parents = []) {
|
||||
const target = String(regionName || '').replace(/\s+/g, '');
|
||||
if (!target) return [];
|
||||
let suffixMatch = [];
|
||||
for (const item of options) {
|
||||
const nextParents = [...parents, item];
|
||||
const name = nextParents.map(region => region.title || region.name || '').join('');
|
||||
if (name === target) return nextParents.map(region => region.id);
|
||||
// 常用地址可能缺省名,允许「市+区」后缀命中完整省市区路径
|
||||
if (!suffixMatch.length && name.endsWith(target) && target.length >= 2) {
|
||||
suffixMatch = nextParents.map(region => region.id);
|
||||
}
|
||||
const path = this.findRegionPathByName(item.children, target, nextParents);
|
||||
if (path.length) return path;
|
||||
}
|
||||
return [];
|
||||
return suffixMatch;
|
||||
},
|
||||
findRegionPathByCode(options = [], regionCode = '', parents = []) {
|
||||
const target = String(regionCode || '').trim();
|
||||
if (!target) return [];
|
||||
for (const item of options) {
|
||||
const nextParents = [...parents, item];
|
||||
if (String(item.id) === target) return nextParents.map(region => region.id);
|
||||
if (String(item.id) === target || String(item.value || '') === target) {
|
||||
return nextParents.map(region => region.id);
|
||||
}
|
||||
const path = this.findRegionPathByCode(item.children, target, nextParents);
|
||||
if (path.length) return path;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
resolveRegionPath(field) {
|
||||
if (!field) return [];
|
||||
const codePath = this.findRegionPathByCode(
|
||||
this.regionOptions,
|
||||
field.model[field.regionCode]
|
||||
);
|
||||
if (codePath.length) return codePath;
|
||||
const namePath = this.findRegionPathByName(this.regionOptions, field.model[field.name]);
|
||||
if (namePath.length) return namePath;
|
||||
const composed = [field.model[field.provinceName], field.model[field.cityName], field.model[field.districtName]]
|
||||
.filter(Boolean)
|
||||
.join('');
|
||||
return this.findRegionPathByName(this.regionOptions, composed);
|
||||
},
|
||||
setAddressRegionPath(target, path = []) {
|
||||
const nextPath = Array.isArray(path) ? path.map(item => String(item)) : [];
|
||||
const current = this.addressRegionPaths[target] || [];
|
||||
if (
|
||||
current.length === nextPath.length &&
|
||||
current.every((item, index) => String(item) === String(nextPath[index]))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.suppressAddressRegionChange = true;
|
||||
// Vue3 直接写动态 key,避免整体替换对象导致其它 cascader 重建并触发空 @change
|
||||
this.addressRegionPaths[target] = nextPath;
|
||||
this.$nextTick(() => {
|
||||
this.suppressAddressRegionChange = false;
|
||||
});
|
||||
},
|
||||
regionLabels(path = []) {
|
||||
let options = this.regionOptions;
|
||||
const labels = [];
|
||||
@@ -947,10 +986,22 @@ export default {
|
||||
this.setAddressRegionNames(field, [provinceMatch?.[0], cityMatch?.[0], districtMatch?.[0]]);
|
||||
},
|
||||
handleAddressRegionChange(target, value) {
|
||||
if (this.suppressAddressRegionChange) return;
|
||||
const field = this.addressModel(target);
|
||||
const path = Array.isArray(value) ? value.map(item => String(item)) : [];
|
||||
this.addressRegionPaths = { ...this.addressRegionPaths, [target]: path };
|
||||
this.setAddressRegionPath(target, path);
|
||||
if (!field) return;
|
||||
// 程序回填/重建过程中 cascader 可能短暂抛出空值,不能据此清空已选常用地址
|
||||
if (!path.length) {
|
||||
const hasExisting =
|
||||
String(field.model[field.name] || '').trim() ||
|
||||
String(field.model[field.address] || '').trim() ||
|
||||
String(field.model[field.regionCode] || '').trim();
|
||||
if (hasExisting) {
|
||||
this.$nextTick(() => this.syncAddressRegionPath(target));
|
||||
return;
|
||||
}
|
||||
}
|
||||
const labels = this.regionLabels(path);
|
||||
field.model[field.name] = labels.join('');
|
||||
field.model[field.regionCode] = path.at(-1) || '';
|
||||
@@ -959,19 +1010,29 @@ export default {
|
||||
},
|
||||
syncAddressRegionPath(target) {
|
||||
const field = this.addressModel(target);
|
||||
if (!field) return;
|
||||
const codePath = this.findRegionPathByCode(this.regionOptions, field.model[field.regionCode]);
|
||||
const path = codePath.length
|
||||
? codePath
|
||||
: this.findRegionPathByName(this.regionOptions, field.model[field.name]);
|
||||
this.addressRegionPaths = { ...this.addressRegionPaths, [target]: path };
|
||||
if (!field || !this.regionOptions.length) return;
|
||||
const path = this.resolveRegionPath(field);
|
||||
this.setAddressRegionPath(target, path);
|
||||
if (path.length) this.setAddressRegionNames(field, this.regionLabels(path));
|
||||
},
|
||||
syncAddressRegionPaths() {
|
||||
if (!this.regionOptions.length) return;
|
||||
['departure', 'arrival', ...this.form.routes.map((route, index) => `route-${index}`)].forEach(target => {
|
||||
this.syncAddressRegionPath(target);
|
||||
});
|
||||
this.suppressAddressRegionChange = true;
|
||||
try {
|
||||
['departure', 'arrival', ...this.form.routes.map((route, index) => `route-${index}`)].forEach(
|
||||
target => {
|
||||
const field = this.addressModel(target);
|
||||
if (!field) return;
|
||||
const path = this.resolveRegionPath(field);
|
||||
this.addressRegionPaths[target] = path;
|
||||
if (path.length) this.setAddressRegionNames(field, this.regionLabels(path));
|
||||
}
|
||||
);
|
||||
} finally {
|
||||
this.$nextTick(() => {
|
||||
this.suppressAddressRegionChange = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
async loadDetail(id) {
|
||||
const res = await api.getDetail(id);
|
||||
@@ -1233,8 +1294,9 @@ export default {
|
||||
this.stationPage.current = 1;
|
||||
this.loadStationList();
|
||||
},
|
||||
selectStation(row) {
|
||||
const target = this.addressModel(this.addressTarget);
|
||||
async selectStation(row) {
|
||||
const targetKey = this.addressTarget;
|
||||
const target = this.addressModel(targetKey);
|
||||
if (!target) return;
|
||||
const station = this.normalizeStation(row);
|
||||
target.model[target.name] = station.stationName || station.regionName;
|
||||
@@ -1245,7 +1307,9 @@ export default {
|
||||
target.model[target.siteCode] = station.stationCode;
|
||||
this.setAddressRegionNamesFromRow(target, station);
|
||||
this.stationDialogVisible = false;
|
||||
this.loadRegionOptions().then(() => this.syncAddressRegionPath(this.addressTarget));
|
||||
await this.loadRegionOptions();
|
||||
await this.$nextTick();
|
||||
this.syncAddressRegionPath(targetKey);
|
||||
},
|
||||
async loadAddressList() {
|
||||
this.addressLoading = true;
|
||||
@@ -1271,8 +1335,9 @@ export default {
|
||||
this.addressPage.current = 1;
|
||||
this.loadAddressList();
|
||||
},
|
||||
selectAddress(row) {
|
||||
const target = this.addressModel(this.addressTarget);
|
||||
async selectAddress(row) {
|
||||
const targetKey = this.addressTarget;
|
||||
const target = this.addressModel(targetKey);
|
||||
if (!target) return;
|
||||
target.model[target.name] = row.regionName || row.addressName || '';
|
||||
target.model[target.address] = row.detailAddress || row.address || '';
|
||||
@@ -1284,7 +1349,10 @@ export default {
|
||||
target.model[target.siteCode] = '';
|
||||
this.setAddressRegionNamesFromRow(target, row);
|
||||
this.addressDialogVisible = false;
|
||||
this.loadRegionOptions().then(() => this.syncAddressRegionPath(this.addressTarget));
|
||||
await this.loadRegionOptions();
|
||||
// nextTick 确保途经点动态 key 已挂载 cascader 后再回填路径
|
||||
await this.$nextTick();
|
||||
this.syncAddressRegionPath(targetKey);
|
||||
},
|
||||
handleAddressDetailClick(target) {
|
||||
if (this.isBasicRouteReadonly) return;
|
||||
@@ -1803,12 +1871,23 @@ export default {
|
||||
},
|
||||
addRoute() {
|
||||
if (this.isBasicRouteReadonly) return;
|
||||
this.form.routes.push(this.createRoute());
|
||||
const index = this.form.routes.length;
|
||||
this.form.routes.push(this.createRoute(index));
|
||||
this.addressRegionPaths[`route-${index}`] = [];
|
||||
},
|
||||
removeRoute(index) {
|
||||
if (this.isBasicRouteReadonly) return;
|
||||
this.form.routes.splice(index, 1);
|
||||
this.syncAddressRegionPaths();
|
||||
const nextPaths = { departure: this.addressRegionPaths.departure || [], arrival: this.addressRegionPaths.arrival || [] };
|
||||
this.form.routes.forEach((route, routeIndex) => {
|
||||
nextPaths[`route-${routeIndex}`] = this.addressRegionPaths[`route-${routeIndex >= index ? routeIndex + 1 : routeIndex}`] || [];
|
||||
});
|
||||
this.suppressAddressRegionChange = true;
|
||||
this.addressRegionPaths = nextPaths;
|
||||
this.$nextTick(() => {
|
||||
this.suppressAddressRegionChange = false;
|
||||
this.syncAddressRegionPaths();
|
||||
});
|
||||
},
|
||||
goodsKey(row = {}) {
|
||||
return `${row.cargoName || ''}\u0000${row.cargoType || ''}`;
|
||||
|
||||
Reference in New Issue
Block a user