✨ 合同变更页支持编辑负责部门与平台公司

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-11-11 01:13:33 +08:00
co-authored by Cursor
parent 0da0c6f493
commit f82b04caff
+214 -4
View File
@@ -66,11 +66,41 @@
<el-form-item label="项目">
<el-input v-model="form.projectName" disabled />
</el-form-item>
<el-form-item label="合同负责部门">
<el-input v-model="form.organizationName" disabled />
<el-form-item label="合同负责部门" prop="organizationName">
<el-select
v-model="selectedOrganizationId"
placeholder="请选择"
filterable
clearable
:loading="businessDeptLoading"
:disabled="isSettlementRuleChange"
@visible-change="visible => visible && loadBusinessDeptOptions()"
@change="handleOrganizationChange"
>
<el-option
v-for="item in businessDeptOptions"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="平台公司">
<el-input v-model="form.platformCompanyName" disabled />
<el-form-item label="平台公司" prop="platformCompanyName">
<el-select
v-model="form.platformCompanyId"
placeholder="请选择平台公司"
filterable
clearable
:disabled="isSettlementRuleChange || !form.projectId"
@change="handlePlatformCompanyChange"
>
<el-option
v-for="item in platformCompanyOptions"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="签订日期">
<el-date-picker
@@ -575,8 +605,11 @@
<script>
import * as contractApi from '@/api/business/contract-manage';
import * as changeApi from '@/api/business/contract-change';
import { getDetail as getProjectDetail } from '@/api/business/project-apply';
import { getBusinessDeptSelect, getPlatformCompanySelect } from '@/api/system/dept';
import { getMkPublicDetail } from '@/api/mk-process';
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
import { normalizeBusinessDeptOptions } from '@/utils/dept';
import BillingPlanEditor from './components/billing-plan-editor.vue';
import ContractAttachmentSection, {
isContractSealMaterialLocation,
@@ -740,6 +773,10 @@ export default {
settlementCurrencyOptions: [],
settlementModeDictOptions: [],
contractFormatDictOptions: [],
selectedOrganizationId: '',
businessDeptOptions: [],
businessDeptLoading: false,
platformCompanyOptions: [],
planDialogVisible: false,
planEditor: { planName: '', remark: '', rules: [] },
planEditorIndex: -1,
@@ -772,6 +809,34 @@ export default {
},
],
contractName: [{ required: true, message: '请输入合同名称', trigger: 'blur' }],
organizationName: [
{
validator: (rule, value, callback) => {
if (this.isSettlementRuleChange) {
return callback();
}
if (!String(value || '').trim()) {
return callback(new Error('请选择合同负责部门'));
}
callback();
},
trigger: 'change',
},
],
platformCompanyName: [
{
validator: (rule, value, callback) => {
if (this.isSettlementRuleChange) {
return callback();
}
if (!String(value || '').trim()) {
return callback(new Error('请选择平台公司'));
}
callback();
},
trigger: 'change',
},
],
contractAmount: [
{ required: true, message: '请输入合同金额', trigger: 'blur' },
{
@@ -924,6 +989,136 @@ export default {
formatContractAmountField() {
this.form.contractAmount = formatContractAmountInput(this.form.contractAmount);
},
handleOrganizationChange(id) {
const organizationId = Array.isArray(id) ? id.at(-1) : id;
const organization = this.businessDeptOptions.find(
item => String(item.id) === String(organizationId)
);
Object.assign(
this.form,
organization
? {
organizationId: organization.id,
organizationName: organization.rawLabel || organization.label,
}
: { organizationId: '', organizationName: '' }
);
this.selectedOrganizationId = this.form.organizationId
? String(this.form.organizationId)
: '';
},
handlePlatformCompanyChange(value) {
const matched = this.platformCompanyOptions.find(item => String(item.id) === String(value));
this.form.platformCompanyId = matched ? matched.id : '';
this.form.platformCompanyName = matched ? matched.label : '';
},
loadBusinessDeptOptions() {
if (this.businessDeptLoading) return;
this.businessDeptLoading = true;
getBusinessDeptSelect()
.then(res => {
this.businessDeptOptions = normalizeBusinessDeptOptions(res.data?.data || []);
this.syncCurrentBusinessDeptOption();
})
.finally(() => {
this.businessDeptLoading = false;
});
},
syncCurrentBusinessDeptOption() {
if (!this.form.organizationId || !this.form.organizationName) return;
if (
this.businessDeptOptions.some(item => String(item.id) === String(this.form.organizationId))
) {
return;
}
this.businessDeptOptions.unshift({
id: String(this.form.organizationId),
value: String(this.form.organizationId),
label: this.form.organizationName,
rawLabel: this.form.organizationName,
});
},
parseUndertakeDeptIds(value) {
if (Array.isArray(value)) {
return value.map(item => String(item || '').trim()).filter(Boolean);
}
return String(value || '')
.split(',')
.map(item => item.trim())
.filter(Boolean);
},
parseUndertakeDeptNames(value) {
if (Array.isArray(value)) {
return value.map(item => String(item || '').trim()).filter(Boolean);
}
return String(value || '')
.split(/[、,,]/)
.map(item => item.trim())
.filter(Boolean);
},
loadProjectPlatformCompanies() {
const projectId = this.form.projectId;
if (!projectId || String(projectId) === '-1') {
this.syncCurrentPlatformCompanyOption();
return Promise.resolve([]);
}
return getProjectDetail(projectId)
.then(res => {
const project = res.data?.data || res.data || {};
const ids = this.parseUndertakeDeptIds(project.undertakeDeptId);
const names = this.parseUndertakeDeptNames(project.undertakeDeptName);
return this.resolveProjectPlatformCompanyOptions(ids, names);
})
.then(options => {
this.platformCompanyOptions = options;
this.syncCurrentPlatformCompanyOption();
return options;
})
.catch(() => {
this.syncCurrentPlatformCompanyOption();
return this.platformCompanyOptions;
});
},
resolveProjectPlatformCompanyOptions(ids, names) {
const fallback = ids.map((id, index) => ({
id: String(id),
label: names[index] || String(id),
}));
if (!ids.length) return Promise.resolve([]);
return getPlatformCompanySelect()
.then(res => {
const liveList = (res.data?.data || []).map(item => ({
id: String(item.id),
label: item.deptName || item.fullName || String(item.id),
}));
return ids.map((id, index) => {
const name = String(names[index] || '').trim();
const byId = liveList.find(item => String(item.id) === String(id));
if (byId) return byId;
const byName = name ? liveList.find(item => item.label === name) : null;
if (byName) return byName;
return {
id: String(id),
label: name || String(id),
};
});
})
.catch(() => fallback);
},
syncCurrentPlatformCompanyOption() {
if (!this.form.platformCompanyId || !this.form.platformCompanyName) return;
if (
this.platformCompanyOptions.some(
item => String(item.id) === String(this.form.platformCompanyId)
)
) {
return;
}
this.platformCompanyOptions.unshift({
id: String(this.form.platformCompanyId),
label: this.form.platformCompanyName,
});
},
loadDictionaries() {
Promise.all([
getSystemDictionary({ code: 'currency_type' }),
@@ -972,6 +1167,10 @@ export default {
...data,
// 独立变更单保留 contractId;旧路由以合同 id 作为主键
contractId: data.contractId || (isChangeRecord ? data.contractId : data.id),
organizationId: data.organizationId ? String(data.organizationId) : '',
organizationName: data.organizationName || '',
platformCompanyId: data.platformCompanyId ? String(data.platformCompanyId) : '',
platformCompanyName: data.platformCompanyName || '',
changeContent: isChangeRecord ? data.changeContent || '' : '',
changeReason: isChangeRecord ? data.changeReason || '' : '',
changeAttachmentsJson: data.changeAttachmentsJson || '',
@@ -984,6 +1183,7 @@ export default {
archiveStatus: data.archiveStatus || '未归档',
changeType: data.changeType || '合同信息变更',
};
this.selectedOrganizationId = this.form.organizationId ? String(this.form.organizationId) : '';
this.changeMaterials = this.parse(data.changeAttachmentsJson);
this.period = data.startDate && data.endDate ? [data.startDate, data.endDate] : [];
this.partyARows = normalizePartyRows(data.partyAJson, data.partyA, true);
@@ -1033,6 +1233,8 @@ export default {
this.feeGenerationMode =
data.feeGenerationMode || (Number(data.billingEnabled) === 0 ? 'manual' : 'system');
this.paymentRatioRows = this.parse(data.paymentRatioJson);
this.loadBusinessDeptOptions();
this.loadProjectPlatformCompanies();
},
goBack() {
if (this.isContractChangeModule) {
@@ -1231,6 +1433,14 @@ export default {
return;
}
this.form.contractNo = contractNo;
if (!String(this.form.organizationName || '').trim()) {
this.$message.warning('请选择合同负责部门');
return;
}
if (!String(this.form.platformCompanyName || '').trim()) {
this.$message.warning('请选择平台公司');
return;
}
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%');