fix bug
This commit is contained in:
@@ -0,0 +1,252 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="visible"
|
||||||
|
title="地图选择地址"
|
||||||
|
width="920px"
|
||||||
|
append-to-body
|
||||||
|
@opened="initMap"
|
||||||
|
>
|
||||||
|
<div class="address-map-picker__toolbar">
|
||||||
|
<el-input
|
||||||
|
v-model="keyword"
|
||||||
|
clearable
|
||||||
|
placeholder="输入地址关键词"
|
||||||
|
@keyup.enter="searchKeyword"
|
||||||
|
/>
|
||||||
|
<el-button type="primary" :loading="searching" @click="searchKeyword">搜索</el-button>
|
||||||
|
</div>
|
||||||
|
<div ref="map" class="address-map-picker__map"></div>
|
||||||
|
<div class="address-map-picker__info">{{ status }}</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="visible = false">取消</el-button>
|
||||||
|
<el-button type="primary" :disabled="!selected.longitude || resolving" @click="confirm">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const AMAP_KEY = '653b7cf105ad7fb8ec9b2f5198ade315';
|
||||||
|
const AMAP_SECURITY_CODE = '5aab65c632e48ebae0d0e28f5b28e21a';
|
||||||
|
let amapLoader;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['update:modelValue', 'confirm'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
keyword: '',
|
||||||
|
status: '可搜索地址或点击地图选点',
|
||||||
|
searching: false,
|
||||||
|
resolving: false,
|
||||||
|
selected: {},
|
||||||
|
amap: null,
|
||||||
|
marker: null,
|
||||||
|
geocoder: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
modelValue: {
|
||||||
|
immediate: true,
|
||||||
|
handler(value) {
|
||||||
|
this.visible = value;
|
||||||
|
if (value) {
|
||||||
|
this.keyword = this.address || '';
|
||||||
|
this.selected = {};
|
||||||
|
this.status = '可搜索地址或点击地图选点';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
visible(value) {
|
||||||
|
this.$emit('update:modelValue', value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
if (this.amap) {
|
||||||
|
this.amap.destroy();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
loadAmap() {
|
||||||
|
if (window.AMap && window.AMap.Map) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
if (!amapLoader) {
|
||||||
|
amapLoader = new Promise((resolve, reject) => {
|
||||||
|
window._AMapSecurityConfig = { securityJsCode: AMAP_SECURITY_CODE };
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = `https://webapi.amap.com/maps?v=2.0&key=${AMAP_KEY}`;
|
||||||
|
script.async = true;
|
||||||
|
script.onload = resolve;
|
||||||
|
script.onerror = () => reject(new Error('高德地图组件加载失败'));
|
||||||
|
document.body.appendChild(script);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return amapLoader;
|
||||||
|
},
|
||||||
|
initMap() {
|
||||||
|
this.loadAmap()
|
||||||
|
.then(() => {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (!this.amap) {
|
||||||
|
this.amap = new window.AMap.Map(this.$refs.map, {
|
||||||
|
center: [116.40769, 39.89945],
|
||||||
|
zoom: 11,
|
||||||
|
});
|
||||||
|
this.amap.on('click', event => this.pickPoint(event.lnglat));
|
||||||
|
} else {
|
||||||
|
this.amap.resize();
|
||||||
|
this.clearMarker();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.$message.error('高德地图组件加载失败,请稍后重试');
|
||||||
|
this.visible = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
ensureGeocoder() {
|
||||||
|
if (this.geocoder) return Promise.resolve(this.geocoder);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
window.AMap.plugin(['AMap.Geocoder'], () => {
|
||||||
|
try {
|
||||||
|
this.geocoder = new window.AMap.Geocoder();
|
||||||
|
resolve(this.geocoder);
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
runGeocode(action, input) {
|
||||||
|
return this.ensureGeocoder().then(
|
||||||
|
geocoder =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const done = (status, result) => {
|
||||||
|
if (status === 'complete' && result) {
|
||||||
|
resolve(result);
|
||||||
|
} else {
|
||||||
|
reject(new Error('高德地图请求失败'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (action === 'location') {
|
||||||
|
geocoder.getLocation(input, done);
|
||||||
|
} else {
|
||||||
|
geocoder.getAddress(input, done);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
searchKeyword() {
|
||||||
|
const keyword = String(this.keyword || '').trim();
|
||||||
|
if (!keyword) {
|
||||||
|
this.$message.warning('请输入地址关键词');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.searching = true;
|
||||||
|
this.loadAmap()
|
||||||
|
.then(() => this.runGeocode('location', keyword))
|
||||||
|
.then(result => {
|
||||||
|
const point = result.geocodes?.[0]?.location || result.location;
|
||||||
|
if (!point) {
|
||||||
|
throw new Error('未找到匹配地址');
|
||||||
|
}
|
||||||
|
this.pickPoint(point, keyword);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.status = '未找到匹配地址';
|
||||||
|
this.$message.warning('地图搜索无匹配地址');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.searching = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
pickPoint(point, fallbackAddress = '') {
|
||||||
|
const longitude = typeof point.getLng === 'function' ? point.getLng() : point.lng;
|
||||||
|
const latitude = typeof point.getLat === 'function' ? point.getLat() : point.lat;
|
||||||
|
if (!Number.isFinite(Number(longitude)) || !Number.isFinite(Number(latitude))) {
|
||||||
|
this.$message.warning('选点坐标无效');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const lnglat = new window.AMap.LngLat(Number(longitude), Number(latitude));
|
||||||
|
this.renderMarker(lnglat);
|
||||||
|
this.selected = { longitude: Number(longitude), latitude: Number(latitude), address: fallbackAddress };
|
||||||
|
this.status = '正在解析地址...';
|
||||||
|
this.resolving = true;
|
||||||
|
this.runGeocode('address', lnglat)
|
||||||
|
.then(result => {
|
||||||
|
const detailAddress = result.regeocode?.formattedAddress || fallbackAddress;
|
||||||
|
this.selected = { ...this.selected, address: detailAddress };
|
||||||
|
this.keyword = detailAddress || this.keyword;
|
||||||
|
this.status = detailAddress || '已选点,可确认回填';
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.status = '地址解析失败,请重新选点';
|
||||||
|
this.$message.error('地址解析失败,请重新选点');
|
||||||
|
this.selected = {};
|
||||||
|
this.clearMarker();
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.resolving = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
renderMarker(point) {
|
||||||
|
this.clearMarker();
|
||||||
|
this.marker = new window.AMap.Marker({ position: point });
|
||||||
|
this.marker.setMap(this.amap);
|
||||||
|
this.amap.setCenter(point);
|
||||||
|
},
|
||||||
|
clearMarker() {
|
||||||
|
if (this.marker) {
|
||||||
|
this.marker.setMap(null);
|
||||||
|
this.marker = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirm() {
|
||||||
|
if (!this.selected.address) {
|
||||||
|
this.$message.warning('请等待地址解析完成后再确认');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$emit('confirm', this.selected.address);
|
||||||
|
this.visible = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.address-map-picker {
|
||||||
|
&__toolbar {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
.el-input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__map {
|
||||||
|
width: 100%;
|
||||||
|
height: 420px;
|
||||||
|
border: 1px solid #eff1f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__info {
|
||||||
|
margin-top: 10px;
|
||||||
|
color: #606266;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -202,6 +202,7 @@ export const option = createCrudOption([
|
|||||||
label: '单价',
|
label: '单价',
|
||||||
prop: 'cargoValue',
|
prop: 'cargoValue',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
|
formatter: row => (String(row.cargoValue) === '-1' ? '' : row.cargoValue),
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
@@ -277,6 +278,9 @@ export const option = createCrudOption([
|
|||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 搜索栏标签统一加宽,给较长的货物类型字段预留足够展示空间。
|
||||||
|
option.searchLabelWidth = 160;
|
||||||
|
|
||||||
export const excelOption = {
|
export const excelOption = {
|
||||||
submitBtn: false,
|
submitBtn: false,
|
||||||
emptyBtn: false,
|
emptyBtn: false,
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export const option = {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
@@ -128,6 +129,7 @@ export const option = {
|
|||||||
prop: 'directEconomicLoss',
|
prop: 'directEconomicLoss',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
|
append: '元',
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
span: 12,
|
span: 12,
|
||||||
placeholder: '请输入',
|
placeholder: '请输入',
|
||||||
@@ -138,6 +140,7 @@ export const option = {
|
|||||||
prop: 'insuranceClaimAmount',
|
prop: 'insuranceClaimAmount',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
|
append: '元',
|
||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
span: 12,
|
span: 12,
|
||||||
placeholder: '请输入',
|
placeholder: '请输入',
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ export const option = {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
@@ -145,6 +146,7 @@ export const option = {
|
|||||||
prop: 'fee',
|
prop: 'fee',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
|
append: '元',
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
span: 12,
|
span: 12,
|
||||||
placeholder: '请输入',
|
placeholder: '请输入',
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export const option = {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export const option = {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export const option = {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export const option = {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
@@ -70,6 +71,7 @@ export const option = {
|
|||||||
prop: 'previousMonthMileage',
|
prop: 'previousMonthMileage',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
|
append: 'km',
|
||||||
minWidth: 210,
|
minWidth: 210,
|
||||||
slot: true,
|
slot: true,
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
@@ -79,6 +81,7 @@ export const option = {
|
|||||||
prop: 'currentMonthMileage',
|
prop: 'currentMonthMileage',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
|
append: 'km',
|
||||||
minWidth: 210,
|
minWidth: 210,
|
||||||
slot: true,
|
slot: true,
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
@@ -88,6 +91,7 @@ export const option = {
|
|||||||
prop: 'monthlyMileage',
|
prop: 'monthlyMileage',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
|
append: 'km',
|
||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
slot: true,
|
slot: true,
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
@@ -97,6 +101,7 @@ export const option = {
|
|||||||
prop: 'totalMileage',
|
prop: 'totalMileage',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
|
append: 'km',
|
||||||
minWidth: 170,
|
minWidth: 170,
|
||||||
slot: true,
|
slot: true,
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export const option = {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
@@ -123,6 +124,7 @@ export const option = {
|
|||||||
prop: 'unitPrice',
|
prop: 'unitPrice',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
|
append: '元/升',
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
rules: [{ validator: validateNonNegative, trigger: 'blur' }],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export const option = {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export const option = {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export const option = {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ export const option = {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
@@ -127,6 +128,8 @@ export const option = {
|
|||||||
{
|
{
|
||||||
label: '地点',
|
label: '地点',
|
||||||
prop: 'location',
|
prop: 'location',
|
||||||
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
overHidden: true,
|
overHidden: true,
|
||||||
span: 12,
|
span: 12,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
@row-del="rowDel"
|
@row-del="rowDel"
|
||||||
@search-change="searchChange"
|
@search-change="searchChange"
|
||||||
@search-reset="searchReset"
|
@search-reset="searchReset"
|
||||||
|
@selection-change="selectionChange"
|
||||||
@current-change="currentChange"
|
@current-change="currentChange"
|
||||||
@size-change="sizeChange"
|
@size-change="sizeChange"
|
||||||
@refresh-change="refreshChange"
|
@refresh-change="refreshChange"
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
v-model="form.feeCategory"
|
v-model="form.feeCategory"
|
||||||
class="fee-item-form-control"
|
class="fee-item-form-control"
|
||||||
clearable
|
clearable
|
||||||
|
:disabled="dialogType !== 'add'"
|
||||||
filterable
|
filterable
|
||||||
placeholder="请选择费用类型"
|
placeholder="请选择费用类型"
|
||||||
@change="handleFeeCategoryChange"
|
@change="handleFeeCategoryChange"
|
||||||
@@ -58,6 +60,7 @@
|
|||||||
:maxlength="feeItemCodeMaxlength"
|
:maxlength="feeItemCodeMaxlength"
|
||||||
class="fee-item-form-control"
|
class="fee-item-form-control"
|
||||||
clearable
|
clearable
|
||||||
|
:disabled="dialogType !== 'add'"
|
||||||
placeholder="请输入费用项代码"
|
placeholder="请输入费用项代码"
|
||||||
@change="handleFeeItemCodeChange"
|
@change="handleFeeItemCodeChange"
|
||||||
>
|
>
|
||||||
@@ -114,12 +117,14 @@ export default {
|
|||||||
data: [],
|
data: [],
|
||||||
excelBox: false,
|
excelBox: false,
|
||||||
excelForm: {},
|
excelForm: {},
|
||||||
|
dialogType: 'add',
|
||||||
feeCategoryOptions: [],
|
feeCategoryOptions: [],
|
||||||
page: {
|
page: {
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
total: 0,
|
total: 0,
|
||||||
},
|
},
|
||||||
|
selectionList: [],
|
||||||
option: {
|
option: {
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
calcHeight: 32,
|
calcHeight: 32,
|
||||||
@@ -139,7 +144,7 @@ export default {
|
|||||||
viewBtn: false,
|
viewBtn: false,
|
||||||
delBtn: false,
|
delBtn: false,
|
||||||
editBtn: false,
|
editBtn: false,
|
||||||
selection: false,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
menuWidth: 180,
|
menuWidth: 180,
|
||||||
column: [
|
column: [
|
||||||
@@ -294,6 +299,9 @@ export default {
|
|||||||
feeItemCodeMaxlength() {
|
feeItemCodeMaxlength() {
|
||||||
return Math.max(1, 100 - this.feeCategoryPrefix.length);
|
return Math.max(1, 100 - this.feeCategoryPrefix.length);
|
||||||
},
|
},
|
||||||
|
ids() {
|
||||||
|
return this.selectionList.map(item => item.id).join(',');
|
||||||
|
},
|
||||||
permissionList() {
|
permissionList() {
|
||||||
return {
|
return {
|
||||||
addBtn: this.validData(this.permission.fee_item_add, false),
|
addBtn: this.validData(this.permission.fee_item_add, false),
|
||||||
@@ -418,6 +426,7 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
beforeOpen(done, type) {
|
beforeOpen(done, type) {
|
||||||
|
this.dialogType = type || 'add';
|
||||||
if (['edit', 'view'].includes(type)) {
|
if (['edit', 'view'].includes(type)) {
|
||||||
getDetail(this.form.id).then(res => {
|
getDetail(this.form.id).then(res => {
|
||||||
this.form = this.normalizeFormForEdit(res.data.data || {});
|
this.form = this.normalizeFormForEdit(res.data.data || {});
|
||||||
@@ -439,6 +448,13 @@ export default {
|
|||||||
this.onLoad(this.page, params);
|
this.onLoad(this.page, params);
|
||||||
done();
|
done();
|
||||||
},
|
},
|
||||||
|
selectionChange(list) {
|
||||||
|
this.selectionList = list;
|
||||||
|
},
|
||||||
|
selectionClear() {
|
||||||
|
this.selectionList = [];
|
||||||
|
this.$refs.crud.toggleSelection();
|
||||||
|
},
|
||||||
currentChange(currentPage) {
|
currentChange(currentPage) {
|
||||||
this.page.currentPage = currentPage;
|
this.page.currentPage = currentPage;
|
||||||
},
|
},
|
||||||
@@ -454,6 +470,7 @@ export default {
|
|||||||
buildExportParams() {
|
buildExportParams() {
|
||||||
return {
|
return {
|
||||||
...this.query,
|
...this.query,
|
||||||
|
ids: this.ids,
|
||||||
[this.website.tokenHeader]: getToken(),
|
[this.website.tokenHeader]: getToken(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -490,6 +507,7 @@ export default {
|
|||||||
const data = res.data.data;
|
const data = res.data.data;
|
||||||
this.page.total = data.total;
|
this.page.total = data.total;
|
||||||
this.data = data.records;
|
this.data = data.records;
|
||||||
|
this.selectionClear();
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -250,81 +250,6 @@ import NProgress from 'nprogress';
|
|||||||
import 'nprogress/nprogress.css';
|
import 'nprogress/nprogress.css';
|
||||||
|
|
||||||
const DEFAULT_COUNTRY_CODE = '+86';
|
const DEFAULT_COUNTRY_CODE = '+86';
|
||||||
const EXCLUDED_EXCEL_HEADERS = ['数据来源', '启停状态'];
|
|
||||||
const REQUIRED_EXPORT_HEADERS = [
|
|
||||||
'港口码头名称',
|
|
||||||
'港口/码头名称',
|
|
||||||
'类型',
|
|
||||||
'国家',
|
|
||||||
'城市',
|
|
||||||
'经度',
|
|
||||||
'纬度',
|
|
||||||
];
|
|
||||||
|
|
||||||
const getExcelCellText = value => {
|
|
||||||
if (value === undefined || value === null) return '';
|
|
||||||
if (typeof value === 'object') {
|
|
||||||
if (Array.isArray(value.richText)) {
|
|
||||||
return value.richText.map(item => item.text || '').join('');
|
|
||||||
}
|
|
||||||
if (value.text) return value.text;
|
|
||||||
if (value.result) return value.result;
|
|
||||||
}
|
|
||||||
return String(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeWorkbookColumnsByHeaders = workbook => {
|
|
||||||
workbook.eachSheet(worksheet => {
|
|
||||||
const maxHeaderRow = Math.min(worksheet.rowCount || 0, 10);
|
|
||||||
for (let rowIndex = 1; rowIndex <= maxHeaderRow; rowIndex += 1) {
|
|
||||||
const row = worksheet.getRow(rowIndex);
|
|
||||||
const indexes = [];
|
|
||||||
row.eachCell((cell, colNumber) => {
|
|
||||||
const text = getExcelCellText(cell.value).trim();
|
|
||||||
if (EXCLUDED_EXCEL_HEADERS.includes(text)) {
|
|
||||||
indexes.push(colNumber);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (indexes.length) {
|
|
||||||
indexes.sort((a, b) => b - a).forEach(colNumber => worksheet.spliceColumns(colNumber, 1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const addWorkbookRequiredHeaderMarks = workbook => {
|
|
||||||
workbook.eachSheet(worksheet => {
|
|
||||||
const maxHeaderRow = Math.min(worksheet.rowCount || 0, 10);
|
|
||||||
for (let rowIndex = 1; rowIndex <= maxHeaderRow; rowIndex += 1) {
|
|
||||||
const row = worksheet.getRow(rowIndex);
|
|
||||||
let hasRequiredHeader = false;
|
|
||||||
row.eachCell(cell => {
|
|
||||||
const text = getExcelCellText(cell.value).trim();
|
|
||||||
const header = text.replace(/\*+$/g, '').trim();
|
|
||||||
if (REQUIRED_EXPORT_HEADERS.includes(header)) {
|
|
||||||
cell.value = `${header}*`;
|
|
||||||
hasRequiredHeader = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (hasRequiredHeader) break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeExcelColumnsByHeaders = async (blob, options = {}) => {
|
|
||||||
const { markRequiredHeaders = false } = options;
|
|
||||||
const ExcelJS = await import('exceljs');
|
|
||||||
const workbook = new ExcelJS.Workbook();
|
|
||||||
await workbook.xlsx.load(await blob.arrayBuffer());
|
|
||||||
removeWorkbookColumnsByHeaders(workbook);
|
|
||||||
if (markRequiredHeaders) {
|
|
||||||
addWorkbookRequiredHeaderMarks(workbook);
|
|
||||||
}
|
|
||||||
const buffer = await workbook.xlsx.writeBuffer();
|
|
||||||
return new Blob([buffer], { type: 'application/vnd.ms-excel' });
|
|
||||||
};
|
|
||||||
|
|
||||||
const newLocal = '请选择类型';
|
const newLocal = '请选择类型';
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -1323,9 +1248,6 @@ export default {
|
|||||||
'港口码头主数据',
|
'港口码头主数据',
|
||||||
() => {
|
() => {
|
||||||
this.loadPortOptions();
|
this.loadPortOptions();
|
||||||
},
|
|
||||||
{
|
|
||||||
failDetailDecorator: removeWorkbookColumnsByHeaders,
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -1339,11 +1261,8 @@ export default {
|
|||||||
exportBlob('/blade-system/port-terminal/export-port-terminal', this.buildExportParams(), {
|
exportBlob('/blade-system/port-terminal/export-port-terminal', this.buildExportParams(), {
|
||||||
feedback: true,
|
feedback: true,
|
||||||
})
|
})
|
||||||
.then(async res => {
|
.then(res => {
|
||||||
const blob = await removeExcelColumnsByHeaders(res.data, {
|
downloadXls(res.data, `港口码头主数据${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
||||||
markRequiredHeaders: true,
|
|
||||||
});
|
|
||||||
downloadXls(blob, `港口码头主数据${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
@@ -1362,9 +1281,8 @@ export default {
|
|||||||
`/blade-system/port-terminal/export-template?${this.website.tokenHeader}=${getToken()}`,
|
`/blade-system/port-terminal/export-template?${this.website.tokenHeader}=${getToken()}`,
|
||||||
undefined,
|
undefined,
|
||||||
{ feedback: true }
|
{ feedback: true }
|
||||||
).then(async res => {
|
).then(res => {
|
||||||
const blob = await removeExcelColumnsByHeaders(res.data);
|
downloadXls(res.data, '港口码头主数据模板.xlsx');
|
||||||
downloadXls(blob, '港口码头主数据模板.xlsx');
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -689,6 +689,7 @@ export default {
|
|||||||
feedback: true,
|
feedback: true,
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
downloadXls(res.data, '行政区划模板.xlsx');
|
downloadXls(res.data, '行政区划模板.xlsx');
|
||||||
|
this.$message.success('模板下载成功');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -399,8 +399,17 @@ export default {
|
|||||||
if (submitRow.cargoValue !== undefined && submitRow.cargoValue !== null) {
|
if (submitRow.cargoValue !== undefined && submitRow.cargoValue !== null) {
|
||||||
submitRow.cargoValue = String(submitRow.cargoValue).trim();
|
submitRow.cargoValue = String(submitRow.cargoValue).trim();
|
||||||
}
|
}
|
||||||
|
if (!submitRow.cargoValue || String(submitRow.cargoValue) === '-1') {
|
||||||
|
submitRow.cargoValue = null;
|
||||||
|
}
|
||||||
return submitRow;
|
return submitRow;
|
||||||
},
|
},
|
||||||
|
normalizeCargoValue(row) {
|
||||||
|
if (row && String(row.cargoValue) === '-1') {
|
||||||
|
row.cargoValue = null;
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
},
|
||||||
validateRow(row) {
|
validateRow(row) {
|
||||||
if (!row.firstCargoTypeName || !row.firstCargoTypeCode) {
|
if (!row.firstCargoTypeName || !row.firstCargoTypeCode) {
|
||||||
this.$message.warning('请选择一级货物类型');
|
this.$message.warning('请选择一级货物类型');
|
||||||
@@ -539,7 +548,7 @@ export default {
|
|||||||
}
|
}
|
||||||
if (['edit', 'view'].includes(type)) {
|
if (['edit', 'view'].includes(type)) {
|
||||||
api.getDetail(this.form.id).then(res => {
|
api.getDetail(this.form.id).then(res => {
|
||||||
this.form = res.data.data || {};
|
this.form = this.normalizeCargoValue(res.data.data || {});
|
||||||
this.ensureCargoTypeOption('firstCargoTypeOptions', {
|
this.ensureCargoTypeOption('firstCargoTypeOptions', {
|
||||||
cargoName: this.form.firstCargoTypeName,
|
cargoName: this.form.firstCargoTypeName,
|
||||||
cargoCode: this.form.firstCargoTypeCode,
|
cargoCode: this.form.firstCargoTypeCode,
|
||||||
@@ -593,7 +602,7 @@ export default {
|
|||||||
.then(res => {
|
.then(res => {
|
||||||
const result = res.data.data;
|
const result = res.data.data;
|
||||||
this.page.total = result.total;
|
this.page.total = result.total;
|
||||||
this.data = result.records;
|
this.data = (result.records || []).map(row => this.normalizeCargoValue(row));
|
||||||
this.selectionClear();
|
this.selectionClear();
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -654,6 +663,12 @@ export default {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.common-cargo-page {
|
.common-cargo-page {
|
||||||
|
// 仅缩短本页面筛选栏中的输入框和下拉框,避免影响表单及其他页面。
|
||||||
|
:deep(.avue-crud__search .el-form-item__content > .el-input),
|
||||||
|
:deep(.avue-crud__search .el-form-item__content > .el-select) {
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
&__value-unit {
|
&__value-unit {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2105,7 +2105,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #menu="{ row, index }">
|
<template #menu="{ row, index }">
|
||||||
<template>
|
<div class="business-crud-page__row-actions">
|
||||||
<el-link type="primary" v-if="showDetailButton(row)" @click="openDetail(row)"
|
<el-link type="primary" v-if="showDetailButton(row)" @click="openDetail(row)"
|
||||||
>详情</el-link
|
>详情</el-link
|
||||||
>
|
>
|
||||||
@@ -2144,7 +2144,7 @@
|
|||||||
{{ operation.label }}
|
{{ operation.label }}
|
||||||
</el-link>
|
</el-link>
|
||||||
<el-link type="danger" v-if="canDelete(row)" @click="rowDel(row)"> 删除 </el-link>
|
<el-link type="danger" v-if="canDelete(row)" @click="rowDel(row)"> 删除 </el-link>
|
||||||
</template>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</component>
|
</component>
|
||||||
|
|
||||||
@@ -13281,6 +13281,13 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__row-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.business-crud-page__full-form-item) {
|
:deep(.business-crud-page__full-form-item) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|||||||
@@ -1705,6 +1705,10 @@ export default {
|
|||||||
departureAddress: this.form.arrivalAddress,
|
departureAddress: this.form.arrivalAddress,
|
||||||
departureContact: this.form.arrivalContact,
|
departureContact: this.form.arrivalContact,
|
||||||
departurePhone: this.form.arrivalPhone,
|
departurePhone: this.form.arrivalPhone,
|
||||||
|
departureLongitude: this.form.arrivalLongitude,
|
||||||
|
departureLatitude: this.form.arrivalLatitude,
|
||||||
|
departureRegionCode: this.form.arrivalRegionCode,
|
||||||
|
departureSiteCode: this.form.arrivalSiteCode,
|
||||||
transportType: this.form.finalTransportType,
|
transportType: this.form.finalTransportType,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -580,29 +580,205 @@
|
|||||||
title="合同详情"
|
title="合同详情"
|
||||||
append-to-body
|
append-to-body
|
||||||
destroy-on-close
|
destroy-on-close
|
||||||
width="1200px"
|
class="contract-manage-detail-dialog"
|
||||||
|
width="92%"
|
||||||
top="4vh"
|
top="4vh"
|
||||||
>
|
>
|
||||||
<div v-loading="detailLoading" class="contract-manage-detail">
|
<div v-loading="detailLoading" class="contract-manage-form contract-manage-detail">
|
||||||
<section v-for="section in config.detailSections" :key="section.title">
|
<section class="contract-manage-form__section contract-manage-form__section--panel">
|
||||||
<div class="dialog-section-title">{{ section.title }}</div>
|
<div class="dialog-section-title">基本信息</div>
|
||||||
<el-descriptions :column="3" border>
|
<el-descriptions :column="3" class="contract-manage-detail__descriptions">
|
||||||
<el-descriptions-item
|
<el-descriptions-item label="签约类型">{{
|
||||||
v-for="field in section.fields"
|
detailValue('signType')
|
||||||
:key="field[0]"
|
}}</el-descriptions-item>
|
||||||
:label="field[1]"
|
<el-descriptions-item label="合同编号">{{
|
||||||
:span="field[2] || 1"
|
detailValue('contractNo')
|
||||||
>
|
}}</el-descriptions-item>
|
||||||
{{ detailValue(field[0]) }}
|
<el-descriptions-item label="合同名称">{{
|
||||||
</el-descriptions-item>
|
detailValue('contractName')
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="合同类型">{{
|
||||||
|
detailValue('contractCategory')
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="项目">{{
|
||||||
|
detailValue('projectName')
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="甲方">{{ detailValue('partyA') }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="乙方">{{ detailValue('partyB') }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="合同期限">{{ detailContractPeriod }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="所属组织">{{
|
||||||
|
detailValue('organizationName')
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="经办人">{{
|
||||||
|
detailValue('handlerUserName')
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="签订日期">{{
|
||||||
|
detailValue('signDate')
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="结算类型">{{
|
||||||
|
detailValue('settlementMode')
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="合同格式">{{
|
||||||
|
detailValue('contractFormat')
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="是否需要加盖法人章">{{
|
||||||
|
detailLegalSealText
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="一式">{{
|
||||||
|
detailUnitValue('copyCount', '份')
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="回款账期">{{
|
||||||
|
detailUnitValue('paymentDays', '天')
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="备注" :span="3">{{
|
||||||
|
detailValue('remark')
|
||||||
|
}}</el-descriptions-item>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<attachment-section
|
||||||
|
title="合同文件"
|
||||||
|
readonly
|
||||||
|
:rows="detailContractFileRows"
|
||||||
|
:preview="previewAttachment"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<section class="contract-manage-form__section contract-manage-form__section--panel">
|
||||||
|
<div class="dialog-section-title">计费信息</div>
|
||||||
|
<el-descriptions :column="3" class="contract-manage-detail__descriptions">
|
||||||
|
<el-descriptions-item label="费用生成模式">{{
|
||||||
|
detailFeeGenerationMode
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
<el-table :data="detailBillingPlanRows" border>
|
||||||
|
<el-table-column type="index" label="序号" width="80" align="center" />
|
||||||
|
<el-table-column prop="planName" label="方案名称" min-width="220" align="center" />
|
||||||
|
<el-table-column label="默认方案" width="140" align="center">
|
||||||
|
<template #default="{ row }">{{ isDefaultBillingPlan(row) ? '是' : '' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="remark"
|
||||||
|
label="备注"
|
||||||
|
min-width="260"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
/>
|
||||||
|
<el-table-column label="操作" width="120" align="center" fixed="right">
|
||||||
|
<template #default="{ row, $index }">
|
||||||
|
<el-link type="primary" @click="openDetailBillingPlan(row, $index)"
|
||||||
|
>查看详情</el-link
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="contract-manage-form__section contract-manage-form__section--panel">
|
||||||
|
<div class="dialog-section-title">结算单规则</div>
|
||||||
|
<el-tabs v-model="detailSettlementConfigTab">
|
||||||
|
<el-tab-pane label="预结算配置" name="pre" />
|
||||||
|
<el-tab-pane label="正式结算配置" name="formal" />
|
||||||
|
</el-tabs>
|
||||||
|
<el-descriptions :column="3" class="contract-manage-detail__descriptions">
|
||||||
|
<el-descriptions-item label="自动生成结算单">{{
|
||||||
|
Number(detailSettlementRule.autoGenerate) === 1 ? '开启' : '关闭'
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<template v-if="Number(detailSettlementRule.autoGenerate) === 1">
|
||||||
|
<el-descriptions-item label="账单起始日期">{{
|
||||||
|
displayValue(detailSettlementRule.billStartDate)
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="结算类型">{{
|
||||||
|
displayValue(detailSettlementRule.settlementType)
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item
|
||||||
|
v-if="detailSettlementRule.settlementType === '月结'"
|
||||||
|
label="账单周期类型"
|
||||||
|
>{{ displayValue(detailSettlementRule.billCycleType) }}</el-descriptions-item
|
||||||
|
>
|
||||||
|
<el-descriptions-item
|
||||||
|
v-if="
|
||||||
|
detailSettlementRule.settlementType === '月结' &&
|
||||||
|
detailSettlementRule.billCycleType === '固定截单日'
|
||||||
|
"
|
||||||
|
label="账单截单日"
|
||||||
|
>{{
|
||||||
|
detailObjectUnitValue(detailSettlementRule, 'billCutoffDay', '日')
|
||||||
|
}}</el-descriptions-item
|
||||||
|
>
|
||||||
|
<el-descriptions-item
|
||||||
|
v-if="detailSettlementRule.settlementType === '固定天数周期结算'"
|
||||||
|
label="周期天数"
|
||||||
|
>{{
|
||||||
|
detailObjectUnitValue(detailSettlementRule, 'cycleDays', '天')
|
||||||
|
}}</el-descriptions-item
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</el-descriptions>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="contract-manage-form__section contract-manage-form__section--panel">
|
||||||
|
<div class="dialog-section-title">付款比例设置</div>
|
||||||
|
<el-table :data="detailPaymentRatioRows" border>
|
||||||
|
<el-table-column type="index" label="序号" width="80" align="center" />
|
||||||
|
<el-table-column prop="paymentTerm" label="付款笔数" min-width="180" align="center" />
|
||||||
|
<el-table-column label="付款比例上限" min-width="220" align="center">
|
||||||
|
<template #default="{ row }">{{
|
||||||
|
detailObjectUnitValue(row, 'ratioLimit', '%')
|
||||||
|
}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="remark" label="备注" min-width="220" />
|
||||||
|
</el-table>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<attachment-section
|
||||||
|
title="其它附件"
|
||||||
|
description
|
||||||
|
readonly
|
||||||
|
:rows="detailAttachmentRows"
|
||||||
|
:preview="previewAttachment"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<section class="contract-manage-form__section contract-manage-form__section--panel">
|
||||||
|
<div class="dialog-section-title">变更记录</div>
|
||||||
|
<el-table :data="detailChangeRecordRows" border>
|
||||||
|
<el-table-column type="index" label="序号" width="70" align="center" />
|
||||||
|
<el-table-column
|
||||||
|
prop="changeDate"
|
||||||
|
label="变更日期"
|
||||||
|
min-width="150"
|
||||||
|
align="center"
|
||||||
|
sortable
|
||||||
|
/>
|
||||||
|
<el-table-column prop="handlerUserName" label="经办人" min-width="140" align="center" />
|
||||||
|
<el-table-column prop="changeType" label="变更类型" min-width="160" align="center" />
|
||||||
|
<el-table-column
|
||||||
|
prop="changeReason"
|
||||||
|
label="变更原因"
|
||||||
|
min-width="240"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
/>
|
||||||
|
<el-table-column prop="statusName" label="状态" min-width="140" align="center" />
|
||||||
|
<el-table-column label="操作" width="120" align="center" fixed="right">
|
||||||
|
<template #default="{ row }"
|
||||||
|
><el-link type="primary" @click="openFlow(row)">流程</el-link></template
|
||||||
|
>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<template #footer
|
<template #footer
|
||||||
><el-button type="primary" @click="detailBox = false">关闭</el-button></template
|
><el-button type="primary" @click="detailBox = false">关闭</el-button></template
|
||||||
>
|
>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<billing-plan-editor
|
||||||
|
v-model="detailBillingPlanBox"
|
||||||
|
:value="detailBillingPlanForm"
|
||||||
|
:index="detailBillingPlanIndex"
|
||||||
|
readonly
|
||||||
|
/>
|
||||||
|
|
||||||
<flow-design
|
<flow-design
|
||||||
v-if="website.design.designMode"
|
v-if="website.design.designMode"
|
||||||
is-dialog
|
is-dialog
|
||||||
@@ -743,6 +919,7 @@ const AttachmentSection = defineComponent({
|
|||||||
title: { type: String, required: true },
|
title: { type: String, required: true },
|
||||||
rows: { type: Array, default: () => [] },
|
rows: { type: Array, default: () => [] },
|
||||||
description: Boolean,
|
description: Boolean,
|
||||||
|
readonly: Boolean,
|
||||||
preview: { type: Function, default: null },
|
preview: { type: Function, default: null },
|
||||||
},
|
},
|
||||||
emits: ['update:rows'],
|
emits: ['update:rows'],
|
||||||
@@ -797,7 +974,9 @@ const AttachmentSection = defineComponent({
|
|||||||
const ElTableColumn = resolveComponent('el-table-column');
|
const ElTableColumn = resolveComponent('el-table-column');
|
||||||
const VehicleAttachmentUpload = resolveComponent('vehicle-attachment-upload');
|
const VehicleAttachmentUpload = resolveComponent('vehicle-attachment-upload');
|
||||||
const columns = [
|
const columns = [
|
||||||
h(ElTableColumn, { type: 'selection', width: 55, align: 'center' }),
|
...(!this.readonly
|
||||||
|
? [h(ElTableColumn, { type: 'selection', width: 55, align: 'center' })]
|
||||||
|
: []),
|
||||||
h(ElTableColumn, { type: 'index', label: '序号', width: 70, align: 'center' }),
|
h(ElTableColumn, { type: 'index', label: '序号', width: 70, align: 'center' }),
|
||||||
h(
|
h(
|
||||||
ElTableColumn,
|
ElTableColumn,
|
||||||
@@ -828,7 +1007,9 @@ const AttachmentSection = defineComponent({
|
|||||||
{ label: '附件描述', minWidth: 220 },
|
{ label: '附件描述', minWidth: 220 },
|
||||||
{
|
{
|
||||||
default: ({ row }) =>
|
default: ({ row }) =>
|
||||||
h(ElInput, {
|
this.readonly
|
||||||
|
? row.description || '-'
|
||||||
|
: h(ElInput, {
|
||||||
modelValue: row.description,
|
modelValue: row.description,
|
||||||
maxlength: 200,
|
maxlength: 200,
|
||||||
'onUpdate:modelValue': value => {
|
'onUpdate:modelValue': value => {
|
||||||
@@ -855,7 +1036,10 @@ const AttachmentSection = defineComponent({
|
|||||||
width: 180,
|
width: 180,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
}),
|
})
|
||||||
|
);
|
||||||
|
if (!this.readonly) {
|
||||||
|
columns.push(
|
||||||
h(
|
h(
|
||||||
ElTableColumn,
|
ElTableColumn,
|
||||||
{ label: '操作', width: 100, align: 'center', fixed: 'right' },
|
{ label: '操作', width: 100, align: 'center', fixed: 'right' },
|
||||||
@@ -865,6 +1049,7 @@ const AttachmentSection = defineComponent({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
return h(
|
return h(
|
||||||
'section',
|
'section',
|
||||||
{
|
{
|
||||||
@@ -874,6 +1059,8 @@ const AttachmentSection = defineComponent({
|
|||||||
h('div', { class: 'dialog-section-title' }, this.title),
|
h('div', { class: 'dialog-section-title' }, this.title),
|
||||||
h('div', { class: 'contract-manage-form__attachment-head' }, [
|
h('div', { class: 'contract-manage-form__attachment-head' }, [
|
||||||
h('div', { class: 'contract-manage-form__attachment-actions' }, [
|
h('div', { class: 'contract-manage-form__attachment-actions' }, [
|
||||||
|
...(!this.readonly
|
||||||
|
? [
|
||||||
h(VehicleAttachmentUpload, {
|
h(VehicleAttachmentUpload, {
|
||||||
modelValue: this.rows,
|
modelValue: this.rows,
|
||||||
fileTypes: this.attachmentFileTypes,
|
fileTypes: this.attachmentFileTypes,
|
||||||
@@ -884,6 +1071,8 @@ const AttachmentSection = defineComponent({
|
|||||||
'onUpdate:modelValue': this.handleChange,
|
'onUpdate:modelValue': this.handleChange,
|
||||||
onChange: this.handleChange,
|
onChange: this.handleChange,
|
||||||
}),
|
}),
|
||||||
|
]
|
||||||
|
: []),
|
||||||
h(
|
h(
|
||||||
ElButton,
|
ElButton,
|
||||||
{ type: 'primary', disabled: !this.rows.length, onClick: this.batchDownload },
|
{ type: 'primary', disabled: !this.rows.length, onClick: this.batchDownload },
|
||||||
@@ -990,6 +1179,17 @@ export default {
|
|||||||
detailBox: false,
|
detailBox: false,
|
||||||
detailLoading: false,
|
detailLoading: false,
|
||||||
detailRow: {},
|
detailRow: {},
|
||||||
|
detailContractFileRows: [],
|
||||||
|
detailAttachmentRows: [],
|
||||||
|
detailBillingPlanRows: [],
|
||||||
|
detailBillingPlanBox: false,
|
||||||
|
detailBillingPlanIndex: -1,
|
||||||
|
detailBillingPlanForm: {},
|
||||||
|
detailSettlementConfigTab: 'pre',
|
||||||
|
detailPreSettlementRuleForm: defaultSettlementRule(),
|
||||||
|
detailFormalSettlementRuleForm: defaultSettlementRule(),
|
||||||
|
detailPaymentRatioRows: [],
|
||||||
|
detailChangeRecordRows: [],
|
||||||
flowBox: false,
|
flowBox: false,
|
||||||
flowUrl: '',
|
flowUrl: '',
|
||||||
processInstanceId: '',
|
processInstanceId: '',
|
||||||
@@ -1069,6 +1269,27 @@ export default {
|
|||||||
value: index + 1,
|
value: index + 1,
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
detailContractPeriod() {
|
||||||
|
const startDate = this.detailRow.startDate || '-';
|
||||||
|
const endDate = this.detailRow.endDate || '-';
|
||||||
|
return `${startDate} 至 ${endDate}`;
|
||||||
|
},
|
||||||
|
detailLegalSealText() {
|
||||||
|
const value = this.detailRow.legalSealFlag;
|
||||||
|
if (value === undefined || value === null || value === '') return '-';
|
||||||
|
return Number(value) === 1 ? '是' : '否';
|
||||||
|
},
|
||||||
|
detailFeeGenerationMode() {
|
||||||
|
const value =
|
||||||
|
this.detailRow.feeGenerationMode ||
|
||||||
|
(Number(this.detailRow.billingEnabled) === 0 ? 'manual' : 'system');
|
||||||
|
return value === 'manual' ? '手动生成' : '系统生成';
|
||||||
|
},
|
||||||
|
detailSettlementRule() {
|
||||||
|
return this.detailSettlementConfigTab === 'formal'
|
||||||
|
? this.detailFormalSettlementRuleForm
|
||||||
|
: this.detailPreSettlementRuleForm;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
'$route.fullPath'() {
|
'$route.fullPath'() {
|
||||||
@@ -1718,16 +1939,55 @@ export default {
|
|||||||
openDetail(row) {
|
openDetail(row) {
|
||||||
this.detailBox = true;
|
this.detailBox = true;
|
||||||
this.detailLoading = true;
|
this.detailLoading = true;
|
||||||
this.detailRow = { ...row };
|
this.applyDetailState(row);
|
||||||
this.api
|
this.api
|
||||||
.getDetail(row.id)
|
.getDetail(row.id)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
this.detailRow = res.data?.data || row;
|
this.applyDetailState(res.data?.data || row);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.detailLoading = false;
|
this.detailLoading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
applyDetailState(detail = {}) {
|
||||||
|
this.detailRow = { ...detail };
|
||||||
|
this.detailContractFileRows = parseArray(detail.contractFileJson);
|
||||||
|
this.detailAttachmentRows = parseArray(detail.attachmentsJson);
|
||||||
|
this.detailBillingPlanRows = parseArray(detail.billingPlanJson);
|
||||||
|
this.detailPaymentRatioRows = parseArray(detail.paymentRatioJson);
|
||||||
|
this.detailChangeRecordRows = parseArray(detail.changeRecordJson);
|
||||||
|
const payload = parseObject(detail.settlementRuleJson);
|
||||||
|
const legacy = Object.keys(payload).some(
|
||||||
|
key => !['preSettlementConfig', 'formalSettlementConfig'].includes(key)
|
||||||
|
)
|
||||||
|
? payload
|
||||||
|
: {};
|
||||||
|
const preConfig = parseObject(detail.preSettlementConfigJson);
|
||||||
|
const formalConfig = parseObject(detail.formalSettlementConfigJson);
|
||||||
|
this.detailPreSettlementRuleForm = this.normalizeSettlementRule(
|
||||||
|
payload.preSettlementConfig || (Object.keys(preConfig).length ? preConfig : legacy)
|
||||||
|
);
|
||||||
|
this.detailFormalSettlementRuleForm = this.normalizeSettlementRule(
|
||||||
|
payload.formalSettlementConfig || (Object.keys(formalConfig).length ? formalConfig : legacy)
|
||||||
|
);
|
||||||
|
this.detailSettlementConfigTab = 'pre';
|
||||||
|
},
|
||||||
|
openDetailBillingPlan(row, index) {
|
||||||
|
this.detailBillingPlanForm = clone(row);
|
||||||
|
this.detailBillingPlanIndex = index;
|
||||||
|
this.detailBillingPlanBox = true;
|
||||||
|
},
|
||||||
|
displayValue(value) {
|
||||||
|
return value === undefined || value === null || value === '' ? '-' : value;
|
||||||
|
},
|
||||||
|
detailUnitValue(prop, unit) {
|
||||||
|
const value = this.detailRow[prop];
|
||||||
|
return value === undefined || value === null || value === '' ? '-' : `${value}${unit}`;
|
||||||
|
},
|
||||||
|
detailObjectUnitValue(row, prop, unit) {
|
||||||
|
const value = row?.[prop];
|
||||||
|
return value === undefined || value === null || value === '' ? '-' : `${value}${unit}`;
|
||||||
|
},
|
||||||
detailValue(prop) {
|
detailValue(prop) {
|
||||||
const value = this.detailRow[prop];
|
const value = this.detailRow[prop];
|
||||||
if (
|
if (
|
||||||
@@ -1743,7 +2003,7 @@ export default {
|
|||||||
if (prop === 'settlementRuleJson') return value ? '已配置' : '-';
|
if (prop === 'settlementRuleJson') return value ? '已配置' : '-';
|
||||||
if (prop === 'paymentRatioJson') return `${parseArray(value).length}项付款比例`;
|
if (prop === 'paymentRatioJson') return `${parseArray(value).length}项付款比例`;
|
||||||
if (prop === 'feeGenerationMode') return value === 'manual' ? '手动生成' : '系统生成';
|
if (prop === 'feeGenerationMode') return value === 'manual' ? '手动生成' : '系统生成';
|
||||||
return value === undefined || value === null || value === '' ? '-' : value;
|
return this.displayValue(value);
|
||||||
},
|
},
|
||||||
handleOperation(operation, row) {
|
handleOperation(operation, row) {
|
||||||
if (operation.action === 'startChange') {
|
if (operation.action === 'startChange') {
|
||||||
@@ -2107,8 +2367,28 @@ export default {
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contract-manage-detail section + section {
|
.contract-manage-detail {
|
||||||
margin-top: 20px;
|
max-height: 74vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
&__descriptions {
|
||||||
|
:deep(.el-descriptions__label) {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 96px;
|
||||||
|
padding-right: 12px;
|
||||||
|
color: #606266;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-descriptions__content) {
|
||||||
|
color: #303133;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-descriptions__cell) {
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
|
|||||||
@@ -2175,7 +2175,7 @@ export default {
|
|||||||
if (draftMode) {
|
if (draftMode) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this.dialogMode === 'add' && this.selectedWaybillRows.length < 2) {
|
if (this.selectedWaybillRows.length < 2) {
|
||||||
ElMessage.warning('请至少选择两条待配载运单');
|
ElMessage.warning('请至少选择两条待配载运单');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -797,11 +797,25 @@ export default {
|
|||||||
result.push(
|
result.push(
|
||||||
`是否接单:${node.confirmMode === 'no_confirm_accept' ? '无需确认接单' : '是'}`
|
`是否接单:${node.confirmMode === 'no_confirm_accept' ? '无需确认接单' : '是'}`
|
||||||
);
|
);
|
||||||
|
result.push(
|
||||||
|
`确认接单人(司机):${node.confirmMode === 'yes' && node.confirmDriver ? '是' : '否'}`
|
||||||
|
);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (node.key === 'return') {
|
if (node.key === 'return') {
|
||||||
|
result.push(
|
||||||
|
`是否确认:${node.confirmMode === 'no_confirm_complete' ? '无需确认完成' : '是'}`
|
||||||
|
);
|
||||||
|
result.push(
|
||||||
|
`确认完成(内部人员):${
|
||||||
|
node.confirmMode === 'yes' && node.confirmInternal ? '是' : '否'
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
if (node.supportVoucher) {
|
||||||
|
result.push(`上传凭证:${node.uploadVoucher ? '是' : '否'}`);
|
||||||
if (node.uploadVoucher && node.voucherTypes.length) {
|
if (node.uploadVoucher && node.voucherTypes.length) {
|
||||||
result.push(`上传凭证:${node.voucherTypes.join('、')}`);
|
result.push(`凭证类型:${node.voucherTypes.join('、')}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -816,11 +830,17 @@ export default {
|
|||||||
result.push(`打卡操作:${node.punch ? '是' : '否'}`);
|
result.push(`打卡操作:${node.punch ? '是' : '否'}`);
|
||||||
result.push(`打卡定位:${node.location ? '是' : '否'}`);
|
result.push(`打卡定位:${node.location ? '是' : '否'}`);
|
||||||
}
|
}
|
||||||
if (node.supportCargo && node.uploadCargo && node.cargoTypes.length) {
|
if (node.supportCargo) {
|
||||||
result.push(`上传货量:${node.cargoTypes.join('、')}`);
|
result.push(`上传货量:${node.uploadCargo ? '是' : '否'}`);
|
||||||
|
if (node.uploadCargo && node.cargoTypes.length) {
|
||||||
|
result.push(`上传货量类型:${node.cargoTypes.join('、')}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.supportVoucher) {
|
||||||
|
result.push(`上传凭证:${node.uploadVoucher ? '是' : '否'}`);
|
||||||
|
if (node.uploadVoucher && node.voucherTypes.length) {
|
||||||
|
result.push(`凭证类型:${node.voucherTypes.join('、')}`);
|
||||||
}
|
}
|
||||||
if (node.supportVoucher && node.uploadVoucher && node.voucherTypes.length) {
|
|
||||||
result.push(`上传凭证:${node.voucherTypes.join('、')}`);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -709,18 +709,33 @@ export default {
|
|||||||
if (!rows.length) return;
|
if (!rows.length) return;
|
||||||
const first = rows[0];
|
const first = rows[0];
|
||||||
const settlementType = this.initialData.settlementType || first.settlementType || 'payable';
|
const settlementType = this.initialData.settlementType || first.settlementType || 'payable';
|
||||||
const contractId = first.contractId || null;
|
const matchedContract = this.allContracts.find(
|
||||||
|
item =>
|
||||||
|
(first.contractId && String(item.id) === String(first.contractId)) ||
|
||||||
|
(first.contractNo && String(item.contractNo) === String(first.contractNo))
|
||||||
|
);
|
||||||
|
const contractId = first.contractId || matchedContract?.id || null;
|
||||||
|
const projectId = first.projectId || matchedContract?.projectId || null;
|
||||||
|
const projectName = first.projectName || matchedContract?.projectName || '';
|
||||||
|
this.contracts = this.allContracts.filter(
|
||||||
|
item => projectId && String(item.projectId) === String(projectId)
|
||||||
|
);
|
||||||
|
if (projectId && !this.projects.some(item => String(item.id) === String(projectId))) {
|
||||||
|
this.projects.push({ id: projectId, name: projectName });
|
||||||
|
}
|
||||||
if (!this.contracts.some(item => String(item.id) === String(contractId))) {
|
if (!this.contracts.some(item => String(item.id) === String(contractId))) {
|
||||||
this.contracts.push({
|
this.contracts.push({
|
||||||
id: contractId,
|
id: contractId,
|
||||||
contractNo: first.contractNo,
|
contractNo: first.contractNo,
|
||||||
contractName: first.contractName,
|
contractName: first.contractName,
|
||||||
projectId: first.projectId,
|
projectId,
|
||||||
projectName: first.projectName,
|
projectName,
|
||||||
deptId: first.deptId,
|
deptId: first.deptId || matchedContract?.deptId,
|
||||||
deptName: first.deptName,
|
deptName: first.deptName || matchedContract?.deptName,
|
||||||
payerName: first.payerName,
|
payerName: first.payerName,
|
||||||
payeeName: first.payeeName,
|
payeeName: first.payeeName,
|
||||||
|
partyA: matchedContract?.partyA,
|
||||||
|
partyB: matchedContract?.partyB,
|
||||||
settlementType,
|
settlementType,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -729,8 +744,8 @@ export default {
|
|||||||
contractId,
|
contractId,
|
||||||
contractNo: first.contractNo || this.form.contractNo,
|
contractNo: first.contractNo || this.form.contractNo,
|
||||||
contractName: first.contractName || this.form.contractName,
|
contractName: first.contractName || this.form.contractName,
|
||||||
projectId: first.projectId || this.form.projectId,
|
projectId: projectId || this.form.projectId,
|
||||||
projectName: first.projectName || this.form.projectName,
|
projectName: projectName || this.form.projectName,
|
||||||
deptId: first.deptId || this.form.deptId,
|
deptId: first.deptId || this.form.deptId,
|
||||||
deptName: first.deptName || this.form.deptName,
|
deptName: first.deptName || this.form.deptName,
|
||||||
payerName: first.payerName || this.form.payerName,
|
payerName: first.payerName || this.form.payerName,
|
||||||
@@ -1035,10 +1050,7 @@ export default {
|
|||||||
return columns.map((column, index) => {
|
return columns.map((column, index) => {
|
||||||
if (index === 0) return '合计';
|
if (index === 0) return '合计';
|
||||||
if (!sumProps.includes(column.property)) return '';
|
if (!sumProps.includes(column.property)) return '';
|
||||||
const total = data.reduce(
|
const total = data.reduce((sum, row) => sum + Number(row[column.property] || 0), 0);
|
||||||
(sum, row) => sum + Number(row[column.property] || 0),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
return this.formatMoney(total);
|
return this.formatMoney(total);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1010,6 +1010,15 @@ export default {
|
|||||||
this.$message.warning('请至少选择一条结算明细');
|
this.$message.warning('请至少选择一条结算明细');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const invalidManualFeeIndex = this.summaryFees.findIndex(
|
||||||
|
row =>
|
||||||
|
Number(row.manualFlag) === 1 &&
|
||||||
|
(!String(row.feeType || '').trim() || !String(row.feeItem || '').trim())
|
||||||
|
);
|
||||||
|
if (invalidManualFeeIndex >= 0) {
|
||||||
|
this.$message.warning(`请完善结算合计第${invalidManualFeeIndex + 1}行的费用类型和费用项`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const stateKey = shouldSubmit ? 'submitting' : 'saving';
|
const stateKey = shouldSubmit ? 'submitting' : 'saving';
|
||||||
this[stateKey] = true;
|
this[stateKey] = true;
|
||||||
try {
|
try {
|
||||||
@@ -1040,7 +1049,7 @@ export default {
|
|||||||
sourceDetailIds: this.details.map(row => row.sourceDetailId || row.id),
|
sourceDetailIds: this.details.map(row => row.sourceDetailId || row.id),
|
||||||
summaryFees: this.summaryFees.map(row => ({
|
summaryFees: this.summaryFees.map(row => ({
|
||||||
id: row.id || undefined,
|
id: row.id || undefined,
|
||||||
feeType: row.feeType,
|
feeType: row.feeType || '',
|
||||||
feeItem: row.feeItem,
|
feeItem: row.feeItem,
|
||||||
adjustAmount: Number(row.adjustAmount || 0),
|
adjustAmount: Number(row.adjustAmount || 0),
|
||||||
remark: row.remark,
|
remark: row.remark,
|
||||||
@@ -1067,7 +1076,7 @@ export default {
|
|||||||
return this.feeOptions.find(item => item.feeType === feeType)?.feeItems || [];
|
return this.feeOptions.find(item => item.feeType === feeType)?.feeItems || [];
|
||||||
},
|
},
|
||||||
feeCategoryName(value) {
|
feeCategoryName(value) {
|
||||||
if (value === undefined || value === null || value === '') return '-';
|
if (value === undefined || value === null || value === '') return '';
|
||||||
const option = this.feeCategoryOptions.find(
|
const option = this.feeCategoryOptions.find(
|
||||||
item => String(item.dictKey) === String(value) || String(item.dictValue) === String(value)
|
item => String(item.dictKey) === String(value) || String(item.dictValue) === String(value)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -318,7 +318,7 @@
|
|||||||
<el-form-item label="转结算类型">
|
<el-form-item label="转结算类型">
|
||||||
<el-radio-group
|
<el-radio-group
|
||||||
v-model="transferForm.settlementBillType"
|
v-model="transferForm.settlementBillType"
|
||||||
@change="loadTransferCandidates"
|
@change="handleTransferTypeChange"
|
||||||
>
|
>
|
||||||
<el-radio label="pre">预结算单</el-radio>
|
<el-radio label="pre">预结算单</el-radio>
|
||||||
<el-radio label="formal">正式结算单</el-radio>
|
<el-radio label="formal">正式结算单</el-radio>
|
||||||
@@ -343,18 +343,26 @@
|
|||||||
<el-input v-else v-model="transferQuery[field.prop]" clearable placeholder="请输入" />
|
<el-input v-else v-model="transferQuery[field.prop]" clearable placeholder="请输入" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="loadTransferCandidates">查询</el-button>
|
<el-button type="primary" @click="handleTransferSearch">查询</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
<el-table
|
<el-table
|
||||||
|
ref="transferTableRef"
|
||||||
v-loading="transferDialog.loading"
|
v-loading="transferDialog.loading"
|
||||||
:data="transferRows"
|
:data="transferRows"
|
||||||
|
row-key="id"
|
||||||
border
|
border
|
||||||
@selection-change="transferSelectionChange"
|
@selection-change="transferSelectionChange"
|
||||||
>
|
>
|
||||||
<el-table-column type="selection" width="52" align="center" />
|
<el-table-column type="selection" width="52" align="center" reserve-selection />
|
||||||
<el-table-column type="index" label="序号" width="70" align="center" />
|
<el-table-column
|
||||||
|
type="index"
|
||||||
|
label="序号"
|
||||||
|
width="70"
|
||||||
|
align="center"
|
||||||
|
:index="transferIndexMethod"
|
||||||
|
/>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
v-for="column in tableColumns.slice(0, 13)"
|
v-for="column in tableColumns.slice(0, 13)"
|
||||||
:key="column.prop"
|
:key="column.prop"
|
||||||
@@ -367,6 +375,17 @@
|
|||||||
<template #default="{ row }">{{ formatColumnValue(row, column) }}</template>
|
<template #default="{ row }">{{ formatColumnValue(row, column) }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<div class="settlement-detail-page__pagination">
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="transferPage.current"
|
||||||
|
v-model:page-size="transferPage.size"
|
||||||
|
:total="transferPage.total"
|
||||||
|
:page-sizes="[10, 20, 50]"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
@current-change="loadTransferCandidates"
|
||||||
|
@size-change="handleTransferSizeChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="transferDialog.visible = false">取消</el-button>
|
<el-button @click="transferDialog.visible = false">取消</el-button>
|
||||||
<el-button type="primary" :loading="transferDialog.submitting" @click="submitTransfer">
|
<el-button type="primary" :loading="transferDialog.submitting" @click="submitTransfer">
|
||||||
@@ -593,6 +612,7 @@ export default {
|
|||||||
transferForm: { settlementBillType: 'formal' },
|
transferForm: { settlementBillType: 'formal' },
|
||||||
transferRows: [],
|
transferRows: [],
|
||||||
transferSelection: [],
|
transferSelection: [],
|
||||||
|
transferPage: { current: 1, size: 10, total: 0 },
|
||||||
generateDialog: { visible: false, loading: false },
|
generateDialog: { visible: false, loading: false },
|
||||||
generateQuery: {},
|
generateQuery: {},
|
||||||
generateRows: [],
|
generateRows: [],
|
||||||
@@ -1029,11 +1049,12 @@ export default {
|
|||||||
this.transferQuery = {};
|
this.transferQuery = {};
|
||||||
this.transferRows = [];
|
this.transferRows = [];
|
||||||
this.transferSelection = [];
|
this.transferSelection = [];
|
||||||
|
this.transferPage = { current: 1, size: 10, total: 0 };
|
||||||
|
this.$nextTick(() => this.$refs.transferTableRef?.clearSelection());
|
||||||
this.loadTransferCandidates();
|
this.loadTransferCandidates();
|
||||||
},
|
},
|
||||||
async loadTransferCandidates() {
|
async loadTransferCandidates() {
|
||||||
this.transferDialog.loading = true;
|
this.transferDialog.loading = true;
|
||||||
this.transferSelection = [];
|
|
||||||
try {
|
try {
|
||||||
const params = this.buildRequestParams(
|
const params = this.buildRequestParams(
|
||||||
this.normalizeQuery(
|
this.normalizeQuery(
|
||||||
@@ -1043,20 +1064,46 @@ export default {
|
|||||||
'generateEndDate'
|
'generateEndDate'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
const res = await api.getTransferCandidates(1, 50, {
|
const res = await api.getTransferCandidates(
|
||||||
|
this.transferPage.current,
|
||||||
|
this.transferPage.size,
|
||||||
|
{
|
||||||
...params,
|
...params,
|
||||||
settlementStatus: 'pending',
|
settlementStatus: 'pending',
|
||||||
settlementType: this.settlementType || undefined,
|
settlementType: this.settlementType || undefined,
|
||||||
settlementBillType: this.transferForm.settlementBillType,
|
settlementBillType: this.transferForm.settlementBillType,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
const data = this.unwrapPage(res);
|
const data = this.unwrapPage(res);
|
||||||
this.transferRows = (data.records || [])
|
this.transferRows = (data.records || [])
|
||||||
.filter(row => this.isTransferCandidate(row))
|
.filter(row => this.isTransferCandidate(row))
|
||||||
.map(this.decorateRow);
|
.map(this.decorateRow);
|
||||||
|
this.transferPage.total = data.total || 0;
|
||||||
} finally {
|
} finally {
|
||||||
this.transferDialog.loading = false;
|
this.transferDialog.loading = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
resetTransferSelection() {
|
||||||
|
this.transferSelection = [];
|
||||||
|
this.$nextTick(() => this.$refs.transferTableRef?.clearSelection());
|
||||||
|
},
|
||||||
|
handleTransferSearch() {
|
||||||
|
this.transferPage.current = 1;
|
||||||
|
this.resetTransferSelection();
|
||||||
|
this.loadTransferCandidates();
|
||||||
|
},
|
||||||
|
handleTransferTypeChange() {
|
||||||
|
this.transferPage.current = 1;
|
||||||
|
this.resetTransferSelection();
|
||||||
|
this.loadTransferCandidates();
|
||||||
|
},
|
||||||
|
handleTransferSizeChange() {
|
||||||
|
this.transferPage.current = 1;
|
||||||
|
this.loadTransferCandidates();
|
||||||
|
},
|
||||||
|
transferIndexMethod(index) {
|
||||||
|
return (this.transferPage.current - 1) * this.transferPage.size + index + 1;
|
||||||
|
},
|
||||||
isTransferCandidate(row) {
|
isTransferCandidate(row) {
|
||||||
const hasValue = value => {
|
const hasValue = value => {
|
||||||
if (Array.isArray(value)) return value.length > 0;
|
if (Array.isArray(value)) return value.length > 0;
|
||||||
@@ -1151,16 +1198,38 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async resolveTransferContractIds(rows) {
|
async resolveTransferContractIds(rows) {
|
||||||
if (rows.every(item => item.contractId)) return rows;
|
if (rows.every(item => item.contractId && item.projectId)) return rows;
|
||||||
|
const contractId = rows.find(item => item.contractId)?.contractId;
|
||||||
const contractNo = rows.find(item => item.contractNo)?.contractNo;
|
const contractNo = rows.find(item => item.contractNo)?.contractNo;
|
||||||
const { data } = await getSettlementContractOptions(contractNo);
|
const { data } = await getSettlementContractOptions(contractNo);
|
||||||
const contracts = data?.data || [];
|
const contracts = data?.data || [];
|
||||||
const contract = contracts.find(item => String(item.contractNo) === String(contractNo));
|
const contract = contracts.find(
|
||||||
if (!contract?.id) {
|
item =>
|
||||||
this.$message.warning('未找到所选明细对应的有效合同,无法转结算');
|
(contractId && String(item.id) === String(contractId)) ||
|
||||||
|
(contractNo && String(item.contractNo) === String(contractNo))
|
||||||
|
);
|
||||||
|
if (!contract?.id || !contract.projectId) {
|
||||||
|
this.$message.warning('未找到所选明细对应的合同或项目信息,无法转结算');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return rows.map(item => ({ ...item, contractId: item.contractId || contract.id }));
|
return rows.map(item => {
|
||||||
|
const settlementType =
|
||||||
|
item.settlementType || this.settlementType || contract.settlementType;
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
contractId: item.contractId || contract.id,
|
||||||
|
contractNo: item.contractNo || contract.contractNo,
|
||||||
|
contractName: item.contractName || contract.contractName,
|
||||||
|
projectId: item.projectId || contract.projectId,
|
||||||
|
projectName: item.projectName || contract.projectName,
|
||||||
|
deptId: item.deptId || contract.deptId,
|
||||||
|
deptName: item.deptName || contract.deptName,
|
||||||
|
payerName:
|
||||||
|
item.payerName || (settlementType === 'receivable' ? contract.partyB : contract.partyA),
|
||||||
|
payeeName:
|
||||||
|
item.payeeName || (settlementType === 'receivable' ? contract.partyA : contract.partyB),
|
||||||
|
};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
openGenerateDialog() {
|
openGenerateDialog() {
|
||||||
this.generateDialog.visible = true;
|
this.generateDialog.visible = true;
|
||||||
|
|||||||
@@ -1309,6 +1309,11 @@ export default {
|
|||||||
},
|
},
|
||||||
normalizeBirthday(value = '') {
|
normalizeBirthday(value = '') {
|
||||||
const birthday = String(value || '').trim();
|
const birthday = String(value || '').trim();
|
||||||
|
const compactMatch = birthday.match(/^(\d{4})(\d{2})(\d{2})$/);
|
||||||
|
if (compactMatch) {
|
||||||
|
const [, year, month, day] = compactMatch;
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
}
|
||||||
const match = birthday.match(/^(\d{4})[-/.年](\d{1,2})[-/.月](\d{1,2})日?$/);
|
const match = birthday.match(/^(\d{4})[-/.年](\d{1,2})[-/.月](\d{1,2})日?$/);
|
||||||
if (!match) return birthday;
|
if (!match) return birthday;
|
||||||
const [, year, month, day] = match;
|
const [, year, month, day] = match;
|
||||||
@@ -1343,6 +1348,10 @@ export default {
|
|||||||
}
|
}
|
||||||
const row = {
|
const row = {
|
||||||
...this.driverForm,
|
...this.driverForm,
|
||||||
|
birthday: this.normalizeBirthday(this.driverForm.birthday),
|
||||||
|
drivingLicenseStartDate: this.normalizeBirthday(this.driverForm.drivingLicenseStartDate),
|
||||||
|
drivingLicenseEndDate: this.normalizeBirthday(this.driverForm.drivingLicenseEndDate),
|
||||||
|
qualificationEndDate: this.normalizeBirthday(this.driverForm.qualificationEndDate),
|
||||||
qualificationNo: this.driverForm.qualificationNo || this.driverForm.idCardNo,
|
qualificationNo: this.driverForm.qualificationNo || this.driverForm.idCardNo,
|
||||||
posts: this.driverForm.postList.join(','),
|
posts: this.driverForm.postList.join(','),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@input="value => normalizeDecimalInput('directEconomicLoss', value)"
|
@input="value => normalizeDecimalInput('directEconomicLoss', value)"
|
||||||
>
|
>
|
||||||
<template #suffix>元</template>
|
<template #append>元</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</template>
|
</template>
|
||||||
<template #insuranceClaimAmountForm>
|
<template #insuranceClaimAmountForm>
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@input="value => normalizeDecimalInput('insuranceClaimAmount', value)"
|
@input="value => normalizeDecimalInput('insuranceClaimAmount', value)"
|
||||||
>
|
>
|
||||||
<template #suffix>元</template>
|
<template #append>元</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</template>
|
</template>
|
||||||
<template #attachments="{ row }">
|
<template #attachments="{ row }">
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@input="value => normalizeDecimalInput('fee', value)"
|
@input="value => normalizeDecimalInput('fee', value)"
|
||||||
>
|
>
|
||||||
<template #suffix>元</template>
|
<template #append>元</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</template>
|
</template>
|
||||||
<template #attachments="{ row }">
|
<template #attachments="{ row }">
|
||||||
|
|||||||
@@ -634,11 +634,20 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="文件名称" min-width="180">
|
<el-table-column label="文件名称" min-width="180" align="left">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-link type="primary" :disabled="!row.url" @click="previewQualificationFile(row)">{{
|
<div
|
||||||
row.originalName || row.name || '-'
|
class="qualification-file-name-cell"
|
||||||
}}</el-link>
|
:title="row.originalName || row.name || '-'"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="qualification-file-name"
|
||||||
|
:class="{ 'is-disabled': !row.url }"
|
||||||
|
@click="row.url && previewQualificationFile(row)"
|
||||||
|
>
|
||||||
|
{{ row.originalName || row.name || '-' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="附件描述" min-width="220">
|
<el-table-column label="附件描述" min-width="220">
|
||||||
@@ -4461,6 +4470,41 @@ export default {
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qualification-file-name-cell {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-align: left;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qualification-file-name {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
vertical-align: middle;
|
||||||
|
white-space: nowrap;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #606266;
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-disabled {
|
||||||
|
cursor: default;
|
||||||
|
color: #606266;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.qualification-upload-bar {
|
.qualification-upload-bar {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto 1fr;
|
grid-template-columns: 1fr auto 1fr;
|
||||||
|
|||||||
@@ -70,6 +70,15 @@
|
|||||||
class="maintenance-plan-page__input"
|
class="maintenance-plan-page__input"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
<template #address-form>
|
||||||
|
<el-input
|
||||||
|
v-model="form.address"
|
||||||
|
:disabled="boxType === 'view'"
|
||||||
|
readonly
|
||||||
|
placeholder="点击地图选址"
|
||||||
|
@click="openAddressMapPicker"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
<template #mileageForm>
|
<template #mileageForm>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.mileage"
|
v-model="form.mileage"
|
||||||
@@ -140,6 +149,11 @@
|
|||||||
</template>
|
</template>
|
||||||
</avue-form>
|
</avue-form>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<address-map-picker
|
||||||
|
v-model="addressMapPickerVisible"
|
||||||
|
:address="form.address"
|
||||||
|
@confirm="handleAddressMapConfirm"
|
||||||
|
/>
|
||||||
</basic-container>
|
</basic-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -154,6 +168,7 @@ import { openImportDialog } from '@/utils/import-excel';
|
|||||||
import { formatUpdateUserName } from '@/utils/audit';
|
import { formatUpdateUserName } from '@/utils/audit';
|
||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||||
|
import AddressMapPicker from '@/components/address-map-picker/main.vue';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import NProgress from 'nprogress';
|
import NProgress from 'nprogress';
|
||||||
import 'nprogress/nprogress.css';
|
import 'nprogress/nprogress.css';
|
||||||
@@ -163,6 +178,9 @@ const createTimeRangeMap = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
AddressMapPicker,
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
const validateNonNegative = (rule, value, callback) => {
|
const validateNonNegative = (rule, value, callback) => {
|
||||||
if (value === undefined || value === null || value === '') {
|
if (value === undefined || value === null || value === '') {
|
||||||
@@ -178,6 +196,7 @@ export default {
|
|||||||
query: {},
|
query: {},
|
||||||
loading: true,
|
loading: true,
|
||||||
excelBox: false,
|
excelBox: false,
|
||||||
|
addressMapPickerVisible: false,
|
||||||
excelForm: {},
|
excelForm: {},
|
||||||
page: {
|
page: {
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
@@ -203,6 +222,7 @@ export default {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
@@ -315,6 +335,8 @@ export default {
|
|||||||
{
|
{
|
||||||
label: '地址',
|
label: '地址',
|
||||||
prop: 'address',
|
prop: 'address',
|
||||||
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
overHidden: true,
|
overHidden: true,
|
||||||
span: 24,
|
span: 24,
|
||||||
@@ -483,6 +505,14 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
openAddressMapPicker() {
|
||||||
|
if (this.boxType !== 'view') {
|
||||||
|
this.addressMapPickerVisible = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleAddressMapConfirm(address) {
|
||||||
|
this.form.address = address;
|
||||||
|
},
|
||||||
hasPermission(code) {
|
hasPermission(code) {
|
||||||
return this.isAdmin || this.validData(this.permission[code], false);
|
return this.isAdmin || this.validData(this.permission[code], false);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -70,6 +70,15 @@
|
|||||||
class="maintenance-record-page__input"
|
class="maintenance-record-page__input"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
<template #address-form>
|
||||||
|
<el-input
|
||||||
|
v-model="form.address"
|
||||||
|
:disabled="boxType === 'view'"
|
||||||
|
readonly
|
||||||
|
placeholder="点击地图选址"
|
||||||
|
@click="openAddressMapPicker"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
<template #costForm>
|
<template #costForm>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.cost"
|
v-model="form.cost"
|
||||||
@@ -126,6 +135,11 @@
|
|||||||
</template>
|
</template>
|
||||||
</avue-form>
|
</avue-form>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<address-map-picker
|
||||||
|
v-model="addressMapPickerVisible"
|
||||||
|
:address="form.address"
|
||||||
|
@confirm="handleAddressMapConfirm"
|
||||||
|
/>
|
||||||
</basic-container>
|
</basic-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -140,6 +154,7 @@ import { openImportDialog } from '@/utils/import-excel';
|
|||||||
import { formatUpdateUserName } from '@/utils/audit';
|
import { formatUpdateUserName } from '@/utils/audit';
|
||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||||
|
import AddressMapPicker from '@/components/address-map-picker/main.vue';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import NProgress from 'nprogress';
|
import NProgress from 'nprogress';
|
||||||
import 'nprogress/nprogress.css';
|
import 'nprogress/nprogress.css';
|
||||||
@@ -149,6 +164,9 @@ const createTimeRangeMap = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
AddressMapPicker,
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
const validateNonNegative = (rule, value, callback) => {
|
const validateNonNegative = (rule, value, callback) => {
|
||||||
if (value === undefined || value === null || value === '') {
|
if (value === undefined || value === null || value === '') {
|
||||||
@@ -164,6 +182,7 @@ export default {
|
|||||||
query: {},
|
query: {},
|
||||||
loading: true,
|
loading: true,
|
||||||
excelBox: false,
|
excelBox: false,
|
||||||
|
addressMapPickerVisible: false,
|
||||||
excelForm: {},
|
excelForm: {},
|
||||||
isDetailLoading: false,
|
isDetailLoading: false,
|
||||||
page: {
|
page: {
|
||||||
@@ -190,6 +209,7 @@ export default {
|
|||||||
border: true,
|
border: true,
|
||||||
index: true,
|
index: true,
|
||||||
indexLabel: '序号',
|
indexLabel: '序号',
|
||||||
|
indexWidth: 90,
|
||||||
viewBtn: true,
|
viewBtn: true,
|
||||||
selection: true,
|
selection: true,
|
||||||
dialogClickModal: false,
|
dialogClickModal: false,
|
||||||
@@ -291,6 +311,8 @@ export default {
|
|||||||
{
|
{
|
||||||
label: '地址',
|
label: '地址',
|
||||||
prop: 'address',
|
prop: 'address',
|
||||||
|
slot: true,
|
||||||
|
formslot: true,
|
||||||
minWidth: 180,
|
minWidth: 180,
|
||||||
overHidden: true,
|
overHidden: true,
|
||||||
span: 24,
|
span: 24,
|
||||||
@@ -478,6 +500,14 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
openAddressMapPicker() {
|
||||||
|
if (this.boxType !== 'view') {
|
||||||
|
this.addressMapPickerVisible = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleAddressMapConfirm(address) {
|
||||||
|
this.form.address = address;
|
||||||
|
},
|
||||||
hasPermission(code) {
|
hasPermission(code) {
|
||||||
return this.isAdmin || this.validData(this.permission[code], false);
|
return this.isAdmin || this.validData(this.permission[code], false);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@input="value => normalizeIntegerInput('previousMonthMileage', value)"
|
@input="value => normalizeIntegerInput('previousMonthMileage', value)"
|
||||||
>
|
>
|
||||||
<template #suffix>km</template>
|
<template #append>km</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</template>
|
</template>
|
||||||
<template #currentMonthMileageForm>
|
<template #currentMonthMileageForm>
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@input="value => normalizeIntegerInput('currentMonthMileage', value)"
|
@input="value => normalizeIntegerInput('currentMonthMileage', value)"
|
||||||
>
|
>
|
||||||
<template #suffix>km</template>
|
<template #append>km</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</template>
|
</template>
|
||||||
<template #monthlyMileageForm>
|
<template #monthlyMileageForm>
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@input="value => normalizeIntegerInput('monthlyMileage', value)"
|
@input="value => normalizeIntegerInput('monthlyMileage', value)"
|
||||||
>
|
>
|
||||||
<template #suffix>km</template>
|
<template #append>km</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</template>
|
</template>
|
||||||
<template #totalMileageForm>
|
<template #totalMileageForm>
|
||||||
@@ -123,7 +123,7 @@
|
|||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@input="value => normalizeIntegerInput('totalMileage', value)"
|
@input="value => normalizeIntegerInput('totalMileage', value)"
|
||||||
>
|
>
|
||||||
<template #suffix>km</template>
|
<template #append>km</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</template>
|
</template>
|
||||||
<template #totalMileageStart-search="{ row }">
|
<template #totalMileageStart-search="{ row }">
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@input="value => normalizeDecimalInput('unitPrice', value)"
|
@input="value => normalizeDecimalInput('unitPrice', value)"
|
||||||
>
|
>
|
||||||
<template #suffix>元</template>
|
<template #append>元/升</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</template>
|
</template>
|
||||||
<template #transactionAmountForm>
|
<template #transactionAmountForm>
|
||||||
|
|||||||
@@ -110,6 +110,15 @@
|
|||||||
@input="value => normalizeIntegerInput('deductPoints', value)"
|
@input="value => normalizeIntegerInput('deductPoints', value)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
<template #location-form>
|
||||||
|
<el-input
|
||||||
|
v-model="form.location"
|
||||||
|
:disabled="boxType === 'view'"
|
||||||
|
readonly
|
||||||
|
placeholder="点击地图选址"
|
||||||
|
@click="openLocationMapPicker"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
<template #processStatus="{ row }">
|
<template #processStatus="{ row }">
|
||||||
<span :class="row.processStatus === '未处理' ? 'violation-record-page__danger' : ''">
|
<span :class="row.processStatus === '未处理' ? 'violation-record-page__danger' : ''">
|
||||||
{{ row.processStatus }}
|
{{ row.processStatus }}
|
||||||
@@ -152,6 +161,11 @@
|
|||||||
</template>
|
</template>
|
||||||
</avue-form>
|
</avue-form>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<address-map-picker
|
||||||
|
v-model="locationMapPickerVisible"
|
||||||
|
:address="form.location"
|
||||||
|
@confirm="handleLocationMapConfirm"
|
||||||
|
/>
|
||||||
</basic-container>
|
</basic-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -167,6 +181,7 @@ import { downloadXls } from '@/utils/util';
|
|||||||
import { openImportDialog } from '@/utils/import-excel';
|
import { openImportDialog } from '@/utils/import-excel';
|
||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
import { normalizeSearchRangeParams } from '@/utils/search-range';
|
||||||
|
import AddressMapPicker from '@/components/address-map-picker/main.vue';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import { excelOption, option } from '@/option/vehicle/violation-record';
|
import { excelOption, option } from '@/option/vehicle/violation-record';
|
||||||
import NProgress from 'nprogress';
|
import NProgress from 'nprogress';
|
||||||
@@ -177,12 +192,16 @@ const createTimeRangeMap = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
AddressMapPicker,
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form: {},
|
form: {},
|
||||||
query: {},
|
query: {},
|
||||||
loading: true,
|
loading: true,
|
||||||
excelBox: false,
|
excelBox: false,
|
||||||
|
locationMapPickerVisible: false,
|
||||||
excelForm: {},
|
excelForm: {},
|
||||||
isDetailLoading: false,
|
isDetailLoading: false,
|
||||||
option,
|
option,
|
||||||
@@ -242,6 +261,14 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
openLocationMapPicker() {
|
||||||
|
if (this.boxType !== 'view') {
|
||||||
|
this.locationMapPickerVisible = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleLocationMapConfirm(address) {
|
||||||
|
this.form.location = address;
|
||||||
|
},
|
||||||
hasPermission(code) {
|
hasPermission(code) {
|
||||||
return this.isAdmin || this.validData(this.permission[code], false);
|
return this.isAdmin || this.validData(this.permission[code], false);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user