调整项目-合同-运单-结算逻辑链
This commit is contained in:
@@ -267,7 +267,7 @@ export const option = createCrudOption([
|
|||||||
searchType: 'select',
|
searchType: 'select',
|
||||||
searchPlaceholder: '请选择',
|
searchPlaceholder: '请选择',
|
||||||
formslot: true,
|
formslot: true,
|
||||||
order: 140,
|
order: 165,
|
||||||
dicUrl:
|
dicUrl:
|
||||||
'/blade-transport/project-apply/list?current=1&size=9999&approvalStatuses=approved,change_approved',
|
'/blade-transport/project-apply/list?current=1&size=9999&approvalStatuses=approved,change_approved',
|
||||||
dicFormatter: listDicFormatter,
|
dicFormatter: listDicFormatter,
|
||||||
@@ -345,14 +345,9 @@ export const option = createCrudOption([
|
|||||||
label: '甲方',
|
label: '甲方',
|
||||||
prop: 'partyA',
|
prop: 'partyA',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
|
formslot: true,
|
||||||
|
disabled: true,
|
||||||
order: 160,
|
order: 160,
|
||||||
dicUrl:
|
|
||||||
'/blade-transport/customer-archive/list?current=1&size=9999&customerType=客户&approvalStatus=approved&status=1',
|
|
||||||
dicFormatter: listDicFormatter,
|
|
||||||
props: {
|
|
||||||
label: 'fullName',
|
|
||||||
value: 'fullName',
|
|
||||||
},
|
|
||||||
filterable: true,
|
filterable: true,
|
||||||
minWidth: 160,
|
minWidth: 160,
|
||||||
rules: selectRule('甲方'),
|
rules: selectRule('甲方'),
|
||||||
@@ -361,14 +356,9 @@ export const option = createCrudOption([
|
|||||||
label: '乙方',
|
label: '乙方',
|
||||||
prop: 'partyB',
|
prop: 'partyB',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
|
formslot: true,
|
||||||
|
disabled: true,
|
||||||
order: 150,
|
order: 150,
|
||||||
dicUrl:
|
|
||||||
'/blade-transport/customer-archive/list?current=1&size=9999&customerType=承运商&approvalStatus=approved&status=1',
|
|
||||||
dicFormatter: listDicFormatter,
|
|
||||||
props: {
|
|
||||||
label: 'fullName',
|
|
||||||
value: 'fullName',
|
|
||||||
},
|
|
||||||
filterable: true,
|
filterable: true,
|
||||||
minWidth: 160,
|
minWidth: 160,
|
||||||
rules: selectRule('乙方'),
|
rules: selectRule('乙方'),
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ export const config = {
|
|||||||
projectQueryParams: {
|
projectQueryParams: {
|
||||||
approvalStatuses: 'approved,change_approved',
|
approvalStatuses: 'approved,change_approved',
|
||||||
},
|
},
|
||||||
|
contractQueryParams: {
|
||||||
|
contractCategory: '客户合同',
|
||||||
|
},
|
||||||
excludeVoidedProjects: true,
|
excludeVoidedProjects: true,
|
||||||
enableAttachmentTable: true,
|
enableAttachmentTable: true,
|
||||||
detailAttachmentDescriptionPlain: true,
|
detailAttachmentDescriptionPlain: true,
|
||||||
|
|||||||
@@ -167,6 +167,9 @@ export const config = {
|
|||||||
projectQueryParams: {
|
projectQueryParams: {
|
||||||
approvalStatuses: 'approved,change_approved',
|
approvalStatuses: 'approved,change_approved',
|
||||||
},
|
},
|
||||||
|
contractQueryParams: {
|
||||||
|
contractCategory: '客户合同',
|
||||||
|
},
|
||||||
templateCreateTarget: 'transport-plan',
|
templateCreateTarget: 'transport-plan',
|
||||||
enableAttachmentTable: true,
|
enableAttachmentTable: true,
|
||||||
enableTransportPlanForm: true,
|
enableTransportPlanForm: true,
|
||||||
|
|||||||
@@ -329,6 +329,9 @@ export const config = {
|
|||||||
projectQueryParams: {
|
projectQueryParams: {
|
||||||
approvalStatuses: 'approved,change_approved',
|
approvalStatuses: 'approved,change_approved',
|
||||||
},
|
},
|
||||||
|
contractQueryParams: {
|
||||||
|
contractCategory: '客户合同',
|
||||||
|
},
|
||||||
templateCreateTarget: 'waybill-manage',
|
templateCreateTarget: 'waybill-manage',
|
||||||
enableContractSelect: true,
|
enableContractSelect: true,
|
||||||
enableShippingPlanSelect: true,
|
enableShippingPlanSelect: true,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<el-table-column label="单价(元)" width="180"><template #default="{ row }"><div v-if="usesRangeUnitPrice(row)" class="limit-list"><el-input v-for="(item, rangeIndex) in getRanges(row)" :key="rangeIndex" v-model="item.unitPrice" :disabled="readonly" placeholder="请输入单价" @input="value => rangeUnitPriceInput(row, rangeIndex, value)" /></div><el-input v-else v-model="row.unitPrice" :disabled="readonly" @input="value => decimalInput(row, 'unitPrice', value)" /></template></el-table-column>
|
<el-table-column label="单价(元)" width="180"><template #default="{ row }"><div v-if="usesRangeUnitPrice(row)" class="limit-list"><el-input v-for="(item, rangeIndex) in getRanges(row)" :key="rangeIndex" v-model="item.unitPrice" :disabled="readonly" placeholder="请输入单价" @input="value => rangeUnitPriceInput(row, rangeIndex, value)" /></div><el-input v-else v-model="row.unitPrice" :disabled="readonly" @input="value => decimalInput(row, 'unitPrice', value)" /></template></el-table-column>
|
||||||
<el-table-column label="计费要素下限" width="250"><template #default="{ row }"><div class="limit-list"><el-input v-for="(item, rangeIndex) in getRanges(row)" :key="rangeIndex" v-model="item.lowerLimit" :disabled="!canEditLimit(row)" :placeholder="canEditLimit(row) ? '请输入下限' : '无需配置'" @input="value => limitInput(row, rangeIndex, 'lowerLimit', value)" /></div></template></el-table-column>
|
<el-table-column label="计费要素下限" width="250"><template #default="{ row }"><div class="limit-list"><el-input v-for="(item, rangeIndex) in getRanges(row)" :key="rangeIndex" v-model="item.lowerLimit" :disabled="!canEditLimit(row)" :placeholder="canEditLimit(row) ? '请输入下限' : '无需配置'" @input="value => limitInput(row, rangeIndex, 'lowerLimit', value)" /></div></template></el-table-column>
|
||||||
<el-table-column label="计费要素上限" width="270"><template #default="{ row }"><div class="limit-list"><div v-for="(item, rangeIndex) in getRanges(row)" :key="rangeIndex" class="limit-row"><el-input v-model="item.upperLimit" :disabled="!canEditLimit(row)" :placeholder="canEditLimit(row) ? '请输入上限' : '无需配置'" @input="value => limitInput(row, rangeIndex, 'upperLimit', value)" /><el-link v-if="canEditLimit(row)" type="primary" @click="addRange(row, rangeIndex)">添加</el-link><el-link v-if="canEditLimit(row) && getRanges(row).length > 1" type="danger" @click="removeRange(row, rangeIndex)">删除</el-link></div></div></template></el-table-column>
|
<el-table-column label="计费要素上限" width="270"><template #default="{ row }"><div class="limit-list"><div v-for="(item, rangeIndex) in getRanges(row)" :key="rangeIndex" class="limit-row"><el-input v-model="item.upperLimit" :disabled="!canEditLimit(row)" :placeholder="canEditLimit(row) ? '请输入上限' : '无需配置'" @input="value => limitInput(row, rangeIndex, 'upperLimit', value)" /><el-link v-if="canEditLimit(row)" type="primary" @click="addRange(row, rangeIndex)">添加</el-link><el-link v-if="canEditLimit(row) && getRanges(row).length > 1" type="danger" @click="removeRange(row, rangeIndex)">删除</el-link></div></div></template></el-table-column>
|
||||||
<el-table-column label="保底计费重量" width="240"><template #default="{ row }"><el-input v-model="row.minimumBillingWeight" :disabled="!canEditMinimum(row)" :placeholder="canEditMinimum(row) ? '实际计量值小于保底数值时按保底计费' : '仅按重量、按吨·公里可填写'" @input="value => decimalInput(row, 'minimumBillingWeight', value)" /></template></el-table-column>
|
<el-table-column label="保底计费重量" width="240"><template #default="{ row }"><div v-if="usesRangeMinimum(row)" class="limit-list"><el-input v-for="(item, rangeIndex) in getRanges(row)" :key="rangeIndex" v-model="item.minimumBillingWeight" :disabled="!canEditMinimum(row)" :placeholder="canEditMinimum(row) ? '请输入保底计费重量' : '无需配置'" @input="value => rangeMinimumInput(row, rangeIndex, value)" /></div><el-input v-else v-model="row.minimumBillingWeight" :disabled="!canEditMinimum(row)" :placeholder="canEditMinimum(row) ? '实际计量值小于保底数值时按保底计费' : '仅按重量、按吨·公里可填写'" @input="value => decimalInput(row, 'minimumBillingWeight', value)" /></template></el-table-column>
|
||||||
<el-table-column label="备注" width="180"><template #default="{ row }"><el-input v-model="row.remark" maxlength="100" show-word-limit :disabled="readonly" /></template></el-table-column>
|
<el-table-column label="备注" width="180"><template #default="{ row }"><el-input v-model="row.remark" maxlength="100" show-word-limit :disabled="readonly" /></template></el-table-column>
|
||||||
<el-table-column label="操作" width="250" fixed="right"><template #default="{ row, $index }"><el-link type="primary" @click="openMatch(row, $index)">{{ readonly ? '查看匹配条件' : '设置匹配条件' }}</el-link><el-link v-if="!readonly" type="primary" @click="copyRule(row)">复制</el-link><el-link v-if="!readonly" type="danger" @click="removeRule($index)">删除</el-link></template></el-table-column>
|
<el-table-column label="操作" width="250" fixed="right"><template #default="{ row, $index }"><el-link type="primary" @click="openMatch(row, $index)">{{ readonly ? '查看匹配条件' : '设置匹配条件' }}</el-link><el-link v-if="!readonly" type="primary" @click="copyRule(row)">复制</el-link><el-link v-if="!readonly" type="danger" @click="removeRule($index)">删除</el-link></template></el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -45,7 +45,7 @@ import { getLazyTree as getRegionLazyTree } from '@/api/base/region';
|
|||||||
import { getDictionary } from '@/api/system/dictbiz';
|
import { getDictionary } from '@/api/system/dictbiz';
|
||||||
|
|
||||||
const clone = value => JSON.parse(JSON.stringify(value));
|
const clone = value => JSON.parse(JSON.stringify(value));
|
||||||
const defaultRule = () => ({ feeType: '', feeItem: '', billingElement: '', billingType: '', billingUnit: '', unitPrice: '', lowerLimit: '', upperLimit: '', limitRanges: [{ lowerLimit: '', upperLimit: '', unitPrice: '' }], minimumBillingWeight: '', remark: '', matchCondition: { origin: '', originCode: '', originPath: [], destination: '', destinationCode: '', destinationPath: [], transportMode: '', cargoType: '', cargoTypeCode: '', cargoTypePath: [] } });
|
const defaultRule = () => ({ feeType: '', feeItem: '', billingElement: '', billingType: '', billingUnit: '', unitPrice: '', lowerLimit: '', upperLimit: '', limitRanges: [{ lowerLimit: '', upperLimit: '', unitPrice: '', minimumBillingWeight: '' }], minimumBillingWeight: '', remark: '', matchCondition: { origin: '', originCode: '', originPath: [], destination: '', destinationCode: '', destinationPath: [], transportMode: '', cargoType: '', cargoTypeCode: '', cargoTypePath: [] } });
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: { modelValue: Boolean, value: { type: Object, default: () => ({}) }, index: { type: Number, default: -1 }, readonly: Boolean },
|
props: { modelValue: Boolean, value: { type: Object, default: () => ({}) }, index: { type: Number, default: -1 }, readonly: Boolean },
|
||||||
@@ -56,9 +56,9 @@ export default {
|
|||||||
watch: { value: { deep: true, handler(value) { if (this.modelValue) { this.draft = this.normalizePlan(value); this.loadRuleItems(); } } } },
|
watch: { value: { deep: true, handler(value) { if (this.modelValue) { this.draft = this.normalizePlan(value); this.loadRuleItems(); } } } },
|
||||||
methods: {
|
methods: {
|
||||||
normalizePlan(value = {}) { const plan = { planName: '', defaultPlan: false, remark: '', ...clone(value || {}) }; plan.rules = (value?.rules?.length ? value.rules : [defaultRule()]).map(rule => this.normalizeRule(rule)); return plan; },
|
normalizePlan(value = {}) { const plan = { planName: '', defaultPlan: false, remark: '', ...clone(value || {}) }; plan.rules = (value?.rules?.length ? value.rules : [defaultRule()]).map(rule => this.normalizeRule(rule)); return plan; },
|
||||||
normalizeRule(rule = {}) { const next = { ...defaultRule(), ...clone(rule) }; next.limitRanges = this.normalizeRanges(next); this.syncLegacyLimit(next); next.matchCondition = { ...defaultRule().matchCondition, ...(rule.matchCondition || {}) }; return next; },
|
normalizeRule(rule = {}) { const next = { ...defaultRule(), ...clone(rule) }; if (next.billingType === '阶梯单价' && next.minimumBillingWeight === '') { const rangeMinimum = (Array.isArray(next.limitRanges) ? next.limitRanges : []).find(item => item?.minimumBillingWeight !== '')?.minimumBillingWeight; if (rangeMinimum !== undefined) next.minimumBillingWeight = rangeMinimum; } next.limitRanges = this.normalizeRanges(next); if (!this.usesRangeMinimum(next)) next.limitRanges = next.limitRanges.map(item => ({ ...item, minimumBillingWeight: '' })); this.syncLegacyLimit(next); next.matchCondition = { ...defaultRule().matchCondition, ...(rule.matchCondition || {}) }; return next; },
|
||||||
normalizeRanges(row) { const ranges = Array.isArray(row.limitRanges) ? row.limitRanges.map(item => ({ lowerLimit: item?.lowerLimit ?? '', upperLimit: item?.upperLimit ?? '', unitPrice: item?.unitPrice === undefined || item?.unitPrice === '' ? row.unitPrice ?? '' : item.unitPrice })).filter(item => item.lowerLimit !== '' || item.upperLimit !== '' || item.unitPrice !== '') : []; if (!ranges.length && (row.lowerLimit !== '' || row.upperLimit !== '' || row.unitPrice !== '')) ranges.push({ lowerLimit: row.lowerLimit ?? '', upperLimit: row.upperLimit ?? '', unitPrice: row.unitPrice ?? '' }); return ranges.length ? ranges : [{ lowerLimit: '', upperLimit: '', unitPrice: '' }]; },
|
normalizeRanges(row) { const ranges = Array.isArray(row.limitRanges) ? row.limitRanges.map(item => ({ lowerLimit: item?.lowerLimit ?? '', upperLimit: item?.upperLimit ?? '', unitPrice: item?.unitPrice === undefined || item?.unitPrice === '' ? row.unitPrice ?? '' : item.unitPrice, minimumBillingWeight: item?.minimumBillingWeight === undefined || item?.minimumBillingWeight === '' ? (this.usesRangeMinimum(row) ? row.minimumBillingWeight ?? '' : '') : item.minimumBillingWeight })).filter(item => item.lowerLimit !== '' || item.upperLimit !== '' || item.unitPrice !== '' || item.minimumBillingWeight !== '') : []; if (!ranges.length && (row.lowerLimit !== '' || row.upperLimit !== '' || row.unitPrice !== '' || row.minimumBillingWeight !== '')) ranges.push({ lowerLimit: row.lowerLimit ?? '', upperLimit: row.upperLimit ?? '', unitPrice: row.unitPrice ?? '', minimumBillingWeight: this.usesRangeMinimum(row) ? row.minimumBillingWeight ?? '' : '' }); return ranges.length ? ranges : [{ lowerLimit: '', upperLimit: '', unitPrice: '', minimumBillingWeight: '' }]; },
|
||||||
syncLegacyLimit(row) { const first = row.limitRanges?.[0] || {}; row.lowerLimit = first.lowerLimit || ''; row.upperLimit = first.upperLimit || ''; if (this.usesRangeUnitPrice(row)) row.unitPrice = first.unitPrice || ''; },
|
syncLegacyLimit(row) { const first = row.limitRanges?.[0] || {}; row.lowerLimit = first.lowerLimit || ''; row.upperLimit = first.upperLimit || ''; if (this.usesRangeUnitPrice(row)) row.unitPrice = first.unitPrice || ''; if (this.usesRangeMinimum(row)) row.minimumBillingWeight = first.minimumBillingWeight || ''; },
|
||||||
loadDictionaries() { this.feeCategoryLoading = true; getDictionary({ code: 'fee_category' }).then(res => { this.feeCategories = res.data?.data || []; this.loadRuleItems(); }).finally(() => { this.feeCategoryLoading = false; }); this.unitLoading = true; getDictionary({ code: 'unit_fee' }).then(res => { this.unitOptions = res.data?.data || []; }).finally(() => { this.unitLoading = false; }); },
|
loadDictionaries() { this.feeCategoryLoading = true; getDictionary({ code: 'fee_category' }).then(res => { this.feeCategories = res.data?.data || []; this.loadRuleItems(); }).finally(() => { this.feeCategoryLoading = false; }); this.unitLoading = true; getDictionary({ code: 'unit_fee' }).then(res => { this.unitOptions = res.data?.data || []; }).finally(() => { this.unitLoading = false; }); },
|
||||||
feeTypeKey(row) { const option = this.feeCategories.find(item => String(item.dictKey) === String(row.feeType) || String(item.dictValue) === String(row.feeType)); return option?.dictKey || row.feeType || ''; },
|
feeTypeKey(row) { const option = this.feeCategories.find(item => String(item.dictKey) === String(row.feeType) || String(item.dictValue) === String(row.feeType)); return option?.dictKey || row.feeType || ''; },
|
||||||
feeItemOptions(row) { return this.feeItems[this.feeTypeKey(row)] || []; },
|
feeItemOptions(row) { return this.feeItems[this.feeTypeKey(row)] || []; },
|
||||||
@@ -66,23 +66,26 @@ export default {
|
|||||||
loadFeeItems(value) { const key = this.feeTypeKey({ feeType: value }); if (!key || this.feeItems[key]) return; this.feeItemLoadingMap[key] = true; getFeeItemList(1, 9999, { feeCategory: key }).then(res => { const data = res?.data?.data || res?.data || {}; this.feeItems[key] = Array.isArray(data) ? data : (data.records || []); }).finally(() => { this.feeItemLoadingMap[key] = false; }); },
|
loadFeeItems(value) { const key = this.feeTypeKey({ feeType: value }); if (!key || this.feeItems[key]) return; this.feeItemLoadingMap[key] = true; getFeeItemList(1, 9999, { feeCategory: key }).then(res => { const data = res?.data?.data || res?.data || {}; this.feeItems[key] = Array.isArray(data) ? data : (data.records || []); }).finally(() => { this.feeItemLoadingMap[key] = false; }); },
|
||||||
handleFeeTypeChange(row, value) { row.feeType = this.feeTypeKey({ feeType: value }); row.feeItem = ''; this.loadFeeItems(row.feeType); },
|
handleFeeTypeChange(row, value) { row.feeType = this.feeTypeKey({ feeType: value }); row.feeItem = ''; this.loadFeeItems(row.feeType); },
|
||||||
billingTypes(row) { return this.typeMap[row.billingElement] || []; },
|
billingTypes(row) { return this.typeMap[row.billingElement] || []; },
|
||||||
handleElementChange(row) { if (!this.billingTypes(row).includes(row.billingType)) row.billingType = ''; if (!this.canEditMinimum(row)) row.minimumBillingWeight = ''; this.handleTypeChange(row); },
|
handleElementChange(row) { if (!this.billingTypes(row).includes(row.billingType)) row.billingType = ''; if (!this.canEditMinimum(row)) { row.minimumBillingWeight = ''; row.limitRanges = (row.limitRanges || []).map(item => ({ ...item, minimumBillingWeight: '' })); } this.handleTypeChange(row); },
|
||||||
handleTypeChange(row) { if (!this.canEditLimit(row)) { row.limitRanges = [{ lowerLimit: '', upperLimit: '', unitPrice: '' }]; row.lowerLimit = ''; row.upperLimit = ''; } else { row.limitRanges = this.normalizeRanges(row); this.syncLegacyLimit(row); } },
|
handleTypeChange(row) { if (!this.canEditMinimum(row)) row.minimumBillingWeight = ''; if (!this.usesRangeMinimum(row)) row.limitRanges = (row.limitRanges || []).map(item => ({ ...item, minimumBillingWeight: '' })); if (!this.canEditLimit(row)) { row.limitRanges = [{ lowerLimit: '', upperLimit: '', unitPrice: '', minimumBillingWeight: '' }]; row.lowerLimit = ''; row.upperLimit = ''; } else { row.limitRanges = this.normalizeRanges(row); this.syncLegacyLimit(row); } },
|
||||||
canEditLimit(row) { return !this.readonly && Boolean(row.billingElement) && Boolean(row.billingType) && (row.billingType.includes('区间') || row.billingType.includes('阶梯')); },
|
canEditLimit(row) { return !this.readonly && Boolean(row.billingElement) && Boolean(row.billingType) && (row.billingType.includes('区间') || row.billingType.includes('阶梯')); },
|
||||||
usesRangeUnitPrice(row) { return ['区间单价', '阶梯单价'].includes(row.billingType); },
|
usesRangeUnitPrice(row) { return ['区间单价', '阶梯单价', '区间阶梯一口价'].includes(row.billingType); },
|
||||||
canEditMinimum(row) { return !this.readonly && ['按重量', '按吨·公里'].includes(row.billingElement); },
|
usesRangeMinimum(row) { return this.supportsMinimum(row) && row.billingType === '区间单价'; },
|
||||||
getRanges(row) { return Array.isArray(row.limitRanges) && row.limitRanges.length ? row.limitRanges : [{ lowerLimit: '', upperLimit: '', unitPrice: '' }]; },
|
supportsMinimum(row) { return ['按重量', '按吨·公里'].includes(row.billingElement) && Boolean(row.billingType) && !row.billingType.includes('一口价'); },
|
||||||
addRange(row, index) { row.limitRanges = this.getRanges(row); row.limitRanges.splice(index + 1, 0, { lowerLimit: '', upperLimit: '', unitPrice: '' }); },
|
canEditMinimum(row) { return !this.readonly && this.supportsMinimum(row); },
|
||||||
removeRange(row, index) { row.limitRanges = this.getRanges(row); row.limitRanges.splice(index, 1); if (!row.limitRanges.length) row.limitRanges.push({ lowerLimit: '', upperLimit: '', unitPrice: '' }); this.syncLegacyLimit(row); },
|
getRanges(row) { return Array.isArray(row.limitRanges) && row.limitRanges.length ? row.limitRanges : [{ lowerLimit: '', upperLimit: '', unitPrice: '', minimumBillingWeight: '' }]; },
|
||||||
|
addRange(row, index) { row.limitRanges = this.getRanges(row); row.limitRanges.splice(index + 1, 0, { lowerLimit: '', upperLimit: '', unitPrice: '', minimumBillingWeight: '' }); },
|
||||||
|
removeRange(row, index) { row.limitRanges = this.getRanges(row); row.limitRanges.splice(index, 1); if (!row.limitRanges.length) row.limitRanges.push({ lowerLimit: '', upperLimit: '', unitPrice: '', minimumBillingWeight: '' }); this.syncLegacyLimit(row); },
|
||||||
limitInput(row, index, prop, value) { row.limitRanges = this.getRanges(row); const text = String(value || '').replace(/[^\d.]/g, ''); const parts = text.split('.'); row.limitRanges[index][prop] = parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 2)}` : parts[0]; this.syncLegacyLimit(row); },
|
limitInput(row, index, prop, value) { row.limitRanges = this.getRanges(row); const text = String(value || '').replace(/[^\d.]/g, ''); const parts = text.split('.'); row.limitRanges[index][prop] = parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 2)}` : parts[0]; this.syncLegacyLimit(row); },
|
||||||
decimalInput(row, prop, value) { const text = String(value || '').replace(/[^\d.]/g, ''); const parts = text.split('.'); row[prop] = parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 2)}` : parts[0]; },
|
decimalInput(row, prop, value) { const text = String(value || '').replace(/[^\d.]/g, ''); const parts = text.split('.'); row[prop] = parts.length > 1 ? `${parts[0]}.${parts.slice(1).join('').slice(0, 2)}` : parts[0]; },
|
||||||
rangeUnitPriceInput(row, index, value) { row.limitRanges = this.getRanges(row); const target = { value }; this.decimalInput(target, 'value', value); row.limitRanges[index].unitPrice = target.value; if (index === 0) row.unitPrice = target.value; },
|
rangeUnitPriceInput(row, index, value) { row.limitRanges = this.getRanges(row); const target = { value }; this.decimalInput(target, 'value', value); row.limitRanges[index].unitPrice = target.value; if (index === 0) row.unitPrice = target.value; },
|
||||||
|
rangeMinimumInput(row, index, value) { row.limitRanges = this.getRanges(row); const target = { value }; this.decimalInput(target, 'value', value); row.limitRanges[index].minimumBillingWeight = target.value; if (index === 0) row.minimumBillingWeight = target.value; },
|
||||||
addRule() { this.draft.rules.push(defaultRule()); },
|
addRule() { this.draft.rules.push(defaultRule()); },
|
||||||
copyRule(row) { const next = clone(row); this.draft.rules.push(this.normalizeRule(next)); this.loadFeeItems(next.feeType); },
|
copyRule(row) { const next = clone(row); this.draft.rules.push(this.normalizeRule(next)); this.loadFeeItems(next.feeType); },
|
||||||
removeRule(index) { this.draft.rules.splice(index, 1); if (!this.draft.rules.length) this.addRule(); },
|
removeRule(index) { this.draft.rules.splice(index, 1); if (!this.draft.rules.length) this.addRule(); },
|
||||||
validateRules() { const groups = {}; const feeItemSet = new Set(); const required = [['feeType', '费用类型'], ['feeItem', '费用项'], ['billingElement', '计费要素'], ['billingType', '计费类型'], ['billingUnit', '计费单位']]; for (const [i, row] of this.draft.rules.entries()) { const empty = required.find(([key]) => row[key] === undefined || row[key] === null || String(row[key]).trim() === ''); if (empty) { this.$message.warning(`第${i + 1}行${empty[1]}不能为空`); return false; } const feeItem = String(row.feeItem).trim(); if (feeItemSet.has(feeItem)) { this.$message.warning(`费用项“${feeItem}”不能重复`); return false; } feeItemSet.add(feeItem); if (!this.usesRangeUnitPrice(row) && (row.unitPrice === undefined || row.unitPrice === null || String(row.unitPrice).trim() === '')) { this.$message.warning(`第${i + 1}行单价不能为空`); return false; } if (!this.billingTypes(row).includes(row.billingType)) { this.$message.warning('请选择计费要素对应的计费类型'); return false; } if (!this.canEditLimit(row)) continue; const key = row.billingElement; groups[key] = groups[key] || []; for (const range of this.getRanges(row)) { const lower = Number(range.lowerLimit); const upper = Number(range.upperLimit); if (range.lowerLimit === '' || range.upperLimit === '' || Number.isNaN(lower) || Number.isNaN(upper)) { this.$message.warning('请完整填写计费要素上下限'); return false; } if (this.usesRangeUnitPrice(row) && (range.unitPrice === undefined || range.unitPrice === null || String(range.unitPrice).trim() === '')) { this.$message.warning('请为每组计费要素区间填写单价'); return false; } if (lower > upper) { this.$message.warning('计费要素下限不能大于上限'); return false; } groups[key].push({ lower, upper }); } } return this.validateRangeGroups(groups); },
|
validateRules() { const groups = {}; const feeItemSet = new Set(); const required = [['feeType', '费用类型'], ['feeItem', '费用项'], ['billingElement', '计费要素'], ['billingType', '计费类型'], ['billingUnit', '计费单位']]; for (const [i, row] of this.draft.rules.entries()) { const empty = required.find(([key]) => row[key] === undefined || row[key] === null || String(row[key]).trim() === ''); if (empty) { this.$message.warning(`第${i + 1}行${empty[1]}不能为空`); return false; } const feeItem = String(row.feeItem).trim(); if (feeItemSet.has(feeItem)) { this.$message.warning(`费用项“${feeItem}”不能重复`); return false; } feeItemSet.add(feeItem); if (!this.usesRangeUnitPrice(row) && (row.unitPrice === undefined || row.unitPrice === null || String(row.unitPrice).trim() === '')) { this.$message.warning(`第${i + 1}行单价不能为空`); return false; } if (!this.billingTypes(row).includes(row.billingType)) { this.$message.warning('请选择计费要素对应的计费类型'); return false; } if (!this.canEditLimit(row)) continue; const key = row.billingElement; groups[key] = groups[key] || []; for (const range of this.getRanges(row)) { const lower = Number(range.lowerLimit); const upper = Number(range.upperLimit); if (range.lowerLimit === '' || range.upperLimit === '' || Number.isNaN(lower) || Number.isNaN(upper)) { this.$message.warning('请完整填写计费要素上下限'); return false; } if (this.usesRangeUnitPrice(row) && (range.unitPrice === undefined || range.unitPrice === null || String(range.unitPrice).trim() === '')) { this.$message.warning('请为每组计费要素区间填写单价'); return false; } if (lower > upper) { this.$message.warning('计费要素下限不能大于上限'); return false; } groups[key].push({ lower, upper }); } } return this.validateRangeGroups(groups); },
|
||||||
validateRangeGroups(groups) { const precision = 0.000001; for (const [element, ranges] of Object.entries(groups)) { const sorted = [...ranges].sort((a, b) => a.lower - b.lower || a.upper - b.upper); for (let i = 1; i < sorted.length; i += 1) { if (sorted[i].lower < sorted[i - 1].upper - precision) { this.$message.warning(`${element}的计费要素区间不能重叠`); return false; } if (sorted[i].lower > sorted[i - 1].upper + precision) { this.$message.warning(`${element}的计费要素区间必须连续,不能存在间隙`); return false; } } } return true; },
|
validateRangeGroups(groups) { const precision = 0.000001; for (const [element, ranges] of Object.entries(groups)) { const sorted = [...ranges].sort((a, b) => a.lower - b.lower || a.upper - b.upper); for (let i = 1; i < sorted.length; i += 1) { if (sorted[i].lower < sorted[i - 1].upper - precision) { this.$message.warning(`${element}的计费要素区间不能重叠`); return false; } if (sorted[i].lower > sorted[i - 1].upper + precision) { this.$message.warning(`${element}的计费要素区间必须连续,不能存在间隙`); return false; } } } return true; },
|
||||||
save() { this.$refs.formRef.validate(valid => { if (!valid || !this.validateRules()) return; const plan = clone(this.draft); plan.rules = plan.rules.map(rule => { const ranges = this.canEditLimit(rule) ? this.getRanges(rule) : []; return { ...rule, unitPrice: this.usesRangeUnitPrice(rule) ? ranges[0]?.unitPrice || '' : rule.unitPrice, limitRanges: ranges, lowerLimit: ranges[0]?.lowerLimit || '', upperLimit: ranges[0]?.upperLimit || '', minimumBillingWeight: this.canEditMinimum(rule) ? rule.minimumBillingWeight : '' }; }); this.$emit('save', plan, this.index); this.visible = false; }); },
|
save() { this.$refs.formRef.validate(valid => { if (!valid || !this.validateRules()) return; const plan = clone(this.draft); plan.rules = plan.rules.map(rule => { const ranges = this.canEditLimit(rule) ? this.getRanges(rule) : []; return { ...rule, unitPrice: this.usesRangeUnitPrice(rule) ? ranges[0]?.unitPrice || '' : rule.unitPrice, limitRanges: ranges, lowerLimit: ranges[0]?.lowerLimit || '', upperLimit: ranges[0]?.upperLimit || '', minimumBillingWeight: this.canEditMinimum(rule) ? (this.usesRangeMinimum(rule) ? ranges[0]?.minimumBillingWeight || '' : rule.minimumBillingWeight) : '' }; }); this.$emit('save', plan, this.index); this.visible = false; }); },
|
||||||
openMatch(row, index) { this.matchIndex = index; this.matchForm = { ...defaultRule().matchCondition, ...(row.matchCondition || {}) }; this.matchVisible = true; this.ensureRegions(); this.ensureCargo().then(() => { const path = this.resolveCargoPath(this.matchForm); if (path.length) this.matchCargoChange(path); }); },
|
openMatch(row, index) { this.matchIndex = index; this.matchForm = { ...defaultRule().matchCondition, ...(row.matchCondition || {}) }; this.matchVisible = true; this.ensureRegions(); this.ensureCargo().then(() => { const path = this.resolveCargoPath(this.matchForm); if (path.length) this.matchCargoChange(path); }); },
|
||||||
ensureRegions() { if (this.regionOptions.length) return Promise.resolve(this.regionOptions); if (this.regionRequest) return this.regionRequest; this.regionLoading = true; this.regionRequest = getRegionLazyTree().then(res => { const raw = res.data?.data || []; this.regionOptions = this.normalizeRegionTree(raw); return this.regionOptions; }).finally(() => { this.regionLoading = false; this.regionRequest = null; }); return this.regionRequest; },
|
ensureRegions() { if (this.regionOptions.length) return Promise.resolve(this.regionOptions); if (this.regionRequest) return this.regionRequest; this.regionLoading = true; this.regionRequest = getRegionLazyTree().then(res => { const raw = res.data?.data || []; this.regionOptions = this.normalizeRegionTree(raw); return this.regionOptions; }).finally(() => { this.regionLoading = false; this.regionRequest = null; }); return this.regionRequest; },
|
||||||
normalizeRegionTree(list) { const map = new Map(); const flat = []; const walk = items => (items || []).forEach(item => { flat.push({ ...item, children: undefined }); if (item.children?.length) walk(item.children); }); walk(list); flat.forEach(item => map.set(String(item.id ?? item.code ?? item.value), { ...item, id: String(item.id ?? item.code ?? item.value), parentId: String(item.parentId ?? item.parentCode ?? ''), children: [] })); const roots = []; map.forEach(node => { const parent = map.get(node.parentId); if (parent && parent !== node) parent.children.push(node); else roots.push(node); }); const china = roots.find(item => ['中国', '中华人民共和国'].includes(item.title || item.name)); const source = china?.children?.length ? china.children : roots; const normalize = (node, level) => ({ ...node, title: node.title || node.name || '', leaf: level === 2, children: level === 1 ? (node.children || []).map(child => normalize(child, 2)) : undefined }); return source.map(node => normalize(node, 1)); },
|
normalizeRegionTree(list) { const map = new Map(); const flat = []; const walk = items => (items || []).forEach(item => { flat.push({ ...item, children: undefined }); if (item.children?.length) walk(item.children); }); walk(list); flat.forEach(item => map.set(String(item.id ?? item.code ?? item.value), { ...item, id: String(item.id ?? item.code ?? item.value), parentId: String(item.parentId ?? item.parentCode ?? ''), children: [] })); const roots = []; map.forEach(node => { const parent = map.get(node.parentId); if (parent && parent !== node) parent.children.push(node); else roots.push(node); }); const china = roots.find(item => ['中国', '中华人民共和国'].includes(item.title || item.name)); const source = china?.children?.length ? china.children : roots; const normalize = (node, level) => ({ ...node, title: node.title || node.name || '', leaf: level === 2, children: level === 1 ? (node.children || []).map(child => normalize(child, 2)) : undefined }); return source.map(node => normalize(node, 1)); },
|
||||||
|
|||||||
@@ -230,6 +230,44 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #partyA-form>
|
||||||
|
<el-select
|
||||||
|
v-model="form.partyA"
|
||||||
|
class="business-crud-page__field"
|
||||||
|
placeholder="请选择甲方"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
:loading="contractPartyLoading"
|
||||||
|
:disabled="dialogReadonly || !form.projectId"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in contractPartyAOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #partyB-form>
|
||||||
|
<el-select
|
||||||
|
v-model="form.partyB"
|
||||||
|
class="business-crud-page__field"
|
||||||
|
placeholder="请选择乙方"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
:loading="contractPartyLoading"
|
||||||
|
:disabled="dialogReadonly || !form.projectId"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in contractPartyBOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #contractName-form>
|
<template #contractName-form>
|
||||||
<el-select
|
<el-select
|
||||||
v-if="contractSelectEnabled"
|
v-if="contractSelectEnabled"
|
||||||
@@ -677,22 +715,26 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="hasTransportType && isCarrierMode"
|
v-if="hasTransportType && taskCarrierRequired"
|
||||||
class="business-crud-page__subsection business-crud-page__carrier-section"
|
class="business-crud-page__subsection business-crud-page__carrier-section"
|
||||||
>
|
>
|
||||||
<div class="business-crud-page__subsection-head">
|
<div class="business-crud-page__subsection-head">
|
||||||
<span>承运信息</span>
|
<span>承运信息</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="business-crud-page__task-row">
|
<div class="business-crud-page__task-row">
|
||||||
<el-form-item label="承运商" required class="business-crud-page__task-span-1">
|
<el-form-item
|
||||||
|
:label="taskCarrierLabel"
|
||||||
|
required
|
||||||
|
class="business-crud-page__task-span-1"
|
||||||
|
>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="form.carrierName"
|
v-model="form.carrierName"
|
||||||
placeholder="请输入"
|
:placeholder="`请选择${taskCarrierLabel}`"
|
||||||
filterable
|
filterable
|
||||||
clearable
|
clearable
|
||||||
:suffix-icon="Search"
|
:suffix-icon="Search"
|
||||||
:loading="taskCarrierLoading"
|
:loading="taskCarrierLoading"
|
||||||
:disabled="dialogReadonly"
|
:disabled="dialogReadonly || (isWaybillDetailLayout && !form.projectId)"
|
||||||
@visible-change="visible => visible && loadTaskCarrierOptions()"
|
@visible-change="visible => visible && loadTaskCarrierOptions()"
|
||||||
@change="handleTaskCarrierChange"
|
@change="handleTaskCarrierChange"
|
||||||
>
|
>
|
||||||
@@ -1221,14 +1263,18 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<template v-if="hasTransportType">
|
<template v-if="hasTransportType">
|
||||||
<el-form-item v-if="isCarrierMode" label="承运商" required>
|
<el-form-item v-if="taskCarrierRequired" :label="taskCarrierLabel" required>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="form.carrierName"
|
v-model="form.carrierName"
|
||||||
placeholder="请选择承运商"
|
:placeholder="`请选择${taskCarrierLabel}`"
|
||||||
filterable
|
filterable
|
||||||
clearable
|
clearable
|
||||||
:loading="taskCarrierLoading"
|
:loading="taskCarrierLoading"
|
||||||
:disabled="dialogReadonly || form.carrierType !== '承运商'"
|
:disabled="
|
||||||
|
dialogReadonly ||
|
||||||
|
(isWaybillDetailLayout && !form.projectId) ||
|
||||||
|
!taskCarrierRequired
|
||||||
|
"
|
||||||
@visible-change="visible => visible && loadTaskCarrierOptions()"
|
@visible-change="visible => visible && loadTaskCarrierOptions()"
|
||||||
@change="handleTaskCarrierChange"
|
@change="handleTaskCarrierChange"
|
||||||
>
|
>
|
||||||
@@ -4181,19 +4227,18 @@
|
|||||||
<el-radio-button v-for="item in taskCarrierTypes" :key="item" :label="item" />
|
<el-radio-button v-for="item in taskCarrierTypes" :key="item" :label="item" />
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="dispatchItemForm.carrierType === '承运商'" label="承运商" required>
|
<el-form-item v-if="dispatchCarrierRequired" :label="dispatchCarrierLabel" required>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="dispatchItemForm.carrierName"
|
v-model="dispatchItemForm.carrierName"
|
||||||
placeholder="请输入"
|
:placeholder="`请选择${dispatchCarrierLabel}`"
|
||||||
filterable
|
filterable
|
||||||
clearable
|
clearable
|
||||||
:suffix-icon="Search"
|
:loading="dispatchCarrierLoading"
|
||||||
:loading="taskCarrierLoading"
|
|
||||||
@visible-change="visible => visible && loadDispatchCarrierOptions()"
|
@visible-change="visible => visible && loadDispatchCarrierOptions()"
|
||||||
@change="handleDispatchCarrierChange"
|
@change="handleDispatchCarrierChange"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in taskCarrierOptions"
|
v-for="item in dispatchCarrierOptions"
|
||||||
:key="
|
:key="
|
||||||
item.id || item.customerName || item.carrierName || item.fullName || item.name
|
item.id || item.customerName || item.carrierName || item.fullName || item.name
|
||||||
"
|
"
|
||||||
@@ -4398,19 +4443,18 @@
|
|||||||
<el-radio-button v-for="item in taskCarrierTypes" :key="item" :label="item" />
|
<el-radio-button v-for="item in taskCarrierTypes" :key="item" :label="item" />
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="dispatchItemForm.carrierType === '承运商'" label="承运商" required>
|
<el-form-item v-if="dispatchCarrierRequired" :label="dispatchCarrierLabel" required>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="dispatchItemForm.carrierName"
|
v-model="dispatchItemForm.carrierName"
|
||||||
placeholder="请输入"
|
:placeholder="`请选择${dispatchCarrierLabel}`"
|
||||||
filterable
|
filterable
|
||||||
clearable
|
clearable
|
||||||
:suffix-icon="Search"
|
:loading="dispatchCarrierLoading"
|
||||||
:loading="taskCarrierLoading"
|
|
||||||
@visible-change="visible => visible && loadDispatchCarrierOptions()"
|
@visible-change="visible => visible && loadDispatchCarrierOptions()"
|
||||||
@change="handleDispatchCarrierChange"
|
@change="handleDispatchCarrierChange"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in taskCarrierOptions"
|
v-for="item in dispatchCarrierOptions"
|
||||||
:key="
|
:key="
|
||||||
item.id || item.customerName || item.carrierName || item.fullName || item.name
|
item.id || item.customerName || item.carrierName || item.fullName || item.name
|
||||||
"
|
"
|
||||||
@@ -5500,7 +5544,10 @@ import {
|
|||||||
getDetail as getContractDetail,
|
getDetail as getContractDetail,
|
||||||
getList as getContractList,
|
getList as getContractList,
|
||||||
} from '@/api/business/contract-manage';
|
} from '@/api/business/contract-manage';
|
||||||
import { getList as getProjectList } from '@/api/business/project-apply';
|
import {
|
||||||
|
getDetail as getProjectDetail,
|
||||||
|
getList as getProjectList,
|
||||||
|
} from '@/api/business/project-apply';
|
||||||
import { getList as getLoadingList } from '@/api/business/loading-manage';
|
import { getList as getLoadingList } from '@/api/business/loading-manage';
|
||||||
import { getList as getCommonRouteList } from '@/api/business/common-route';
|
import { getList as getCommonRouteList } from '@/api/business/common-route';
|
||||||
import {
|
import {
|
||||||
@@ -5908,6 +5955,10 @@ export default {
|
|||||||
projectLoading: false,
|
projectLoading: false,
|
||||||
contractOptions: [],
|
contractOptions: [],
|
||||||
contractLoading: false,
|
contractLoading: false,
|
||||||
|
contractPartyAOptions: [],
|
||||||
|
contractPartyBOptions: [],
|
||||||
|
contractPartyLoading: false,
|
||||||
|
contractPartyRequestId: 0,
|
||||||
shippingPlanOptions: [],
|
shippingPlanOptions: [],
|
||||||
shippingPlanLoading: false,
|
shippingPlanLoading: false,
|
||||||
selectedOrganizationId: '',
|
selectedOrganizationId: '',
|
||||||
@@ -5923,6 +5974,9 @@ export default {
|
|||||||
dispatchRow: {},
|
dispatchRow: {},
|
||||||
dispatchRows: [],
|
dispatchRows: [],
|
||||||
dispatchSaving: '',
|
dispatchSaving: '',
|
||||||
|
dispatchCarrierOptions: [],
|
||||||
|
dispatchCarrierLoading: false,
|
||||||
|
dispatchCarrierRequestId: 0,
|
||||||
dispatchItemBox: false,
|
dispatchItemBox: false,
|
||||||
dispatchItemIndex: -1,
|
dispatchItemIndex: -1,
|
||||||
dispatchItemForm: defaultDispatchRow(),
|
dispatchItemForm: defaultDispatchRow(),
|
||||||
@@ -6008,6 +6062,7 @@ export default {
|
|||||||
taskCarrierTypes,
|
taskCarrierTypes,
|
||||||
taskCarrierOptions: [],
|
taskCarrierOptions: [],
|
||||||
taskCarrierLoading: false,
|
taskCarrierLoading: false,
|
||||||
|
taskCarrierRequestId: 0,
|
||||||
taskDriverOptions: [],
|
taskDriverOptions: [],
|
||||||
taskDriverLoading: false,
|
taskDriverLoading: false,
|
||||||
taskCargoOptionsMap: {},
|
taskCargoOptionsMap: {},
|
||||||
@@ -6356,6 +6411,12 @@ export default {
|
|||||||
isCarrierMode() {
|
isCarrierMode() {
|
||||||
return this.form.carrierType === '承运商';
|
return this.form.carrierType === '承运商';
|
||||||
},
|
},
|
||||||
|
taskCarrierRequired() {
|
||||||
|
return this.isTaskCarrierRequired(this.form.carrierType);
|
||||||
|
},
|
||||||
|
taskCarrierLabel() {
|
||||||
|
return this.form.carrierType === '网货平台' ? '承运方' : '承运商';
|
||||||
|
},
|
||||||
showRoadEscortFields() {
|
showRoadEscortFields() {
|
||||||
return this.isRoadTransport && !this.isCarrierMode;
|
return this.isRoadTransport && !this.isCarrierMode;
|
||||||
},
|
},
|
||||||
@@ -6503,6 +6564,12 @@ export default {
|
|||||||
dispatchIsCarrierMode() {
|
dispatchIsCarrierMode() {
|
||||||
return this.dispatchItemForm.carrierType === '承运商';
|
return this.dispatchItemForm.carrierType === '承运商';
|
||||||
},
|
},
|
||||||
|
dispatchCarrierRequired() {
|
||||||
|
return this.isDispatchCarrierRequired(this.dispatchItemForm.carrierType);
|
||||||
|
},
|
||||||
|
dispatchCarrierLabel() {
|
||||||
|
return this.dispatchItemForm.carrierType === '网货平台' ? '承运方' : '承运商';
|
||||||
|
},
|
||||||
dispatchStationMode() {
|
dispatchStationMode() {
|
||||||
return ['water', 'rail', 'air'].includes(this.dispatchTransportMode);
|
return ['water', 'rail', 'air'].includes(this.dispatchTransportMode);
|
||||||
},
|
},
|
||||||
@@ -7723,6 +7790,101 @@ export default {
|
|||||||
column.disabled = type !== 'add';
|
column.disabled = type !== 'add';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
syncContractPartyDisabled() {
|
||||||
|
if (!this.isContractConfig) return;
|
||||||
|
const disabled = !this.form?.projectId;
|
||||||
|
['partyA', 'partyB'].forEach(prop => {
|
||||||
|
const column = this.findColumn?.(this.option.column, prop);
|
||||||
|
if (column) column.disabled = disabled;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
clearContractPartyOptions() {
|
||||||
|
this.contractPartyRequestId += 1;
|
||||||
|
this.contractPartyLoading = false;
|
||||||
|
this.contractPartyAOptions = [];
|
||||||
|
this.contractPartyBOptions = [];
|
||||||
|
},
|
||||||
|
contractPartyNames(value, type = '') {
|
||||||
|
const names = [];
|
||||||
|
const append = item => {
|
||||||
|
if (item === undefined || item === null) return;
|
||||||
|
if (Array.isArray(item)) {
|
||||||
|
item.forEach(append);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof item === 'object') {
|
||||||
|
append(
|
||||||
|
item[type === 'carrier' ? 'carrier' : 'customer'] ||
|
||||||
|
item.fullName ||
|
||||||
|
item.shortName ||
|
||||||
|
item.customerName ||
|
||||||
|
item.carrierName ||
|
||||||
|
item.name
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const text = String(item).trim();
|
||||||
|
if (!text) return;
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(text);
|
||||||
|
if (parsed !== item) {
|
||||||
|
append(parsed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 普通名称字符串按项目页面使用的分隔符拆分。
|
||||||
|
}
|
||||||
|
text
|
||||||
|
.split(/[、,,;;\n]/)
|
||||||
|
.map(name => name.trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
.forEach(name => {
|
||||||
|
if (!names.includes(name)) names.push(name);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
append(value);
|
||||||
|
return names;
|
||||||
|
},
|
||||||
|
contractPartyOptionsFromProject(project = {}, type = '') {
|
||||||
|
const names = this.contractPartyNames(
|
||||||
|
[
|
||||||
|
project[type === 'carrier' ? 'carrierJson' : 'customerJson'],
|
||||||
|
project[type === 'carrier' ? 'carrierNames' : 'customerNames'],
|
||||||
|
project[type === 'carrier' ? 'carrierName' : 'customerName'],
|
||||||
|
project[type === 'carrier' ? 'carriers' : 'customers'],
|
||||||
|
],
|
||||||
|
type
|
||||||
|
);
|
||||||
|
return names.map(name => ({ label: name, value: name }));
|
||||||
|
},
|
||||||
|
syncContractPartyOptions(project = {}, preserveCurrent = true) {
|
||||||
|
if (!this.isContractConfig) return;
|
||||||
|
this.contractPartyAOptions = this.contractPartyOptionsFromProject(project, 'customer');
|
||||||
|
this.contractPartyBOptions = this.contractPartyOptionsFromProject(project, 'carrier');
|
||||||
|
if (!preserveCurrent) {
|
||||||
|
this.form.partyA = '';
|
||||||
|
this.form.partyB = '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loadContractPartyOptions(projectId, project = {}, preserveCurrent = true) {
|
||||||
|
if (!this.isContractConfig || !projectId) {
|
||||||
|
this.clearContractPartyOptions();
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
const requestId = ++this.contractPartyRequestId;
|
||||||
|
this.syncContractPartyOptions(project, preserveCurrent);
|
||||||
|
this.contractPartyLoading = true;
|
||||||
|
return getProjectDetail(projectId)
|
||||||
|
.then(res => {
|
||||||
|
if (requestId !== this.contractPartyRequestId) return;
|
||||||
|
const detail = res?.data?.data || {};
|
||||||
|
this.syncContractPartyOptions({ ...project, ...detail }, preserveCurrent);
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
.finally(() => {
|
||||||
|
if (requestId === this.contractPartyRequestId) this.contractPartyLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
syncCustomCreateDialogButtons(type) {
|
syncCustomCreateDialogButtons(type) {
|
||||||
if (
|
if (
|
||||||
!this.config.enableContractCreateActions &&
|
!this.config.enableContractCreateActions &&
|
||||||
@@ -7868,6 +8030,24 @@ export default {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
isDefaultBillingPlan(plan) {
|
||||||
|
const value = plan?.defaultPlan;
|
||||||
|
return value === true || value === 1 || ['true', '1'].includes(String(value).toLowerCase());
|
||||||
|
},
|
||||||
|
validateBillingPlanDefault() {
|
||||||
|
const plans = Array.isArray(this.billingPlanRows) ? this.billingPlanRows : [];
|
||||||
|
if (!plans.length) return true;
|
||||||
|
const defaultCount = plans.filter(plan => this.isDefaultBillingPlan(plan)).length;
|
||||||
|
if (defaultCount === 0) {
|
||||||
|
this.$message.warning('请勾选一个默认计费方案');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (defaultCount > 1) {
|
||||||
|
this.$message.warning('计费方案存在重复默认方案,请仅保留一个默认方案');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
validateSettlementRule(source = this.settlementRuleForm, label = '') {
|
validateSettlementRule(source = this.settlementRuleForm, label = '') {
|
||||||
const rule = this.normalizeSettlementRule(source);
|
const rule = this.normalizeSettlementRule(source);
|
||||||
this.settlementRuleErrors = {};
|
this.settlementRuleErrors = {};
|
||||||
@@ -7944,6 +8124,13 @@ export default {
|
|||||||
submitRow.contractFileJson = JSON.stringify(this.contractFileRows);
|
submitRow.contractFileJson = JSON.stringify(this.contractFileRows);
|
||||||
}
|
}
|
||||||
if (this.config.enableBillingPlan) {
|
if (this.config.enableBillingPlan) {
|
||||||
|
if (
|
||||||
|
this.isContractConfig &&
|
||||||
|
!skipValidation &&
|
||||||
|
!this.validateBillingPlanDefault()
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
submitRow.billingPlanJson = JSON.stringify(this.billingPlanRows);
|
submitRow.billingPlanJson = JSON.stringify(this.billingPlanRows);
|
||||||
}
|
}
|
||||||
if (this.config.enableSettlementRule) {
|
if (this.config.enableSettlementRule) {
|
||||||
@@ -8519,6 +8706,7 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.isContractFormPage) {
|
if (this.isContractFormPage) {
|
||||||
|
this.$router.$avueRouter?.closeTag?.();
|
||||||
this.$router.push('/business/contract-manage');
|
this.$router.push('/business/contract-manage');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -8575,12 +8763,15 @@ export default {
|
|||||||
this.syncCustomCreateDialogButtons(type);
|
this.syncCustomCreateDialogButtons(type);
|
||||||
this.dialogReadonly = type === 'view';
|
this.dialogReadonly = type === 'view';
|
||||||
this.syncContractNoDisabled(type);
|
this.syncContractNoDisabled(type);
|
||||||
|
this.syncContractPartyDisabled();
|
||||||
if (type === 'add') {
|
if (type === 'add') {
|
||||||
this.form = {
|
this.form = {
|
||||||
...(this.config.defaultForm || {}),
|
...(this.config.defaultForm || {}),
|
||||||
};
|
};
|
||||||
|
this.syncContractPartyDisabled();
|
||||||
this.form.taskEntryMode = 'simple';
|
this.form.taskEntryMode = 'simple';
|
||||||
this.selectedProjectId = '';
|
this.selectedProjectId = '';
|
||||||
|
this.clearContractPartyOptions();
|
||||||
this.selectedOrganizationId = '';
|
this.selectedOrganizationId = '';
|
||||||
this.attachmentRows = [];
|
this.attachmentRows = [];
|
||||||
this.selectedAttachmentRows = [];
|
this.selectedAttachmentRows = [];
|
||||||
@@ -8608,6 +8799,9 @@ export default {
|
|||||||
this.form.feeGenerationMode = this.form.feeGenerationMode || 'system';
|
this.form.feeGenerationMode = this.form.feeGenerationMode || 'system';
|
||||||
this.changeRecordRows = [];
|
this.changeRecordRows = [];
|
||||||
this.applyCurrentUserHandler();
|
this.applyCurrentUserHandler();
|
||||||
|
this.taskCarrierRequestId += 1;
|
||||||
|
this.taskCarrierOptions = [];
|
||||||
|
this.taskCarrierLoading = false;
|
||||||
this.initTaskInfoForm();
|
this.initTaskInfoForm();
|
||||||
this.initTransportPlanFormRows();
|
this.initTransportPlanFormRows();
|
||||||
this.syncContractPeriod(false);
|
this.syncContractPeriod(false);
|
||||||
@@ -8644,6 +8838,14 @@ export default {
|
|||||||
this.suppressTransportTypeClear = false;
|
this.suppressTransportTypeClear = false;
|
||||||
});
|
});
|
||||||
this.selectedProjectId = this.form.projectId || '';
|
this.selectedProjectId = this.form.projectId || '';
|
||||||
|
this.syncContractPartyDisabled();
|
||||||
|
this.loadContractPartyOptions(this.form.projectId, {
|
||||||
|
projectName: this.form.projectName,
|
||||||
|
customerNames: this.form.customerNames,
|
||||||
|
carrierNames: this.form.carrierNames,
|
||||||
|
customerJson: this.form.customerJson,
|
||||||
|
carrierJson: this.form.carrierJson,
|
||||||
|
});
|
||||||
this.loadProjectProcessConfigState();
|
this.loadProjectProcessConfigState();
|
||||||
this.selectedOrganizationId = this.form.organizationId || '';
|
this.selectedOrganizationId = this.form.organizationId || '';
|
||||||
this.attachmentRows = this.parseJsonArray(this.form.attachmentsJson);
|
this.attachmentRows = this.parseJsonArray(this.form.attachmentsJson);
|
||||||
@@ -8797,6 +8999,12 @@ export default {
|
|||||||
this.form.projectFundLimit = '';
|
this.form.projectFundLimit = '';
|
||||||
this.form.usedFundLimit = 0;
|
this.form.usedFundLimit = 0;
|
||||||
this.form.remainingFundLimit = 0;
|
this.form.remainingFundLimit = 0;
|
||||||
|
if (this.isContractConfig) {
|
||||||
|
this.form.partyA = '';
|
||||||
|
this.form.partyB = '';
|
||||||
|
}
|
||||||
|
this.clearContractPartyOptions();
|
||||||
|
this.syncContractPartyDisabled();
|
||||||
if (this.contractSelectEnabled) {
|
if (this.contractSelectEnabled) {
|
||||||
this.form.contractId = '';
|
this.form.contractId = '';
|
||||||
this.form.contractName = '';
|
this.form.contractName = '';
|
||||||
@@ -8807,6 +9015,13 @@ export default {
|
|||||||
this.shippingPlanOptions = [];
|
this.shippingPlanOptions = [];
|
||||||
}
|
}
|
||||||
this.hasProjectProcessConfig = false;
|
this.hasProjectProcessConfig = false;
|
||||||
|
if (this.isWaybillDetailLayout) {
|
||||||
|
this.taskCarrierRequestId += 1;
|
||||||
|
this.taskCarrierOptions = [];
|
||||||
|
this.taskCarrierLoading = false;
|
||||||
|
this.form.carrierName = '';
|
||||||
|
this.form.carrierId = '';
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.form.projectId = project.id;
|
this.form.projectId = project.id;
|
||||||
@@ -8816,6 +9031,17 @@ export default {
|
|||||||
this.form.projectFundLimit = project.fundLimit || project.projectFundLimit || 0;
|
this.form.projectFundLimit = project.fundLimit || project.projectFundLimit || 0;
|
||||||
this.form.usedFundLimit = 0;
|
this.form.usedFundLimit = 0;
|
||||||
this.form.remainingFundLimit = this.calculateRemainingFundLimit();
|
this.form.remainingFundLimit = this.calculateRemainingFundLimit();
|
||||||
|
if (this.isWaybillDetailLayout) {
|
||||||
|
this.form.carrierName = '';
|
||||||
|
this.form.carrierId = '';
|
||||||
|
this.loadTaskCarrierOptions(project);
|
||||||
|
}
|
||||||
|
if (this.isContractConfig) {
|
||||||
|
this.form.partyA = '';
|
||||||
|
this.form.partyB = '';
|
||||||
|
this.loadContractPartyOptions(project.id, project, false);
|
||||||
|
}
|
||||||
|
this.syncContractPartyDisabled();
|
||||||
if (this.contractSelectEnabled || this.config.enableTransportPlanForm) {
|
if (this.contractSelectEnabled || this.config.enableTransportPlanForm) {
|
||||||
this.form.customerName =
|
this.form.customerName =
|
||||||
project.customerName ||
|
project.customerName ||
|
||||||
@@ -8852,6 +9078,7 @@ export default {
|
|||||||
return getContractList(1, 9999, {
|
return getContractList(1, 9999, {
|
||||||
projectId: this.form.projectId,
|
projectId: this.form.projectId,
|
||||||
projectName: this.form.projectName,
|
projectName: this.form.projectName,
|
||||||
|
...(this.config.contractQueryParams || {}),
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
this.contractOptions = extractRecords(res);
|
this.contractOptions = extractRecords(res);
|
||||||
@@ -9122,6 +9349,9 @@ export default {
|
|||||||
if (this.isTaskFullMode) {
|
if (this.isTaskFullMode) {
|
||||||
this.initTaskFullCargoRows(goodsRows);
|
this.initTaskFullCargoRows(goodsRows);
|
||||||
}
|
}
|
||||||
|
if (this.isWaybillDetailLayout && this.form.projectId) {
|
||||||
|
this.loadTaskCarrierOptions();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handleTaskEntryModeChange(value) {
|
handleTaskEntryModeChange(value) {
|
||||||
if (
|
if (
|
||||||
@@ -9177,14 +9407,45 @@ export default {
|
|||||||
this.form.trailerVehicleNo = '';
|
this.form.trailerVehicleNo = '';
|
||||||
this.form.escortName = '';
|
this.form.escortName = '';
|
||||||
this.form.escortPhone = '';
|
this.form.escortPhone = '';
|
||||||
} else {
|
} else if (!this.isTaskCarrierRequired(nextValue)) {
|
||||||
this.form.carrierName = '';
|
this.form.carrierName = '';
|
||||||
this.form.carrierId = '';
|
this.form.carrierId = '';
|
||||||
}
|
}
|
||||||
this.form.carrierType = nextValue;
|
this.form.carrierType = nextValue;
|
||||||
},
|
},
|
||||||
loadTaskCarrierOptions() {
|
isTaskCarrierRequired(carrierType) {
|
||||||
|
return ['承运商', '网货平台'].includes(String(carrierType || '').trim());
|
||||||
|
},
|
||||||
|
loadTaskCarrierOptions(project = {}) {
|
||||||
if (!this.taskInfoFormEnabled || this.taskCarrierLoading) return Promise.resolve([]);
|
if (!this.taskInfoFormEnabled || this.taskCarrierLoading) return Promise.resolve([]);
|
||||||
|
if (this.isWaybillDetailLayout) {
|
||||||
|
const projectId = project.id || project.projectId || this.form.projectId;
|
||||||
|
const requestId = ++this.taskCarrierRequestId;
|
||||||
|
const currentProject = this.projectOptions.find(
|
||||||
|
item => String(item.id) === String(projectId)
|
||||||
|
);
|
||||||
|
this.taskCarrierOptions = this.getProjectCarrierOptions({
|
||||||
|
...currentProject,
|
||||||
|
...project,
|
||||||
|
});
|
||||||
|
if (!projectId) return Promise.resolve(this.taskCarrierOptions);
|
||||||
|
this.taskCarrierLoading = true;
|
||||||
|
return getProjectDetail(projectId)
|
||||||
|
.then(res => {
|
||||||
|
if (requestId !== this.taskCarrierRequestId) return this.taskCarrierOptions;
|
||||||
|
const detail = res?.data?.data || {};
|
||||||
|
this.taskCarrierOptions = this.getProjectCarrierOptions({
|
||||||
|
...currentProject,
|
||||||
|
...project,
|
||||||
|
...detail,
|
||||||
|
});
|
||||||
|
return this.taskCarrierOptions;
|
||||||
|
})
|
||||||
|
.catch(() => this.taskCarrierOptions)
|
||||||
|
.finally(() => {
|
||||||
|
if (requestId === this.taskCarrierRequestId) this.taskCarrierLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
this.taskCarrierLoading = true;
|
this.taskCarrierLoading = true;
|
||||||
return getCarrierCustomerList(1, 9999, { customerType: '承运商', status: 1 })
|
return getCarrierCustomerList(1, 9999, { customerType: '承运商', status: 1 })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
@@ -9540,8 +9801,8 @@ export default {
|
|||||||
['carrierType', '承运类型'],
|
['carrierType', '承运类型'],
|
||||||
['vehicleNo', this.transportVehicleNoLabel],
|
['vehicleNo', this.transportVehicleNoLabel],
|
||||||
];
|
];
|
||||||
if (row.carrierType === '承运商') {
|
if (this.isTaskCarrierRequired(row.carrierType)) {
|
||||||
requiredFields.push(['carrierName', '承运商']);
|
requiredFields.push(['carrierName', row.carrierType === '网货平台' ? '承运方' : '承运商']);
|
||||||
}
|
}
|
||||||
if (this.isRoadTransport && row.carrierType === '自运') {
|
if (this.isRoadTransport && row.carrierType === '自运') {
|
||||||
requiredFields.push(['driverName', '司机']);
|
requiredFields.push(['driverName', '司机']);
|
||||||
@@ -11890,7 +12151,11 @@ export default {
|
|||||||
this.transportPlanImportContractOptions = [];
|
this.transportPlanImportContractOptions = [];
|
||||||
if (!projectId) return;
|
if (!projectId) return;
|
||||||
this.transportPlanImportContractLoading = true;
|
this.transportPlanImportContractLoading = true;
|
||||||
getContractList(1, 9999, { projectId, projectName: project?.projectName })
|
getContractList(1, 9999, {
|
||||||
|
projectId,
|
||||||
|
projectName: project?.projectName,
|
||||||
|
...(this.config.contractQueryParams || {}),
|
||||||
|
})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
this.transportPlanImportContractOptions = extractRecords(res);
|
this.transportPlanImportContractOptions = extractRecords(res);
|
||||||
const contract = this.transportPlanImportContractOptions[0];
|
const contract = this.transportPlanImportContractOptions[0];
|
||||||
@@ -12264,6 +12529,8 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.dispatchRow = { ...row };
|
this.dispatchRow = { ...row };
|
||||||
|
this.dispatchCarrierOptions = [];
|
||||||
|
this.dispatchCarrierRequestId += 1;
|
||||||
this.dispatchBox = true;
|
this.dispatchBox = true;
|
||||||
this.dispatchLoading = true;
|
this.dispatchLoading = true;
|
||||||
this.dispatchRows = [];
|
this.dispatchRows = [];
|
||||||
@@ -12280,6 +12547,7 @@ export default {
|
|||||||
};
|
};
|
||||||
this.dispatchRow = detail;
|
this.dispatchRow = detail;
|
||||||
this.dispatchRows = this.buildDispatchRows(detail);
|
this.dispatchRows = this.buildDispatchRows(detail);
|
||||||
|
this.loadDispatchCarrierOptions(detail);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.dispatchLoading = false;
|
this.dispatchLoading = false;
|
||||||
@@ -12313,6 +12581,9 @@ export default {
|
|||||||
this.dispatchRows = [];
|
this.dispatchRows = [];
|
||||||
this.dispatchLoading = false;
|
this.dispatchLoading = false;
|
||||||
this.dispatchSaving = '';
|
this.dispatchSaving = '';
|
||||||
|
this.dispatchCarrierRequestId += 1;
|
||||||
|
this.dispatchCarrierOptions = [];
|
||||||
|
this.dispatchCarrierLoading = false;
|
||||||
this.dispatchItemBox = false;
|
this.dispatchItemBox = false;
|
||||||
this.dispatchItemIndex = -1;
|
this.dispatchItemIndex = -1;
|
||||||
this.dispatchItemForm = defaultDispatchRow();
|
this.dispatchItemForm = defaultDispatchRow();
|
||||||
@@ -12911,30 +13182,72 @@ export default {
|
|||||||
this.dispatchItemForm.trailerVehicleNo = '';
|
this.dispatchItemForm.trailerVehicleNo = '';
|
||||||
this.dispatchItemForm.escortName = '';
|
this.dispatchItemForm.escortName = '';
|
||||||
this.dispatchItemForm.escortPhone = '';
|
this.dispatchItemForm.escortPhone = '';
|
||||||
} else {
|
} else if (!this.isDispatchCarrierRequired(nextValue)) {
|
||||||
this.dispatchItemForm.carrierId = '';
|
this.dispatchItemForm.carrierId = '';
|
||||||
this.dispatchItemForm.carrierName = '';
|
this.dispatchItemForm.carrierName = '';
|
||||||
}
|
}
|
||||||
this.dispatchItemForm.carrierType = nextValue;
|
this.dispatchItemForm.carrierType = nextValue;
|
||||||
},
|
},
|
||||||
loadDispatchCarrierOptions() {
|
isDispatchCarrierRequired(carrierType) {
|
||||||
if (this.taskCarrierLoading) return Promise.resolve([]);
|
return ['承运商', '网货平台'].includes(String(carrierType || '').trim());
|
||||||
this.taskCarrierLoading = true;
|
},
|
||||||
return getCarrierCustomerList(1, 9999, { customerType: '承运商', status: 1 })
|
getProjectCarrierOptions(project = {}) {
|
||||||
|
const rows = this.parseJsonArray(project.carrierJson);
|
||||||
|
const names = String(project.carrierNames || '')
|
||||||
|
.split(/[、,,;;\n]/)
|
||||||
|
.map(item => item.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
const options = [];
|
||||||
|
const append = item => {
|
||||||
|
if (!item) return;
|
||||||
|
const id = item.id || item.carrierId || item.customerId || '';
|
||||||
|
const label =
|
||||||
|
(typeof item === 'string' ? item : '') ||
|
||||||
|
item.carrier ||
|
||||||
|
item.carrierName ||
|
||||||
|
item.fullName ||
|
||||||
|
item.shortName ||
|
||||||
|
item.customerName ||
|
||||||
|
item.name ||
|
||||||
|
'';
|
||||||
|
const value = String(label).trim();
|
||||||
|
if (!value || options.some(option => option.value === value)) return;
|
||||||
|
options.push({ id, carrierName: value, fullName: value, value });
|
||||||
|
};
|
||||||
|
rows.forEach(append);
|
||||||
|
names.forEach(append);
|
||||||
|
return options;
|
||||||
|
},
|
||||||
|
loadDispatchCarrierOptions(plan = this.dispatchRow) {
|
||||||
|
if (this.dispatchCarrierLoading) return Promise.resolve(this.dispatchCarrierOptions);
|
||||||
|
const projectId = plan?.projectId;
|
||||||
|
const requestId = ++this.dispatchCarrierRequestId;
|
||||||
|
const project = this.projectOptions.find(
|
||||||
|
item => String(item.id) === String(projectId)
|
||||||
|
);
|
||||||
|
this.dispatchCarrierOptions = this.getProjectCarrierOptions({ ...project, ...plan });
|
||||||
|
if (!projectId) return Promise.resolve(this.dispatchCarrierOptions);
|
||||||
|
this.dispatchCarrierLoading = true;
|
||||||
|
return getProjectDetail(projectId)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
this.taskCarrierOptions = extractRecords(res);
|
if (requestId !== this.dispatchCarrierRequestId) return this.dispatchCarrierOptions;
|
||||||
return this.taskCarrierOptions;
|
const detail = res?.data?.data || {};
|
||||||
|
this.dispatchCarrierOptions = this.getProjectCarrierOptions({
|
||||||
|
...project,
|
||||||
|
...plan,
|
||||||
|
...detail,
|
||||||
|
});
|
||||||
|
return this.dispatchCarrierOptions;
|
||||||
})
|
})
|
||||||
|
.catch(() => this.dispatchCarrierOptions)
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
this.taskCarrierLoading = false;
|
if (requestId === this.dispatchCarrierRequestId) {
|
||||||
|
this.dispatchCarrierLoading = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleDispatchCarrierChange(value) {
|
handleDispatchCarrierChange(value) {
|
||||||
const carrier = this.taskCarrierOptions.find(item =>
|
const carrier = this.dispatchCarrierOptions.find(item => item.value === String(value || ''));
|
||||||
[item.customerName, item.carrierName, item.fullName, item.name].some(
|
|
||||||
name => String(name || '') === String(value || '')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
this.dispatchItemForm.carrierId = carrier?.id || '';
|
this.dispatchItemForm.carrierId = carrier?.id || '';
|
||||||
this.dispatchItemForm.carrierName = value || '';
|
this.dispatchItemForm.carrierName = value || '';
|
||||||
},
|
},
|
||||||
@@ -13140,8 +13453,8 @@ export default {
|
|||||||
: '车牌号',
|
: '车牌号',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
if (row.carrierType === '承运商') {
|
if (this.isDispatchCarrierRequired(row.carrierType)) {
|
||||||
requiredFields.push(['carrierName', '承运商']);
|
requiredFields.push(['carrierName', row.carrierType === '网货平台' ? '承运方' : '承运商']);
|
||||||
}
|
}
|
||||||
const fullEntry = row.taskEntryMode === 'full';
|
const fullEntry = row.taskEntryMode === 'full';
|
||||||
const roadTransport = this.resolveTransportMode(row.transportType) === 'road';
|
const roadTransport = this.resolveTransportMode(row.transportType) === 'road';
|
||||||
|
|||||||
@@ -57,6 +57,7 @@
|
|||||||
v-if="hasPermission('formal_settlement_payment')"
|
v-if="hasPermission('formal_settlement_payment')"
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
|
disabled
|
||||||
@click="openPaymentDialog"
|
@click="openPaymentDialog"
|
||||||
>付款申请</el-button
|
>付款申请</el-button
|
||||||
>
|
>
|
||||||
@@ -64,6 +65,7 @@
|
|||||||
v-if="hasPermission('formal_settlement_sync')"
|
v-if="hasPermission('formal_settlement_sync')"
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
|
disabled
|
||||||
@click="handleSync"
|
@click="handleSync"
|
||||||
>同步金蝶</el-button
|
>同步金蝶</el-button
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
v-if="hasPermission('pre_settlement_advance')"
|
v-if="hasPermission('pre_settlement_advance')"
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
|
disabled
|
||||||
@click="openAdvanceDialog"
|
@click="openAdvanceDialog"
|
||||||
>
|
>
|
||||||
预付申请
|
预付申请
|
||||||
@@ -61,6 +62,7 @@
|
|||||||
v-if="hasPermission('pre_settlement_formal')"
|
v-if="hasPermission('pre_settlement_formal')"
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
|
disabled
|
||||||
@click="handleFormalSettlement"
|
@click="handleFormalSettlement"
|
||||||
>
|
>
|
||||||
尾款结算
|
尾款结算
|
||||||
|
|||||||
@@ -680,7 +680,12 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
async loadContracts() {
|
async loadContracts() {
|
||||||
const res = await getContractList(1, 999, { approvalStatus: 'approved' });
|
const contractCategory =
|
||||||
|
this.settlementType === 'payable' ? '承运商合同' : '客户合同';
|
||||||
|
const res = await getContractList(1, 999, {
|
||||||
|
approvalStatus: 'approved',
|
||||||
|
contractCategory,
|
||||||
|
});
|
||||||
const data = this.unwrapPage(res);
|
const data = this.unwrapPage(res);
|
||||||
this.contractOptions = data.records || [];
|
this.contractOptions = data.records || [];
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -31,10 +31,6 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="reconciliation-page__table-panel">
|
<section class="reconciliation-page__table-panel">
|
||||||
<el-tabs v-model="settlementType" @tab-change="handleTabChange">
|
|
||||||
<el-tab-pane label="应付" name="payable" />
|
|
||||||
<el-tab-pane label="应收" name="receivable" />
|
|
||||||
</el-tabs>
|
|
||||||
<div class="reconciliation-page__toolbar">
|
<div class="reconciliation-page__toolbar">
|
||||||
<div>
|
<div>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -51,6 +47,15 @@
|
|||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<el-tabs
|
||||||
|
v-model="settlementType"
|
||||||
|
class="reconciliation-page__settlement-tabs"
|
||||||
|
type="card"
|
||||||
|
@tab-change="handleTabChange"
|
||||||
|
>
|
||||||
|
<el-tab-pane label="应付" name="payable" />
|
||||||
|
<el-tab-pane label="应收" name="receivable" />
|
||||||
|
</el-tabs>
|
||||||
<el-table v-loading="loading" :data="rows" border @selection-change="selection = $event">
|
<el-table v-loading="loading" :data="rows" border @selection-change="selection = $event">
|
||||||
<el-table-column type="selection" width="52" fixed="left" align="center" />
|
<el-table-column type="selection" width="52" fixed="left" align="center" />
|
||||||
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
<el-table-column type="index" label="序号" width="64" fixed="left" align="center" />
|
||||||
@@ -314,6 +319,12 @@ export default {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
.reconciliation-page__settlement-tabs {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.reconciliation-page__settlement-tabs :deep(.el-tabs__header) {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
.reconciliation-page__links {
|
.reconciliation-page__links {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
Reference in New Issue
Block a user