✨ 正式结算保存草稿与同步入口,项目申请平台公司多选等业务优化
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -185,7 +185,7 @@ export const option = createCrudOption([
|
|||||||
searchPlaceholder: '请输入',
|
searchPlaceholder: '请输入',
|
||||||
searchOrder: 8,
|
searchOrder: 8,
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
rules: textRule('平台公司', 50, true),
|
rules: textRule('平台公司', 500, true),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '平台公司ID',
|
label: '平台公司ID',
|
||||||
|
|||||||
@@ -887,11 +887,14 @@ const syncCarrierOptions = () => {
|
|||||||
carrierOptions.value = [];
|
carrierOptions.value = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const carrierId =
|
const carrierId = resolveCarrierArchiveId(
|
||||||
customerContract?.partyBId ||
|
customerContract?.partyBId ||
|
||||||
customerContract?.partyBUserId ||
|
customerContract?.partyBUserId ||
|
||||||
customerContract?.customerId ||
|
customerContract?.contractPartyBId ||
|
||||||
'';
|
customerContract?.customerId ||
|
||||||
|
'',
|
||||||
|
carrierName
|
||||||
|
);
|
||||||
carrierOptions.value = [{ id: carrierId, carrierName, label: carrierName, value: carrierName }];
|
carrierOptions.value = [{ id: carrierId, carrierName, label: carrierName, value: carrierName }];
|
||||||
form.carrierId = carrierId;
|
form.carrierId = carrierId;
|
||||||
form.carrierIds = carrierId ? [carrierId] : [];
|
form.carrierIds = carrierId ? [carrierId] : [];
|
||||||
@@ -1317,12 +1320,20 @@ const contractChange = id => {
|
|||||||
const carrierTypeChange = () => {
|
const carrierTypeChange = () => {
|
||||||
syncCarrierOptions();
|
syncCarrierOptions();
|
||||||
};
|
};
|
||||||
|
const resolveCarrierArchiveId = (carrierId, carrierName) => {
|
||||||
|
if (carrierId) return carrierId;
|
||||||
|
const name = String(carrierName || '').trim();
|
||||||
|
if (!name) return '';
|
||||||
|
const matched = queryCarriers.value.find(item => String(item.name || '').trim() === name);
|
||||||
|
return matched?.id || '';
|
||||||
|
};
|
||||||
const carrierChange = value => {
|
const carrierChange = value => {
|
||||||
const item = carrierOptions.value.find(option => String(option.value) === String(value || ''));
|
const item = carrierOptions.value.find(option => String(option.value) === String(value || ''));
|
||||||
clearCarrier();
|
clearCarrier();
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
form.carrierId = item.id || '';
|
const carrierId = resolveCarrierArchiveId(item.id, item.carrierName);
|
||||||
form.carrierIds = item.id ? [item.id] : [];
|
form.carrierId = carrierId;
|
||||||
|
form.carrierIds = carrierId ? [carrierId] : [];
|
||||||
form.carrierName = item.carrierName || '';
|
form.carrierName = item.carrierName || '';
|
||||||
if (!isSelfOperated.value) form.carrierContractId = item.carrierContractId || '';
|
if (!isSelfOperated.value) form.carrierContractId = item.carrierContractId || '';
|
||||||
};
|
};
|
||||||
@@ -1738,11 +1749,23 @@ const normalizeOptionalPlanId = value => {
|
|||||||
const buildImportPayload = (status = form.status, rowList = rows.value, extra = {}) => {
|
const buildImportPayload = (status = form.status, rowList = rows.value, extra = {}) => {
|
||||||
const { file, ...batch } = form;
|
const { file, ...batch } = form;
|
||||||
const planId = normalizeOptionalPlanId(batch.planId);
|
const planId = normalizeOptionalPlanId(batch.planId);
|
||||||
|
const carrierId = resolveCarrierArchiveId(
|
||||||
|
batch.carrierId || batch.carrierIds?.[0] || '',
|
||||||
|
batch.carrierName
|
||||||
|
);
|
||||||
|
const carrierIds =
|
||||||
|
Array.isArray(batch.carrierIds) && batch.carrierIds.length
|
||||||
|
? batch.carrierIds
|
||||||
|
: carrierId
|
||||||
|
? [carrierId]
|
||||||
|
: [];
|
||||||
return {
|
return {
|
||||||
...batch,
|
...batch,
|
||||||
planId,
|
planId,
|
||||||
// 未选计划时不带占位名称,避免落库/回显 -1
|
// 未选计划时不带占位名称,避免落库/回显 -1
|
||||||
planName: planId ? batch.planName || undefined : null,
|
planName: planId ? batch.planName || undefined : null,
|
||||||
|
carrierId: carrierId || undefined,
|
||||||
|
carrierIds,
|
||||||
status,
|
status,
|
||||||
rows: rowList.map(normalizeImportRow).map(stripInternalRowFields),
|
rows: rowList.map(normalizeImportRow).map(stripInternalRowFields),
|
||||||
...extra,
|
...extra,
|
||||||
|
|||||||
@@ -6508,17 +6508,10 @@ export default {
|
|||||||
if (isAddMode) {
|
if (isAddMode) {
|
||||||
delete submitRow.id;
|
delete submitRow.id;
|
||||||
delete submitRow.waybillNo;
|
delete submitRow.waybillNo;
|
||||||
// 复制提交:状态列未进表单,Avue 可能不带回;显式保留原运单业务状态(含已完成)
|
// 复制新建:业务状态固定为草稿,不沿用原运单状态
|
||||||
const copyId = this.$route.query.copyId || '';
|
const copyId = this.$route.query.copyId || '';
|
||||||
if (copyId && !saveAsDraft) {
|
if (copyId) {
|
||||||
const copiedStatus =
|
submitRow.businessStatus = this.config.draftStatus || 'draft';
|
||||||
this.form?.businessStatus ||
|
|
||||||
this.copySourceBusinessStatus ||
|
|
||||||
submitRow.businessStatus ||
|
|
||||||
'';
|
|
||||||
if (copiedStatus) {
|
|
||||||
submitRow.businessStatus = copiedStatus;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const skipValidation = saveAsDraft && this.config.skipDraftValidation === true;
|
const skipValidation = saveAsDraft && this.config.skipDraftValidation === true;
|
||||||
@@ -6541,14 +6534,16 @@ export default {
|
|||||||
if (this.config.enableAttachmentTable) {
|
if (this.config.enableAttachmentTable) {
|
||||||
submitRow.attachmentsJson = JSON.stringify(this.attachmentRows);
|
submitRow.attachmentsJson = JSON.stringify(this.attachmentRows);
|
||||||
}
|
}
|
||||||
|
const isCopyAdd = Boolean(this.$route.query.copyId) && isAddMode;
|
||||||
if (this.config.saveAsDraft && saveAsDraft) {
|
if (this.config.saveAsDraft && saveAsDraft) {
|
||||||
submitRow[this.config.draftStatusProp || 'approvalStatus'] =
|
submitRow[this.config.draftStatusProp || 'approvalStatus'] =
|
||||||
this.config.draftStatus || 'draft';
|
this.config.draftStatus || 'draft';
|
||||||
} else if (
|
} else if (
|
||||||
|
!isCopyAdd &&
|
||||||
this.config.draftStatusProp === 'businessStatus' &&
|
this.config.draftStatusProp === 'businessStatus' &&
|
||||||
submitRow.businessStatus === (this.config.draftStatus || 'draft')
|
submitRow.businessStatus === (this.config.draftStatus || 'draft')
|
||||||
) {
|
) {
|
||||||
// 正式提交:清空草稿态,由后端按过程配置校正为待执行/进行中
|
// 正式提交:清空草稿态,由后端按过程配置校正为待执行/进行中(复制新建除外,保持草稿)
|
||||||
submitRow.businessStatus = '';
|
submitRow.businessStatus = '';
|
||||||
}
|
}
|
||||||
delete submitRow.basicInfoTitle;
|
delete submitRow.basicInfoTitle;
|
||||||
@@ -6811,12 +6806,18 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
rowSave(row, done, loading) {
|
rowSave(row, done, loading) {
|
||||||
const submitRow = this.normalizeRow(row);
|
// 复制页提交走草稿保存,避免 submit 接口把 draft 校正为待执行/进行中
|
||||||
|
const isCopySubmit = Boolean(this.$route.query.copyId);
|
||||||
|
const submitRow = this.normalizeRow(row, isCopySubmit);
|
||||||
if (!submitRow) {
|
if (!submitRow) {
|
||||||
this.stopSubmitLoading(loading);
|
this.stopSubmitLoading(loading);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.getSaveRequest()(submitRow).then(
|
const request =
|
||||||
|
isCopySubmit && typeof this.api.saveDraft === 'function'
|
||||||
|
? this.api.saveDraft
|
||||||
|
: this.getSaveRequest();
|
||||||
|
request(submitRow).then(
|
||||||
res => {
|
res => {
|
||||||
this.markWaybillListNeedRefresh();
|
this.markWaybillListNeedRefresh();
|
||||||
this.onLoad(this.page);
|
this.onLoad(this.page);
|
||||||
@@ -6945,13 +6946,14 @@ export default {
|
|||||||
if (type === 'add' && copyId) {
|
if (type === 'add' && copyId) {
|
||||||
this.api.getDetail(copyId).then(res => {
|
this.api.getDetail(copyId).then(res => {
|
||||||
const sourceData = res.data.data || {};
|
const sourceData = res.data.data || {};
|
||||||
// 原运单业务状态(如 completed)提交时需原样带回并生成应收应付
|
this.copySourceBusinessStatus = '';
|
||||||
this.copySourceBusinessStatus = sourceData.businessStatus || '';
|
// 清除不应该复制的字段;复制新建固定为草稿
|
||||||
// 清除不应该复制的字段(业务状态与原运单保持一致)
|
|
||||||
delete sourceData.id;
|
delete sourceData.id;
|
||||||
delete sourceData.code;
|
delete sourceData.code;
|
||||||
delete sourceData.waybillNo;
|
delete sourceData.waybillNo;
|
||||||
delete sourceData.waybillStatus;
|
delete sourceData.waybillStatus;
|
||||||
|
delete sourceData.businessStatus;
|
||||||
|
delete sourceData.businessStatusName;
|
||||||
delete sourceData.driverAcceptStatus;
|
delete sourceData.driverAcceptStatus;
|
||||||
delete sourceData.driverAcceptTime;
|
delete sourceData.driverAcceptTime;
|
||||||
delete sourceData.driverAcceptDriverId;
|
delete sourceData.driverAcceptDriverId;
|
||||||
@@ -6968,11 +6970,8 @@ export default {
|
|||||||
delete sourceData.updateUserName;
|
delete sourceData.updateUserName;
|
||||||
|
|
||||||
this.applyFormDetail(sourceData);
|
this.applyFormDetail(sourceData);
|
||||||
// 标记为手工创建;业务状态沿用原运单(含已完成)
|
|
||||||
this.form.dataSource = '手工创建';
|
this.form.dataSource = '手工创建';
|
||||||
if (this.copySourceBusinessStatus) {
|
this.form.businessStatus = this.config.draftStatus || 'draft';
|
||||||
this.form.businessStatus = this.copySourceBusinessStatus;
|
|
||||||
}
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -231,6 +231,9 @@
|
|||||||
<el-select
|
<el-select
|
||||||
v-model="form.undertakeDeptId"
|
v-model="form.undertakeDeptId"
|
||||||
placeholder="请选择"
|
placeholder="请选择"
|
||||||
|
multiple
|
||||||
|
collapse-tags
|
||||||
|
collapse-tags-tooltip
|
||||||
clearable
|
clearable
|
||||||
filterable
|
filterable
|
||||||
:disabled="isBasicInfoReadonly"
|
:disabled="isBasicInfoReadonly"
|
||||||
@@ -956,7 +959,7 @@ const emptyForm = () => ({
|
|||||||
projectShortName: '',
|
projectShortName: '',
|
||||||
businessDeptId: '',
|
businessDeptId: '',
|
||||||
businessDeptName: '',
|
businessDeptName: '',
|
||||||
undertakeDeptId: '',
|
undertakeDeptId: [],
|
||||||
undertakeDeptName: '',
|
undertakeDeptName: '',
|
||||||
projectSource: '',
|
projectSource: '',
|
||||||
sourceRemark: '',
|
sourceRemark: '',
|
||||||
@@ -1146,7 +1149,15 @@ export default {
|
|||||||
{ max: 20, message: '项目简称不能超过20个字符', trigger: 'blur' },
|
{ max: 20, message: '项目简称不能超过20个字符', trigger: 'blur' },
|
||||||
],
|
],
|
||||||
businessDeptId: [{ required: true, message: '请选择业务部门', trigger: 'change' }],
|
businessDeptId: [{ required: true, message: '请选择业务部门', trigger: 'change' }],
|
||||||
undertakeDeptId: [{ required: true, message: '请选择平台公司', trigger: 'change' }],
|
undertakeDeptId: [
|
||||||
|
{
|
||||||
|
type: 'array',
|
||||||
|
required: true,
|
||||||
|
min: 1,
|
||||||
|
message: '请选择平台公司',
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
],
|
||||||
businessMode: [{ required: true, message: '请选择业务模式', trigger: 'change' }],
|
businessMode: [{ required: true, message: '请选择业务模式', trigger: 'change' }],
|
||||||
customerNames: [{ required: true, message: '请选择客户名称', trigger: 'change' }],
|
customerNames: [{ required: true, message: '请选择客户名称', trigger: 'change' }],
|
||||||
carrierNames: [{ required: true, message: '请选择下游承运商', trigger: 'change' }],
|
carrierNames: [{ required: true, message: '请选择下游承运商', trigger: 'change' }],
|
||||||
@@ -1508,13 +1519,13 @@ export default {
|
|||||||
this.businessDeptTreeOptions = [{ label, value: detail.businessDeptId }];
|
this.businessDeptTreeOptions = [{ label, value: detail.businessDeptId }];
|
||||||
this.deptOptions = [{ label, rawLabel: label, value: detail.businessDeptId }];
|
this.deptOptions = [{ label, rawLabel: label, value: detail.businessDeptId }];
|
||||||
}
|
}
|
||||||
if (detail.undertakeDeptId) {
|
const undertakeDeptIds = this.parseUndertakeDeptIds(detail.undertakeDeptId);
|
||||||
this.platformCompanyOptions = [
|
const undertakeDeptNames = this.parseUndertakeDeptNames(detail.undertakeDeptName);
|
||||||
{
|
if (undertakeDeptIds.length) {
|
||||||
label: detail.undertakeDeptName || String(detail.undertakeDeptId),
|
this.platformCompanyOptions = undertakeDeptIds.map((id, index) => ({
|
||||||
value: detail.undertakeDeptId,
|
label: undertakeDeptNames[index] || String(id),
|
||||||
},
|
value: id,
|
||||||
];
|
}));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolvePublicDictOptions(options, currentValue) {
|
resolvePublicDictOptions(options, currentValue) {
|
||||||
@@ -1860,6 +1871,8 @@ export default {
|
|||||||
this.form = {
|
this.form = {
|
||||||
...form,
|
...form,
|
||||||
...situation,
|
...situation,
|
||||||
|
undertakeDeptId: this.parseUndertakeDeptIds(form.undertakeDeptId),
|
||||||
|
undertakeDeptName: form.undertakeDeptName || '',
|
||||||
customerNames: this.getCustomerRowNames(customerRows, 'customer') || form.customerNames,
|
customerNames: this.getCustomerRowNames(customerRows, 'customer') || form.customerNames,
|
||||||
carrierNames: this.getCustomerRowNames(carrierRows, 'carrier') || form.carrierNames,
|
carrierNames: this.getCustomerRowNames(carrierRows, 'carrier') || form.carrierNames,
|
||||||
};
|
};
|
||||||
@@ -2026,8 +2039,13 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
normalizeSubmitForm(options = {}) {
|
normalizeSubmitForm(options = {}) {
|
||||||
|
const undertakeDeptIds = this.parseUndertakeDeptIds(this.form.undertakeDeptId);
|
||||||
|
const undertakeDeptName =
|
||||||
|
this.resolveUndertakeDeptNames(undertakeDeptIds) || this.form.undertakeDeptName || '';
|
||||||
const submitRow = {
|
const submitRow = {
|
||||||
...this.form,
|
...this.form,
|
||||||
|
undertakeDeptId: undertakeDeptIds.join(','),
|
||||||
|
undertakeDeptName,
|
||||||
fundLimit: this.formatAmount(this.form.fundLimit),
|
fundLimit: this.formatAmount(this.form.fundLimit),
|
||||||
receivableLimit: this.formatAmount(this.form.receivableLimit),
|
receivableLimit: this.formatAmount(this.form.receivableLimit),
|
||||||
...Object.fromEntries(
|
...Object.fromEntries(
|
||||||
@@ -2419,11 +2437,40 @@ export default {
|
|||||||
this.$refs.projectForm?.validateField('businessDeptId');
|
this.$refs.projectForm?.validateField('businessDeptId');
|
||||||
},
|
},
|
||||||
handleUndertakeDeptChange(value) {
|
handleUndertakeDeptChange(value) {
|
||||||
const id = Array.isArray(value) ? value.at(-1) : value;
|
const ids = this.parseUndertakeDeptIds(value);
|
||||||
const dept = this.platformCompanyOptions.find(item => String(item.value) === String(id));
|
this.form.undertakeDeptId = ids;
|
||||||
this.form.undertakeDeptName = dept ? dept.label : '';
|
this.form.undertakeDeptName = this.resolveUndertakeDeptNames(ids);
|
||||||
this.$refs.projectForm?.validateField('undertakeDeptId');
|
this.$refs.projectForm?.validateField('undertakeDeptId');
|
||||||
},
|
},
|
||||||
|
parseUndertakeDeptIds(value) {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value
|
||||||
|
.map(item => String(item ?? '').trim())
|
||||||
|
.filter(item => item && item !== '-1');
|
||||||
|
}
|
||||||
|
return String(value ?? '')
|
||||||
|
.split(/[,,]/)
|
||||||
|
.map(item => item.trim())
|
||||||
|
.filter(item => item && item !== '-1');
|
||||||
|
},
|
||||||
|
parseUndertakeDeptNames(value) {
|
||||||
|
return String(value ?? '')
|
||||||
|
.split(/[,,、]/)
|
||||||
|
.map(item => item.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
},
|
||||||
|
resolveUndertakeDeptNames(ids = []) {
|
||||||
|
return ids
|
||||||
|
.map(id => {
|
||||||
|
const dept = this.platformCompanyOptions.find(item => String(item.value) === String(id));
|
||||||
|
return dept?.label || '';
|
||||||
|
})
|
||||||
|
.filter(Boolean)
|
||||||
|
.join('、');
|
||||||
|
},
|
||||||
|
firstUndertakeDeptId(value) {
|
||||||
|
return this.parseUndertakeDeptIds(value)[0] || '';
|
||||||
|
},
|
||||||
// 由部门 id 反查「根 → 该节点」的 id 路径,供级联回显(找不到返回 null)
|
// 由部门 id 反查「根 → 该节点」的 id 路径,供级联回显(找不到返回 null)
|
||||||
findDeptPath(id, tree = [], parents = []) {
|
findDeptPath(id, tree = [], parents = []) {
|
||||||
const target = Array.isArray(id) ? id.at(-1) : id;
|
const target = Array.isArray(id) ? id.at(-1) : id;
|
||||||
@@ -2462,15 +2509,23 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
ensureCurrentPlatformOption() {
|
ensureCurrentPlatformOption() {
|
||||||
const id = this.form.undertakeDeptId;
|
const ids = this.parseUndertakeDeptIds(this.form.undertakeDeptId);
|
||||||
if (!id) return;
|
if (!ids.length) return;
|
||||||
const exists = this.platformCompanyOptions.some(item => String(item.value) === String(id));
|
const names = this.parseUndertakeDeptNames(this.form.undertakeDeptName);
|
||||||
if (!exists) {
|
ids.forEach((id, index) => {
|
||||||
this.platformCompanyOptions.unshift({
|
const exists = this.platformCompanyOptions.some(item => String(item.value) === String(id));
|
||||||
label: this.form.undertakeDeptName || String(id),
|
if (!exists) {
|
||||||
value: id,
|
this.platformCompanyOptions.unshift({
|
||||||
});
|
label: names[index] || String(id),
|
||||||
}
|
value: id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 选项 value 与已选 ID 类型对齐,避免回显失败
|
||||||
|
this.form.undertakeDeptId = ids.map(id => {
|
||||||
|
const matched = this.platformCompanyOptions.find(item => String(item.value) === String(id));
|
||||||
|
return matched ? matched.value : id;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
excludeExternalOrganization(list = []) {
|
excludeExternalOrganization(list = []) {
|
||||||
return list.reduce((result, item) => {
|
return list.reduce((result, item) => {
|
||||||
|
|||||||
@@ -36,23 +36,25 @@
|
|||||||
<el-col v-if="isSettlementRelatedType" :span="6"
|
<el-col v-if="isSettlementRelatedType" :span="6"
|
||||||
><el-form-item label="结算单号" prop="referenceId">
|
><el-form-item label="结算单号" prop="referenceId">
|
||||||
<div class="payment-form-page__settlement-nos">
|
<div class="payment-form-page__settlement-nos">
|
||||||
<template v-if="referenceSettlementLinks.length">
|
<el-select
|
||||||
<el-link
|
ref="settlementNoSelectRef"
|
||||||
v-for="item in referenceSettlementLinks"
|
:model-value="referenceSettlementNos"
|
||||||
:key="`${item.id || item.settlementNo}`"
|
multiple
|
||||||
type="primary"
|
collapse-tags
|
||||||
@click="openSettlementDetail(item)"
|
collapse-tags-tooltip
|
||||||
>
|
:max-collapse-tags="1"
|
||||||
{{ item.settlementNo }}
|
|
||||||
</el-link>
|
|
||||||
</template>
|
|
||||||
<el-input
|
|
||||||
v-else
|
|
||||||
v-model="referenceLabel"
|
|
||||||
readonly
|
|
||||||
:disabled="readonly"
|
:disabled="readonly"
|
||||||
placeholder="请选择预结算/正式结算单"
|
placeholder="请选择预结算/正式结算单"
|
||||||
/>
|
class="payment-form-page__settlement-select"
|
||||||
|
@visible-change="handleSettlementSelectVisible"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in referenceSettlementLinks"
|
||||||
|
:key="`${item.id || item.settlementNo}`"
|
||||||
|
:label="item.settlementNo"
|
||||||
|
:value="item.settlementNo"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
class="payment-form-page__settlement-select-btn"
|
class="payment-form-page__settlement-select-btn"
|
||||||
@@ -251,7 +253,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</section-card>
|
</section-card>
|
||||||
<section-card v-if="isSettlementRelatedType" title="发票信息">
|
<section-card v-if="showInvoiceSection" title="发票信息">
|
||||||
<el-table :data="form.invoices" border>
|
<el-table :data="form.invoices" border>
|
||||||
<el-table-column type="index" label="序号" width="70" />
|
<el-table-column type="index" label="序号" width="70" />
|
||||||
<el-table-column prop="settlementNo" label="结算单号" min-width="120">
|
<el-table-column prop="settlementNo" label="结算单号" min-width="120">
|
||||||
@@ -874,6 +876,10 @@ export default {
|
|||||||
isSettlementRelatedType() {
|
isSettlementRelatedType() {
|
||||||
return ['progress_advance', 'settlement_payment'].includes(this.form.paymentType);
|
return ['progress_advance', 'settlement_payment'].includes(this.form.paymentType);
|
||||||
},
|
},
|
||||||
|
// 项目预付、进度预付不展示发票信息,仅尾款付款展示
|
||||||
|
showInvoiceSection() {
|
||||||
|
return this.form.paymentType === 'settlement_payment';
|
||||||
|
},
|
||||||
canSelectPreSettlement() {
|
canSelectPreSettlement() {
|
||||||
// 进度预付仅预结算;尾款付款可正式/预结算
|
// 进度预付仅预结算;尾款付款可正式/预结算
|
||||||
return ['progress_advance', 'settlement_payment'].includes(this.form.paymentType);
|
return ['progress_advance', 'settlement_payment'].includes(this.form.paymentType);
|
||||||
@@ -926,6 +932,9 @@ export default {
|
|||||||
referenceType: this.form.preSettlementId ? 'pre' : 'formal',
|
referenceType: this.form.preSettlementId ? 'pre' : 'formal',
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
referenceSettlementNos() {
|
||||||
|
return this.referenceSettlementLinks.map(item => item.settlementNo).filter(Boolean);
|
||||||
|
},
|
||||||
settlementRows() {
|
settlementRows() {
|
||||||
if (this.referenceRows.length) {
|
if (this.referenceRows.length) {
|
||||||
return this.referenceRows.map(item => ({
|
return this.referenceRows.map(item => ({
|
||||||
@@ -1110,7 +1119,7 @@ export default {
|
|||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
validateInvoices() {
|
validateInvoices() {
|
||||||
if (this.form.paymentType === 'project_advance') return;
|
if (!this.showInvoiceSection) return;
|
||||||
for (const invoice of this.form.invoices || []) {
|
for (const invoice of this.form.invoices || []) {
|
||||||
if (String(invoice.settlementNo || '').length > 100) {
|
if (String(invoice.settlementNo || '').length > 100) {
|
||||||
throw new Error('结算单号不能超过100个字符');
|
throw new Error('结算单号不能超过100个字符');
|
||||||
@@ -1869,6 +1878,7 @@ export default {
|
|||||||
this.contractPaymentRatioExceeded = exceeded;
|
this.contractPaymentRatioExceeded = exceeded;
|
||||||
},
|
},
|
||||||
handleTypeChange() {
|
handleTypeChange() {
|
||||||
|
// 切换类型时清空发票;预付类型本身也不再展示/提交发票
|
||||||
this.form.invoices = [];
|
this.form.invoices = [];
|
||||||
this.paymentRecords = [];
|
this.paymentRecords = [];
|
||||||
Object.assign(this.form, {
|
Object.assign(this.form, {
|
||||||
@@ -2056,8 +2066,20 @@ export default {
|
|||||||
const project = this.projectOptions.find(item => String(item.id) === String(projectId));
|
const project = this.projectOptions.find(item => String(item.id) === String(projectId));
|
||||||
this.form.projectName = project?.projectName || project?.projectShortName || '';
|
this.form.projectName = project?.projectName || project?.projectShortName || '';
|
||||||
Object.assign(this.form, {
|
Object.assign(this.form, {
|
||||||
deptId: project?.undertakeDeptId || project?.businessDeptId || null,
|
deptId:
|
||||||
deptName: project?.undertakeDeptName || project?.businessDeptName || '',
|
String(project?.undertakeDeptId || '')
|
||||||
|
.split(/[,,]/)
|
||||||
|
.map(item => item.trim())
|
||||||
|
.find(Boolean) ||
|
||||||
|
project?.businessDeptId ||
|
||||||
|
null,
|
||||||
|
deptName:
|
||||||
|
String(project?.undertakeDeptName || '')
|
||||||
|
.split(/[,,、]/)
|
||||||
|
.map(item => item.trim())
|
||||||
|
.find(Boolean) ||
|
||||||
|
project?.businessDeptName ||
|
||||||
|
'',
|
||||||
contractId: null,
|
contractId: null,
|
||||||
contractNo: '',
|
contractNo: '',
|
||||||
contractName: '',
|
contractName: '',
|
||||||
@@ -2225,6 +2247,13 @@ export default {
|
|||||||
}
|
}
|
||||||
return Promise.all(loaders);
|
return Promise.all(loaders);
|
||||||
},
|
},
|
||||||
|
handleSettlementSelectVisible(visible) {
|
||||||
|
// 结算单号仅做展示,通过「选择」按钮维护,避免下拉改值
|
||||||
|
if (!visible) return;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.settlementNoSelectRef?.blur?.();
|
||||||
|
});
|
||||||
|
},
|
||||||
handleReferenceSearch() {
|
handleReferenceSearch() {
|
||||||
this.formalPage.current = 1;
|
this.formalPage.current = 1;
|
||||||
this.prePage.current = 1;
|
this.prePage.current = 1;
|
||||||
@@ -2588,7 +2617,7 @@ export default {
|
|||||||
attachmentsJson: JSON.stringify(attachments || []),
|
attachmentsJson: JSON.stringify(attachments || []),
|
||||||
remark,
|
remark,
|
||||||
invoices:
|
invoices:
|
||||||
paymentType === 'project_advance'
|
paymentType === 'project_advance' || paymentType === 'progress_advance'
|
||||||
? []
|
? []
|
||||||
: invoices.map(invoice => ({
|
: invoices.map(invoice => ({
|
||||||
settlementNo: invoice.settlementNo || '',
|
settlementNo: invoice.settlementNo || '',
|
||||||
@@ -2669,13 +2698,18 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
flex-wrap: wrap;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 32px;
|
min-height: 32px;
|
||||||
}
|
}
|
||||||
.payment-form-page__settlement-nos :deep(.el-input) {
|
.payment-form-page__settlement-select {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 120px;
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.payment-form-page__settlement-select :deep(.el-select__wrapper) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.payment-form-page__settlement-select :deep(.el-tag__close) {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
.payment-form-page__settlement-select-btn {
|
.payment-form-page__settlement-select-btn {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|||||||
@@ -658,9 +658,10 @@
|
|||||||
</section-card>
|
</section-card>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="!pageMode" #footer>
|
<template v-if="!pageMode" #footer>
|
||||||
|
<el-button v-if="editable" @click="handleSyncPlaceholder">同步</el-button>
|
||||||
<el-button @click="visible = false">取消</el-button>
|
<el-button @click="visible = false">取消</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="editable && !recordId"
|
v-if="editable"
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
:loading="draftSaving"
|
:loading="draftSaving"
|
||||||
@@ -673,9 +674,10 @@
|
|||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
<div v-if="pageMode && !publicMode" class="formal-editor__page-actions">
|
<div v-if="pageMode && !publicMode" class="formal-editor__page-actions">
|
||||||
|
<el-button v-if="editable" @click="handleSyncPlaceholder">同步</el-button>
|
||||||
<el-button @click="visible = false">取消</el-button>
|
<el-button @click="visible = false">取消</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
v-if="editable && !recordId"
|
v-if="editable"
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
:loading="draftSaving"
|
:loading="draftSaving"
|
||||||
@@ -2547,7 +2549,11 @@ export default {
|
|||||||
remark: this.form.remark,
|
remark: this.form.remark,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
handleSyncPlaceholder() {
|
||||||
|
this.$message.info('开发中');
|
||||||
|
},
|
||||||
async handleDraftSave() {
|
async handleDraftSave() {
|
||||||
|
// 保存草稿:不做表单校验,直接落草稿并返回列表刷新
|
||||||
this.draftSaving = true;
|
this.draftSaving = true;
|
||||||
try {
|
try {
|
||||||
await save({
|
await save({
|
||||||
@@ -2555,8 +2561,8 @@ export default {
|
|||||||
approvalStatus: 'draft',
|
approvalStatus: 'draft',
|
||||||
});
|
});
|
||||||
this.$message.success('保存成功');
|
this.$message.success('保存成功');
|
||||||
this.visible = false;
|
|
||||||
this.$emit('success');
|
this.$emit('success');
|
||||||
|
this.visible = false;
|
||||||
} finally {
|
} finally {
|
||||||
this.draftSaving = false;
|
this.draftSaving = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
:record-id="recordId"
|
:record-id="recordId"
|
||||||
:readonly="readonly"
|
:readonly="readonly"
|
||||||
:initial-data="editorInitialData"
|
:initial-data="editorInitialData"
|
||||||
|
@success="markListNeedRefresh"
|
||||||
/>
|
/>
|
||||||
</basic-container>
|
</basic-container>
|
||||||
</template>
|
</template>
|
||||||
@@ -16,6 +17,8 @@
|
|||||||
import FormalSettlementEditor from './components/formal-settlement-editor.vue';
|
import FormalSettlementEditor from './components/formal-settlement-editor.vue';
|
||||||
import { readSettlementTransfer, removeSettlementTransfer } from '@/utils/settlement-transfer';
|
import { readSettlementTransfer, removeSettlementTransfer } from '@/utils/settlement-transfer';
|
||||||
|
|
||||||
|
const LIST_REFRESH_KEY = 'formal-settlement-list-refresh';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'FormalSettlementForm',
|
name: 'FormalSettlementForm',
|
||||||
components: { FormalSettlementEditor },
|
components: { FormalSettlementEditor },
|
||||||
@@ -54,6 +57,9 @@ export default {
|
|||||||
this.syncTagTitle();
|
this.syncTagTitle();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
markListNeedRefresh() {
|
||||||
|
sessionStorage.setItem(LIST_REFRESH_KEY, '1');
|
||||||
|
},
|
||||||
goBack() {
|
goBack() {
|
||||||
removeSettlementTransfer(this.$route.query.transferToken);
|
removeSettlementTransfer(this.$route.query.transferToken);
|
||||||
this.$router.$avueRouter.closeTag();
|
this.$router.$avueRouter.closeTag();
|
||||||
|
|||||||
@@ -262,6 +262,12 @@ export default {
|
|||||||
this.mkEnabled = false;
|
this.mkEnabled = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
activated() {
|
||||||
|
if (sessionStorage.getItem('formal-settlement-list-refresh') === '1') {
|
||||||
|
sessionStorage.removeItem('formal-settlement-list-refresh');
|
||||||
|
this.loadTable();
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
hasPermission(code) {
|
hasPermission(code) {
|
||||||
return this.permission?.[code] !== false;
|
return this.permission?.[code] !== false;
|
||||||
|
|||||||
@@ -2693,6 +2693,10 @@ export default {
|
|||||||
return this.formatCell(row?.[prop]);
|
return this.formatCell(row?.[prop]);
|
||||||
},
|
},
|
||||||
formatFeeDetailCell(row, prop) {
|
formatFeeDetailCell(row, prop) {
|
||||||
|
if (prop === 'transportQuantityText' || prop === 'transportQuantity') {
|
||||||
|
if (this.isBlankTransportQuantity(row)) return '-';
|
||||||
|
return this.formatDetailCell(row, prop);
|
||||||
|
}
|
||||||
if (prop !== 'originalAmountText') return this.formatDetailCell(row, prop);
|
if (prop !== 'originalAmountText') return this.formatDetailCell(row, prop);
|
||||||
|
|
||||||
const adjustAmount = Number(row?.adjustAmount || 0);
|
const adjustAmount = Number(row?.adjustAmount || 0);
|
||||||
@@ -2711,6 +2715,17 @@ export default {
|
|||||||
formatCell(value) {
|
formatCell(value) {
|
||||||
return value === null || value === undefined || value === '' ? '-' : value;
|
return value === null || value === undefined || value === '' ? '-' : value;
|
||||||
},
|
},
|
||||||
|
isBlankTransportQuantity(row = {}) {
|
||||||
|
const quantity = row.transportQuantity;
|
||||||
|
if (quantity !== null && quantity !== undefined && quantity !== '') {
|
||||||
|
const amount = Number(quantity);
|
||||||
|
return !Number.isFinite(amount) || amount === 0 || amount === -1;
|
||||||
|
}
|
||||||
|
const text = String(row.transportQuantityText || '').trim();
|
||||||
|
if (!text || text === '-') return true;
|
||||||
|
const amount = Number(text.split(/\s+/)[0]);
|
||||||
|
return Number.isFinite(amount) && (amount === 0 || amount === -1);
|
||||||
|
},
|
||||||
parseJson(value) {
|
parseJson(value) {
|
||||||
if (!value) return [];
|
if (!value) return [];
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -138,7 +138,7 @@
|
|||||||
type="warning"
|
type="warning"
|
||||||
v-if="
|
v-if="
|
||||||
hasPermission('customer_archive_submit') &&
|
hasPermission('customer_archive_submit') &&
|
||||||
['draft', 'reviewing'].includes(row.approvalStatus)
|
row.approvalStatus === 'reviewing'
|
||||||
"
|
"
|
||||||
@click="handleWithdrawApproval(row)"
|
@click="handleWithdrawApproval(row)"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user