fix bug
This commit is contained in:
@@ -79,15 +79,45 @@
|
||||
{{ row.status === 1 ? '停用' : '启用' }}
|
||||
</el-button>
|
||||
</template>
|
||||
<template #districtCode-form>
|
||||
<el-select
|
||||
v-model="form.districtCode"
|
||||
clearable
|
||||
filterable
|
||||
:loading="districtLoading"
|
||||
:disabled="!form.cityCode"
|
||||
:placeholder="form.cityCode ? '请选择区县' : '请先选择城市'"
|
||||
style="width: 100%"
|
||||
@change="handleDistrictChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in districtOptions"
|
||||
:key="item.id"
|
||||
:label="item.title"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template #longitude-form>
|
||||
<el-input
|
||||
v-model="form.longitude"
|
||||
clearable
|
||||
placeholder="请输入经度"
|
||||
@input="handleCoordinateInput('longitude', $event)"
|
||||
/>
|
||||
</template>
|
||||
<template #latitude-form>
|
||||
<el-input
|
||||
v-model="form.latitude"
|
||||
clearable
|
||||
placeholder="请输入纬度"
|
||||
@input="handleCoordinateInput('latitude', $event)"
|
||||
/>
|
||||
</template>
|
||||
</avue-crud>
|
||||
|
||||
<el-dialog title="空港机场主数据导入" append-to-body v-model="excelBox" width="555px">
|
||||
<avue-form
|
||||
:option="excelOption"
|
||||
v-model="excelForm"
|
||||
:upload-before="uploadBefore"
|
||||
:upload-after="uploadAfter"
|
||||
>
|
||||
<avue-form :option="excelOption" v-model="excelForm">
|
||||
<template #excelTemplate>
|
||||
<el-button type="primary" @click="handleTemplate">
|
||||
点击下载<i class="el-icon-download el-icon--right"></i>
|
||||
@@ -104,8 +134,10 @@ import { getLazyTree } from '@/api/base/region';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { formatUpdateUserName } from '@/utils/audit';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { getCoordinateValidationMessage, normalizeCoordinateInput } from '@/utils/coordinate';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
@@ -128,19 +160,17 @@ export default {
|
||||
}
|
||||
};
|
||||
const validateLongitude = (rule, value, callback) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
callback();
|
||||
} else if (Number(value) < -180 || Number(value) > 180) {
|
||||
callback(new Error('经度范围为 -180 到 180'));
|
||||
const message = getCoordinateValidationMessage(value, 'longitude');
|
||||
if (message) {
|
||||
callback(new Error(message));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const validateLatitude = (rule, value, callback) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
callback();
|
||||
} else if (Number(value) < -90 || Number(value) > 90) {
|
||||
callback(new Error('纬度范围为 -90 到 90'));
|
||||
const message = getCoordinateValidationMessage(value, 'latitude');
|
||||
if (message) {
|
||||
callback(new Error(message));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
@@ -154,6 +184,9 @@ export default {
|
||||
excelForm: {},
|
||||
provinceOptions: [],
|
||||
cityOptions: [],
|
||||
districtOptions: [],
|
||||
districtLoading: false,
|
||||
regionInitializing: false,
|
||||
page: {
|
||||
pageSize: 10,
|
||||
pageSizes: [10, 20, 50, 100],
|
||||
@@ -165,11 +198,15 @@ export default {
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
dialogWidth: 980,
|
||||
labelPosition: 'right',
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
labelWidth: 120,
|
||||
searchLabelWidth: 120,
|
||||
searchMenuSpan: 6,
|
||||
labelWidth: 'auto',
|
||||
searchLabelWidth: 160,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
indexLabel: '序号',
|
||||
@@ -185,8 +222,8 @@ export default {
|
||||
label: '编码',
|
||||
prop: 'code',
|
||||
search: true,
|
||||
addDisabled: true,
|
||||
editDisabled: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
placeholder: '系统自动生成',
|
||||
searchPlaceholder: '请输入编码',
|
||||
},
|
||||
@@ -271,14 +308,35 @@ export default {
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '行政区划',
|
||||
prop: 'regionName',
|
||||
search: true,
|
||||
label: '所属区县',
|
||||
prop: 'districtCode',
|
||||
type: 'select',
|
||||
formslot: true,
|
||||
hide: true,
|
||||
props: {
|
||||
label: 'title',
|
||||
value: 'id',
|
||||
},
|
||||
dicData: [],
|
||||
filterable: true,
|
||||
rules: [{ required: true, message: '请选择区县', trigger: 'change' }],
|
||||
change: ({ value }) => this.handleDistrictChange(value),
|
||||
},
|
||||
{
|
||||
label: '所属区县',
|
||||
prop: 'districtName',
|
||||
minWidth: 140,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '行政区划编号',
|
||||
prop: 'regionCode',
|
||||
minWidth: 160,
|
||||
overHidden: false,
|
||||
maxlength: 128,
|
||||
showWordLimit: true,
|
||||
rules: [{ max: 128, message: '行政区划不能超过128字', trigger: 'blur' }],
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
rules: [{ max: 32, message: '行政区划编码不能超过32字', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '详细地址',
|
||||
@@ -295,20 +353,24 @@ export default {
|
||||
{
|
||||
label: '经度',
|
||||
prop: 'longitude',
|
||||
type: 'number',
|
||||
precision: 6,
|
||||
formslot: true,
|
||||
minWidth: 130,
|
||||
overHidden: false,
|
||||
rules: [{ validator: validateLongitude, trigger: 'blur' }],
|
||||
rules: [
|
||||
{ required: true, message: '请输入经度', trigger: 'blur' },
|
||||
{ validator: validateLongitude, trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '纬度',
|
||||
prop: 'latitude',
|
||||
type: 'number',
|
||||
precision: 6,
|
||||
formslot: true,
|
||||
minWidth: 130,
|
||||
overHidden: false,
|
||||
rules: [{ validator: validateLatitude, trigger: 'blur' }],
|
||||
rules: [
|
||||
{ required: true, message: '请输入纬度', trigger: 'blur' },
|
||||
{ validator: validateLatitude, trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '数据来源',
|
||||
@@ -317,6 +379,8 @@ export default {
|
||||
search: true,
|
||||
minWidth: 120,
|
||||
overHidden: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
dicData: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '初始导入', value: '初始导入' },
|
||||
@@ -333,6 +397,8 @@ export default {
|
||||
dataType: 'number',
|
||||
minWidth: 110,
|
||||
overHidden: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
dicData: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '启用', value: 1 },
|
||||
@@ -383,6 +449,7 @@ export default {
|
||||
],
|
||||
},
|
||||
excelOption: {
|
||||
labelPosition: 'right',
|
||||
submitBtn: false,
|
||||
emptyBtn: false,
|
||||
column: [
|
||||
@@ -419,7 +486,9 @@ export default {
|
||||
},
|
||||
isAdmin() {
|
||||
const authority = this.userInfo && this.userInfo.authority;
|
||||
return Array.isArray(authority) ? authority.includes('admin') : String(authority || '').includes('admin');
|
||||
return Array.isArray(authority)
|
||||
? authority.includes('admin')
|
||||
: String(authority || '').includes('admin');
|
||||
},
|
||||
ids() {
|
||||
let ids = [];
|
||||
@@ -441,7 +510,7 @@ export default {
|
||||
},
|
||||
loadProvinceOptions() {
|
||||
getLazyTree(DEFAULT_COUNTRY_CODE).then(res => {
|
||||
this.provinceOptions = res.data.data;
|
||||
this.provinceOptions = (res.data.data || []).map(this.normalizeRegionOption);
|
||||
this.findColumn('provinceCode').dicData = this.provinceOptions;
|
||||
});
|
||||
},
|
||||
@@ -452,10 +521,60 @@ export default {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return getLazyTree(provinceCode).then(res => {
|
||||
this.cityOptions = res.data.data;
|
||||
this.cityOptions = (res.data.data || []).map(this.normalizeRegionOption);
|
||||
this.findColumn('cityCode').dicData = this.cityOptions;
|
||||
});
|
||||
},
|
||||
loadDistrictOptions(cityCode) {
|
||||
if (!cityCode) {
|
||||
this.districtOptions = [];
|
||||
this.findColumn('districtCode').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;
|
||||
})
|
||||
.finally(() => {
|
||||
this.districtLoading = false;
|
||||
});
|
||||
},
|
||||
normalizeRegionOption(region) {
|
||||
return {
|
||||
...region,
|
||||
id: region.id === undefined || region.id === null ? region.id : String(region.id),
|
||||
};
|
||||
},
|
||||
normalizeRegionForm(row) {
|
||||
return {
|
||||
...row,
|
||||
provinceCode:
|
||||
row.provinceCode === undefined || row.provinceCode === null
|
||||
? row.provinceCode
|
||||
: String(row.provinceCode),
|
||||
cityCode:
|
||||
row.cityCode === undefined || row.cityCode === null ? row.cityCode : String(row.cityCode),
|
||||
districtCode:
|
||||
row.districtCode === undefined || row.districtCode === null
|
||||
? row.districtCode
|
||||
: String(row.districtCode),
|
||||
};
|
||||
},
|
||||
ensureDistrictOption(row) {
|
||||
if (!row.districtCode || !row.districtName) return;
|
||||
const exists = this.districtOptions.some(item => item.id === row.districtCode);
|
||||
if (exists) return;
|
||||
this.districtOptions = [
|
||||
...this.districtOptions,
|
||||
{
|
||||
id: row.districtCode,
|
||||
title: row.districtName,
|
||||
},
|
||||
];
|
||||
this.findColumn('districtCode').dicData = this.districtOptions;
|
||||
},
|
||||
handleIataChange(value) {
|
||||
this.form.iataCode = String(value || '')
|
||||
.toUpperCase()
|
||||
@@ -472,22 +591,67 @@ export default {
|
||||
handleProvinceChange(value) {
|
||||
const province = this.provinceOptions.find(item => item.id === value);
|
||||
this.form.provinceName = province ? province.title : '';
|
||||
if (this.regionInitializing) {
|
||||
this.loadCityOptions(value);
|
||||
return;
|
||||
}
|
||||
this.form.cityCode = undefined;
|
||||
this.form.cityName = '';
|
||||
this.form.districtCode = undefined;
|
||||
this.form.districtName = '';
|
||||
this.form.regionCode = '';
|
||||
this.form.regionName = '';
|
||||
this.loadCityOptions(value);
|
||||
this.loadDistrictOptions();
|
||||
},
|
||||
handleCityChange(value) {
|
||||
const city = this.cityOptions.find(item => item.id === value);
|
||||
this.form.cityName = city ? city.title : '';
|
||||
if (this.regionInitializing) {
|
||||
this.loadDistrictOptions(value);
|
||||
return;
|
||||
}
|
||||
this.form.districtCode = undefined;
|
||||
this.form.districtName = '';
|
||||
this.form.regionCode = '';
|
||||
this.form.regionName = '';
|
||||
this.loadDistrictOptions(value);
|
||||
},
|
||||
handleDistrictChange(value) {
|
||||
const district = this.districtOptions.find(item => item.id === value);
|
||||
this.form.districtName = district ? district.title : '';
|
||||
this.form.regionCode = value || '';
|
||||
this.form.regionName = district ? district.title : '';
|
||||
},
|
||||
handleCoordinateInput(prop, value) {
|
||||
this.form[prop] = normalizeCoordinateInput(value);
|
||||
},
|
||||
normalizeRow(row) {
|
||||
row.code = row.iataCode ? `JC-${row.iataCode}` : row.code;
|
||||
row.regionCode = String(row.regionCode || '').trim();
|
||||
row.regionName = String(row.regionName || '').trim();
|
||||
row.districtCode = String(row.districtCode || '').trim();
|
||||
row.districtName = String(row.districtName || '').trim();
|
||||
row.detailAddress = String(row.detailAddress || '').trim();
|
||||
row.longitude = normalizeCoordinateInput(row.longitude);
|
||||
row.latitude = normalizeCoordinateInput(row.latitude);
|
||||
if (!row.dataSource) row.dataSource = '手动录入';
|
||||
if (!row.status) row.status = 1;
|
||||
return row;
|
||||
},
|
||||
validateCoordinateFields(row) {
|
||||
const longitudeMessage = getCoordinateValidationMessage(row.longitude, 'longitude', true);
|
||||
if (longitudeMessage) {
|
||||
this.$message.warning(longitudeMessage);
|
||||
return false;
|
||||
}
|
||||
const latitudeMessage = getCoordinateValidationMessage(row.latitude, 'latitude', true);
|
||||
if (latitudeMessage) {
|
||||
this.$message.warning(latitudeMessage);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
validateUnique(row) {
|
||||
const rowId = String(row.id || '');
|
||||
const hasDuplicate = (params, prop) => {
|
||||
@@ -519,6 +683,10 @@ export default {
|
||||
},
|
||||
rowSave(row, done, loading) {
|
||||
const submitRow = this.normalizeRow(row);
|
||||
if (!this.validateCoordinateFields(submitRow)) {
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
this.validateUnique(submitRow)
|
||||
.then(() => submit(submitRow))
|
||||
.then(() => {
|
||||
@@ -530,6 +698,10 @@ export default {
|
||||
},
|
||||
rowUpdate(row, index, done, loading) {
|
||||
const submitRow = this.normalizeRow(row);
|
||||
if (!this.validateCoordinateFields(submitRow)) {
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
this.validateUnique(submitRow)
|
||||
.then(() => submit(submitRow))
|
||||
.then(() => {
|
||||
@@ -584,16 +756,30 @@ export default {
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
this.regionInitializing = true;
|
||||
getDetail(this.form.id).then(res => {
|
||||
this.form = res.data.data;
|
||||
this.loadCityOptions(this.form.provinceCode).then(() => done());
|
||||
const detail = this.normalizeRegionForm(res.data.data || {});
|
||||
this.loadCityOptions(detail.provinceCode)
|
||||
.then(() => this.loadDistrictOptions(detail.cityCode))
|
||||
.then(() => {
|
||||
this.ensureDistrictOption(detail);
|
||||
this.form = detail;
|
||||
done();
|
||||
this.$nextTick(() => {
|
||||
window.setTimeout(() => {
|
||||
this.regionInitializing = false;
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.form.code = '';
|
||||
this.form.dataSource = '手动录入';
|
||||
this.form.status = 1;
|
||||
this.loadCityOptions(this.form.provinceCode).then(() => done());
|
||||
this.loadCityOptions(this.form.provinceCode)
|
||||
.then(() => this.loadDistrictOptions(this.form.cityCode))
|
||||
.then(() => done());
|
||||
},
|
||||
searchReset() {
|
||||
this.query = {};
|
||||
@@ -635,23 +821,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadBefore(file, done) {
|
||||
const fileName = file && file.name ? file.name.toLowerCase() : '';
|
||||
if (!/\.(xls|xlsx)$/.test(fileName)) {
|
||||
this.$message.error('请上传 .xls,.xlsx 标准格式文件');
|
||||
return false;
|
||||
}
|
||||
if (typeof done === 'function') {
|
||||
done();
|
||||
}
|
||||
return true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '空港机场主数据');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出空港机场主数据?', '提示', {
|
||||
|
||||
705
src/views/base/cargo-type.vue
Normal file
705
src/views/base/cargo-type.vue
Normal file
@@ -0,0 +1,705 @@
|
||||
<template>
|
||||
<basic-container class="cargo-type-page">
|
||||
<avue-crud
|
||||
:option="option"
|
||||
:table-loading="loading"
|
||||
:data="data"
|
||||
v-model:page="page"
|
||||
v-model="form"
|
||||
ref="crud"
|
||||
:permission="permissionList"
|
||||
:before-open="beforeOpen"
|
||||
@row-save="rowSave"
|
||||
@row-update="rowUpdate"
|
||||
@row-del="rowDel"
|
||||
@search-change="searchChange"
|
||||
@search-reset="searchReset"
|
||||
@selection-change="selectionChange"
|
||||
@current-change="currentChange"
|
||||
@size-change="sizeChange"
|
||||
@refresh-change="refreshChange"
|
||||
@on-load="onLoad"
|
||||
>
|
||||
<template #menu-left>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-upload"
|
||||
plain
|
||||
v-if="permission.cargo_type_import"
|
||||
@click="handleImport"
|
||||
>批量导入
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-download"
|
||||
plain
|
||||
v-if="permission.cargo_type_template"
|
||||
@click="handleTemplate"
|
||||
>下载模板
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-download"
|
||||
plain
|
||||
v-if="permission.cargo_type_export"
|
||||
@click="handleExport"
|
||||
>批量导出
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
plain
|
||||
v-if="permission.cargo_type_delete"
|
||||
@click="handleDelete"
|
||||
>批量删除
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<template #parentCargoName="{ row }">
|
||||
{{ row.typeLevel === 1 ? '/' : row.parentCargoName || '/' }}
|
||||
</template>
|
||||
<template #parentCargoCode="{ row }">
|
||||
{{ row.typeLevel === 1 ? '/' : row.parentCargoCode || '/' }}
|
||||
</template>
|
||||
<template #createUserName="{ row }">
|
||||
{{ row.createUserName || row.createUser || '' }}
|
||||
</template>
|
||||
|
||||
<template #parentId-form>
|
||||
<el-select
|
||||
v-model="form.parentId"
|
||||
filterable
|
||||
remote
|
||||
clearable
|
||||
:remote-method="loadParentOptions"
|
||||
:loading="parentLoading"
|
||||
:disabled="form.typeLevel !== 2"
|
||||
placeholder="请输入名称或编码搜索"
|
||||
style="width: 100%"
|
||||
@change="handleParentChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in parentOptions"
|
||||
:key="item.id"
|
||||
:label="`${item.cargoName}(${item.cargoCode})`"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<template #menu="{ row, index }">
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
icon="el-icon-view"
|
||||
v-if="permission.cargo_type_view"
|
||||
@click="$refs.crud.rowView(row, index)"
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
icon="el-icon-edit"
|
||||
v-if="permission.cargo_type_edit"
|
||||
@click="$refs.crud.rowEdit(row, index)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
icon="el-icon-delete"
|
||||
v-if="permission.cargo_type_delete"
|
||||
@click="rowDel(row)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</avue-crud>
|
||||
|
||||
<empty-pagination
|
||||
:page="page"
|
||||
@size-change="sizeChange"
|
||||
@current-change="currentChange"
|
||||
@load="onLoad(page, query)"
|
||||
/>
|
||||
|
||||
<el-dialog title="货物类型导入" append-to-body v-model="excelBox" width="555px">
|
||||
<avue-form :option="excelOption" v-model="excelForm">
|
||||
<template #excelTemplate>
|
||||
<el-button type="primary" @click="handleTemplate">
|
||||
点击下载<i class="el-icon-download el-icon--right"></i>
|
||||
</el-button>
|
||||
</template>
|
||||
</avue-form>
|
||||
</el-dialog>
|
||||
</basic-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getDetail,
|
||||
getList,
|
||||
getNextCode,
|
||||
getParentOptions,
|
||||
remove,
|
||||
submit,
|
||||
} from '@/api/base/cargo-type';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
const typeLevelDic = [
|
||||
{ label: '一级货物类型', value: 1 },
|
||||
{ label: '二级货物类型', value: 2 },
|
||||
];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
const validateCargoName = (rule, value, callback) => {
|
||||
const cargoName = String(value || '').trim();
|
||||
if (!cargoName) {
|
||||
callback(new Error('请输入货物类型名称'));
|
||||
} else if (cargoName.length > 50) {
|
||||
callback(new Error('货物类型名称不能超过50字符'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const validateCargoCode = (rule, value, callback) => {
|
||||
const cargoCode = String(value || '').trim();
|
||||
const pattern = this.form.typeLevel === 1 ? /^\d{2}$/ : /^\d{4}$/;
|
||||
if (!pattern.test(cargoCode)) {
|
||||
callback(new Error('货物类型编码格式不正确'));
|
||||
} else if (
|
||||
this.form.typeLevel === 2 &&
|
||||
this.form.parentCargoCode &&
|
||||
!cargoCode.startsWith(this.form.parentCargoCode)
|
||||
) {
|
||||
callback(new Error('二级编码前2位必须与上级货物类型编码一致'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const validateRemark = (rule, value, callback) => {
|
||||
if (String(value || '').length > 200) {
|
||||
callback(new Error('备注不能超过200字'));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
return {
|
||||
form: {},
|
||||
query: {},
|
||||
loading: true,
|
||||
data: [],
|
||||
excelBox: false,
|
||||
excelForm: {},
|
||||
parentOptions: [],
|
||||
parentLoading: false,
|
||||
page: {
|
||||
pageSize: 10,
|
||||
pageSizes: [10, 20, 50, 100],
|
||||
currentPage: 1,
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
option: {
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
dialogWidth: 760,
|
||||
labelPosition: 'right',
|
||||
labelWidth: 'auto',
|
||||
tip: false,
|
||||
searchBtnText: '查询',
|
||||
emptyBtnText: '重置',
|
||||
saveBtnText: '提交',
|
||||
updateBtnText: '提交',
|
||||
searchShow: true,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
indexLabel: '序号',
|
||||
indexWidth: 70,
|
||||
viewBtn: false,
|
||||
delBtn: false,
|
||||
editBtn: false,
|
||||
selection: true,
|
||||
dialogClickModal: false,
|
||||
menuWidth: 220,
|
||||
column: [
|
||||
{
|
||||
label: '类型',
|
||||
prop: 'typeLevel',
|
||||
type: 'radio',
|
||||
dataType: 'number',
|
||||
dicData: typeLevelDic,
|
||||
search: true,
|
||||
value: 1,
|
||||
span: 24,
|
||||
minWidth: 120,
|
||||
rules: [{ required: true, message: '请选择货物类型级别', trigger: 'change' }],
|
||||
change: ({ value }) => this.handleTypeLevelChange(value),
|
||||
},
|
||||
{
|
||||
label: '上级货物类型',
|
||||
prop: 'parentId',
|
||||
formslot: true,
|
||||
hide: true,
|
||||
display: false,
|
||||
span: 24,
|
||||
rules: [{ required: true, message: '请选择上级货物类型', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '上级货物类型',
|
||||
prop: 'parentCargoName',
|
||||
slot: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
display: false,
|
||||
minWidth: 160,
|
||||
},
|
||||
{
|
||||
label: '上级货物类型编码',
|
||||
prop: 'parentCargoCode',
|
||||
slot: true,
|
||||
readonly: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
display: false,
|
||||
minWidth: 160,
|
||||
rules: [{ required: true, message: '请选择上级货物类型', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '货物类型',
|
||||
prop: 'cargoName',
|
||||
minWidth: 150,
|
||||
maxlength: 50,
|
||||
showWordLimit: true,
|
||||
rules: [{ validator: validateCargoName, trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '货物类型编码',
|
||||
prop: 'cargoCode',
|
||||
minWidth: 140,
|
||||
search: true,
|
||||
maxlength: 4,
|
||||
rules: [{ validator: validateCargoCode, trigger: 'blur' }],
|
||||
change: ({ value }) => this.handleCargoCodeChange(value),
|
||||
},
|
||||
{
|
||||
label: '创建人',
|
||||
prop: 'createUserName',
|
||||
slot: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
display: false,
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
type: 'textarea',
|
||||
minRows: 4,
|
||||
span: 24,
|
||||
minWidth: 180,
|
||||
maxlength: 200,
|
||||
showWordLimit: true,
|
||||
overHidden: true,
|
||||
rules: [{ validator: validateRemark, trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '更新时间',
|
||||
prop: 'updateTime',
|
||||
type: 'datetime',
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
display: false,
|
||||
minWidth: 160,
|
||||
},
|
||||
{
|
||||
label: '创建时间',
|
||||
prop: 'createTime',
|
||||
type: 'datetime',
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
display: false,
|
||||
minWidth: 160,
|
||||
},
|
||||
],
|
||||
},
|
||||
excelOption: {
|
||||
submitBtn: false,
|
||||
emptyBtn: false,
|
||||
column: [
|
||||
{
|
||||
label: '模板上传',
|
||||
prop: 'excelFile',
|
||||
type: 'upload',
|
||||
drag: true,
|
||||
loadText: '模板上传中,请稍等',
|
||||
span: 24,
|
||||
propsHttp: {
|
||||
res: 'data',
|
||||
},
|
||||
headers: {
|
||||
'Blade-Auth': `bearer ${getToken()}`,
|
||||
},
|
||||
tip: '请上传 .xls,.xlsx 标准格式文件',
|
||||
action: '/blade-system/cargo-type/import-cargo-type',
|
||||
},
|
||||
{
|
||||
label: '模板下载',
|
||||
prop: 'excelTemplate',
|
||||
formslot: true,
|
||||
span: 24,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permission']),
|
||||
permissionList() {
|
||||
return {
|
||||
addBtn: this.validData(this.permission.cargo_type_add, false),
|
||||
};
|
||||
},
|
||||
ids() {
|
||||
return this.selectionList.map(ele => ele.id).join(',');
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
findCargoColumn(prop) {
|
||||
return this.option.column.find(item => item.prop === prop) || {};
|
||||
},
|
||||
syncColumnDisplay() {
|
||||
const isChild = this.form.typeLevel === 2;
|
||||
this.findCargoColumn('parentId').display = isChild;
|
||||
this.findCargoColumn('parentCargoCode').display = isChild;
|
||||
this.findCargoColumn('parentCargoCode').addDisplay = isChild;
|
||||
this.findCargoColumn('parentCargoCode').editDisplay = isChild;
|
||||
},
|
||||
handleTypeLevelChange(value) {
|
||||
this.form.typeLevel = value;
|
||||
if (value === 1) {
|
||||
this.form.parentId = undefined;
|
||||
this.form.parentCargoName = '';
|
||||
this.form.parentCargoCode = '';
|
||||
this.form.cargoCode = String(this.form.cargoCode || '')
|
||||
.replace(/\D/g, '')
|
||||
.slice(0, 2);
|
||||
} else {
|
||||
this.form.cargoCode = String(this.form.cargoCode || '')
|
||||
.replace(/\D/g, '')
|
||||
.slice(0, 4);
|
||||
}
|
||||
this.syncColumnDisplay();
|
||||
},
|
||||
handleCargoCodeChange(value) {
|
||||
const maxLength = this.form.typeLevel === 1 ? 2 : 4;
|
||||
this.form.cargoCode = String(value || '')
|
||||
.replace(/\D/g, '')
|
||||
.slice(0, maxLength);
|
||||
},
|
||||
loadParentOptions(keyword = '') {
|
||||
this.parentLoading = true;
|
||||
return getParentOptions(keyword)
|
||||
.then(res => {
|
||||
this.parentOptions = res.data.data || [];
|
||||
})
|
||||
.finally(() => {
|
||||
this.parentLoading = false;
|
||||
});
|
||||
},
|
||||
ensureParentOption(row) {
|
||||
if (!row.parentId || !row.parentCargoName) return;
|
||||
const exists = this.parentOptions.some(item => String(item.id) === String(row.parentId));
|
||||
if (exists) return;
|
||||
this.parentOptions = [
|
||||
...this.parentOptions,
|
||||
{
|
||||
id: row.parentId,
|
||||
cargoName: row.parentCargoName,
|
||||
cargoCode: row.parentCargoCode,
|
||||
},
|
||||
];
|
||||
},
|
||||
handleParentChange(value) {
|
||||
const parent = this.parentOptions.find(item => String(item.id) === String(value));
|
||||
this.form.parentCargoName = parent ? parent.cargoName : '';
|
||||
this.form.parentCargoCode = parent ? parent.cargoCode : '';
|
||||
if (!parent) {
|
||||
this.form.cargoCode = '';
|
||||
return;
|
||||
}
|
||||
getNextCode(parent.cargoCode).then(res => {
|
||||
this.form.cargoCode = res.data.data;
|
||||
});
|
||||
},
|
||||
normalizeRow(row) {
|
||||
row.typeLevel = Number(row.typeLevel || 1);
|
||||
row.cargoName = String(row.cargoName || '').trim();
|
||||
row.cargoCode = String(row.cargoCode || '').trim();
|
||||
row.remark = String(row.remark || '').trim();
|
||||
if (row.typeLevel === 1) {
|
||||
row.parentId = undefined;
|
||||
row.parentCargoName = '';
|
||||
row.parentCargoCode = '';
|
||||
}
|
||||
return row;
|
||||
},
|
||||
validateRow(row) {
|
||||
if (![1, 2].includes(row.typeLevel)) {
|
||||
this.$message.warning('请选择货物类型级别');
|
||||
return false;
|
||||
}
|
||||
if (row.typeLevel === 2 && !row.parentId) {
|
||||
this.$message.warning('请选择上级货物类型');
|
||||
return false;
|
||||
}
|
||||
if (!row.cargoName) {
|
||||
this.$message.warning('请输入货物类型名称');
|
||||
return false;
|
||||
}
|
||||
if (row.cargoName.length > 50) {
|
||||
this.$message.warning('货物类型名称不能超过50字符');
|
||||
return false;
|
||||
}
|
||||
const pattern = row.typeLevel === 1 ? /^\d{2}$/ : /^\d{4}$/;
|
||||
if (!pattern.test(row.cargoCode)) {
|
||||
this.$message.warning('货物类型编码格式不正确');
|
||||
return false;
|
||||
}
|
||||
if (row.typeLevel === 2 && !row.cargoCode.startsWith(row.parentCargoCode)) {
|
||||
this.$message.warning('二级编码前2位必须与上级货物类型编码一致');
|
||||
return false;
|
||||
}
|
||||
if (row.remark.length > 200) {
|
||||
this.$message.warning('备注不能超过200字');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
rowSave(row, done, loading) {
|
||||
const submitRow = this.normalizeRow(row);
|
||||
if (!this.validateRow(submitRow)) {
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
submit(submitRow).then(
|
||||
() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message({ type: 'success', message: '操作成功!' });
|
||||
done();
|
||||
},
|
||||
error => {
|
||||
window.console.log(error);
|
||||
loading();
|
||||
}
|
||||
);
|
||||
},
|
||||
rowUpdate(row, index, done, loading) {
|
||||
const submitRow = this.normalizeRow(row);
|
||||
if (!this.validateRow(submitRow)) {
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
submit(submitRow).then(
|
||||
() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message({ type: 'success', message: '操作成功!' });
|
||||
done();
|
||||
},
|
||||
error => {
|
||||
window.console.log(error);
|
||||
loading();
|
||||
}
|
||||
);
|
||||
},
|
||||
rowDel(row) {
|
||||
this.$confirm('确定要删除该货物类型吗?删除后不可恢复。', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => remove(row.id))
|
||||
.then(() => {
|
||||
this.afterDelete(1);
|
||||
this.$message({ type: 'success', message: '操作成功!' });
|
||||
});
|
||||
},
|
||||
handleDelete() {
|
||||
if (this.selectionList.length === 0) {
|
||||
this.$message.warning('请选择至少一条数据');
|
||||
return;
|
||||
}
|
||||
this.$confirm('确定删除所选数据,删除后不可恢复?', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => remove(this.ids))
|
||||
.then(() => {
|
||||
this.afterDelete(this.selectionList.length);
|
||||
this.$message({ type: 'success', message: '操作成功!' });
|
||||
this.$refs.crud.toggleSelection();
|
||||
});
|
||||
},
|
||||
afterDelete(deleteCount) {
|
||||
if (this.page.currentPage > 1 && this.data.length <= deleteCount) {
|
||||
this.page.currentPage -= 1;
|
||||
}
|
||||
this.onLoad(this.page, this.query);
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
this.form = res.data.data || {};
|
||||
this.ensureParentOption(this.form);
|
||||
this.syncColumnDisplay();
|
||||
done();
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.form = {
|
||||
typeLevel: 1,
|
||||
cargoName: '',
|
||||
cargoCode: '',
|
||||
parentId: undefined,
|
||||
parentCargoName: '',
|
||||
parentCargoCode: '',
|
||||
remark: '',
|
||||
};
|
||||
this.syncColumnDisplay();
|
||||
done();
|
||||
},
|
||||
searchReset() {
|
||||
this.query = {};
|
||||
this.page.currentPage = 1;
|
||||
this.onLoad(this.page);
|
||||
},
|
||||
searchChange(params, done) {
|
||||
this.query = params;
|
||||
this.page.currentPage = 1;
|
||||
this.onLoad(this.page, params);
|
||||
done();
|
||||
},
|
||||
selectionChange(list) {
|
||||
this.selectionList = list;
|
||||
},
|
||||
selectionClear() {
|
||||
this.selectionList = [];
|
||||
this.$refs.crud.toggleSelection();
|
||||
},
|
||||
currentChange(currentPage) {
|
||||
this.page.currentPage = currentPage;
|
||||
},
|
||||
sizeChange(pageSize) {
|
||||
this.page.pageSize = pageSize;
|
||||
},
|
||||
refreshChange() {
|
||||
this.onLoad(this.page, this.query);
|
||||
},
|
||||
onLoad(page, params = {}) {
|
||||
this.loading = true;
|
||||
getList(page.currentPage, page.pageSize, { ...params, ...this.query })
|
||||
.then(res => {
|
||||
const data = res.data.data;
|
||||
this.page.total = data.total;
|
||||
this.data = data.records || [];
|
||||
this.selectionClear();
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
openImportDialog(this, '货物类型');
|
||||
},
|
||||
buildExportParams() {
|
||||
const params = { ...this.query };
|
||||
if (this.ids) {
|
||||
params.ids = this.ids;
|
||||
}
|
||||
return params;
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出货物类型数据?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-system/cargo-type/export-cargo-type', this.buildExportParams())
|
||||
.then(res => {
|
||||
downloadXls(res.data, `货物类型${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
.finally(() => {
|
||||
NProgress.done();
|
||||
});
|
||||
});
|
||||
},
|
||||
handleTemplate() {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-system/cargo-type/export-template', {})
|
||||
.then(res => {
|
||||
downloadXls(res.data, '货物类型导入模板.xlsx');
|
||||
})
|
||||
.finally(() => {
|
||||
NProgress.done();
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.cargo-type-page {
|
||||
:deep(.avue-crud__header) {
|
||||
margin-top: 12px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
:deep(.el-card) {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
:deep(.avue-crud__search) {
|
||||
padding: 12px 12px 4px;
|
||||
margin-bottom: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
:deep(.avue-crud__search .el-form-item__label) {
|
||||
min-width: 160px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:deep(.el-table) {
|
||||
--el-table-border-color: #eff1f7;
|
||||
--el-table-row-hover-bg-color: #f5f7fa;
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:nth-child(even) > td.el-table__cell) {
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:nth-child(even) > td.el-table-fixed-column--left),
|
||||
:deep(.el-table__body tr:nth-child(even) > td.el-table-fixed-column--right) {
|
||||
background: #fafafa;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -133,6 +133,26 @@
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #longitude-form>
|
||||
<el-input
|
||||
v-model="form.longitude"
|
||||
clearable
|
||||
placeholder="请输入经度"
|
||||
:disabled="dialogReadonly || form.addressType !== '常规地址'"
|
||||
@input="handleCoordinateInput('longitude', $event)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #latitude-form>
|
||||
<el-input
|
||||
v-model="form.latitude"
|
||||
clearable
|
||||
placeholder="请输入纬度"
|
||||
:disabled="dialogReadonly || form.addressType !== '常规地址'"
|
||||
@input="handleCoordinateInput('latitude', $event)"
|
||||
/>
|
||||
</template>
|
||||
</avue-crud>
|
||||
|
||||
<el-dialog
|
||||
@@ -179,6 +199,7 @@ import { createOption } from '@/option/base/common-address';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { isCoordinateInput, normalizeCoordinateInput } from '@/utils/coordinate';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
@@ -190,6 +211,8 @@ export default {
|
||||
const validateLongitude = (rule, value, callback) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
callback(new Error('经度不能为空'));
|
||||
} else if (!isCoordinateInput(value)) {
|
||||
callback(new Error('经度最多保留6位小数'));
|
||||
} else if (Number(value) < -180 || Number(value) > 180) {
|
||||
callback(new Error('经度范围为 -180 到 180'));
|
||||
} else {
|
||||
@@ -199,6 +222,8 @@ export default {
|
||||
const validateLatitude = (rule, value, callback) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
callback(new Error('纬度不能为空'));
|
||||
} else if (!isCoordinateInput(value)) {
|
||||
callback(new Error('纬度最多保留6位小数'));
|
||||
} else if (Number(value) < -90 || Number(value) > 90) {
|
||||
callback(new Error('纬度范围为 -90 到 90'));
|
||||
} else {
|
||||
@@ -319,6 +344,9 @@ export default {
|
||||
this.form.longitude = source.longitude;
|
||||
this.form.latitude = source.latitude;
|
||||
},
|
||||
handleCoordinateInput(prop, value) {
|
||||
this.form[prop] = normalizeCoordinateInput(value);
|
||||
},
|
||||
clearTypeRelatedFields(siteCode = '') {
|
||||
this.form.sourceId = undefined;
|
||||
this.form.siteCode = siteCode;
|
||||
@@ -356,6 +384,8 @@ export default {
|
||||
detailAddress: String(row.detailAddress || '').trim(),
|
||||
regionCode: String(row.regionCode || '').trim(),
|
||||
regionName: String(row.regionName || '').trim(),
|
||||
longitude: normalizeCoordinateInput(row.longitude),
|
||||
latitude: normalizeCoordinateInput(row.latitude),
|
||||
contactName: String(row.contactName || '').trim(),
|
||||
contactPhone: String(row.contactPhone || '').trim(),
|
||||
remark: String(row.remark || '').trim(),
|
||||
@@ -400,6 +430,10 @@ export default {
|
||||
return false;
|
||||
}
|
||||
if (row.longitude !== undefined && row.longitude !== null && row.longitude !== '') {
|
||||
if (!isCoordinateInput(row.longitude)) {
|
||||
this.$message.warning('经度最多保留6位小数');
|
||||
return false;
|
||||
}
|
||||
if (Number(row.longitude) < -180 || Number(row.longitude) > 180) {
|
||||
this.$message.warning('经度范围为 -180 到 180');
|
||||
return false;
|
||||
@@ -407,6 +441,10 @@ export default {
|
||||
row.longitude = Number(row.longitude).toFixed(6);
|
||||
}
|
||||
if (row.latitude !== undefined && row.latitude !== null && row.latitude !== '') {
|
||||
if (!isCoordinateInput(row.latitude)) {
|
||||
this.$message.warning('纬度最多保留6位小数');
|
||||
return false;
|
||||
}
|
||||
if (Number(row.latitude) < -90 || Number(row.latitude) > 90) {
|
||||
this.$message.warning('纬度范围为 -90 到 90');
|
||||
return false;
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
</avue-crud>
|
||||
|
||||
<el-dialog title="币种汇率导入" append-to-body v-model="excelBox" width="555px">
|
||||
<avue-form :option="excelOption" v-model="excelForm" :upload-after="uploadAfter">
|
||||
<avue-form :option="excelOption" v-model="excelForm">
|
||||
<template #excelTemplate>
|
||||
<el-button type="primary" @click="handleTemplate">
|
||||
点击下载<i class="el-icon-download el-icon--right"></i>
|
||||
@@ -106,6 +106,8 @@ import { changeStatus, getDetail, getList, submit } from '@/api/base/currency';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { formatUpdateUserName } from '@/utils/audit';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
@@ -131,7 +133,7 @@ export default {
|
||||
};
|
||||
const validateExchangeRate = (rule, value, callback) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
callback(new Error('请输入汇率'));
|
||||
callback();
|
||||
} else if (Number(value) <= 0) {
|
||||
callback(new Error('汇率必须大于0'));
|
||||
} else if (!/^\d+(\.\d{1,6})?$/.test(String(value))) {
|
||||
@@ -157,10 +159,13 @@ export default {
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
dialogWidth: 860,
|
||||
labelPosition: 'top',
|
||||
labelPosition: 'right',
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
indexLabel: '序号',
|
||||
@@ -195,7 +200,6 @@ export default {
|
||||
label: '汇率',
|
||||
prop: 'exchangeRate',
|
||||
type: 'number',
|
||||
search: true,
|
||||
minWidth: 120,
|
||||
precision: 6,
|
||||
rules: [{ validator: validateExchangeRate, trigger: 'blur' }],
|
||||
@@ -216,7 +220,6 @@ export default {
|
||||
format: 'YYYY-MM-DD',
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
searchRange: true,
|
||||
search: true,
|
||||
hide: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
@@ -239,7 +242,6 @@ export default {
|
||||
format: 'YYYY-MM-DD',
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
searchRange: true,
|
||||
search: true,
|
||||
hide: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
@@ -278,6 +280,14 @@ export default {
|
||||
showWordLimit: true,
|
||||
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '更新人',
|
||||
prop: 'updateUserName',
|
||||
formatter: formatUpdateUserName,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
minWidth: 120,
|
||||
},
|
||||
{
|
||||
label: '更新时间',
|
||||
prop: 'updateTime',
|
||||
@@ -296,7 +306,6 @@ export default {
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
searchRange: true,
|
||||
search: true,
|
||||
hide: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
@@ -344,7 +353,10 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
handleCodeChange(value) {
|
||||
this.form.code = String(value || '').toUpperCase().replace(/[^A-Z]/g, '').slice(0, 3);
|
||||
this.form.code = String(value || '')
|
||||
.toUpperCase()
|
||||
.replace(/[^A-Z]/g, '')
|
||||
.slice(0, 3);
|
||||
const matched = this.data.find(item => item.code === this.form.code);
|
||||
if (matched) {
|
||||
this.form.name = matched.name;
|
||||
@@ -375,6 +387,7 @@ export default {
|
||||
normalizeRow(row) {
|
||||
const values = { ...row };
|
||||
values.code = String(values.code || '').toUpperCase();
|
||||
values.exchangeRate = values.exchangeRate === '' ? null : values.exchangeRate;
|
||||
values.dataSource = values.dataSource || '手工录入';
|
||||
values.status = values.status || 1;
|
||||
return values;
|
||||
@@ -384,11 +397,21 @@ export default {
|
||||
this.$message.warning('备注不能超过 200 字');
|
||||
return false;
|
||||
}
|
||||
if (Number(row.exchangeRate) <= 0) {
|
||||
if (
|
||||
row.exchangeRate !== undefined &&
|
||||
row.exchangeRate !== null &&
|
||||
row.exchangeRate !== '' &&
|
||||
Number(row.exchangeRate) <= 0
|
||||
) {
|
||||
this.$message.warning('汇率必须大于0');
|
||||
return false;
|
||||
}
|
||||
if (!/^\d+(\.\d{1,6})?$/.test(String(row.exchangeRate))) {
|
||||
if (
|
||||
row.exchangeRate !== undefined &&
|
||||
row.exchangeRate !== null &&
|
||||
row.exchangeRate !== '' &&
|
||||
!/^\d+(\.\d{1,6})?$/.test(String(row.exchangeRate))
|
||||
) {
|
||||
this.$message.warning('汇率最多保留6位小数');
|
||||
return false;
|
||||
}
|
||||
@@ -519,12 +542,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '币种汇率');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出币种汇率数据?', '提示', {
|
||||
@@ -550,7 +568,9 @@ export default {
|
||||
};
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(`/blade-system/currency/export-template?${this.website.tokenHeader}=${getToken()}`).then(res => {
|
||||
exportBlob(
|
||||
`/blade-system/currency/export-template?${this.website.tokenHeader}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '币种汇率模板.xlsx');
|
||||
});
|
||||
},
|
||||
|
||||
@@ -93,7 +93,10 @@ export default {
|
||||
saveBtnText: '提交',
|
||||
updateBtnText: '提交',
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
indexLabel: '序号',
|
||||
|
||||
@@ -80,9 +80,13 @@ export default {
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
dialogWidth: 680,
|
||||
labelPosition: 'right',
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
indexLabel: '序号',
|
||||
@@ -94,15 +98,29 @@ export default {
|
||||
menuWidth: 160,
|
||||
column: [
|
||||
{
|
||||
label: '中文名称',
|
||||
label: '费用类型',
|
||||
prop: 'feeCategory',
|
||||
type: 'select',
|
||||
search: true,
|
||||
filterable: true,
|
||||
dicUrl: '/blade-system/dict/dictionary?code=fee_category',
|
||||
props: {
|
||||
label: 'dictValue',
|
||||
value: 'dictKey',
|
||||
},
|
||||
minWidth: 120,
|
||||
rules: [{ required: true, message: '请选择费用类型', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '费用项',
|
||||
prop: 'name',
|
||||
minWidth: 140,
|
||||
search: true,
|
||||
maxlength: 50,
|
||||
rules: [{ required: true, message: '请输入中文名称', trigger: 'blur' }],
|
||||
rules: [{ required: true, message: '请输入费用项', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '英文名称',
|
||||
label: '费用项代码',
|
||||
prop: 'englishName',
|
||||
minWidth: 160,
|
||||
search: true,
|
||||
@@ -119,6 +137,8 @@ export default {
|
||||
{ label: '启用', value: 1 },
|
||||
{ label: '停用', value: 2 },
|
||||
],
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
@@ -164,6 +184,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
normalizeRow(row) {
|
||||
row.feeCategory = String(row.feeCategory || '').trim();
|
||||
row.name = String(row.name || '').trim();
|
||||
row.englishName = String(row.englishName || '').trim();
|
||||
if (!row.status) row.status = 1;
|
||||
|
||||
@@ -60,6 +60,9 @@
|
||||
<template #parentCode="{ row }">
|
||||
<span>{{ row.category === '港口' ? '-' : row.parentCode }}</span>
|
||||
</template>
|
||||
<template #name-header>
|
||||
<span>港口/码头</span>
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<el-tag :type="row.status === 1 ? 'primary' : 'info'">
|
||||
{{ row.status === 1 ? '启用' : '停用' }}
|
||||
@@ -71,7 +74,7 @@
|
||||
clearable
|
||||
filterable
|
||||
:disabled="isParentRegionLocked"
|
||||
placeholder="请选择国家"
|
||||
:placeholder="isParentRegionLocked ? '自动带出' : '请选择国家'"
|
||||
style="width: 100%"
|
||||
@change="handleCountryChange"
|
||||
>
|
||||
@@ -83,6 +86,32 @@
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template #category-form>
|
||||
<el-radio-group v-model="form.category" @change="handleCategoryChange">
|
||||
<el-radio label="港口">港口</el-radio>
|
||||
<el-radio label="码头">码头</el-radio>
|
||||
</el-radio-group>
|
||||
</template>
|
||||
<template #code-form>
|
||||
<el-input
|
||||
v-if="form.category !== '码头'"
|
||||
v-model="form.code"
|
||||
clearable
|
||||
maxlength="5"
|
||||
placeholder="请输入5位大写字母"
|
||||
@input="handleCodeChange"
|
||||
@blur="handleCodeChange(form.code)"
|
||||
/>
|
||||
<div v-else>
|
||||
<el-input
|
||||
v-model="form.terminalCode"
|
||||
clearable
|
||||
maxlength="24"
|
||||
placeholder="请输入码头标识"
|
||||
@input="handleTerminalCodeChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #menu="{ row, index }">
|
||||
<el-button
|
||||
type="primary"
|
||||
@@ -103,27 +132,72 @@
|
||||
{{ row.status === 1 ? '停用' : '启用' }}
|
||||
</el-button>
|
||||
</template>
|
||||
<template #regionCode-form>
|
||||
<el-cascader
|
||||
:key="regionCascaderKey"
|
||||
v-model="form.regionCode"
|
||||
:props="regionProps"
|
||||
<template #cityCode-form>
|
||||
<el-select
|
||||
v-model="form.cityCode"
|
||||
clearable
|
||||
filterable
|
||||
:disabled="isRegionDisabled"
|
||||
:loading="cityLoading"
|
||||
:disabled="isCityDisabled"
|
||||
:placeholder="isParentRegionLocked ? '自动带出' : '请先选择国家'"
|
||||
style="width: 100%"
|
||||
@change="handleRegionChange"
|
||||
@change="handleCityChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in cityOptions"
|
||||
:key="item.id"
|
||||
:label="item.title"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template #districtCode-form>
|
||||
<el-select
|
||||
v-model="form.districtCode"
|
||||
clearable
|
||||
filterable
|
||||
:loading="districtLoading"
|
||||
:disabled="isDistrictDisabled"
|
||||
:placeholder="
|
||||
isParentRegionLocked ? '自动带出' : form.cityCode ? '请选择区县' : '请先选择城市'
|
||||
"
|
||||
style="width: 100%"
|
||||
@change="handleDistrictChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in districtOptions"
|
||||
:key="item.id"
|
||||
:label="item.title"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template #longitude-form>
|
||||
<el-input
|
||||
v-model="form.longitude"
|
||||
clearable
|
||||
placeholder="请输入经度"
|
||||
@input="handleCoordinateInput('longitude', $event)"
|
||||
/>
|
||||
</template>
|
||||
<template #latitude-form>
|
||||
<el-input
|
||||
v-model="form.latitude"
|
||||
clearable
|
||||
placeholder="请输入纬度"
|
||||
@input="handleCoordinateInput('latitude', $event)"
|
||||
/>
|
||||
</template>
|
||||
</avue-crud>
|
||||
<empty-pagination
|
||||
:page="page"
|
||||
@size-change="sizeChange"
|
||||
@current-change="currentChange"
|
||||
@load="onLoad(page, query)"
|
||||
/>
|
||||
|
||||
<el-dialog title="港口码头主数据导入" append-to-body v-model="excelBox" width="555px">
|
||||
<avue-form
|
||||
:option="excelOption"
|
||||
v-model="excelForm"
|
||||
:upload-before="uploadBefore"
|
||||
:upload-after="uploadAfter"
|
||||
>
|
||||
<avue-form :option="excelOption" v-model="excelForm">
|
||||
<template #excelTemplate>
|
||||
<el-button type="primary" @click="handleTemplate">
|
||||
点击下载<i class="el-icon-download el-icon--right"></i>
|
||||
@@ -147,8 +221,10 @@ import { getLazyTree } from '@/api/base/region';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { formatUpdateUserName } from '@/utils/audit';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { getCoordinateValidationMessage, normalizeCoordinateInput } from '@/utils/coordinate';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
@@ -179,19 +255,17 @@ export default {
|
||||
callback();
|
||||
};
|
||||
const validateLongitude = (rule, value, callback) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
callback();
|
||||
} else if (Number(value) < -180 || Number(value) > 180) {
|
||||
callback(new Error('经度范围为 -180 到 180'));
|
||||
const message = getCoordinateValidationMessage(value, 'longitude');
|
||||
if (message) {
|
||||
callback(new Error(message));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const validateLatitude = (rule, value, callback) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
callback();
|
||||
} else if (Number(value) < -90 || Number(value) > 90) {
|
||||
callback(new Error('纬度范围为 -90 到 90'));
|
||||
const message = getCoordinateValidationMessage(value, 'latitude');
|
||||
if (message) {
|
||||
callback(new Error(message));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
@@ -205,17 +279,12 @@ export default {
|
||||
excelForm: {},
|
||||
portOptions: [],
|
||||
countryOptions: [],
|
||||
regionCascaderKey: 0,
|
||||
regionNodeMap: {},
|
||||
regionNameMap: {},
|
||||
regionProps: {
|
||||
lazy: true,
|
||||
lazyLoad: this.loadRegionNode,
|
||||
label: 'title',
|
||||
value: 'id',
|
||||
checkStrictly: false,
|
||||
emitPath: true,
|
||||
},
|
||||
cityOptions: [],
|
||||
cityLoading: false,
|
||||
cityOptionCache: {},
|
||||
districtOptions: [],
|
||||
districtLoading: false,
|
||||
districtOptionCache: {},
|
||||
page: {
|
||||
pageSize: 10,
|
||||
pageSizes: [10, 20, 50, 100],
|
||||
@@ -227,10 +296,15 @@ export default {
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
dialogWidth: 980,
|
||||
labelPosition: 'right',
|
||||
labelWidth: 'auto',
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchLabelWidth: 120,
|
||||
searchMenuSpan: 6,
|
||||
searchLabelWidth: 160,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuSpan: 24,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
indexLabel: '序号',
|
||||
@@ -242,31 +316,13 @@ export default {
|
||||
dialogClickModal: false,
|
||||
menuWidth: 160,
|
||||
column: [
|
||||
{
|
||||
label: '编码',
|
||||
prop: 'code',
|
||||
search: true,
|
||||
width: 140,
|
||||
placeholder: '港口如 CNSHG,码头如 CNSHG-CT1',
|
||||
rules: [
|
||||
{ required: true, message: '请输入编码', trigger: 'blur' },
|
||||
{ validator: validateCode, trigger: 'blur' },
|
||||
],
|
||||
change: ({ value }) => this.handleCodeChange(value),
|
||||
blur: ({ value }) => this.handleCodeChange(value),
|
||||
},
|
||||
{
|
||||
label: '港口/码头名称',
|
||||
prop: 'name',
|
||||
minWidth: 140,
|
||||
search: true,
|
||||
rules: [{ required: true, message: '请输入港口/码头名称', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '类型',
|
||||
prop: 'category',
|
||||
type: 'select',
|
||||
search: true,
|
||||
formslot: true,
|
||||
span: 24,
|
||||
dicData: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '港口', value: '港口' },
|
||||
@@ -285,6 +341,8 @@ export default {
|
||||
},
|
||||
dicData: [],
|
||||
hide: true,
|
||||
span: 12,
|
||||
placeholder: '请选择',
|
||||
rules: [{ required: false, message: '请选择上级港口', trigger: 'change' }],
|
||||
change: ({ value }) => this.handleParentChange(value),
|
||||
},
|
||||
@@ -301,50 +359,147 @@ export default {
|
||||
prop: 'parentCode',
|
||||
minWidth: 120,
|
||||
slot: true,
|
||||
disabled: true,
|
||||
span: 12,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
placeholder: '自动带出',
|
||||
rules: [{ required: false, message: '请选择上级港口', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '港口/码头名称',
|
||||
prop: 'name',
|
||||
minWidth: 140,
|
||||
search: true,
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [{ required: true, message: '请输入港口/码头名称', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '编码',
|
||||
prop: 'code',
|
||||
search: true,
|
||||
formslot: true,
|
||||
width: 140,
|
||||
span: 12,
|
||||
placeholder: '请输入编码',
|
||||
rules: [
|
||||
{ required: true, message: '请输入编码', trigger: 'blur' },
|
||||
{ validator: validateCode, trigger: 'blur' },
|
||||
],
|
||||
change: ({ value }) => this.handleCodeChange(value),
|
||||
blur: ({ value }) => this.handleCodeChange(value),
|
||||
},
|
||||
{
|
||||
label: '国家',
|
||||
prop: 'country',
|
||||
type: 'select',
|
||||
search: true,
|
||||
formslot: true,
|
||||
filterable: true,
|
||||
dicData: [],
|
||||
span: 12,
|
||||
minWidth: 100,
|
||||
minWidth: 140,
|
||||
overHidden: false,
|
||||
placeholder: '自动带出',
|
||||
searchPlaceholder: '请选择 国家',
|
||||
change: ({ value }) => this.handleCountryNameChange(value),
|
||||
rules: [{ required: true, message: '请选择国家', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '城市',
|
||||
prop: 'regionCode',
|
||||
prop: 'cityCode',
|
||||
formslot: true,
|
||||
hide: true,
|
||||
span: 12,
|
||||
placeholder: '自动带出',
|
||||
rules: [{ required: true, message: '请选择所属城市', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '城市',
|
||||
prop: 'city',
|
||||
type: 'select',
|
||||
search: true,
|
||||
filterable: true,
|
||||
dicData: [],
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
minWidth: 100,
|
||||
change: ({ value }) => this.handleCityNameChange(value),
|
||||
},
|
||||
{
|
||||
label: '区县',
|
||||
prop: 'districtCode',
|
||||
type: 'select',
|
||||
formslot: true,
|
||||
hide: true,
|
||||
props: {
|
||||
label: 'title',
|
||||
value: 'id',
|
||||
},
|
||||
dicData: [],
|
||||
span: 12,
|
||||
placeholder: '选择城市后再选择区县',
|
||||
rules: [{ required: true, message: '请选择区县', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '区县',
|
||||
prop: 'districtName',
|
||||
type: 'select',
|
||||
search: true,
|
||||
filterable: true,
|
||||
dicData: [],
|
||||
minWidth: 100,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '行政区划编号',
|
||||
prop: 'regionCode',
|
||||
minWidth: 140,
|
||||
span: 12,
|
||||
placeholder: '选择区县后自动填写',
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
rules: [{ max: 32, message: '行政区划编码不能超过32字', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '详细地址',
|
||||
prop: 'detailAddress',
|
||||
type: 'textarea',
|
||||
minRows: 3,
|
||||
span: 24,
|
||||
minWidth: 220,
|
||||
overHidden: false,
|
||||
placeholder: '请输入',
|
||||
maxlength: 255,
|
||||
showWordLimit: true,
|
||||
rules: [{ max: 255, message: '详细地址不能超过255字', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '经度',
|
||||
prop: 'longitude',
|
||||
type: 'number',
|
||||
precision: 6,
|
||||
formslot: true,
|
||||
minWidth: 130,
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
overHidden: false,
|
||||
rules: [{ validator: validateLongitude, trigger: 'blur' }],
|
||||
rules: [
|
||||
{ required: true, message: '请输入经度', trigger: 'blur' },
|
||||
{ validator: validateLongitude, trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '纬度',
|
||||
prop: 'latitude',
|
||||
type: 'number',
|
||||
precision: 6,
|
||||
formslot: true,
|
||||
minWidth: 130,
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
overHidden: false,
|
||||
rules: [{ validator: validateLatitude, trigger: 'blur' }],
|
||||
rules: [
|
||||
{ required: true, message: '请输入纬度', trigger: 'blur' },
|
||||
{ validator: validateLatitude, trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '数据来源',
|
||||
@@ -353,6 +508,8 @@ export default {
|
||||
search: true,
|
||||
minWidth: 120,
|
||||
overHidden: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
dicData: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '初始化导入', value: '初始化导入' },
|
||||
@@ -369,6 +526,8 @@ export default {
|
||||
dataType: 'number',
|
||||
minWidth: 110,
|
||||
overHidden: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
dicData: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '启用', value: 1 },
|
||||
@@ -418,6 +577,7 @@ export default {
|
||||
],
|
||||
},
|
||||
excelOption: {
|
||||
labelPosition: 'right',
|
||||
submitBtn: false,
|
||||
emptyBtn: false,
|
||||
column: [
|
||||
@@ -459,11 +619,14 @@ export default {
|
||||
: String(authority || '').includes('admin');
|
||||
},
|
||||
isParentRegionLocked() {
|
||||
return this.form.category === '码头' && !!this.form.parentId;
|
||||
return this.form.category === '码头';
|
||||
},
|
||||
isRegionDisabled() {
|
||||
isCityDisabled() {
|
||||
return this.isParentRegionLocked || !this.form.countryCode;
|
||||
},
|
||||
isDistrictDisabled() {
|
||||
return this.isParentRegionLocked || !this.form.cityCode;
|
||||
},
|
||||
ids() {
|
||||
let ids = [];
|
||||
this.selectionList.forEach(ele => {
|
||||
@@ -487,36 +650,52 @@ export default {
|
||||
return;
|
||||
}
|
||||
if (this.form.category === '码头') {
|
||||
this.form.code = code.replace(/[^A-Z0-9-]/g, '');
|
||||
const terminalCode = this.getTerminalCodePart(code).replace(/[^A-Z0-9]/g, '');
|
||||
if (this.form.parentCode) {
|
||||
this.handleTerminalCodeChange(terminalCode);
|
||||
} else {
|
||||
this.form.terminalCode = terminalCode;
|
||||
this.form.code = code.replace(/[^A-Z0-9-]/g, '');
|
||||
}
|
||||
}
|
||||
},
|
||||
loadRegionNode(node, resolve) {
|
||||
const parentCode = node.level === 0 ? this.form.countryCode : node.value;
|
||||
if (!parentCode) {
|
||||
resolve([]);
|
||||
return;
|
||||
handleTerminalCodeChange(value) {
|
||||
const terminalCode = String(value || '')
|
||||
.toUpperCase()
|
||||
.replace(/[^A-Z0-9]/g, '');
|
||||
this.form.terminalCode = terminalCode;
|
||||
this.form.code =
|
||||
this.form.parentCode && terminalCode ? `${this.form.parentCode}-${terminalCode}` : '';
|
||||
},
|
||||
getTerminalCodePart(code) {
|
||||
const value = String(code || '').toUpperCase();
|
||||
if (this.form.parentCode && value.startsWith(`${this.form.parentCode}-`)) {
|
||||
return value.slice(this.form.parentCode.length + 1);
|
||||
}
|
||||
getLazyTree(parentCode).then(res => {
|
||||
const regionList = res.data.data || [];
|
||||
const nodes = regionList.map(region => {
|
||||
this.regionNodeMap[region.id] = region;
|
||||
this.regionNameMap[region.title] = region.id;
|
||||
return {
|
||||
id: region.id,
|
||||
title: region.title,
|
||||
leaf: node.level >= 1,
|
||||
};
|
||||
});
|
||||
resolve(nodes);
|
||||
});
|
||||
return value.split('-').slice(1).join('-');
|
||||
},
|
||||
syncTerminalCode() {
|
||||
if (this.form.category !== '码头') return;
|
||||
this.form.terminalCode = this.getTerminalCodePart(this.form.code);
|
||||
this.handleTerminalCodeChange(this.form.terminalCode);
|
||||
},
|
||||
setColumnDisplay(prop, display) {
|
||||
const column = this.findColumn(this.option.column, prop);
|
||||
if (!column) return;
|
||||
column.display = display;
|
||||
column.addDisplay = display;
|
||||
column.editDisplay = display;
|
||||
column.viewDisplay = display;
|
||||
},
|
||||
loadCountryOptions() {
|
||||
return getLazyTree('0').then(res => {
|
||||
this.countryOptions = res.data.data || [];
|
||||
this.countryOptions.forEach(country => {
|
||||
this.regionNodeMap[country.id] = country;
|
||||
this.regionNameMap[country.title] = country.id;
|
||||
});
|
||||
this.countryOptions = (res.data.data || []).map(this.normalizeRegionOption);
|
||||
const countryColumn = this.findColumn(this.option.column, 'country');
|
||||
countryColumn.dicData = this.countryOptions.map(country => ({
|
||||
label: country.title,
|
||||
value: country.title,
|
||||
id: country.id,
|
||||
}));
|
||||
});
|
||||
},
|
||||
loadPortOptions() {
|
||||
@@ -525,22 +704,39 @@ export default {
|
||||
this.findColumn(this.option.column, 'parentId').dicData = this.portOptions;
|
||||
});
|
||||
},
|
||||
handleCategoryChange(value) {
|
||||
clearParentPortFields() {
|
||||
this.form.parentId = undefined;
|
||||
this.form.parentCode = '';
|
||||
this.form.parentName = '';
|
||||
this.form.countryCode = '';
|
||||
this.form.country = '';
|
||||
this.clearCityValue();
|
||||
},
|
||||
handleCategoryChange(value, reset = true) {
|
||||
const parentColumn = this.findColumn(this.option.column, 'parentId');
|
||||
parentColumn.rules[0].required = value === '码头';
|
||||
this.setColumnDisplay('parentId', value === '码头');
|
||||
if (value === '港口') {
|
||||
this.form.parentId = undefined;
|
||||
this.form.parentCode = '';
|
||||
this.form.parentName = '';
|
||||
this.form.terminalCode = '';
|
||||
this.form.code = reset ? '' : String(this.form.code || '').split('-')[0];
|
||||
} else if (reset) {
|
||||
this.clearParentPortFields();
|
||||
}
|
||||
this.handleCodeChange(this.form.code);
|
||||
},
|
||||
handleCountryChange(value) {
|
||||
const country = this.countryOptions.find(item => item.id === value);
|
||||
this.form.country = country ? country.title : '';
|
||||
this.form.regionCode = [];
|
||||
this.form.city = '';
|
||||
this.regionCascaderKey += 1;
|
||||
this.clearCityValue();
|
||||
this.loadCityOptions(value);
|
||||
},
|
||||
handleCountryNameChange(value) {
|
||||
const country = this.countryOptions.find(item => item.title === value);
|
||||
this.setDistrictOptions([]);
|
||||
this.loadCityOptions(country ? country.id : '');
|
||||
},
|
||||
syncCountryName(countryCode) {
|
||||
const country = this.countryOptions.find(item => item.id === countryCode);
|
||||
@@ -548,37 +744,177 @@ export default {
|
||||
this.form.country = country.title;
|
||||
}
|
||||
},
|
||||
normalizeRegionOption(region) {
|
||||
return {
|
||||
...region,
|
||||
id: region.id === undefined || region.id === null ? region.id : String(region.id),
|
||||
parentCode:
|
||||
region.parentCode === undefined || region.parentCode === null
|
||||
? region.parentCode
|
||||
: String(region.parentCode),
|
||||
};
|
||||
},
|
||||
setCityOptions(cityOptions) {
|
||||
this.cityOptions = cityOptions;
|
||||
const cityCodeColumn = this.findColumn(this.option.column, 'cityCode');
|
||||
if (cityCodeColumn) {
|
||||
cityCodeColumn.dicData = cityOptions;
|
||||
}
|
||||
const cityColumn = this.findColumn(this.option.column, 'city');
|
||||
if (cityColumn) {
|
||||
cityColumn.dicData = cityOptions.map(city => ({
|
||||
label: city.title,
|
||||
value: city.title,
|
||||
id: city.id,
|
||||
}));
|
||||
}
|
||||
},
|
||||
clearCityValue() {
|
||||
this.form.cityCode = undefined;
|
||||
this.form.city = '';
|
||||
this.clearDistrictValue();
|
||||
},
|
||||
clearDistrictValue() {
|
||||
this.form.districtCode = undefined;
|
||||
this.form.districtName = '';
|
||||
this.form.regionCode = '';
|
||||
},
|
||||
loadCityOptions(countryCode) {
|
||||
if (!countryCode) {
|
||||
this.setCityOptions([]);
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
if (this.cityOptionCache[countryCode]) {
|
||||
this.setCityOptions(this.cityOptionCache[countryCode]);
|
||||
return Promise.resolve(this.cityOptionCache[countryCode]);
|
||||
}
|
||||
this.cityLoading = true;
|
||||
return getLazyTree(countryCode)
|
||||
.then(res => {
|
||||
const firstLevelList = (res.data.data || []).map(this.normalizeRegionOption);
|
||||
return Promise.all(
|
||||
firstLevelList.map(parent => {
|
||||
return getLazyTree(parent.id).then(childRes => {
|
||||
const childList = (childRes.data.data || []).map(this.normalizeRegionOption);
|
||||
return childList.map(child => ({
|
||||
...child,
|
||||
parentCode: child.parentCode || parent.id,
|
||||
}));
|
||||
});
|
||||
})
|
||||
).then(cityGroups => {
|
||||
const cityList = cityGroups.flat();
|
||||
const options = cityList.length > 0 ? cityList : firstLevelList;
|
||||
this.cityOptionCache[countryCode] = options;
|
||||
this.setCityOptions(options);
|
||||
return options;
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
this.cityLoading = false;
|
||||
});
|
||||
},
|
||||
resolveCityCode(cityName, regionCode) {
|
||||
const city = this.cityOptions.find(item => item.title === cityName || item.id === regionCode);
|
||||
return city ? city.id : '';
|
||||
},
|
||||
setDistrictOptions(districtOptions) {
|
||||
this.districtOptions = districtOptions;
|
||||
const districtCodeColumn = this.findColumn(this.option.column, 'districtCode');
|
||||
if (districtCodeColumn) {
|
||||
districtCodeColumn.dicData = districtOptions;
|
||||
}
|
||||
const districtNameColumn = this.findColumn(this.option.column, 'districtName');
|
||||
if (districtNameColumn) {
|
||||
districtNameColumn.dicData = districtOptions.map(district => ({
|
||||
label: district.title,
|
||||
value: district.title,
|
||||
id: district.id,
|
||||
}));
|
||||
}
|
||||
},
|
||||
loadDistrictOptions(cityCode) {
|
||||
if (!cityCode) {
|
||||
this.setDistrictOptions([]);
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
if (this.districtOptionCache[cityCode]) {
|
||||
this.setDistrictOptions(this.districtOptionCache[cityCode]);
|
||||
return Promise.resolve(this.districtOptionCache[cityCode]);
|
||||
}
|
||||
this.districtLoading = true;
|
||||
return getLazyTree(cityCode)
|
||||
.then(res => {
|
||||
const options = (res.data.data || []).map(this.normalizeRegionOption);
|
||||
this.districtOptionCache[cityCode] = options;
|
||||
this.setDistrictOptions(options);
|
||||
return options;
|
||||
})
|
||||
.finally(() => {
|
||||
this.districtLoading = false;
|
||||
});
|
||||
},
|
||||
resolveDistrictCode(districtName, regionCode) {
|
||||
const district = this.districtOptions.find(
|
||||
item => item.id === regionCode || item.title === districtName
|
||||
);
|
||||
return district ? district.id : regionCode || '';
|
||||
},
|
||||
handleParentChange(value) {
|
||||
const parent = this.portOptions.find(item => item.id === value);
|
||||
if (!parent) return;
|
||||
const terminalCode = String(this.form.code || '')
|
||||
.split('-')
|
||||
.slice(1)
|
||||
.join('-');
|
||||
if (!parent) {
|
||||
this.clearParentPortFields();
|
||||
this.syncTerminalCode();
|
||||
return;
|
||||
}
|
||||
const terminalCode =
|
||||
this.form.terminalCode ||
|
||||
String(this.form.code || '')
|
||||
.split('-')
|
||||
.slice(1)
|
||||
.join('-');
|
||||
this.form.parentCode = parent.code;
|
||||
this.form.parentName = parent.name;
|
||||
if (this.form.category === '码头' && terminalCode) {
|
||||
this.form.code = `${parent.code}-${terminalCode}`;
|
||||
}
|
||||
this.form.terminalCode = terminalCode;
|
||||
this.handleTerminalCodeChange(terminalCode);
|
||||
this.form.country = parent.country;
|
||||
this.form.city = parent.city;
|
||||
this.form.districtCode = parent.districtCode;
|
||||
this.form.districtName = parent.districtName;
|
||||
this.form.regionCode = parent.regionCode;
|
||||
this.resolveCountryCode(parent.country)
|
||||
.then(countryCode => {
|
||||
this.form.countryCode = countryCode;
|
||||
this.syncCountryName(countryCode);
|
||||
this.regionCascaderKey += 1;
|
||||
return this.resolveRegionCode(parent.country, parent.city);
|
||||
return this.loadCityOptions(countryCode);
|
||||
})
|
||||
.then(regionCode => {
|
||||
this.form.regionCode = regionCode;
|
||||
.then(() => {
|
||||
this.form.cityCode = this.resolveCityCode(parent.city, parent.regionCode);
|
||||
return this.loadDistrictOptions(this.form.cityCode);
|
||||
})
|
||||
.then(() => {
|
||||
this.form.districtCode = this.resolveDistrictCode(parent.districtName, parent.regionCode);
|
||||
this.handleDistrictChange(this.form.districtCode);
|
||||
});
|
||||
},
|
||||
handleRegionChange(value) {
|
||||
const regionCode = Array.isArray(value) ? value : [];
|
||||
const provinceCode = regionCode[0];
|
||||
const cityCode = regionCode[1];
|
||||
const city = this.regionNodeMap[cityCode];
|
||||
handleCityChange(value) {
|
||||
const city = this.cityOptions.find(item => item.id === value);
|
||||
this.form.city = city ? city.title : '';
|
||||
this.clearDistrictValue();
|
||||
this.loadDistrictOptions(value);
|
||||
},
|
||||
handleCityNameChange(value) {
|
||||
const city = this.cityOptions.find(item => item.title === value);
|
||||
this.setDistrictOptions([]);
|
||||
this.loadDistrictOptions(city ? city.id : '');
|
||||
},
|
||||
handleDistrictChange(value) {
|
||||
const district = this.districtOptions.find(item => item.id === value);
|
||||
this.form.districtName = district ? district.title : '';
|
||||
this.form.regionCode = value || '';
|
||||
},
|
||||
handleCoordinateInput(prop, value) {
|
||||
this.form[prop] = normalizeCoordinateInput(value);
|
||||
},
|
||||
resolveCountryCode(country) {
|
||||
if (!country) {
|
||||
@@ -597,55 +933,26 @@ export default {
|
||||
return option ? option.id : DEFAULT_COUNTRY_CODE;
|
||||
});
|
||||
},
|
||||
resolveRegionCode(country, city) {
|
||||
if (!country || !city) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
const countryCode = this.form.countryCode || this.regionNameMap[country];
|
||||
if (!countryCode) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return this.loadRegionList(countryCode).then(provinceList => {
|
||||
const province = provinceList.find(item => item.title === country || item.title === city);
|
||||
if (province) {
|
||||
return this.loadRegionList(province.id).then(cityList => {
|
||||
const cityNode = cityList.find(item => item.title === city);
|
||||
return cityNode ? [province.id, cityNode.id] : [province.id];
|
||||
});
|
||||
}
|
||||
return provinceList.reduce((promise, item) => {
|
||||
return promise.then(result => {
|
||||
if (result.length > 0) {
|
||||
return result;
|
||||
}
|
||||
return this.loadRegionList(item.id).then(cityList => {
|
||||
const cityNode = cityList.find(child => child.title === city);
|
||||
return cityNode ? [item.id, cityNode.id] : [];
|
||||
});
|
||||
});
|
||||
}, Promise.resolve([]));
|
||||
});
|
||||
},
|
||||
loadRegionList(parentCode) {
|
||||
return getLazyTree(parentCode).then(res => {
|
||||
const regionList = res.data.data || [];
|
||||
regionList.forEach(region => {
|
||||
this.regionNodeMap[region.id] = region;
|
||||
this.regionNameMap[region.title] = region.id;
|
||||
});
|
||||
return regionList;
|
||||
});
|
||||
},
|
||||
normalizeRow(row) {
|
||||
row.code = String(row.code || '').toUpperCase();
|
||||
if (row.category === '港口') {
|
||||
row.parentId = undefined;
|
||||
row.parentCode = undefined;
|
||||
row.parentName = undefined;
|
||||
const submitRow = { ...row };
|
||||
submitRow.code = String(submitRow.code || '').toUpperCase();
|
||||
submitRow.regionCode = String(submitRow.regionCode || '').trim();
|
||||
submitRow.districtCode = String(submitRow.districtCode || '').trim();
|
||||
submitRow.districtName = String(submitRow.districtName || '').trim();
|
||||
submitRow.detailAddress = String(submitRow.detailAddress || '').trim();
|
||||
submitRow.longitude = normalizeCoordinateInput(submitRow.longitude);
|
||||
submitRow.latitude = normalizeCoordinateInput(submitRow.latitude);
|
||||
if (submitRow.category === '港口') {
|
||||
submitRow.parentId = undefined;
|
||||
submitRow.parentCode = undefined;
|
||||
submitRow.parentName = undefined;
|
||||
}
|
||||
if (!row.dataSource) row.dataSource = '手工导入';
|
||||
if (!row.status) row.status = 1;
|
||||
return row;
|
||||
if (!submitRow.dataSource) submitRow.dataSource = '手工导入';
|
||||
if (!submitRow.status) submitRow.status = 1;
|
||||
delete submitRow.terminalCode;
|
||||
delete submitRow.cityCode;
|
||||
delete submitRow.countryCode;
|
||||
return submitRow;
|
||||
},
|
||||
validateRequiredFields(row) {
|
||||
const isBlank = value => value === undefined || value === null || String(value).trim() === '';
|
||||
@@ -665,8 +972,26 @@ export default {
|
||||
this.$message.warning('请选择上级港口');
|
||||
return false;
|
||||
}
|
||||
if (!Array.isArray(row.regionCode) || row.regionCode.length < 2) {
|
||||
this.$message.warning('请选择所属城市');
|
||||
if (isBlank(row.regionCode)) {
|
||||
this.$message.warning('请选择区县');
|
||||
return false;
|
||||
}
|
||||
if (isBlank(row.longitude)) {
|
||||
this.$message.warning('请输入经度');
|
||||
return false;
|
||||
}
|
||||
const longitudeMessage = getCoordinateValidationMessage(row.longitude, 'longitude');
|
||||
if (longitudeMessage) {
|
||||
this.$message.warning(longitudeMessage);
|
||||
return false;
|
||||
}
|
||||
if (isBlank(row.latitude)) {
|
||||
this.$message.warning('请输入纬度');
|
||||
return false;
|
||||
}
|
||||
const latitudeMessage = getCoordinateValidationMessage(row.latitude, 'latitude');
|
||||
if (latitudeMessage) {
|
||||
this.$message.warning(latitudeMessage);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -770,37 +1095,57 @@ export default {
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
this.form = res.data.data;
|
||||
this.form.terminalCode = this.getTerminalCodePart(this.form.code);
|
||||
this.resolveCountryCode(this.form.country)
|
||||
.then(countryCode => {
|
||||
this.form.countryCode = countryCode;
|
||||
this.syncCountryName(countryCode);
|
||||
this.regionCascaderKey += 1;
|
||||
return this.resolveRegionCode(this.form.country, this.form.city);
|
||||
return this.loadCityOptions(countryCode);
|
||||
})
|
||||
.then(regionCode => {
|
||||
this.form.regionCode = regionCode;
|
||||
this.handleCategoryChange(this.form.category);
|
||||
.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);
|
||||
}
|
||||
this.handleCategoryChange(this.form.category, false);
|
||||
this.syncTerminalCode();
|
||||
done();
|
||||
});
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
this.resolveCountryCode(this.form.country)
|
||||
.then(countryCode => {
|
||||
this.form.countryCode = countryCode;
|
||||
this.syncCountryName(countryCode);
|
||||
this.regionCascaderKey += 1;
|
||||
return this.resolveRegionCode(this.form.country, this.form.city);
|
||||
})
|
||||
.then(regionCode => {
|
||||
this.form.regionCode = regionCode;
|
||||
done();
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.resolveCountryCode(this.form.country)
|
||||
.then(countryCode => {
|
||||
this.form.countryCode = countryCode;
|
||||
this.syncCountryName(countryCode);
|
||||
return this.loadCityOptions(countryCode);
|
||||
})
|
||||
.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();
|
||||
});
|
||||
},
|
||||
searchReset() {
|
||||
this.query = {};
|
||||
this.setCityOptions([]);
|
||||
this.setDistrictOptions([]);
|
||||
this.onLoad(this.page);
|
||||
},
|
||||
searchChange(params, done) {
|
||||
@@ -839,24 +1184,9 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadBefore(file, done) {
|
||||
const fileName = file && file.name ? file.name.toLowerCase() : '';
|
||||
if (!/\.(xls|xlsx)$/.test(fileName)) {
|
||||
this.$message.error('请上传 .xls,.xlsx 标准格式文件');
|
||||
return false;
|
||||
}
|
||||
if (typeof done === 'function') {
|
||||
done();
|
||||
}
|
||||
return true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
this.loadPortOptions();
|
||||
done();
|
||||
openImportDialog(this, '港口码头主数据', () => {
|
||||
this.loadPortOptions();
|
||||
});
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出港口码头主数据?', '提示', {
|
||||
@@ -894,13 +1224,3 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.port-terminal-page {
|
||||
:deep(.avue-crud__header),
|
||||
:deep(.el-table th .cell),
|
||||
:deep(.el-table td .cell) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -79,15 +79,45 @@
|
||||
{{ row.status === 1 ? '停用' : '启用' }}
|
||||
</el-button>
|
||||
</template>
|
||||
<template #districtCode-form>
|
||||
<el-select
|
||||
v-model="form.districtCode"
|
||||
clearable
|
||||
filterable
|
||||
:loading="districtLoading"
|
||||
:disabled="!form.cityCode"
|
||||
:placeholder="form.cityCode ? '请选择区县' : '请先选择城市'"
|
||||
style="width: 100%"
|
||||
@change="handleDistrictChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in districtOptions"
|
||||
:key="item.id"
|
||||
:label="item.title"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template #longitude-form>
|
||||
<el-input
|
||||
v-model="form.longitude"
|
||||
clearable
|
||||
placeholder="请输入经度"
|
||||
@input="handleCoordinateInput('longitude', $event)"
|
||||
/>
|
||||
</template>
|
||||
<template #latitude-form>
|
||||
<el-input
|
||||
v-model="form.latitude"
|
||||
clearable
|
||||
placeholder="请输入纬度"
|
||||
@input="handleCoordinateInput('latitude', $event)"
|
||||
/>
|
||||
</template>
|
||||
</avue-crud>
|
||||
|
||||
<el-dialog title="铁路车站主数据导入" append-to-body v-model="excelBox" width="555px">
|
||||
<avue-form
|
||||
:option="excelOption"
|
||||
v-model="excelForm"
|
||||
:upload-before="uploadBefore"
|
||||
:upload-after="uploadAfter"
|
||||
>
|
||||
<avue-form :option="excelOption" v-model="excelForm">
|
||||
<template #excelTemplate>
|
||||
<el-button type="primary" @click="handleTemplate">
|
||||
点击下载<i class="el-icon-download el-icon--right"></i>
|
||||
@@ -104,8 +134,10 @@ import { getLazyTree } from '@/api/base/region';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { formatUpdateUserName } from '@/utils/audit';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { getCoordinateValidationMessage, normalizeCoordinateInput } from '@/utils/coordinate';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
|
||||
@@ -128,19 +160,17 @@ export default {
|
||||
}
|
||||
};
|
||||
const validateLongitude = (rule, value, callback) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
callback();
|
||||
} else if (Number(value) < -180 || Number(value) > 180) {
|
||||
callback(new Error('经度范围为 -180 到 180'));
|
||||
const message = getCoordinateValidationMessage(value, 'longitude');
|
||||
if (message) {
|
||||
callback(new Error(message));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const validateLatitude = (rule, value, callback) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
callback();
|
||||
} else if (Number(value) < -90 || Number(value) > 90) {
|
||||
callback(new Error('纬度范围为 -90 到 90'));
|
||||
const message = getCoordinateValidationMessage(value, 'latitude');
|
||||
if (message) {
|
||||
callback(new Error(message));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
@@ -154,6 +184,8 @@ export default {
|
||||
excelForm: {},
|
||||
provinceOptions: [],
|
||||
cityOptions: [],
|
||||
districtOptions: [],
|
||||
districtLoading: false,
|
||||
regionInitializing: false,
|
||||
page: {
|
||||
pageSize: 10,
|
||||
@@ -166,9 +198,14 @@ export default {
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
dialogWidth: 980,
|
||||
labelPosition: 'right',
|
||||
labelWidth: 'auto',
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
indexLabel: '序号',
|
||||
@@ -186,8 +223,8 @@ export default {
|
||||
minWidth: 120,
|
||||
overHidden: false,
|
||||
search: true,
|
||||
addDisabled: true,
|
||||
editDisabled: true,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
placeholder: '系统自动生成',
|
||||
searchPlaceholder: '请输入编码',
|
||||
},
|
||||
@@ -271,14 +308,36 @@ export default {
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '行政区划',
|
||||
prop: 'regionName',
|
||||
search: true,
|
||||
label: '所属区县',
|
||||
prop: 'districtCode',
|
||||
type: 'select',
|
||||
formslot: true,
|
||||
hide: true,
|
||||
props: {
|
||||
label: 'title',
|
||||
value: 'id',
|
||||
},
|
||||
dicData: [],
|
||||
filterable: true,
|
||||
span: 12,
|
||||
rules: [{ required: true, message: '请选择所属区县', trigger: 'change' }],
|
||||
change: ({ value }) => this.handleDistrictChange(value),
|
||||
},
|
||||
{
|
||||
label: '所属区县',
|
||||
prop: 'districtName',
|
||||
minWidth: 140,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
},
|
||||
{
|
||||
label: '行政区划编号',
|
||||
prop: 'regionCode',
|
||||
minWidth: 160,
|
||||
overHidden: false,
|
||||
maxlength: 128,
|
||||
showWordLimit: true,
|
||||
rules: [{ max: 128, message: '行政区划不能超过128字', trigger: 'blur' }],
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
rules: [{ max: 32, message: '行政区划编码不能超过32字', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '详细地址',
|
||||
@@ -295,20 +354,24 @@ export default {
|
||||
{
|
||||
label: '经度',
|
||||
prop: 'longitude',
|
||||
type: 'number',
|
||||
precision: 6,
|
||||
formslot: true,
|
||||
minWidth: 130,
|
||||
overHidden: false,
|
||||
rules: [{ validator: validateLongitude, trigger: 'blur' }],
|
||||
rules: [
|
||||
{ required: true, message: '请输入经度', trigger: 'blur' },
|
||||
{ validator: validateLongitude, trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '纬度',
|
||||
prop: 'latitude',
|
||||
type: 'number',
|
||||
precision: 6,
|
||||
formslot: true,
|
||||
minWidth: 130,
|
||||
overHidden: false,
|
||||
rules: [{ validator: validateLatitude, trigger: 'blur' }],
|
||||
rules: [
|
||||
{ required: true, message: '请输入纬度', trigger: 'blur' },
|
||||
{ validator: validateLatitude, trigger: 'blur' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '数据来源',
|
||||
@@ -317,6 +380,8 @@ export default {
|
||||
search: true,
|
||||
minWidth: 120,
|
||||
overHidden: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
dicData: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '初始化导入', value: '初始化导入' },
|
||||
@@ -333,6 +398,8 @@ export default {
|
||||
dataType: 'number',
|
||||
minWidth: 110,
|
||||
overHidden: false,
|
||||
addDisplay: false,
|
||||
editDisplay: false,
|
||||
dicData: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '启用', value: 1 },
|
||||
@@ -383,6 +450,7 @@ export default {
|
||||
],
|
||||
},
|
||||
excelOption: {
|
||||
labelPosition: 'right',
|
||||
submitBtn: false,
|
||||
emptyBtn: false,
|
||||
column: [
|
||||
@@ -419,7 +487,9 @@ export default {
|
||||
},
|
||||
isAdmin() {
|
||||
const authority = this.userInfo && this.userInfo.authority;
|
||||
return Array.isArray(authority) ? authority.includes('admin') : String(authority || '').includes('admin');
|
||||
return Array.isArray(authority)
|
||||
? authority.includes('admin')
|
||||
: String(authority || '').includes('admin');
|
||||
},
|
||||
ids() {
|
||||
let ids = [];
|
||||
@@ -456,6 +526,22 @@ export default {
|
||||
this.findColumn('cityCode').dicData = this.cityOptions;
|
||||
});
|
||||
},
|
||||
loadDistrictOptions(cityCode) {
|
||||
if (!cityCode) {
|
||||
this.districtOptions = [];
|
||||
this.findColumn('districtCode').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;
|
||||
})
|
||||
.finally(() => {
|
||||
this.districtLoading = false;
|
||||
});
|
||||
},
|
||||
normalizeRegionOption(region) {
|
||||
return {
|
||||
...region,
|
||||
@@ -471,6 +557,10 @@ export default {
|
||||
: String(row.provinceCode),
|
||||
cityCode:
|
||||
row.cityCode === undefined || row.cityCode === null ? row.cityCode : String(row.cityCode),
|
||||
districtCode:
|
||||
row.districtCode === undefined || row.districtCode === null
|
||||
? row.districtCode
|
||||
: String(row.districtCode),
|
||||
};
|
||||
},
|
||||
ensureCityOption(row) {
|
||||
@@ -486,6 +576,19 @@ export default {
|
||||
];
|
||||
this.findColumn('cityCode').dicData = this.cityOptions;
|
||||
},
|
||||
ensureDistrictOption(row) {
|
||||
if (!row.districtCode || !row.districtName) return;
|
||||
const exists = this.districtOptions.some(item => item.id === row.districtCode);
|
||||
if (exists) return;
|
||||
this.districtOptions = [
|
||||
...this.districtOptions,
|
||||
{
|
||||
id: row.districtCode,
|
||||
title: row.districtName,
|
||||
},
|
||||
];
|
||||
this.findColumn('districtCode').dicData = this.districtOptions;
|
||||
},
|
||||
handleTmisChange(value) {
|
||||
this.form.tmisCode = String(value || '')
|
||||
.replace(/\D/g, '')
|
||||
@@ -507,20 +610,61 @@ export default {
|
||||
}
|
||||
this.form.cityCode = undefined;
|
||||
this.form.cityName = '';
|
||||
this.form.districtCode = undefined;
|
||||
this.form.districtName = '';
|
||||
this.form.regionCode = '';
|
||||
this.form.regionName = '';
|
||||
this.loadCityOptions(value);
|
||||
this.loadDistrictOptions();
|
||||
},
|
||||
handleCityChange(value) {
|
||||
const city = this.cityOptions.find(item => item.id === value);
|
||||
this.form.cityName = city ? city.title : '';
|
||||
if (this.regionInitializing) {
|
||||
this.loadDistrictOptions(value).then(() => this.ensureDistrictOption(this.form));
|
||||
return;
|
||||
}
|
||||
this.form.districtCode = undefined;
|
||||
this.form.districtName = '';
|
||||
this.form.regionCode = '';
|
||||
this.form.regionName = '';
|
||||
this.loadDistrictOptions(value);
|
||||
},
|
||||
handleDistrictChange(value) {
|
||||
const district = this.districtOptions.find(item => item.id === value);
|
||||
this.form.districtName = district ? district.title : '';
|
||||
this.form.regionCode = value || '';
|
||||
this.form.regionName = district ? district.title : '';
|
||||
},
|
||||
handleCoordinateInput(prop, value) {
|
||||
this.form[prop] = normalizeCoordinateInput(value);
|
||||
},
|
||||
normalizeRow(row) {
|
||||
row.code = row.tmisCode ? `TL${row.tmisCode}` : row.code;
|
||||
row.regionCode = String(row.regionCode || '').trim();
|
||||
row.regionName = String(row.regionName || '').trim();
|
||||
row.districtCode = String(row.districtCode || '').trim();
|
||||
row.districtName = String(row.districtName || '').trim();
|
||||
row.detailAddress = String(row.detailAddress || '').trim();
|
||||
row.longitude = normalizeCoordinateInput(row.longitude);
|
||||
row.latitude = normalizeCoordinateInput(row.latitude);
|
||||
if (!row.dataSource) row.dataSource = '手动';
|
||||
if (!row.status) row.status = 1;
|
||||
return row;
|
||||
},
|
||||
validateCoordinateFields(row) {
|
||||
const longitudeMessage = getCoordinateValidationMessage(row.longitude, 'longitude', true);
|
||||
if (longitudeMessage) {
|
||||
this.$message.warning(longitudeMessage);
|
||||
return false;
|
||||
}
|
||||
const latitudeMessage = getCoordinateValidationMessage(row.latitude, 'latitude', true);
|
||||
if (latitudeMessage) {
|
||||
this.$message.warning(latitudeMessage);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
validateUnique(row) {
|
||||
const rowId = String(row.id || '');
|
||||
const hasDuplicate = (params, prop) => {
|
||||
@@ -552,6 +696,10 @@ export default {
|
||||
},
|
||||
rowSave(row, done, loading) {
|
||||
const submitRow = this.normalizeRow(row);
|
||||
if (!this.validateCoordinateFields(submitRow)) {
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
this.validateUnique(submitRow)
|
||||
.then(() => submit(submitRow))
|
||||
.then(() => {
|
||||
@@ -563,6 +711,10 @@ export default {
|
||||
},
|
||||
rowUpdate(row, index, done, loading) {
|
||||
const submitRow = this.normalizeRow(row);
|
||||
if (!this.validateCoordinateFields(submitRow)) {
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
this.validateUnique(submitRow)
|
||||
.then(() => submit(submitRow))
|
||||
.then(() => {
|
||||
@@ -620,23 +772,30 @@ export default {
|
||||
this.regionInitializing = true;
|
||||
getDetail(this.form.id).then(res => {
|
||||
const detail = this.normalizeRegionForm(res.data.data || {});
|
||||
this.loadCityOptions(detail.provinceCode).then(() => {
|
||||
this.ensureCityOption(detail);
|
||||
this.form = detail;
|
||||
done();
|
||||
this.$nextTick(() => {
|
||||
window.setTimeout(() => {
|
||||
this.regionInitializing = false;
|
||||
}, 0);
|
||||
this.loadCityOptions(detail.provinceCode)
|
||||
.then(() => {
|
||||
this.ensureCityOption(detail);
|
||||
return this.loadDistrictOptions(detail.cityCode);
|
||||
})
|
||||
.then(() => {
|
||||
this.ensureDistrictOption(detail);
|
||||
this.form = detail;
|
||||
done();
|
||||
this.$nextTick(() => {
|
||||
window.setTimeout(() => {
|
||||
this.regionInitializing = false;
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.form.code = '';
|
||||
this.form.dataSource = '手动';
|
||||
this.form.status = 1;
|
||||
this.loadCityOptions(this.form.provinceCode).then(() => done());
|
||||
this.loadCityOptions(this.form.provinceCode)
|
||||
.then(() => this.loadDistrictOptions(this.form.cityCode))
|
||||
.then(() => done());
|
||||
},
|
||||
searchReset() {
|
||||
this.query = {};
|
||||
@@ -678,23 +837,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadBefore(file, done) {
|
||||
const fileName = file && file.name ? file.name.toLowerCase() : '';
|
||||
if (!/\.(xls|xlsx)$/.test(fileName)) {
|
||||
this.$message.error('请上传 .xls,.xlsx 标准格式文件');
|
||||
return false;
|
||||
}
|
||||
if (typeof done === 'function') {
|
||||
done();
|
||||
}
|
||||
return true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '铁路车站主数据');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出铁路车站主数据?', '提示', {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-row>
|
||||
<el-col :span="9">
|
||||
<el-row class="region-page">
|
||||
<el-col class="region-page__tree-panel" :span="6">
|
||||
<div class="box">
|
||||
<el-scrollbar>
|
||||
<basic-container>
|
||||
@@ -9,7 +9,7 @@
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="15">
|
||||
<el-col class="region-page__form-panel" :span="18">
|
||||
<basic-container>
|
||||
<el-button-group>
|
||||
<el-button
|
||||
@@ -55,17 +55,34 @@
|
||||
@click="handleSync"
|
||||
>同步
|
||||
</el-button>
|
||||
<!-- <el-button-->
|
||||
<!-- v-if="permission.region_debug"-->
|
||||
<!-- type="primary"-->
|
||||
<!-- icon="el-icon-video-play"-->
|
||||
<!-- @click="handleDebug"-->
|
||||
<!-- >调试-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-button-->
|
||||
<!-- v-if="permission.region_debug"-->
|
||||
<!-- type="primary"-->
|
||||
<!-- icon="el-icon-video-play"-->
|
||||
<!-- @click="handleDebug"-->
|
||||
<!-- >调试-->
|
||||
<!-- </el-button>-->
|
||||
</el-button-group>
|
||||
</basic-container>
|
||||
<basic-container>
|
||||
<avue-form ref="form" :option="regionOption" v-model="regionForm" @submit="handleSubmit">
|
||||
<template #parentName="{}">
|
||||
<el-select
|
||||
class="region-parent-select"
|
||||
v-model="regionForm.parentCode"
|
||||
filterable
|
||||
:disabled="isCountryRegion"
|
||||
placeholder="请选择父区划"
|
||||
@change="handleParentChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in parentOptions"
|
||||
:key="item.code"
|
||||
:label="item.name"
|
||||
:value="item.code"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template #code="{}">
|
||||
<el-input
|
||||
v-if="isCountryRegion"
|
||||
@@ -83,7 +100,7 @@
|
||||
</template>
|
||||
</avue-form>
|
||||
<el-dialog title="行政区划数据导入" append-to-body v-model="excelBox" width="555px">
|
||||
<avue-form :option="excelOption" v-model="excelForm" :upload-after="uploadAfter">
|
||||
<avue-form :option="excelOption" v-model="excelForm">
|
||||
<template #excelTemplate>
|
||||
<el-button type="primary" @click="handleTemplate">
|
||||
点击下载<i class="el-icon-download el-icon--right"></i>
|
||||
@@ -105,6 +122,7 @@ import { exportBlob } from '@/api/common';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { validatenull } from '@/utils/validate';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import NProgress from 'nprogress';
|
||||
import 'nprogress/nprogress.css';
|
||||
@@ -118,6 +136,7 @@ export default {
|
||||
treeCode: '',
|
||||
treeParentCode: '',
|
||||
treeData: [],
|
||||
parentOptions: [],
|
||||
syncLoading: false,
|
||||
treeOption: {
|
||||
nodeKey: 'id',
|
||||
@@ -137,7 +156,7 @@ export default {
|
||||
},
|
||||
addBtn: false,
|
||||
menu: false,
|
||||
size: 'small',
|
||||
size: 'default',
|
||||
props: {
|
||||
labelText: '标题',
|
||||
label: 'title',
|
||||
@@ -147,13 +166,13 @@ export default {
|
||||
},
|
||||
regionForm: {},
|
||||
regionOption: {
|
||||
labelWidth: 100,
|
||||
labelWidth: 'auto',
|
||||
column: [
|
||||
{
|
||||
label: '父区划编号',
|
||||
prop: 'parentCode',
|
||||
span: 24,
|
||||
disabled: true,
|
||||
display: false,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
@@ -166,7 +185,7 @@ export default {
|
||||
label: '父区划名称',
|
||||
prop: 'parentName',
|
||||
span: 24,
|
||||
disabled: true,
|
||||
formslot: true,
|
||||
},
|
||||
{
|
||||
label: '区划编号',
|
||||
@@ -295,7 +314,7 @@ export default {
|
||||
debugBox: false,
|
||||
debugForm: {},
|
||||
debugOption: {
|
||||
labelWidth: 50,
|
||||
labelWidth: 'auto',
|
||||
submitBtn: false,
|
||||
emptyBtn: false,
|
||||
column: [
|
||||
@@ -345,24 +364,25 @@ export default {
|
||||
if (this.isCountryRegion) {
|
||||
return;
|
||||
}
|
||||
const parentCode = this.isProvinceRegion ? '' : this.regionForm.parentCode;
|
||||
this.regionForm.code = parentCode + this.regionForm.subCode;
|
||||
this.syncRegionCode();
|
||||
},
|
||||
'excelForm.isCovered'() {
|
||||
if (this.excelForm.isCovered !== '') {
|
||||
const column = this.findColumn(this.excelOption.column, 'excelFile');
|
||||
column.action = `/blade-system/region/import-region?isCovered=${this.excelForm.isCovered}`;
|
||||
}
|
||||
this.syncImportAction();
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['permission']),
|
||||
isCountryRegion() {
|
||||
return Number(this.regionForm.regionLevel) === 0 || this.regionForm.parentCode === this.topCode;
|
||||
return (
|
||||
Number(this.regionForm.regionLevel) === 0 || this.regionForm.parentCode === this.topCode
|
||||
);
|
||||
},
|
||||
isProvinceRegion() {
|
||||
return Number(this.regionForm.regionLevel) === 1;
|
||||
},
|
||||
isEditRegion() {
|
||||
return !validatenull(this.regionForm.originalCode);
|
||||
},
|
||||
permissionList() {
|
||||
return {
|
||||
addBtn: this.validData(this.permission.region_add, false),
|
||||
@@ -392,28 +412,30 @@ export default {
|
||||
});
|
||||
},
|
||||
nodeClick(data) {
|
||||
const column = this.findColumn(this.regionOption.column, 'parentCode');
|
||||
column.disabled = true;
|
||||
this.setRegionColumnDisplay('code', true);
|
||||
this.treeCode = data.id;
|
||||
this.treeParentCode = data.parentId;
|
||||
getDetail(this.treeCode).then(res => {
|
||||
this.regionForm = res.data.data;
|
||||
this.regionForm.originalCode = this.regionForm.code;
|
||||
this.regionForm.subCode =
|
||||
this.regionForm.parentCode === this.topCode
|
||||
? this.regionForm.code
|
||||
: this.regionForm.code.replace(this.regionForm.parentCode, '');
|
||||
this.loadParentOptions(this.regionForm.parentCode, this.regionForm.parentName);
|
||||
});
|
||||
},
|
||||
addCountry() {
|
||||
const column = this.findColumn(this.regionOption.column, 'parentCode');
|
||||
column.disabled = true;
|
||||
this.setRegionColumnDisplay('code', true);
|
||||
this.treeCode = '';
|
||||
this.treeParentCode = this.topCode;
|
||||
this.parentOptions = this.getRootParentOptions();
|
||||
this.regionForm = {
|
||||
parentCode: this.topCode,
|
||||
parentName: '根节点',
|
||||
code: '',
|
||||
subCode: '',
|
||||
originalCode: '',
|
||||
name: '',
|
||||
regionLevel: 0,
|
||||
sort: 1,
|
||||
@@ -424,13 +446,84 @@ export default {
|
||||
this.$message.warning('请先选择一项区划');
|
||||
return;
|
||||
}
|
||||
this.regionForm.parentCode = this.regionForm.code;
|
||||
this.regionForm.parentName = this.regionForm.name;
|
||||
const parentCode = this.regionForm.code;
|
||||
const parentName = this.regionForm.name;
|
||||
const parentGroupCode = this.regionForm.parentCode || this.topCode;
|
||||
this.setRegionColumnDisplay('code', true);
|
||||
this.regionForm.parentCode = parentCode;
|
||||
this.regionForm.parentName = parentName;
|
||||
this.regionForm.code = '';
|
||||
this.regionForm.subCode = '';
|
||||
this.regionForm.originalCode = '';
|
||||
this.regionForm.name = '';
|
||||
this.regionForm.regionLevel =
|
||||
this.regionForm.regionLevel === 5 ? 5 : this.regionForm.regionLevel + 1;
|
||||
this.loadParentOptionsByGroup(parentGroupCode, parentCode, parentName);
|
||||
},
|
||||
setRegionColumnDisplay(prop, display) {
|
||||
const column = this.findColumn(this.regionOption.column, prop);
|
||||
if (column) {
|
||||
column.display = display;
|
||||
}
|
||||
},
|
||||
handleParentChange(value) {
|
||||
const parent = this.parentOptions.find(item => item.code === value);
|
||||
this.regionForm.parentName = parent ? parent.name : '';
|
||||
this.syncRegionCode();
|
||||
},
|
||||
syncRegionCode() {
|
||||
if (this.isCountryRegion) {
|
||||
return;
|
||||
}
|
||||
const parentCode = this.isProvinceRegion ? '' : this.regionForm.parentCode || '';
|
||||
this.regionForm.code = parentCode + (this.regionForm.subCode || '');
|
||||
},
|
||||
getRootParentOptions() {
|
||||
return [
|
||||
{
|
||||
code: this.topCode,
|
||||
name: '根节点',
|
||||
},
|
||||
];
|
||||
},
|
||||
normalizeParentOption(region) {
|
||||
return {
|
||||
code: String(region.code || region.id || ''),
|
||||
name: region.name || region.title || '',
|
||||
};
|
||||
},
|
||||
ensureSelectedParent(options, selectedCode, selectedName) {
|
||||
if (validatenull(selectedCode) || options.some(item => item.code === selectedCode)) {
|
||||
return options;
|
||||
}
|
||||
return [
|
||||
...options,
|
||||
{
|
||||
code: String(selectedCode),
|
||||
name: selectedName || selectedCode,
|
||||
},
|
||||
];
|
||||
},
|
||||
loadParentOptions(selectedCode, selectedName) {
|
||||
if (validatenull(selectedCode) || selectedCode === this.topCode) {
|
||||
this.parentOptions = this.getRootParentOptions();
|
||||
return;
|
||||
}
|
||||
getDetail(selectedCode).then(res => {
|
||||
const parent = res.data.data || {};
|
||||
const groupCode = parent.parentCode || this.topCode;
|
||||
this.loadParentOptionsByGroup(groupCode, selectedCode, selectedName);
|
||||
});
|
||||
},
|
||||
loadParentOptionsByGroup(groupCode, selectedCode, selectedName) {
|
||||
if (validatenull(groupCode)) {
|
||||
this.parentOptions = this.ensureSelectedParent([], selectedCode, selectedName);
|
||||
return;
|
||||
}
|
||||
getLazyTree(groupCode).then(res => {
|
||||
const options = res.data.data.map(this.normalizeParentOption).filter(item => item.code);
|
||||
this.parentOptions = this.ensureSelectedParent(options, selectedCode, selectedName);
|
||||
});
|
||||
},
|
||||
handleSubmit(form, done) {
|
||||
if (Number(form.regionLevel) === 0) {
|
||||
@@ -481,18 +574,27 @@ export default {
|
||||
this.$refs.form.resetForm();
|
||||
});
|
||||
},
|
||||
uploadAfter(res, done, loading, column) {
|
||||
window.console.log(column);
|
||||
this.excelBox = false;
|
||||
this.initTree();
|
||||
done();
|
||||
handleImport() {
|
||||
this.syncImportAction();
|
||||
openImportDialog(this, '行政区划', () => {
|
||||
this.initTree();
|
||||
});
|
||||
},
|
||||
syncImportAction() {
|
||||
const column = this.findColumn(this.excelOption.column, 'excelFile');
|
||||
if (!column) {
|
||||
return;
|
||||
}
|
||||
const covered = this.excelForm.isCovered;
|
||||
if (covered === '' || covered === undefined || covered === null) {
|
||||
column.action = '/blade-system/region/import-region';
|
||||
} else {
|
||||
column.action = `/blade-system/region/import-region?isCovered=${covered}`;
|
||||
}
|
||||
},
|
||||
handleDebug() {
|
||||
this.debugBox = true;
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
handleSync() {
|
||||
this.$confirm('确定同步最新行政区划数据?', {
|
||||
confirmButtonText: '确定',
|
||||
@@ -553,4 +655,46 @@ export default {
|
||||
.box .el-scrollbar__wrap {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.region-parent-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.region-page .region-page__tree-panel {
|
||||
flex: 0 0 17.5%;
|
||||
max-width: 17.5%;
|
||||
}
|
||||
|
||||
.region-page .region-page__form-panel {
|
||||
flex: 0 0 82.5%;
|
||||
max-width: 82.5%;
|
||||
}
|
||||
|
||||
.region-page__tree-panel .avue-tree__filter {
|
||||
padding: 0 8px 8px;
|
||||
}
|
||||
|
||||
.region-page__tree-panel .avue-tree__filter .el-input,
|
||||
.region-page__tree-panel .avue-tree__filter .el-input__wrapper {
|
||||
width: 100%;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.region-page__tree-panel .el-tree.el-tree--highlight-current {
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.region-page__form-panel .avue-form__group.avue-form__group--flex {
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.region-page .region-page__tree-panel,
|
||||
.region-page .region-page__form-panel {
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user