This commit is contained in:
2026-07-21 13:20:06 +08:00
parent 76df2b9cd2
commit e50d1b8fda
21 changed files with 714 additions and 129 deletions

View File

@@ -109,6 +109,8 @@ import { getToken } from '@/utils/auth';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
const DEFAULT_COUNTRY_CODE = '+86';
export default {
data() {
const validateIataCode = (rule, value, callback) => {
@@ -165,6 +167,8 @@ export default {
dialogWidth: 980,
tip: false,
searchShow: true,
labelWidth: 120,
searchLabelWidth: 120,
searchMenuSpan: 6,
border: true,
index: true,
@@ -266,11 +270,35 @@ export default {
addDisplay: false,
editDisplay: false,
},
{
label: '行政区划',
prop: 'regionName',
search: true,
minWidth: 160,
overHidden: false,
maxlength: 128,
showWordLimit: true,
rules: [{ max: 128, message: '行政区划不能超过128字', trigger: 'blur' }],
},
{
label: '详细地址',
prop: 'detailAddress',
type: 'textarea',
minRows: 3,
span: 24,
minWidth: 220,
overHidden: false,
maxlength: 255,
showWordLimit: true,
rules: [{ max: 255, message: '详细地址不能超过255字', trigger: 'blur' }],
},
{
label: '经度',
prop: 'longitude',
type: 'number',
precision: 6,
minWidth: 130,
overHidden: false,
rules: [{ validator: validateLongitude, trigger: 'blur' }],
},
{
@@ -278,6 +306,8 @@ export default {
prop: 'latitude',
type: 'number',
precision: 6,
minWidth: 130,
overHidden: false,
rules: [{ validator: validateLatitude, trigger: 'blur' }],
},
{
@@ -285,6 +315,8 @@ export default {
prop: 'dataSource',
type: 'select',
search: true,
minWidth: 120,
overHidden: false,
dicData: [
{ label: '全部', value: '' },
{ label: '初始导入', value: '初始导入' },
@@ -299,6 +331,8 @@ export default {
search: true,
slot: true,
dataType: 'number',
minWidth: 110,
overHidden: false,
dicData: [
{ label: '全部', value: '' },
{ label: '启用', value: 1 },
@@ -406,7 +440,7 @@ export default {
return this.option.column.find(item => item.prop === prop);
},
loadProvinceOptions() {
getLazyTree('00').then(res => {
getLazyTree(DEFAULT_COUNTRY_CODE).then(res => {
this.provinceOptions = res.data.data;
this.findColumn('provinceCode').dicData = this.provinceOptions;
});
@@ -448,6 +482,8 @@ export default {
},
normalizeRow(row) {
row.code = row.iataCode ? `JC-${row.iataCode}` : row.code;
row.regionName = String(row.regionName || '').trim();
row.detailAddress = String(row.detailAddress || '').trim();
if (!row.dataSource) row.dataSource = '手动录入';
if (!row.status) row.status = 1;
return row;

View File

@@ -189,8 +189,7 @@ export default {
prop: 'name',
minWidth: 150,
search: true,
disabled: true,
rules: [{ required: true, message: '请选择币种编码带出币种名称', trigger: 'blur' }],
rules: [{ required: true, message: '请输入币种名称', trigger: 'blur' }],
},
{
label: '汇率',

View File

@@ -56,6 +56,12 @@
</el-button>
</template>
</avue-crud>
<empty-pagination
:page="page"
@size-change="sizeChange"
@current-change="currentChange"
@load="onLoad(page, query)"
/>
</basic-container>
</template>
@@ -72,6 +78,7 @@ export default {
data: [],
page: {
pageSize: 10,
pageSizes: [10, 20, 50, 100],
currentPage: 1,
total: 0,
},
@@ -81,6 +88,10 @@ export default {
calcHeight: 32,
dialogWidth: 680,
tip: false,
searchBtnText: '查询',
emptyBtnText: '重置',
saveBtnText: '提交',
updateBtnText: '提交',
searchShow: true,
searchMenuSpan: 6,
border: true,
@@ -119,6 +130,7 @@ export default {
{ label: '启用', value: 1 },
{ label: '停用', value: 2 },
],
clearable: true,
value: 1,
},
{
@@ -196,7 +208,7 @@ export default {
);
},
rowDel(row) {
this.$confirm('确定将选择数据删除?', {
this.$confirm('确定删除该条数据删除后不可恢复?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
@@ -212,7 +224,7 @@ export default {
this.$message.warning('请选择至少一条数据');
return;
}
this.$confirm('确定将选择数据删除?', {
this.$confirm('确定删除所选数据删除后不可恢复?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',

View File

@@ -65,6 +65,24 @@
{{ row.status === 1 ? '启用' : '停用' }}
</el-tag>
</template>
<template #country-form>
<el-select
v-model="form.countryCode"
clearable
filterable
:disabled="isParentRegionLocked"
placeholder="请选择国家"
style="width: 100%"
@change="handleCountryChange"
>
<el-option
v-for="item in countryOptions"
:key="item.id"
:label="item.title"
:value="item.id"
/>
</el-select>
</template>
<template #menu="{ row, index }">
<el-button
type="primary"
@@ -87,11 +105,12 @@
</template>
<template #regionCode-form>
<el-cascader
:key="regionCascaderKey"
v-model="form.regionCode"
:props="regionProps"
clearable
filterable
:disabled="isParentRegionLocked"
:disabled="isRegionDisabled"
style="width: 100%"
@change="handleRegionChange"
/>
@@ -133,6 +152,8 @@ import { getToken } from '@/utils/auth';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
const DEFAULT_COUNTRY_CODE = '+86';
export default {
data() {
const validateCode = (rule, value, callback) => {
@@ -183,6 +204,8 @@ export default {
excelBox: false,
excelForm: {},
portOptions: [],
countryOptions: [],
regionCascaderKey: 0,
regionNodeMap: {},
regionNameMap: {},
regionProps: {
@@ -206,6 +229,7 @@ export default {
dialogWidth: 980,
tip: false,
searchShow: true,
searchLabelWidth: 120,
searchMenuSpan: 6,
border: true,
index: true,
@@ -279,6 +303,15 @@ export default {
slot: true,
disabled: true,
},
{
label: '国家',
prop: 'country',
search: true,
formslot: true,
span: 12,
minWidth: 100,
rules: [{ required: true, message: '请选择国家', trigger: 'change' }],
},
{
label: '城市',
prop: 'regionCode',
@@ -287,14 +320,6 @@ export default {
span: 12,
rules: [{ required: true, message: '请选择所属城市', trigger: 'change' }],
},
{
label: '国家',
prop: 'country',
search: true,
addDisplay: false,
editDisplay: false,
minWidth: 100,
},
{
label: '城市',
prop: 'city',
@@ -309,6 +334,7 @@ export default {
type: 'number',
precision: 6,
minWidth: 130,
overHidden: false,
rules: [{ validator: validateLongitude, trigger: 'blur' }],
},
{
@@ -317,6 +343,7 @@ export default {
type: 'number',
precision: 6,
minWidth: 130,
overHidden: false,
rules: [{ validator: validateLatitude, trigger: 'blur' }],
},
{
@@ -324,6 +351,8 @@ export default {
prop: 'dataSource',
type: 'select',
search: true,
minWidth: 120,
overHidden: false,
dicData: [
{ label: '全部', value: '' },
{ label: '初始化导入', value: '初始化导入' },
@@ -338,6 +367,8 @@ export default {
search: true,
slot: true,
dataType: 'number',
minWidth: 110,
overHidden: false,
dicData: [
{ label: '全部', value: '' },
{ label: '启用', value: 1 },
@@ -423,11 +454,16 @@ 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');
},
isParentRegionLocked() {
return this.form.category === '码头' && !!this.form.parentId;
},
isRegionDisabled() {
return this.isParentRegionLocked || !this.form.countryCode;
},
ids() {
let ids = [];
this.selectionList.forEach(ele => {
@@ -437,6 +473,7 @@ export default {
},
},
created() {
this.loadCountryOptions();
this.loadPortOptions();
},
methods: {
@@ -454,7 +491,11 @@ export default {
}
},
loadRegionNode(node, resolve) {
const parentCode = node.level === 0 ? '00' : node.value;
const parentCode = node.level === 0 ? this.form.countryCode : node.value;
if (!parentCode) {
resolve([]);
return;
}
getLazyTree(parentCode).then(res => {
const regionList = res.data.data || [];
const nodes = regionList.map(region => {
@@ -469,6 +510,15 @@ export default {
resolve(nodes);
});
},
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;
});
});
},
loadPortOptions() {
getPortSelect().then(res => {
this.portOptions = res.data.data;
@@ -485,6 +535,19 @@ export default {
}
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;
},
syncCountryName(countryCode) {
const country = this.countryOptions.find(item => item.id === countryCode);
if (country) {
this.form.country = country.title;
}
},
handleParentChange(value) {
const parent = this.portOptions.find(item => item.id === value);
if (!parent) return;
@@ -499,43 +562,68 @@ export default {
}
this.form.country = parent.country;
this.form.city = parent.city;
this.resolveRegionCode(parent.country, parent.city).then(regionCode => {
this.form.regionCode = regionCode;
});
this.resolveCountryCode(parent.country)
.then(countryCode => {
this.form.countryCode = countryCode;
this.syncCountryName(countryCode);
this.regionCascaderKey += 1;
return this.resolveRegionCode(parent.country, parent.city);
})
.then(regionCode => {
this.form.regionCode = regionCode;
});
},
handleRegionChange(value) {
const regionCode = Array.isArray(value) ? value : [];
const provinceCode = regionCode[0];
const cityCode = regionCode[1];
const province = this.regionNodeMap[provinceCode];
const city = this.regionNodeMap[cityCode];
this.form.country = province ? province.title : '';
this.form.city = city ? city.title : '';
},
resolveCountryCode(country) {
if (!country) {
return Promise.resolve('');
}
const countryOption = this.countryOptions.find(
item => item.title === country || item.id === country
);
if (countryOption) {
return Promise.resolve(countryOption.id);
}
return this.loadCountryOptions().then(() => {
const option = this.countryOptions.find(
item => item.title === country || item.id === country
);
return option ? option.id : DEFAULT_COUNTRY_CODE;
});
},
resolveRegionCode(country, city) {
if (!country || !city) {
return Promise.resolve([]);
}
const provinceCode = this.regionNameMap[country];
if (provinceCode) {
const cityCode = this.regionNameMap[city];
if (cityCode) {
return Promise.resolve([provinceCode, cityCode]);
}
return this.loadRegionList(provinceCode).then(cityList => {
const cityNode = cityList.find(item => item.title === city);
return cityNode ? [provinceCode, cityNode.id] : [provinceCode];
});
const countryCode = this.form.countryCode || this.regionNameMap[country];
if (!countryCode) {
return Promise.resolve([]);
}
return this.loadRegionList('00').then(provinceList => {
const province = provinceList.find(item => item.title === country);
if (!province) {
return [];
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 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) {
@@ -682,18 +770,32 @@ export default {
if (['edit', 'view'].includes(type)) {
getDetail(this.form.id).then(res => {
this.form = res.data.data;
this.resolveRegionCode(this.form.country, this.form.city).then(regionCode => {
this.form.regionCode = regionCode;
this.handleCategoryChange(this.form.category);
done();
});
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;
this.handleCategoryChange(this.form.category);
done();
});
});
return;
} else {
this.resolveRegionCode(this.form.country, this.form.city).then(regionCode => {
this.form.regionCode = regionCode;
done();
});
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;
}
},

View File

@@ -109,6 +109,8 @@ import { getToken } from '@/utils/auth';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
const DEFAULT_COUNTRY_CODE = '+86';
export default {
data() {
const validateTmisCode = (rule, value, callback) => {
@@ -152,6 +154,7 @@ export default {
excelForm: {},
provinceOptions: [],
cityOptions: [],
regionInitializing: false,
page: {
pageSize: 10,
pageSizes: [10, 20, 50, 100],
@@ -180,6 +183,8 @@ export default {
{
label: '编码',
prop: 'code',
minWidth: 120,
overHidden: false,
search: true,
addDisabled: true,
editDisabled: true,
@@ -216,11 +221,11 @@ export default {
search: true,
rules: [{ required: true, message: '请输入车站名称', trigger: 'blur' }],
},
{
label: '所属铁路线路',
prop: 'railwayLine',
minWidth: 130,
},
// {
// label: '所属铁路线路',
// prop: 'railwayLine',
// minWidth: 130,
// },
{
label: '所属省份',
prop: 'provinceCode',
@@ -265,11 +270,35 @@ export default {
addDisplay: false,
editDisplay: false,
},
{
label: '行政区划',
prop: 'regionName',
search: true,
minWidth: 160,
overHidden: false,
maxlength: 128,
showWordLimit: true,
rules: [{ max: 128, message: '行政区划不能超过128字', trigger: 'blur' }],
},
{
label: '详细地址',
prop: 'detailAddress',
type: 'textarea',
minRows: 3,
span: 24,
minWidth: 220,
overHidden: false,
maxlength: 255,
showWordLimit: true,
rules: [{ max: 255, message: '详细地址不能超过255字', trigger: 'blur' }],
},
{
label: '经度',
prop: 'longitude',
type: 'number',
precision: 6,
minWidth: 130,
overHidden: false,
rules: [{ validator: validateLongitude, trigger: 'blur' }],
},
{
@@ -277,6 +306,8 @@ export default {
prop: 'latitude',
type: 'number',
precision: 6,
minWidth: 130,
overHidden: false,
rules: [{ validator: validateLatitude, trigger: 'blur' }],
},
{
@@ -284,6 +315,8 @@ export default {
prop: 'dataSource',
type: 'select',
search: true,
minWidth: 120,
overHidden: false,
dicData: [
{ label: '全部', value: '' },
{ label: '初始化导入', value: '初始化导入' },
@@ -298,6 +331,8 @@ export default {
search: true,
slot: true,
dataType: 'number',
minWidth: 110,
overHidden: false,
dicData: [
{ label: '全部', value: '' },
{ label: '启用', value: 1 },
@@ -405,8 +440,8 @@ export default {
return this.option.column.find(item => item.prop === prop);
},
loadProvinceOptions() {
getLazyTree('00').then(res => {
this.provinceOptions = res.data.data;
getLazyTree(DEFAULT_COUNTRY_CODE).then(res => {
this.provinceOptions = (res.data.data || []).map(this.normalizeRegionOption);
this.findColumn('provinceCode').dicData = this.provinceOptions;
});
},
@@ -417,10 +452,40 @@ 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;
});
},
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),
};
},
ensureCityOption(row) {
if (!row.cityCode || !row.cityName) return;
const exists = this.cityOptions.some(item => item.id === row.cityCode);
if (exists) return;
this.cityOptions = [
...this.cityOptions,
{
id: row.cityCode,
title: row.cityName,
},
];
this.findColumn('cityCode').dicData = this.cityOptions;
},
handleTmisChange(value) {
this.form.tmisCode = String(value || '')
.replace(/\D/g, '')
@@ -436,6 +501,10 @@ 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).then(() => this.ensureCityOption(this.form));
return;
}
this.form.cityCode = undefined;
this.form.cityName = '';
this.loadCityOptions(value);
@@ -446,6 +515,8 @@ export default {
},
normalizeRow(row) {
row.code = row.tmisCode ? `TL${row.tmisCode}` : row.code;
row.regionName = String(row.regionName || '').trim();
row.detailAddress = String(row.detailAddress || '').trim();
if (!row.dataSource) row.dataSource = '手动';
if (!row.status) row.status = 1;
return row;
@@ -546,9 +617,19 @@ 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.ensureCityOption(detail);
this.form = detail;
done();
this.$nextTick(() => {
window.setTimeout(() => {
this.regionInitializing = false;
}, 0);
});
});
});
return;
}

View File

@@ -12,6 +12,13 @@
<el-col :span="15">
<basic-container>
<el-button-group>
<el-button
v-if="permission.region_add"
type="primary"
icon="el-icon-plus"
@click="addCountry"
>新增国家
</el-button>
<el-button
v-if="permission.region_add"
type="primary"
@@ -48,19 +55,29 @@
@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 #code="{}">
<el-input placeholder="请输入 区划子编号" v-model="regionForm.subCode">
<el-input
v-if="isCountryRegion"
placeholder="请输入国家编码,如 +86"
v-model="regionForm.code"
/>
<el-input
v-else-if="isProvinceRegion"
placeholder="请输入省级区划编号"
v-model="regionForm.subCode"
/>
<el-input v-else placeholder="请输入 区划子编号" v-model="regionForm.subCode">
<template #prepend>{{ regionForm.parentCode }}</template>
</el-input>
</template>
@@ -92,10 +109,12 @@ import { getToken } from '@/utils/auth';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
const ROOT_PARENT_CODE = '0';
export default {
data() {
return {
topCode: '00',
topCode: ROOT_PARENT_CODE,
treeCode: '',
treeParentCode: '',
treeData: [],
@@ -104,7 +123,7 @@ export default {
nodeKey: 'id',
lazy: true,
treeLoad: function (node, resolve) {
const parentCode = node.level === 0 ? '00' : node.data.id;
const parentCode = node.level === 0 ? ROOT_PARENT_CODE : node.data.id;
getLazyTree(parentCode).then(res => {
resolve(
res.data.data.map(item => {
@@ -323,7 +342,11 @@ export default {
},
watch: {
'regionForm.subCode'() {
this.regionForm.code = this.regionForm.parentCode + this.regionForm.subCode;
if (this.isCountryRegion) {
return;
}
const parentCode = this.isProvinceRegion ? '' : this.regionForm.parentCode;
this.regionForm.code = parentCode + this.regionForm.subCode;
},
'excelForm.isCovered'() {
if (this.excelForm.isCovered !== '') {
@@ -334,6 +357,12 @@ export default {
},
computed: {
...mapGetters(['permission']),
isCountryRegion() {
return Number(this.regionForm.regionLevel) === 0 || this.regionForm.parentCode === this.topCode;
},
isProvinceRegion() {
return Number(this.regionForm.regionLevel) === 1;
},
permissionList() {
return {
addBtn: this.validData(this.permission.region_add, false),
@@ -369,9 +398,27 @@ export default {
this.treeParentCode = data.parentId;
getDetail(this.treeCode).then(res => {
this.regionForm = res.data.data;
this.regionForm.subCode = this.regionForm.code.replace(this.regionForm.parentCode, '');
this.regionForm.subCode =
this.regionForm.parentCode === this.topCode
? this.regionForm.code
: this.regionForm.code.replace(this.regionForm.parentCode, '');
});
},
addCountry() {
const column = this.findColumn(this.regionOption.column, 'parentCode');
column.disabled = true;
this.treeCode = '';
this.treeParentCode = this.topCode;
this.regionForm = {
parentCode: this.topCode,
parentName: '根节点',
code: '',
subCode: '',
name: '',
regionLevel: 0,
sort: 1,
};
},
addChildren() {
if (validatenull(this.regionForm.code) || validatenull(this.regionForm.name)) {
this.$message.warning('请先选择一项区划');
@@ -386,8 +433,14 @@ export default {
this.regionForm.regionLevel === 5 ? 5 : this.regionForm.regionLevel + 1;
},
handleSubmit(form, done) {
const parentCode = form.parentCode === this.topCode ? '' : form.parentCode;
form.code = parentCode + form.subCode;
if (Number(form.regionLevel) === 0) {
form.parentCode = this.topCode;
form.ancestors = this.topCode;
form.subCode = form.code;
} else {
const parentCode = Number(form.regionLevel) === 1 ? '' : form.parentCode;
form.code = parentCode + form.subCode;
}
submit(form).then(
() => {
this.$message({