fix bug
This commit is contained in:
@@ -72,7 +72,7 @@
|
||||
v-for="(item, index) in apiPathList"
|
||||
:key="index"
|
||||
:gutter="8"
|
||||
style="margin-bottom: 8px"
|
||||
style="margin-bottom: 16px"
|
||||
>
|
||||
<el-col :span="22">
|
||||
<el-input
|
||||
@@ -106,7 +106,7 @@
|
||||
v-for="(item, index) in extParamsList"
|
||||
:key="index"
|
||||
:gutter="8"
|
||||
style="margin-bottom: 8px"
|
||||
style="margin-bottom: 16px"
|
||||
>
|
||||
<el-col :span="8">
|
||||
<el-input v-model="item.key" placeholder="参数名" :disabled="type === 'view'" />
|
||||
@@ -330,7 +330,10 @@ export default {
|
||||
menuWidth: 350,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
@@ -493,7 +496,10 @@ export default {
|
||||
tip: false,
|
||||
header: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -157,13 +157,16 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
selection: true,
|
||||
labelWidth: 120,
|
||||
searchLabelWidth: 120,
|
||||
labelWidth: 'auto',
|
||||
searchLabelWidth: 160,
|
||||
menuWidth: 250,
|
||||
dialogWidth: 900,
|
||||
dialogClickModal: false,
|
||||
@@ -263,7 +266,10 @@ export default {
|
||||
tip: false,
|
||||
simplePage: true,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
tree: true,
|
||||
border: true,
|
||||
index: true,
|
||||
@@ -324,12 +330,15 @@ export default {
|
||||
optionScope: {
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
selection: true,
|
||||
labelWidth: 120,
|
||||
labelWidth: 'auto',
|
||||
menuWidth: 250,
|
||||
dialogWidth: 900,
|
||||
dialogClickModal: false,
|
||||
|
||||
@@ -158,13 +158,16 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
selection: true,
|
||||
labelWidth: 120,
|
||||
searchLabelWidth: 120,
|
||||
labelWidth: 'auto',
|
||||
searchLabelWidth: 160,
|
||||
menuWidth: 250,
|
||||
dialogWidth: 900,
|
||||
dialogClickModal: false,
|
||||
@@ -300,7 +303,10 @@ export default {
|
||||
tip: false,
|
||||
simplePage: true,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
tree: true,
|
||||
border: true,
|
||||
index: true,
|
||||
@@ -363,12 +369,15 @@ export default {
|
||||
optionScope: {
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
selection: true,
|
||||
labelWidth: 120,
|
||||
labelWidth: 'auto',
|
||||
menuWidth: 250,
|
||||
dialogWidth: 900,
|
||||
dialogClickModal: false,
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
v-for="(item, index) in limitPatternList"
|
||||
:key="index"
|
||||
:gutter="8"
|
||||
style="margin-bottom: 8px"
|
||||
style="margin-bottom: 16px"
|
||||
>
|
||||
<el-col :span="22">
|
||||
<el-input
|
||||
@@ -208,9 +208,12 @@ export default {
|
||||
dialogWidth: 700,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
labelWidth: 110,
|
||||
searchLabelWidth: 90,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
labelWidth: 'auto',
|
||||
searchLabelWidth: 160,
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
@@ -360,7 +363,10 @@ export default {
|
||||
tip: false,
|
||||
header: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -242,14 +242,17 @@ export default {
|
||||
tip: false,
|
||||
simplePage: true,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
tree: true,
|
||||
border: true,
|
||||
index: true,
|
||||
selection: true,
|
||||
viewBtn: true,
|
||||
labelWidth: 120,
|
||||
searchLabelWidth: 120,
|
||||
labelWidth: 'auto',
|
||||
searchLabelWidth: 160,
|
||||
menuWidth: 350,
|
||||
dialogWidth: 600,
|
||||
dialogClickModal: false,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -89,8 +89,9 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchIndex: 3,
|
||||
searchMenuSpan: 24,
|
||||
searchMenuPosition: 'right',
|
||||
searchIndex: 8,
|
||||
searchIcon: true,
|
||||
border: true,
|
||||
index: true,
|
||||
@@ -99,7 +100,7 @@ export default {
|
||||
addBtn: false,
|
||||
delBtn: false,
|
||||
menuWidth: 120,
|
||||
labelWidth: 120,
|
||||
labelWidth: 'auto',
|
||||
dialogType: 'drawer',
|
||||
column: [
|
||||
{
|
||||
|
||||
@@ -59,7 +59,10 @@ const option = reactive({
|
||||
dialogWidth: 950,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -60,7 +60,10 @@ export default {
|
||||
dialogWidth: 950,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -24,7 +24,7 @@ export default {
|
||||
file: {},
|
||||
},
|
||||
option: {
|
||||
labelWidth: 120,
|
||||
labelWidth: 'auto',
|
||||
menuBtn: false,
|
||||
column: [
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</template>
|
||||
</avue-crud>
|
||||
<el-dialog title="流程删除" append-to-body v-model="followBox" width="20%">
|
||||
<el-form :model="form" ref="form" label-width="80px">
|
||||
<el-form :model="form" ref="form" label-width="auto">
|
||||
<el-form-item label="删除理由">
|
||||
<el-input v-model="deleteReason" placeholder="请输入删除理由" />
|
||||
</el-form-item>
|
||||
@@ -62,7 +62,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
selection: true,
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog title="流程变更" append-to-body v-model="stateBox" width="20%">
|
||||
<el-form :model="form" ref="form" label-width="80px">
|
||||
<el-form :model="form" ref="form" label-width="auto">
|
||||
<el-form-item label="流程状态">
|
||||
<el-select v-model="flowState" placeholder="请选择" value="">
|
||||
<el-option
|
||||
@@ -150,7 +150,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
selection: true,
|
||||
|
||||
@@ -207,7 +207,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
selection: true,
|
||||
|
||||
@@ -41,7 +41,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -41,7 +41,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -41,7 +41,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -69,7 +69,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
selection: true,
|
||||
|
||||
@@ -108,7 +108,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -86,14 +86,17 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
selection: true,
|
||||
grid: true,
|
||||
menuWidth: 350,
|
||||
labelWidth: 100,
|
||||
labelWidth: 'auto',
|
||||
dialogWidth: 880,
|
||||
dialogClickModal: false,
|
||||
column: [
|
||||
@@ -103,7 +106,7 @@ export default {
|
||||
value: 1,
|
||||
span: 24,
|
||||
width: 120,
|
||||
searchLabelWidth: 50,
|
||||
searchLabelWidth: 160,
|
||||
row: true,
|
||||
dicUrl: '/blade-system/dict/dictionary?code=oss',
|
||||
props: {
|
||||
|
||||
@@ -86,14 +86,17 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
selection: true,
|
||||
grid: true,
|
||||
menuWidth: 350,
|
||||
labelWidth: 100,
|
||||
labelWidth: 'auto',
|
||||
dialogWidth: 880,
|
||||
dialogClickModal: false,
|
||||
column: [
|
||||
@@ -103,7 +106,7 @@ export default {
|
||||
value: 1,
|
||||
span: 24,
|
||||
width: 100,
|
||||
searchLabelWidth: 50,
|
||||
searchLabelWidth: 160,
|
||||
row: true,
|
||||
dicUrl: '/blade-system/dict/dictionary?code=sms',
|
||||
props: {
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
|
||||
<!-- 手动锁定用户 -->
|
||||
<el-dialog title="锁定用户" append-to-body v-model="lockUserBox" width="500px">
|
||||
<el-form :model="lockUserForm" label-width="100px" :rules="lockUserRules" ref="lockUserFormRef">
|
||||
<el-form :model="lockUserForm" label-width="auto" :rules="lockUserRules" ref="lockUserFormRef">
|
||||
<el-form-item label="用户账号">
|
||||
<el-input :model-value="lockUserForm.account" disabled />
|
||||
</el-form-item>
|
||||
@@ -108,7 +108,7 @@
|
||||
|
||||
<!-- 解锁原因确认 -->
|
||||
<el-dialog title="解锁确认" append-to-body v-model="unlockReasonBox" width="450px">
|
||||
<el-form :model="unlockReasonForm" label-width="80px">
|
||||
<el-form :model="unlockReasonForm" label-width="auto">
|
||||
<el-form-item label="解锁原因">
|
||||
<el-input
|
||||
v-model="unlockReasonForm.unlockReason"
|
||||
|
||||
@@ -55,7 +55,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -73,7 +73,10 @@ export default {
|
||||
tip: false,
|
||||
simplePage: true,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
tree: true,
|
||||
border: true,
|
||||
index: true,
|
||||
|
||||
@@ -79,7 +79,10 @@ export default {
|
||||
tip: false,
|
||||
simplePage: true,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
dialogWidth: '60%',
|
||||
tree: true,
|
||||
border: true,
|
||||
@@ -137,13 +140,6 @@ export default {
|
||||
type: 'icon',
|
||||
slot: true,
|
||||
iconList: iconList,
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入菜单图标',
|
||||
trigger: 'click',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '菜单编号',
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
:before-close="beforeClose"
|
||||
append-to-body
|
||||
>
|
||||
<el-form :disabled="view" ref="form" :model="form" label-width="80px">
|
||||
<el-form :disabled="view" ref="form" :model="form" label-width="auto">
|
||||
<!-- 表单字段 -->
|
||||
<el-form-item label="参数名:" prop="paramName">
|
||||
<el-input v-model="form.paramName" placeholder="请输入参数名" />
|
||||
|
||||
@@ -59,7 +59,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -231,7 +231,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
selection: true,
|
||||
|
||||
@@ -55,7 +55,10 @@ export default {
|
||||
dialogWidth: 900,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
@@ -84,7 +87,7 @@ export default {
|
||||
value: 1,
|
||||
span: 24,
|
||||
width: 120,
|
||||
searchLabelWidth: 100,
|
||||
searchLabelWidth: 160,
|
||||
row: true,
|
||||
gridRow: true,
|
||||
dicUrl: '/blade-system/dict/dictionary?code=datasource_category',
|
||||
|
||||
@@ -90,7 +90,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -165,7 +165,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
|
||||
@@ -275,7 +275,7 @@
|
||||
ref="passwordFormRef"
|
||||
:model="passwordForm"
|
||||
:rules="passwordRules"
|
||||
label-width="90px"
|
||||
label-width="auto"
|
||||
>
|
||||
<el-form-item label="登录账号">
|
||||
<el-input v-model="passwordForm.account" disabled />
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
||||
<!-- 个人信息 Tab -->
|
||||
<el-tab-pane label="个人信息" name="info">
|
||||
<el-form ref="infoForm" :model="infoForm" label-width="100px">
|
||||
<el-form ref="infoForm" :model="infoForm" label-width="auto">
|
||||
<el-form-item label="头像">
|
||||
<div class="avatar-upload-container">
|
||||
<div class="avatar-wrapper" v-if="infoForm.avatar">
|
||||
@@ -74,7 +74,7 @@
|
||||
|
||||
<!-- 修改密码 Tab -->
|
||||
<el-tab-pane label="修改密码" name="password">
|
||||
<el-form ref="passwordForm" :model="passwordForm" label-width="100px">
|
||||
<el-form ref="passwordForm" :model="passwordForm" label-width="auto">
|
||||
<el-form-item label="原密码">
|
||||
<el-input
|
||||
v-model="passwordForm.oldPassword"
|
||||
|
||||
@@ -57,7 +57,10 @@ export default {
|
||||
dialogWidth: 900,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
@@ -86,7 +89,7 @@ export default {
|
||||
value: 1,
|
||||
span: 24,
|
||||
width: 120,
|
||||
searchLabelWidth: 100,
|
||||
searchLabelWidth: 160,
|
||||
row: true,
|
||||
gridRow: true,
|
||||
display: false,
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
ref="driverForm"
|
||||
:model="driverForm"
|
||||
:rules="formRules"
|
||||
label-position="top"
|
||||
label-position="right"
|
||||
:disabled="readonly"
|
||||
class="driver-form"
|
||||
>
|
||||
@@ -156,13 +156,22 @@
|
||||
<el-col :span="4">
|
||||
<el-form-item label="学历" prop="education">
|
||||
<el-select v-model="driverForm.education" clearable filterable>
|
||||
<el-option v-for="item in educationOptions" :key="item" :label="item" :value="item" />
|
||||
<el-option
|
||||
v-for="item in educationOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="住址" prop="addressRegion">
|
||||
<el-input v-model="driverForm.addressRegion" maxlength="100" placeholder="省 / 市 / 区" />
|
||||
<el-input
|
||||
v-model="driverForm.addressRegion"
|
||||
maxlength="100"
|
||||
placeholder="省 / 市 / 区"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
@@ -223,8 +232,19 @@
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="准驾车型" prop="drivingType">
|
||||
<el-select v-model="driverForm.drivingType" clearable filterable allow-create default-first-option>
|
||||
<el-option v-for="item in drivingTypeOptions" :key="item" :label="item" :value="item" />
|
||||
<el-select
|
||||
v-model="driverForm.drivingType"
|
||||
clearable
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
>
|
||||
<el-option
|
||||
v-for="item in drivingTypeOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -254,7 +274,11 @@
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label="长期有效" prop="drivingLicenseLongTerm">
|
||||
<el-checkbox v-model="driverForm.drivingLicenseLongTerm" :true-label="1" :false-label="0">
|
||||
<el-checkbox
|
||||
v-model="driverForm.drivingLicenseLongTerm"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
>
|
||||
是
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
@@ -287,7 +311,13 @@
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="从业资格证类型" prop="qualificationType">
|
||||
<el-select v-model="driverForm.qualificationType" clearable filterable allow-create default-first-option>
|
||||
<el-select
|
||||
v-model="driverForm.qualificationType"
|
||||
clearable
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
>
|
||||
<el-option label="道路运输从业资格证" value="道路运输从业资格证" />
|
||||
<el-option label="危险货物运输从业资格证" value="危险货物运输从业资格证" />
|
||||
</el-select>
|
||||
@@ -295,7 +325,11 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="资格证号" prop="qualificationNo">
|
||||
<el-input v-model="driverForm.qualificationNo" maxlength="50" placeholder="默认身份证号" />
|
||||
<el-input
|
||||
v-model="driverForm.qualificationNo"
|
||||
maxlength="50"
|
||||
placeholder="默认身份证号"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
@@ -310,7 +344,11 @@
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label="长期有效" prop="qualificationLongTerm">
|
||||
<el-checkbox v-model="driverForm.qualificationLongTerm" :true-label="1" :false-label="0">
|
||||
<el-checkbox
|
||||
v-model="driverForm.qualificationLongTerm"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
>
|
||||
是
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
@@ -366,19 +404,42 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="与联系人关系" prop="contactRelation">
|
||||
<el-select v-model="driverForm.contactRelation" clearable filterable allow-create default-first-option>
|
||||
<el-option v-for="item in relationOptions" :key="item" :label="item" :value="item" />
|
||||
<el-select
|
||||
v-model="driverForm.contactRelation"
|
||||
clearable
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
>
|
||||
<el-option
|
||||
v-for="item in relationOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="所属组织" prop="organizationName">
|
||||
<el-input v-model="driverForm.organizationName" maxlength="50" />
|
||||
<el-cascader
|
||||
v-model="driverForm.organizationName"
|
||||
:options="deptCascaderOptions"
|
||||
:props="deptCascaderProps"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="driverForm.remark" type="textarea" maxlength="200" show-word-limit />
|
||||
<el-input
|
||||
v-model="driverForm.remark"
|
||||
type="textarea"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -397,7 +458,15 @@
|
||||
import { mapGetters } from 'vuex';
|
||||
import NProgress from 'nprogress';
|
||||
import { option } from '@/option/transportCapacity/driver';
|
||||
import { getList, getDetail, submit, remove, changeStatus, getExpiryStat } from '@/api/transportCapacity/driver';
|
||||
import {
|
||||
getList,
|
||||
getDetail,
|
||||
submit,
|
||||
remove,
|
||||
changeStatus,
|
||||
getExpiryStat,
|
||||
} from '@/api/transportCapacity/driver';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
@@ -528,16 +597,30 @@ export default {
|
||||
educationOptions: ['初中', '高中', '中专', '大专', '本科', '硕士及以上'],
|
||||
drivingTypeOptions: ['A1', 'A2', 'A3', 'B1', 'B2', 'C1', 'C2'],
|
||||
relationOptions: ['父母', '配偶', '子女', '兄弟姐妹', '朋友', '同事'],
|
||||
deptCascaderOptions: [],
|
||||
deptCascaderProps: {
|
||||
label: 'label',
|
||||
value: 'value',
|
||||
children: 'children',
|
||||
checkStrictly: true,
|
||||
emitPath: false,
|
||||
},
|
||||
formRules: {
|
||||
driverName: [{ required: true, message: '请输入司机姓名', trigger: 'blur' }],
|
||||
idCardNo: [{ required: true, message: '请输入身份证号', trigger: 'blur' }],
|
||||
drivingType: [{ required: true, message: '请选择准驾车型', trigger: 'change' }],
|
||||
drivingLicenseEndDate: [{ validator: this.validateDrivingLicenseEndDate, trigger: 'change' }],
|
||||
drivingLicenseEndDate: [
|
||||
{ validator: this.validateDrivingLicenseEndDate, trigger: 'change' },
|
||||
],
|
||||
driverType: [{ required: true, message: '请选择司机类型', trigger: 'change' }],
|
||||
mobile: [{ required: true, message: '请输入手机号', trigger: 'blur' }],
|
||||
emergencyContactName: [{ required: true, message: '请输入紧急联系人姓名', trigger: 'blur' }],
|
||||
emergencyContactMobile: [{ required: true, message: '请输入紧急联系人手机号', trigger: 'blur' }],
|
||||
organizationName: [{ required: true, message: '请输入所属组织', trigger: 'blur' }],
|
||||
emergencyContactName: [
|
||||
{ required: true, message: '请输入紧急联系人姓名', trigger: 'blur' },
|
||||
],
|
||||
emergencyContactMobile: [
|
||||
{ required: true, message: '请输入紧急联系人手机号', trigger: 'blur' },
|
||||
],
|
||||
organizationName: [{ required: true, message: '请选择所属组织', trigger: 'change' }],
|
||||
idCardFront: [{ required: true, message: '请上传身份证正面照', trigger: 'change' }],
|
||||
idCardBack: [{ required: true, message: '请上传身份证反面照', trigger: 'change' }],
|
||||
drivingLicenseFront: [{ required: true, message: '请上传驾驶证主页', trigger: 'change' }],
|
||||
@@ -567,10 +650,33 @@ export default {
|
||||
return this.driverForm.id ? '修改司机' : '新增司机';
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.initDeptTree();
|
||||
},
|
||||
methods: {
|
||||
hasPermission(code) {
|
||||
return this.isAdmin || this.permission?.[code] === true;
|
||||
},
|
||||
initDeptTree() {
|
||||
getDeptTree(this.userInfo.tenantId).then(res => {
|
||||
this.deptCascaderOptions = this.formatDeptCascaderOptions(res.data.data || []);
|
||||
const column = this.findColumn(this.option.column, 'organizationName');
|
||||
column.dicData = this.deptCascaderOptions;
|
||||
});
|
||||
},
|
||||
formatDeptCascaderOptions(tree = []) {
|
||||
return tree.map(item => {
|
||||
const label = item.title || item.deptName || item.name;
|
||||
const option = {
|
||||
label,
|
||||
value: label,
|
||||
};
|
||||
if (item.children && item.children.length) {
|
||||
option.children = this.formatDeptCascaderOptions(item.children);
|
||||
}
|
||||
return option;
|
||||
});
|
||||
},
|
||||
validateDrivingLicenseEndDate(rule, value, callback) {
|
||||
if (this.driverForm.drivingLicenseLongTerm !== 1 && !value) {
|
||||
callback(new Error('请选择驾驶证有效期止'));
|
||||
@@ -720,6 +826,9 @@ export default {
|
||||
...params,
|
||||
...this.searchForm,
|
||||
};
|
||||
if (Array.isArray(query.organizationName)) {
|
||||
query.organizationName = query.organizationName[query.organizationName.length - 1] || '';
|
||||
}
|
||||
if (includeExpire && this.query.expireStatus) {
|
||||
query.expireStatus = this.query.expireStatus;
|
||||
}
|
||||
|
||||
@@ -2,13 +2,31 @@
|
||||
<basic-container class="transport-ship-page">
|
||||
<div class="ship-toolbar">
|
||||
<div class="ship-toolbar__actions">
|
||||
<el-button type="primary" icon="el-icon-plus" plain v-if="hasPermission('transport_ship_add')" @click="openShip()">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('transport_ship_add')"
|
||||
@click="openShip()"
|
||||
>
|
||||
新增
|
||||
</el-button>
|
||||
<el-button type="primary" icon="el-icon-download" plain v-if="hasPermission('transport_ship_export')" @click="handleExport">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-download"
|
||||
plain
|
||||
v-if="hasPermission('transport_ship_export')"
|
||||
@click="handleExport"
|
||||
>
|
||||
导出
|
||||
</el-button>
|
||||
<el-button type="danger" icon="el-icon-delete" plain v-if="hasPermission('transport_ship_delete')" @click="handleDelete">
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
plain
|
||||
v-if="hasPermission('transport_ship_delete')"
|
||||
@click="handleDelete"
|
||||
>
|
||||
批量删除
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -56,7 +74,11 @@
|
||||
</span>
|
||||
</template>
|
||||
<template #businessTransportCertEndDate="{ row }">
|
||||
<span :class="getDateClass(row, 'businessTransportCertEndDate', 'businessTransportCertLongTerm')">
|
||||
<span
|
||||
:class="
|
||||
getDateClass(row, 'businessTransportCertEndDate', 'businessTransportCertLongTerm')
|
||||
"
|
||||
>
|
||||
{{ formatEndDate(row.businessTransportCertEndDate, row.businessTransportCertLongTerm) }}
|
||||
</span>
|
||||
</template>
|
||||
@@ -66,10 +88,22 @@
|
||||
</span>
|
||||
</template>
|
||||
<template #menu="{ row }">
|
||||
<el-button type="primary" text icon="el-icon-edit" v-if="hasPermission('transport_ship_edit')" @click="openShip(row)">
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
icon="el-icon-edit"
|
||||
v-if="hasPermission('transport_ship_edit')"
|
||||
@click="openShip(row)"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
<el-button type="primary" text icon="el-icon-view" v-if="hasPermission('transport_ship_view')" @click="openShip(row, true)">
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
icon="el-icon-view"
|
||||
v-if="hasPermission('transport_ship_view')"
|
||||
@click="openShip(row, true)"
|
||||
>
|
||||
综合台账
|
||||
</el-button>
|
||||
<el-button
|
||||
@@ -84,8 +118,22 @@
|
||||
</template>
|
||||
</avue-crud>
|
||||
|
||||
<el-dialog :title="dialogTitle" append-to-body v-model="shipBox" width="92%" top="4vh" @closed="resetShip">
|
||||
<el-form ref="shipForm" :model="shipForm" :rules="formRules" label-position="top" :disabled="readonly" class="ship-form">
|
||||
<el-dialog
|
||||
:title="dialogTitle"
|
||||
append-to-body
|
||||
v-model="shipBox"
|
||||
width="92%"
|
||||
top="4vh"
|
||||
@closed="resetShip"
|
||||
>
|
||||
<el-form
|
||||
ref="shipForm"
|
||||
:model="shipForm"
|
||||
:rules="formRules"
|
||||
label-position="right"
|
||||
:disabled="readonly"
|
||||
class="ship-form"
|
||||
>
|
||||
<div class="section-title">基础船舶信息</div>
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="6">
|
||||
@@ -95,7 +143,14 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="船舶识别号" prop="shipIdentifierNo">
|
||||
<el-input v-model="shipForm.shipIdentifierNo" maxlength="50" show-word-limit @input="shipForm.shipIdentifierNo = String(shipForm.shipIdentifierNo || '').toUpperCase()" />
|
||||
<el-input
|
||||
v-model="shipForm.shipIdentifierNo"
|
||||
maxlength="50"
|
||||
show-word-limit
|
||||
@input="
|
||||
shipForm.shipIdentifierNo = String(shipForm.shipIdentifierNo || '').toUpperCase()
|
||||
"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
@@ -111,7 +166,12 @@
|
||||
<el-col :span="6">
|
||||
<el-form-item label="船舶类型" prop="shipType">
|
||||
<el-select v-model="shipForm.shipType" filterable allow-create default-first-option>
|
||||
<el-option v-for="item in shipTypeOptions" :key="item" :label="item" :value="item" />
|
||||
<el-option
|
||||
v-for="item in shipTypeOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -134,16 +194,34 @@
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="国籍证有效期至" prop="nationalityCertEndDate">
|
||||
<el-date-picker v-model="shipForm.nationalityCertEndDate" type="date" value-format="YYYY-MM-DD" :disabled="shipForm.nationalityCertLongTerm === 1" />
|
||||
<el-date-picker
|
||||
v-model="shipForm.nationalityCertEndDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
:disabled="shipForm.nationalityCertLongTerm === 1"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label="长期有效" prop="nationalityCertLongTerm">
|
||||
<el-checkbox v-model="shipForm.nationalityCertLongTerm" :true-label="1" :false-label="0">是</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="shipForm.nationalityCertLongTerm"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
>是</el-checkbox
|
||||
>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<image-upload-field label="国籍证图片" prop="nationalityCertImage" :value="shipForm.nationalityCertImage" :readonly="readonly" :headers="uploadHeaders" large @success="url => setImage('nationalityCertImage', url)" />
|
||||
<image-upload-field
|
||||
label="国籍证图片"
|
||||
prop="nationalityCertImage"
|
||||
:value="shipForm.nationalityCertImage"
|
||||
:readonly="readonly"
|
||||
:headers="uploadHeaders"
|
||||
large
|
||||
@success="url => setImage('nationalityCertImage', url)"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -151,16 +229,34 @@
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="最低安全配员证书有效期至" prop="safeManningCertEndDate">
|
||||
<el-date-picker v-model="shipForm.safeManningCertEndDate" type="date" value-format="YYYY-MM-DD" :disabled="shipForm.safeManningCertLongTerm === 1" />
|
||||
<el-date-picker
|
||||
v-model="shipForm.safeManningCertEndDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
:disabled="shipForm.safeManningCertLongTerm === 1"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label="长期有效" prop="safeManningCertLongTerm">
|
||||
<el-checkbox v-model="shipForm.safeManningCertLongTerm" :true-label="1" :false-label="0">是</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="shipForm.safeManningCertLongTerm"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
>是</el-checkbox
|
||||
>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<image-upload-field label="最低安全配员证书图片" prop="safeManningCertImage" :value="shipForm.safeManningCertImage" :readonly="readonly" :headers="uploadHeaders" large @success="url => setImage('safeManningCertImage', url)" />
|
||||
<image-upload-field
|
||||
label="最低安全配员证书图片"
|
||||
prop="safeManningCertImage"
|
||||
:value="shipForm.safeManningCertImage"
|
||||
:readonly="readonly"
|
||||
:headers="uploadHeaders"
|
||||
large
|
||||
@success="url => setImage('safeManningCertImage', url)"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -168,16 +264,34 @@
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="营业运输证有效期至" prop="businessTransportCertEndDate">
|
||||
<el-date-picker v-model="shipForm.businessTransportCertEndDate" type="date" value-format="YYYY-MM-DD" :disabled="shipForm.businessTransportCertLongTerm === 1" />
|
||||
<el-date-picker
|
||||
v-model="shipForm.businessTransportCertEndDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
:disabled="shipForm.businessTransportCertLongTerm === 1"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label="长期有效" prop="businessTransportCertLongTerm">
|
||||
<el-checkbox v-model="shipForm.businessTransportCertLongTerm" :true-label="1" :false-label="0">是</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="shipForm.businessTransportCertLongTerm"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
>是</el-checkbox
|
||||
>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<image-upload-field label="营业运输证图片" prop="businessTransportCertImage" :value="shipForm.businessTransportCertImage" :readonly="readonly" :headers="uploadHeaders" large @success="url => setImage('businessTransportCertImage', url)" />
|
||||
<image-upload-field
|
||||
label="营业运输证图片"
|
||||
prop="businessTransportCertImage"
|
||||
:value="shipForm.businessTransportCertImage"
|
||||
:readonly="readonly"
|
||||
:headers="uploadHeaders"
|
||||
large
|
||||
@success="url => setImage('businessTransportCertImage', url)"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -185,22 +299,39 @@
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="承租有效期至" prop="leaseEndDate">
|
||||
<el-date-picker v-model="shipForm.leaseEndDate" type="date" value-format="YYYY-MM-DD" :disabled="shipForm.leaseLongTerm === 1" />
|
||||
<el-date-picker
|
||||
v-model="shipForm.leaseEndDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
:disabled="shipForm.leaseLongTerm === 1"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label="长期有效" prop="leaseLongTerm">
|
||||
<el-checkbox v-model="shipForm.leaseLongTerm" :true-label="1" :false-label="0">是</el-checkbox>
|
||||
<el-checkbox v-model="shipForm.leaseLongTerm" :true-label="1" :false-label="0"
|
||||
>是</el-checkbox
|
||||
>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<image-upload-field label="承租合同图片" prop="leaseContractImage" :value="shipForm.leaseContractImage" :readonly="readonly" :headers="uploadHeaders" large @success="url => setImage('leaseContractImage', url)" />
|
||||
<image-upload-field
|
||||
label="承租合同图片"
|
||||
prop="leaseContractImage"
|
||||
:value="shipForm.leaseContractImage"
|
||||
:readonly="readonly"
|
||||
:headers="uploadHeaders"
|
||||
large
|
||||
@success="url => setImage('leaseContractImage', url)"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="shipBox = false">取消</el-button>
|
||||
<el-button type="primary" v-if="!readonly" :loading="submitLoading" @click="handleSubmit">确定</el-button>
|
||||
<el-button type="primary" v-if="!readonly" :loading="submitLoading" @click="handleSubmit"
|
||||
>确定</el-button
|
||||
>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</basic-container>
|
||||
@@ -210,7 +341,14 @@
|
||||
import { mapGetters } from 'vuex';
|
||||
import NProgress from 'nprogress';
|
||||
import { option } from '@/option/transportCapacity/transport-ship';
|
||||
import { getList, getDetail, submit, remove, changeStatus, getExpiryStat } from '@/api/transportCapacity/transport-ship';
|
||||
import {
|
||||
getList,
|
||||
getDetail,
|
||||
submit,
|
||||
remove,
|
||||
changeStatus,
|
||||
getExpiryStat,
|
||||
} from '@/api/transportCapacity/transport-ship';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
@@ -313,9 +451,15 @@ export default {
|
||||
shipIdentifierNo: [{ required: true, message: '请输入船舶识别号', trigger: 'blur' }],
|
||||
organizationName: [{ required: true, message: '请输入所属组织', trigger: 'blur' }],
|
||||
shipType: [{ required: true, message: '请选择船舶类型', trigger: 'change' }],
|
||||
nationalityCertEndDate: [{ validator: this.validateNationalityCertEndDate, trigger: 'change' }],
|
||||
safeManningCertEndDate: [{ validator: this.validateSafeManningCertEndDate, trigger: 'change' }],
|
||||
businessTransportCertEndDate: [{ validator: this.validateBusinessTransportCertEndDate, trigger: 'change' }],
|
||||
nationalityCertEndDate: [
|
||||
{ validator: this.validateNationalityCertEndDate, trigger: 'change' },
|
||||
],
|
||||
safeManningCertEndDate: [
|
||||
{ validator: this.validateSafeManningCertEndDate, trigger: 'change' },
|
||||
],
|
||||
businessTransportCertEndDate: [
|
||||
{ validator: this.validateBusinessTransportCertEndDate, trigger: 'change' },
|
||||
],
|
||||
remark: [{ max: 200, message: '备注最多200字', trigger: 'blur' }],
|
||||
},
|
||||
};
|
||||
@@ -344,15 +488,18 @@ export default {
|
||||
return this.isAdmin || this.permission?.[code] === true;
|
||||
},
|
||||
validateNationalityCertEndDate(rule, value, callback) {
|
||||
if (this.shipForm.nationalityCertLongTerm !== 1 && !value) return callback(new Error('请选择国籍证有效期至'));
|
||||
if (this.shipForm.nationalityCertLongTerm !== 1 && !value)
|
||||
return callback(new Error('请选择国籍证有效期至'));
|
||||
callback();
|
||||
},
|
||||
validateSafeManningCertEndDate(rule, value, callback) {
|
||||
if (this.shipForm.safeManningCertLongTerm !== 1 && !value) return callback(new Error('请选择最低安全配员证书有效期至'));
|
||||
if (this.shipForm.safeManningCertLongTerm !== 1 && !value)
|
||||
return callback(new Error('请选择最低安全配员证书有效期至'));
|
||||
callback();
|
||||
},
|
||||
validateBusinessTransportCertEndDate(rule, value, callback) {
|
||||
if (this.shipForm.businessTransportCertLongTerm !== 1 && !value) return callback(new Error('请选择营业运输证有效期至'));
|
||||
if (this.shipForm.businessTransportCertLongTerm !== 1 && !value)
|
||||
return callback(new Error('请选择营业运输证有效期至'));
|
||||
callback();
|
||||
},
|
||||
openShip(row, readonly = false) {
|
||||
@@ -395,7 +542,11 @@ export default {
|
||||
handleStatus(row) {
|
||||
const status = row.status === 1 ? 2 : 1;
|
||||
const text = status === 1 ? '启用' : '停用';
|
||||
this.$confirm(`是否${text}该船舶?`, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
this.$confirm(`是否${text}该船舶?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
changeStatus(row.id, status).then(() => {
|
||||
this.$message.success('操作成功');
|
||||
this.onLoad(this.page);
|
||||
@@ -407,7 +558,11 @@ export default {
|
||||
this.$message.warning('请选择至少一条数据');
|
||||
return;
|
||||
}
|
||||
this.$confirm('是否删除选中的船舶数据?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
this.$confirm('是否删除选中的船舶数据?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
remove(this.ids).then(() => {
|
||||
this.$message.success('操作成功');
|
||||
this.onLoad(this.page);
|
||||
@@ -476,9 +631,16 @@ export default {
|
||||
return query;
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出船舶数据?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||
this.$confirm('是否导出船舶数据?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-transport/transport-ship/export-transport-ship', this.buildExportParams())
|
||||
exportBlob(
|
||||
'/blade-transport/transport-ship/export-transport-ship',
|
||||
this.buildExportParams()
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `船舶管理${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
|
||||
@@ -27,7 +27,11 @@
|
||||
>批量删除
|
||||
</el-button>
|
||||
</div>
|
||||
<el-radio-group v-model="query.expireStatus" class="vehicle-stat" @change="handleExpireChange">
|
||||
<el-radio-group
|
||||
v-model="query.expireStatus"
|
||||
class="vehicle-stat"
|
||||
@change="handleExpireChange"
|
||||
>
|
||||
<el-radio-button label="">全部({{ expiryStat.total }})</el-radio-button>
|
||||
<el-radio-button label="within30">30天内到期({{ expiryStat.within30 }})</el-radio-button>
|
||||
<el-radio-button label="expired">已到期({{ expiryStat.expired }})</el-radio-button>
|
||||
@@ -119,7 +123,7 @@
|
||||
ref="vehicleForm"
|
||||
:model="vehicleForm"
|
||||
:rules="formRules"
|
||||
label-position="top"
|
||||
label-position="right"
|
||||
:disabled="readonly"
|
||||
class="vehicle-form"
|
||||
>
|
||||
@@ -142,33 +146,68 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="车辆类型" prop="vehicleType">
|
||||
<el-select v-model="vehicleForm.vehicleType" filterable allow-create default-first-option>
|
||||
<el-option v-for="item in vehicleTypeOptions" :key="item" :label="item" :value="item" />
|
||||
<el-select
|
||||
v-model="vehicleForm.vehicleType"
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
>
|
||||
<el-option
|
||||
v-for="item in vehicleTypeOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="业务关系" prop="businessRelation">
|
||||
<el-select v-model="vehicleForm.businessRelation">
|
||||
<el-option v-for="item in businessRelationOptions" :key="item" :label="item" :value="item" />
|
||||
<el-option
|
||||
v-for="item in businessRelationOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="能源类型" prop="energyType">
|
||||
<el-select v-model="vehicleForm.energyType" filterable allow-create default-first-option>
|
||||
<el-option v-for="item in energyTypeOptions" :key="item" :label="item" :value="item" />
|
||||
<el-select
|
||||
v-model="vehicleForm.energyType"
|
||||
filterable
|
||||
allow-create
|
||||
default-first-option
|
||||
>
|
||||
<el-option
|
||||
v-for="item in energyTypeOptions"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="核定载质量(KG)" prop="approvedLoadKg">
|
||||
<el-input-number v-model="vehicleForm.approvedLoadKg" :min="0" :precision="0" controls-position="right" />
|
||||
<el-input-number
|
||||
v-model="vehicleForm.approvedLoadKg"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="准牵引总质量(KG)" prop="tractionMassKg">
|
||||
<el-input-number v-model="vehicleForm.tractionMassKg" :min="0" :precision="0" controls-position="right" />
|
||||
<el-input-number
|
||||
v-model="vehicleForm.tractionMassKg"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
@@ -181,17 +220,32 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="外廓长度(mm)" prop="outerLength">
|
||||
<el-input-number v-model="vehicleForm.outerLength" :min="0" :precision="0" controls-position="right" />
|
||||
<el-input-number
|
||||
v-model="vehicleForm.outerLength"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="外廓宽度(mm)" prop="outerWidth">
|
||||
<el-input-number v-model="vehicleForm.outerWidth" :min="0" :precision="0" controls-position="right" />
|
||||
<el-input-number
|
||||
v-model="vehicleForm.outerWidth"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="外廓高度(mm)" prop="outerHeight">
|
||||
<el-input-number v-model="vehicleForm.outerHeight" :min="0" :precision="0" controls-position="right" />
|
||||
<el-input-number
|
||||
v-model="vehicleForm.outerHeight"
|
||||
:min="0"
|
||||
:precision="0"
|
||||
controls-position="right"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
@@ -211,7 +265,11 @@
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label="长期有效" prop="compulsoryScrapLongTerm">
|
||||
<el-checkbox v-model="vehicleForm.compulsoryScrapLongTerm" :true-label="1" :false-label="0">
|
||||
<el-checkbox
|
||||
v-model="vehicleForm.compulsoryScrapLongTerm"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
>
|
||||
是
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
@@ -228,7 +286,12 @@
|
||||
<el-col :span="10">
|
||||
<el-form-item label="行驶证有效期" prop="drivingLicenseEndDate">
|
||||
<div class="date-range">
|
||||
<el-date-picker v-model="vehicleForm.drivingLicenseStartDate" type="date" value-format="YYYY-MM-DD" placeholder="起" />
|
||||
<el-date-picker
|
||||
v-model="vehicleForm.drivingLicenseStartDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="起"
|
||||
/>
|
||||
<el-date-picker
|
||||
v-model="vehicleForm.drivingLicenseEndDate"
|
||||
type="date"
|
||||
@@ -241,7 +304,11 @@
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label="长期有效" prop="drivingLicenseLongTerm">
|
||||
<el-checkbox v-model="vehicleForm.drivingLicenseLongTerm" :true-label="1" :false-label="0">
|
||||
<el-checkbox
|
||||
v-model="vehicleForm.drivingLicenseLongTerm"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
>
|
||||
是
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
@@ -269,7 +336,12 @@
|
||||
<el-col :span="10">
|
||||
<el-form-item label="道路运输证有效期" prop="roadTransportCertEndDate">
|
||||
<div class="date-range">
|
||||
<el-date-picker v-model="vehicleForm.roadTransportCertStartDate" type="date" value-format="YYYY-MM-DD" placeholder="起" />
|
||||
<el-date-picker
|
||||
v-model="vehicleForm.roadTransportCertStartDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="起"
|
||||
/>
|
||||
<el-date-picker
|
||||
v-model="vehicleForm.roadTransportCertEndDate"
|
||||
type="date"
|
||||
@@ -282,7 +354,11 @@
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label="长期有效" prop="roadTransportCertLongTerm">
|
||||
<el-checkbox v-model="vehicleForm.roadTransportCertLongTerm" :true-label="1" :false-label="0">
|
||||
<el-checkbox
|
||||
v-model="vehicleForm.roadTransportCertLongTerm"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
>
|
||||
是
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
@@ -299,7 +375,11 @@
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-form-item label="年审长期有效" prop="annualReviewLongTerm">
|
||||
<el-checkbox v-model="vehicleForm.annualReviewLongTerm" :true-label="1" :false-label="0">
|
||||
<el-checkbox
|
||||
v-model="vehicleForm.annualReviewLongTerm"
|
||||
:true-label="1"
|
||||
:false-label="0"
|
||||
>
|
||||
是
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
@@ -326,12 +406,21 @@
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="机动车登记日期" prop="registrationDate">
|
||||
<el-date-picker v-model="vehicleForm.registrationDate" type="date" value-format="YYYY-MM-DD" />
|
||||
<el-date-picker
|
||||
v-model="vehicleForm.registrationDate"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="vehicleForm.remark" type="textarea" maxlength="200" show-word-limit />
|
||||
<el-input
|
||||
v-model="vehicleForm.remark"
|
||||
type="textarea"
|
||||
maxlength="200"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
@@ -499,16 +588,24 @@ export default {
|
||||
organizationName: [{ required: true, message: '请输入所属组织', trigger: 'blur' }],
|
||||
plateNo: [
|
||||
{ required: true, message: '请输入车牌号', trigger: 'blur' },
|
||||
{ pattern: /^[\u4e00-\u9fa5][A-Z][A-Z0-9挂学警港澳]{5,6}$/, message: '请输入标准车牌号', trigger: 'blur' },
|
||||
{
|
||||
pattern: /^[\u4e00-\u9fa5][A-Z][A-Z0-9挂学警港澳]{5,6}$/,
|
||||
message: '请输入标准车牌号',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
vehicleType: [{ required: true, message: '请选择车辆类型', trigger: 'change' }],
|
||||
approvedLoadKg: [{ required: true, message: '请输入核定载质量', trigger: 'blur' }],
|
||||
businessRelation: [{ required: true, message: '请选择业务关系', trigger: 'change' }],
|
||||
energyType: [{ required: true, message: '请选择能源类型', trigger: 'change' }],
|
||||
drivingLicenseNo: [{ required: true, message: '请输入行驶证档案编号', trigger: 'blur' }],
|
||||
drivingLicenseEndDate: [{ validator: this.validateDrivingLicenseEndDate, trigger: 'change' }],
|
||||
drivingLicenseEndDate: [
|
||||
{ validator: this.validateDrivingLicenseEndDate, trigger: 'change' },
|
||||
],
|
||||
roadTransportCertNo: [{ required: true, message: '请输入道路运输证号', trigger: 'blur' }],
|
||||
roadTransportCertEndDate: [{ validator: this.validateRoadTransportCertEndDate, trigger: 'change' }],
|
||||
roadTransportCertEndDate: [
|
||||
{ validator: this.validateRoadTransportCertEndDate, trigger: 'change' },
|
||||
],
|
||||
annualReviewEndDate: [{ validator: this.validateAnnualReviewEndDate, trigger: 'change' }],
|
||||
registrationNo: [{ required: true, message: '请输入机动车登记编号', trigger: 'blur' }],
|
||||
remark: [{ max: 200, message: '备注最多200字', trigger: 'blur' }],
|
||||
@@ -708,7 +805,10 @@ export default {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-transport/transport-vehicle/export-transport-vehicle', this.buildExportParams())
|
||||
exportBlob(
|
||||
'/blade-transport/transport-vehicle/export-transport-vehicle',
|
||||
this.buildExportParams()
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `车辆管理${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
|
||||
@@ -65,7 +65,10 @@ export default {
|
||||
option: {
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
tree: true,
|
||||
border: true,
|
||||
index: true,
|
||||
|
||||
@@ -110,7 +110,10 @@ export default {
|
||||
option: {
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
tree: true,
|
||||
border: true,
|
||||
index: true,
|
||||
|
||||
@@ -114,7 +114,10 @@ export default {
|
||||
option: {
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
tree: true,
|
||||
border: true,
|
||||
index: true,
|
||||
|
||||
@@ -15,7 +15,7 @@ export default {
|
||||
return {
|
||||
form: {},
|
||||
option: {
|
||||
labelWidth: 110,
|
||||
labelWidth: 'auto',
|
||||
column: [
|
||||
{
|
||||
label: '姓名',
|
||||
|
||||
@@ -11,7 +11,7 @@ export default {
|
||||
return {
|
||||
form: {},
|
||||
option: {
|
||||
labelWidth: 110,
|
||||
labelWidth: 'auto',
|
||||
column: [
|
||||
{
|
||||
label: '用户名',
|
||||
|
||||
@@ -63,8 +63,9 @@
|
||||
<el-autocomplete
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
placeholder="输入车牌号/船号查询选择"
|
||||
:placeholder="vehicleNoPlaceholder"
|
||||
value-key="value"
|
||||
class="accident-record-page__input"
|
||||
/>
|
||||
@@ -72,6 +73,24 @@
|
||||
<template #attachments="{ row }">
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
</avue-crud>
|
||||
<empty-pagination
|
||||
:page="page"
|
||||
@@ -80,7 +99,7 @@
|
||||
@load="onLoad(page, query)"
|
||||
/>
|
||||
<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>
|
||||
@@ -98,6 +117,7 @@ import { getList as getShipList } from '@/api/transportCapacity/transport-ship';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/accident-record';
|
||||
@@ -112,6 +132,7 @@ export default {
|
||||
loading: true,
|
||||
excelBox: false,
|
||||
excelForm: {},
|
||||
isDetailLoading: false,
|
||||
option,
|
||||
excelOption,
|
||||
page: {
|
||||
@@ -121,6 +142,7 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
boxType: '',
|
||||
data: [],
|
||||
};
|
||||
},
|
||||
@@ -141,6 +163,9 @@ export default {
|
||||
editBtn: this.hasPermission('accident_record_edit'),
|
||||
};
|
||||
},
|
||||
vehicleNoPlaceholder() {
|
||||
return this.form.vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
},
|
||||
ids() {
|
||||
const ids = [];
|
||||
this.selectionList.forEach(ele => {
|
||||
@@ -151,8 +176,8 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
'form.vehicleType': {
|
||||
handler(value) {
|
||||
this.updateVehicleTypeDisplays(value || '车辆');
|
||||
handler(value, oldValue) {
|
||||
this.updateVehicleTypeDisplays(value || '车辆', oldValue);
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
@@ -167,10 +192,13 @@ export default {
|
||||
column.dicData = res.data.data;
|
||||
});
|
||||
},
|
||||
updateVehicleTypeDisplays(vehicleType) {
|
||||
updateVehicleTypeDisplays(vehicleType, oldValue) {
|
||||
const vehicleTypeColumn = this.findColumn(this.option.column, 'vehicleType');
|
||||
const vehicleNoColumn = this.findColumn(this.option.column, 'vehicleNo');
|
||||
vehicleNoColumn.placeholder =
|
||||
vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
vehicleTypeColumn.disabled = Boolean(this.form.id);
|
||||
if (!this.form.id && this.form.vehicleNo) {
|
||||
if (!this.isDetailLoading && oldValue && vehicleType !== oldValue && this.form.vehicleNo) {
|
||||
this.form.vehicleNo = '';
|
||||
}
|
||||
},
|
||||
@@ -227,7 +255,10 @@ export default {
|
||||
const values = { ...row };
|
||||
values.vehicleType = values.vehicleType || '车辆';
|
||||
if (values.vehicleNo) {
|
||||
values.vehicleNo = values.vehicleNo.trim().toUpperCase();
|
||||
values.vehicleNo =
|
||||
values.vehicleType === '船舶'
|
||||
? values.vehicleNo.trim()
|
||||
: values.vehicleNo.trim().toUpperCase();
|
||||
}
|
||||
values.attachments = this.stringifyAttachments(values.attachments);
|
||||
return values;
|
||||
@@ -329,6 +360,7 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
if (type === 'add') {
|
||||
this.form = {
|
||||
vehicleType: '车辆',
|
||||
@@ -336,12 +368,18 @@ export default {
|
||||
this.updateVehicleTypeDisplays('车辆');
|
||||
}
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
this.form = detail;
|
||||
this.updateVehicleTypeDisplays(detail.vehicleType);
|
||||
});
|
||||
this.isDetailLoading = true;
|
||||
getDetail(this.form.id)
|
||||
.then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
detail.vehicleType = detail.vehicleType || '车辆';
|
||||
this.form = detail;
|
||||
this.updateVehicleTypeDisplays(detail.vehicleType);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isDetailLoading = false;
|
||||
});
|
||||
}
|
||||
done();
|
||||
},
|
||||
@@ -385,12 +423,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '事故记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出事故记录数据?', '提示', {
|
||||
@@ -399,7 +432,10 @@ export default {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-transport/accident-record/export-accident-record', this.buildExportParams())
|
||||
exportBlob(
|
||||
'/blade-transport/accident-record/export-accident-record',
|
||||
this.buildExportParams()
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `事故记录${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
<el-autocomplete
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
placeholder="输入车牌号/船号查询选择"
|
||||
value-key="value"
|
||||
@@ -72,6 +73,24 @@
|
||||
<template #attachments="{ row }">
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
</avue-crud>
|
||||
<empty-pagination
|
||||
:page="page"
|
||||
@@ -80,7 +99,7 @@
|
||||
@load="onLoad(page, query)"
|
||||
/>
|
||||
<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>
|
||||
@@ -98,6 +117,7 @@ import { getList as getShipList } from '@/api/transportCapacity/transport-ship';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/annual-inspection-record';
|
||||
@@ -121,6 +141,7 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
boxType: '',
|
||||
data: [],
|
||||
};
|
||||
},
|
||||
@@ -332,6 +353,7 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
if (type === 'add') {
|
||||
this.form = {
|
||||
vehicleType: '车辆',
|
||||
@@ -389,12 +411,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '年检记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出年检记录数据?', '提示', {
|
||||
@@ -424,7 +441,9 @@ export default {
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(
|
||||
`/blade-transport/annual-inspection-record/export-template?${this.website.tokenHeader}=${getToken()}`
|
||||
`/blade-transport/annual-inspection-record/export-template?${
|
||||
this.website.tokenHeader
|
||||
}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '年检记录模板.xlsx');
|
||||
});
|
||||
|
||||
@@ -17,14 +17,14 @@
|
||||
@on-load="onLoad"
|
||||
>
|
||||
<template #menu-left>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('credit_score_quantification_add')"
|
||||
@click="openConfig()"
|
||||
>新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
plain
|
||||
v-if="hasPermission('credit_score_quantification_add')"
|
||||
@click="openConfig()"
|
||||
>新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-upload"
|
||||
@@ -49,9 +49,9 @@
|
||||
@click="handleExport"
|
||||
>批量导出
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
plain
|
||||
v-if="hasPermission('credit_score_quantification_delete')"
|
||||
@click="handleDelete"
|
||||
@@ -109,7 +109,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>
|
||||
@@ -127,8 +127,14 @@
|
||||
@closed="resetConfig"
|
||||
>
|
||||
<div class="score-config">
|
||||
<div class="section-title">评分量化表</div>
|
||||
<el-form :model="configForm" label-width="110px" class="base-form" :disabled="readonly">
|
||||
<div class="section-title dialog-section-title">评分量化表</div>
|
||||
<el-form
|
||||
:model="configForm"
|
||||
label-position="right"
|
||||
label-width="auto"
|
||||
class="base-form"
|
||||
:disabled="readonly"
|
||||
>
|
||||
<el-form-item label="评定表名称" required>
|
||||
<el-input v-model="configForm.name" maxlength="30" show-word-limit />
|
||||
</el-form-item>
|
||||
@@ -138,7 +144,7 @@
|
||||
</el-form>
|
||||
|
||||
<div class="section-head">
|
||||
<div class="section-title">评分表</div>
|
||||
<div class="section-title dialog-section-title">评分表</div>
|
||||
</div>
|
||||
<el-table :data="configForm.categories" border class="config-table">
|
||||
<el-table-column label="序号" type="index" width="70" align="center" />
|
||||
@@ -154,13 +160,8 @@
|
||||
</el-table>
|
||||
|
||||
<div class="section-head standard-head">
|
||||
<div class="section-title">评估标准</div>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
v-if="!readonly"
|
||||
@click="openStandard()"
|
||||
>
|
||||
<div class="section-title dialog-section-title">评估标准</div>
|
||||
<el-button type="primary" icon="el-icon-plus" v-if="!readonly" @click="openStandard()">
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -168,7 +169,9 @@
|
||||
<el-table-column label="序号" type="index" width="70" align="center" />
|
||||
<el-table-column label="信用等级" prop="creditLevel" width="120" align="center" />
|
||||
<el-table-column label="得分率" width="160" align="center">
|
||||
<template #default="{ row }">{{ row.scoreRateLower }}% - {{ row.scoreRateUpper }}%</template>
|
||||
<template #default="{ row }"
|
||||
>{{ row.scoreRateLower }}% - {{ row.scoreRateUpper }}%</template
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column label="最大资金使用额度(万元)" width="210" align="center">
|
||||
<template #default="{ row }">
|
||||
@@ -179,7 +182,9 @@
|
||||
<el-table-column label="操作" width="160" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-button type="primary" text @click="openStandard(row, $index)">编辑</el-button>
|
||||
<el-button type="danger" text v-if="!readonly" @click="removeStandard($index)">删除</el-button>
|
||||
<el-button type="danger" text v-if="!readonly" @click="removeStandard($index)"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -215,7 +220,9 @@
|
||||
<el-table-column label="操作" width="160" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-button type="primary" text @click="openItem(row, $index)">编辑</el-button>
|
||||
<el-button type="danger" text v-if="!readonly" @click="removeItem($index)">删除</el-button>
|
||||
<el-button type="danger" text v-if="!readonly" @click="removeItem($index)"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -226,7 +233,7 @@
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="评分项目详情" append-to-body v-model="itemBox" width="76%">
|
||||
<el-form :model="itemForm" label-width="100px" :disabled="readonly">
|
||||
<el-form :model="itemForm" label-position="right" label-width="auto" :disabled="readonly">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="评分项目" required>
|
||||
@@ -248,7 +255,12 @@
|
||||
<el-input v-model="option.optionName" maxlength="100" placeholder="选项描述" />
|
||||
<el-input-number v-model="option.score" :min="0" :precision="2" placeholder="分值" />
|
||||
<span class="score-unit">分</span>
|
||||
<el-button type="danger" text v-if="!readonly && itemForm.options.length > 1" @click="removeOption(index)">
|
||||
<el-button
|
||||
type="danger"
|
||||
text
|
||||
v-if="!readonly && itemForm.options.length > 1"
|
||||
@click="removeOption(index)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -263,19 +275,36 @@
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="评估标准设置" append-to-body v-model="standardBox" width="76%">
|
||||
<el-form :model="standardForm" label-width="170px" :disabled="readonly">
|
||||
<el-form :model="standardForm" label-position="right" label-width="auto" :disabled="readonly">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="信用等级" required>
|
||||
<el-input v-model="standardForm.creditLevel" maxlength="30" />
|
||||
<el-select v-model="standardForm.creditLevel" placeholder="请选择信用等级" clearable>
|
||||
<el-option
|
||||
v-for="item in creditLevelOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="得分率(%)" required>
|
||||
<div class="range-input">
|
||||
<el-input-number v-model="standardForm.scoreRateLower" :min="0" :max="100" :precision="0" />
|
||||
<el-input-number
|
||||
v-model="standardForm.scoreRateLower"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="0"
|
||||
/>
|
||||
<span>至</span>
|
||||
<el-input-number v-model="standardForm.scoreRateUpper" :min="0" :max="100" :precision="0" />
|
||||
<el-input-number
|
||||
v-model="standardForm.scoreRateUpper"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:precision="0"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -303,7 +332,12 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="标准说明">
|
||||
<el-input v-model="standardForm.standardDescription" type="textarea" maxlength="500" show-word-limit />
|
||||
<el-input
|
||||
v-model="standardForm.standardDescription"
|
||||
type="textarea"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -325,6 +359,7 @@ import {
|
||||
} from '@/api/vehicle/credit-score-quantification';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import NProgress from 'nprogress';
|
||||
@@ -361,13 +396,21 @@ export default {
|
||||
2: { label: '停用', type: 'info' },
|
||||
3: { label: '草稿', type: 'warning' },
|
||||
},
|
||||
creditLevelOptions: ['A', 'B', 'C', 'D', 'E', 'F'].map(item => ({
|
||||
label: item,
|
||||
value: item,
|
||||
})),
|
||||
option: {
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
dialogWidth: 760,
|
||||
labelPosition: 'right',
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
indexLabel: '序号',
|
||||
@@ -421,7 +464,6 @@ export default {
|
||||
type: 'date',
|
||||
format: 'YYYY-MM-DD 00:00:00',
|
||||
valueFormat: 'YYYY-MM-DD 00:00:00',
|
||||
search: true,
|
||||
hide: true,
|
||||
display: false,
|
||||
},
|
||||
@@ -431,13 +473,13 @@ export default {
|
||||
type: 'date',
|
||||
format: 'YYYY-MM-DD 23:59:59',
|
||||
valueFormat: 'YYYY-MM-DD 23:59:59',
|
||||
search: true,
|
||||
hide: true,
|
||||
display: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
excelOption: {
|
||||
labelPosition: 'right',
|
||||
submitBtn: false,
|
||||
emptyBtn: false,
|
||||
column: [
|
||||
@@ -452,7 +494,8 @@ export default {
|
||||
res: 'data',
|
||||
},
|
||||
tip: '请上传 .xls,.xlsx 标准格式文件',
|
||||
action: '/blade-transport/credit-score-quantification/import-credit-score-quantification',
|
||||
action:
|
||||
'/blade-transport/credit-score-quantification/import-credit-score-quantification',
|
||||
},
|
||||
{
|
||||
label: '模板下载',
|
||||
@@ -532,7 +575,8 @@ export default {
|
||||
...category,
|
||||
items: (category.items || []).map(item => ({
|
||||
...item,
|
||||
options: item.options && item.options.length ? item.options : [{ optionName: '', score: 0 }],
|
||||
options:
|
||||
item.options && item.options.length ? item.options : [{ optionName: '', score: 0 }],
|
||||
})),
|
||||
};
|
||||
});
|
||||
@@ -601,9 +645,26 @@ export default {
|
||||
this.standardForm = row ? JSON.parse(JSON.stringify(row)) : this.emptyStandard();
|
||||
this.standardBox = true;
|
||||
},
|
||||
hasDuplicateCreditLevel(creditLevel, currentIndex = -1) {
|
||||
const level = String(creditLevel || '').trim();
|
||||
return this.configForm.standards.some(
|
||||
(item, index) => index !== currentIndex && String(item.creditLevel || '').trim() === level
|
||||
);
|
||||
},
|
||||
isValidCreditLevel(creditLevel) {
|
||||
return this.creditLevelOptions.some(item => item.value === String(creditLevel || '').trim());
|
||||
},
|
||||
saveStandard() {
|
||||
if (!this.standardForm.creditLevel || !this.standardForm.creditLevel.trim()) {
|
||||
this.$message.warning('请输入信用等级');
|
||||
if (!this.standardForm.creditLevel) {
|
||||
this.$message.warning('请选择信用等级');
|
||||
return;
|
||||
}
|
||||
if (!this.isValidCreditLevel(this.standardForm.creditLevel)) {
|
||||
this.$message.warning('信用等级只能选择A/B/C/D/E/F');
|
||||
return;
|
||||
}
|
||||
if (this.hasDuplicateCreditLevel(this.standardForm.creditLevel, this.currentStandardIndex)) {
|
||||
this.$message.warning('信用等级不能重复');
|
||||
return;
|
||||
}
|
||||
if (
|
||||
@@ -624,6 +685,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
const standard = JSON.parse(JSON.stringify(this.standardForm));
|
||||
standard.creditLevel = String(standard.creditLevel || '').trim();
|
||||
if (this.currentStandardIndex >= 0) {
|
||||
this.configForm.standards.splice(this.currentStandardIndex, 1, standard);
|
||||
} else {
|
||||
@@ -652,6 +714,17 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
const creditLevels = this.configForm.standards
|
||||
.map(item => String(item.creditLevel || '').trim())
|
||||
.filter(Boolean);
|
||||
if (creditLevels.some(level => !this.isValidCreditLevel(level))) {
|
||||
this.$message.warning('评估标准中的信用等级只能选择A/B/C/D/E/F');
|
||||
return false;
|
||||
}
|
||||
if (new Set(creditLevels).size !== creditLevels.length) {
|
||||
this.$message.warning('评估标准中的信用等级不能重复');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
saveConfig() {
|
||||
@@ -749,12 +822,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '评分量化表');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出评分量化表数据?', '提示', {
|
||||
@@ -784,7 +852,9 @@ export default {
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(
|
||||
`/blade-transport/credit-score-quantification/export-template?${this.website.tokenHeader}=${getToken()}`
|
||||
`/blade-transport/credit-score-quantification/export-template?${
|
||||
this.website.tokenHeader
|
||||
}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '评分量化表模板.xlsx');
|
||||
});
|
||||
@@ -808,12 +878,17 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 24px 0 12px;
|
||||
|
||||
.section-title {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
margin: 18px 0 12px;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
line-height: 20px;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
|
||||
@@ -151,11 +151,11 @@
|
||||
ref="archiveForm"
|
||||
:model="archiveForm"
|
||||
:rules="formRules"
|
||||
label-position="top"
|
||||
label-position="right"
|
||||
:disabled="readonly"
|
||||
class="archive-form"
|
||||
>
|
||||
<div class="section-title">基本信息</div>
|
||||
<div class="section-title dialog-section-title">基本信息</div>
|
||||
<el-alert
|
||||
type="warning"
|
||||
:closable="false"
|
||||
@@ -164,7 +164,7 @@
|
||||
class="archive-rule-alert"
|
||||
/>
|
||||
<el-row :gutter="18">
|
||||
<el-col :span="6">
|
||||
<el-col v-if="readonly" :span="6">
|
||||
<el-form-item label="客商编号" prop="customerCode">
|
||||
<el-input v-model="archiveForm.customerCode" disabled placeholder="保存后自动生成" />
|
||||
</el-form-item>
|
||||
@@ -221,7 +221,11 @@
|
||||
v-model="archiveForm.unifiedCreditCode"
|
||||
maxlength="18"
|
||||
show-word-limit
|
||||
@input="archiveForm.unifiedCreditCode = String(archiveForm.unifiedCreditCode || '').toUpperCase()"
|
||||
@input="
|
||||
archiveForm.unifiedCreditCode = String(
|
||||
archiveForm.unifiedCreditCode || ''
|
||||
).toUpperCase()
|
||||
"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -335,16 +339,23 @@
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="archiveForm.remark" type="textarea" maxlength="500" show-word-limit />
|
||||
<el-input
|
||||
v-model="archiveForm.remark"
|
||||
type="textarea"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div class="section-head">
|
||||
<div class="section-title">资质附件</div>
|
||||
<div class="section-title dialog-section-title">资质附件</div>
|
||||
<div v-if="!readonly" class="section-actions">
|
||||
<el-button type="primary" icon="el-icon-upload" @click="addAttachment">OCR上传识别</el-button>
|
||||
<el-button type="primary" icon="el-icon-upload" @click="addAttachment"
|
||||
>OCR上传识别</el-button
|
||||
>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="addAttachment">添加附件</el-button>
|
||||
<el-button icon="el-icon-download" @click="downloadAttachments">批量下载</el-button>
|
||||
</div>
|
||||
@@ -352,7 +363,7 @@
|
||||
<el-alert
|
||||
type="info"
|
||||
:closable="false"
|
||||
title="支持 JPG、PNG、PDF,单文件大小不超过 10MB;正式客商需上传公司营业执照、道路运输证等核心材料。"
|
||||
title="支持 JPG、PNG、PDF、Word、Excel、PPT,单文件大小不超过 10MB;正式客商需上传公司营业执照、道路运输证等核心材料。"
|
||||
class="archive-rule-alert"
|
||||
/>
|
||||
<el-alert
|
||||
@@ -377,7 +388,16 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="文件名称" min-width="180">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.name" :disabled="readonly" maxlength="100" />
|
||||
<vehicle-attachment-upload
|
||||
v-model="row.files"
|
||||
:readonly="readonly"
|
||||
:multiple="false"
|
||||
accept=".jpg,.jpeg,.png,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx"
|
||||
:max-size="10"
|
||||
button-text="上传文件"
|
||||
:show-tip="false"
|
||||
@success="file => handleQualificationUploadSuccess(file, row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="附件描述" min-width="220">
|
||||
@@ -387,27 +407,24 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="文件大小" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.size" :disabled="readonly" maxlength="30" />
|
||||
<span>{{ row.size || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传人" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.uploadUserName" :disabled="readonly" maxlength="30" />
|
||||
<span>{{ row.uploadUserName || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传时间" min-width="170">
|
||||
<template #default="{ row }">
|
||||
<el-date-picker
|
||||
v-model="row.uploadTime"
|
||||
type="datetime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:disabled="readonly"
|
||||
/>
|
||||
<span>{{ row.uploadTime || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="90" align="center" v-if="!readonly">
|
||||
<template #default="{ $index }">
|
||||
<el-button type="danger" text @click="qualificationFiles.splice($index, 1)">删除</el-button>
|
||||
<el-button type="danger" text @click="qualificationFiles.splice($index, 1)"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -437,7 +454,12 @@
|
||||
<el-table-column label="最终得分" prop="finalScore" width="110" align="center" />
|
||||
<el-table-column label="额度" min-width="150">
|
||||
<template #default="{ row }">
|
||||
<el-input-number v-model="row.applyCreditLimit" :min="0" :precision="2" :disabled="readonly" />
|
||||
<el-input-number
|
||||
v-model="row.applyCreditLimit"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:disabled="readonly"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="信用等级" min-width="130">
|
||||
@@ -450,8 +472,15 @@
|
||||
<el-table-column label="操作" width="210" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-button type="primary" text @click="openScore(row)">评分明细</el-button>
|
||||
<el-button type="success" text v-if="!readonly" @click="finishScore(row)">完成评分</el-button>
|
||||
<el-button type="danger" text v-if="!readonly" @click="archiveForm.scores.splice($index, 1)">
|
||||
<el-button type="success" text v-if="!readonly" @click="finishScore(row)"
|
||||
>完成评分</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
text
|
||||
v-if="!readonly"
|
||||
@click="archiveForm.scores.splice($index, 1)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -500,7 +529,13 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="评分明细" append-to-body v-model="scoreBox" width="88%" class="archive-dialog">
|
||||
<el-dialog
|
||||
title="评分明细"
|
||||
append-to-body
|
||||
v-model="scoreBox"
|
||||
width="88%"
|
||||
class="archive-dialog"
|
||||
>
|
||||
<el-table :data="currentScore.details" border class="score-detail-table">
|
||||
<el-table-column label="序号" type="index" width="70" align="center" />
|
||||
<el-table-column label="评分类目" prop="categoryName" min-width="130" />
|
||||
@@ -530,7 +565,12 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="复评得分" width="130" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input-number v-model="row.reviewScore" :min="0" :precision="2" :disabled="readonly" />
|
||||
<el-input-number
|
||||
v-model="row.reviewScore"
|
||||
:min="0"
|
||||
:precision="2"
|
||||
:disabled="readonly"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="得分说明" prop="scoreDescription" min-width="220" />
|
||||
@@ -746,7 +786,10 @@ export default {
|
||||
searchBtnText: '查询',
|
||||
emptyBtnText: '重置',
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
indexLabel: '序号',
|
||||
@@ -877,12 +920,20 @@ export default {
|
||||
},
|
||||
missingQualificationText() {
|
||||
if (this.archiveForm.accessType !== 'formal') return '';
|
||||
const types = this.qualificationFiles.map(item => item.type || item.name).filter(Boolean);
|
||||
const types = this.qualificationFiles
|
||||
.filter(item => item.url)
|
||||
.map(item => item.type || item.name)
|
||||
.filter(Boolean);
|
||||
const missing = ['公司营业执照', '道路运输证'].filter(
|
||||
item => !types.some(type => String(type).includes(item))
|
||||
);
|
||||
return missing.length ? `缺失核心资质材料:${missing.join('、')}` : '';
|
||||
},
|
||||
uploadHeaders() {
|
||||
return {
|
||||
[this.website.tokenHeader]: getToken(),
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hasPermission(code) {
|
||||
@@ -902,7 +953,14 @@ export default {
|
||||
};
|
||||
},
|
||||
emptyContact() {
|
||||
return { contactName: '', contactPhone: '', email: '', positionName: '', isDefault: 0, remark: '' };
|
||||
return {
|
||||
contactName: '',
|
||||
contactPhone: '',
|
||||
email: '',
|
||||
positionName: '',
|
||||
isDefault: 0,
|
||||
remark: '',
|
||||
};
|
||||
},
|
||||
emptyReceiptAccount() {
|
||||
return {
|
||||
@@ -976,16 +1034,26 @@ export default {
|
||||
if (Array.isArray(value)) return value;
|
||||
try {
|
||||
const list = JSON.parse(value);
|
||||
return Array.isArray(list) ? list : [];
|
||||
return Array.isArray(list)
|
||||
? list.map(item => ({
|
||||
...item,
|
||||
files: item.url ? [item] : [],
|
||||
}))
|
||||
: [];
|
||||
} catch (error) {
|
||||
return String(value)
|
||||
.split(',')
|
||||
.map(item => ({ name: item.trim(), url: item.trim() }))
|
||||
.filter(item => item.url);
|
||||
.filter(item => item.url)
|
||||
.map(item => ({
|
||||
...item,
|
||||
files: [item],
|
||||
}));
|
||||
}
|
||||
},
|
||||
stringifyAttachments(list) {
|
||||
const files = (list || [])
|
||||
.filter(item => item.url)
|
||||
.map(item => ({
|
||||
type: String(item.type || '').trim(),
|
||||
name: String(item.name || '').trim(),
|
||||
@@ -995,7 +1063,7 @@ export default {
|
||||
uploadTime: String(item.uploadTime || '').trim(),
|
||||
url: String(item.url || '').trim(),
|
||||
}))
|
||||
.filter(item => item.type || item.name || item.url);
|
||||
.filter(item => item.url);
|
||||
return files.length ? JSON.stringify(files) : '';
|
||||
},
|
||||
addAttachment() {
|
||||
@@ -1007,8 +1075,25 @@ export default {
|
||||
uploadUserName: this.userInfo.realName || this.userInfo.userName || '',
|
||||
uploadTime: this.$dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||
url: '',
|
||||
files: [],
|
||||
});
|
||||
},
|
||||
formatAttachmentSize(size) {
|
||||
if (!size) return '';
|
||||
const byteSize = Number(size);
|
||||
if (!Number.isFinite(byteSize)) return String(size);
|
||||
const mb = byteSize / 1024 / 1024;
|
||||
if (mb >= 1) return `${mb.toFixed(2)} MB`;
|
||||
return `${(byteSize / 1024).toFixed(2)} KB`;
|
||||
},
|
||||
handleQualificationUploadSuccess(file, row) {
|
||||
row.name = file.name || row.name || '资质附件';
|
||||
row.size = this.formatAttachmentSize(file.size || row.size);
|
||||
row.uploadUserName = this.userInfo.realName || this.userInfo.userName || '';
|
||||
row.uploadTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||||
row.url = file.url || row.url || '';
|
||||
row.files = [file];
|
||||
},
|
||||
downloadAttachments() {
|
||||
const files = this.qualificationFiles.filter(item => item.url);
|
||||
if (!files.length) {
|
||||
@@ -1051,7 +1136,9 @@ export default {
|
||||
if (row && row.id) {
|
||||
getDetail(row.id).then(res => {
|
||||
this.archiveForm = this.normalizeDetail(res.data.data);
|
||||
this.qualificationFiles = this.parseAttachments(this.archiveForm.qualificationAttachments);
|
||||
this.qualificationFiles = this.parseAttachments(
|
||||
this.archiveForm.qualificationAttachments
|
||||
);
|
||||
this.archiveBox = true;
|
||||
});
|
||||
return;
|
||||
@@ -1089,7 +1176,9 @@ export default {
|
||||
? archive.customerType.join(',')
|
||||
: archive.customerType;
|
||||
archive.qualificationAttachments = this.stringifyAttachments(this.qualificationFiles);
|
||||
archive.contacts = (archive.contacts || []).filter(item => item.contactName || item.contactPhone);
|
||||
archive.contacts = (archive.contacts || []).filter(
|
||||
item => item.contactName || item.contactPhone
|
||||
);
|
||||
archive.receiptAccounts = (archive.receiptAccounts || []).filter(
|
||||
item => item.accountName || item.bankAccount
|
||||
);
|
||||
@@ -1161,7 +1250,9 @@ export default {
|
||||
}
|
||||
},
|
||||
scoreOptionChange(detail, optionValue) {
|
||||
const option = this.parseScoreOptions(detail.optionsJson).find(item => item.value === optionValue);
|
||||
const option = this.parseScoreOptions(detail.optionsJson).find(
|
||||
item => item.value === optionValue
|
||||
);
|
||||
const score = Number(option?.score || 0);
|
||||
detail.selfScore = score;
|
||||
detail.reviewScore = score;
|
||||
@@ -1327,7 +1418,10 @@ export default {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-transport/customer-archive/export-customer-archive', this.buildExportParams())
|
||||
exportBlob(
|
||||
'/blade-transport/customer-archive/export-customer-archive',
|
||||
this.buildExportParams()
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `客商档案${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
@@ -1375,6 +1469,10 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 18px 0 12px;
|
||||
|
||||
.section-title {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.section-actions {
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
<el-autocomplete
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
placeholder="输入车牌号模糊查询选择"
|
||||
value-key="value"
|
||||
@@ -72,9 +73,15 @@
|
||||
<template #attachments="{ row }">
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<el-dialog title="ETC记录数据导入" 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>
|
||||
@@ -91,6 +98,7 @@ import { getList as getVehicleList } from '@/api/transportCapacity/transport-veh
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/etc-record';
|
||||
@@ -114,6 +122,7 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
boxType: '',
|
||||
data: [],
|
||||
};
|
||||
},
|
||||
@@ -308,6 +317,7 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
if (type === 'add') {
|
||||
this.form = { dataSource: '手工录入' };
|
||||
}
|
||||
@@ -360,12 +370,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, 'ETC记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出ETC记录数据?', '提示', {
|
||||
@@ -391,7 +396,9 @@ export default {
|
||||
};
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(`/blade-transport/etc-record/export-template?${this.website.tokenHeader}=${getToken()}`).then(res => {
|
||||
exportBlob(
|
||||
`/blade-transport/etc-record/export-template?${this.website.tokenHeader}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, 'ETC记录模板.xlsx');
|
||||
});
|
||||
},
|
||||
|
||||
@@ -64,19 +64,27 @@
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
clearable
|
||||
placeholder="输入车牌号/船号模糊查询选择"
|
||||
:placeholder="vehicleNoPlaceholder"
|
||||
value-key="value"
|
||||
class="insurance-record-page__vehicle-input"
|
||||
/>
|
||||
</template>
|
||||
<template #policyFileForm>
|
||||
<div class="insurance-record-page__upload">
|
||||
<div class="insurance-record-page__upload-icon">OCR</div>
|
||||
<div class="insurance-record-page__upload-text">
|
||||
<strong>上传图片,自动识别填写</strong>
|
||||
<span>支持JPG、PNG、PDF上传</span>
|
||||
<div class="insurance-record-page__upload-info">
|
||||
<div class="insurance-record-page__upload-icon" aria-hidden="true">
|
||||
<span class="insurance-record-page__upload-card">
|
||||
<span></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="insurance-record-page__upload-text">
|
||||
<strong>上传图片,自动识别填写</strong>
|
||||
<span>支持JPG、PNG、PDF上传</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-upload
|
||||
v-if="hasPermission('insurance_record_ocr')"
|
||||
class="insurance-record-page__upload-action"
|
||||
:action="recognizeUrl"
|
||||
:data="recognizeData"
|
||||
:headers="uploadHeaders"
|
||||
@@ -84,9 +92,40 @@
|
||||
:on-success="handleRecognizeSuccess"
|
||||
:on-error="handleRecognizeError"
|
||||
accept=".jpg,.jpeg,.png,.pdf"
|
||||
v-if="hasPermission('insurance_record_ocr')"
|
||||
>
|
||||
<el-button type="primary" plain>上传文件</el-button>
|
||||
<el-button class="insurance-record-page__upload-button" type="primary" plain>
|
||||
上传文件
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
<template #policyFile-form>
|
||||
<div class="insurance-record-page__upload">
|
||||
<div class="insurance-record-page__upload-info">
|
||||
<div class="insurance-record-page__upload-icon" aria-hidden="true">
|
||||
<span class="insurance-record-page__upload-card">
|
||||
<span></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="insurance-record-page__upload-text">
|
||||
<strong>上传图片,自动识别填写</strong>
|
||||
<span>支持JPG、PNG、PDF上传</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-upload
|
||||
v-if="hasPermission('insurance_record_ocr')"
|
||||
class="insurance-record-page__upload-action"
|
||||
:action="recognizeUrl"
|
||||
:data="recognizeData"
|
||||
:headers="uploadHeaders"
|
||||
:show-file-list="false"
|
||||
:on-success="handleRecognizeSuccess"
|
||||
:on-error="handleRecognizeError"
|
||||
accept=".jpg,.jpeg,.png,.pdf"
|
||||
>
|
||||
<el-button class="insurance-record-page__upload-button" type="primary" plain>
|
||||
上传文件
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
@@ -98,7 +137,7 @@
|
||||
@load="onLoad(page, query)"
|
||||
/>
|
||||
<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>
|
||||
@@ -116,6 +155,7 @@ import { getList as getShipList } from '@/api/transportCapacity/transport-ship';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/insurance-record';
|
||||
@@ -130,6 +170,7 @@ export default {
|
||||
loading: true,
|
||||
excelBox: false,
|
||||
excelForm: {},
|
||||
isDetailLoading: false,
|
||||
option,
|
||||
excelOption,
|
||||
page: {
|
||||
@@ -159,6 +200,9 @@ export default {
|
||||
editBtn: this.hasPermission('insurance_record_edit'),
|
||||
};
|
||||
},
|
||||
vehicleNoPlaceholder() {
|
||||
return this.form.vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
},
|
||||
ids() {
|
||||
const ids = [];
|
||||
this.selectionList.forEach(ele => {
|
||||
@@ -181,10 +225,26 @@ export default {
|
||||
};
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'form.vehicleType': {
|
||||
handler(value, oldValue) {
|
||||
this.updateVehicleTypeDisplays(value || '车辆', oldValue);
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hasPermission(code) {
|
||||
return this.isAdmin || this.validData(this.permission[code], false);
|
||||
},
|
||||
updateVehicleTypeDisplays(vehicleType, oldValue) {
|
||||
const vehicleNoColumn = this.findColumn(this.option.column, 'vehicleNo');
|
||||
vehicleNoColumn.placeholder =
|
||||
vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
if (!this.isDetailLoading && oldValue && vehicleType !== oldValue && this.form.vehicleNo) {
|
||||
this.form.vehicleNo = '';
|
||||
}
|
||||
},
|
||||
initDeptTree() {
|
||||
getDeptTree(this.userInfo.tenantId).then(res => {
|
||||
const column = this.findColumn(this.option.column, 'createDept');
|
||||
@@ -195,9 +255,7 @@ export default {
|
||||
const vehicleType = this.form.vehicleType || '车辆';
|
||||
const request = vehicleType === '船舶' ? getShipList : getVehicleList;
|
||||
const params =
|
||||
vehicleType === '船舶'
|
||||
? { shipIdentifierNo: queryString }
|
||||
: { plateNo: queryString };
|
||||
vehicleType === '船舶' ? { shipIdentifierNo: queryString } : { plateNo: queryString };
|
||||
request(1, 20, params)
|
||||
.then(res => {
|
||||
const records = res.data.data.records || [];
|
||||
@@ -211,8 +269,12 @@ export default {
|
||||
},
|
||||
normalizeRow(row) {
|
||||
const values = { ...row };
|
||||
values.vehicleType = values.vehicleType || '车辆';
|
||||
if (values.vehicleNo) {
|
||||
values.vehicleNo = values.vehicleNo.trim().toUpperCase();
|
||||
values.vehicleNo =
|
||||
values.vehicleType === '船舶'
|
||||
? values.vehicleNo.trim()
|
||||
: values.vehicleNo.trim().toUpperCase();
|
||||
}
|
||||
if (values.policyNo) {
|
||||
values.policyNo = values.policyNo.trim();
|
||||
@@ -305,9 +367,17 @@ export default {
|
||||
this.form.ocrTemplate = '紫金-机动车交强险';
|
||||
}
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
this.form = res.data.data;
|
||||
});
|
||||
this.isDetailLoading = true;
|
||||
getDetail(this.form.id)
|
||||
.then(res => {
|
||||
this.form = {
|
||||
...res.data.data,
|
||||
vehicleType: res.data.data.vehicleType || '车辆',
|
||||
};
|
||||
})
|
||||
.finally(() => {
|
||||
this.isDetailLoading = false;
|
||||
});
|
||||
}
|
||||
done();
|
||||
},
|
||||
@@ -351,12 +421,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '保险记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出保险记录数据?', '提示', {
|
||||
@@ -365,7 +430,10 @@ export default {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-transport/insurance-record/export-insurance-record', this.buildExportParams())
|
||||
exportBlob(
|
||||
'/blade-transport/insurance-record/export-insurance-record',
|
||||
this.buildExportParams()
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `保险记录${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
@@ -383,7 +451,9 @@ export default {
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(
|
||||
`/blade-transport/insurance-record/export-template?${this.website.tokenHeader}=${getToken()}`
|
||||
`/blade-transport/insurance-record/export-template?${
|
||||
this.website.tokenHeader
|
||||
}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '保险记录模板.xlsx');
|
||||
});
|
||||
@@ -417,39 +487,153 @@ export default {
|
||||
&__vehicle-input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&__upload {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 18px;
|
||||
min-height: 88px;
|
||||
padding: 18px 24px;
|
||||
border: 1px dashed #8c8c8c;
|
||||
border-radius: 6px;
|
||||
}
|
||||
:global(.insurance-record-page__upload) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 116px;
|
||||
padding: 26px 46px 26px 32px;
|
||||
border: 2px dashed #8b8b8b;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
&__upload-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
color: #606266;
|
||||
border: 2px solid #8c8c8c;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
}
|
||||
:global(.insurance-record-page__upload-info) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
&__upload-text {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
:global(.insurance-record-page__upload-icon) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin-right: 30px;
|
||||
color: #707070;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-icon::before),
|
||||
:global(.insurance-record-page__upload-icon::after) {
|
||||
position: absolute;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
content: '';
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-icon::before) {
|
||||
top: 0;
|
||||
left: 0;
|
||||
border-top: 4px solid currentColor;
|
||||
border-left: 4px solid currentColor;
|
||||
border-radius: 4px 0 0;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-icon::after) {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border-right: 4px solid currentColor;
|
||||
border-bottom: 4px solid currentColor;
|
||||
border-radius: 0 0 4px;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-card) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 28px;
|
||||
border: 4px solid currentColor;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-card::before),
|
||||
:global(.insurance-record-page__upload-card::after) {
|
||||
position: absolute;
|
||||
content: '';
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-card::before) {
|
||||
top: 7px;
|
||||
left: 9px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border: 3px solid currentColor;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-card::after) {
|
||||
top: 8px;
|
||||
right: 7px;
|
||||
width: 8px;
|
||||
height: 3px;
|
||||
background: currentColor;
|
||||
box-shadow: 0 8px 0 currentColor;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-card span) {
|
||||
position: absolute;
|
||||
right: 7px;
|
||||
bottom: 5px;
|
||||
width: 10px;
|
||||
height: 3px;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-text) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
color: #303133;
|
||||
font-size: 20px;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-text strong) {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-text span) {
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-action) {
|
||||
flex: 0 0 auto;
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-action .el-upload) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-button) {
|
||||
min-width: 156px;
|
||||
height: 58px;
|
||||
border-radius: 8px;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
:global(.insurance-record-page__upload) {
|
||||
align-items: stretch;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
color: #303133;
|
||||
gap: 18px;
|
||||
padding: 22px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #606266;
|
||||
}
|
||||
:global(.insurance-record-page__upload-action) {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
:global(.insurance-record-page__upload-button) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -59,6 +59,17 @@
|
||||
{{ row.vehicleNo }}
|
||||
</el-button>
|
||||
</template>
|
||||
<template #vehicleNoForm>
|
||||
<el-autocomplete
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
:placeholder="vehicleNoPlaceholder"
|
||||
value-key="value"
|
||||
class="maintenance-plan-page__input"
|
||||
/>
|
||||
</template>
|
||||
<template #mileage="{ row }">
|
||||
<span>{{ formatMileage(row.mileage, row.mileageUnit) }}</span>
|
||||
</template>
|
||||
@@ -68,9 +79,27 @@
|
||||
<template #attachments="{ row }">
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
</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>
|
||||
@@ -83,9 +112,12 @@
|
||||
|
||||
<script>
|
||||
import { getList, getDetail, add, update, remove } from '@/api/vehicle/maintenance-plan';
|
||||
import { getList as getVehicleList } from '@/api/transportCapacity/transport-vehicle';
|
||||
import { getList as getShipList } from '@/api/transportCapacity/transport-ship';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { formatUpdateUserName } from '@/utils/audit';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
@@ -116,13 +148,20 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
boxType: '',
|
||||
option: {
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
dialogWidth: 980,
|
||||
dialogWidth: 960,
|
||||
labelPosition: 'right',
|
||||
labelWidth: 'auto',
|
||||
searchLabelWidth: 160,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
@@ -141,6 +180,8 @@ export default {
|
||||
],
|
||||
value: '车辆',
|
||||
search: true,
|
||||
span: 24,
|
||||
change: ({ value }) => this.handleVehicleTypeChange(value || '车辆'),
|
||||
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
@@ -149,6 +190,8 @@ export default {
|
||||
slot: true,
|
||||
search: true,
|
||||
minWidth: 130,
|
||||
span: 12,
|
||||
placeholder: '输入车牌号/船号查询选择',
|
||||
rules: [
|
||||
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
||||
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
||||
@@ -157,6 +200,8 @@ export default {
|
||||
{
|
||||
label: '保养人',
|
||||
prop: 'maintainer',
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [{ max: 20, message: '最多 20 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
@@ -166,6 +211,8 @@ export default {
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
minWidth: 170,
|
||||
span: 12,
|
||||
placeholder: '请选择',
|
||||
rules: [{ required: true, message: '请选择保养时间', trigger: 'click' }],
|
||||
},
|
||||
{
|
||||
@@ -175,6 +222,9 @@ export default {
|
||||
precision: 2,
|
||||
minWidth: 130,
|
||||
slot: true,
|
||||
span: 12,
|
||||
append: '公里',
|
||||
placeholder: '请输入',
|
||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
@@ -187,11 +237,14 @@ export default {
|
||||
],
|
||||
value: '公里',
|
||||
hide: true,
|
||||
display: false,
|
||||
},
|
||||
{
|
||||
label: '保养项目',
|
||||
prop: 'maintenanceItem',
|
||||
minWidth: 160,
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [{ max: 100, message: '最多 100 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
@@ -199,6 +252,9 @@ export default {
|
||||
prop: 'cost',
|
||||
type: 'number',
|
||||
precision: 2,
|
||||
append: '元',
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [
|
||||
{ required: true, message: '请输入费用', trigger: 'blur' },
|
||||
{ validator: validateNonNegative, trigger: 'blur' },
|
||||
@@ -207,12 +263,16 @@ export default {
|
||||
{
|
||||
label: '店名',
|
||||
prop: 'storeName',
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '联系电话',
|
||||
prop: 'contactPhone',
|
||||
minWidth: 150,
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [{ max: 20, message: '最多 20 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
@@ -221,6 +281,7 @@ export default {
|
||||
minWidth: 180,
|
||||
overHidden: true,
|
||||
span: 24,
|
||||
placeholder: '地图选址',
|
||||
rules: [{ max: 100, message: '最多 100 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
@@ -230,6 +291,8 @@ export default {
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
minWidth: 170,
|
||||
span: 12,
|
||||
placeholder: '请选择',
|
||||
},
|
||||
{
|
||||
label: '下次保养里程/航程',
|
||||
@@ -238,34 +301,29 @@ export default {
|
||||
precision: 2,
|
||||
minWidth: 170,
|
||||
slot: true,
|
||||
span: 12,
|
||||
append: '公里',
|
||||
placeholder: '请输入',
|
||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
type: 'upload',
|
||||
listType: 'text',
|
||||
multiple: true,
|
||||
accept: '.jpg,.jpeg,.png,.pdf',
|
||||
propsHttp: {
|
||||
res: 'data',
|
||||
url: 'link',
|
||||
name: 'name',
|
||||
},
|
||||
action: '/blade-resource/oss/endpoint/put-file',
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
type: 'textarea',
|
||||
minRows: 4,
|
||||
minRows: 5,
|
||||
span: 24,
|
||||
hide: true,
|
||||
placeholder: '请输入',
|
||||
rules: [{ max: 500, message: '最多 500 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
formslot: true,
|
||||
},
|
||||
{
|
||||
label: '创建时间',
|
||||
prop: 'createTime',
|
||||
@@ -341,6 +399,7 @@ export default {
|
||||
],
|
||||
},
|
||||
excelOption: {
|
||||
labelPosition: 'right',
|
||||
submitBtn: false,
|
||||
emptyBtn: false,
|
||||
column: [
|
||||
@@ -385,6 +444,9 @@ export default {
|
||||
editBtn: this.hasPermission('maintenance_plan_edit'),
|
||||
};
|
||||
},
|
||||
vehicleNoPlaceholder() {
|
||||
return this.form.vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
},
|
||||
ids() {
|
||||
let ids = [];
|
||||
this.selectionList.forEach(ele => {
|
||||
@@ -397,6 +459,41 @@ export default {
|
||||
hasPermission(code) {
|
||||
return this.isAdmin || this.validData(this.permission[code], false);
|
||||
},
|
||||
handleVehicleTypeChange(vehicleType) {
|
||||
this.updateVehicleType(vehicleType);
|
||||
if (!this.form.id && this.form.vehicleNo) {
|
||||
this.form.vehicleNo = '';
|
||||
}
|
||||
},
|
||||
updateVehicleType(vehicleType) {
|
||||
const mileageUnit = vehicleType === '船舶' ? '海里' : '公里';
|
||||
const mileageColumn = this.findColumn(this.option.column, 'mileage');
|
||||
const nextMaintenanceMileageColumn = this.findColumn(
|
||||
this.option.column,
|
||||
'nextMaintenanceMileage'
|
||||
);
|
||||
const mileageUnitColumn = this.findColumn(this.option.column, 'mileageUnit');
|
||||
mileageColumn.append = mileageUnit;
|
||||
nextMaintenanceMileageColumn.append = mileageUnit;
|
||||
mileageUnitColumn.value = mileageUnit;
|
||||
this.form.mileageUnit = mileageUnit;
|
||||
},
|
||||
fetchVehicleOptions(queryString, callback) {
|
||||
const vehicleType = this.form.vehicleType || '车辆';
|
||||
const request = vehicleType === '船舶' ? getShipList : getVehicleList;
|
||||
const params =
|
||||
vehicleType === '船舶' ? { shipIdentifierNo: queryString } : { plateNo: queryString };
|
||||
request(1, 20, params)
|
||||
.then(res => {
|
||||
const records = res.data.data.records || [];
|
||||
callback(
|
||||
records.map(item => ({
|
||||
value: vehicleType === '船舶' ? item.shipIdentifierNo || item.shipName : item.plateNo,
|
||||
}))
|
||||
);
|
||||
})
|
||||
.catch(() => callback([]));
|
||||
},
|
||||
formatMileage(value, unit) {
|
||||
if (value === undefined || value === null || value === '') return '';
|
||||
return `${Math.max(Number(value), 0)} ${unit || '公里'}`;
|
||||
@@ -409,12 +506,20 @@ export default {
|
||||
const attachments = JSON.parse(value);
|
||||
return Array.isArray(attachments) ? `${attachments.length} 个` : '1 个';
|
||||
} catch (error) {
|
||||
return value
|
||||
.split(',')
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean).length + ' 个';
|
||||
return (
|
||||
value
|
||||
.split(',')
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean).length + ' 个'
|
||||
);
|
||||
}
|
||||
},
|
||||
isEmpty(value) {
|
||||
return value === undefined || value === null || value === '';
|
||||
},
|
||||
toNumber(value) {
|
||||
return this.isEmpty(value) ? null : Number(value);
|
||||
},
|
||||
parseAttachments(value) {
|
||||
if (!value || Array.isArray(value)) return value;
|
||||
if (typeof value !== 'string') return [];
|
||||
@@ -440,14 +545,31 @@ export default {
|
||||
},
|
||||
normalizeRow(row) {
|
||||
const values = { ...row };
|
||||
if (!values.mileageUnit) {
|
||||
values.mileageUnit = values.vehicleType === '船舶' ? '海里' : '公里';
|
||||
}
|
||||
values.vehicleType = values.vehicleType || '车辆';
|
||||
values.mileageUnit = values.vehicleType === '船舶' ? '海里' : '公里';
|
||||
values.attachments = this.stringifyAttachments(values.attachments);
|
||||
return values;
|
||||
},
|
||||
validateRow(row) {
|
||||
const mileage = this.toNumber(row.mileage);
|
||||
const nextMaintenanceMileage = this.toNumber(row.nextMaintenanceMileage);
|
||||
if (
|
||||
mileage !== null &&
|
||||
nextMaintenanceMileage !== null &&
|
||||
nextMaintenanceMileage <= mileage
|
||||
) {
|
||||
this.$message.warning('下次保养里程/航程应大于本次里程/航程数');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
rowSave(row, done, loading) {
|
||||
add(this.normalizeRow(row)).then(
|
||||
const values = this.normalizeRow(row);
|
||||
if (!this.validateRow(values)) {
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
add(values).then(
|
||||
() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message({ type: 'success', message: '操作成功!' });
|
||||
@@ -460,7 +582,12 @@ export default {
|
||||
);
|
||||
},
|
||||
rowUpdate(row, index, done, loading) {
|
||||
update(this.normalizeRow(row)).then(
|
||||
const values = this.normalizeRow(row);
|
||||
if (!this.validateRow(values)) {
|
||||
loading();
|
||||
return;
|
||||
}
|
||||
update(values).then(
|
||||
() => {
|
||||
this.onLoad(this.page);
|
||||
this.$message({ type: 'success', message: '操作成功!' });
|
||||
@@ -502,11 +629,20 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
if (type === 'add') {
|
||||
this.form.vehicleType = '车辆';
|
||||
this.form.mileageUnit = '公里';
|
||||
this.updateVehicleType(this.form.vehicleType);
|
||||
}
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
detail.vehicleType = detail.vehicleType || '车辆';
|
||||
detail.mileageUnit = detail.vehicleType === '船舶' ? '海里' : '公里';
|
||||
this.form = detail;
|
||||
this.updateVehicleType(detail.vehicleType);
|
||||
});
|
||||
}
|
||||
done();
|
||||
@@ -551,12 +687,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '保养记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出保养记录数据?', '提示', {
|
||||
@@ -565,7 +696,10 @@ export default {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-transport/maintenance-plan/export-maintenance-plan', this.buildExportParams())
|
||||
exportBlob(
|
||||
'/blade-transport/maintenance-plan/export-maintenance-plan',
|
||||
this.buildExportParams()
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `保养记录${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
@@ -583,7 +717,9 @@ export default {
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(
|
||||
`/blade-transport/maintenance-plan/export-template?${this.website.tokenHeader}=${getToken()}`
|
||||
`/blade-transport/maintenance-plan/export-template?${
|
||||
this.website.tokenHeader
|
||||
}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '保养记录模板.xlsx');
|
||||
});
|
||||
@@ -598,5 +734,9 @@ export default {
|
||||
:deep(.el-table td .cell) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&__input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -59,15 +59,44 @@
|
||||
{{ row.vehicleNo }}
|
||||
</el-button>
|
||||
</template>
|
||||
<template #vehicleNoForm>
|
||||
<el-autocomplete
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
:placeholder="vehicleNoPlaceholder"
|
||||
value-key="value"
|
||||
class="maintenance-record-page__input"
|
||||
/>
|
||||
</template>
|
||||
<template #mileage="{ row }">
|
||||
<span>{{ formatMileage(row.mileage, row.mileageUnit) }}</span>
|
||||
</template>
|
||||
<template #attachments="{ row }">
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
</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>
|
||||
@@ -80,9 +109,12 @@
|
||||
|
||||
<script>
|
||||
import { getList, getDetail, add, update, remove } from '@/api/vehicle/maintenance-record';
|
||||
import { getList as getVehicleList } from '@/api/transportCapacity/transport-vehicle';
|
||||
import { getList as getShipList } from '@/api/transportCapacity/transport-ship';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { formatUpdateUserName } from '@/utils/audit';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
@@ -106,6 +138,7 @@ export default {
|
||||
loading: true,
|
||||
excelBox: false,
|
||||
excelForm: {},
|
||||
isDetailLoading: false,
|
||||
page: {
|
||||
pageSize: 10,
|
||||
pageSizes: [10, 20, 50, 100],
|
||||
@@ -113,13 +146,20 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
boxType: '',
|
||||
option: {
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
dialogWidth: 980,
|
||||
dialogWidth: 960,
|
||||
labelPosition: 'right',
|
||||
labelWidth: 'auto',
|
||||
searchLabelWidth: 160,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
viewBtn: true,
|
||||
@@ -138,14 +178,19 @@ export default {
|
||||
],
|
||||
value: '车辆',
|
||||
search: true,
|
||||
span: 24,
|
||||
change: ({ value }) => this.updateVehicleType(value || '车辆'),
|
||||
rules: [{ required: true, message: '请选择车船类型', trigger: 'change' }],
|
||||
},
|
||||
{
|
||||
label: '车牌号/船号',
|
||||
prop: 'vehicleNo',
|
||||
slot: true,
|
||||
formslot: true,
|
||||
search: true,
|
||||
minWidth: 130,
|
||||
span: 12,
|
||||
placeholder: '输入车牌号/船号查询选择',
|
||||
rules: [
|
||||
{ required: true, message: '请输入车牌号/船号', trigger: 'blur' },
|
||||
{ max: 30, message: '最多 30 个字符', trigger: 'blur' },
|
||||
@@ -154,6 +199,8 @@ export default {
|
||||
{
|
||||
label: '维修人',
|
||||
prop: 'maintainer',
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [{ max: 20, message: '最多 20 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
@@ -163,12 +210,16 @@ export default {
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
minWidth: 170,
|
||||
span: 12,
|
||||
placeholder: '日期时间选择器',
|
||||
rules: [{ required: true, message: '请选择维修时间', trigger: 'click' }],
|
||||
},
|
||||
{
|
||||
label: '维修位置',
|
||||
prop: 'location',
|
||||
minWidth: 160,
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [{ max: 100, message: '最多 100 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
@@ -176,6 +227,8 @@ export default {
|
||||
prop: 'replacedPart',
|
||||
minWidth: 160,
|
||||
overHidden: true,
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [{ max: 200, message: '最多 200 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
@@ -183,6 +236,9 @@ export default {
|
||||
prop: 'cost',
|
||||
type: 'number',
|
||||
precision: 2,
|
||||
append: '元',
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [
|
||||
{ required: true, message: '请输入费用', trigger: 'blur' },
|
||||
{ validator: validateNonNegative, trigger: 'blur' },
|
||||
@@ -192,14 +248,27 @@ export default {
|
||||
label: '维修单位',
|
||||
prop: 'company',
|
||||
minWidth: 180,
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [{ max: 50, message: '最多 50 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '联系方式',
|
||||
prop: 'contact',
|
||||
minWidth: 150,
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [{ max: 20, message: '最多 20 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '地址',
|
||||
prop: 'address',
|
||||
minWidth: 180,
|
||||
overHidden: true,
|
||||
span: 24,
|
||||
placeholder: '地图选址',
|
||||
rules: [{ max: 100, message: '最多 100 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '出厂时间',
|
||||
prop: 'factoryTime',
|
||||
@@ -207,6 +276,8 @@ export default {
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
minWidth: 170,
|
||||
span: 12,
|
||||
placeholder: '日期时间选择器',
|
||||
},
|
||||
{
|
||||
label: '里程/航程数',
|
||||
@@ -214,7 +285,10 @@ export default {
|
||||
type: 'number',
|
||||
precision: 2,
|
||||
minWidth: 130,
|
||||
append: '公里',
|
||||
slot: true,
|
||||
span: 12,
|
||||
placeholder: '请输入',
|
||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
@@ -229,38 +303,22 @@ export default {
|
||||
hide: true,
|
||||
},
|
||||
{
|
||||
label: '地址',
|
||||
prop: 'address',
|
||||
minWidth: 180,
|
||||
overHidden: true,
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
type: 'textarea',
|
||||
minRows: 5,
|
||||
span: 24,
|
||||
rules: [{ max: 100, message: '最多 100 个字符', trigger: 'blur' }],
|
||||
hide: true,
|
||||
placeholder: '请输入',
|
||||
rules: [{ max: 500, message: '最多 500 个字符', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
label: '附件',
|
||||
prop: 'attachments',
|
||||
type: 'upload',
|
||||
listType: 'text',
|
||||
multiple: true,
|
||||
accept: '.jpg,.jpeg,.png,.pdf',
|
||||
propsHttp: {
|
||||
res: 'data',
|
||||
url: 'link',
|
||||
name: 'name',
|
||||
},
|
||||
action: '/blade-resource/oss/endpoint/put-file',
|
||||
span: 24,
|
||||
minWidth: 100,
|
||||
slot: true,
|
||||
},
|
||||
{
|
||||
label: '备注',
|
||||
prop: 'remark',
|
||||
type: 'textarea',
|
||||
minRows: 4,
|
||||
span: 24,
|
||||
hide: true,
|
||||
rules: [{ max: 500, message: '最多 500 个字符', trigger: 'blur' }],
|
||||
formslot: true,
|
||||
},
|
||||
{
|
||||
label: '创建时间',
|
||||
@@ -337,6 +395,7 @@ export default {
|
||||
],
|
||||
},
|
||||
excelOption: {
|
||||
labelPosition: 'right',
|
||||
submitBtn: false,
|
||||
emptyBtn: false,
|
||||
column: [
|
||||
@@ -381,6 +440,9 @@ export default {
|
||||
editBtn: this.hasPermission('maintenance_record_edit'),
|
||||
};
|
||||
},
|
||||
vehicleNoPlaceholder() {
|
||||
return this.form.vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
},
|
||||
ids() {
|
||||
let ids = [];
|
||||
this.selectionList.forEach(ele => {
|
||||
@@ -389,10 +451,50 @@ export default {
|
||||
return ids.join(',');
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'form.vehicleType': {
|
||||
handler(value, oldValue) {
|
||||
this.updateVehicleType(value || '车辆', oldValue);
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hasPermission(code) {
|
||||
return this.isAdmin || this.validData(this.permission[code], false);
|
||||
},
|
||||
updateVehicleType(vehicleType, oldValue) {
|
||||
const mileageUnit = vehicleType === '船舶' ? '海里' : '公里';
|
||||
const vehicleTypeColumn = this.findColumn(this.option.column, 'vehicleType');
|
||||
const vehicleNoColumn = this.findColumn(this.option.column, 'vehicleNo');
|
||||
const mileageColumn = this.findColumn(this.option.column, 'mileage');
|
||||
const mileageUnitColumn = this.findColumn(this.option.column, 'mileageUnit');
|
||||
vehicleNoColumn.placeholder =
|
||||
vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
vehicleTypeColumn.disabled = Boolean(this.form.id);
|
||||
mileageColumn.append = mileageUnit;
|
||||
mileageUnitColumn.value = mileageUnit;
|
||||
this.form.mileageUnit = mileageUnit;
|
||||
if (!this.isDetailLoading && oldValue && vehicleType !== oldValue && this.form.vehicleNo) {
|
||||
this.form.vehicleNo = '';
|
||||
}
|
||||
},
|
||||
fetchVehicleOptions(queryString, callback) {
|
||||
const vehicleType = this.form.vehicleType || '车辆';
|
||||
const request = vehicleType === '船舶' ? getShipList : getVehicleList;
|
||||
const params =
|
||||
vehicleType === '船舶' ? { shipIdentifierNo: queryString } : { plateNo: queryString };
|
||||
request(1, 20, params)
|
||||
.then(res => {
|
||||
const records = res.data.data.records || [];
|
||||
callback(
|
||||
records.map(item => ({
|
||||
value: vehicleType === '船舶' ? item.shipIdentifierNo || item.shipName : item.plateNo,
|
||||
}))
|
||||
);
|
||||
})
|
||||
.catch(() => callback([]));
|
||||
},
|
||||
formatMileage(value, unit) {
|
||||
if (value === undefined || value === null || value === '') return '';
|
||||
return `${Math.max(Number(value), 0)} ${unit || '公里'}`;
|
||||
@@ -405,10 +507,12 @@ export default {
|
||||
const attachments = JSON.parse(value);
|
||||
return Array.isArray(attachments) ? `${attachments.length} 个` : '1 个';
|
||||
} catch (error) {
|
||||
return value
|
||||
.split(',')
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean).length + ' 个';
|
||||
return (
|
||||
value
|
||||
.split(',')
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean).length + ' 个'
|
||||
);
|
||||
}
|
||||
},
|
||||
parseAttachments(value) {
|
||||
@@ -436,8 +540,13 @@ export default {
|
||||
},
|
||||
normalizeRow(row) {
|
||||
const values = { ...row };
|
||||
if (!values.mileageUnit) {
|
||||
values.mileageUnit = values.vehicleType === '船舶' ? '海里' : '公里';
|
||||
values.vehicleType = values.vehicleType || '车辆';
|
||||
values.mileageUnit = values.vehicleType === '船舶' ? '海里' : '公里';
|
||||
if (values.vehicleNo) {
|
||||
values.vehicleNo =
|
||||
values.vehicleType === '船舶'
|
||||
? values.vehicleNo.trim()
|
||||
: values.vehicleNo.trim().toUpperCase();
|
||||
}
|
||||
values.attachments = this.stringifyAttachments(values.attachments);
|
||||
return values;
|
||||
@@ -498,12 +607,28 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
if (type === 'add') {
|
||||
this.form = {
|
||||
vehicleType: '车辆',
|
||||
mileageUnit: '公里',
|
||||
};
|
||||
this.updateVehicleType('车辆');
|
||||
}
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
this.form = detail;
|
||||
});
|
||||
this.isDetailLoading = true;
|
||||
getDetail(this.form.id)
|
||||
.then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
detail.vehicleType = detail.vehicleType || '车辆';
|
||||
detail.mileageUnit = detail.vehicleType === '船舶' ? '海里' : '公里';
|
||||
this.form = detail;
|
||||
this.updateVehicleType(detail.vehicleType);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isDetailLoading = false;
|
||||
});
|
||||
}
|
||||
done();
|
||||
},
|
||||
@@ -547,12 +672,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '维修记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出维修记录数据?', '提示', {
|
||||
@@ -561,7 +681,10 @@ export default {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-transport/maintenance-record/export-maintenance-record', this.buildExportParams())
|
||||
exportBlob(
|
||||
'/blade-transport/maintenance-record/export-maintenance-record',
|
||||
this.buildExportParams()
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `维修记录${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
@@ -579,7 +702,9 @@ export default {
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(
|
||||
`/blade-transport/maintenance-record/export-template?${this.website.tokenHeader}=${getToken()}`
|
||||
`/blade-transport/maintenance-record/export-template?${
|
||||
this.website.tokenHeader
|
||||
}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '维修记录模板.xlsx');
|
||||
});
|
||||
@@ -594,5 +719,9 @@ export default {
|
||||
:deep(.el-table td .cell) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&__input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -59,20 +59,57 @@
|
||||
{{ row.vehicleNo }}
|
||||
</el-button>
|
||||
</template>
|
||||
<template #previousMonthMileage="{ row }">
|
||||
<span>{{ formatMileage(row.previousMonthMileage, row.mileageUnit) }}</span>
|
||||
</template>
|
||||
<template #currentMonthMileage="{ row }">
|
||||
<span>{{ formatMileage(row.currentMonthMileage, row.mileageUnit) }}</span>
|
||||
</template>
|
||||
<template #monthlyMileage="{ row }">
|
||||
<span>{{ formatMileage(row.monthlyMileage, row.mileageUnit) }}</span>
|
||||
</template>
|
||||
<template #totalMileage="{ row }">
|
||||
<span>{{ formatMileage(row.totalMileage, row.mileageUnit) }}</span>
|
||||
</template>
|
||||
<template #vehicleNoForm>
|
||||
<el-autocomplete
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
:disabled="Boolean(form.id)"
|
||||
clearable
|
||||
placeholder="输入车牌号模糊查询选择"
|
||||
:placeholder="vehicleNoPlaceholder"
|
||||
value-key="value"
|
||||
class="mileage-record-page__input"
|
||||
/>
|
||||
</template>
|
||||
<template #totalMileageStart-search="{ row }">
|
||||
<div class="mileage-record-page__range">
|
||||
<el-input
|
||||
v-model="row.totalMileageStart"
|
||||
clearable
|
||||
placeholder="请输入"
|
||||
type="number"
|
||||
class="mileage-record-page__range-input"
|
||||
/>
|
||||
<span class="mileage-record-page__range-separator">-</span>
|
||||
<el-input
|
||||
v-model="row.totalMileageEnd"
|
||||
clearable
|
||||
placeholder="请输入"
|
||||
type="number"
|
||||
class="mileage-record-page__range-input"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #attachments="{ row }">
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</avue-crud>
|
||||
<empty-pagination
|
||||
:page="page"
|
||||
@@ -81,7 +118,7 @@
|
||||
@load="onLoad(page, query)"
|
||||
/>
|
||||
<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>
|
||||
@@ -95,9 +132,11 @@
|
||||
<script>
|
||||
import { add, getDetail, getList, remove, update } from '@/api/vehicle/mileage-record';
|
||||
import { getList as getVehicleList } from '@/api/transportCapacity/transport-vehicle';
|
||||
import { getList as getShipList } from '@/api/transportCapacity/transport-ship';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/mileage-record';
|
||||
@@ -121,6 +160,7 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
boxType: '',
|
||||
data: [],
|
||||
};
|
||||
},
|
||||
@@ -141,6 +181,9 @@ export default {
|
||||
editBtn: this.hasPermission('mileage_record_edit'),
|
||||
};
|
||||
},
|
||||
vehicleNoPlaceholder() {
|
||||
return this.form.vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
},
|
||||
ids() {
|
||||
const ids = [];
|
||||
this.selectionList.forEach(ele => {
|
||||
@@ -149,10 +192,43 @@ export default {
|
||||
return ids.join(',');
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'form.vehicleType': {
|
||||
handler(value) {
|
||||
this.updateVehicleTypeDisplays(value || '车辆');
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hasPermission(code) {
|
||||
return this.isAdmin || this.validData(this.permission[code], false);
|
||||
},
|
||||
updateVehicleTypeDisplays(vehicleType) {
|
||||
const isShip = vehicleType === '船舶';
|
||||
const unit = isShip ? '海里' : '公里';
|
||||
const vehicleTypeColumn = this.findColumn(this.option.column, 'vehicleType');
|
||||
const labelMap = {
|
||||
previousMonthMileage: isShip ? '上月统计航程数' : '上月统计里程数',
|
||||
currentMonthMileage: isShip ? '本月统计航程数' : '本月统计里程数',
|
||||
monthlyMileage: isShip ? '本月航行航程数' : '本月行驶里程数',
|
||||
totalMileage: isShip ? '累计航程数' : '累计行驶里程数',
|
||||
totalMileageStart: isShip ? '累计航程' : '累计行驶里程',
|
||||
totalMileageEnd: isShip ? '累计航程数结束值' : '累计行驶里程数结束值',
|
||||
};
|
||||
Object.keys(labelMap).forEach(prop => {
|
||||
const column = this.findColumn(this.option.column, prop);
|
||||
column.label = labelMap[prop];
|
||||
column.append = unit;
|
||||
});
|
||||
vehicleTypeColumn.disabled = Boolean(this.form.id);
|
||||
const unitColumn = this.findColumn(this.option.column, 'mileageUnit');
|
||||
unitColumn.value = unit;
|
||||
this.form.mileageUnit = unit;
|
||||
if (!this.form.id && this.form.vehicleNo) {
|
||||
this.form.vehicleNo = '';
|
||||
}
|
||||
},
|
||||
initDeptTree() {
|
||||
getDeptTree(this.userInfo.tenantId).then(res => {
|
||||
const column = this.findColumn(this.option.column, 'createDept');
|
||||
@@ -160,13 +236,27 @@ export default {
|
||||
});
|
||||
},
|
||||
fetchVehicleOptions(queryString, callback) {
|
||||
getVehicleList(1, 20, { plateNo: queryString })
|
||||
const vehicleType = this.form.vehicleType || '车辆';
|
||||
const request = vehicleType === '船舶' ? getShipList : getVehicleList;
|
||||
const params =
|
||||
vehicleType === '船舶' ? { shipIdentifierNo: queryString } : { plateNo: queryString };
|
||||
request(1, 20, params)
|
||||
.then(res => {
|
||||
const records = res.data.data.records || [];
|
||||
callback(records.map(item => ({ value: item.plateNo })));
|
||||
callback(
|
||||
records.map(item => ({
|
||||
value: vehicleType === '船舶' ? item.shipIdentifierNo || item.shipName : item.plateNo,
|
||||
}))
|
||||
);
|
||||
})
|
||||
.catch(() => callback([]));
|
||||
},
|
||||
formatMileage(value, unit) {
|
||||
if (this.isEmpty(value)) {
|
||||
return '';
|
||||
}
|
||||
return `${value} ${unit || '公里'}`;
|
||||
},
|
||||
formatAttachments(value) {
|
||||
if (!value) return '';
|
||||
if (Array.isArray(value)) return `${value.length} 个`;
|
||||
@@ -211,12 +301,21 @@ export default {
|
||||
},
|
||||
normalizeRow(row) {
|
||||
const values = { ...row };
|
||||
values.vehicleType = values.vehicleType || '车辆';
|
||||
values.mileageUnit = values.vehicleType === '船舶' ? '海里' : '公里';
|
||||
if (values.vehicleNo) {
|
||||
values.vehicleNo = values.vehicleNo.trim().toUpperCase();
|
||||
values.vehicleNo =
|
||||
values.vehicleType === '船舶'
|
||||
? values.vehicleNo.trim()
|
||||
: values.vehicleNo.trim().toUpperCase();
|
||||
}
|
||||
const previousMonthMileage = this.toNumber(values.previousMonthMileage);
|
||||
const currentMonthMileage = this.toNumber(values.currentMonthMileage);
|
||||
if (this.isEmpty(values.monthlyMileage) && previousMonthMileage !== null && currentMonthMileage !== null) {
|
||||
if (
|
||||
this.isEmpty(values.monthlyMileage) &&
|
||||
previousMonthMileage !== null &&
|
||||
currentMonthMileage !== null
|
||||
) {
|
||||
values.monthlyMileage = this.toMoney(currentMonthMileage - previousMonthMileage);
|
||||
}
|
||||
values.attachments = this.stringifyAttachments(values.attachments);
|
||||
@@ -237,11 +336,12 @@ export default {
|
||||
return true;
|
||||
},
|
||||
validateRow(row) {
|
||||
const isShip = row.vehicleType === '船舶';
|
||||
const mileageFields = [
|
||||
['previousMonthMileage', '上月统计里程'],
|
||||
['currentMonthMileage', '本月统计里程'],
|
||||
['monthlyMileage', '本月行驶里程'],
|
||||
['totalMileage', '累计行驶里程'],
|
||||
['previousMonthMileage', isShip ? '上月统计航程数' : '上月统计里程数'],
|
||||
['currentMonthMileage', isShip ? '本月统计航程数' : '本月统计里程数'],
|
||||
['monthlyMileage', isShip ? '本月航行航程数' : '本月行驶里程数'],
|
||||
['totalMileage', isShip ? '累计航程数' : '累计行驶里程数'],
|
||||
];
|
||||
if (!mileageFields.every(([prop, label]) => this.validateMileage(row[prop], label))) {
|
||||
return false;
|
||||
@@ -256,11 +356,21 @@ export default {
|
||||
monthlyMileage !== null &&
|
||||
this.toMoney(currentMonthMileage - previousMonthMileage) !== this.toMoney(monthlyMileage)
|
||||
) {
|
||||
this.$message.warning('本月行驶里程应等于本月统计里程减去上月统计里程');
|
||||
this.$message.warning(
|
||||
isShip
|
||||
? '本月航行航程数应等于本月统计航程数减去上月统计航程数'
|
||||
: '本月行驶里程数应等于本月统计里程数减去上月统计里程数'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (totalMileage !== null && currentMonthMileage !== null && totalMileage < currentMonthMileage) {
|
||||
this.$message.warning('累计行驶里程应大于等于本月统计里程');
|
||||
if (
|
||||
totalMileage !== null &&
|
||||
currentMonthMileage !== null &&
|
||||
totalMileage < currentMonthMileage
|
||||
) {
|
||||
this.$message.warning(
|
||||
isShip ? '累计航程数应大于等于本月统计航程数' : '累计行驶里程数应大于等于本月统计里程数'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -331,19 +441,32 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
const vehicleNoColumn = this.findColumn(this.option.column, 'vehicleNo');
|
||||
vehicleNoColumn.disabled = type !== 'add';
|
||||
if (type === 'add') {
|
||||
this.form.vehicleType = '车辆';
|
||||
this.form.mileageUnit = '公里';
|
||||
this.updateVehicleTypeDisplays(this.form.vehicleType);
|
||||
}
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
detail.vehicleType = detail.vehicleType || this.form.vehicleType || '车辆';
|
||||
detail.mileageUnit = detail.vehicleType === '船舶' ? '海里' : '公里';
|
||||
this.form = detail;
|
||||
this.updateVehicleTypeDisplays(detail.vehicleType);
|
||||
});
|
||||
}
|
||||
done();
|
||||
},
|
||||
searchReset() {
|
||||
this.query = {};
|
||||
if (this.$refs.crud?.search) {
|
||||
this.$refs.crud.search.totalMileageStart = undefined;
|
||||
this.$refs.crud.search.totalMileageEnd = undefined;
|
||||
}
|
||||
this.onLoad(this.page);
|
||||
},
|
||||
searchChange(params, done) {
|
||||
@@ -382,12 +505,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '里程记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出里程记录数据?', '提示', {
|
||||
@@ -396,7 +514,10 @@ export default {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-transport/mileage-record/export-mileage-record', this.buildExportParams())
|
||||
exportBlob(
|
||||
'/blade-transport/mileage-record/export-mileage-record',
|
||||
this.buildExportParams()
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `里程记录${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
@@ -413,11 +534,11 @@ export default {
|
||||
};
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(`/blade-transport/mileage-record/export-template?${this.website.tokenHeader}=${getToken()}`).then(
|
||||
res => {
|
||||
downloadXls(res.data, '里程记录模板.xlsx');
|
||||
}
|
||||
);
|
||||
exportBlob(
|
||||
`/blade-transport/mileage-record/export-template?${this.website.tokenHeader}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '里程记录模板.xlsx');
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -433,5 +554,21 @@ export default {
|
||||
&__input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__range {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__range-input {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
&__range-separator {
|
||||
color: #606266;
|
||||
line-height: 32px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -63,8 +63,9 @@
|
||||
<el-autocomplete
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
placeholder="输入车牌号/船号查询选择"
|
||||
:placeholder="vehicleNoPlaceholder"
|
||||
value-key="value"
|
||||
class="oil-electric-record-page__input"
|
||||
/>
|
||||
@@ -72,9 +73,15 @@
|
||||
<template #attachments="{ row }">
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</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>
|
||||
@@ -92,6 +99,7 @@ import { getList as getShipList } from '@/api/transportCapacity/transport-ship';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/oil-electric-record';
|
||||
@@ -106,6 +114,7 @@ export default {
|
||||
loading: true,
|
||||
excelBox: false,
|
||||
excelForm: {},
|
||||
isDetailLoading: false,
|
||||
option,
|
||||
excelOption,
|
||||
page: {
|
||||
@@ -115,6 +124,7 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
boxType: '',
|
||||
data: [],
|
||||
};
|
||||
},
|
||||
@@ -135,6 +145,9 @@ export default {
|
||||
editBtn: this.hasPermission('oil_electric_record_edit'),
|
||||
};
|
||||
},
|
||||
vehicleNoPlaceholder() {
|
||||
return this.form.vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
},
|
||||
ids() {
|
||||
const ids = [];
|
||||
this.selectionList.forEach(ele => {
|
||||
@@ -145,8 +158,8 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
'form.vehicleType': {
|
||||
handler() {
|
||||
this.updateVehicleType();
|
||||
handler(value, oldValue) {
|
||||
this.updateVehicleType(value || '车辆', oldValue);
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
@@ -167,8 +180,11 @@ export default {
|
||||
column.dicData = res.data.data;
|
||||
});
|
||||
},
|
||||
updateVehicleType() {
|
||||
if (!this.form.id && this.form.vehicleNo) {
|
||||
updateVehicleType(vehicleType, oldValue) {
|
||||
const vehicleNoColumn = this.findColumn(this.option.column, 'vehicleNo');
|
||||
vehicleNoColumn.placeholder =
|
||||
vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
if (!this.isDetailLoading && oldValue && vehicleType !== oldValue && this.form.vehicleNo) {
|
||||
this.form.vehicleNo = '';
|
||||
}
|
||||
},
|
||||
@@ -238,7 +254,10 @@ export default {
|
||||
values.vehicleType = values.vehicleType || '车辆';
|
||||
values.dataSource = values.dataSource || '手工录入';
|
||||
if (values.vehicleNo) {
|
||||
values.vehicleNo = values.vehicleType === '船舶' ? values.vehicleNo.trim() : values.vehicleNo.trim().toUpperCase();
|
||||
values.vehicleNo =
|
||||
values.vehicleType === '船舶'
|
||||
? values.vehicleNo.trim()
|
||||
: values.vehicleNo.trim().toUpperCase();
|
||||
}
|
||||
if (values.feeType === '充电') {
|
||||
values.oilProduct = undefined;
|
||||
@@ -341,17 +360,26 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
if (type === 'add') {
|
||||
this.form = { vehicleType: '车辆', feeType: '加油', dataSource: '手工录入' };
|
||||
this.updateVehicleType('车辆');
|
||||
this.updateFeeType('加油');
|
||||
}
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
this.form = detail;
|
||||
this.updateFeeType(detail.feeType);
|
||||
});
|
||||
this.isDetailLoading = true;
|
||||
getDetail(this.form.id)
|
||||
.then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
detail.vehicleType = detail.vehicleType || '车辆';
|
||||
this.form = detail;
|
||||
this.updateVehicleType(detail.vehicleType);
|
||||
this.updateFeeType(detail.feeType);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isDetailLoading = false;
|
||||
});
|
||||
}
|
||||
done();
|
||||
},
|
||||
@@ -395,12 +423,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '油电记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出油电记录数据?', '提示', {
|
||||
@@ -409,7 +432,10 @@ export default {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-transport/oil-electric-record/export-oil-electric-record', this.buildExportParams())
|
||||
exportBlob(
|
||||
'/blade-transport/oil-electric-record/export-oil-electric-record',
|
||||
this.buildExportParams()
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `油电记录${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
@@ -426,11 +452,13 @@ export default {
|
||||
};
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(`/blade-transport/oil-electric-record/export-template?${this.website.tokenHeader}=${getToken()}`).then(
|
||||
res => {
|
||||
downloadXls(res.data, '油电记录模板.xlsx');
|
||||
}
|
||||
);
|
||||
exportBlob(
|
||||
`/blade-transport/oil-electric-record/export-template?${
|
||||
this.website.tokenHeader
|
||||
}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '油电记录模板.xlsx');
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -63,8 +63,9 @@
|
||||
<el-autocomplete
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
placeholder="输入车牌号/船号查询选择"
|
||||
:placeholder="vehicleNoPlaceholder"
|
||||
value-key="value"
|
||||
class="other-expense-record-page__input"
|
||||
/>
|
||||
@@ -72,9 +73,15 @@
|
||||
<template #attachments="{ row }">
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</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>
|
||||
@@ -92,6 +99,7 @@ import { getList as getShipList } from '@/api/transportCapacity/transport-ship';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/other-expense-record';
|
||||
@@ -106,6 +114,7 @@ export default {
|
||||
loading: true,
|
||||
excelBox: false,
|
||||
excelForm: {},
|
||||
isDetailLoading: false,
|
||||
option,
|
||||
excelOption,
|
||||
page: {
|
||||
@@ -115,6 +124,7 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
boxType: '',
|
||||
data: [],
|
||||
};
|
||||
},
|
||||
@@ -135,6 +145,9 @@ export default {
|
||||
editBtn: this.hasPermission('other_expense_record_edit'),
|
||||
};
|
||||
},
|
||||
vehicleNoPlaceholder() {
|
||||
return this.form.vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
},
|
||||
ids() {
|
||||
const ids = [];
|
||||
this.selectionList.forEach(ele => {
|
||||
@@ -145,8 +158,8 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
'form.vehicleType': {
|
||||
handler() {
|
||||
this.updateVehicleType();
|
||||
handler(value, oldValue) {
|
||||
this.updateVehicleType(value || '车辆', oldValue);
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
@@ -161,8 +174,11 @@ export default {
|
||||
column.dicData = res.data.data;
|
||||
});
|
||||
},
|
||||
updateVehicleType() {
|
||||
if (!this.form.id && this.form.vehicleNo) {
|
||||
updateVehicleType(vehicleType, oldValue) {
|
||||
const vehicleNoColumn = this.findColumn(this.option.column, 'vehicleNo');
|
||||
vehicleNoColumn.placeholder =
|
||||
vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
if (!this.isDetailLoading && oldValue && vehicleType !== oldValue && this.form.vehicleNo) {
|
||||
this.form.vehicleNo = '';
|
||||
}
|
||||
},
|
||||
@@ -223,7 +239,10 @@ export default {
|
||||
values.vehicleType = values.vehicleType || '车辆';
|
||||
values.dataSource = values.dataSource || '手工录入';
|
||||
if (values.vehicleNo) {
|
||||
values.vehicleNo = values.vehicleType === '船舶' ? values.vehicleNo.trim() : values.vehicleNo.trim().toUpperCase();
|
||||
values.vehicleNo =
|
||||
values.vehicleType === '船舶'
|
||||
? values.vehicleNo.trim()
|
||||
: values.vehicleNo.trim().toUpperCase();
|
||||
}
|
||||
values.attachments = this.stringifyAttachments(values.attachments);
|
||||
return values;
|
||||
@@ -320,19 +339,28 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
if (type === 'add') {
|
||||
this.form = {
|
||||
vehicleType: '车辆',
|
||||
expenseDate: this.$dayjs().format('YYYY-MM-DD'),
|
||||
dataSource: '手工录入',
|
||||
};
|
||||
this.updateVehicleType('车辆');
|
||||
}
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
this.form = detail;
|
||||
});
|
||||
this.isDetailLoading = true;
|
||||
getDetail(this.form.id)
|
||||
.then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
detail.vehicleType = detail.vehicleType || '车辆';
|
||||
this.form = detail;
|
||||
this.updateVehicleType(detail.vehicleType);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isDetailLoading = false;
|
||||
});
|
||||
}
|
||||
done();
|
||||
},
|
||||
@@ -386,12 +414,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '其他费用记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出其他费用记录数据?', '提示', {
|
||||
@@ -400,9 +423,15 @@ export default {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-transport/other-expense-record/export-other-expense-record', this.buildExportParams())
|
||||
exportBlob(
|
||||
'/blade-transport/other-expense-record/export-other-expense-record',
|
||||
this.buildExportParams()
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `其他费用记录${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
downloadXls(
|
||||
res.data,
|
||||
`其他费用记录${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
NProgress.done();
|
||||
@@ -417,11 +446,13 @@ export default {
|
||||
};
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(`/blade-transport/other-expense-record/export-template?${this.website.tokenHeader}=${getToken()}`).then(
|
||||
res => {
|
||||
downloadXls(res.data, '其他费用记录模板.xlsx');
|
||||
}
|
||||
);
|
||||
exportBlob(
|
||||
`/blade-transport/other-expense-record/export-template?${
|
||||
this.website.tokenHeader
|
||||
}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '其他费用记录模板.xlsx');
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -63,8 +63,9 @@
|
||||
<el-autocomplete
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
placeholder="请输入关键字"
|
||||
placeholder="输入车牌号查询选择"
|
||||
value-key="value"
|
||||
class="tire-replacement-record-page__input"
|
||||
/>
|
||||
@@ -72,6 +73,24 @@
|
||||
<template #attachments="{ row }">
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
</avue-crud>
|
||||
<empty-pagination
|
||||
:page="page"
|
||||
@@ -80,7 +99,7 @@
|
||||
@load="onLoad(page, query)"
|
||||
/>
|
||||
<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>
|
||||
@@ -97,6 +116,7 @@ import { getList as getVehicleList } from '@/api/transportCapacity/transport-veh
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/tire-replacement-record';
|
||||
@@ -120,6 +140,7 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
boxType: '',
|
||||
data: [],
|
||||
};
|
||||
},
|
||||
@@ -289,6 +310,7 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
if (type === 'add') {
|
||||
this.form = {};
|
||||
}
|
||||
@@ -341,12 +363,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '换胎记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出换胎记录数据?', '提示', {
|
||||
@@ -376,7 +393,9 @@ export default {
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(
|
||||
`/blade-transport/tire-replacement-record/export-template?${this.website.tokenHeader}=${getToken()}`
|
||||
`/blade-transport/tire-replacement-record/export-template?${
|
||||
this.website.tokenHeader
|
||||
}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '换胎记录模板.xlsx');
|
||||
});
|
||||
|
||||
@@ -63,8 +63,9 @@
|
||||
<el-autocomplete
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
placeholder="输入车牌号/船号模糊查询选择"
|
||||
:placeholder="vehicleNoPlaceholder"
|
||||
value-key="value"
|
||||
class="transport-change-record-page__input"
|
||||
/>
|
||||
@@ -72,9 +73,15 @@
|
||||
<template #attachments="{ row }">
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload v-model="form.attachments" :readonly="boxType === 'view'" />
|
||||
</template>
|
||||
</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>
|
||||
@@ -92,6 +99,7 @@ import { getList as getShipList } from '@/api/transportCapacity/transport-ship';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/transport-change-record';
|
||||
@@ -106,6 +114,7 @@ export default {
|
||||
loading: true,
|
||||
excelBox: false,
|
||||
excelForm: {},
|
||||
isDetailLoading: false,
|
||||
option,
|
||||
excelOption,
|
||||
page: {
|
||||
@@ -115,6 +124,7 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
boxType: '',
|
||||
data: [],
|
||||
};
|
||||
},
|
||||
@@ -135,6 +145,9 @@ export default {
|
||||
editBtn: this.hasPermission('transport_change_record_edit'),
|
||||
};
|
||||
},
|
||||
vehicleNoPlaceholder() {
|
||||
return this.form.vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
},
|
||||
ids() {
|
||||
const ids = [];
|
||||
this.selectionList.forEach(ele => {
|
||||
@@ -145,8 +158,8 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
'form.vehicleType': {
|
||||
handler(value) {
|
||||
this.updateVehicleType(value || '车辆');
|
||||
handler(value, oldValue) {
|
||||
this.updateVehicleType(value || '车辆', oldValue);
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
@@ -161,8 +174,11 @@ export default {
|
||||
column.dicData = res.data.data;
|
||||
});
|
||||
},
|
||||
updateVehicleType() {
|
||||
if (!this.form.id && this.form.vehicleNo) {
|
||||
updateVehicleType(vehicleType, oldValue) {
|
||||
const vehicleNoColumn = this.findColumn(this.option.column, 'vehicleNo');
|
||||
vehicleNoColumn.placeholder =
|
||||
vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
if (!this.isDetailLoading && oldValue && vehicleType !== oldValue && this.form.vehicleNo) {
|
||||
this.form.vehicleNo = '';
|
||||
}
|
||||
},
|
||||
@@ -219,7 +235,10 @@ export default {
|
||||
const values = { ...row };
|
||||
values.vehicleType = values.vehicleType || '车辆';
|
||||
if (values.vehicleNo) {
|
||||
values.vehicleNo = values.vehicleType === '船舶' ? values.vehicleNo.trim() : values.vehicleNo.trim().toUpperCase();
|
||||
values.vehicleNo =
|
||||
values.vehicleType === '船舶'
|
||||
? values.vehicleNo.trim()
|
||||
: values.vehicleNo.trim().toUpperCase();
|
||||
}
|
||||
values.attachments = this.stringifyAttachments(values.attachments);
|
||||
return values;
|
||||
@@ -301,15 +320,24 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
if (type === 'add') {
|
||||
this.form = { vehicleType: '车辆' };
|
||||
this.updateVehicleType('车辆');
|
||||
}
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
this.form = detail;
|
||||
});
|
||||
this.isDetailLoading = true;
|
||||
getDetail(this.form.id)
|
||||
.then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
detail.vehicleType = detail.vehicleType || '车辆';
|
||||
this.form = detail;
|
||||
this.updateVehicleType(detail.vehicleType);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isDetailLoading = false;
|
||||
});
|
||||
}
|
||||
done();
|
||||
},
|
||||
@@ -353,12 +381,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '变更记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出变更记录数据?', '提示', {
|
||||
@@ -388,7 +411,9 @@ export default {
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(
|
||||
`/blade-transport/transport-change-record/export-template?${this.website.tokenHeader}=${getToken()}`
|
||||
`/blade-transport/transport-change-record/export-template?${
|
||||
this.website.tokenHeader
|
||||
}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '变更记录模板.xlsx');
|
||||
});
|
||||
|
||||
@@ -63,8 +63,9 @@
|
||||
<el-autocomplete
|
||||
v-model="form.vehicleNo"
|
||||
:fetch-suggestions="fetchVehicleOptions"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
placeholder="输入车牌号/船号模糊查询选择"
|
||||
:placeholder="vehicleNoPlaceholder"
|
||||
value-key="value"
|
||||
class="violation-record-page__input"
|
||||
/>
|
||||
@@ -74,12 +75,20 @@
|
||||
v-if="form.vehicleType !== '船舶'"
|
||||
v-model="form.driverName"
|
||||
:fetch-suggestions="fetchDriverOptions"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
placeholder="输入驾驶人模糊查询选择"
|
||||
value-key="value"
|
||||
class="violation-record-page__input"
|
||||
/>
|
||||
<el-input v-else v-model="form.driverName" clearable maxlength="20" placeholder="请输入船长" />
|
||||
<el-input
|
||||
v-else
|
||||
v-model="form.driverName"
|
||||
:disabled="boxType === 'view'"
|
||||
clearable
|
||||
maxlength="20"
|
||||
placeholder="请输入船长"
|
||||
/>
|
||||
</template>
|
||||
<template #processStatus="{ row }">
|
||||
<span :class="row.processStatus === '未处理' ? 'violation-record-page__danger' : ''">
|
||||
@@ -89,6 +98,24 @@
|
||||
<template #attachments="{ row }">
|
||||
<span>{{ formatAttachments(row.attachments) }}</span>
|
||||
</template>
|
||||
<template #attachmentsForm>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
<template #attachments-form>
|
||||
<vehicle-attachment-upload
|
||||
v-model="form.attachments"
|
||||
:readonly="boxType === 'view'"
|
||||
button-text="新增"
|
||||
button-icon="el-icon-plus"
|
||||
:show-tip="false"
|
||||
/>
|
||||
</template>
|
||||
</avue-crud>
|
||||
<empty-pagination
|
||||
:page="page"
|
||||
@@ -97,7 +124,7 @@
|
||||
@load="onLoad(page, query)"
|
||||
/>
|
||||
<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>
|
||||
@@ -116,6 +143,7 @@ import { getList as getDriverList } from '@/api/transportCapacity/driver';
|
||||
import { getDeptTree } from '@/api/system/dept';
|
||||
import { exportBlob } from '@/api/common';
|
||||
import { downloadXls } from '@/utils/util';
|
||||
import { openImportDialog } from '@/utils/import-excel';
|
||||
import { getToken } from '@/utils/auth';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { excelOption, option } from '@/option/vehicle/violation-record';
|
||||
@@ -130,6 +158,7 @@ export default {
|
||||
loading: true,
|
||||
excelBox: false,
|
||||
excelForm: {},
|
||||
isDetailLoading: false,
|
||||
option,
|
||||
excelOption,
|
||||
page: {
|
||||
@@ -139,6 +168,7 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
selectionList: [],
|
||||
boxType: '',
|
||||
data: [],
|
||||
};
|
||||
},
|
||||
@@ -159,6 +189,9 @@ export default {
|
||||
editBtn: this.hasPermission('violation_record_edit'),
|
||||
};
|
||||
},
|
||||
vehicleNoPlaceholder() {
|
||||
return this.form.vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
},
|
||||
ids() {
|
||||
const ids = [];
|
||||
this.selectionList.forEach(ele => {
|
||||
@@ -169,8 +202,8 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
'form.vehicleType': {
|
||||
handler(value) {
|
||||
this.updateVehicleTypeDisplays(value || '车辆');
|
||||
handler(value, oldValue) {
|
||||
this.updateVehicleTypeDisplays(value || '车辆', oldValue);
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
@@ -191,15 +224,22 @@ export default {
|
||||
column.dicData = res.data.data;
|
||||
});
|
||||
},
|
||||
updateVehicleTypeDisplays(vehicleType) {
|
||||
updateVehicleTypeDisplays(vehicleType, oldValue) {
|
||||
const vehicleTypeColumn = this.findColumn(this.option.column, 'vehicleType');
|
||||
const vehicleNoColumn = this.findColumn(this.option.column, 'vehicleNo');
|
||||
const driverColumn = this.findColumn(this.option.column, 'driverName');
|
||||
const typeColumn = this.findColumn(this.option.column, 'violationType');
|
||||
const itemColumn = this.findColumn(this.option.column, 'violationItem');
|
||||
vehicleNoColumn.placeholder =
|
||||
vehicleType === '船舶' ? '输入船号模糊查询选择' : '输入车牌号模糊查询选择';
|
||||
driverColumn.label = vehicleType === '船舶' ? '船长' : '驾驶人';
|
||||
typeColumn.display = vehicleType !== '船舶';
|
||||
itemColumn.display = vehicleType === '船舶';
|
||||
vehicleTypeColumn.disabled = Boolean(this.form.id);
|
||||
if (!this.isDetailLoading && oldValue && vehicleType !== oldValue) {
|
||||
this.form.vehicleNo = '';
|
||||
this.form.driverName = '';
|
||||
}
|
||||
if (vehicleType === '船舶') {
|
||||
this.form.violationType = undefined;
|
||||
} else {
|
||||
@@ -217,9 +257,7 @@ export default {
|
||||
const vehicleType = this.form.vehicleType || '车辆';
|
||||
const request = vehicleType === '船舶' ? getShipList : getVehicleList;
|
||||
const params =
|
||||
vehicleType === '船舶'
|
||||
? { shipIdentifierNo: queryString }
|
||||
: { plateNo: queryString };
|
||||
vehicleType === '船舶' ? { shipIdentifierNo: queryString } : { plateNo: queryString };
|
||||
request(1, 20, params)
|
||||
.then(res => {
|
||||
const records = res.data.data.records || [];
|
||||
@@ -277,7 +315,10 @@ export default {
|
||||
values.vehicleType = values.vehicleType || '车辆';
|
||||
values.processStatus = values.processStatus || '未处理';
|
||||
if (values.vehicleNo) {
|
||||
values.vehicleNo = values.vehicleNo.trim().toUpperCase();
|
||||
values.vehicleNo =
|
||||
values.vehicleType === '船舶'
|
||||
? values.vehicleNo.trim()
|
||||
: values.vehicleNo.trim().toUpperCase();
|
||||
}
|
||||
if (values.processStatus === '未处理') {
|
||||
values.processResult = undefined;
|
||||
@@ -291,7 +332,10 @@ export default {
|
||||
return values;
|
||||
},
|
||||
validateRow(row) {
|
||||
if (row.violationTime && new Date(row.violationTime.replace(/-/g, '/')).getTime() > Date.now()) {
|
||||
if (
|
||||
row.violationTime &&
|
||||
new Date(row.violationTime.replace(/-/g, '/')).getTime() > Date.now()
|
||||
) {
|
||||
this.$message.warning('时间不能超过当前时间');
|
||||
return false;
|
||||
}
|
||||
@@ -378,6 +422,7 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeOpen(done, type) {
|
||||
this.boxType = type;
|
||||
if (type === 'add') {
|
||||
this.form = {
|
||||
vehicleType: '车辆',
|
||||
@@ -387,13 +432,20 @@ export default {
|
||||
this.updateProcessResultDisplay('未处理');
|
||||
}
|
||||
if (['edit', 'view'].includes(type)) {
|
||||
getDetail(this.form.id).then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
this.form = detail;
|
||||
this.updateVehicleTypeDisplays(detail.vehicleType);
|
||||
this.updateProcessResultDisplay(detail.processStatus);
|
||||
});
|
||||
this.isDetailLoading = true;
|
||||
getDetail(this.form.id)
|
||||
.then(res => {
|
||||
const detail = res.data.data;
|
||||
detail.attachments = this.parseAttachments(detail.attachments);
|
||||
detail.vehicleType = detail.vehicleType || '车辆';
|
||||
detail.processStatus = detail.processStatus || '未处理';
|
||||
this.form = detail;
|
||||
this.updateVehicleTypeDisplays(detail.vehicleType);
|
||||
this.updateProcessResultDisplay(detail.processStatus);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isDetailLoading = false;
|
||||
});
|
||||
}
|
||||
done();
|
||||
},
|
||||
@@ -437,12 +489,7 @@ export default {
|
||||
});
|
||||
},
|
||||
handleImport() {
|
||||
this.excelBox = true;
|
||||
},
|
||||
uploadAfter(res, done) {
|
||||
this.excelBox = false;
|
||||
this.onLoad(this.page);
|
||||
done();
|
||||
openImportDialog(this, '违章记录');
|
||||
},
|
||||
handleExport() {
|
||||
this.$confirm('是否导出违章记录数据?', '提示', {
|
||||
@@ -451,7 +498,10 @@ export default {
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
NProgress.start();
|
||||
exportBlob('/blade-transport/violation-record/export-violation-record', this.buildExportParams())
|
||||
exportBlob(
|
||||
'/blade-transport/violation-record/export-violation-record',
|
||||
this.buildExportParams()
|
||||
)
|
||||
.then(res => {
|
||||
downloadXls(res.data, `违章记录${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||
})
|
||||
@@ -469,7 +519,9 @@ export default {
|
||||
},
|
||||
handleTemplate() {
|
||||
exportBlob(
|
||||
`/blade-transport/violation-record/export-template?${this.website.tokenHeader}=${getToken()}`
|
||||
`/blade-transport/violation-record/export-template?${
|
||||
this.website.tokenHeader
|
||||
}=${getToken()}`
|
||||
).then(res => {
|
||||
downloadXls(res.data, '违章记录模板.xlsx');
|
||||
});
|
||||
|
||||
@@ -101,7 +101,10 @@ export default {
|
||||
tip: false,
|
||||
simplePage: true,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
selection: true,
|
||||
|
||||
@@ -93,7 +93,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
selection: true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<basic-container>
|
||||
<el-form ref="form" :model="form" label-width="80px">
|
||||
<el-form ref="form" :model="form" label-width="auto">
|
||||
<el-row type="flex" class="row-bg" justify="end">
|
||||
<el-form-item>
|
||||
<el-button @click="handleCancel">关闭</el-button>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<basic-container>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="auto">
|
||||
<el-row type="flex" class="row-bg" justify="end">
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleAgree">同意</el-button>
|
||||
|
||||
@@ -96,7 +96,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
selection: true,
|
||||
|
||||
@@ -109,7 +109,10 @@ export default {
|
||||
calcHeight: 32,
|
||||
tip: false,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
selection: true,
|
||||
|
||||
@@ -101,7 +101,10 @@ export default {
|
||||
tip: false,
|
||||
simplePage: true,
|
||||
searchShow: true,
|
||||
searchMenuSpan: 6,
|
||||
searchMenuSpan: 24,
|
||||
searchIcon: true,
|
||||
searchIndex: 8,
|
||||
searchMenuPosition: 'right',
|
||||
border: true,
|
||||
index: true,
|
||||
selection: true,
|
||||
|
||||
Reference in New Issue
Block a user