This commit is contained in:
2026-08-26 23:18:14 +08:00
parent 9d512ebad4
commit b36aefc7c4
43 changed files with 991 additions and 383 deletions
@@ -8651,15 +8651,18 @@ export default {
handleTaskDriverSelect(target, item = {}) {
const value = item.driverName || item.name || '';
const driverPhone = item.mobile || item.phone || item.driverPhone || '';
const drivingVehicle = String(item.drivingVehicle || '').trim();
if (target === 'dispatch') {
this.dispatchItemForm.driverId = item.id || '';
this.dispatchItemForm.driverName = value;
if (driverPhone) this.dispatchItemForm.driverPhone = driverPhone;
if (drivingVehicle) this.dispatchItemForm.vehicleNo = drivingVehicle;
return;
}
this.form.driverId = item.id || '';
this.form.driverName = value;
if (driverPhone) this.form.driverPhone = driverPhone;
if (drivingVehicle) this.form.vehicleNo = drivingVehicle;
},
handleTaskDriverChange(value) {
const driver = this.taskDriverOptions.find(item =>
@@ -8670,6 +8673,9 @@ export default {
if (driver) {
this.form.driverPhone =
driver.mobile || driver.phone || driver.driverPhone || this.form.driverPhone || '';
if (String(driver.drivingVehicle || '').trim()) {
this.form.vehicleNo = String(driver.drivingVehicle).trim();
}
}
},
getTaskCargoTypeOptionsKey(path = []) {
@@ -12348,6 +12354,9 @@ export default {
driver.driverPhone ||
this.dispatchItemForm.driverPhone ||
'';
if (String(driver.drivingVehicle || '').trim()) {
this.dispatchItemForm.vehicleNo = String(driver.drivingVehicle).trim();
}
}
},
getDispatchCargoRowOptions(row = {}) {
@@ -543,7 +543,12 @@ export default {
driverOptionKey(item) { return item.id || item.driverId || this.driverOptionLabel(item) || item.mobile; },
handleDriverChange(route, value) {
const driver = this.driverOptions.find(item => this.driverOptionLabel(item) === value);
if (driver) route.driverPhone = driver.mobile || driver.driverPhone || driver.phone || '';
if (driver) {
route.driverPhone = driver.mobile || driver.driverPhone || driver.phone || '';
if (String(driver.drivingVehicle || '').trim()) {
route.vehicleNo = String(driver.drivingVehicle).trim();
}
}
},
async loadCarrierOptions() {
this.carrierLoading = true;
@@ -577,6 +582,8 @@ export default {
route.driverName = this.driverOptionLabel(item);
route.driverId = item.id || item.driverId || '';
route.driverPhone = item.mobile || item.driverPhone || item.phone || route.driverPhone || '';
const drivingVehicle = String(item.drivingVehicle || '').trim();
if (drivingVehicle) route.vehicleNo = drivingVehicle;
},
setDriverInput(segmentNo, element) {
if (element) this.driverInputs[segmentNo] = element;
+52 -28
View File
@@ -1,26 +1,32 @@
<template>
<basic-container class="contract-change-page">
<el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-width="auto">
<section class="change-section">
<el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-width="auto" class="contract-change-form">
<section class="change-section contract-basic-section">
<div class="dialog-section-title">基本信息</div>
<el-row :gutter="28">
<el-col :span="24"><el-form-item label="变更类型"><el-radio-group v-model="form.changeType"><el-radio label="合同信息变更" /><el-radio label="终止合同" /></el-radio-group></el-form-item></el-col>
<el-col :span="6"><el-form-item label="合同编号"><el-input v-model="form.contractNo" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="合同名称" prop="contractName"><el-input v-model="form.contractName" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="合同类型"><el-select v-model="form.contractCategory" disabled><el-option label="客户合同" value="客户合同" /><el-option label="承运商合同" value="承运商合同" /></el-select></el-form-item></el-col>
<el-col :span="6"><el-form-item label="甲方"><el-input v-model="form.partyA" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="乙方"><el-input v-model="form.partyB" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="所属项目"><el-input v-model="form.projectName" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="合同期限"><el-date-picker v-model="period" type="daterange" value-format="YYYY-MM-DD" range-separator="至" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="所属组织"><el-input v-model="form.organizationName" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="签订日期"><el-date-picker v-model="form.signDate" type="date" value-format="YYYY-MM-DD" disabled /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="合同格式"><el-select v-model="form.contractFormat"><el-option label="电子合同" value="电子合同" /><el-option label="纸质合同" value="纸质合同" /></el-select></el-form-item></el-col>
<el-col :span="6"><el-form-item label="结算方式"><el-input v-model="form.settlementMode" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="是否需要加盖法人章"><el-select v-model="form.legalSealFlag"><el-option label="是" :value="1" /><el-option label="否" :value="0" /></el-select></el-form-item></el-col>
<el-col :span="6"><el-form-item label="一式(份)"><div class="inline-field"><el-input-number v-model="form.copyCount" :min="1" controls-position="right" /></div></el-form-item></el-col>
<el-col :span="6"><el-form-item label="回款账期(天)"><el-input-number v-model="form.paymentDays" :min="0" controls-position="right" /></el-form-item></el-col>
<el-col :span="24"><el-form-item label="备注"><el-input v-model="form.remark" type="textarea" maxlength="2000" show-word-limit /></el-form-item></el-col>
</el-row>
<div class="contract-basic-section__grid">
<el-form-item label="变更类型" class="contract-basic-section__change-type"><el-radio-group v-model="form.changeType"><el-radio label="合同信息变更" /><el-radio label="终止合同" /></el-radio-group></el-form-item>
<el-form-item label="合同编号"><el-input v-model="form.contractNo" disabled /></el-form-item>
<el-form-item label="合同名称" prop="contractName"><el-input v-model="form.contractName" /></el-form-item>
<el-form-item label="合同类型"><el-select v-model="form.contractCategory" disabled><el-option label="客户合同" value="客户合同" /><el-option label="承运商合同" value="承运商合同" /></el-select></el-form-item>
<el-form-item label="甲方"><el-input v-model="form.partyA" disabled /></el-form-item>
<el-form-item label="乙方"><el-input v-model="form.partyB" disabled /></el-form-item>
<el-form-item label="所属项目"><el-input v-model="form.projectName" disabled /></el-form-item>
<el-form-item label="合同期限">
<div class="contract-basic-section__date-range">
<el-date-picker v-model="period[0]" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="YYYY-MM-DD" />
<span></span>
<el-date-picker v-model="period[1]" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="YYYY-MM-DD" />
</div>
</el-form-item>
<el-form-item label="所属组织"><el-input v-model="form.organizationName" disabled /></el-form-item>
<el-form-item label="签订日期"><el-date-picker v-model="form.signDate" type="date" value-format="YYYY-MM-DD" disabled /></el-form-item>
<el-form-item label="合同格式"><el-select v-model="form.contractFormat"><el-option label="电子合同" value="电子合同" /><el-option label="纸质合同" value="纸质合同" /></el-select></el-form-item>
<el-form-item label="结算方式"><el-input v-model="form.settlementMode" /></el-form-item>
<el-form-item label="是否需要加盖法人章"><el-select v-model="form.legalSealFlag"><el-option label="是" :value="1" /><el-option label="否" :value="0" /></el-select></el-form-item>
<el-form-item label="一式(份)"><el-input v-model="form.copyCount" inputmode="numeric" maxlength="9" placeholder="请输入" @input="value => positiveIntegerInput('copyCount', value)" /></el-form-item>
<el-form-item label="回款账期(天)"><el-input v-model="form.paymentDays" inputmode="numeric" maxlength="9" placeholder="请输入" @input="value => positiveIntegerInput('paymentDays', value)" /></el-form-item>
</div>
<el-form-item label="备注" class="contract-basic-section__remark"><el-input v-model="form.remark" type="textarea" :rows="2" maxlength="2000" show-word-limit placeholder="请输入备注" /></el-form-item>
</section>
<section class="change-section">
@@ -103,10 +109,10 @@ const viewerPlugins = [
textPlugin(),
fallbackPlugin(),
];
const normalizeOptionalInteger = value => {
if (value === undefined || value === null || value === '' || Number(value) < 0) return null;
const normalizeOptionalPositiveInteger = value => {
if (value === undefined || value === null || value === '') return null;
const number = Number(value);
return Number.isFinite(number) ? Math.trunc(number) : null;
return Number.isInteger(number) && number > 0 ? number : null;
};
export default {
@@ -116,9 +122,10 @@ export default {
mounted() { this.load(); },
watch: { settlementConfigTab(tab, oldTab) { if (tab === oldTab) return; if (oldTab === 'pre') this.preSettlementConfig = { ...this.settlementRule }; else this.formalSettlementConfig = { ...this.settlementRule }; this.settlementRule = { ...(tab === 'pre' ? this.preSettlementConfig : this.formalSettlementConfig) }; } },
methods: {
async load() { const id = this.$route.query.id; if (!id) return; const res = await api.getDetail(id); const data = res.data?.data || res.data || {}; this.form = { ...data, copyCount: normalizeOptionalInteger(data.copyCount), paymentDays: normalizeOptionalInteger(data.paymentDays), changeType: '合同信息变更' }; this.period = data.startDate && data.endDate ? [data.startDate, data.endDate] : []; this.plans = this.parse(data.billingPlanJson); this.attachments = this.parse(data.attachmentsJson); this.contractFileRows = this.parse(data.contractFileJson); const rules = this.parseObject(data.settlementRuleJson); const pre = this.parseObject(data.preSettlementConfigJson); const formal = this.parseObject(data.formalSettlementConfigJson); const legacy = Object.keys(rules).some(key => !['preSettlementConfig', 'formalSettlementConfig'].includes(key)) ? rules : {}; this.preSettlementConfig = rules.preSettlementConfig || (Object.keys(pre).length ? pre : legacy); this.formalSettlementConfig = rules.formalSettlementConfig || (Object.keys(formal).length ? formal : legacy); this.settlementRule = { ...this.preSettlementConfig }; this.feeGenerationMode = data.feeGenerationMode || (Number(data.billingEnabled) === 0 ? 'manual' : 'system'); this.paymentRatioRows = this.parse(data.paymentRatioJson); },
async load() { const id = this.$route.query.id; if (!id) return; const res = await api.getDetail(id); const data = res.data?.data || res.data || {}; this.form = { ...data, copyCount: normalizeOptionalPositiveInteger(data.copyCount), paymentDays: normalizeOptionalPositiveInteger(data.paymentDays), changeType: '合同信息变更' }; this.period = data.startDate && data.endDate ? [data.startDate, data.endDate] : []; this.plans = this.parse(data.billingPlanJson); this.attachments = this.parse(data.attachmentsJson); this.contractFileRows = this.parse(data.contractFileJson); const rules = this.parseObject(data.settlementRuleJson); const pre = this.parseObject(data.preSettlementConfigJson); const formal = this.parseObject(data.formalSettlementConfigJson); const legacy = Object.keys(rules).some(key => !['preSettlementConfig', 'formalSettlementConfig'].includes(key)) ? rules : {}; this.preSettlementConfig = rules.preSettlementConfig || (Object.keys(pre).length ? pre : legacy); this.formalSettlementConfig = rules.formalSettlementConfig || (Object.keys(formal).length ? formal : legacy); this.settlementRule = { ...this.preSettlementConfig }; this.feeGenerationMode = data.feeGenerationMode || (Number(data.billingEnabled) === 0 ? 'manual' : 'system'); this.paymentRatioRows = this.parse(data.paymentRatioJson); },
parse(value) { try { const result = JSON.parse(value || '[]'); return Array.isArray(result) ? result : []; } catch { return []; } },
parseObject(value) { try { return { autoGenerate: 1, settlementType: '月结', billCycleType: '固定截单日', billCutoffDay: 25, cycleDays: 15, ...(JSON.parse(value || '{}') || {}) }; } catch { return { autoGenerate: 1, settlementType: '月结', billCycleType: '固定截单日', billCutoffDay: 25, cycleDays: 15 }; } },
positiveIntegerInput(prop, value) { this.form[prop] = String(value ?? '').replace(/\D/g, '').replace(/^0+/, ''); },
addPlan() { this.planEditorIndex = -1; this.planEditor = { planName: `计费方案${this.plans.length + 1}`, defaultPlan: !this.plans.length, remark: '', rules: [{}] }; this.planDialogVisible = true; },
editPlan(row, index) { this.planEditorIndex = index; this.planEditor = JSON.parse(JSON.stringify(row)); this.planDialogVisible = true; },
toggleDefaultPlan(value) { if (value) this.plans.forEach(item => { item.defaultPlan = false; }); },
@@ -139,21 +146,36 @@ export default {
formatFileSize(value) { const size = Number(value || 0); return size > 1024 * 1024 ? `${(size / 1024 / 1024).toFixed(2)}MB` : `${Math.max(1, Math.ceil(size / 1024))}KB`; },
handleChangeMaterial(event) { if (event.raw) this.changeMaterials.push(event.raw); },
addPaymentRatioRow() { this.paymentRatioRows.push({ paymentTerm: `${this.paymentRatioRows.length + 1}`, ratioLimit: '', remark: '' }); },
async submit() { await this.$refs.formRef.validate(); const total = this.paymentRatioRows.reduce((sum, row) => sum + Number(row.ratioLimit || 0), 0); if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) { this.$message.warning('付款比例上限合计必须等于100%'); return; } const settlementRule = { preSettlementConfig: this.preSettlementConfig, formalSettlementConfig: this.formalSettlementConfig }; await api.submitChange({ ...this.form, copyCount: normalizeOptionalInteger(this.form.copyCount), paymentDays: normalizeOptionalInteger(this.form.paymentDays), startDate: this.period[0], endDate: this.period[1], feeGenerationMode: this.feeGenerationMode, billingEnabled: this.feeGenerationMode === 'system' ? 1 : 0, billingPlanJson: JSON.stringify(this.plans), settlementRuleJson: JSON.stringify(settlementRule), preSettlementConfigJson: JSON.stringify(this.preSettlementConfig), formalSettlementConfigJson: JSON.stringify(this.formalSettlementConfig), paymentRatioJson: JSON.stringify(this.paymentRatioRows), contractFileJson: JSON.stringify(this.contractFileRows), attachmentsJson: JSON.stringify(this.attachments), changeContent: this.form.changeReason, changeReason: this.form.changeReason }); this.$message.success('变更已提交'); this.$router.back(); },
async submit() { await this.$refs.formRef.validate(); const total = this.paymentRatioRows.reduce((sum, row) => sum + Number(row.ratioLimit || 0), 0); if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) { this.$message.warning('付款比例上限合计必须等于100%'); return; } const settlementRule = { preSettlementConfig: this.preSettlementConfig, formalSettlementConfig: this.formalSettlementConfig }; await api.submitChange({ ...this.form, copyCount: normalizeOptionalPositiveInteger(this.form.copyCount), paymentDays: normalizeOptionalPositiveInteger(this.form.paymentDays), startDate: this.period[0], endDate: this.period[1], feeGenerationMode: this.feeGenerationMode, billingEnabled: this.feeGenerationMode === 'system' ? 1 : 0, billingPlanJson: JSON.stringify(this.plans), settlementRuleJson: JSON.stringify(settlementRule), preSettlementConfigJson: JSON.stringify(this.preSettlementConfig), formalSettlementConfigJson: JSON.stringify(this.formalSettlementConfig), paymentRatioJson: JSON.stringify(this.paymentRatioRows), contractFileJson: JSON.stringify(this.contractFileRows), attachmentsJson: JSON.stringify(this.attachments), changeContent: this.form.changeReason, changeReason: this.form.changeReason }); this.$message.success('变更已提交'); this.$router.back(); },
},
};
</script>
<style scoped>
.contract-change-page { min-height: 100%; background: #fff; }
.change-section { padding: 20px 24px; border-bottom: 1px solid #eff1f7; }
.contract-change-page { min-height: 100%; background: #f5f6fa; }
.contract-change-page :deep(.basic-container__card) { border: 0; background: transparent; box-shadow: none; }
.contract-change-form { background: #f5f6fa; }
.change-section { padding: 20px 24px; background: #fff; border-bottom: 1px solid #eff1f7; }
.contract-basic-section { margin-bottom: 12px; padding: 14px 16px 16px; overflow: hidden; background: #fff; border-bottom: 0; border-radius: 6px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); }
.contract-basic-section > .dialog-section-title { margin-bottom: 20px; color: #303133; }
.contract-basic-section__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 48px; }
.contract-basic-section__change-type { grid-column: 1 / -1; }
.contract-basic-section__remark { width: 100%; margin-bottom: 0 !important; }
.contract-basic-section__date-range { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px; width: 360px; max-width: 100%; }
.contract-basic-section__date-range span { color: #606266; }
.contract-basic-section__date-range :deep(.el-date-editor) { width: auto; min-width: 0; }
.contract-basic-section :deep(.el-form-item) { align-items: center; margin-bottom: 16px; }
.contract-basic-section :deep(.el-form-item__label) { flex: 0 0 96px !important; width: 96px !important; height: auto; padding-right: 12px; white-space: normal; word-break: break-all; line-height: 18px; }
.contract-basic-section :deep(.el-form-item__content) { min-width: 0; }
.contract-basic-section :deep(.el-input),
.contract-basic-section :deep(.el-select),
.contract-basic-section :deep(.el-date-editor) { width: 360px; max-width: 100%; }
.dialog-section-title { margin-bottom: 18px; font-size: 16px; font-weight: 600; }
.dialog-section-title::before { display: inline-block; width: 4px; height: 16px; margin-right: 8px; vertical-align: -2px; background: #409eff; content: ''; }
.section-head { display: flex; align-items: center; justify-content: space-between; }
.change-table { margin: 16px 0; }
.ratio-tip { margin-bottom: 8px; color: #f56c6c; }
.unit { margin-left: 8px; }
.inline-field { display: flex; align-items: center; gap: 8px; }
.attachment-head { display: flex; align-items: center; justify-content: flex-end; margin-bottom: 12px; }
.attachment-upload { display: flex; justify-content: flex-start; margin-top: 12px; }
.attachment-upload .vehicle-attachment-upload { width: auto; }
@@ -162,4 +184,6 @@ export default {
.settlement-form { display: grid; grid-template-columns: repeat(3, minmax(240px, 1fr)); gap: 8px 28px; }
.change-reason-section { border: 1px dashed #ff8f9a; margin: 20px 16px; }
.page-footer { display: flex; gap: 16px; padding: 20px 40px; border-top: 1px solid #eff1f7; }
@media (max-width: 1200px) { .contract-basic-section__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 32px; } }
@media (max-width: 768px) { .contract-basic-section__grid { grid-template-columns: 1fr; } }
</style>
+21 -8
View File
@@ -225,14 +225,16 @@
</div>
</el-form-item>
<el-form-item label="所属组织" prop="organizationName">
<el-cascader
<el-tree-select
v-model="selectedOrganizationId"
:options="organizationOptions"
:props="organizationCascaderProps"
:data="organizationOptions"
:props="organizationTreeSelectProps"
node-key="id"
placeholder="请选择"
check-strictly
clearable
filterable
:show-all-levels="false"
:render-after-expand="false"
@visible-change="visible => visible && loadOrganizationOptions()"
@change="handleOrganizationChange"
/>
@@ -1234,13 +1236,11 @@ export default {
contractFormatOptions() {
return this.columnOptions('contractFormat');
},
organizationCascaderProps() {
organizationTreeSelectProps() {
return {
label: 'label',
value: 'id',
children: 'children',
checkStrictly: true,
emitPath: false,
};
},
settlementRuleEnabled() {
@@ -1688,7 +1688,8 @@ export default {
this.organizationLoading = true;
getDeptTree(this.userInfo?.tenantId)
.then(res => {
this.organizationOptions = this.normalizeOrganizationTree(res.data?.data || []);
const organizationTree = this.excludeExternalOrganization(res.data?.data || []);
this.organizationOptions = this.normalizeOrganizationTree(organizationTree);
this.organizationFlatOptions = this.flattenOrganizationTree(this.organizationOptions);
const column = this.findColumn(this.tableOption.column, 'organizationName');
if (column) column.dicData = this.organizationOptions;
@@ -1698,6 +1699,17 @@ export default {
this.organizationLoading = false;
});
},
excludeExternalOrganization(tree = []) {
return tree.reduce((result, item) => {
const organizationName = item.title || item.deptName || item.name || item.label || '';
if (String(organizationName).trim() === '外部组织') return result;
result.push({
...item,
children: this.excludeExternalOrganization(item.children || []),
});
return result;
}, []);
},
normalizeOrganizationTree(tree) {
return (tree || []).map(item => {
const label = item.title || item.deptName || item.name || item.label || '';
@@ -2279,6 +2291,7 @@ export default {
:deep(.el-input),
:deep(.el-select),
:deep(.el-cascader),
:deep(.el-tree-select),
:deep(.el-input-number),
:deep(.el-date-editor) {
width: 360px;
+5
View File
@@ -2331,6 +2331,9 @@ export default {
if (driver && !this.dialogForm.driverPhone) {
this.dialogForm.driverPhone = driver.mobile || driver.driverPhone || driver.phone || '';
}
if (String(driver?.drivingVehicle || '').trim()) {
this.dialogForm.vehicleNo = String(driver.drivingVehicle).trim();
}
},
fetchDriverSuggestions(queryString, callback) {
this.loadDriverOptions(String(queryString || '').trim())
@@ -2350,6 +2353,8 @@ export default {
this.dialogForm.driverName = value;
const phone = item.mobile || item.driverPhone || item.phone || '';
if (phone) this.dialogForm.driverPhone = phone;
const drivingVehicle = String(item.drivingVehicle || '').trim();
if (drivingVehicle) this.dialogForm.vehicleNo = drivingVehicle;
}
},
handleMileageInput(value) {
+57 -29
View File
@@ -157,31 +157,31 @@
/>
</el-form-item>
<el-form-item label="业务部门" prop="businessDeptId">
<el-select
<el-tree-select
v-model="form.businessDeptId"
:data="businessDeptTreeOptions"
:props="deptTreeSelectProps"
node-key="value"
placeholder="请选择业务部门"
check-strictly
filterable
clearable
:render-after-expand="false"
:disabled="isBasicInfoReadonly"
@change="handleBusinessDeptChange"
>
<el-option
v-for="item in deptOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
/>
</el-form-item>
<el-form-item label="承办部门" prop="undertakeDeptId">
<el-cascader
<el-tree-select
v-model="form.undertakeDeptId"
style="width: 100%"
:data="deptTreeOptions"
:props="deptTreeSelectProps"
node-key="value"
placeholder="请选择承办部门"
check-strictly
clearable
filterable
:options="deptTreeOptions"
:props="deptCascaderProps"
:render-after-expand="false"
:disabled="isBasicInfoReadonly"
@change="handleUndertakeDeptChange"
/>
@@ -823,6 +823,15 @@ const emptyForm = () => ({
changeReason: '',
});
const optionalSentinelFields = [
'projectScale',
'estimatedProfit',
'fundDemand',
'receivableDays',
'paymentDays',
'cargoQuantity',
];
const changeTypeOptions = [
{ label: '项目变更', value: '项目变更' },
{ label: '项目备案调整', value: '项目备案调整' },
@@ -885,7 +894,7 @@ export default {
};
const validateDays = (rule, value, callback) => {
if (value === '' || value === undefined || value === null) {
callback(new Error(`请输入${rule.label}`));
callback();
return;
}
const number = Number(value);
@@ -961,10 +970,10 @@ export default {
},
],
receivableDays: [
{ required: true, label: '应收账款回款期限', validator: validateDays, trigger: 'blur' },
{ label: '应收账款回款期限', validator: validateDays, trigger: 'blur' },
],
paymentDays: [
{ required: true, label: '回款账期', validator: validateDays, trigger: 'blur' },
{ label: '回款账期', validator: validateDays, trigger: 'blur' },
],
projectScale: [{ label: '项目规模', validator: validateAmount, trigger: 'blur' }],
estimatedProfit: [{ label: '预估利润', validator: validateAmount, trigger: 'blur' }],
@@ -997,13 +1006,12 @@ export default {
],
},
deptOptions: [],
businessDeptTreeOptions: [],
deptTreeOptions: [],
deptCascaderProps: {
deptTreeSelectProps: {
label: 'label',
value: 'value',
children: 'children',
emitPath: false,
checkStrictly: true,
},
cargoTypeOptions: [],
selectedCustomerId: [],
@@ -1415,13 +1423,12 @@ export default {
...row,
fundLimit: this.formatAmount(row.fundLimit),
receivableLimit: this.formatAmount(row.receivableLimit),
...(this.dialogReadonly
? {
projectScale: this.normalizeReadonlyAmount(row.projectScale),
estimatedProfit: this.normalizeReadonlyAmount(row.estimatedProfit),
fundDemand: this.normalizeReadonlyAmount(row.fundDemand),
}
: {}),
projectScale: this.normalizeOptionalSentinel(row.projectScale),
estimatedProfit: this.normalizeOptionalSentinel(row.estimatedProfit),
fundDemand: this.normalizeOptionalSentinel(row.fundDemand),
receivableDays: this.normalizeOptionalSentinel(row.receivableDays),
paymentDays: this.normalizeOptionalSentinel(row.paymentDays),
cargoQuantity: this.normalizeOptionalSentinel(row.cargoQuantity),
};
const form = {
...emptyForm(),
@@ -1589,6 +1596,9 @@ export default {
...this.form,
fundLimit: this.formatAmount(this.form.fundLimit),
receivableLimit: this.formatAmount(this.form.receivableLimit),
...Object.fromEntries(
optionalSentinelFields.map(key => [key, this.normalizeOptionalSentinel(this.form[key], null)])
),
businessStartDate,
businessEndDate,
customerJson: JSON.stringify(this.customerRows),
@@ -1732,8 +1742,11 @@ export default {
.filter(Boolean);
},
normalizeReadonlyAmount(value) {
return this.normalizeOptionalSentinel(value);
},
normalizeOptionalSentinel(value, emptyValue = '') {
return value === null || value === undefined || value === '' || Number(value) === -1
? ''
? emptyValue
: value;
},
mergeCustomerOptions(options = [], selectedOptions = []) {
@@ -1789,9 +1802,13 @@ export default {
loadDeptOptions() {
getDeptTree().then(res => {
const deptTree = res.data.data || [];
const businessDeptTree = ['add', 'edit'].includes(this.dialogType)
? this.excludeExternalOrganization(deptTree)
: deptTree;
const undertakeDeptTree =
this.dialogType === 'add' ? this.excludeExternalOrganization(deptTree) : deptTree;
this.deptOptions = this.flattenDept(deptTree);
this.deptOptions = this.flattenDept(businessDeptTree);
this.businessDeptTreeOptions = this.toDeptCascaderOptions(businessDeptTree);
this.deptTreeOptions = this.toDeptCascaderOptions(undertakeDeptTree);
});
},
@@ -1852,7 +1869,9 @@ export default {
getCustomerArchiveList(1, 100, {
customerType: type,
status: 1,
...(type === '客户' ? { approvalStatus: 'approved' } : {}),
...(this.dialogType !== 'add' && type === '客户'
? { approvalStatus: 'approved' }
: {}),
})
.then(res => {
const records = (res.data.data && res.data.data.records) || [];
@@ -1934,6 +1953,10 @@ export default {
return row;
},
handleNumberInput(prop, value) {
if (optionalSentinelFields.includes(prop) && Number(value) === -1) {
this.form[prop] = '';
return;
}
const text = String(value || '').replace(/[^\d.]/g, '');
const parts = text.split('.');
this.form[prop] =
@@ -1948,6 +1971,10 @@ export default {
this.form[prop] = this.formatAmount(this.form[prop]);
},
handleIntegerInput(prop, value) {
if (optionalSentinelFields.includes(prop) && Number(value) === -1) {
this.form[prop] = '';
return;
}
this.form[prop] = String(value || '').replace(/[^\d]/g, '');
},
handleAttachmentChange(list) {
@@ -2098,6 +2125,7 @@ export default {
:deep(.el-input),
:deep(.el-select),
:deep(.el-tree-select),
:deep(.el-date-editor) {
width: 100%;
}