1、修复基础配置
2、修复业务模块 3、拆分页面代码
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>合同弹窗调试</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module">
|
||||||
|
import { createApp, nextTick, onMounted, ref } from 'vue/dist/vue.esm-bundler.js';
|
||||||
|
import ElementPlus from 'element-plus';
|
||||||
|
import 'element-plus/dist/index.css';
|
||||||
|
import './src/styles/common.scss';
|
||||||
|
import ReceivablePayableDetail from './src/views/settlement/receivable-payable-detail.vue';
|
||||||
|
import { setupTableColumnDrag } from './src/utils/table-column-drag.js';
|
||||||
|
|
||||||
|
const fields = [
|
||||||
|
'contractNo',
|
||||||
|
'contractName',
|
||||||
|
'projectName',
|
||||||
|
'organizationName',
|
||||||
|
'contractCategory',
|
||||||
|
'signType',
|
||||||
|
'partyA',
|
||||||
|
'partyB',
|
||||||
|
'startDate',
|
||||||
|
'endDate',
|
||||||
|
'temporaryStartDate',
|
||||||
|
'temporaryEndDate',
|
||||||
|
];
|
||||||
|
const row = Object.fromEntries(fields.map(field => [field, `${field}数据`]));
|
||||||
|
const TestComponent = { ...ReceivablePayableDetail, mounted() {} };
|
||||||
|
const app = createApp({
|
||||||
|
components: { TestComponent },
|
||||||
|
setup() {
|
||||||
|
const target = ref();
|
||||||
|
onMounted(async () => {
|
||||||
|
await nextTick();
|
||||||
|
target.value.generateContractDialog.rows = Array.from({ length: 10 }, () => ({ ...row }));
|
||||||
|
target.value.generateContractDialog.page.total = 10;
|
||||||
|
target.value.generateContractDialog.visible = true;
|
||||||
|
});
|
||||||
|
return { target };
|
||||||
|
},
|
||||||
|
template: '<test-component ref="target" settlement-type="payable" />',
|
||||||
|
});
|
||||||
|
app.component('basic-container', { template: '<div><slot /></div>' });
|
||||||
|
app.config.globalProperties.$route = { fullPath: '/debug', query: {} };
|
||||||
|
app.config.globalProperties.$store = { getters: { permission: {}, userInfo: {} } };
|
||||||
|
app.use(ElementPlus, { table: { showOverflowTooltip: true } });
|
||||||
|
setupTableColumnDrag(app);
|
||||||
|
app.mount('#app');
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -86,3 +86,10 @@ export const getDictionary = params => {
|
|||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getDictionaryAll = () => {
|
||||||
|
return request({
|
||||||
|
url: '/blade-system/dict-biz/select-all',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -30,6 +30,9 @@
|
|||||||
{{ row.status === 1 ? '启用' : '停用' }}
|
{{ row.status === 1 ? '启用' : '停用' }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
|
<template #feeCategory="{ row }">
|
||||||
|
{{ formatFeeCategory(row.feeCategory) }}
|
||||||
|
</template>
|
||||||
<template #feeCategory-form>
|
<template #feeCategory-form>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="form.feeCategory"
|
v-model="form.feeCategory"
|
||||||
@@ -78,7 +81,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getList, getDetail, submit, remove, changeStatus } from '@/api/base/fee-item';
|
import { getList, getDetail, submit, remove, changeStatus } from '@/api/base/fee-item';
|
||||||
import { exportBlob } from '@/api/common';
|
import { exportBlob } from '@/api/common';
|
||||||
import { getDictionary } from '@/api/system/dictbiz';
|
import { getDictionaryAll } from '@/api/system/dictbiz';
|
||||||
import { getDeptTree } from '@/api/system/dept';
|
import { getDeptTree } from '@/api/system/dept';
|
||||||
import { downloadXls } from '@/utils/util';
|
import { downloadXls } from '@/utils/util';
|
||||||
import { getToken } from '@/utils/auth';
|
import { getToken } from '@/utils/auth';
|
||||||
@@ -134,10 +137,11 @@ export default {
|
|||||||
searchOrder: 3,
|
searchOrder: 3,
|
||||||
filterable: true,
|
filterable: true,
|
||||||
formslot: true,
|
formslot: true,
|
||||||
|
slot: true,
|
||||||
span: 12,
|
span: 12,
|
||||||
dicData: [],
|
dicData: [],
|
||||||
props: {
|
props: {
|
||||||
label: 'dictValue',
|
label: 'displayLabel',
|
||||||
value: 'dictKey',
|
value: 'dictKey',
|
||||||
},
|
},
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
@@ -168,7 +172,8 @@ export default {
|
|||||||
type: 'textarea',
|
type: 'textarea',
|
||||||
minRows: 2,
|
minRows: 2,
|
||||||
span: 24,
|
span: 24,
|
||||||
hide: true,
|
minWidth: 200,
|
||||||
|
overHidden: true,
|
||||||
maxlength: 200,
|
maxlength: 200,
|
||||||
showWordLimit: true,
|
showWordLimit: true,
|
||||||
rules: [{ max: 200, message: '备注不能超过200个字', trigger: 'blur' }],
|
rules: [{ max: 200, message: '备注不能超过200个字', trigger: 'blur' }],
|
||||||
@@ -273,10 +278,17 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initFeeCategoryOptions() {
|
initFeeCategoryOptions() {
|
||||||
getDictionary({ code: 'fee_category' }).then(res => {
|
getDictionaryAll().then(res => {
|
||||||
this.feeCategoryOptions = res.data.data || [];
|
const options = (res.data.data || [])
|
||||||
|
.filter(item => item.code === 'fee_category' && Number(item.parentId) > 0)
|
||||||
|
.sort((first, second) => Number(first.sort || 0) - Number(second.sort || 0))
|
||||||
|
.map(item => ({
|
||||||
|
...item,
|
||||||
|
displayLabel: `${item.dictValue}/${item.dictKey}`,
|
||||||
|
}));
|
||||||
|
this.feeCategoryOptions = options;
|
||||||
const column = this.findColumn(this.option.column, 'feeCategory');
|
const column = this.findColumn(this.option.column, 'feeCategory');
|
||||||
column.dicData = this.feeCategoryOptions;
|
column.dicData = options;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
initDeptTree() {
|
initDeptTree() {
|
||||||
@@ -305,6 +317,15 @@ export default {
|
|||||||
);
|
);
|
||||||
return String((option && option.dictKey) || feeCategory);
|
return String((option && option.dictKey) || feeCategory);
|
||||||
},
|
},
|
||||||
|
formatFeeCategory(value) {
|
||||||
|
const feeCategory = String(value || '').trim();
|
||||||
|
if (!feeCategory) return '';
|
||||||
|
const option = this.feeCategoryOptions.find(
|
||||||
|
item =>
|
||||||
|
String(item.dictKey || '') === feeCategory || String(item.dictValue || '') === feeCategory
|
||||||
|
);
|
||||||
|
return option ? `${option.dictValue}/${option.dictKey}` : feeCategory;
|
||||||
|
},
|
||||||
getFeeItemCodeSuffix(code, feeCategory) {
|
getFeeItemCodeSuffix(code, feeCategory) {
|
||||||
const value = String(code || '').trim();
|
const value = String(code || '').trim();
|
||||||
const prefix = this.getFeeCategoryPrefix(feeCategory);
|
const prefix = this.getFeeCategoryPrefix(feeCategory);
|
||||||
|
|||||||
@@ -93,6 +93,24 @@
|
|||||||
<el-radio label="码头">码头</el-radio>
|
<el-radio label="码头">码头</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</template>
|
</template>
|
||||||
|
<template #provinceCode-form>
|
||||||
|
<el-select
|
||||||
|
v-model="form.provinceCode"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
:disabled="isProvinceDisabled"
|
||||||
|
placeholder="请选择"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleProvinceChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in provinceOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.title"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
<template #code-form>
|
<template #code-form>
|
||||||
<el-input
|
<el-input
|
||||||
v-if="form.category !== '码头'"
|
v-if="form.category !== '码头'"
|
||||||
@@ -300,6 +318,8 @@ export default {
|
|||||||
excelForm: {},
|
excelForm: {},
|
||||||
portOptions: [],
|
portOptions: [],
|
||||||
countryOptions: [],
|
countryOptions: [],
|
||||||
|
provinceOptions: [],
|
||||||
|
provinceOptionCache: {},
|
||||||
cityOptions: [],
|
cityOptions: [],
|
||||||
cityLoading: false,
|
cityLoading: false,
|
||||||
cityOptionCache: {},
|
cityOptionCache: {},
|
||||||
@@ -436,13 +456,30 @@ export default {
|
|||||||
change: ({ value }) => this.handleCountryNameChange(value),
|
change: ({ value }) => this.handleCountryNameChange(value),
|
||||||
rules: [{ required: true, message: '请选择国家', trigger: 'change' }],
|
rules: [{ required: true, message: '请选择国家', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '所属省份',
|
||||||
|
prop: 'provinceCode',
|
||||||
|
formslot: true,
|
||||||
|
hide: true,
|
||||||
|
span: 12,
|
||||||
|
order: 88,
|
||||||
|
placeholder: '请选择',
|
||||||
|
rules: [{ required: true, message: '请选择所属省份', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '所属省份',
|
||||||
|
prop: 'provinceName',
|
||||||
|
addDisplay: false,
|
||||||
|
editDisplay: false,
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '城市',
|
label: '城市',
|
||||||
prop: 'cityCode',
|
prop: 'cityCode',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
hide: true,
|
hide: true,
|
||||||
span: 12,
|
span: 12,
|
||||||
order: 88,
|
order: 87,
|
||||||
placeholder: '请选择',
|
placeholder: '请选择',
|
||||||
rules: [{ required: true, message: '请选择所属城市', trigger: 'change' }],
|
rules: [{ required: true, message: '请选择所属城市', trigger: 'change' }],
|
||||||
},
|
},
|
||||||
@@ -465,7 +502,7 @@ export default {
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
hide: true,
|
hide: true,
|
||||||
order: 87,
|
order: 86,
|
||||||
props: {
|
props: {
|
||||||
label: 'title',
|
label: 'title',
|
||||||
value: 'id',
|
value: 'id',
|
||||||
@@ -534,7 +571,7 @@ export default {
|
|||||||
span: 12,
|
span: 12,
|
||||||
minWidth: 220,
|
minWidth: 220,
|
||||||
overHidden: false,
|
overHidden: false,
|
||||||
order: 86,
|
order: 85,
|
||||||
placeholder: '请输入',
|
placeholder: '请输入',
|
||||||
maxlength: 255,
|
maxlength: 255,
|
||||||
showWordLimit: true,
|
showWordLimit: true,
|
||||||
@@ -667,6 +704,9 @@ export default {
|
|||||||
return this.form.category === '码头';
|
return this.form.category === '码头';
|
||||||
},
|
},
|
||||||
isCityDisabled() {
|
isCityDisabled() {
|
||||||
|
return this.isParentRegionLocked || !this.form.provinceCode;
|
||||||
|
},
|
||||||
|
isProvinceDisabled() {
|
||||||
return this.isParentRegionLocked || !this.form.countryCode;
|
return this.isParentRegionLocked || !this.form.countryCode;
|
||||||
},
|
},
|
||||||
isDistrictDisabled() {
|
isDistrictDisabled() {
|
||||||
@@ -755,7 +795,7 @@ export default {
|
|||||||
this.form.parentName = '';
|
this.form.parentName = '';
|
||||||
this.form.countryCode = '';
|
this.form.countryCode = '';
|
||||||
this.form.country = '';
|
this.form.country = '';
|
||||||
this.clearCityValue();
|
this.clearProvinceValue();
|
||||||
},
|
},
|
||||||
handleCategoryChange(value, reset = true) {
|
handleCategoryChange(value, reset = true) {
|
||||||
const required = value === '码头';
|
const required = value === '码头';
|
||||||
@@ -779,13 +819,15 @@ export default {
|
|||||||
handleCountryChange(value) {
|
handleCountryChange(value) {
|
||||||
const country = this.countryOptions.find(item => item.id === value);
|
const country = this.countryOptions.find(item => item.id === value);
|
||||||
this.form.country = country ? country.title : '';
|
this.form.country = country ? country.title : '';
|
||||||
this.clearCityValue();
|
this.clearProvinceValue();
|
||||||
this.loadCityOptions(value);
|
this.loadProvinceOptions(value);
|
||||||
},
|
},
|
||||||
handleCountryNameChange(value) {
|
handleCountryNameChange(value) {
|
||||||
const country = this.countryOptions.find(item => item.title === value);
|
const country = this.countryOptions.find(item => item.title === value);
|
||||||
|
this.setProvinceOptions([]);
|
||||||
|
this.setCityOptions([]);
|
||||||
this.setDistrictOptions([]);
|
this.setDistrictOptions([]);
|
||||||
this.loadCityOptions(country ? country.id : '');
|
this.loadProvinceOptions(country ? country.id : '');
|
||||||
},
|
},
|
||||||
syncCountryName(countryCode) {
|
syncCountryName(countryCode) {
|
||||||
const country = this.countryOptions.find(item => item.id === countryCode);
|
const country = this.countryOptions.find(item => item.id === countryCode);
|
||||||
@@ -818,6 +860,18 @@ export default {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setProvinceOptions(provinceOptions) {
|
||||||
|
this.provinceOptions = provinceOptions;
|
||||||
|
const provinceCodeColumn = this.findColumn(this.option.column, 'provinceCode');
|
||||||
|
if (provinceCodeColumn) {
|
||||||
|
provinceCodeColumn.dicData = provinceOptions;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearProvinceValue() {
|
||||||
|
this.form.provinceCode = undefined;
|
||||||
|
this.form.provinceName = '';
|
||||||
|
this.clearCityValue();
|
||||||
|
},
|
||||||
clearCityValue() {
|
clearCityValue() {
|
||||||
this.form.cityCode = undefined;
|
this.form.cityCode = undefined;
|
||||||
this.form.city = '';
|
this.form.city = '';
|
||||||
@@ -828,36 +882,38 @@ export default {
|
|||||||
this.form.districtName = '';
|
this.form.districtName = '';
|
||||||
this.form.regionCode = '';
|
this.form.regionCode = '';
|
||||||
},
|
},
|
||||||
loadCityOptions(countryCode) {
|
loadProvinceOptions(countryCode) {
|
||||||
if (!countryCode) {
|
if (!countryCode) {
|
||||||
|
this.setProvinceOptions([]);
|
||||||
|
return Promise.resolve([]);
|
||||||
|
}
|
||||||
|
if (this.provinceOptionCache[countryCode]) {
|
||||||
|
this.setProvinceOptions(this.provinceOptionCache[countryCode]);
|
||||||
|
return Promise.resolve(this.provinceOptionCache[countryCode]);
|
||||||
|
}
|
||||||
|
return getLazyTree(countryCode).then(res => {
|
||||||
|
const options = (res.data.data || []).map(this.normalizeRegionOption);
|
||||||
|
this.provinceOptionCache[countryCode] = options;
|
||||||
|
this.setProvinceOptions(options);
|
||||||
|
return options;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
loadCityOptions(provinceCode) {
|
||||||
|
if (!provinceCode) {
|
||||||
this.setCityOptions([]);
|
this.setCityOptions([]);
|
||||||
return Promise.resolve([]);
|
return Promise.resolve([]);
|
||||||
}
|
}
|
||||||
if (this.cityOptionCache[countryCode]) {
|
if (this.cityOptionCache[provinceCode]) {
|
||||||
this.setCityOptions(this.cityOptionCache[countryCode]);
|
this.setCityOptions(this.cityOptionCache[provinceCode]);
|
||||||
return Promise.resolve(this.cityOptionCache[countryCode]);
|
return Promise.resolve(this.cityOptionCache[provinceCode]);
|
||||||
}
|
}
|
||||||
this.cityLoading = true;
|
this.cityLoading = true;
|
||||||
return getLazyTree(countryCode)
|
return getLazyTree(provinceCode)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
const firstLevelList = (res.data.data || []).map(this.normalizeRegionOption);
|
const options = (res.data.data || []).map(this.normalizeRegionOption);
|
||||||
return Promise.all(
|
this.cityOptionCache[provinceCode] = options;
|
||||||
firstLevelList.map(parent => {
|
this.setCityOptions(options);
|
||||||
return getLazyTree(parent.id).then(childRes => {
|
return options;
|
||||||
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(() => {
|
.finally(() => {
|
||||||
this.cityLoading = false;
|
this.cityLoading = false;
|
||||||
@@ -867,6 +923,12 @@ export default {
|
|||||||
const city = this.cityOptions.find(item => item.title === cityName || item.id === regionCode);
|
const city = this.cityOptions.find(item => item.title === cityName || item.id === regionCode);
|
||||||
return city ? city.id : '';
|
return city ? city.id : '';
|
||||||
},
|
},
|
||||||
|
resolveProvinceCode(provinceName) {
|
||||||
|
const province = this.provinceOptions.find(
|
||||||
|
item => item.title === provinceName || item.id === provinceName
|
||||||
|
);
|
||||||
|
return province ? province.id : '';
|
||||||
|
},
|
||||||
setDistrictOptions(districtOptions) {
|
setDistrictOptions(districtOptions) {
|
||||||
this.districtOptions = districtOptions;
|
this.districtOptions = districtOptions;
|
||||||
const districtCodeColumn = this.findColumn(this.option.column, 'districtCode');
|
const districtCodeColumn = this.findColumn(this.option.column, 'districtCode');
|
||||||
@@ -927,6 +989,8 @@ export default {
|
|||||||
this.form.terminalCode = terminalCode;
|
this.form.terminalCode = terminalCode;
|
||||||
this.handleTerminalCodeChange(terminalCode);
|
this.handleTerminalCodeChange(terminalCode);
|
||||||
this.form.country = parent.country;
|
this.form.country = parent.country;
|
||||||
|
this.form.provinceCode = parent.provinceCode;
|
||||||
|
this.form.provinceName = parent.provinceName;
|
||||||
this.form.city = parent.city;
|
this.form.city = parent.city;
|
||||||
this.form.districtCode = parent.districtCode;
|
this.form.districtCode = parent.districtCode;
|
||||||
this.form.districtName = parent.districtName;
|
this.form.districtName = parent.districtName;
|
||||||
@@ -935,7 +999,12 @@ export default {
|
|||||||
.then(countryCode => {
|
.then(countryCode => {
|
||||||
this.form.countryCode = countryCode;
|
this.form.countryCode = countryCode;
|
||||||
this.syncCountryName(countryCode);
|
this.syncCountryName(countryCode);
|
||||||
return this.loadCityOptions(countryCode);
|
return this.loadProvinceOptions(countryCode);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.form.provinceCode =
|
||||||
|
String(parent.provinceCode || '') || this.resolveProvinceCode(parent.provinceName);
|
||||||
|
return this.loadCityOptions(this.form.provinceCode);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.form.cityCode = this.resolveCityCode(parent.city, parent.regionCode);
|
this.form.cityCode = this.resolveCityCode(parent.city, parent.regionCode);
|
||||||
@@ -952,6 +1021,12 @@ export default {
|
|||||||
this.clearDistrictValue();
|
this.clearDistrictValue();
|
||||||
this.loadDistrictOptions(value);
|
this.loadDistrictOptions(value);
|
||||||
},
|
},
|
||||||
|
handleProvinceChange(value) {
|
||||||
|
const province = this.provinceOptions.find(item => item.id === value);
|
||||||
|
this.form.provinceName = province ? province.title : '';
|
||||||
|
this.clearCityValue();
|
||||||
|
this.loadCityOptions(value);
|
||||||
|
},
|
||||||
handleCityNameChange(value) {
|
handleCityNameChange(value) {
|
||||||
const city = this.cityOptions.find(item => item.title === value);
|
const city = this.cityOptions.find(item => item.title === value);
|
||||||
this.setDistrictOptions([]);
|
this.setDistrictOptions([]);
|
||||||
@@ -988,6 +1063,8 @@ export default {
|
|||||||
submitRow.regionCode = String(submitRow.regionCode || '').trim();
|
submitRow.regionCode = String(submitRow.regionCode || '').trim();
|
||||||
submitRow.districtCode = String(submitRow.districtCode || '').trim();
|
submitRow.districtCode = String(submitRow.districtCode || '').trim();
|
||||||
submitRow.districtName = String(submitRow.districtName || '').trim();
|
submitRow.districtName = String(submitRow.districtName || '').trim();
|
||||||
|
submitRow.provinceCode = String(submitRow.provinceCode || '').trim();
|
||||||
|
submitRow.provinceName = String(submitRow.provinceName || '').trim();
|
||||||
submitRow.detailAddress = String(submitRow.detailAddress || '').trim();
|
submitRow.detailAddress = String(submitRow.detailAddress || '').trim();
|
||||||
submitRow.longitude = normalizeCoordinateInput(submitRow.longitude);
|
submitRow.longitude = normalizeCoordinateInput(submitRow.longitude);
|
||||||
submitRow.latitude = normalizeCoordinateInput(submitRow.latitude);
|
submitRow.latitude = normalizeCoordinateInput(submitRow.latitude);
|
||||||
@@ -1021,6 +1098,10 @@ export default {
|
|||||||
this.$message.warning('请选择上级港口');
|
this.$message.warning('请选择上级港口');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (isBlank(row.provinceCode)) {
|
||||||
|
this.$message.warning('请选择所属省份');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (isBlank(row.regionCode)) {
|
if (isBlank(row.regionCode)) {
|
||||||
this.$message.warning('请选择区县');
|
this.$message.warning('请选择区县');
|
||||||
return false;
|
return false;
|
||||||
@@ -1153,7 +1234,13 @@ export default {
|
|||||||
.then(countryCode => {
|
.then(countryCode => {
|
||||||
this.form.countryCode = countryCode;
|
this.form.countryCode = countryCode;
|
||||||
this.syncCountryName(countryCode);
|
this.syncCountryName(countryCode);
|
||||||
return this.loadCityOptions(countryCode);
|
return this.loadProvinceOptions(countryCode);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.form.provinceCode =
|
||||||
|
String(this.form.provinceCode || '') ||
|
||||||
|
this.resolveProvinceCode(this.form.provinceName);
|
||||||
|
return this.loadCityOptions(this.form.provinceCode);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.form.cityCode = this.resolveCityCode(this.form.city, this.form.regionCode);
|
this.form.cityCode = this.resolveCityCode(this.form.city, this.form.regionCode);
|
||||||
@@ -1179,7 +1266,13 @@ export default {
|
|||||||
.then(countryCode => {
|
.then(countryCode => {
|
||||||
this.form.countryCode = countryCode;
|
this.form.countryCode = countryCode;
|
||||||
this.syncCountryName(countryCode);
|
this.syncCountryName(countryCode);
|
||||||
return this.loadCityOptions(countryCode);
|
return this.loadProvinceOptions(countryCode);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.form.provinceCode =
|
||||||
|
String(this.form.provinceCode || '') ||
|
||||||
|
this.resolveProvinceCode(this.form.provinceName);
|
||||||
|
return this.loadCityOptions(this.form.provinceCode);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.form.cityCode = this.resolveCityCode(this.form.city, this.form.regionCode);
|
this.form.cityCode = this.resolveCityCode(this.form.city, this.form.regionCode);
|
||||||
@@ -1211,6 +1304,7 @@ export default {
|
|||||||
},
|
},
|
||||||
searchReset() {
|
searchReset() {
|
||||||
this.query = {};
|
this.query = {};
|
||||||
|
this.setProvinceOptions([]);
|
||||||
this.setCityOptions([]);
|
this.setCityOptions([]);
|
||||||
this.setDistrictOptions([]);
|
this.setDistrictOptions([]);
|
||||||
this.onLoad(this.page);
|
this.onLoad(this.page);
|
||||||
@@ -1251,14 +1345,10 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleImport() {
|
handleImport() {
|
||||||
openImportDialog(
|
openImportDialog(this, '港口码头主数据', () => {
|
||||||
this,
|
this.loadPortOptions();
|
||||||
'港口码头主数据',
|
this.onLoad(this.page, this.query);
|
||||||
() => {
|
});
|
||||||
this.loadPortOptions();
|
|
||||||
this.onLoad(this.page, this.query);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
handleExport() {
|
handleExport() {
|
||||||
this.$confirm('是否导出港口码头主数据?', '提示', {
|
this.$confirm('是否导出港口码头主数据?', '提示', {
|
||||||
@@ -1271,7 +1361,10 @@ export default {
|
|||||||
feedback: true,
|
feedback: true,
|
||||||
})
|
})
|
||||||
.then(res => {
|
.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(() => {
|
.finally(() => {
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
|
|||||||
@@ -411,9 +411,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['permission']),
|
...mapGetters(['permission']),
|
||||||
isCountryRegion() {
|
isCountryRegion() {
|
||||||
return (
|
return Number(this.regionForm.regionLevel) === 0;
|
||||||
Number(this.regionForm.regionLevel) === 0 || this.regionForm.parentCode === this.topCode
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
isProvinceRegion() {
|
isProvinceRegion() {
|
||||||
return Number(this.regionForm.regionLevel) === 1;
|
return Number(this.regionForm.regionLevel) === 1;
|
||||||
@@ -641,7 +639,7 @@ export default {
|
|||||||
() => {
|
() => {
|
||||||
this.initTree();
|
this.initTree();
|
||||||
},
|
},
|
||||||
{ timeout: 180000 }
|
{ timeout: 300000 }
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
syncImportAction() {
|
syncImportAction() {
|
||||||
|
|||||||
@@ -110,24 +110,24 @@
|
|||||||
|
|
||||||
<div class="freight-heading"><h3>运费信息</h3></div>
|
<div class="freight-heading"><h3>运费信息</h3></div>
|
||||||
<el-form :model="route" label-position="right" label-width="auto" class="dispatch-form freight-form">
|
<el-form :model="route" label-position="right" label-width="auto" class="dispatch-form freight-form">
|
||||||
<el-row v-for="(item, index) in route.freightItems" :key="item.sourceIndex" :gutter="16">
|
<el-row v-for="(group, index) in freightGroups(route)" :key="group.key" :gutter="16">
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item :label="`单价${index + 1}`">
|
<el-form-item :label="`单价${index + 1}`">
|
||||||
<el-input :model-value="item.unitPrice" inputmode="decimal" placeholder="请输入" @input="value => handleFreightUnitPriceInput(item, value)">
|
<el-input :model-value="freightGroupUnitPrice(group)" inputmode="decimal" placeholder="请输入" @input="value => handleFreightGroupUnitPriceInput(group, value)" @clear="() => handleFreightGroupUnitPriceInput(group, '')">
|
||||||
<template #append><el-select v-model="item.priceUnit" class="freight-unit-select"><el-option label="元/吨" value="元/吨" /><el-option label="元/件" value="元/件" /><el-option label="元/方" value="元/方" /></el-select></template>
|
<template #append><el-select :model-value="freightGroupPriceUnit(group)" class="freight-unit-select" @change="value => handleFreightGroupPriceUnitChange(group, value)"><el-option label="元/吨" value="元/吨" /><el-option label="元/件" value="元/件" /><el-option label="元/方" value="元/方" /></el-select></template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item :label="`数量${index + 1}`">
|
<el-form-item :label="`数量${index + 1}`">
|
||||||
<el-input :model-value="formatQuantity(item.quantity)" readonly>
|
<el-input :model-value="formatQuantity(freightGroupQuantity(group))" readonly>
|
||||||
<template #append><el-select v-model="item.quantityUnit" class="freight-unit-select" @change="value => handleFreightQuantityUnitChange(route, item, value)"><el-option v-for="unit in quantityUnitOptions" :key="unit" :label="unit" :value="unit" /></el-select></template>
|
<template #append><el-select :model-value="group.quantityUnit" class="freight-unit-select" @change="value => handleFreightGroupQuantityUnitChange(route, group, value)"><el-option v-for="unit in quantityUnitOptions" :key="unit" :label="unit" :value="unit" /></el-select></template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item :label="`运费${index + 1}`">
|
<el-form-item :label="`运费${index + 1}`">
|
||||||
<el-input :model-value="formatAmount(freightAmount(item))" readonly><template #suffix>{{ currencyLabel(route.currency) }}</template></el-input>
|
<el-input :model-value="formatAmount(freightGroupAmount(group))" readonly><template #suffix>{{ currencyLabel(route.currency) }}</template></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@@ -360,6 +360,42 @@ export default {
|
|||||||
formatAmount(value) { return Number(value || 0).toFixed(2); },
|
formatAmount(value) { return Number(value || 0).toFixed(2); },
|
||||||
dispatchWeight(route) { return (route.goods || []).reduce((sum, item) => sum + Number(item.dispatchQuantity || 0), 0); },
|
dispatchWeight(route) { return (route.goods || []).reduce((sum, item) => sum + Number(item.dispatchQuantity || 0), 0); },
|
||||||
freightAmount(item = {}) { return Number(item.unitPrice || 0) * Number(item.quantity || 0); },
|
freightAmount(item = {}) { return Number(item.unitPrice || 0) * Number(item.quantity || 0); },
|
||||||
|
freightGroups(route = {}) {
|
||||||
|
const groups = [];
|
||||||
|
const groupMap = new Map();
|
||||||
|
(route.freightItems || []).forEach((item, index) => {
|
||||||
|
const quantityUnit = String(item.quantityUnit || '').trim();
|
||||||
|
const key = quantityUnit || `__empty_${index}`;
|
||||||
|
let group = groupMap.get(key);
|
||||||
|
if (!group) {
|
||||||
|
group = { key, quantityUnit, rows: [] };
|
||||||
|
groupMap.set(key, group);
|
||||||
|
groups.push(group);
|
||||||
|
}
|
||||||
|
group.rows.push(item);
|
||||||
|
});
|
||||||
|
return groups;
|
||||||
|
},
|
||||||
|
freightGroupQuantity(group = {}) { return (group.rows || []).reduce((sum, item) => sum + Number(item.quantity || 0), 0); },
|
||||||
|
freightGroupUnitPrice(group = {}) {
|
||||||
|
const prices = (group.rows || []).map(item => String(item.unitPrice ?? '').trim()).filter(Boolean);
|
||||||
|
return !prices.length || prices.some(price => price !== prices[0]) ? '' : prices[0];
|
||||||
|
},
|
||||||
|
freightGroupPriceUnit(group = {}) { return group.rows?.[0]?.priceUnit || (group.quantityUnit ? `元/${group.quantityUnit}` : ''); },
|
||||||
|
freightGroupAmount(group = {}) { return (group.rows || []).reduce((sum, item) => sum + this.freightAmount(item), 0); },
|
||||||
|
handleFreightGroupUnitPriceInput(group, value) {
|
||||||
|
const [integer = '', decimal = ''] = String(value || '').replace(/[^\d.]/g, '').split('.');
|
||||||
|
const normalized = decimal || String(value || '').includes('.') ? `${integer}.${decimal.slice(0, 2)}` : integer;
|
||||||
|
(group.rows || []).forEach(item => { item.unitPrice = normalized; });
|
||||||
|
},
|
||||||
|
handleFreightGroupPriceUnitChange(group, value) { (group.rows || []).forEach(item => { item.priceUnit = value || ''; }); },
|
||||||
|
handleFreightGroupQuantityUnitChange(route, group, value) {
|
||||||
|
(group.rows || []).forEach(item => {
|
||||||
|
item.quantityUnit = value || '';
|
||||||
|
const goods = (route.goods || []).find(row => String(row.sourceIndex) === String(item.sourceIndex));
|
||||||
|
if (goods) goods.quantityUnit = value || '';
|
||||||
|
});
|
||||||
|
},
|
||||||
freightTotal(route) {
|
freightTotal(route) {
|
||||||
const goodsFreight = (route.freightItems || []).reduce(
|
const goodsFreight = (route.freightItems || []).reduce(
|
||||||
(sum, item) => sum + this.freightAmount(item),
|
(sum, item) => sum + this.freightAmount(item),
|
||||||
|
|||||||
@@ -1708,18 +1708,20 @@
|
|||||||
<div
|
<div
|
||||||
class="transport-plan-page__dispatch-item-grid transport-plan-page__dispatch-item-grid--full"
|
class="transport-plan-page__dispatch-item-grid transport-plan-page__dispatch-item-grid--full"
|
||||||
>
|
>
|
||||||
<template v-for="(cargo, index) in dispatchItemCargoRows" :key="cargo._key || index">
|
<template v-for="(group, index) in dispatchItemFreightGroups" :key="group.key">
|
||||||
<el-form-item :label="`单价${index + 1}`">
|
<el-form-item :label="`单价${index + 1}`">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="cargo.unitPrice"
|
:model-value="dispatchFreightGroupUnitPrice(group)"
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
@input="value => handleDispatchCargoNumberInput(cargo, 'unitPrice', value)"
|
@input="value => handleDispatchFreightGroupNumberInput(group, value)"
|
||||||
|
@clear="() => handleDispatchFreightGroupNumberInput(group, '')"
|
||||||
>
|
>
|
||||||
<template #append
|
<template #append
|
||||||
><el-select
|
><el-select
|
||||||
v-model="cargo.priceUnit"
|
:model-value="dispatchFreightGroupPriceUnit(group)"
|
||||||
class="transport-plan-page__dispatch-unit-select"
|
class="transport-plan-page__dispatch-unit-select"
|
||||||
placeholder="元/吨"
|
placeholder="元/吨"
|
||||||
|
@change="value => handleDispatchFreightGroupPriceUnitChange(group, value)"
|
||||||
@visible-change="visible => visible && loadTaskFeeUnitOptions()"
|
@visible-change="visible => visible && loadTaskFeeUnitOptions()"
|
||||||
><el-option
|
><el-option
|
||||||
v-for="item in taskFeeUnitOptions"
|
v-for="item in taskFeeUnitOptions"
|
||||||
@@ -1730,12 +1732,12 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="`数量合计${index + 1}`"
|
<el-form-item :label="`数量合计${index + 1}`"
|
||||||
><el-input :model-value="formatDispatchQuantity(cargo.quantity)" disabled
|
><el-input :model-value="dispatchFreightGroupQuantity(group)" disabled
|
||||||
><template #append>{{ cargo.quantityUnit || '吨' }}</template></el-input
|
><template #append>{{ group.quantityUnit || '吨' }}</template></el-input
|
||||||
></el-form-item
|
></el-form-item
|
||||||
>
|
>
|
||||||
<el-form-item :label="`运费${index + 1}`"
|
<el-form-item :label="`运费${index + 1}`"
|
||||||
><el-input :model-value="dispatchCargoFreightAmount(cargo)" disabled
|
><el-input :model-value="dispatchFreightGroupAmount(group)" disabled
|
||||||
><template #suffix>{{ dispatchItemFreightCurrencyLabel }}</template></el-input
|
><template #suffix>{{ dispatchItemFreightCurrencyLabel }}</template></el-input
|
||||||
></el-form-item
|
></el-form-item
|
||||||
>
|
>
|
||||||
@@ -1786,8 +1788,22 @@
|
|||||||
:key="
|
:key="
|
||||||
item.id || item.customerName || item.carrierName || item.fullName || item.name
|
item.id || item.customerName || item.carrierName || item.fullName || item.name
|
||||||
"
|
"
|
||||||
:label="item.label || item.customerName || item.carrierName || item.fullName || item.name"
|
:label="
|
||||||
:value="dispatchIsCarrierMode ? item.carrierContractId : item.value || item.customerName || item.carrierName || item.fullName || item.name"
|
item.label ||
|
||||||
|
item.customerName ||
|
||||||
|
item.carrierName ||
|
||||||
|
item.fullName ||
|
||||||
|
item.name
|
||||||
|
"
|
||||||
|
:value="
|
||||||
|
dispatchIsCarrierMode
|
||||||
|
? item.carrierContractId
|
||||||
|
: item.value ||
|
||||||
|
item.customerName ||
|
||||||
|
item.carrierName ||
|
||||||
|
item.fullName ||
|
||||||
|
item.name
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -1998,8 +2014,18 @@
|
|||||||
:key="
|
:key="
|
||||||
item.id || item.customerName || item.carrierName || item.fullName || item.name
|
item.id || item.customerName || item.carrierName || item.fullName || item.name
|
||||||
"
|
"
|
||||||
:label="item.label || item.customerName || item.carrierName || item.fullName || item.name"
|
:label="
|
||||||
:value="dispatchIsCarrierMode ? item.carrierContractId : item.value || item.customerName || item.carrierName || item.fullName || item.name"
|
item.label || item.customerName || item.carrierName || item.fullName || item.name
|
||||||
|
"
|
||||||
|
:value="
|
||||||
|
dispatchIsCarrierMode
|
||||||
|
? item.carrierContractId
|
||||||
|
: item.value ||
|
||||||
|
item.customerName ||
|
||||||
|
item.carrierName ||
|
||||||
|
item.fullName ||
|
||||||
|
item.name
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -3448,8 +3474,8 @@ export default {
|
|||||||
return Number.isInteger(total) ? String(total) : String(Number(total.toFixed(2)));
|
return Number.isInteger(total) ? String(total) : String(Number(total.toFixed(2)));
|
||||||
}
|
}
|
||||||
const otherFeeTotal = Number(this.dispatchItemForm.otherFeeTotal || 0);
|
const otherFeeTotal = Number(this.dispatchItemForm.otherFeeTotal || 0);
|
||||||
const freightTotal = this.dispatchItemCargoRows.reduce(
|
const freightTotal = this.dispatchItemFreightGroups.reduce(
|
||||||
(total, cargo) => total + Number(this.dispatchCargoFreightAmount(cargo) || 0),
|
(total, group) => total + Number(this.dispatchFreightGroupAmount(group) || 0),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const hasOtherFee = this.dispatchItemForm.otherFeeTotal !== '';
|
const hasOtherFee = this.dispatchItemForm.otherFeeTotal !== '';
|
||||||
@@ -3465,8 +3491,8 @@ export default {
|
|||||||
const total = quantity * unitPrice;
|
const total = quantity * unitPrice;
|
||||||
return Number.isInteger(total) ? String(total) : String(Number(total.toFixed(2)));
|
return Number.isInteger(total) ? String(total) : String(Number(total.toFixed(2)));
|
||||||
}
|
}
|
||||||
const total = this.dispatchItemCargoRows.reduce(
|
const total = this.dispatchItemFreightGroups.reduce(
|
||||||
(sum, cargo) => sum + Number(this.dispatchCargoFreightAmount(cargo) || 0),
|
(sum, group) => sum + Number(this.dispatchFreightGroupAmount(group) || 0),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
return total
|
return total
|
||||||
@@ -3475,6 +3501,22 @@ export default {
|
|||||||
: String(Number(total.toFixed(2)))
|
: String(Number(total.toFixed(2)))
|
||||||
: '';
|
: '';
|
||||||
},
|
},
|
||||||
|
dispatchItemFreightGroups() {
|
||||||
|
const groups = [];
|
||||||
|
const groupMap = new Map();
|
||||||
|
(this.dispatchItemCargoRows || []).forEach((cargo, index) => {
|
||||||
|
const quantityUnit = String(cargo.quantityUnit || '').trim();
|
||||||
|
const key = quantityUnit || `__empty_${index}`;
|
||||||
|
let group = groupMap.get(key);
|
||||||
|
if (!group) {
|
||||||
|
group = { key, quantityUnit, rows: [] };
|
||||||
|
groupMap.set(key, group);
|
||||||
|
groups.push(group);
|
||||||
|
}
|
||||||
|
group.rows.push(cargo);
|
||||||
|
});
|
||||||
|
return groups;
|
||||||
|
},
|
||||||
dispatchItemFreightCurrencyLabel() {
|
dispatchItemFreightCurrencyLabel() {
|
||||||
const value = this.dispatchItemForm.freightCurrency || 'RMB';
|
const value = this.dispatchItemForm.freightCurrency || 'RMB';
|
||||||
return this.currencyRemark(value);
|
return this.currencyRemark(value);
|
||||||
@@ -7321,7 +7363,8 @@ export default {
|
|||||||
if (carrierTypeAtRequest === '承运商') {
|
if (carrierTypeAtRequest === '承运商') {
|
||||||
this.dispatchCarrierOptions = carrierContracts || [];
|
this.dispatchCarrierOptions = carrierContracts || [];
|
||||||
const current = this.dispatchCarrierOptions.find(
|
const current = this.dispatchCarrierOptions.find(
|
||||||
item => String(item.carrierContractId) === String(this.dispatchItemForm.carrierContractId)
|
item =>
|
||||||
|
String(item.carrierContractId) === String(this.dispatchItemForm.carrierContractId)
|
||||||
);
|
);
|
||||||
if (current) {
|
if (current) {
|
||||||
this.dispatchItemForm.carrierName = current.carrierName;
|
this.dispatchItemForm.carrierName = current.carrierName;
|
||||||
@@ -7446,13 +7489,47 @@ export default {
|
|||||||
const amount = quantity * unitPrice;
|
const amount = quantity * unitPrice;
|
||||||
return Number.isInteger(amount) ? String(amount) : String(Number(amount.toFixed(2)));
|
return Number.isInteger(amount) ? String(amount) : String(Number(amount.toFixed(2)));
|
||||||
},
|
},
|
||||||
|
dispatchFreightGroupQuantity(group = {}) {
|
||||||
|
const quantity = (group.rows || []).reduce(
|
||||||
|
(sum, cargo) => sum + Number(cargo.quantity || 0),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
return this.formatDispatchQuantity(quantity);
|
||||||
|
},
|
||||||
|
dispatchFreightGroupUnitPrice(group = {}) {
|
||||||
|
const prices = (group.rows || [])
|
||||||
|
.map(cargo => String(cargo.unitPrice ?? '').trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
if (!prices.length || prices.some(price => price !== prices[0])) return '';
|
||||||
|
return prices[0];
|
||||||
|
},
|
||||||
|
dispatchFreightGroupPriceUnit(group = {}) {
|
||||||
|
return group.rows?.[0]?.priceUnit || (group.quantityUnit ? `元/${group.quantityUnit}` : '');
|
||||||
|
},
|
||||||
|
dispatchFreightGroupAmount(group = {}) {
|
||||||
|
const amount = (group.rows || []).reduce(
|
||||||
|
(sum, cargo) => sum + Number(this.dispatchCargoFreightAmount(cargo) || 0),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
return Number.isInteger(amount) ? String(amount) : String(Number(amount.toFixed(2)));
|
||||||
|
},
|
||||||
|
handleDispatchFreightGroupNumberInput(group, value) {
|
||||||
|
this.handleFreightNumberInput(group.rows?.[0] || {}, 'unitPrice', value);
|
||||||
|
const unitPrice = group.rows?.[0]?.unitPrice || '';
|
||||||
|
(group.rows || []).forEach(cargo => {
|
||||||
|
cargo.unitPrice = unitPrice;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleDispatchFreightGroupPriceUnitChange(group, value) {
|
||||||
|
(group.rows || []).forEach(cargo => {
|
||||||
|
cargo.priceUnit = value || '';
|
||||||
|
});
|
||||||
|
},
|
||||||
dispatchItemRemainingQuantity(row = {}) {
|
dispatchItemRemainingQuantity(row = {}) {
|
||||||
const unit = this.getDispatchQuantityUnit(row);
|
const unit = this.getDispatchQuantityUnit(row);
|
||||||
const hasCargoIdentity = Boolean(
|
const hasCargoIdentity = Boolean(
|
||||||
String(row.cargoName || row.goodsName || row.name || '').trim() ||
|
String(row.cargoName || row.goodsName || row.name || '').trim() ||
|
||||||
String(
|
String(row.cargoType || row.secondCargoTypeName || row.goodsType || row.type || '').trim()
|
||||||
row.cargoType || row.secondCargoTypeName || row.goodsType || row.type || ''
|
|
||||||
).trim()
|
|
||||||
);
|
);
|
||||||
const planGoodsRows = this.dispatchPlanGoodsRows;
|
const planGoodsRows = this.dispatchPlanGoodsRows;
|
||||||
const cargoKey = this.getDispatchCargoIdentity(row);
|
const cargoKey = this.getDispatchCargoIdentity(row);
|
||||||
@@ -7472,10 +7549,7 @@ export default {
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
const assigned = this.dispatchRows.reduce((sum, dispatchRow, index) => {
|
const assigned = this.dispatchRows.reduce((sum, dispatchRow, index) => {
|
||||||
if (
|
if (index === this.dispatchItemIndex || !this.hasDispatchVehicleIdentifier(dispatchRow)) {
|
||||||
index === this.dispatchItemIndex ||
|
|
||||||
!this.hasDispatchVehicleIdentifier(dispatchRow)
|
|
||||||
) {
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1041,21 +1041,25 @@
|
|||||||
label-width="auto"
|
label-width="auto"
|
||||||
class="waybill-manage-page__freight-form waybill-manage-page__freight-form--road"
|
class="waybill-manage-page__freight-form waybill-manage-page__freight-form--road"
|
||||||
>
|
>
|
||||||
<template v-for="(cargo, index) in transportCargoRows" :key="index">
|
<template v-for="(group, index) in taskFreightGroups" :key="group.key">
|
||||||
<el-form-item :label="`单价${index + 1}`">
|
<el-form-item :label="`单价${index + 1}`">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="cargo.unitPrice"
|
:model-value="taskFullFreightGroupUnitPrice(group)"
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
clearable
|
clearable
|
||||||
:disabled="dialogReadonly"
|
:disabled="dialogReadonly"
|
||||||
@input="value => handleTaskFullFreightNumberInput(cargo, 'unitPrice', value)"
|
@input="
|
||||||
|
value => handleTaskFullFreightGroupNumberInput(group, 'unitPrice', value)
|
||||||
|
"
|
||||||
|
@clear="() => handleTaskFullFreightGroupNumberInput(group, 'unitPrice', '')"
|
||||||
>
|
>
|
||||||
<template #append>
|
<template #append>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="cargo.priceUnit"
|
:model-value="taskFullFreightGroupPriceUnit(group)"
|
||||||
class="waybill-manage-page__append-select waybill-manage-page__append-select--wide"
|
class="waybill-manage-page__append-select waybill-manage-page__append-select--wide"
|
||||||
placeholder="单位"
|
placeholder="单位"
|
||||||
:disabled="dialogReadonly"
|
:disabled="dialogReadonly"
|
||||||
|
@change="value => handleTaskFullFreightGroupPriceUnitChange(group, value)"
|
||||||
@visible-change="visible => visible && loadTaskFeeUnitOptions()"
|
@visible-change="visible => visible && loadTaskFeeUnitOptions()"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
@@ -1069,17 +1073,17 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="`数量合计${index + 1}`">
|
<el-form-item :label="`数量合计${index + 1}`">
|
||||||
<el-input :model-value="taskFullFreightQuantity(index)" disabled>
|
<el-input :model-value="taskFullFreightGroupQuantity(group)" disabled>
|
||||||
<template #append>
|
<template #append>
|
||||||
<el-select
|
<el-select
|
||||||
:model-value="cargo.quantityUnit"
|
:model-value="group.quantityUnit"
|
||||||
class="waybill-manage-page__append-select waybill-manage-page__append-select--wide"
|
class="waybill-manage-page__append-select waybill-manage-page__append-select--wide"
|
||||||
placeholder="单位"
|
placeholder="单位"
|
||||||
disabled
|
disabled
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
:label="cargo.quantityUnit || '单位'"
|
:label="group.quantityUnit || '单位'"
|
||||||
:value="cargo.quantityUnit || ''"
|
:value="group.quantityUnit || ''"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
@@ -1087,10 +1091,11 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="`运费${index + 1}`">
|
<el-form-item :label="`运费${index + 1}`">
|
||||||
<el-input
|
<el-input
|
||||||
:model-value="taskFullFreightAmount(cargo)"
|
:model-value="taskFullFreightGroupAmount(group)"
|
||||||
placeholder="请输入运费"
|
placeholder="请输入运费"
|
||||||
:disabled="dialogReadonly"
|
:disabled="dialogReadonly"
|
||||||
@input="value => handleTaskFullFreightAmountInput(cargo, value)"
|
@input="value => handleTaskFullFreightGroupAmountInput(group, value)"
|
||||||
|
@clear="() => handleTaskFullFreightGroupAmountInput(group, '')"
|
||||||
>
|
>
|
||||||
<template #suffix>{{ taskFreightCurrencyLabel }}</template>
|
<template #suffix>{{ taskFreightCurrencyLabel }}</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
@@ -1520,11 +1525,7 @@
|
|||||||
<span>
|
<span>
|
||||||
运费合计:<strong>¥{{ formatFooterFreightTotal }}</strong>
|
运费合计:<strong>¥{{ formatFooterFreightTotal }}</strong>
|
||||||
</span>
|
</span>
|
||||||
<el-link
|
<el-link v-if="hasProjectProcessConfig" type="primary" @click="openWaybillProcessConfig">
|
||||||
v-if="hasProjectProcessConfig"
|
|
||||||
type="primary"
|
|
||||||
@click="openWaybillProcessConfig"
|
|
||||||
>
|
|
||||||
查看过程配置
|
查看过程配置
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
@@ -3362,9 +3363,25 @@ export default {
|
|||||||
const amount = quantity * unitPrice;
|
const amount = quantity * unitPrice;
|
||||||
return Number.isInteger(amount) ? String(amount) : String(Number(amount.toFixed(2)));
|
return Number.isInteger(amount) ? String(amount) : String(Number(amount.toFixed(2)));
|
||||||
},
|
},
|
||||||
|
taskFreightGroups() {
|
||||||
|
const groups = [];
|
||||||
|
const groupMap = new Map();
|
||||||
|
(this.transportCargoRows || []).forEach((cargo, index) => {
|
||||||
|
const quantityUnit = String(cargo.quantityUnit || '').trim();
|
||||||
|
const key = quantityUnit || `__empty_${index}`;
|
||||||
|
let group = groupMap.get(key);
|
||||||
|
if (!group) {
|
||||||
|
group = { key, quantityUnit, rows: [] };
|
||||||
|
groupMap.set(key, group);
|
||||||
|
groups.push(group);
|
||||||
|
}
|
||||||
|
group.rows.push(cargo);
|
||||||
|
});
|
||||||
|
return groups;
|
||||||
|
},
|
||||||
taskFullFreightTotal() {
|
taskFullFreightTotal() {
|
||||||
const total = this.transportCargoRows.reduce(
|
const total = this.taskFreightGroups.reduce(
|
||||||
(sum, cargo) => sum + Number(this.taskFullFreightAmount(cargo) || 0),
|
(sum, group) => sum + Number(this.taskFullFreightGroupAmount(group) || 0),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
return this.formatTaskFullFreightNumber(total);
|
return this.formatTaskFullFreightNumber(total);
|
||||||
@@ -3852,7 +3869,8 @@ export default {
|
|||||||
fillCustomerNameFromProject(projectId = this.form.projectId) {
|
fillCustomerNameFromProject(projectId = this.form.projectId) {
|
||||||
if (this.form.customerName || !projectId) return Promise.resolve(this.form.customerName);
|
if (this.form.customerName || !projectId) return Promise.resolve(this.form.customerName);
|
||||||
const project = this.projectOptions.find(item => String(item.id) === String(projectId));
|
const project = this.projectOptions.find(item => String(item.id) === String(projectId));
|
||||||
const customerName = project?.customerNames || project?.customerName || project?.customer || '';
|
const customerName =
|
||||||
|
project?.customerNames || project?.customerName || project?.customer || '';
|
||||||
if (customerName) {
|
if (customerName) {
|
||||||
this.form.customerName = customerName;
|
this.form.customerName = customerName;
|
||||||
return Promise.resolve(customerName);
|
return Promise.resolve(customerName);
|
||||||
@@ -5253,6 +5271,69 @@ export default {
|
|||||||
Number(cargo.unitPrice || 0) * Number(cargo.quantity || 0)
|
Number(cargo.unitPrice || 0) * Number(cargo.quantity || 0)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
taskFullFreightGroupQuantity(group = {}) {
|
||||||
|
const total = (group.rows || []).reduce((sum, cargo) => sum + Number(cargo.quantity || 0), 0);
|
||||||
|
return this.formatTaskFullFreightNumber(total);
|
||||||
|
},
|
||||||
|
taskFullFreightGroupUnitPrice(group = {}) {
|
||||||
|
const prices = (group.rows || [])
|
||||||
|
.map(cargo => String(cargo.unitPrice ?? '').trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
if (!prices.length || prices.some(price => price !== prices[0])) return '';
|
||||||
|
return prices[0];
|
||||||
|
},
|
||||||
|
taskFullFreightGroupPriceUnit(group = {}) {
|
||||||
|
return group.rows?.[0]?.priceUnit || (group.quantityUnit ? `元/${group.quantityUnit}` : '');
|
||||||
|
},
|
||||||
|
taskFullFreightGroupAmount(group = {}) {
|
||||||
|
const total = (group.rows || []).reduce(
|
||||||
|
(sum, cargo) => sum + Number(this.taskFullFreightAmount(cargo) || 0),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
return this.formatTaskFullFreightNumber(total);
|
||||||
|
},
|
||||||
|
handleTaskFullFreightGroupNumberInput(group, prop, value) {
|
||||||
|
const text = String(value || '').replace(/[^\d.]/g, '');
|
||||||
|
const parts = text.split('.');
|
||||||
|
const normalized =
|
||||||
|
parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 2)}` : parts[0];
|
||||||
|
(group.rows || []).forEach(cargo => {
|
||||||
|
cargo[prop] = normalized;
|
||||||
|
});
|
||||||
|
this.syncTransportCargoJson();
|
||||||
|
},
|
||||||
|
handleTaskFullFreightGroupPriceUnitChange(group, value) {
|
||||||
|
(group.rows || []).forEach(cargo => {
|
||||||
|
cargo.priceUnit = value || '';
|
||||||
|
});
|
||||||
|
this.syncTransportCargoJson();
|
||||||
|
},
|
||||||
|
handleTaskFullFreightGroupAmountInput(group, value) {
|
||||||
|
const text = String(value || '').replace(/[^\d.]/g, '');
|
||||||
|
const parts = text.split('.');
|
||||||
|
const normalized =
|
||||||
|
parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 2)}` : parts[0];
|
||||||
|
const rows = group.rows || [];
|
||||||
|
const total = Number(normalized || 0);
|
||||||
|
const quantities = rows.map(cargo => Math.max(0, Number(cargo.quantity || 0)));
|
||||||
|
const quantityTotal = quantities.reduce((sum, quantity) => sum + quantity, 0);
|
||||||
|
let allocated = 0;
|
||||||
|
rows.forEach((cargo, index) => {
|
||||||
|
if (index === rows.length - 1) {
|
||||||
|
cargo.freightAmount = this.formatTaskFullFreightNumber(total - allocated);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let amount = 0;
|
||||||
|
if (quantityTotal) {
|
||||||
|
amount = Number((total * (quantities[index] / quantityTotal)).toFixed(2));
|
||||||
|
} else if (index === 0) {
|
||||||
|
amount = total;
|
||||||
|
}
|
||||||
|
allocated += amount;
|
||||||
|
cargo.freightAmount = this.formatTaskFullFreightNumber(amount);
|
||||||
|
});
|
||||||
|
this.syncTransportCargoJson();
|
||||||
|
},
|
||||||
formatTaskFullFreightNumber(value) {
|
formatTaskFullFreightNumber(value) {
|
||||||
if (value === undefined || value === null || String(value).trim() === '') return '';
|
if (value === undefined || value === null || String(value).trim() === '') return '';
|
||||||
const number = Number(value || 0);
|
const number = Number(value || 0);
|
||||||
|
|||||||
@@ -438,20 +438,16 @@
|
|||||||
class="settlement-detail-page__dialog-form"
|
class="settlement-detail-page__dialog-form"
|
||||||
>
|
>
|
||||||
<el-form-item label="更新范围" prop="contractId">
|
<el-form-item label="更新范围" prop="contractId">
|
||||||
<el-select
|
<el-input
|
||||||
v-model="updateFeeForm.contractId"
|
:model-value="updateContractName"
|
||||||
clearable
|
class="settlement-detail-page__generate-select"
|
||||||
filterable
|
readonly
|
||||||
placeholder="请选择合同"
|
placeholder="请选择合同"
|
||||||
@change="handleUpdateContractChange"
|
|
||||||
>
|
>
|
||||||
<el-option
|
<template #append>
|
||||||
v-for="item in updateContractOptions"
|
<el-button @click="openUpdateContractDialog">选择</el-button>
|
||||||
:key="item.id"
|
</template>
|
||||||
:label="item.contractName"
|
</el-input>
|
||||||
:value="item.id"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="合同计费方案" prop="billingPlanId">
|
<el-form-item label="合同计费方案" prop="billingPlanId">
|
||||||
<el-select
|
<el-select
|
||||||
@@ -817,35 +813,112 @@
|
|||||||
ref="generateContractTable"
|
ref="generateContractTable"
|
||||||
v-loading="generateContractDialog.loading"
|
v-loading="generateContractDialog.loading"
|
||||||
:data="generateContractDialog.rows"
|
:data="generateContractDialog.rows"
|
||||||
|
style="width: 100%"
|
||||||
border
|
border
|
||||||
highlight-current-row
|
highlight-current-row
|
||||||
@current-change="generateContractDialog.current = $event"
|
@current-change="generateContractDialog.current = $event"
|
||||||
@row-dblclick="selectGenerateContract"
|
@row-dblclick="selectContract"
|
||||||
>
|
>
|
||||||
<el-table-column type="index" label="序号" width="64" align="center" />
|
<el-table-column type="index" label="序号" width="64" align="center" />
|
||||||
<el-table-column
|
<el-table-column
|
||||||
v-for="column in contractSelectionColumns"
|
prop="contractNo"
|
||||||
:key="column.prop"
|
label="合同编号"
|
||||||
:prop="column.prop"
|
min-width="180"
|
||||||
:label="column.label"
|
|
||||||
:min-width="column.minWidth"
|
|
||||||
align="center"
|
align="center"
|
||||||
show-overflow-tooltip
|
show-overflow-tooltip
|
||||||
>
|
:formatter="formatContractSelectionCell"
|
||||||
<template #default="{ row }">
|
/>
|
||||||
<span v-if="column.prop === 'organizationName'">{{
|
<el-table-column
|
||||||
row.organizationName || row.deptName || '-'
|
prop="contractName"
|
||||||
}}</span>
|
label="合同名称"
|
||||||
<span v-else-if="column.prop === 'contractCategory'">{{
|
min-width="220"
|
||||||
contractCategoryName(row.contractCategory)
|
align="center"
|
||||||
}}</span>
|
show-overflow-tooltip
|
||||||
<span v-else-if="column.prop === 'signType'">{{ signTypeName(row.signType) }}</span>
|
:formatter="formatContractSelectionCell"
|
||||||
<span v-else>{{ displayValue(row[column.prop]) }}</span>
|
/>
|
||||||
</template>
|
<el-table-column
|
||||||
</el-table-column>
|
prop="projectName"
|
||||||
|
label="所属项目"
|
||||||
|
min-width="170"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
:formatter="formatContractSelectionCell"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="organizationName"
|
||||||
|
label="所属组织"
|
||||||
|
min-width="170"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
:formatter="formatContractSelectionCell"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="contractCategory"
|
||||||
|
label="合同类别"
|
||||||
|
min-width="130"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
:formatter="formatContractSelectionCell"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="signType"
|
||||||
|
label="签约类型"
|
||||||
|
min-width="120"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
:formatter="formatContractSelectionCell"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="partyA"
|
||||||
|
label="甲方"
|
||||||
|
min-width="170"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
:formatter="formatContractSelectionCell"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="partyB"
|
||||||
|
label="乙方"
|
||||||
|
min-width="170"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
:formatter="formatContractSelectionCell"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="startDate"
|
||||||
|
label="开始日期"
|
||||||
|
min-width="130"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
:formatter="formatContractSelectionCell"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="endDate"
|
||||||
|
label="结束日期"
|
||||||
|
min-width="130"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
:formatter="formatContractSelectionCell"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="temporaryStartDate"
|
||||||
|
label="临时效力起"
|
||||||
|
min-width="130"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
:formatter="formatContractSelectionCell"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="temporaryEndDate"
|
||||||
|
label="临时效力止"
|
||||||
|
min-width="130"
|
||||||
|
align="center"
|
||||||
|
show-overflow-tooltip
|
||||||
|
:formatter="formatContractSelectionCell"
|
||||||
|
/>
|
||||||
<el-table-column label="操作" width="90" fixed="right" align="center">
|
<el-table-column label="操作" width="90" fixed="right" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-link type="primary" @click.stop="selectGenerateContract(row)">选择</el-link>
|
<el-link type="primary" @click.stop="selectContract(row)">选择</el-link>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -862,7 +935,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="generateContractDialog.visible = false">取消</el-button>
|
<el-button @click="generateContractDialog.visible = false">取消</el-button>
|
||||||
<el-button type="primary" @click="selectGenerateContract(generateContractDialog.current)">
|
<el-button type="primary" @click="selectContract(generateContractDialog.current)">
|
||||||
确定
|
确定
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -900,21 +973,6 @@ import {
|
|||||||
signTypeOptions,
|
signTypeOptions,
|
||||||
} from '@/option/business/common';
|
} from '@/option/business/common';
|
||||||
|
|
||||||
const contractSelectionColumns = [
|
|
||||||
{ prop: 'contractNo', label: '合同编号', minWidth: 180 },
|
|
||||||
{ prop: 'contractName', label: '合同名称', minWidth: 220 },
|
|
||||||
{ prop: 'projectName', label: '所属项目', minWidth: 170 },
|
|
||||||
{ prop: 'organizationName', label: '所属组织', minWidth: 170 },
|
|
||||||
{ prop: 'contractCategory', label: '合同类别', minWidth: 130 },
|
|
||||||
{ prop: 'signType', label: '签约类型', minWidth: 120 },
|
|
||||||
{ prop: 'partyA', label: '甲方', minWidth: 170 },
|
|
||||||
{ prop: 'partyB', label: '乙方', minWidth: 170 },
|
|
||||||
{ prop: 'startDate', label: '开始日期', minWidth: 130 },
|
|
||||||
{ prop: 'endDate', label: '结束日期', minWidth: 130 },
|
|
||||||
{ prop: 'temporaryStartDate', label: '临时效力起', minWidth: 130 },
|
|
||||||
{ prop: 'temporaryEndDate', label: '临时效力止', minWidth: 130 },
|
|
||||||
];
|
|
||||||
|
|
||||||
const ADJUST_BILLING_ELEMENTS = [
|
const ADJUST_BILLING_ELEMENTS = [
|
||||||
'按重量',
|
'按重量',
|
||||||
'按体积',
|
'按体积',
|
||||||
@@ -1008,7 +1066,6 @@ export default {
|
|||||||
effectiveTypeOptions,
|
effectiveTypeOptions,
|
||||||
contractStageOptions,
|
contractStageOptions,
|
||||||
contractApprovalStatusOptions,
|
contractApprovalStatusOptions,
|
||||||
contractSelectionColumns,
|
|
||||||
transportTypeOptions: [],
|
transportTypeOptions: [],
|
||||||
billingPlanOptions: [],
|
billingPlanOptions: [],
|
||||||
transferDialog: { visible: false, loading: false, submitting: false },
|
transferDialog: { visible: false, loading: false, submitting: false },
|
||||||
@@ -1019,6 +1076,7 @@ export default {
|
|||||||
transferPage: { current: 1, size: 10, total: 0 },
|
transferPage: { current: 1, size: 10, total: 0 },
|
||||||
generateDialog: { visible: false, loading: false },
|
generateDialog: { visible: false, loading: false },
|
||||||
generateQuery: {},
|
generateQuery: {},
|
||||||
|
contractDialogMode: 'generate',
|
||||||
generateContractDialog: {
|
generateContractDialog: {
|
||||||
visible: false,
|
visible: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -1053,24 +1111,16 @@ export default {
|
|||||||
);
|
);
|
||||||
return contract?.contractName || '';
|
return contract?.contractName || '';
|
||||||
},
|
},
|
||||||
|
updateContractName() {
|
||||||
|
const contractId = this.updateFeeForm.contractId;
|
||||||
|
const contract = [...this.updateContractOptions, ...this.contractOptions].find(
|
||||||
|
item => String(item.id) === String(contractId)
|
||||||
|
);
|
||||||
|
return contract?.contractName || '';
|
||||||
|
},
|
||||||
generateContractCategory() {
|
generateContractCategory() {
|
||||||
return this.settlementType === 'payable' ? '承运商合同' : '客户合同';
|
return this.settlementType === 'payable' ? '承运商合同' : '客户合同';
|
||||||
},
|
},
|
||||||
contractCategoryName(value) {
|
|
||||||
return (
|
|
||||||
this.contractCategoryOptions.find(item => String(item.value) === String(value))?.label ||
|
|
||||||
this.formatCell(value)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
signTypeName(value) {
|
|
||||||
return (
|
|
||||||
this.signTypeOptions.find(item => String(item.value) === String(value))?.label ||
|
|
||||||
this.formatCell(value)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
displayValue(value) {
|
|
||||||
return this.formatCell(value);
|
|
||||||
},
|
|
||||||
settlementTypeLabel() {
|
settlementTypeLabel() {
|
||||||
if (this.settlementType === 'receivable') return '应收';
|
if (this.settlementType === 'receivable') return '应收';
|
||||||
if (this.settlementType === 'payable') return '应付';
|
if (this.settlementType === 'payable') return '应付';
|
||||||
@@ -1158,6 +1208,21 @@ export default {
|
|||||||
this.clearAdjustCalculations();
|
this.clearAdjustCalculations();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
contractCategoryName(value) {
|
||||||
|
return (
|
||||||
|
this.contractCategoryOptions.find(item => String(item.value) === String(value))?.label ||
|
||||||
|
this.formatCell(value)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
signTypeName(value) {
|
||||||
|
return (
|
||||||
|
this.signTypeOptions.find(item => String(item.value) === String(value))?.label ||
|
||||||
|
this.formatCell(value)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
displayValue(value) {
|
||||||
|
return this.formatCell(value);
|
||||||
|
},
|
||||||
async loadTransportTypeOptions() {
|
async loadTransportTypeOptions() {
|
||||||
const res = await getDictionary({ code: 'transport_type' });
|
const res = await getDictionary({ code: 'transport_type' });
|
||||||
const records = res.data?.data || [];
|
const records = res.data?.data || [];
|
||||||
@@ -1435,6 +1500,26 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
openGenerateContractDialog() {
|
openGenerateContractDialog() {
|
||||||
|
this.contractDialogMode = 'generate';
|
||||||
|
this.generateContractDialog.visible = true;
|
||||||
|
this.generateContractDialog.expanded = false;
|
||||||
|
this.generateContractDialog.current = null;
|
||||||
|
this.generateContractDialog.page.current = 1;
|
||||||
|
this.loadGenerateContracts();
|
||||||
|
},
|
||||||
|
openUpdateContractDialog() {
|
||||||
|
this.contractDialogMode = 'update';
|
||||||
|
this.generateContractDialog.query = {
|
||||||
|
contractNo: '',
|
||||||
|
contractName: '',
|
||||||
|
projectName: '',
|
||||||
|
organizationName: '',
|
||||||
|
contractCategory: '',
|
||||||
|
signType: '',
|
||||||
|
effectiveType: '',
|
||||||
|
contractStage: '',
|
||||||
|
approvalStatus: '',
|
||||||
|
};
|
||||||
this.generateContractDialog.visible = true;
|
this.generateContractDialog.visible = true;
|
||||||
this.generateContractDialog.expanded = false;
|
this.generateContractDialog.expanded = false;
|
||||||
this.generateContractDialog.current = null;
|
this.generateContractDialog.current = null;
|
||||||
@@ -1456,16 +1541,30 @@ export default {
|
|||||||
const data = this.unwrapPage(res);
|
const data = this.unwrapPage(res);
|
||||||
this.generateContractDialog.rows = data.records || [];
|
this.generateContractDialog.rows = data.records || [];
|
||||||
this.generateContractDialog.page.total = Number(data.total || 0);
|
this.generateContractDialog.page.total = Number(data.total || 0);
|
||||||
this.layoutGenerateContractTable();
|
|
||||||
} finally {
|
} finally {
|
||||||
this.generateContractDialog.loading = false;
|
this.generateContractDialog.loading = false;
|
||||||
|
this.layoutGenerateContractTable();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
layoutGenerateContractTable() {
|
layoutGenerateContractTable() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.generateContractTable?.doLayout?.();
|
window.requestAnimationFrame(() => {
|
||||||
|
this.$refs.generateContractTable?.doLayout?.();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
formatContractSelectionCell(row, column, cellValue) {
|
||||||
|
if (column.property === 'organizationName') {
|
||||||
|
return this.displayValue(row.organizationName || row.deptName);
|
||||||
|
}
|
||||||
|
if (column.property === 'contractCategory') {
|
||||||
|
return this.contractCategoryName(row.contractCategory);
|
||||||
|
}
|
||||||
|
if (column.property === 'signType') {
|
||||||
|
return this.signTypeName(row.signType);
|
||||||
|
}
|
||||||
|
return this.displayValue(cellValue);
|
||||||
|
},
|
||||||
searchGenerateContracts() {
|
searchGenerateContracts() {
|
||||||
this.generateContractDialog.page.current = 1;
|
this.generateContractDialog.page.current = 1;
|
||||||
this.loadGenerateContracts();
|
this.loadGenerateContracts();
|
||||||
@@ -1488,7 +1587,7 @@ export default {
|
|||||||
this.generateContractDialog.page.current = 1;
|
this.generateContractDialog.page.current = 1;
|
||||||
this.loadGenerateContracts();
|
this.loadGenerateContracts();
|
||||||
},
|
},
|
||||||
selectGenerateContract(row) {
|
selectContract(row) {
|
||||||
if (!row) {
|
if (!row) {
|
||||||
this.$message.warning('请选择合同');
|
this.$message.warning('请选择合同');
|
||||||
return;
|
return;
|
||||||
@@ -1500,11 +1599,18 @@ export default {
|
|||||||
partyA: row.partyA || row.payerName,
|
partyA: row.partyA || row.payerName,
|
||||||
partyB: row.partyB || row.payeeName,
|
partyB: row.partyB || row.payeeName,
|
||||||
};
|
};
|
||||||
const index = this.contractOptions.findIndex(item => String(item.id) === String(contract.id));
|
const targetOptions =
|
||||||
if (index >= 0) this.contractOptions.splice(index, 1, contract);
|
this.contractDialogMode === 'update' ? this.updateContractOptions : this.contractOptions;
|
||||||
else this.contractOptions.push(contract);
|
const index = targetOptions.findIndex(item => String(item.id) === String(contract.id));
|
||||||
this.generateQuery.contractId = contract.id;
|
if (index >= 0) targetOptions.splice(index, 1, contract);
|
||||||
this.handleGenerateContractChange(contract.id);
|
else targetOptions.push(contract);
|
||||||
|
if (this.contractDialogMode === 'update') {
|
||||||
|
this.updateFeeForm.contractId = contract.id;
|
||||||
|
this.handleUpdateContractChange(contract.id);
|
||||||
|
} else {
|
||||||
|
this.generateQuery.contractId = contract.id;
|
||||||
|
this.handleGenerateContractChange(contract.id);
|
||||||
|
}
|
||||||
this.generateContractDialog.visible = false;
|
this.generateContractDialog.visible = false;
|
||||||
this.generateContractDialog.current = null;
|
this.generateContractDialog.current = null;
|
||||||
},
|
},
|
||||||
@@ -1918,22 +2024,30 @@ export default {
|
|||||||
this.changePage.current = 1;
|
this.changePage.current = 1;
|
||||||
this.loadChangeRecords();
|
this.loadChangeRecords();
|
||||||
},
|
},
|
||||||
async openUpdateFeeDialog(row) {
|
openUpdateFeeDialog(row) {
|
||||||
await this.loadUpdateFeeContracts();
|
|
||||||
this.updateFeeDialog = { ...this.updateFeeDialog, visible: true, row: row || null };
|
this.updateFeeDialog = { ...this.updateFeeDialog, visible: true, row: row || null };
|
||||||
this.updateFeeForm = {
|
this.updateFeeForm = {
|
||||||
settlementType: this.settlementType || undefined,
|
settlementType: this.settlementType || undefined,
|
||||||
contractId: row?.contractId || '',
|
contractId: row?.contractId || '',
|
||||||
billingPlanId: '',
|
billingPlanId: '',
|
||||||
};
|
};
|
||||||
|
if (row?.contractId) {
|
||||||
|
const contract = {
|
||||||
|
...row,
|
||||||
|
id: row.contractId,
|
||||||
|
deptId: row.deptId || row.organizationId,
|
||||||
|
deptName: row.deptName || row.organizationName,
|
||||||
|
partyA: row.partyA || row.payerName,
|
||||||
|
partyB: row.partyB || row.payeeName,
|
||||||
|
};
|
||||||
|
const index = this.updateContractOptions.findIndex(
|
||||||
|
item => String(item.id) === String(contract.id)
|
||||||
|
);
|
||||||
|
if (index >= 0) this.updateContractOptions.splice(index, 1, contract);
|
||||||
|
else this.updateContractOptions.push(contract);
|
||||||
|
}
|
||||||
this.handleUpdateContractChange(this.updateFeeForm.contractId);
|
this.handleUpdateContractChange(this.updateFeeForm.contractId);
|
||||||
},
|
},
|
||||||
async loadUpdateFeeContracts() {
|
|
||||||
const res = await api.getUpdateFeeContracts({
|
|
||||||
settlementType: this.settlementType || undefined,
|
|
||||||
});
|
|
||||||
this.updateContractOptions = res.data?.data || [];
|
|
||||||
},
|
|
||||||
handleUpdateContractChange(contractId) {
|
handleUpdateContractChange(contractId) {
|
||||||
this.updateFeeForm.billingPlanId = '';
|
this.updateFeeForm.billingPlanId = '';
|
||||||
if (!contractId) {
|
if (!contractId) {
|
||||||
@@ -2392,7 +2506,7 @@ export default {
|
|||||||
const currency = row.currency || 'RMB';
|
const currency = row.currency || 'RMB';
|
||||||
return {
|
return {
|
||||||
...row,
|
...row,
|
||||||
unitPriceText: this.money(row.unitPrice, currency),
|
unitPriceText: this.hasMultipleCargo(row) ? '-' : this.money(row.unitPrice, currency),
|
||||||
freightAmountText: this.money(row.freightAmount, currency),
|
freightAmountText: this.money(row.freightAmount, currency),
|
||||||
otherFeeAmountText: this.money(row.otherFeeAmount, currency),
|
otherFeeAmountText: this.money(row.otherFeeAmount, currency),
|
||||||
totalAmountText: this.money(row.totalAmount, currency),
|
totalAmountText: this.money(row.totalAmount, currency),
|
||||||
@@ -2402,6 +2516,67 @@ export default {
|
|||||||
'-',
|
'-',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
parseCargoRows(value) {
|
||||||
|
if (value === null || value === undefined || value === '') return [];
|
||||||
|
if (Array.isArray(value)) return value;
|
||||||
|
if (typeof value === 'object') return [value];
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(value);
|
||||||
|
if (Array.isArray(parsed)) return parsed;
|
||||||
|
return parsed && typeof parsed === 'object' ? [parsed] : [];
|
||||||
|
} catch (error) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hasMultipleCargo(row = {}) {
|
||||||
|
const countFields = [
|
||||||
|
'cargoCount',
|
||||||
|
'goodsCount',
|
||||||
|
'cargoNum',
|
||||||
|
'goodsNum',
|
||||||
|
'cargoNumber',
|
||||||
|
'goodsNumber',
|
||||||
|
'cargoSize',
|
||||||
|
'goodsSize',
|
||||||
|
'cargoItemCount',
|
||||||
|
'goodsItemCount',
|
||||||
|
];
|
||||||
|
if (
|
||||||
|
countFields.some(field => {
|
||||||
|
const count = Number(row[field]);
|
||||||
|
return Number.isFinite(count) && count > 1;
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cargoSources = [
|
||||||
|
row.goodsJson,
|
||||||
|
row.goodsList,
|
||||||
|
row.goodsRows,
|
||||||
|
row.cargoList,
|
||||||
|
row.cargoRows,
|
||||||
|
row.goods,
|
||||||
|
row.cargoDetails,
|
||||||
|
row.cargoItems,
|
||||||
|
row.cargoNames,
|
||||||
|
row.goodsNames,
|
||||||
|
];
|
||||||
|
if (cargoSources.some(source => this.parseCargoRows(source).length > 1)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const summaryValues = [row.cargoName, row.cargoInfo, row.goodsInfo];
|
||||||
|
if (summaryValues.some(value => Array.isArray(value) && value.length > 1)) return true;
|
||||||
|
const summaryText = summaryValues
|
||||||
|
.filter(value => value !== null && value !== undefined)
|
||||||
|
.map(value => String(value))
|
||||||
|
.join(';');
|
||||||
|
return (
|
||||||
|
/等\s*\d+\s*[种个]\s*货物/.test(summaryText) ||
|
||||||
|
summaryText.split(/[、,,;;]/).filter(Boolean).length > 1
|
||||||
|
);
|
||||||
|
},
|
||||||
collectFeeItemNames(rows) {
|
collectFeeItemNames(rows) {
|
||||||
const names = [];
|
const names = [];
|
||||||
(rows || []).forEach(row => {
|
(rows || []).forEach(row => {
|
||||||
|
|||||||
Reference in New Issue
Block a user