|
|
|
|
|
<template>
|
|
|
|
|
|
<div class="p-2">
|
|
|
|
|
|
<el-card shadow="never">
|
|
|
|
|
|
<template #header>
|
|
|
|
|
|
<span>{{ isEdit ? '编辑合同变更' : '合同变更申请' }}</span>
|
|
|
|
|
|
<el-button class="float-right" link @click="goBack">返回</el-button>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
|
|
|
|
|
|
<el-form-item label="变更类型" prop="changeType">
|
|
|
|
|
|
<el-radio-group v-model="form.changeType" :disabled="isEdit">
|
|
|
|
|
|
<el-radio v-for="dict in contract_change_type" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="选择合同" prop="contractId">
|
|
|
|
|
|
<el-select
|
|
|
|
|
|
v-model="form.contractId"
|
|
|
|
|
|
placeholder="请选择已激活的合同(仅可变更状态=可用且已激活的合同)"
|
|
|
|
|
|
filterable
|
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
|
:disabled="isEdit"
|
|
|
|
|
|
@change="onContractChange"
|
|
|
|
|
|
>
|
|
|
|
|
|
<el-option
|
|
|
|
|
|
v-for="item in activatedContractList"
|
|
|
|
|
|
:key="item.contractId"
|
|
|
|
|
|
:label="`${item.contractCode} - ${item.contractName}`"
|
|
|
|
|
|
:value="item.contractId"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="变更原因" prop="changeReason">
|
|
|
|
|
|
<el-input v-model="form.changeReason" type="textarea" :rows="3" placeholder="请输入变更原因(解除合同时即解除原因)" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<template v-if="form.changeType === '1'">
|
|
|
|
|
|
<el-divider content-position="left">变更后合同信息(可编辑)</el-divider>
|
|
|
|
|
|
<el-row :gutter="20" v-if="form.changeInfo">
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="合同编号">
|
|
|
|
|
|
<el-input v-model="form.changeInfo.contractCode" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="合同名称">
|
|
|
|
|
|
<el-input v-model="form.changeInfo.contractName" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
|
<el-form-item label="合同总价">
|
|
|
|
|
|
<el-input v-model="form.changeInfo.totalPrice" type="number" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
<el-divider content-position="left">变更后物料</el-divider>
|
|
|
|
|
|
<el-table v-if="form.changeMaterialList?.length" :data="form.changeMaterialList" border max-height="260">
|
|
|
|
|
|
<el-table-column type="index" label="序号" width="55" />
|
|
|
|
|
|
<el-table-column prop="productName" label="产品名称" min-width="120" />
|
|
|
|
|
|
<el-table-column prop="specificationDescription" label="规格" min-width="100" />
|
|
|
|
|
|
<el-table-column prop="amount" label="数量" width="80" />
|
|
|
|
|
|
<el-table-column prop="beforePrice" label="未税单价" width="100" />
|
|
|
|
|
|
<el-table-column prop="subtotal" label="小计" width="100" />
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
<el-divider content-position="left">变更后付款方式</el-divider>
|
|
|
|
|
|
<el-table v-if="form.changePaymentMethodList?.length" :data="form.changePaymentMethodList" border max-height="200">
|
|
|
|
|
|
<el-table-column type="index" label="序号" width="55" />
|
|
|
|
|
|
<el-table-column prop="paymentDescription" label="付款条款" min-width="200" />
|
|
|
|
|
|
<el-table-column prop="paymentAmount" label="支付金额" width="120" />
|
|
|
|
|
|
<el-table-column prop="paymentPercentage" label="支付比例(%)" width="100" />
|
|
|
|
|
|
</el-table>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<el-form-item label="备注" prop="remark">
|
|
|
|
|
|
<el-input v-model="form.remark" type="textarea" placeholder="选填" />
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item>
|
|
|
|
|
|
<el-button type="primary" :loading="buttonLoading" @click="submitSave">暂存</el-button>
|
|
|
|
|
|
<el-button @click="goBack">取消</el-button>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup name="ContractChangeApply" lang="ts">
|
|
|
|
|
|
import { getContractInfo } from '@/api/oa/erp/contractInfo';
|
|
|
|
|
|
import { getErpContractInfoList } from '@/api/oa/erp/contractInfo';
|
|
|
|
|
|
import { saveContractChange, getContractChangeDetail } from '@/api/oa/erp/contractChange';
|
|
|
|
|
|
import type { ContractChangeSaveForm } from '@/api/oa/erp/contractChange/types';
|
|
|
|
|
|
|
|
|
|
|
|
const route = useRoute();
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
|
|
|
|
|
const { contract_change_type } = toRefs<any>(proxy?.useDict('contract_change_type'));
|
|
|
|
|
|
|
|
|
|
|
|
const formRef = ref<ElFormInstance>();
|
|
|
|
|
|
const buttonLoading = ref(false);
|
|
|
|
|
|
const activatedContractList = ref<any[]>([]);
|
|
|
|
|
|
|
|
|
|
|
|
const contractChangeId = computed(() => route.params.contractChangeId as string);
|
|
|
|
|
|
const isEdit = computed(() => !!contractChangeId.value);
|
|
|
|
|
|
|
|
|
|
|
|
const form = ref<ContractChangeSaveForm & { changeInfo?: any; changeMaterialList?: any[]; changePaymentMethodList?: any[] }>({
|
|
|
|
|
|
contractChangeId: undefined,
|
|
|
|
|
|
contractId: undefined as any,
|
|
|
|
|
|
changeType: '1',
|
|
|
|
|
|
changeReason: '',
|
|
|
|
|
|
applyTime: undefined,
|
|
|
|
|
|
remark: undefined,
|
|
|
|
|
|
changeStatus: '1',
|
|
|
|
|
|
activeFlag: '1',
|
|
|
|
|
|
contractCode: undefined,
|
|
|
|
|
|
contractName: undefined,
|
|
|
|
|
|
originalCustomerName: undefined,
|
|
|
|
|
|
originalContractAmount: undefined,
|
|
|
|
|
|
changeContractCode: undefined,
|
|
|
|
|
|
changeContractName: undefined,
|
|
|
|
|
|
customerName: undefined,
|
|
|
|
|
|
changeContractAmount: undefined,
|
|
|
|
|
|
changeInfo: undefined,
|
|
|
|
|
|
changeMaterialList: undefined,
|
|
|
|
|
|
changePaymentMethodList: undefined
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const rules = {
|
|
|
|
|
|
changeType: [{ required: true, message: '请选择变更类型', trigger: 'change' }],
|
|
|
|
|
|
contractId: [{ required: true, message: '请选择合同', trigger: 'change' }],
|
|
|
|
|
|
changeReason: [{ required: true, message: '请输入变更原因', trigger: 'blur' }]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function goBack() {
|
|
|
|
|
|
proxy?.$tab.closePage(route);
|
|
|
|
|
|
router.push({ path: '/oa/erp/contractChange' });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function loadActivatedContracts() {
|
|
|
|
|
|
const res = await getErpContractInfoList({ contractStatus: '3', activeFlag: '1' });
|
|
|
|
|
|
activatedContractList.value = res.data || [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function onContractChange(contractId: string | number) {
|
|
|
|
|
|
if (!contractId || form.value.changeType !== '1') return;
|
|
|
|
|
|
const res = await getContractInfo(contractId);
|
|
|
|
|
|
const c = res.data;
|
|
|
|
|
|
if (!c) return;
|
|
|
|
|
|
form.value.contractCode = c.contractCode;
|
|
|
|
|
|
form.value.contractName = c.contractName;
|
|
|
|
|
|
form.value.originalCustomerName = c.oneCustomerName || c.twoCustomerName;
|
|
|
|
|
|
form.value.originalContractAmount = c.totalPrice as any;
|
|
|
|
|
|
form.value.changeContractCode = c.contractCode;
|
|
|
|
|
|
form.value.changeContractName = c.contractName;
|
|
|
|
|
|
form.value.customerName = c.oneCustomerName || c.twoCustomerName;
|
|
|
|
|
|
form.value.changeContractAmount = c.totalPrice as any;
|
|
|
|
|
|
form.value.changeInfo = c ? mapContractToChangeInfo(c) : undefined;
|
|
|
|
|
|
form.value.changeMaterialList = (c.contractMaterialList || []).map((m: any) => ({
|
|
|
|
|
|
...m,
|
|
|
|
|
|
changeMaterialId: undefined,
|
|
|
|
|
|
contractChangeId: undefined
|
|
|
|
|
|
}));
|
|
|
|
|
|
form.value.changePaymentMethodList = (c.contractPaymentMethodList || []).map((p: any) => ({
|
|
|
|
|
|
...p,
|
|
|
|
|
|
changePaymentId: undefined,
|
|
|
|
|
|
contractChangeId: undefined
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function mapContractToChangeInfo(c: any) {
|
|
|
|
|
|
const info: any = {};
|
|
|
|
|
|
const keys = [
|
|
|
|
|
|
'contractFlag', 'customerContractCode', 'contractCode', 'contractName', 'contractCategory', 'contractType',
|
|
|
|
|
|
'businessDirection', 'contractDeptId', 'contractDate', 'totalPrice', 'oneCustomerId', 'oneRepresent', 'oneDate',
|
|
|
|
|
|
'twoCustomerId', 'twoRepresent', 'twoDate', 'contractManagerId', 'templateId', 'ossId', 'paymentAccountId',
|
|
|
|
|
|
'paymentMethod', 'signatureAppendix', 'warrantyPeriod', 'internalContractCode', 'externalContractCode',
|
|
|
|
|
|
'orderContractCode', 'projectContractCode', 'deliveryStart', 'warrantyPeriodDescription', 'deliveryLocation',
|
|
|
|
|
|
'shipMethod', 'taxRate', 'signingPlace', 'materialRemark', 'contractTemplateFlag', 'capitalizedAmount', 'remark'
|
|
|
|
|
|
];
|
|
|
|
|
|
keys.forEach(k => { if (c[k] !== undefined) info[k] = c[k]; });
|
|
|
|
|
|
info.changeInfoId = undefined;
|
|
|
|
|
|
info.contractChangeId = undefined;
|
|
|
|
|
|
return info;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function loadDetail() {
|
|
|
|
|
|
if (!contractChangeId.value) return;
|
|
|
|
|
|
const res = await getContractChangeDetail(contractChangeId.value);
|
|
|
|
|
|
const d = res.data;
|
|
|
|
|
|
if (!d?.main) return;
|
|
|
|
|
|
const m = d.main;
|
|
|
|
|
|
form.value.contractChangeId = m.contractChangeId;
|
|
|
|
|
|
form.value.contractId = m.contractId;
|
|
|
|
|
|
form.value.changeType = m.changeType;
|
|
|
|
|
|
form.value.changeReason = m.changeReason;
|
|
|
|
|
|
form.value.changeCode = m.changeCode;
|
|
|
|
|
|
form.value.applyTime = m.applyTime;
|
|
|
|
|
|
form.value.remark = m.remark;
|
|
|
|
|
|
form.value.contractCode = m.contractCode;
|
|
|
|
|
|
form.value.contractName = m.contractName;
|
|
|
|
|
|
form.value.originalCustomerName = m.originalCustomerName;
|
|
|
|
|
|
form.value.originalContractAmount = m.originalContractAmount;
|
|
|
|
|
|
form.value.changeContractCode = m.changeContractCode;
|
|
|
|
|
|
form.value.changeContractName = m.changeContractName;
|
|
|
|
|
|
form.value.customerName = m.customerName;
|
|
|
|
|
|
form.value.changeContractAmount = m.changeContractAmount;
|
|
|
|
|
|
form.value.changeInfo = d.changeInfo ? { ...d.changeInfo } : undefined;
|
|
|
|
|
|
form.value.changeMaterialList = (d.changeMaterialList || []).map((x: any) => ({ ...x }));
|
|
|
|
|
|
form.value.changePaymentMethodList = (d.changePaymentMethodList || []).map((x: any) => ({ ...x }));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function buildPayload(): ContractChangeSaveForm {
|
|
|
|
|
|
const f = form.value;
|
|
|
|
|
|
const payload: ContractChangeSaveForm = {
|
|
|
|
|
|
contractChangeId: f.contractChangeId,
|
|
|
|
|
|
contractId: f.contractId,
|
|
|
|
|
|
changeType: f.changeType,
|
|
|
|
|
|
changeReason: f.changeReason,
|
|
|
|
|
|
applyTime: f.applyTime || new Date().toISOString().slice(0, 19).replace('T', ' '),
|
|
|
|
|
|
remark: f.remark,
|
|
|
|
|
|
changeStatus: '1',
|
|
|
|
|
|
activeFlag: '1',
|
|
|
|
|
|
contractCode: f.contractCode,
|
|
|
|
|
|
contractName: f.contractName,
|
|
|
|
|
|
originalCustomerName: f.originalCustomerName,
|
|
|
|
|
|
originalContractAmount: f.originalContractAmount,
|
|
|
|
|
|
changeContractCode: f.changeContractCode,
|
|
|
|
|
|
changeContractName: f.changeContractName,
|
|
|
|
|
|
customerName: f.customerName,
|
|
|
|
|
|
changeContractAmount: f.changeContractAmount
|
|
|
|
|
|
};
|
|
|
|
|
|
if (f.changeType === '1') {
|
|
|
|
|
|
payload.changeInfo = f.changeInfo;
|
|
|
|
|
|
payload.changeMaterialList = f.changeMaterialList;
|
|
|
|
|
|
payload.changePaymentMethodList = f.changePaymentMethodList;
|
|
|
|
|
|
}
|
|
|
|
|
|
return payload;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function submitSave() {
|
|
|
|
|
|
await formRef.value?.validate().catch(() => {});
|
|
|
|
|
|
buttonLoading.value = true;
|
|
|
|
|
|
try {
|
|
|
|
|
|
const payload = buildPayload();
|
|
|
|
|
|
await saveContractChange(payload);
|
|
|
|
|
|
proxy?.$modal.msgSuccess('保存成功');
|
|
|
|
|
|
goBack();
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
buttonLoading.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
await loadActivatedContracts();
|
|
|
|
|
|
if (isEdit.value) {
|
|
|
|
|
|
await loadDetail();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
form.value.changeType = '1';
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|