|
|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div class="project-budget-container">
|
|
|
|
|
<div class="project-budget-container" v-loading="loading">
|
|
|
|
|
<!-- 审批按钮组件 -->
|
|
|
|
|
<approvalButton
|
|
|
|
|
@submitForm="handleSave"
|
|
|
|
|
@ -27,19 +27,17 @@
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="6">
|
|
|
|
|
<el-form-item label="版本号">
|
|
|
|
|
<el-input v-model="searchForm.budgetVersion" disabled>
|
|
|
|
|
</el-input>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="6">
|
|
|
|
|
<el-form-item label="申请说明">
|
|
|
|
|
<el-input v-model="searchForm.remark" type="textarea" placeholder="请输入申请说明" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="6">
|
|
|
|
|
<el-form-item label="版本号">
|
|
|
|
|
<el-input v-model="searchForm.budgetVersion" disabled> </el-input>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="6">
|
|
|
|
|
<el-form-item label="申请说明">
|
|
|
|
|
<el-input v-model="searchForm.remark" type="textarea" placeholder="请输入申请说明" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
|
|
<!-- <el-col :span="12" class="text-right">-->
|
|
|
|
|
<!-- <el-button type="primary" @click="exportBudget" size="default">-->
|
|
|
|
|
@ -55,7 +53,10 @@
|
|
|
|
|
<!-- 研发项目预算 -->
|
|
|
|
|
<el-card class="mb-6" v-if="searchForm.projectCategory === PROJECT_CATEGORY.RD || searchForm.projectCategory === PROJECT_CATEGORY.PRE_PRODUCTION">
|
|
|
|
|
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
|
|
|
|
<el-tab-pane label="预算表" name="budgetTable">
|
|
|
|
|
<el-tab-pane label="预算编制标准说明" name="budgetDefinition">
|
|
|
|
|
<RdBudgetDefinition ref="rdBudgetDefinitionRef" :projectId="searchForm.projectId" />
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="表1-预算汇总" name="budgetTable">
|
|
|
|
|
<RdBudgetTable
|
|
|
|
|
ref="rdBudgetTableRef"
|
|
|
|
|
:projectId="searchForm.projectId"
|
|
|
|
|
@ -64,25 +65,22 @@
|
|
|
|
|
:userList="userList"
|
|
|
|
|
/>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="设备费" name="equipmentCost">
|
|
|
|
|
<RdEquipmentCost ref="rdEquipmentCostRef" :projectId="searchForm.projectId" />
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="材料费" name="materialCost">
|
|
|
|
|
<el-tab-pane label="表2-材料费" name="materialCost">
|
|
|
|
|
<RdMaterialCost ref="rdMaterialCostRef" :projectId="searchForm.projectId" />
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="会议差旅交流" name="travelMeetingExchange">
|
|
|
|
|
<RdTravelMeetingExchange ref="rdTravelMeetingExchangeRef" :projectId="searchForm.projectId" />
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="人工劳务咨询" name="laborService">
|
|
|
|
|
<el-tab-pane label="表3-人工费" name="laborService">
|
|
|
|
|
<RdLaborService ref="rdLaborServiceRef" :projectId="searchForm.projectId" />
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="资料文献费" name="literatureCost">
|
|
|
|
|
<RdLiteratureCost ref="rdLiteratureCostRef" :projectId="searchForm.projectId" />
|
|
|
|
|
<el-tab-pane label="表4-差旅费" name="travelMeetingExchange">
|
|
|
|
|
<RdTravelMeetingExchange ref="rdTravelMeetingExchangeRef" :projectId="searchForm.projectId" />
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="测试化验费" name="testingCost">
|
|
|
|
|
<el-tab-pane label="表5-测试化验加工费" name="testingCost">
|
|
|
|
|
<RdTestingCost ref="rdTestingCostRef" :projectId="searchForm.projectId" />
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="其他" name="otherCost">
|
|
|
|
|
<el-tab-pane label="表6-咨询费、设计费" name="techCost">
|
|
|
|
|
<RdTechCost ref="rdTechCostRef" :projectId="searchForm.projectId" />
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="表7-其他费用" name="otherCost">
|
|
|
|
|
<RdOtherCost ref="rdOtherCostRef" :projectId="searchForm.projectId" />
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
</el-tabs>
|
|
|
|
|
@ -190,7 +188,14 @@
|
|
|
|
|
<script setup lang="ts" name="BudgetInfoEdit">
|
|
|
|
|
import { ref, reactive } from 'vue';
|
|
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
|
|
import { listProjectInfo, addErpBudgetInfo, updateErpBudgetInfo, changeErpBudgetInfo, getErpBudgetInfo } from '@/api/oa/erp/budgetInfo';
|
|
|
|
|
import {
|
|
|
|
|
listProjectInfo,
|
|
|
|
|
addErpBudgetInfo,
|
|
|
|
|
updateErpBudgetInfo,
|
|
|
|
|
changeErpBudgetInfo,
|
|
|
|
|
getErpBudgetInfo,
|
|
|
|
|
getRdBudgetDefinitionList
|
|
|
|
|
} from '@/api/oa/erp/budgetInfo';
|
|
|
|
|
import { ProjectInfoVO, ProjectInfoQuery } from '@/api/oa/erp/projectInfo/types';
|
|
|
|
|
import { getUserList } from '@/api/system/user';
|
|
|
|
|
|
|
|
|
|
@ -205,12 +210,12 @@ const { business_direction, project_status, project_category } = toRefs<any>(
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
//研发项目tab
|
|
|
|
|
import RdBudgetDefinition from './rd/BudgetDefinition.vue';
|
|
|
|
|
import RdBudgetTable from './rd/BudgetTable.vue';
|
|
|
|
|
import RdEquipmentCost from './rd/EquipmentCost.vue';
|
|
|
|
|
import RdMaterialCost from './rd/MaterialCost.vue';
|
|
|
|
|
import RdTravelMeetingExchange from './rd/TravelMeetingExchange.vue';
|
|
|
|
|
import RdLaborService from './rd/LaborService.vue';
|
|
|
|
|
import RdLiteratureCost from './rd/LiteratureCost.vue';
|
|
|
|
|
import RdTechCost from './rd/TechCost.vue';
|
|
|
|
|
import RdTestingCost from './rd/TestingCost.vue';
|
|
|
|
|
import RdOtherCost from './rd/OtherCost.vue';
|
|
|
|
|
|
|
|
|
|
@ -222,6 +227,8 @@ import InstallationCost from './market/InstallationCost.vue';
|
|
|
|
|
import TravelCost from './market/TravelCost.vue';
|
|
|
|
|
import OtherCost from './market/OtherCost.vue';
|
|
|
|
|
|
|
|
|
|
const loading = ref(true);
|
|
|
|
|
|
|
|
|
|
// 定义成本数据类型
|
|
|
|
|
interface CostData {
|
|
|
|
|
equipmentCost: number;
|
|
|
|
|
@ -238,12 +245,12 @@ interface CostData {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 研发项目预算tab组件引用
|
|
|
|
|
const rdBudgetDefinitionRef = ref();
|
|
|
|
|
const rdBudgetTableRef = ref();
|
|
|
|
|
const rdEquipmentCostRef = ref();
|
|
|
|
|
const rdMaterialCostRef = ref();
|
|
|
|
|
const rdTravelMeetingExchangeRef = ref();
|
|
|
|
|
const rdLaborServiceRef = ref();
|
|
|
|
|
const rdLiteratureCostRef = ref();
|
|
|
|
|
const rdTechCostRef = ref();
|
|
|
|
|
const rdTestingCostRef = ref();
|
|
|
|
|
const rdOtherCostRef = ref();
|
|
|
|
|
|
|
|
|
|
@ -261,20 +268,15 @@ const oriBudgetInstallCostList = ref<budgetInstallCostVO[]>([]);
|
|
|
|
|
const oriBudgetTravelCostList = ref<budgetTravelCostVO[]>([]);
|
|
|
|
|
const oriBudgetOtherCostList = ref<budgetOtherCostVO[]>([]);
|
|
|
|
|
|
|
|
|
|
const oriRdBudgetEquipmentCostList = ref<rdBudgetEquipmentCostVO[]>([]);
|
|
|
|
|
const oriRdBudgetMaterialCostList = ref<rdBudgetMaterialCostVO[]>([]);
|
|
|
|
|
const oriRdBudgetTravelCostList = ref<rdBudgetTravelCostVO[]>([]);
|
|
|
|
|
const oriRdBudgetMeetingCostList = ref<rdBudgetMeetingCostVO[]>([]);
|
|
|
|
|
const oriRdBudgetExchangeCostList = ref<rdBudgetExchangeCostVO[]>([]);
|
|
|
|
|
const oriRdBudgetTechConsultCostList = ref<rdBudgetTechCostVO[]>([]); //技术咨询
|
|
|
|
|
const oriRdBudgetLaborCostList = ref<rdBudgetLaborCostVO[]>([]); //人工费
|
|
|
|
|
const oriRdBudgetTravelCostList = ref<rdBudgetTravelCostVO[]>([]); //差旅费-差旅费
|
|
|
|
|
const oriRdBudgetTransportationCostList = ref<rdBudgetTravelCostVO[]>([]); //差旅费-交通费
|
|
|
|
|
const oriRdBudgetTestingCostList = ref<rdBudgetTestingCostVO[]>([]); //测试化验加工费
|
|
|
|
|
const oriRdBudgetTechConsultCostList = ref<rdBudgetTechCostVO[]>([]); //新产品设计费
|
|
|
|
|
const oriRdBudgetExpertMeetingCostList = ref<rdBudgetTechCostVO[]>([]); //专家咨询会议形式
|
|
|
|
|
const oriRdBudgetExpertCommCostList = ref<rdBudgetTechCostVO[]>([]); //专家咨询通讯形式
|
|
|
|
|
const oriRdBudgetLaborCostList = ref<rdBudgetLaborCostVO[]>([]); //人工费
|
|
|
|
|
const oriRdBudgetServiceCostList = ref<rdBudgetLaborCostVO[]>([]); //劳务费
|
|
|
|
|
const oriRdBudgetLiteratureMaterialCostList = ref<rdBudgetLiteratureCostVO[]>([]); //资料费
|
|
|
|
|
const oriRdBudgetLiteratureSofwareCostList = ref<rdBudgetLiteratureCostVO[]>([]); //专用软件购买费
|
|
|
|
|
const oriRdBudgetTestingCostList = ref<rdBudgetTestingCostVO[]>([]);
|
|
|
|
|
const oriRdBudgetOtherCostList = ref<rdBudgetOtherCostVO[]>([]);
|
|
|
|
|
const oriRdBudgetOtherCostList = ref<rdBudgetOtherCostVO[]>([]); //其他费用
|
|
|
|
|
|
|
|
|
|
const PROJECT_CATEGORY = reactive({
|
|
|
|
|
MARKET: '1', //销售(实施、物流)
|
|
|
|
|
@ -289,26 +291,15 @@ const BUSINESS_STATUS = reactive({
|
|
|
|
|
AVAILABLE: '3' //可用
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const MATERIAL_TYPE = {
|
|
|
|
|
MAIN: '1', //主要材料费
|
|
|
|
|
OTHER: '2' //其他材料费
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const TECH_TYPE = reactive({
|
|
|
|
|
TECH_CONSULT: '1', //技术咨询开发
|
|
|
|
|
TECH_CONSULT: '1', //新产品设计费
|
|
|
|
|
EXPERT_MEETING: '2', //专家咨询-会议形式
|
|
|
|
|
EXPERT_COMM: '3' //专家咨询-通讯形式
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const LABOR_TYPE = reactive({
|
|
|
|
|
LABOR: '1', //人工费
|
|
|
|
|
SERVICE: '2' //劳务费
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const LITERATURE_TYPE = {
|
|
|
|
|
MATERIAL: '1', //资料费
|
|
|
|
|
DOCUMENT: '2', //文件检索费
|
|
|
|
|
SOFTWARE: '3' //专用软件购买费
|
|
|
|
|
const TRIP_TYPE = {
|
|
|
|
|
TRAVEL: '1', //差旅费
|
|
|
|
|
TRANSPORTATION: '2' //交通费
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 响应式数据
|
|
|
|
|
@ -478,66 +469,6 @@ const confirmProjectSelection = () => {
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 设备费更新处理
|
|
|
|
|
const handleEquipmentCostUpdate = (data: { equipmentCost: number }) => {
|
|
|
|
|
costData.equipmentCost = data.equipmentCost;
|
|
|
|
|
if (rdBudgetTableRef.value) {
|
|
|
|
|
rdBudgetTableRef.value.updateCostData(costData);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 材料费更新处理
|
|
|
|
|
const handleMaterialCostUpdate = (data: { mainMaterialCost: number; otherMaterialCost: number; totalAmount: number }) => {
|
|
|
|
|
costData.materialCost = data.materialCost;
|
|
|
|
|
if (rdBudgetTableRef.value) {
|
|
|
|
|
rdBudgetTableRef.value.updateCostData(costData);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 会议差旅交流更新处理
|
|
|
|
|
const handleTravelMeetingExchangeUpdate = (data: { travelCost: number; meetingCost: number; internationalExchangeCost: number }) => {
|
|
|
|
|
costData.travelCost = data.travelCost;
|
|
|
|
|
costData.meetingCost = data.meetingCost;
|
|
|
|
|
costData.internationalExchangeCost = data.internationalExchangeCost;
|
|
|
|
|
if (rdBudgetTableRef.value) {
|
|
|
|
|
rdBudgetTableRef.value.updateCostData(costData);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 人工劳务咨询更新处理
|
|
|
|
|
const handleLaborServiceUpdate = (data: { techConsultTotal: number; laborTotal: number; serviceTotal: number }) => {
|
|
|
|
|
costData.consultingDevelopmentCost = data.techConsultTotal;
|
|
|
|
|
costData.laborCost = data.laborTotal;
|
|
|
|
|
costData.serviceCost = data.serviceTotal;
|
|
|
|
|
if (rdBudgetTableRef.value) {
|
|
|
|
|
rdBudgetTableRef.value.updateCostData(costData);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 资料文献费更新处理
|
|
|
|
|
const handleLiteratureCostUpdate = (data: { literatureCost: number }) => {
|
|
|
|
|
costData.literatureCost = data.literatureCost;
|
|
|
|
|
if (rdBudgetTableRef.value) {
|
|
|
|
|
rdBudgetTableRef.value.updateCostData(costData);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 测试化验费更新处理
|
|
|
|
|
const handleTestingCostUpdate = (data: { totalAmount: number }) => {
|
|
|
|
|
costData.testingCost = data.totalAmount;
|
|
|
|
|
if (rdBudgetTableRef.value) {
|
|
|
|
|
rdBudgetTableRef.value.updateCostData(costData);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 其他费用更新处理
|
|
|
|
|
const handleOtherCostUpdate = (data: { totalAmount: number }) => {
|
|
|
|
|
costData.otherCost = data.totalAmount;
|
|
|
|
|
if (rdBudgetTableRef.value) {
|
|
|
|
|
rdBudgetTableRef.value.updateCostData(costData);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 更新市场项目预算预算表数据
|
|
|
|
|
const updateBudgetTable = async () => {
|
|
|
|
|
if (!budgetTableRef.value) return;
|
|
|
|
|
@ -560,75 +491,31 @@ const updateBudgetTable = async () => {
|
|
|
|
|
// 更新研发项目预算预算表数据
|
|
|
|
|
const updateRdBudgetTable = async () => {
|
|
|
|
|
// 获取各tab页的合计数据
|
|
|
|
|
const equipmentAmount = rdEquipmentCostRef.value?.getTotalAmount();
|
|
|
|
|
const equipmentTotal = equipmentAmount.equipmentTotal || 0;
|
|
|
|
|
const materialTotal = rdMaterialCostRef.value?.getTotalAmount() || 0;
|
|
|
|
|
const travelMeetingExchangeAmount = rdTravelMeetingExchangeRef.value?.getTravelMeetingExchangeAmount();
|
|
|
|
|
const travelTotal = travelMeetingExchangeAmount.travelSubtotalTotal || 0;
|
|
|
|
|
const meetingFeeTotal = travelMeetingExchangeAmount.meetingFeeTotal || 0;
|
|
|
|
|
const internationalSubtotalTotal = travelMeetingExchangeAmount.internationalSubtotalTotal || 0;
|
|
|
|
|
const laborAmount = rdLaborServiceRef.value?.getLaborAmount();
|
|
|
|
|
const techConsultTotal = laborAmount.techConsultTotal || 0;
|
|
|
|
|
const laborTotal = laborAmount.laborTotal || 0;
|
|
|
|
|
const serviceTotal = laborAmount.serviceTotal || 0;
|
|
|
|
|
const literatureCost = rdLiteratureCostRef.value?.getLiteratureCost() || 0;
|
|
|
|
|
const literatureTotal = literatureCost.literatureTotal || 0;
|
|
|
|
|
|
|
|
|
|
const techCost = rdTechCostRef.value?.getTechAmount() || 0;
|
|
|
|
|
const expertConsultTotal = techCost.expertConsultTotal || 0;
|
|
|
|
|
const techConsultTotal = techCost.techConsultTotal || 0;
|
|
|
|
|
|
|
|
|
|
const travelMeetingExchangeAmount = rdTravelMeetingExchangeRef.value?.getTravelAmount();
|
|
|
|
|
const travelTotal = travelMeetingExchangeAmount.travelSubtotalTotal || 0;
|
|
|
|
|
const testingCost = rdTestingCostRef.value?.getTestingAmount() || 0;
|
|
|
|
|
const testingTotal = testingCost.testingTotal || 0;
|
|
|
|
|
const otherCost = rdOtherCostRef.value?.getOtherCost() || 0;
|
|
|
|
|
const otherTotal = otherCost.otherTotal || 0;
|
|
|
|
|
|
|
|
|
|
// 更新预算表,目前是按单位是万元传值,后续如果根据单位是元,则在此判断更新传的值
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('设备费', equipmentTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('材料费', materialTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('差旅费', travelTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('会议费', meetingFeeTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('国际合作与交流费', internationalSubtotalTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('咨询开发费', techConsultTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('人工费', laborTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('劳务费', serviceTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('资料/文献费', literatureTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('测试化验费', testingTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('差旅费', travelTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('测试化验加工费', testingTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('专家咨询费用', expertConsultTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('新产品设计费', techConsultTotal / 10000);
|
|
|
|
|
rdBudgetTableRef.value.updateRdBudgetDetailData('其他费用', otherTotal / 10000);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 新增一个方法用于在tab切换时更新预算数据
|
|
|
|
|
const updateBudgetDataOnTabChange = () => {
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
if (searchForm.projectCategory === PROJECT_CATEGORY.RD) {
|
|
|
|
|
// 确保调用更新方法时传递正确的参数
|
|
|
|
|
if (rdEquipmentCostRef.value?.getTotalAmount) {
|
|
|
|
|
handleEquipmentCostUpdate({ equipmentCost: rdEquipmentCostRef.value.getTotalAmount() });
|
|
|
|
|
}
|
|
|
|
|
if (rdMaterialCostRef.value?.getTotalAmount) {
|
|
|
|
|
const materialTotal = rdMaterialCostRef.value.getTotalAmount();
|
|
|
|
|
handleMaterialCostUpdate({
|
|
|
|
|
mainMaterialCost: materialTotal.mainMaterialCost || 0,
|
|
|
|
|
otherMaterialCost: materialTotal.otherMaterialCost || 0,
|
|
|
|
|
materialCost: (materialTotal.mainMaterialCost || 0) + (materialTotal.otherMaterialCost || 0)
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// 其他方法类似处理...
|
|
|
|
|
} else if (searchForm.projectCategory === PROJECT_CATEGORY.MARKET) {
|
|
|
|
|
updateBudgetTable();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 监听tab切换,更新预算表数据
|
|
|
|
|
// watch(activeTab, () => {
|
|
|
|
|
// updateBudgetDataOnTabChange();
|
|
|
|
|
// });
|
|
|
|
|
// 导出预算
|
|
|
|
|
const exportBudget = () => {
|
|
|
|
|
if (!searchForm.projectId) {
|
|
|
|
|
ElMessage.warning('请先选择项目');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ElMessage.success('导出预算成功');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 提取用户查找逻辑
|
|
|
|
|
const findUserName = (userList: any[], userId: number): string => {
|
|
|
|
|
const user = userList?.find((item) => item.userId === userId);
|
|
|
|
|
@ -695,7 +582,7 @@ const processRdBudgetForm = async (status: string): Promise<budgetInfoForm> => {
|
|
|
|
|
|
|
|
|
|
const budgetDetailData = rdBudgetTableRef.value?.budgetDetailData || [];
|
|
|
|
|
const rdBudgetInfoForm = rdBudgetTableRef.value?.rdBudgetInfoForm || {};
|
|
|
|
|
const footerForm = rdBudgetTableRef.value?.footerForm || {};
|
|
|
|
|
rdBudgetInfoForm.budgetCost = rdBudgetTableRef.value?.totalAmount;
|
|
|
|
|
|
|
|
|
|
// 合并表单数据
|
|
|
|
|
const budgetForm = {
|
|
|
|
|
@ -704,10 +591,9 @@ const processRdBudgetForm = async (status: string): Promise<budgetInfoForm> => {
|
|
|
|
|
budgetStatus: getBudgetStatus(status),
|
|
|
|
|
flowStatus: getFlowStatus(status),
|
|
|
|
|
// 设置负责人信息
|
|
|
|
|
managerId: footerForm.managerId,
|
|
|
|
|
managerName: findUserName(userList.value, footerForm.managerId),
|
|
|
|
|
approveUserId: footerForm.approveUserId,
|
|
|
|
|
approveUserName: findUserName(userList.value, footerForm.approveUserId),
|
|
|
|
|
managerName: findUserName(userList.value, rdBudgetInfoForm.managerId),
|
|
|
|
|
productManagerName: findUserName(userList.value, rdBudgetInfoForm.productManagerId),
|
|
|
|
|
approveUserName: findUserName(userList.value, rdBudgetInfoForm.approveUserId),
|
|
|
|
|
// 预算详情
|
|
|
|
|
erpBudgetDetailList: budgetDetailData,
|
|
|
|
|
// 初始化所有成本列表
|
|
|
|
|
@ -764,15 +650,11 @@ const getFlowStatus = (status: string): string => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const initializeRdCostLists = () => ({
|
|
|
|
|
erpRdBudgetEquipmentCostList: [],
|
|
|
|
|
erpRdBudgetMaterialCostList: [],
|
|
|
|
|
erpRdBudgetTravelCostList: [],
|
|
|
|
|
erpRdBudgetMeetingCostList: [],
|
|
|
|
|
erpRdBudgetExchangeCostList: [],
|
|
|
|
|
erpRdBudgetTechCostList: [],
|
|
|
|
|
erpRdBudgetLaborCostList: [],
|
|
|
|
|
erpRdBudgetLiteratureCostList: [],
|
|
|
|
|
erpRdBudgetTravelCostList: [],
|
|
|
|
|
erpRdBudgetTestingCostList: [],
|
|
|
|
|
erpRdBudgetTechCostList: [],
|
|
|
|
|
erpRdBudgetOtherCostList: []
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@ -787,70 +669,35 @@ const initializeMarketCostLists = () => ({
|
|
|
|
|
// 处理研发成本数据
|
|
|
|
|
const processRdCostData = (budgetForm: budgetInfoForm) => {
|
|
|
|
|
// 设备成本
|
|
|
|
|
console.log(rdMaterialCostRef.value?.allMaterialData);
|
|
|
|
|
console.log(oriRdBudgetMaterialCostList.value);
|
|
|
|
|
if (assignIfChanged([], rdEquipmentCostRef.value?.equipmentData, oriRdBudgetEquipmentCostList.value).length) {
|
|
|
|
|
budgetForm.erpRdBudgetEquipmentCostList = rdEquipmentCostRef.value?.equipmentData || [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 材料成本
|
|
|
|
|
if (assignIfChanged([], rdMaterialCostRef.value?.allMaterialData, oriRdBudgetMaterialCostList.value).length) {
|
|
|
|
|
budgetForm.erpRdBudgetMaterialCostList = (rdMaterialCostRef.value?.allMaterialData || []).map(item => {
|
|
|
|
|
const newItem = { ...item };
|
|
|
|
|
|
|
|
|
|
// 如果 是其他材料费,需要将万元转为元
|
|
|
|
|
if (newItem.materialType === 2 || newItem.materialType === '2') {
|
|
|
|
|
if (newItem.price !== null && newItem.price !== undefined) {
|
|
|
|
|
const priceValue = parseFloat(newItem.price);
|
|
|
|
|
if (!isNaN(priceValue)) {
|
|
|
|
|
// 乘以10000
|
|
|
|
|
newItem.price = priceValue * 10000;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return newItem;
|
|
|
|
|
});
|
|
|
|
|
if (assignIfChanged([], rdMaterialCostRef.value?.materialData, oriRdBudgetMaterialCostList.value).length) {
|
|
|
|
|
budgetForm.erpRdBudgetMaterialCostList = rdMaterialCostRef.value?.materialData || [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 差旅、会议、交流成本
|
|
|
|
|
const travelMeetingExchangeRef = rdTravelMeetingExchangeRef.value;
|
|
|
|
|
if (assignIfChanged([], travelMeetingExchangeRef?.travelList, oriRdBudgetTravelCostList.value).length) {
|
|
|
|
|
budgetForm.erpRdBudgetTravelCostList = travelMeetingExchangeRef?.travelList || [];
|
|
|
|
|
}
|
|
|
|
|
if (assignIfChanged([], travelMeetingExchangeRef?.meetingList, oriRdBudgetMeetingCostList.value).length) {
|
|
|
|
|
budgetForm.erpRdBudgetMeetingCostList = travelMeetingExchangeRef?.meetingList || [];
|
|
|
|
|
}
|
|
|
|
|
if (assignIfChanged([], travelMeetingExchangeRef?.exchangeList, oriRdBudgetExchangeCostList.value).length) {
|
|
|
|
|
budgetForm.erpRdBudgetExchangeCostList = travelMeetingExchangeRef?.exchangeList || [];
|
|
|
|
|
// 人工成本
|
|
|
|
|
if (assignIfChanged([], rdLaborServiceRef.value?.laborList, oriRdBudgetLaborCostList.value).length) {
|
|
|
|
|
budgetForm.erpRdBudgetLaborCostList = rdLaborServiceRef.value?.laborList || [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 技术成本
|
|
|
|
|
const laborServiceRef = rdLaborServiceRef.value;
|
|
|
|
|
budgetForm.erpRdBudgetTechCostList = [
|
|
|
|
|
...assignIfChanged([], laborServiceRef?.techConsultList, oriRdBudgetTechConsultCostList.value),
|
|
|
|
|
...assignIfChanged([], laborServiceRef?.expertMeetingList, oriRdBudgetExpertMeetingCostList.value),
|
|
|
|
|
...assignIfChanged([], laborServiceRef?.expertCommList, oriRdBudgetExpertCommCostList.value)
|
|
|
|
|
// 差旅费成本
|
|
|
|
|
budgetForm.erpRdBudgetTravelCostList = [
|
|
|
|
|
...assignIfChanged([], rdTravelMeetingExchangeRef.value?.travelList, oriRdBudgetTravelCostList.value),
|
|
|
|
|
...assignIfChanged([], rdTravelMeetingExchangeRef.value?.transportationList, oriRdBudgetTransportationCostList.value)
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// 劳务成本
|
|
|
|
|
budgetForm.erpRdBudgetLaborCostList = [
|
|
|
|
|
...assignIfChanged([], laborServiceRef?.laborList, oriRdBudgetLaborCostList.value),
|
|
|
|
|
...assignIfChanged([], laborServiceRef?.serviceList, oriRdBudgetServiceCostList.value)
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// 文献成本
|
|
|
|
|
const literatureCostRef = rdLiteratureCostRef.value;
|
|
|
|
|
budgetForm.erpRdBudgetLiteratureCostList = [
|
|
|
|
|
...assignIfChanged([], literatureCostRef?.materialsList, oriRdBudgetLiteratureMaterialCostList.value),
|
|
|
|
|
...assignIfChanged([], literatureCostRef?.softwareList, oriRdBudgetLiteratureSofwareCostList.value),
|
|
|
|
|
literatureCostRef?.literatureRetrieval || {}
|
|
|
|
|
].filter((item) => Object.keys(item).length > 0);
|
|
|
|
|
|
|
|
|
|
// 测试成本
|
|
|
|
|
// 测试化验加工成本
|
|
|
|
|
if (assignIfChanged([], rdTestingCostRef.value?.testData, oriRdBudgetTestingCostList.value).length) {
|
|
|
|
|
budgetForm.erpRdBudgetTestingCostList = rdTestingCostRef.value?.testData || [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 咨询费、设计费
|
|
|
|
|
budgetForm.erpRdBudgetTechCostList = [
|
|
|
|
|
...assignIfChanged([], rdTechCostRef.value?.techConsultList, oriRdBudgetTechConsultCostList.value),
|
|
|
|
|
...assignIfChanged([], rdTechCostRef.value?.expertMeetingList, oriRdBudgetExpertMeetingCostList.value),
|
|
|
|
|
...assignIfChanged([], rdTechCostRef.value?.expertCommList, oriRdBudgetExpertCommCostList.value)
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// 其他成本
|
|
|
|
|
if (assignIfChanged([], rdOtherCostRef.value?.otherCostList, oriRdBudgetOtherCostList.value).length) {
|
|
|
|
|
budgetForm.erpRdBudgetOtherCostList = rdOtherCostRef.value?.otherCostList || [];
|
|
|
|
|
@ -860,24 +707,19 @@ const processRdCostData = (budgetForm: budgetInfoForm) => {
|
|
|
|
|
// 设置研发删除列表
|
|
|
|
|
const setRdToDeletedLists = (budgetForm: budgetInfoForm) => {
|
|
|
|
|
const refs = {
|
|
|
|
|
equipment: rdEquipmentCostRef.value,
|
|
|
|
|
material: rdMaterialCostRef.value,
|
|
|
|
|
travelMeetingExchange: rdTravelMeetingExchangeRef.value,
|
|
|
|
|
laborService: rdLaborServiceRef.value,
|
|
|
|
|
literature: rdLiteratureCostRef.value,
|
|
|
|
|
testing: rdTestingCostRef.value,
|
|
|
|
|
tech: rdTechCostRef.value,
|
|
|
|
|
other: rdOtherCostRef.value
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
budgetForm.toDeletedRdEquipmentCostIdList = refs.equipment?.toDeletedEquipmentCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdMaterialCostIdList = refs.material?.toDeletedMaterialCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdTravelCostIdList = refs.travelMeetingExchange?.toDeletedTravelCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdMeetingCostIdList = refs.travelMeetingExchange?.toDeletedMeetingCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdExchangeCostIdList = refs.travelMeetingExchange?.toDeletedExchangeCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdTechCostIdList = refs.laborService?.toDeletedTechCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdLaborCostIdList = refs.laborService?.toDeletedLaborCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdLiteratureCostIdList = refs.literature?.toDeletedLiteratureCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdTravelCostIdList = refs.travelMeetingExchange?.toDeletedTravelCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdTestingCostIdList = refs.testing?.toDeletedTestCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdTechCostIdList = refs.tech?.toDeletedTechCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdOtherCostIdList = refs.other?.toDeletedOtherCostIdList;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@ -931,14 +773,10 @@ const budgetId = ref();
|
|
|
|
|
// 定义不同类型的主键字段映射
|
|
|
|
|
const PRIMARY_KEY_MAP = {
|
|
|
|
|
// 研发预算相关
|
|
|
|
|
erpRdBudgetEquipmentCostList: 'equipmentCostId',
|
|
|
|
|
erpRdBudgetMaterialCostList: 'materialCostId',
|
|
|
|
|
erpRdBudgetTravelCostList: 'travelCostId',
|
|
|
|
|
erpRdBudgetMeetingCostList: 'meetingCostId',
|
|
|
|
|
erpRdBudgetExchangeCostList: 'exchangeCostId',
|
|
|
|
|
erpRdBudgetTechCostList: 'techCostId',
|
|
|
|
|
erpRdBudgetLaborCostList: 'laborCostId',
|
|
|
|
|
erpRdBudgetLiteratureCostList: 'literatureCostId',
|
|
|
|
|
erpRdBudgetTestingCostList: 'testingCostId',
|
|
|
|
|
erpRdBudgetOtherCostList: 'otherCostId',
|
|
|
|
|
|
|
|
|
|
@ -973,16 +811,22 @@ async function loadBudgetData() {
|
|
|
|
|
await getUsers();
|
|
|
|
|
|
|
|
|
|
if (!budgetId.value || !['update', 'view', 'approval'].includes(routeParams.value.type as string)) {
|
|
|
|
|
handleAddMode();
|
|
|
|
|
return;
|
|
|
|
|
await handleAddMode();
|
|
|
|
|
} else {
|
|
|
|
|
await handleLoadMode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await handleLoadMode();
|
|
|
|
|
loading.value = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleAddMode() {
|
|
|
|
|
async function handleAddMode() {
|
|
|
|
|
searchForm.projectCategory = routeParams.value.projectCategory;
|
|
|
|
|
queryParams.value.projectCategory = searchForm.projectCategory;
|
|
|
|
|
if (isRdOrPreProductionCategory()) {
|
|
|
|
|
const rdBudgetDefinitionListData = await getRdBudgetDefinitionList();
|
|
|
|
|
if (rdBudgetDefinitionRef.value.budgetDefinitionData) {
|
|
|
|
|
rdBudgetDefinitionRef.value.budgetDefinitionData = rdBudgetDefinitionListData.data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleLoadMode() {
|
|
|
|
|
@ -1022,47 +866,15 @@ async function handleRdOrPreProductionData(data: any) {
|
|
|
|
|
initOriginalRdData(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 分组数据
|
|
|
|
|
const groupedMaterialData = groupByField(data.erpRdBudgetMaterialCostList, 'materialType');
|
|
|
|
|
groupedMaterialData[MATERIAL_TYPE.OTHER] = groupedMaterialData[MATERIAL_TYPE.OTHER].map(item => {
|
|
|
|
|
return {
|
|
|
|
|
...item,
|
|
|
|
|
unitPrice: undefined,
|
|
|
|
|
amount: undefined,
|
|
|
|
|
unitId: undefined,
|
|
|
|
|
// 转换为万元显示
|
|
|
|
|
price: item.price ? (item.price / 10000).toFixed(2) : ''
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const groupedTechData = groupByField(data.erpRdBudgetTechCostList, 'techType');
|
|
|
|
|
const groupedLaborData = groupByField(data.erpRdBudgetLaborCostList, 'laborType');
|
|
|
|
|
const groupedLiteratureData = groupByField(data.erpRdBudgetLiteratureCostList, 'literatureType');
|
|
|
|
|
|
|
|
|
|
const groupedTravelData = groupByField(data.erpRdBudgetTravelCostList, 'tripType');
|
|
|
|
|
// 获取并处理分类数据
|
|
|
|
|
const categorizedData = {
|
|
|
|
|
rdBudgetMainMaterialCostList: handleChangeTypeIds(groupedMaterialData[MATERIAL_TYPE.MAIN] || [], 'erpRdBudgetMaterialCostList', isChangeType),
|
|
|
|
|
rdBudgetOtherMaterialCostList: handleChangeTypeIds(groupedMaterialData[MATERIAL_TYPE.OTHER] || [], 'erpRdBudgetMaterialCostList', isChangeType),
|
|
|
|
|
rdBudgetTravelCostList: handleChangeTypeIds(groupedTravelData[TRIP_TYPE.TRAVEL] || [], 'erpRdBudgetTravelCostList', isChangeType),
|
|
|
|
|
rdBudgetTransportationCostList: handleChangeTypeIds(groupedTravelData[TRIP_TYPE.TRANSPORTATION] || [], 'erpRdBudgetTravelCostList', isChangeType),
|
|
|
|
|
rdBudgetTechConsultCostList: handleChangeTypeIds(groupedTechData[TECH_TYPE.TECH_CONSULT] || [], 'erpRdBudgetTechCostList', isChangeType),
|
|
|
|
|
rdBudgetExpertMeetingCostList: handleChangeTypeIds(groupedTechData[TECH_TYPE.EXPERT_MEETING] || [], 'erpRdBudgetTechCostList', isChangeType),
|
|
|
|
|
rdBudgetExpertCommCostList: handleChangeTypeIds(groupedTechData[TECH_TYPE.EXPERT_COMM] || [], 'erpRdBudgetTechCostList', isChangeType),
|
|
|
|
|
rdBudgetLaborCostList: handleChangeTypeIds(groupedLaborData[LABOR_TYPE.LABOR] || [], 'erpRdBudgetLaborCostList', isChangeType),
|
|
|
|
|
rdBudgetServiceCostList: handleChangeTypeIds(groupedLaborData[LABOR_TYPE.SERVICE] || [], 'erpRdBudgetLaborCostList', isChangeType),
|
|
|
|
|
rdBudgetLiteratureMaterialCostList: handleChangeTypeIds(
|
|
|
|
|
groupedLiteratureData[LITERATURE_TYPE.MATERIAL] || [],
|
|
|
|
|
'erpRdBudgetLiteratureCostList',
|
|
|
|
|
isChangeType
|
|
|
|
|
),
|
|
|
|
|
rdBudgetLiteratureSoftwareCostList: handleChangeTypeIds(
|
|
|
|
|
groupedLiteratureData[LITERATURE_TYPE.SOFTWARE] || [],
|
|
|
|
|
'erpRdBudgetLiteratureCostList',
|
|
|
|
|
isChangeType
|
|
|
|
|
),
|
|
|
|
|
rdBudgetLiteratureRetrievalCostList: handleChangeTypeIds(
|
|
|
|
|
groupedLiteratureData[LITERATURE_TYPE.DOCUMENT] || [],
|
|
|
|
|
'erpRdBudgetLiteratureCostList',
|
|
|
|
|
isChangeType
|
|
|
|
|
)
|
|
|
|
|
rdBudgetExpertCommCostList: handleChangeTypeIds(groupedTechData[TECH_TYPE.EXPERT_COMM] || [], 'erpRdBudgetTechCostList', isChangeType)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
await nextTick();
|
|
|
|
|
@ -1152,36 +964,27 @@ function groupByField(array: any[], field: string): Record<string, any[]> {
|
|
|
|
|
|
|
|
|
|
function initOriginalRdData(data: any) {
|
|
|
|
|
// 只保存原始数据,不处理变更逻辑
|
|
|
|
|
oriRdBudgetEquipmentCostList.value = deepClone(data.erpRdBudgetEquipmentCostList);
|
|
|
|
|
oriRdBudgetMaterialCostList.value = deepClone(data.erpRdBudgetMaterialCostList);
|
|
|
|
|
oriRdBudgetTravelCostList.value = deepClone(data.erpRdBudgetTravelCostList);
|
|
|
|
|
oriRdBudgetMeetingCostList.value = deepClone(data.erpRdBudgetMeetingCostList);
|
|
|
|
|
oriRdBudgetExchangeCostList.value = deepClone(data.erpRdBudgetExchangeCostList);
|
|
|
|
|
oriRdBudgetLaborCostList.value = deepClone(data.erpRdBudgetLaborCostList);
|
|
|
|
|
oriRdBudgetTestingCostList.value = deepClone(data.erpRdBudgetTestingCostList);
|
|
|
|
|
oriRdBudgetOtherCostList.value = deepClone(data.erpRdBudgetOtherCostList);
|
|
|
|
|
|
|
|
|
|
// 处理分组后的数据
|
|
|
|
|
// 处理差旅费分组后的数据
|
|
|
|
|
if (data.erpRdBudgetTravelCostList) {
|
|
|
|
|
const groupedTravelData = groupByField(data.erpRdBudgetTravelCostList, 'tripType');
|
|
|
|
|
oriRdBudgetTravelCostList.value = deepClone(groupedTravelData[TRIP_TYPE.TRAVEL] || []);
|
|
|
|
|
oriRdBudgetTransportationCostList.value = deepClone(groupedTravelData[TRIP_TYPE.TRANSPORTATION] || []);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理咨询费分组后的数据
|
|
|
|
|
if (data.erpRdBudgetTechCostList) {
|
|
|
|
|
const groupedTechData = groupByField(data.erpRdBudgetTechCostList, 'techType');
|
|
|
|
|
oriRdBudgetTechConsultCostList.value = deepClone(groupedTechData[TECH_TYPE.TECH_CONSULT] || []);
|
|
|
|
|
oriRdBudgetExpertMeetingCostList.value = deepClone(groupedTechData[TECH_TYPE.EXPERT_MEETING] || []);
|
|
|
|
|
oriRdBudgetExpertCommCostList.value = deepClone(groupedTechData[TECH_TYPE.EXPERT_COMM] || []);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (data.erpRdBudgetLaborCostList) {
|
|
|
|
|
const groupedLaborData = groupByField(data.erpRdBudgetLaborCostList, 'laborType');
|
|
|
|
|
oriRdBudgetLaborCostList.value = deepClone(groupedLaborData[LABOR_TYPE.LABOR] || []);
|
|
|
|
|
oriRdBudgetServiceCostList.value = deepClone(groupedLaborData[LABOR_TYPE.SERVICE] || []);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (data.erpRdBudgetLiteratureCostList) {
|
|
|
|
|
const groupedLiteratureData = groupByField(data.erpRdBudgetLiteratureCostList, 'literatureType');
|
|
|
|
|
oriRdBudgetLiteratureMaterialCostList.value = deepClone(groupedLiteratureData[LITERATURE_TYPE.MATERIAL] || []);
|
|
|
|
|
oriRdBudgetLiteratureSofwareCostList.value = deepClone(groupedLiteratureData[LITERATURE_TYPE.SOFTWARE] || []);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 修改 initOriginalMarketData 函数,移除 isChangeType 参数
|
|
|
|
|
function initOriginalMarketData(data: any) {
|
|
|
|
|
// 只保存原始数据,不处理变更逻辑
|
|
|
|
|
oriBudgetMaterialCostList.value = deepClone(data.erpBudgetMaterialCostList);
|
|
|
|
|
@ -1191,14 +994,18 @@ function initOriginalMarketData(data: any) {
|
|
|
|
|
oriBudgetOtherCostList.value = deepClone(data.erpBudgetOtherCostList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 研发数据赋值到组件(保持不变)
|
|
|
|
|
// 研发数据赋值到组件
|
|
|
|
|
function assignRdDataToComponents(data: any, categorizedData: any, isChangeType: boolean) {
|
|
|
|
|
if (!rdBudgetTableRef.value) return;
|
|
|
|
|
|
|
|
|
|
// 处理基础表单数据 - 如果是变更类型,清空预算ID
|
|
|
|
|
const formData = isChangeType ? processFormDataForChange(data, 'budgetId') : data;
|
|
|
|
|
Object.assign(rdBudgetTableRef.value.rdBudgetInfoForm, formData);
|
|
|
|
|
Object.assign(rdBudgetTableRef.value.footerForm, formData);
|
|
|
|
|
|
|
|
|
|
// 预算编制标准说明数据
|
|
|
|
|
if (rdBudgetDefinitionRef.value.budgetDefinitionData) {
|
|
|
|
|
rdBudgetDefinitionRef.value.budgetDefinitionData = data.budgetDefinitionDTOList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 处理预算明细数据
|
|
|
|
|
const budgetDetailList = isChangeType
|
|
|
|
|
@ -1210,101 +1017,36 @@ function assignRdDataToComponents(data: any, categorizedData: any, isChangeType:
|
|
|
|
|
rdBudgetTableRef.value.budgetDetailData = budgetDetailList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设备费数据 - 如果是变更类型,直接从 categorizedData 获取;否则从 ori 获取
|
|
|
|
|
const equipmentData = isChangeType
|
|
|
|
|
? handleChangeTypeIds(data.erpRdBudgetEquipmentCostList, 'erpRdBudgetEquipmentCostList', true)
|
|
|
|
|
: oriRdBudgetEquipmentCostList.value;
|
|
|
|
|
|
|
|
|
|
if (rdEquipmentCostRef.value?.equipmentData) {
|
|
|
|
|
rdEquipmentCostRef.value.equipmentData = deepClone(equipmentData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 材料费数据
|
|
|
|
|
if (rdMaterialCostRef.value) {
|
|
|
|
|
// 主要材料
|
|
|
|
|
if (rdMaterialCostRef.value.materialData) {
|
|
|
|
|
rdMaterialCostRef.value.materialData = deepClone(categorizedData.rdBudgetMainMaterialCostList);
|
|
|
|
|
}
|
|
|
|
|
const materialData = isChangeType
|
|
|
|
|
? handleChangeTypeIds(data.erpRdBudgetMaterialCostList, 'erpRdBudgetMaterialCostList', true)
|
|
|
|
|
: oriRdBudgetMaterialCostList.value;
|
|
|
|
|
|
|
|
|
|
// 其他材料(单个对象)
|
|
|
|
|
if (categorizedData.rdBudgetOtherMaterialCostList.length > 0) {
|
|
|
|
|
rdMaterialCostRef.value.otherMaterial = deepClone(categorizedData.rdBudgetOtherMaterialCostList[0]);
|
|
|
|
|
}
|
|
|
|
|
if (rdMaterialCostRef.value?.materialData) {
|
|
|
|
|
rdMaterialCostRef.value.materialData = deepClone(materialData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 差旅/会议/交流费数据
|
|
|
|
|
if (rdTravelMeetingExchangeRef.value) {
|
|
|
|
|
// 差旅费
|
|
|
|
|
const travelData = isChangeType
|
|
|
|
|
? handleChangeTypeIds(data.erpRdBudgetTravelCostList, 'erpRdBudgetTravelCostList', true)
|
|
|
|
|
: oriRdBudgetTravelCostList.value;
|
|
|
|
|
|
|
|
|
|
if (rdTravelMeetingExchangeRef.value.travelList) {
|
|
|
|
|
rdTravelMeetingExchangeRef.value.travelList = deepClone(travelData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 会议费
|
|
|
|
|
const meetingData = isChangeType
|
|
|
|
|
? handleChangeTypeIds(data.erpRdBudgetMeetingCostList, 'erpRdBudgetMeetingCostList', true)
|
|
|
|
|
: oriRdBudgetMeetingCostList.value;
|
|
|
|
|
|
|
|
|
|
if (rdTravelMeetingExchangeRef.value.meetingList) {
|
|
|
|
|
rdTravelMeetingExchangeRef.value.meetingList = deepClone(meetingData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 交流费
|
|
|
|
|
const exchangeData = isChangeType
|
|
|
|
|
? handleChangeTypeIds(data.erpRdBudgetExchangeCostList, 'erpRdBudgetExchangeCostList', true)
|
|
|
|
|
: oriRdBudgetExchangeCostList.value;
|
|
|
|
|
|
|
|
|
|
if (rdTravelMeetingExchangeRef.value.exchangeList) {
|
|
|
|
|
rdTravelMeetingExchangeRef.value.exchangeList = deepClone(exchangeData);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 劳务/服务费数据
|
|
|
|
|
// 人工费
|
|
|
|
|
const laborData = isChangeType
|
|
|
|
|
? handleChangeTypeIds(data.erpRdBudgetLaborCostList, 'erpRdBudgetLaborCostList', true)
|
|
|
|
|
: oriRdBudgetLaborCostList.value;
|
|
|
|
|
if (rdLaborServiceRef.value) {
|
|
|
|
|
// 技术咨询费
|
|
|
|
|
if (rdLaborServiceRef.value.techConsultList) {
|
|
|
|
|
rdLaborServiceRef.value.techConsultList = deepClone(categorizedData.rdBudgetTechConsultCostList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 专家咨询会议形式
|
|
|
|
|
if (rdLaborServiceRef.value.expertMeetingList) {
|
|
|
|
|
rdLaborServiceRef.value.expertMeetingList = deepClone(categorizedData.rdBudgetExpertMeetingCostList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 专家咨询通讯形式
|
|
|
|
|
if (rdLaborServiceRef.value.expertCommList) {
|
|
|
|
|
rdLaborServiceRef.value.expertCommList = deepClone(categorizedData.rdBudgetExpertCommCostList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 人工费
|
|
|
|
|
if (rdLaborServiceRef.value.laborList) {
|
|
|
|
|
rdLaborServiceRef.value.laborList = deepClone(categorizedData.rdBudgetLaborCostList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 劳务费
|
|
|
|
|
if (rdLaborServiceRef.value.serviceList) {
|
|
|
|
|
rdLaborServiceRef.value.serviceList = deepClone(categorizedData.rdBudgetServiceCostList);
|
|
|
|
|
rdLaborServiceRef.value.laborList = deepClone(laborData);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 资料/软件/文献检索费数据
|
|
|
|
|
if (rdLiteratureCostRef.value) {
|
|
|
|
|
// 资料费
|
|
|
|
|
if (rdLiteratureCostRef.value.materialsList) {
|
|
|
|
|
rdLiteratureCostRef.value.materialsList = deepClone(categorizedData.rdBudgetLiteratureMaterialCostList);
|
|
|
|
|
// 差旅费数据
|
|
|
|
|
if (rdTravelMeetingExchangeRef.value) {
|
|
|
|
|
// 差旅费
|
|
|
|
|
if (rdTravelMeetingExchangeRef.value.travelList) {
|
|
|
|
|
rdTravelMeetingExchangeRef.value.travelList = deepClone(categorizedData.rdBudgetTravelCostList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 专用软件购买费
|
|
|
|
|
if (rdLiteratureCostRef.value.softwareList) {
|
|
|
|
|
rdLiteratureCostRef.value.softwareList = deepClone(categorizedData.rdBudgetLiteratureSoftwareCostList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 文献检索费(单个对象)
|
|
|
|
|
if (rdLiteratureCostRef.value.literatureRetrieval && categorizedData.rdBudgetLiteratureRetrievalCostList.length > 0) {
|
|
|
|
|
rdLiteratureCostRef.value.literatureRetrieval = deepClone(categorizedData.rdBudgetLiteratureRetrievalCostList[0]);
|
|
|
|
|
// 交通费
|
|
|
|
|
if (rdTravelMeetingExchangeRef.value.transportationList) {
|
|
|
|
|
rdTravelMeetingExchangeRef.value.transportationList = deepClone(categorizedData.rdBudgetTransportationCostList);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1317,6 +1059,24 @@ function assignRdDataToComponents(data: any, categorizedData: any, isChangeType:
|
|
|
|
|
rdTestingCostRef.value.testData = deepClone(testingData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 咨询费、设计费
|
|
|
|
|
if (rdTechCostRef.value) {
|
|
|
|
|
// 技术咨询费
|
|
|
|
|
if (rdTechCostRef.value.techConsultList) {
|
|
|
|
|
rdTechCostRef.value.techConsultList = deepClone(categorizedData.rdBudgetTechConsultCostList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 专家咨询会议形式
|
|
|
|
|
if (rdTechCostRef.value.expertMeetingList) {
|
|
|
|
|
rdTechCostRef.value.expertMeetingList = deepClone(categorizedData.rdBudgetExpertMeetingCostList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 专家咨询通讯形式
|
|
|
|
|
if (rdTechCostRef.value.expertCommList) {
|
|
|
|
|
rdTechCostRef.value.expertCommList = deepClone(categorizedData.rdBudgetExpertCommCostList);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 其他费用数据
|
|
|
|
|
const otherData = isChangeType
|
|
|
|
|
? handleChangeTypeIds(data.erpRdBudgetOtherCostList, 'erpRdBudgetOtherCostList', true)
|
|
|
|
|
@ -1373,21 +1133,16 @@ function deepClone<T>(obj: T): T {
|
|
|
|
|
import SubmitVerify from '@/components/Process/submitVerify.vue';
|
|
|
|
|
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
|
|
|
|
import ApprovalButton from '@/components/Process/approvalButton.vue';
|
|
|
|
|
import { getContractInfo } from '@/api/oa/erp/contractInfo';
|
|
|
|
|
import { budgetMaterialCostVO } from '@/api/oa/erp/budgetInfo/market/budgetMaterialCost/types';
|
|
|
|
|
import { budgetLaborCostVO } from '@/api/oa/erp/budgetInfo/market/budgetLaborCost/types';
|
|
|
|
|
import { budgetInstallCostVO } from '@/api/oa/erp/budgetInfo/market/budgetInstallCost/types';
|
|
|
|
|
import { budgetTravelCostVO } from '@/api/oa/erp/budgetInfo/market/budgetTravelCost/types';
|
|
|
|
|
import { budgetOtherCostVO } from '@/api/oa/erp/budgetInfo/market/budgetOtherCost/types';
|
|
|
|
|
import { budgetInfoForm } from '@/api/oa/erp/budgetInfo/types';
|
|
|
|
|
import { rdBudgetEquipmentCostVO } from '@/api/oa/erp/budgetInfo/rd/rdBudgetEquipmentCost/types';
|
|
|
|
|
import { rdBudgetMaterialCostVO } from '@/api/oa/erp/budgetInfo/rd/rdBudgetMaterialCost/types';
|
|
|
|
|
import { rdBudgetTravelCostVO } from '@/api/oa/erp/budgetInfo/rd/rdBudgetTravelCost/types';
|
|
|
|
|
import { rdBudgetMeetingCostVO } from '@/api/oa/erp/budgetInfo/rd/rdBudgetMeetingCost/types';
|
|
|
|
|
import { rdBudgetExchangeCostVO } from '@/api/oa/erp/budgetInfo/rd/rdBudgetExchangeCost/types';
|
|
|
|
|
import { rdBudgetTechCostVO } from '@/api/oa/erp/budgetInfo/rd/rdBudgetTechCost/types';
|
|
|
|
|
import { rdBudgetLaborCostVO } from '@/api/oa/erp/budgetInfo/rd/rdBudgetLaborCost/types';
|
|
|
|
|
import { rdBudgetLiteratureCostVO } from '@/api/oa/erp/budgetInfo/rd/rdBudgetLiteratureCost/types';
|
|
|
|
|
import { rdBudgetTestingCostVO } from '@/api/oa/erp/budgetInfo/rd/rdBudgetTestingCost/types';
|
|
|
|
|
import { rdBudgetOtherCostVO } from '@/api/oa/erp/budgetInfo/rd/rdBudgetOtherCost/types';
|
|
|
|
|
import { UserVO } from '@/api/system/user/types';
|
|
|
|
|
|