✨ 优化主数据地图回填与表单校验间距,并修复运单导入筛选与组织树定位
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+8
-1
@@ -189,7 +189,14 @@ axios.interceptors.response.use(
|
||||
// 兼容 Blob(浏览器 responseType='blob')与 string(非浏览器环境)两种形态。
|
||||
if (isJsonContentType(res) && !isPlainObject(res.data)) {
|
||||
try {
|
||||
const text = res.data instanceof Blob ? await res.data.text() : res.data;
|
||||
let text = '';
|
||||
if (typeof res.data?.text === 'function') {
|
||||
text = await res.data.text();
|
||||
} else if (typeof res.data === 'string') {
|
||||
text = res.data;
|
||||
} else if (typeof res.data?.arrayBuffer === 'function') {
|
||||
text = new TextDecoder().decode(await res.data.arrayBuffer());
|
||||
}
|
||||
const parsed = typeof text === 'string' && text ? JSON.parse(text) : null;
|
||||
if (parsed && typeof parsed === 'object') {
|
||||
res.data = parsed;
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
<div class="address-map-picker__info">{{ status }}</div>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" :disabled="!selected.longitude || resolving" @click="confirm">
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="!hasCoordinateValue(selected.longitude) || !hasCoordinateValue(selected.latitude) || resolving"
|
||||
@click="confirm"
|
||||
>
|
||||
确定
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -322,8 +326,31 @@ export default {
|
||||
this.marker = null;
|
||||
}
|
||||
},
|
||||
syncSelectedFromMarker() {
|
||||
// 确认时以当前标记点坐标为准,避免换地址后仍回填上一次经纬度
|
||||
if (!this.marker || typeof this.marker.getPosition !== 'function') {
|
||||
return;
|
||||
}
|
||||
const point = this.marker.getPosition();
|
||||
if (!point) {
|
||||
return;
|
||||
}
|
||||
const longitude =
|
||||
typeof point.getLng === 'function' ? point.getLng() : point.lng ?? point.longitude;
|
||||
const latitude =
|
||||
typeof point.getLat === 'function' ? point.getLat() : point.lat ?? point.latitude;
|
||||
if (!Number.isFinite(Number(longitude)) || !Number.isFinite(Number(latitude))) {
|
||||
return;
|
||||
}
|
||||
this.selected = {
|
||||
...this.selected,
|
||||
longitude: Number(longitude),
|
||||
latitude: Number(latitude),
|
||||
};
|
||||
},
|
||||
confirm() {
|
||||
if (!this.selected.longitude || !this.selected.latitude) {
|
||||
this.syncSelectedFromMarker();
|
||||
if (!this.hasCoordinateValue(this.selected.longitude) || !this.hasCoordinateValue(this.selected.latitude)) {
|
||||
this.$message.warning('请先搜索或点击地图完成选点');
|
||||
return;
|
||||
}
|
||||
@@ -333,8 +360,8 @@ export default {
|
||||
}
|
||||
this.$emit('confirm', {
|
||||
address: this.selected.address,
|
||||
longitude: this.selected.longitude,
|
||||
latitude: this.selected.latitude,
|
||||
longitude: Number(this.selected.longitude),
|
||||
latitude: Number(this.selected.latitude),
|
||||
country: this.selected.country || this.selected.countryName || '',
|
||||
province: this.selected.province || this.selected.provinceName || '',
|
||||
city: this.selected.city || this.selected.cityName || '',
|
||||
|
||||
@@ -576,7 +576,7 @@ export default {
|
||||
}
|
||||
|
||||
.mode-content :deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.mode-content :deep(.el-form-item:last-child) {
|
||||
|
||||
@@ -173,7 +173,10 @@
|
||||
}
|
||||
|
||||
.el-dialog .el-col {
|
||||
// 取消列自身下边距,改由 form-item 统一控制行距;
|
||||
// flow-root 避免子级 margin 折叠穿透导致换行后行距失效、校验提示被下一行遮挡
|
||||
margin-bottom: 0;
|
||||
display: flow-root;
|
||||
}
|
||||
|
||||
.el-dialog .el-form-item,
|
||||
@@ -181,7 +184,7 @@
|
||||
.el-dialog .el-form-item--small.el-form-item,
|
||||
.el-dialog .el-form-item--large.el-form-item,
|
||||
.el-dialog .el-form-item--medium.el-form-item {
|
||||
//margin-bottom: 20px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
/* 全站弹窗:底部操作栏浮动效果(参照 business/project-apply)
|
||||
@@ -362,9 +365,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 4) 弹窗内表单项默认上下间距 16px(覆盖默认 18px / 22px,与 customer-archive 对齐)
|
||||
// 4) 弹窗内表单项上下间距:预留绝对定位校验提示(约 14~18px)的可视空间
|
||||
.el-dialog .el-form-item {
|
||||
//margin-bottom: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
// 校验提示浮在控件下方,提高层级避免被下一行输入框背景遮挡
|
||||
.el-form-item__error {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
// 5) 通用分组白卡组件(<section-card>):标题融入卡头
|
||||
@@ -446,7 +454,7 @@
|
||||
.dialog-form--carded {
|
||||
.el-form-item {
|
||||
align-items: center;
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.el-form-item__label {
|
||||
@@ -1073,7 +1081,12 @@ td.el-table-fixed-column--right {
|
||||
align-items: normal;
|
||||
}
|
||||
.el-form-item--default {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
// 独立表单页(非弹窗)同样避免 el-col 折叠吃掉行距
|
||||
.el-form .el-col {
|
||||
display: flow-root;
|
||||
}
|
||||
|
||||
// 配套:星号必须保持「高度 auto + 继承行高」,stretch 才会按首行排布;
|
||||
|
||||
+99
-22
@@ -6,7 +6,31 @@ import 'nprogress/nprogress.css';
|
||||
|
||||
const excelPattern = /\.(xls|xlsx)$/;
|
||||
|
||||
/** 是否为浏览器 Blob(含跨 realm 的 Blob-like) */
|
||||
const isBlobLike = value =>
|
||||
value != null &&
|
||||
typeof value === 'object' &&
|
||||
typeof value.size === 'number' &&
|
||||
typeof value.type === 'string' &&
|
||||
(typeof value.text === 'function' || typeof value.arrayBuffer === 'function');
|
||||
|
||||
/** axios 拦截器已把 JSON Blob 解析成的业务对象 */
|
||||
const isBusinessJson = value =>
|
||||
value != null &&
|
||||
typeof value === 'object' &&
|
||||
!isBlobLike(value) &&
|
||||
!(value instanceof ArrayBuffer) &&
|
||||
('code' in value || 'success' in value || 'msg' in value);
|
||||
|
||||
const isExcelResponse = res => {
|
||||
// 已是业务 JSON(导入成功/失败提示)时,绝不能当失败明细 Excel 处理
|
||||
if (isBusinessJson(res?.data)) {
|
||||
return false;
|
||||
}
|
||||
// 只有文件流才可能是失败明细;普通对象没有 .text/.arrayBuffer
|
||||
if (!isBlobLike(res?.data)) {
|
||||
return false;
|
||||
}
|
||||
const headers = res.headers || {};
|
||||
const contentType = String(headers['content-type'] || res.data?.type || '').toLowerCase();
|
||||
const contentDisposition = String(headers['content-disposition'] || '').toLowerCase();
|
||||
@@ -23,8 +47,34 @@ const isExcelResponse = res => {
|
||||
);
|
||||
};
|
||||
|
||||
const parseBlobJson = async blob => {
|
||||
const text = await blob.text();
|
||||
/**
|
||||
* 解析导入接口响应体为 JSON 对象。
|
||||
* <p>
|
||||
* axios 拦截器在 Content-Type 为 JSON 时,会把 `responseType: 'blob'` 的 Blob
|
||||
* 提前解析成普通对象;此处需同时兼容 Blob / 字符串 / 已解析对象,避免再调
|
||||
* `blob.text()` 时出现「blob.text is not a function」。
|
||||
*/
|
||||
const parseBlobJson = async data => {
|
||||
if (data == null) {
|
||||
return {};
|
||||
}
|
||||
if (isBusinessJson(data)) {
|
||||
return data;
|
||||
}
|
||||
if (typeof data === 'object' && !isBlobLike(data) && !(data instanceof ArrayBuffer)) {
|
||||
return data;
|
||||
}
|
||||
if (typeof data === 'string') {
|
||||
return data ? JSON.parse(data) : {};
|
||||
}
|
||||
let text = '';
|
||||
if (typeof data.text === 'function') {
|
||||
text = await data.text();
|
||||
} else if (typeof data.arrayBuffer === 'function') {
|
||||
text = new TextDecoder().decode(await data.arrayBuffer());
|
||||
} else if (data instanceof ArrayBuffer) {
|
||||
text = new TextDecoder().decode(data);
|
||||
}
|
||||
return text ? JSON.parse(text) : {};
|
||||
};
|
||||
|
||||
@@ -39,18 +89,21 @@ const parseBlobJson = async blob => {
|
||||
* 这里补上这一步:从错误响应的 Blob 里取出后端 `msg`,取不到再退回通用文案。
|
||||
*/
|
||||
const resolveErrorMessage = async error => {
|
||||
const blob = error?.response?.data ?? error?.data;
|
||||
if (blob instanceof Blob) {
|
||||
const payload = error?.response?.data ?? error?.data;
|
||||
if (isBusinessJson(payload) && payload.msg) {
|
||||
return payload.msg;
|
||||
}
|
||||
if (isBlobLike(payload) || typeof payload === 'string') {
|
||||
try {
|
||||
const result = await parseBlobJson(blob);
|
||||
const result = await parseBlobJson(payload);
|
||||
if (result?.msg) return result.msg;
|
||||
} catch (ignored) {
|
||||
// 响应体不是 JSON(如网关返回的 HTML 错误页),退回通用文案
|
||||
}
|
||||
}
|
||||
const fallback = error?.response?.data?.msg || error?.message;
|
||||
const fallback = payload?.msg || error?.message;
|
||||
// axios 的英文通用文案对用户没有意义,统一换成中文提示
|
||||
if (!fallback || /Request failed with status code/i.test(fallback)) {
|
||||
if (!fallback || /Request failed with status code|\.text is not a function/i.test(fallback)) {
|
||||
return '导入失败,请检查导入文件后重试';
|
||||
}
|
||||
return fallback;
|
||||
@@ -68,8 +121,11 @@ const resolveErrorMessage = async error => {
|
||||
*/
|
||||
const decorateFailExcel = async (blob, businessName, failDetailDecorator) => {
|
||||
if (typeof failDetailDecorator !== 'function') return blob;
|
||||
if (!isBlobLike(blob) && !(blob instanceof ArrayBuffer)) {
|
||||
return blob;
|
||||
}
|
||||
const ExcelJS = await import('exceljs');
|
||||
const buf = await blob.arrayBuffer();
|
||||
const buf = typeof blob.arrayBuffer === 'function' ? await blob.arrayBuffer() : blob;
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
await workbook.xlsx.load(buf);
|
||||
await failDetailDecorator(workbook, { businessName });
|
||||
@@ -77,6 +133,31 @@ const decorateFailExcel = async (blob, businessName, failDetailDecorator) => {
|
||||
return new Blob([out], { type: 'application/vnd.ms-excel' });
|
||||
};
|
||||
|
||||
/** 通知上传组件成功:只传业务响应体,避免其误调 axios 响应上的 .text() */
|
||||
const notifyUploadSuccess = (option, res) => {
|
||||
if (typeof option?.onSuccess !== 'function') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const body = isBusinessJson(res?.data) ? res.data : { code: 200, success: true };
|
||||
option.onSuccess(body);
|
||||
} catch (callbackError) {
|
||||
console.warn('upload onSuccess callback failed', callbackError);
|
||||
}
|
||||
};
|
||||
|
||||
/** 通知上传组件失败 */
|
||||
const notifyUploadError = (option, error) => {
|
||||
if (typeof option?.onError !== 'function') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
option.onError(error instanceof Error ? error : new Error(String(error?.message || error || '导入失败')));
|
||||
} catch (callbackError) {
|
||||
console.warn('upload onError callback failed', callbackError);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 打开导入弹窗
|
||||
* @param {Object} vm 组件实例
|
||||
@@ -108,9 +189,7 @@ export const handleImportExcel = async (vm, option, column, businessName, onSucc
|
||||
const fileName = file && file.name ? file.name.toLowerCase() : '';
|
||||
if (!excelPattern.test(fileName)) {
|
||||
vm.$message.error('请上传 .xls,.xlsx 标准格式文件');
|
||||
if (typeof option.onError === 'function') {
|
||||
option.onError(new Error('请上传 .xls,.xlsx 标准格式文件'));
|
||||
}
|
||||
notifyUploadError(option, new Error('请上传 .xls,.xlsx 标准格式文件'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -130,12 +209,11 @@ export const handleImportExcel = async (vm, option, column, businessName, onSucc
|
||||
);
|
||||
vm.$message.warning('部分数据导入失败,已下载失败明细');
|
||||
} else {
|
||||
const result = await parseBlobJson(res.data);
|
||||
if (result.code !== 200) {
|
||||
// 成功体常被 axios 拦截器提前解析成对象;优先走业务 JSON,避免再调 Blob.text
|
||||
const result = isBusinessJson(res?.data) ? res.data : await parseBlobJson(res?.data);
|
||||
if (Number(result.code) !== 200) {
|
||||
vm.$message.error(result.msg || '导入失败');
|
||||
if (typeof option.onError === 'function') {
|
||||
option.onError(new Error(result.msg || '导入失败'));
|
||||
}
|
||||
notifyUploadError(option, new Error(result.msg || '导入失败'));
|
||||
return;
|
||||
}
|
||||
vm.$message.success('导入完成');
|
||||
@@ -149,18 +227,17 @@ export const handleImportExcel = async (vm, option, column, businessName, onSucc
|
||||
} else if (typeof vm.initTree === 'function') {
|
||||
vm.initTree();
|
||||
}
|
||||
if (typeof option.onSuccess === 'function') {
|
||||
option.onSuccess(res);
|
||||
}
|
||||
// 上传组件 onSuccess 约定接收「响应体」,不是完整 axios 响应。
|
||||
// 若传入 axios 响应对象,部分环境下会按 Fetch Response 调用 .text(),
|
||||
// 从而在导入已成功后仍弹出「e.text is not a function」。
|
||||
notifyUploadSuccess(option, res);
|
||||
} catch (error) {
|
||||
// 拦截器已提示过的错误(如后端 400 返回的业务提示)不再重复弹一次,
|
||||
// 只保留一次清晰的中文提示。
|
||||
if (!error?._notified) {
|
||||
vm.$message.error(await resolveErrorMessage(error));
|
||||
}
|
||||
if (typeof option.onError === 'function') {
|
||||
option.onError(error);
|
||||
}
|
||||
notifyUploadError(option, error);
|
||||
} finally {
|
||||
loading.close();
|
||||
NProgress.done();
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
|
||||
<script>
|
||||
import { getList, getDetail, submit, remove, changeStatus } from '@/api/base/airport-master';
|
||||
import { getLazyTree } from '@/api/base/region';
|
||||
import { getDetail as getRegionDetail, getLazyTree } from '@/api/base/region';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
@@ -322,6 +322,20 @@ export default {
|
||||
prop: 'shortName',
|
||||
minWidth: 130,
|
||||
},
|
||||
{
|
||||
label: '详细地址',
|
||||
prop: 'detailAddress',
|
||||
formslot: true,
|
||||
span: 24,
|
||||
minWidth: 220,
|
||||
overHidden: false,
|
||||
maxlength: 255,
|
||||
showWordLimit: true,
|
||||
rules: [
|
||||
{ required: true, message: '请选择详细地址', trigger: 'change' },
|
||||
{ max: 255, message: '详细地址不能超过255字', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '所属省份',
|
||||
prop: 'provinceCode',
|
||||
@@ -388,20 +402,6 @@ export default {
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '详细地址',
|
||||
prop: 'detailAddress',
|
||||
formslot: true,
|
||||
span: 24,
|
||||
minWidth: 220,
|
||||
overHidden: false,
|
||||
maxlength: 255,
|
||||
showWordLimit: true,
|
||||
rules: [
|
||||
{ required: true, message: '请选择详细地址', trigger: 'change' },
|
||||
{ max: 255, message: '详细地址不能超过255字', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '经度',
|
||||
prop: 'longitude',
|
||||
@@ -578,33 +578,51 @@ export default {
|
||||
return targetColumns.find(item => item.prop === targetProp) || null;
|
||||
},
|
||||
loadProvinceOptions() {
|
||||
getLazyTree(DEFAULT_COUNTRY_CODE).then(res => {
|
||||
return getLazyTree(DEFAULT_COUNTRY_CODE).then(res => {
|
||||
this.provinceOptions = (res.data.data || []).map(this.normalizeRegionOption);
|
||||
this.findColumn('provinceCode').dicData = this.provinceOptions;
|
||||
const provinceColumn = this.findColumn('provinceCode');
|
||||
if (provinceColumn) {
|
||||
provinceColumn.dicData = this.provinceOptions;
|
||||
}
|
||||
return this.provinceOptions;
|
||||
});
|
||||
},
|
||||
loadCityOptions(provinceCode) {
|
||||
if (!provinceCode) {
|
||||
this.cityOptions = [];
|
||||
this.findColumn('cityCode').dicData = [];
|
||||
return Promise.resolve();
|
||||
const cityColumn = this.findColumn('cityCode');
|
||||
if (cityColumn) {
|
||||
cityColumn.dicData = [];
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return getLazyTree(provinceCode).then(res => {
|
||||
this.cityOptions = (res.data.data || []).map(this.normalizeRegionOption);
|
||||
this.findColumn('cityCode').dicData = this.cityOptions;
|
||||
const cityColumn = this.findColumn('cityCode');
|
||||
if (cityColumn) {
|
||||
cityColumn.dicData = this.cityOptions;
|
||||
}
|
||||
return this.cityOptions;
|
||||
});
|
||||
},
|
||||
loadDistrictOptions(cityCode) {
|
||||
if (!cityCode) {
|
||||
this.districtOptions = [];
|
||||
this.findColumn('districtCode').dicData = [];
|
||||
return Promise.resolve();
|
||||
const districtColumn = this.findColumn('districtCode');
|
||||
if (districtColumn) {
|
||||
districtColumn.dicData = [];
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
this.districtLoading = true;
|
||||
return getLazyTree(cityCode)
|
||||
.then(res => {
|
||||
this.districtOptions = (res.data.data || []).map(this.normalizeRegionOption);
|
||||
this.findColumn('districtCode').dicData = this.districtOptions;
|
||||
const districtColumn = this.findColumn('districtCode');
|
||||
if (districtColumn) {
|
||||
districtColumn.dicData = this.districtOptions;
|
||||
}
|
||||
return this.districtOptions;
|
||||
})
|
||||
.finally(() => {
|
||||
this.districtLoading = false;
|
||||
@@ -631,6 +649,22 @@ export default {
|
||||
: String(row.districtCode),
|
||||
};
|
||||
},
|
||||
ensureCityOption(row) {
|
||||
if (!row.cityCode || !row.cityName) return;
|
||||
const exists = this.cityOptions.some(item => item.id === row.cityCode);
|
||||
if (exists) return;
|
||||
this.cityOptions = [
|
||||
...this.cityOptions,
|
||||
{
|
||||
id: row.cityCode,
|
||||
title: row.cityName,
|
||||
},
|
||||
];
|
||||
const cityColumn = this.findColumn('cityCode');
|
||||
if (cityColumn) {
|
||||
cityColumn.dicData = this.cityOptions;
|
||||
}
|
||||
},
|
||||
ensureDistrictOption(row) {
|
||||
if (!row.districtCode || !row.districtName) return;
|
||||
const exists = this.districtOptions.some(item => item.id === row.districtCode);
|
||||
@@ -642,7 +676,10 @@ export default {
|
||||
title: row.districtName,
|
||||
},
|
||||
];
|
||||
this.findColumn('districtCode').dicData = this.districtOptions;
|
||||
const districtColumn = this.findColumn('districtCode');
|
||||
if (districtColumn) {
|
||||
districtColumn.dicData = this.districtOptions;
|
||||
}
|
||||
},
|
||||
handleIataChange(value) {
|
||||
this.form.iataCode = String(value || '')
|
||||
@@ -698,25 +735,265 @@ export default {
|
||||
openAddressMapPicker() {
|
||||
this.addressMapPickerVisible = true;
|
||||
},
|
||||
formatMapCoordinate(value) {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
return '';
|
||||
}
|
||||
const number = Number(value);
|
||||
if (!Number.isFinite(number)) {
|
||||
return '';
|
||||
}
|
||||
return normalizeCoordinateInput(number.toFixed(6));
|
||||
},
|
||||
patchDialogForm(patch = {}) {
|
||||
Object.assign(this.form, patch);
|
||||
const tableForm = this.$refs.crud?.tableForm;
|
||||
if (tableForm && tableForm !== this.form) {
|
||||
Object.assign(tableForm, patch);
|
||||
}
|
||||
},
|
||||
handleAddressMapConfirm(payload) {
|
||||
const selection = typeof payload === 'string' ? { address: payload } : payload || {};
|
||||
const longitude = this.formatMapCoordinate(selection.longitude);
|
||||
const latitude = this.formatMapCoordinate(selection.latitude);
|
||||
const patch = {};
|
||||
if (selection.address) {
|
||||
this.form.detailAddress = selection.address;
|
||||
patch.detailAddress = selection.address;
|
||||
}
|
||||
if (longitude !== '' && latitude !== '') {
|
||||
patch.longitude = longitude;
|
||||
patch.latitude = latitude;
|
||||
}
|
||||
if (Object.keys(patch).length) {
|
||||
this.patchDialogForm(patch);
|
||||
}
|
||||
this.applyMapRegionSelection(selection);
|
||||
},
|
||||
normalizeAmapCityName(city, province) {
|
||||
if (Array.isArray(city)) {
|
||||
return String(province || '').trim();
|
||||
}
|
||||
const cityName = String(city || '').trim();
|
||||
return cityName || String(province || '').trim();
|
||||
},
|
||||
buildRegionLookupCodes(adcode) {
|
||||
const code = String(adcode || '').trim();
|
||||
if (!code) {
|
||||
return [];
|
||||
}
|
||||
const codes = [code];
|
||||
if (/^\d{6}$/.test(code)) {
|
||||
if (code.endsWith('00')) {
|
||||
const cityCode = code.slice(0, 4);
|
||||
if (cityCode && !codes.includes(cityCode)) {
|
||||
codes.push(cityCode);
|
||||
}
|
||||
}
|
||||
if (code.endsWith('0000')) {
|
||||
const provinceCode = code.slice(0, 2);
|
||||
if (provinceCode && !codes.includes(provinceCode)) {
|
||||
codes.push(provinceCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
},
|
||||
fetchRegionDetailByCodes(codes = []) {
|
||||
const tryNext = index => {
|
||||
if (index >= codes.length) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
return getRegionDetail(codes[index])
|
||||
.then(res => {
|
||||
const detail = res.data && res.data.data;
|
||||
if (detail && detail.code) {
|
||||
return detail;
|
||||
}
|
||||
return tryNext(index + 1);
|
||||
})
|
||||
.catch(() => tryNext(index + 1));
|
||||
};
|
||||
return tryNext(0);
|
||||
},
|
||||
resolveProvinceCode(provinceName) {
|
||||
const name = String(provinceName || '').trim();
|
||||
if (!name) {
|
||||
return '';
|
||||
}
|
||||
const province = this.provinceOptions.find(
|
||||
item => item.title === name || item.id === name || String(item.title).includes(name)
|
||||
);
|
||||
return province ? province.id : '';
|
||||
},
|
||||
resolveCityCode(cityName, regionCode) {
|
||||
const name = String(cityName || '').trim();
|
||||
const code = String(regionCode || '').trim();
|
||||
const city = this.cityOptions.find(
|
||||
item => item.title === name || item.id === code || item.id === name
|
||||
);
|
||||
return city ? city.id : '';
|
||||
},
|
||||
resolveDistrictCode(districtName, regionCode) {
|
||||
const name = String(districtName || '').trim();
|
||||
const code = String(regionCode || '').trim();
|
||||
const district = this.districtOptions.find(
|
||||
item => item.title === name || item.id === code || item.id === name
|
||||
);
|
||||
return district ? district.id : code || '';
|
||||
},
|
||||
applyRegionDetail(detail = {}) {
|
||||
const provinceName = detail.provinceName || '';
|
||||
const cityName = detail.cityName || '';
|
||||
const districtName = detail.districtName || detail.name || '';
|
||||
return this.loadProvinceOptions()
|
||||
.then(() => {
|
||||
const provinceCode =
|
||||
String(detail.provinceCode || '').trim() || this.resolveProvinceCode(provinceName);
|
||||
const province = this.provinceOptions.find(item => item.id === provinceCode);
|
||||
this.patchDialogForm({
|
||||
provinceCode: provinceCode || undefined,
|
||||
provinceName: province ? province.title : provinceName,
|
||||
});
|
||||
if (!provinceCode) {
|
||||
return null;
|
||||
}
|
||||
return this.loadCityOptions(provinceCode);
|
||||
})
|
||||
.then(cities => {
|
||||
if (!cities) {
|
||||
return null;
|
||||
}
|
||||
const cityCode =
|
||||
String(detail.cityCode || '').trim() ||
|
||||
this.resolveCityCode(cityName, detail.districtCode || detail.code);
|
||||
const city = this.cityOptions.find(item => item.id === cityCode);
|
||||
this.patchDialogForm({
|
||||
cityCode: cityCode || undefined,
|
||||
cityName: city ? city.title : cityName,
|
||||
});
|
||||
this.ensureCityOption({
|
||||
cityCode,
|
||||
cityName: city ? city.title : cityName,
|
||||
});
|
||||
if (!cityCode) {
|
||||
return null;
|
||||
}
|
||||
return this.loadDistrictOptions(cityCode);
|
||||
})
|
||||
.then(districts => {
|
||||
if (!districts) {
|
||||
return;
|
||||
}
|
||||
const districtCode = this.resolveDistrictCode(
|
||||
districtName,
|
||||
detail.districtCode || detail.code
|
||||
);
|
||||
this.patchDialogForm({
|
||||
districtCode: districtCode || undefined,
|
||||
});
|
||||
this.handleDistrictChange(districtCode);
|
||||
this.ensureDistrictOption({
|
||||
districtCode,
|
||||
districtName: this.form.districtName || districtName,
|
||||
});
|
||||
});
|
||||
},
|
||||
applyMapRegionByNames(selection = {}) {
|
||||
const provinceName = String(selection.province || selection.provinceName || '').trim();
|
||||
const cityName = this.normalizeAmapCityName(
|
||||
selection.city || selection.cityName,
|
||||
provinceName
|
||||
);
|
||||
const districtName = String(selection.district || selection.districtName || '').trim();
|
||||
const adcode = String(selection.adcode || selection.regionCode || '').trim();
|
||||
// 本页无国家字段:国内 adcode 走中国省份树;无匹配则不强制回填
|
||||
if (
|
||||
selection.longitude !== undefined &&
|
||||
selection.longitude !== null &&
|
||||
selection.longitude !== ''
|
||||
!provinceName &&
|
||||
!cityName &&
|
||||
!districtName &&
|
||||
!(/^\d{6}$/.test(adcode) || String(selection.country || selection.countryName || '').includes('中国'))
|
||||
) {
|
||||
this.form.longitude = Number(selection.longitude).toFixed(6);
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (
|
||||
selection.latitude !== undefined &&
|
||||
selection.latitude !== null &&
|
||||
selection.latitude !== ''
|
||||
) {
|
||||
this.form.latitude = Number(selection.latitude).toFixed(6);
|
||||
return this.loadProvinceOptions()
|
||||
.then(() => {
|
||||
const provinceCode = this.resolveProvinceCode(provinceName);
|
||||
const province = this.provinceOptions.find(item => item.id === provinceCode);
|
||||
this.patchDialogForm({
|
||||
provinceCode: provinceCode || undefined,
|
||||
provinceName: province ? province.title : provinceName,
|
||||
});
|
||||
if (!provinceCode) {
|
||||
return null;
|
||||
}
|
||||
return this.loadCityOptions(provinceCode);
|
||||
})
|
||||
.then(cities => {
|
||||
if (!cities) {
|
||||
return null;
|
||||
}
|
||||
const cityCode = this.resolveCityCode(cityName, adcode);
|
||||
const city = this.cityOptions.find(item => item.id === cityCode);
|
||||
this.patchDialogForm({
|
||||
cityCode: cityCode || undefined,
|
||||
cityName: city ? city.title : cityName,
|
||||
});
|
||||
this.ensureCityOption({
|
||||
cityCode,
|
||||
cityName: city ? city.title : cityName,
|
||||
});
|
||||
if (!cityCode) {
|
||||
return null;
|
||||
}
|
||||
return this.loadDistrictOptions(cityCode);
|
||||
})
|
||||
.then(districts => {
|
||||
if (!districts) {
|
||||
return;
|
||||
}
|
||||
const districtCode = this.resolveDistrictCode(districtName, adcode);
|
||||
this.patchDialogForm({
|
||||
districtCode: districtCode || undefined,
|
||||
});
|
||||
this.handleDistrictChange(districtCode);
|
||||
this.ensureDistrictOption({
|
||||
districtCode,
|
||||
districtName: this.form.districtName || districtName,
|
||||
});
|
||||
});
|
||||
},
|
||||
applyMapRegionSelection(selection = {}) {
|
||||
const adcode = String(selection.adcode || selection.regionCode || '').trim();
|
||||
const hasNameHint = Boolean(
|
||||
selection.country ||
|
||||
selection.countryName ||
|
||||
selection.province ||
|
||||
selection.provinceName ||
|
||||
selection.city ||
|
||||
selection.cityName ||
|
||||
selection.district ||
|
||||
selection.districtName
|
||||
);
|
||||
if (!adcode && !hasNameHint) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
this.regionInitializing = true;
|
||||
const lookupCodes = this.buildRegionLookupCodes(adcode);
|
||||
return this.fetchRegionDetailByCodes(lookupCodes)
|
||||
.then(detail => {
|
||||
if (detail) {
|
||||
return this.applyRegionDetail(detail);
|
||||
}
|
||||
return this.applyMapRegionByNames(selection);
|
||||
})
|
||||
.catch(() => this.applyMapRegionByNames(selection))
|
||||
.finally(() => {
|
||||
this.$nextTick(() => {
|
||||
window.setTimeout(() => {
|
||||
this.regionInitializing = false;
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
},
|
||||
normalizeRow(row) {
|
||||
row.code = row.iataCode ? `JC-${row.iataCode}` : row.code;
|
||||
|
||||
@@ -584,7 +584,7 @@ export default {
|
||||
span: 12,
|
||||
minWidth: 220,
|
||||
overHidden: false,
|
||||
order: 85,
|
||||
order: 90,
|
||||
placeholder: '点击选择地图地址',
|
||||
maxlength: 255,
|
||||
showWordLimit: true,
|
||||
@@ -1115,16 +1115,39 @@ export default {
|
||||
openAddressMapPicker() {
|
||||
this.addressMapPickerVisible = true;
|
||||
},
|
||||
formatMapCoordinate(value) {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
return '';
|
||||
}
|
||||
const number = Number(value);
|
||||
if (!Number.isFinite(number)) {
|
||||
return '';
|
||||
}
|
||||
return normalizeCoordinateInput(number.toFixed(6));
|
||||
},
|
||||
patchDialogForm(patch = {}) {
|
||||
// 同步页面 form 与 Avue 弹窗内部 tableForm,避免只改了一边导致经纬度不刷新
|
||||
Object.assign(this.form, patch);
|
||||
const tableForm = this.$refs.crud?.tableForm;
|
||||
if (tableForm && tableForm !== this.form) {
|
||||
Object.assign(tableForm, patch);
|
||||
}
|
||||
},
|
||||
handleAddressMapConfirm(payload) {
|
||||
const selection = typeof payload === 'string' ? { address: payload } : payload || {};
|
||||
const longitude = this.formatMapCoordinate(selection.longitude);
|
||||
const latitude = this.formatMapCoordinate(selection.latitude);
|
||||
const patch = {};
|
||||
if (selection.address) {
|
||||
this.form.detailAddress = selection.address;
|
||||
patch.detailAddress = selection.address;
|
||||
}
|
||||
if (selection.longitude !== undefined && selection.longitude !== null && selection.longitude !== '') {
|
||||
this.form.longitude = Number(selection.longitude).toFixed(6);
|
||||
// 换地址时必须同步覆盖经纬度,不能保留上一次选点
|
||||
if (longitude !== '' && latitude !== '') {
|
||||
patch.longitude = longitude;
|
||||
patch.latitude = latitude;
|
||||
}
|
||||
if (selection.latitude !== undefined && selection.latitude !== null && selection.latitude !== '') {
|
||||
this.form.latitude = Number(selection.latitude).toFixed(6);
|
||||
if (Object.keys(patch).length) {
|
||||
this.patchDialogForm(patch);
|
||||
}
|
||||
this.applyMapRegionSelection(selection);
|
||||
},
|
||||
@@ -1490,13 +1513,50 @@ export default {
|
||||
this.$message({ type: 'success', message: '操作成功!' });
|
||||
});
|
||||
},
|
||||
createEmptyPortTerminalForm() {
|
||||
return {
|
||||
category: '港口',
|
||||
dataSource: '手动录入',
|
||||
status: 1,
|
||||
parentId: undefined,
|
||||
parentCode: '',
|
||||
parentName: '',
|
||||
name: '',
|
||||
code: '',
|
||||
terminalCode: '',
|
||||
country: '',
|
||||
countryCode: '',
|
||||
provinceCode: undefined,
|
||||
provinceName: '',
|
||||
cityCode: undefined,
|
||||
city: '',
|
||||
districtCode: undefined,
|
||||
districtName: '',
|
||||
regionCode: '',
|
||||
detailAddress: '',
|
||||
longitude: '',
|
||||
latitude: '',
|
||||
remark: '',
|
||||
};
|
||||
},
|
||||
resetAddForm() {
|
||||
// 新增必须整表重置,避免沿用上一次编辑/查看残留
|
||||
this.form = this.createEmptyPortTerminalForm();
|
||||
this.setProvinceOptions([]);
|
||||
this.setCityOptions([]);
|
||||
this.setDistrictOptions([]);
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
if (type === 'add') {
|
||||
this.form.category = this.form.category || '港口';
|
||||
this.form.dataSource = this.form.dataSource || '手动录入';
|
||||
this.form.status = this.form.status || 1;
|
||||
this.resetAddForm();
|
||||
this.handleCategoryChange('港口', false);
|
||||
done();
|
||||
this.$nextTick(() => {
|
||||
this.$refs.crud?.clearValidate?.();
|
||||
setTimeout(() => this.disableDialogAutocomplete(), 50);
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.handleCategoryChange(this.form.category || '港口');
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
this.form = res.data.data;
|
||||
@@ -1531,35 +1591,7 @@ export default {
|
||||
setTimeout(() => this.disableDialogAutocomplete(), 50);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.resolveCountryCode(this.form.country)
|
||||
.then(countryCode => {
|
||||
this.form.countryCode = countryCode;
|
||||
this.syncCountryName(countryCode);
|
||||
return this.loadProvinceOptions(countryCode);
|
||||
})
|
||||
.then(() => {
|
||||
this.form.provinceCode =
|
||||
String(this.form.provinceCode || '') ||
|
||||
this.resolveProvinceCode(this.form.provinceName);
|
||||
return this.loadCityOptions(this.form.provinceCode);
|
||||
})
|
||||
.then(() => {
|
||||
this.form.cityCode = this.resolveCityCode(this.form.city, this.form.regionCode);
|
||||
return this.loadDistrictOptions(this.form.cityCode);
|
||||
})
|
||||
.then(() => {
|
||||
this.form.districtCode = this.resolveDistrictCode(
|
||||
this.form.districtName,
|
||||
this.form.regionCode
|
||||
);
|
||||
if (!this.form.regionCode) {
|
||||
this.handleDistrictChange(this.form.districtCode);
|
||||
}
|
||||
done();
|
||||
setTimeout(() => this.disableDialogAutocomplete(), 50);
|
||||
});
|
||||
},
|
||||
disableDialogAutocomplete() {
|
||||
this.$nextTick(() => {
|
||||
@@ -1682,14 +1714,14 @@ export default {
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
/* 港口码头编辑/新增弹窗:表单项行间距略高于全局默认 */
|
||||
/* 港口码头编辑/新增弹窗:与全局表单项行距保持一致 */
|
||||
.port-terminal-edit-dialog {
|
||||
.el-form-item,
|
||||
.el-form-item--default.el-form-item,
|
||||
.el-form-item--small.el-form-item,
|
||||
.el-form-item--large.el-form-item,
|
||||
.el-form-item--medium.el-form-item {
|
||||
margin-bottom: 22px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
|
||||
<script>
|
||||
import { getList, getDetail, submit, remove, changeStatus } from '@/api/base/railway-station';
|
||||
import { getLazyTree } from '@/api/base/region';
|
||||
import { getDetail as getRegionDetail, getLazyTree } from '@/api/base/region';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
@@ -295,6 +295,20 @@ export default {
|
||||
// prop: 'railwayLine',
|
||||
// minWidth: 130,
|
||||
// },
|
||||
{
|
||||
label: '详细地址',
|
||||
prop: 'detailAddress',
|
||||
formslot: true,
|
||||
span: 24,
|
||||
minWidth: 220,
|
||||
overHidden: false,
|
||||
maxlength: 255,
|
||||
showWordLimit: true,
|
||||
rules: [
|
||||
{ required: true, message: '请选择详细地址', trigger: 'change' },
|
||||
{ max: 255, message: '详细地址不能超过255字', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '所属省份',
|
||||
prop: 'provinceCode',
|
||||
@@ -362,20 +376,6 @@ export default {
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '详细地址',
|
||||
prop: 'detailAddress',
|
||||
formslot: true,
|
||||
span: 24,
|
||||
minWidth: 220,
|
||||
overHidden: false,
|
||||
maxlength: 255,
|
||||
showWordLimit: true,
|
||||
rules: [
|
||||
{ required: true, message: '请选择详细地址', trigger: 'change' },
|
||||
{ max: 255, message: '详细地址不能超过255字', trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '经度',
|
||||
prop: 'longitude',
|
||||
@@ -551,33 +551,51 @@ export default {
|
||||
return targetColumns.find(item => item.prop === targetProp) || null;
|
||||
},
|
||||
loadProvinceOptions() {
|
||||
getLazyTree(DEFAULT_COUNTRY_CODE).then(res => {
|
||||
return getLazyTree(DEFAULT_COUNTRY_CODE).then(res => {
|
||||
this.provinceOptions = (res.data.data || []).map(this.normalizeRegionOption);
|
||||
this.findColumn('provinceCode').dicData = this.provinceOptions;
|
||||
const provinceColumn = this.findColumn('provinceCode');
|
||||
if (provinceColumn) {
|
||||
provinceColumn.dicData = this.provinceOptions;
|
||||
}
|
||||
return this.provinceOptions;
|
||||
});
|
||||
},
|
||||
loadCityOptions(provinceCode) {
|
||||
if (!provinceCode) {
|
||||
this.cityOptions = [];
|
||||
this.findColumn('cityCode').dicData = [];
|
||||
return Promise.resolve();
|
||||
const cityColumn = this.findColumn('cityCode');
|
||||
if (cityColumn) {
|
||||
cityColumn.dicData = [];
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return getLazyTree(provinceCode).then(res => {
|
||||
this.cityOptions = (res.data.data || []).map(this.normalizeRegionOption);
|
||||
this.findColumn('cityCode').dicData = this.cityOptions;
|
||||
const cityColumn = this.findColumn('cityCode');
|
||||
if (cityColumn) {
|
||||
cityColumn.dicData = this.cityOptions;
|
||||
}
|
||||
return this.cityOptions;
|
||||
});
|
||||
},
|
||||
loadDistrictOptions(cityCode) {
|
||||
if (!cityCode) {
|
||||
this.districtOptions = [];
|
||||
this.findColumn('districtCode').dicData = [];
|
||||
return Promise.resolve();
|
||||
const districtColumn = this.findColumn('districtCode');
|
||||
if (districtColumn) {
|
||||
districtColumn.dicData = [];
|
||||
}
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
this.districtLoading = true;
|
||||
return getLazyTree(cityCode)
|
||||
.then(res => {
|
||||
this.districtOptions = (res.data.data || []).map(this.normalizeRegionOption);
|
||||
this.findColumn('districtCode').dicData = this.districtOptions;
|
||||
const districtColumn = this.findColumn('districtCode');
|
||||
if (districtColumn) {
|
||||
districtColumn.dicData = this.districtOptions;
|
||||
}
|
||||
return this.districtOptions;
|
||||
})
|
||||
.finally(() => {
|
||||
this.districtLoading = false;
|
||||
@@ -683,25 +701,265 @@ export default {
|
||||
openAddressMapPicker() {
|
||||
this.addressMapPickerVisible = true;
|
||||
},
|
||||
formatMapCoordinate(value) {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
return '';
|
||||
}
|
||||
const number = Number(value);
|
||||
if (!Number.isFinite(number)) {
|
||||
return '';
|
||||
}
|
||||
return normalizeCoordinateInput(number.toFixed(6));
|
||||
},
|
||||
patchDialogForm(patch = {}) {
|
||||
Object.assign(this.form, patch);
|
||||
const tableForm = this.$refs.crud?.tableForm;
|
||||
if (tableForm && tableForm !== this.form) {
|
||||
Object.assign(tableForm, patch);
|
||||
}
|
||||
},
|
||||
handleAddressMapConfirm(payload) {
|
||||
const selection = typeof payload === 'string' ? { address: payload } : payload || {};
|
||||
const longitude = this.formatMapCoordinate(selection.longitude);
|
||||
const latitude = this.formatMapCoordinate(selection.latitude);
|
||||
const patch = {};
|
||||
if (selection.address) {
|
||||
this.form.detailAddress = selection.address;
|
||||
patch.detailAddress = selection.address;
|
||||
}
|
||||
if (longitude !== '' && latitude !== '') {
|
||||
patch.longitude = longitude;
|
||||
patch.latitude = latitude;
|
||||
}
|
||||
if (Object.keys(patch).length) {
|
||||
this.patchDialogForm(patch);
|
||||
}
|
||||
this.applyMapRegionSelection(selection);
|
||||
},
|
||||
normalizeAmapCityName(city, province) {
|
||||
if (Array.isArray(city)) {
|
||||
return String(province || '').trim();
|
||||
}
|
||||
const cityName = String(city || '').trim();
|
||||
return cityName || String(province || '').trim();
|
||||
},
|
||||
buildRegionLookupCodes(adcode) {
|
||||
const code = String(adcode || '').trim();
|
||||
if (!code) {
|
||||
return [];
|
||||
}
|
||||
const codes = [code];
|
||||
if (/^\d{6}$/.test(code)) {
|
||||
if (code.endsWith('00')) {
|
||||
const cityCode = code.slice(0, 4);
|
||||
if (cityCode && !codes.includes(cityCode)) {
|
||||
codes.push(cityCode);
|
||||
}
|
||||
}
|
||||
if (code.endsWith('0000')) {
|
||||
const provinceCode = code.slice(0, 2);
|
||||
if (provinceCode && !codes.includes(provinceCode)) {
|
||||
codes.push(provinceCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
},
|
||||
fetchRegionDetailByCodes(codes = []) {
|
||||
const tryNext = index => {
|
||||
if (index >= codes.length) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
return getRegionDetail(codes[index])
|
||||
.then(res => {
|
||||
const detail = res.data && res.data.data;
|
||||
if (detail && detail.code) {
|
||||
return detail;
|
||||
}
|
||||
return tryNext(index + 1);
|
||||
})
|
||||
.catch(() => tryNext(index + 1));
|
||||
};
|
||||
return tryNext(0);
|
||||
},
|
||||
resolveProvinceCode(provinceName) {
|
||||
const name = String(provinceName || '').trim();
|
||||
if (!name) {
|
||||
return '';
|
||||
}
|
||||
const province = this.provinceOptions.find(
|
||||
item => item.title === name || item.id === name || String(item.title).includes(name)
|
||||
);
|
||||
return province ? province.id : '';
|
||||
},
|
||||
resolveCityCode(cityName, regionCode) {
|
||||
const name = String(cityName || '').trim();
|
||||
const code = String(regionCode || '').trim();
|
||||
const city = this.cityOptions.find(
|
||||
item => item.title === name || item.id === code || item.id === name
|
||||
);
|
||||
return city ? city.id : '';
|
||||
},
|
||||
resolveDistrictCode(districtName, regionCode) {
|
||||
const name = String(districtName || '').trim();
|
||||
const code = String(regionCode || '').trim();
|
||||
const district = this.districtOptions.find(
|
||||
item => item.title === name || item.id === code || item.id === name
|
||||
);
|
||||
return district ? district.id : code || '';
|
||||
},
|
||||
applyRegionDetail(detail = {}) {
|
||||
const provinceName = detail.provinceName || '';
|
||||
const cityName = detail.cityName || '';
|
||||
const districtName = detail.districtName || detail.name || '';
|
||||
return this.loadProvinceOptions()
|
||||
.then(() => {
|
||||
const provinceCode =
|
||||
String(detail.provinceCode || '').trim() || this.resolveProvinceCode(provinceName);
|
||||
const province = this.provinceOptions.find(item => item.id === provinceCode);
|
||||
this.patchDialogForm({
|
||||
provinceCode: provinceCode || undefined,
|
||||
provinceName: province ? province.title : provinceName,
|
||||
});
|
||||
if (!provinceCode) {
|
||||
return null;
|
||||
}
|
||||
return this.loadCityOptions(provinceCode);
|
||||
})
|
||||
.then(cities => {
|
||||
if (!cities) {
|
||||
return null;
|
||||
}
|
||||
const cityCode =
|
||||
String(detail.cityCode || '').trim() ||
|
||||
this.resolveCityCode(cityName, detail.districtCode || detail.code);
|
||||
const city = this.cityOptions.find(item => item.id === cityCode);
|
||||
this.patchDialogForm({
|
||||
cityCode: cityCode || undefined,
|
||||
cityName: city ? city.title : cityName,
|
||||
});
|
||||
this.ensureCityOption({
|
||||
cityCode,
|
||||
cityName: city ? city.title : cityName,
|
||||
});
|
||||
if (!cityCode) {
|
||||
return null;
|
||||
}
|
||||
return this.loadDistrictOptions(cityCode);
|
||||
})
|
||||
.then(districts => {
|
||||
if (!districts) {
|
||||
return;
|
||||
}
|
||||
const districtCode = this.resolveDistrictCode(
|
||||
districtName,
|
||||
detail.districtCode || detail.code
|
||||
);
|
||||
this.patchDialogForm({
|
||||
districtCode: districtCode || undefined,
|
||||
});
|
||||
this.handleDistrictChange(districtCode);
|
||||
this.ensureDistrictOption({
|
||||
districtCode,
|
||||
districtName: this.form.districtName || districtName,
|
||||
});
|
||||
});
|
||||
},
|
||||
applyMapRegionByNames(selection = {}) {
|
||||
const provinceName = String(selection.province || selection.provinceName || '').trim();
|
||||
const cityName = this.normalizeAmapCityName(
|
||||
selection.city || selection.cityName,
|
||||
provinceName
|
||||
);
|
||||
const districtName = String(selection.district || selection.districtName || '').trim();
|
||||
const adcode = String(selection.adcode || selection.regionCode || '').trim();
|
||||
// 本页无国家字段:国内 adcode 走中国省份树;无匹配则不强制回填
|
||||
if (
|
||||
selection.longitude !== undefined &&
|
||||
selection.longitude !== null &&
|
||||
selection.longitude !== ''
|
||||
!provinceName &&
|
||||
!cityName &&
|
||||
!districtName &&
|
||||
!(/^\d{6}$/.test(adcode) || String(selection.country || selection.countryName || '').includes('中国'))
|
||||
) {
|
||||
this.form.longitude = Number(selection.longitude).toFixed(6);
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (
|
||||
selection.latitude !== undefined &&
|
||||
selection.latitude !== null &&
|
||||
selection.latitude !== ''
|
||||
) {
|
||||
this.form.latitude = Number(selection.latitude).toFixed(6);
|
||||
return this.loadProvinceOptions()
|
||||
.then(() => {
|
||||
const provinceCode = this.resolveProvinceCode(provinceName);
|
||||
const province = this.provinceOptions.find(item => item.id === provinceCode);
|
||||
this.patchDialogForm({
|
||||
provinceCode: provinceCode || undefined,
|
||||
provinceName: province ? province.title : provinceName,
|
||||
});
|
||||
if (!provinceCode) {
|
||||
return null;
|
||||
}
|
||||
return this.loadCityOptions(provinceCode);
|
||||
})
|
||||
.then(cities => {
|
||||
if (!cities) {
|
||||
return null;
|
||||
}
|
||||
const cityCode = this.resolveCityCode(cityName, adcode);
|
||||
const city = this.cityOptions.find(item => item.id === cityCode);
|
||||
this.patchDialogForm({
|
||||
cityCode: cityCode || undefined,
|
||||
cityName: city ? city.title : cityName,
|
||||
});
|
||||
this.ensureCityOption({
|
||||
cityCode,
|
||||
cityName: city ? city.title : cityName,
|
||||
});
|
||||
if (!cityCode) {
|
||||
return null;
|
||||
}
|
||||
return this.loadDistrictOptions(cityCode);
|
||||
})
|
||||
.then(districts => {
|
||||
if (!districts) {
|
||||
return;
|
||||
}
|
||||
const districtCode = this.resolveDistrictCode(districtName, adcode);
|
||||
this.patchDialogForm({
|
||||
districtCode: districtCode || undefined,
|
||||
});
|
||||
this.handleDistrictChange(districtCode);
|
||||
this.ensureDistrictOption({
|
||||
districtCode,
|
||||
districtName: this.form.districtName || districtName,
|
||||
});
|
||||
});
|
||||
},
|
||||
applyMapRegionSelection(selection = {}) {
|
||||
const adcode = String(selection.adcode || selection.regionCode || '').trim();
|
||||
const hasNameHint = Boolean(
|
||||
selection.country ||
|
||||
selection.countryName ||
|
||||
selection.province ||
|
||||
selection.provinceName ||
|
||||
selection.city ||
|
||||
selection.cityName ||
|
||||
selection.district ||
|
||||
selection.districtName
|
||||
);
|
||||
if (!adcode && !hasNameHint) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
this.regionInitializing = true;
|
||||
const lookupCodes = this.buildRegionLookupCodes(adcode);
|
||||
return this.fetchRegionDetailByCodes(lookupCodes)
|
||||
.then(detail => {
|
||||
if (detail) {
|
||||
return this.applyRegionDetail(detail);
|
||||
}
|
||||
return this.applyMapRegionByNames(selection);
|
||||
})
|
||||
.catch(() => this.applyMapRegionByNames(selection))
|
||||
.finally(() => {
|
||||
this.$nextTick(() => {
|
||||
window.setTimeout(() => {
|
||||
this.regionInitializing = false;
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
},
|
||||
normalizeRow(row) {
|
||||
row.code = row.tmisCode ? `TL${row.tmisCode}` : row.code;
|
||||
|
||||
@@ -787,6 +787,6 @@ export default {
|
||||
margin-bottom: 12px !important;
|
||||
}
|
||||
.el-form-item{
|
||||
margin-bottom: 9px !important;
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -14113,7 +14113,7 @@ export default {
|
||||
|
||||
&__dispatch-shipping-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14636,7 +14636,7 @@ export default {
|
||||
width: 100%;
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.el-select),
|
||||
@@ -16253,7 +16253,7 @@ export default {
|
||||
}
|
||||
|
||||
:global(.business-crud-page__mileage-dialog .business-crud-page__mileage-form .el-form-item) {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:global(.business-crud-page__mileage-dialog .business-crud-page__mileage-form .el-input),
|
||||
|
||||
@@ -1260,7 +1260,7 @@ export default {
|
||||
.route-overview__line { flex: 0 1 56px; min-width: 24px; height: 32px; margin-top: 0; border-bottom: 6px solid #e4e7ed; }
|
||||
.segment-header { min-height: 46px; padding: 0 20px; border-bottom: 1px solid #eff1f7; font-weight: 600; em { color: #409eff; font-style: normal; } }
|
||||
.segment-content { padding: 16px 24px; }
|
||||
.dispatch-form { :deep(.el-form-item) { margin-bottom: 14px; } :deep(.el-input), :deep(.el-select), :deep(.el-date-editor), :deep(.el-input-number) { width: 100%; } :deep(.el-input-group__append .el-select) { width: auto; } }
|
||||
.dispatch-form { :deep(.el-form-item) { margin-bottom: 24px; } :deep(.el-input), :deep(.el-select), :deep(.el-date-editor), :deep(.el-input-number) { width: 100%; } :deep(.el-input-group__append .el-select) { width: auto; } }
|
||||
/* 短标签按自身宽度,避免被「预计发货日期」等长标签把左侧撑开 */
|
||||
.dispatch-form__compact-label {
|
||||
:deep(.el-form-item__label) {
|
||||
|
||||
@@ -2067,7 +2067,7 @@ export default {
|
||||
font-size: 16px;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
.master-editor__quantity-field {
|
||||
|
||||
@@ -3524,7 +3524,7 @@ export default {
|
||||
}
|
||||
.shipping-template-page__detail-form :deep(.el-form-item) {
|
||||
min-width: 0;
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.shipping-template-page__detail-form :deep(.el-form-item__label) {
|
||||
color: #909399;
|
||||
@@ -3713,7 +3713,7 @@ export default {
|
||||
}
|
||||
|
||||
:global(.shipping-template-form-page-dialog .avue-group .el-form-item) {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:global(.shipping-template-form-page-dialog .avue-form__menu) {
|
||||
|
||||
@@ -8807,7 +8807,7 @@ export default {
|
||||
|
||||
&__dispatch-shipping-form {
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9998,7 +9998,7 @@ export default {
|
||||
}
|
||||
|
||||
:global(.transport-plan-form-page-dialog .avue-group .el-form-item) {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:global(.transport-plan-form-page-dialog .avue-group .dialog-section-title) {
|
||||
|
||||
@@ -1087,19 +1087,40 @@ const transportTypeLabel = value => {
|
||||
);
|
||||
return matched?.dictValue || matched?.label || named || text || '-';
|
||||
};
|
||||
const buildBatchQueryParams = () => ({
|
||||
batchNo: query.batchNo || undefined,
|
||||
carrierId: query.carrierId || undefined,
|
||||
createUser: query.createUser || undefined,
|
||||
createTimeStart: query.createTimeRange?.[0] || undefined,
|
||||
createTimeEnd: query.createTimeRange?.[1] || undefined,
|
||||
current: page.current,
|
||||
size: page.size,
|
||||
});
|
||||
const loadListOptions = async () => {
|
||||
const res = await api.getImportOptions?.();
|
||||
const data = res?.data?.data || {};
|
||||
queryCarriers.value = data.carriers || [];
|
||||
creators.value = data.creators || [];
|
||||
};
|
||||
const loadBatches = async () => {
|
||||
const res = await api.getImportBatches({ ...query, current: page.current, size: page.size });
|
||||
const res = await api.getImportBatches(buildBatchQueryParams());
|
||||
batches.value = res.data?.data?.records || [];
|
||||
page.total = res.data?.data?.total || 0;
|
||||
};
|
||||
onMounted(() => {
|
||||
if (props.standalone) loadBatches();
|
||||
if (props.standalone) {
|
||||
loadListOptions();
|
||||
loadBatches();
|
||||
}
|
||||
if (props.createPage) openCreatePage();
|
||||
});
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
value => {
|
||||
if (value) loadBatches();
|
||||
if (value) {
|
||||
loadListOptions();
|
||||
loadBatches();
|
||||
}
|
||||
}
|
||||
);
|
||||
const resetQuery = () => {
|
||||
|
||||
@@ -12090,7 +12090,7 @@ export default {
|
||||
}
|
||||
|
||||
:global(.waybill-manage-page__mileage-dialog .waybill-manage-page__mileage-form .el-form-item) {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:global(.waybill-manage-page__mileage-dialog .waybill-manage-page__mileage-form .el-input),
|
||||
|
||||
@@ -739,7 +739,7 @@ export default {
|
||||
.contract-basic-section__date-range { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px; width: 360px; max-width: 100%; }
|
||||
.contract-basic-section__date-range span { color: #606266; }
|
||||
.contract-basic-section__date-range :deep(.el-date-editor) { width: auto; min-width: 0; }
|
||||
.contract-basic-section :deep(.el-form-item) { align-items: center; margin-bottom: 16px; }
|
||||
.contract-basic-section :deep(.el-form-item) { align-items: center; margin-bottom: 24px; }
|
||||
.contract-basic-section :deep(.el-form-item__label) { flex: 0 0 96px !important; width: 96px !important; height: auto; padding-right: 12px; white-space: normal; word-break: break-all; line-height: 18px; }
|
||||
.contract-basic-section :deep(.el-form-item__content) { min-width: 0; }
|
||||
.contract-basic-section :deep(.el-input),
|
||||
|
||||
@@ -3322,7 +3322,7 @@ export default {
|
||||
|
||||
:deep(.el-form-item) {
|
||||
align-items: center;
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
|
||||
@@ -4731,7 +4731,7 @@ export default {
|
||||
}
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
|
||||
@@ -2831,7 +2831,7 @@ export default {
|
||||
}
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
|
||||
@@ -653,7 +653,7 @@ export default {
|
||||
}
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1370,7 +1370,7 @@ load();
|
||||
display: none;
|
||||
}
|
||||
&__upload-form :deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
&__upload-tip {
|
||||
margin-left: 16px;
|
||||
|
||||
@@ -529,7 +529,7 @@ export default {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.bill-ledger-form-page__form :deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.bill-ledger-form-page__basic-grid {
|
||||
display: grid;
|
||||
|
||||
@@ -367,7 +367,7 @@ export default {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.bill-payment-form-page__form :deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.bill-payment-form-page__form :deep(.el-input),
|
||||
.bill-payment-form-page__form :deep(.el-input-number),
|
||||
|
||||
@@ -813,7 +813,7 @@ export default {
|
||||
padding-bottom: 72px;
|
||||
}
|
||||
.receipt-form-page__form :deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.receipt-form-page__form :deep(.el-select),
|
||||
.receipt-form-page__form :deep(.el-input-number) {
|
||||
|
||||
@@ -2788,7 +2788,7 @@ export default {
|
||||
display: inline-flex;
|
||||
}
|
||||
.payment-form-page :deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.payment-form-page :deep(.el-input-number .el-input__inner) {
|
||||
text-align: left;
|
||||
|
||||
@@ -2864,7 +2864,7 @@ export default {
|
||||
gap: 8px;
|
||||
}
|
||||
.formal-editor :deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.formal-editor :deep(.el-form-item__content) {
|
||||
line-height: normal;
|
||||
|
||||
@@ -2975,7 +2975,7 @@ export default {
|
||||
}
|
||||
|
||||
:deep(.pre-settlement-editor .el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.pre-settlement-editor .el-table),
|
||||
|
||||
@@ -638,7 +638,7 @@ export default {
|
||||
gap: 8px;
|
||||
}
|
||||
.settlement-adjustment-editor :deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.settlement-adjustment-editor :deep(.el-table) {
|
||||
--el-table-border-color: #eff1f7;
|
||||
|
||||
@@ -2072,7 +2072,7 @@ export default {
|
||||
display: none;
|
||||
}
|
||||
.reconciliation-editor :deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.reconciliation-editor :deep(.el-table) {
|
||||
--el-table-border-color: #eff1f7;
|
||||
|
||||
@@ -2759,7 +2759,7 @@ export default {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
|
||||
+144
-2
@@ -1091,6 +1091,136 @@ export default {
|
||||
column.addDisabled = true;
|
||||
this.$refs.crud.rowAdd();
|
||||
},
|
||||
getDeptTableRef() {
|
||||
return this.$refs.crud?.$refs?.table;
|
||||
},
|
||||
getDeptTableScrollWrap() {
|
||||
const table = this.getDeptTableRef();
|
||||
const root = table?.$el || this.$refs.crud?.$el;
|
||||
if (!root || typeof root.querySelector !== 'function') {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
root.querySelector('.el-table__body-wrapper .el-scrollbar__wrap') ||
|
||||
root.querySelector('.el-scrollbar__wrap') ||
|
||||
root.querySelector('.el-table__body-wrapper')
|
||||
);
|
||||
},
|
||||
getDeptTableScrollTop() {
|
||||
const wrap = this.getDeptTableScrollWrap();
|
||||
return wrap ? wrap.scrollTop : 0;
|
||||
},
|
||||
restoreDeptTableScroll(scrollTop) {
|
||||
const wrap = this.getDeptTableScrollWrap();
|
||||
if (!wrap) {
|
||||
return;
|
||||
}
|
||||
wrap.scrollTop = scrollTop;
|
||||
},
|
||||
findDeptRowById(list, id) {
|
||||
if (!Array.isArray(list) || id === undefined || id === null || id === '') {
|
||||
return null;
|
||||
}
|
||||
for (let index = 0; index < list.length; index += 1) {
|
||||
const item = list[index];
|
||||
if (String(item.id) === String(id)) {
|
||||
return item;
|
||||
}
|
||||
const child = this.findDeptRowById(item.children, id);
|
||||
if (child) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
syncLazyTreeAfterAdd(row, parentId) {
|
||||
const table = this.getDeptTableRef();
|
||||
if (!table || !parentId || String(parentId) === '0') {
|
||||
return;
|
||||
}
|
||||
const parentRow = this.findDeptRowById(this.data, parentId);
|
||||
if (parentRow) {
|
||||
parentRow.hasChildren = true;
|
||||
if (!Array.isArray(parentRow.children)) {
|
||||
parentRow.children = [];
|
||||
}
|
||||
if (!parentRow.children.some(item => String(item.id) === String(row.id))) {
|
||||
parentRow.children.push(row);
|
||||
}
|
||||
}
|
||||
const lazyMapRef = table.store?.states?.lazyTreeNodeMap;
|
||||
const treeDataRef = table.store?.states?.treeData;
|
||||
const lazyMap = lazyMapRef?.value ?? lazyMapRef;
|
||||
const treeData = treeDataRef?.value ?? treeDataRef;
|
||||
const mapKey =
|
||||
(lazyMap && Object.prototype.hasOwnProperty.call(lazyMap, parentId) && parentId) ||
|
||||
(lazyMap && Object.prototype.hasOwnProperty.call(lazyMap, String(parentId)) && String(parentId)) ||
|
||||
(parentRow && parentRow.id);
|
||||
if (mapKey !== undefined && mapKey !== null && lazyMap) {
|
||||
const currentChildren = Array.isArray(lazyMap[mapKey])
|
||||
? lazyMap[mapKey]
|
||||
: parentRow?.children || [];
|
||||
const nextChildren = currentChildren.some(item => String(item.id) === String(row.id))
|
||||
? [...currentChildren]
|
||||
: [...currentChildren, row];
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(lazyMap, mapKey) &&
|
||||
typeof table.updateKeyChildren === 'function'
|
||||
) {
|
||||
table.updateKeyChildren(mapKey, nextChildren);
|
||||
} else if (lazyMapRef && Object.prototype.hasOwnProperty.call(lazyMapRef, 'value')) {
|
||||
// 首次挂子节点:直接写入懒加载缓存,避免再次 treeLoad 导致滚动回顶
|
||||
lazyMapRef.value = {
|
||||
...lazyMapRef.value,
|
||||
[mapKey]: nextChildren,
|
||||
};
|
||||
} else {
|
||||
lazyMap[mapKey] = nextChildren;
|
||||
}
|
||||
}
|
||||
if (treeData && parentRow) {
|
||||
const treeKey = Object.prototype.hasOwnProperty.call(treeData, parentRow.id)
|
||||
? parentRow.id
|
||||
: Object.prototype.hasOwnProperty.call(treeData, String(parentRow.id))
|
||||
? String(parentRow.id)
|
||||
: parentRow.id;
|
||||
const nextNode = {
|
||||
...(treeData[treeKey] || {}),
|
||||
lazy: true,
|
||||
loaded: true,
|
||||
loading: false,
|
||||
expanded: true,
|
||||
hasChildren: true,
|
||||
};
|
||||
if (treeDataRef && Object.prototype.hasOwnProperty.call(treeDataRef, 'value')) {
|
||||
treeDataRef.value = {
|
||||
...treeDataRef.value,
|
||||
[treeKey]: nextNode,
|
||||
};
|
||||
} else {
|
||||
treeData[treeKey] = nextNode;
|
||||
}
|
||||
}
|
||||
if (parentRow && typeof table.toggleRowExpansion === 'function') {
|
||||
table.toggleRowExpansion(parentRow, true);
|
||||
}
|
||||
},
|
||||
scrollDeptRowIntoView(rowId) {
|
||||
if (rowId === undefined || rowId === null || rowId === '') {
|
||||
return;
|
||||
}
|
||||
const table = this.getDeptTableRef();
|
||||
const root = table?.$el || this.$refs.crud?.$el;
|
||||
if (!root || typeof root.querySelector !== 'function') {
|
||||
return;
|
||||
}
|
||||
const rowEl =
|
||||
root.querySelector(`tr[data-row-key="${rowId}"]`) ||
|
||||
root.querySelector(`tr[data-row-key='${rowId}']`);
|
||||
if (rowEl && typeof rowEl.scrollIntoView === 'function') {
|
||||
rowEl.scrollIntoView({ block: 'nearest', behavior: 'auto' });
|
||||
}
|
||||
},
|
||||
rowSave(row, done, loading) {
|
||||
row.tenantId = row.tenantId || this.userInfo.tenantId || website.tenantId;
|
||||
row.deptCode = String(row.deptCode || '').trim();
|
||||
@@ -1107,6 +1237,7 @@ export default {
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
const scrollTop = this.getDeptTableScrollTop();
|
||||
add(row).then(
|
||||
res => {
|
||||
// 获取新增数据的相关字段
|
||||
@@ -1114,12 +1245,22 @@ export default {
|
||||
row.id = data.id;
|
||||
row.deptCategoryName = data.deptCategoryName;
|
||||
row.tenantId = data.tenantId;
|
||||
if (row.hasChildren === undefined || row.hasChildren === null) {
|
||||
row.hasChildren = false;
|
||||
}
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '操作成功!',
|
||||
});
|
||||
// 数据回调进行刷新
|
||||
// 数据回调进行刷新(局部插入,避免整树重载跳回顶部)
|
||||
done(row);
|
||||
this.$nextTick(() => {
|
||||
this.syncLazyTreeAfterAdd(row, this.normalizeParentId(row.parentId));
|
||||
this.restoreDeptTableScroll(scrollTop);
|
||||
this.$nextTick(() => {
|
||||
this.scrollDeptRowIntoView(row.id);
|
||||
});
|
||||
});
|
||||
},
|
||||
error => {
|
||||
window.console.log(error);
|
||||
@@ -1265,7 +1406,8 @@ export default {
|
||||
done();
|
||||
},
|
||||
beforeClose(done) {
|
||||
this.parentId = '';
|
||||
// 保持为根级查询条件,避免关闭弹窗后若触发重载时 parentId 为空导致整树重置
|
||||
this.parentId = 0;
|
||||
this.parentDeptCode = '';
|
||||
this.parentDept = null;
|
||||
const column = this.findColumn(this.option.column, 'parentId');
|
||||
|
||||
@@ -1471,7 +1471,7 @@ export default {
|
||||
}
|
||||
|
||||
.user-edit-dialog .el-form-item {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.user-edit-dialog .el-form-item__label {
|
||||
|
||||
@@ -1934,6 +1934,6 @@ export default {
|
||||
font-weight: 600;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 14px !important;
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1406,6 +1406,6 @@ export default {
|
||||
font-weight: 600;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 14px !important;
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1607,6 +1607,6 @@ export default {
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 14px !important;
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1384,7 +1384,7 @@ export default {
|
||||
padding: 4px 0 6px;
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
@@ -1422,7 +1422,7 @@ export default {
|
||||
column-gap: 112px;
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5389,7 +5389,7 @@ export default {
|
||||
padding: 8px 36px 0;
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
@@ -5517,7 +5517,7 @@ export default {
|
||||
max-width: 620px;
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.el-input) {
|
||||
@@ -5733,6 +5733,6 @@ export default {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 14px !important;
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user