|
|
|
|
@ -16,21 +16,14 @@
|
|
|
|
|
<el-form :model="searchForm" label-width="80px">
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="6">
|
|
|
|
|
<el-form-item label="项目名称">
|
|
|
|
|
<el-input v-model="searchForm.projectName" placeholder="请选择项目名称" readonly @click="showProjectSelectDialog">
|
|
|
|
|
<template #append>
|
|
|
|
|
<el-icon @click="showProjectSelectDialog">
|
|
|
|
|
<el-icon :size="16">
|
|
|
|
|
<Search />
|
|
|
|
|
</el-icon>
|
|
|
|
|
</el-icon>
|
|
|
|
|
</template>
|
|
|
|
|
<el-form-item label="项目号">
|
|
|
|
|
<el-input v-model="searchForm.projectCode" placeholder="请选择项目" readonly @click="showProjectSelectDialog" suffix-icon="Search">
|
|
|
|
|
</el-input>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="6">
|
|
|
|
|
<el-form-item label="项目号">
|
|
|
|
|
<el-input v-model="searchForm.projectCode" placeholder="项目号" readonly />
|
|
|
|
|
<el-form-item label="项目名称">
|
|
|
|
|
<el-input v-model="searchForm.projectName" placeholder="请选择项目后自动填充" disabled />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<!-- <el-col :span="12" class="text-right">-->
|
|
|
|
|
@ -48,7 +41,13 @@
|
|
|
|
|
<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">
|
|
|
|
|
<RdBudgetTable ref="rdBudgetTableRef" :projectId="searchForm.projectId" :costData="costData" :projectInfo="projectInfo" />
|
|
|
|
|
<RdBudgetTable
|
|
|
|
|
ref="rdBudgetTableRef"
|
|
|
|
|
:projectId="searchForm.projectId"
|
|
|
|
|
:costData="costData"
|
|
|
|
|
:projectInfo="projectInfo"
|
|
|
|
|
:userList="userList"
|
|
|
|
|
/>
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="设备费" name="equipmentCost">
|
|
|
|
|
<RdEquipmentCost ref="rdEquipmentCostRef" :projectId="searchForm.projectId" />
|
|
|
|
|
@ -82,7 +81,7 @@
|
|
|
|
|
>
|
|
|
|
|
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
|
|
|
|
<el-tab-pane label="预算表" name="budget">
|
|
|
|
|
<BudgetTable ref="budgetTableRef" :projectInfo="projectInfo" />
|
|
|
|
|
<BudgetTable ref="budgetTableRef" :projectInfo="projectInfo" :userList="userList" />
|
|
|
|
|
</el-tab-pane>
|
|
|
|
|
<el-tab-pane label="材料费" name="material">
|
|
|
|
|
<MaterialCost ref="materialCostRef" :budgetId="budgetId" />
|
|
|
|
|
@ -103,14 +102,30 @@
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
|
|
<!-- 项目选择弹窗 -->
|
|
|
|
|
<el-dialog v-model="projectSelectDialogVisible" title="选择项目" width="800px">
|
|
|
|
|
<div class="mb-4">
|
|
|
|
|
<el-input v-model="projectSearchForm.keyword" placeholder="请输入项目名称或项目号" clearable @input="handleProjectSearch">
|
|
|
|
|
<template #append>
|
|
|
|
|
<el-button @click="handleProjectSearch">搜索</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-input>
|
|
|
|
|
</div>
|
|
|
|
|
<el-dialog v-model="projectSelectDialogVisible" title="选择项目" width="880px">
|
|
|
|
|
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
|
|
|
|
<div class="mb-[10px]">
|
|
|
|
|
<el-card shadow="hover">
|
|
|
|
|
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="80px">
|
|
|
|
|
<el-form-item label="项目号" prop="projectCode">
|
|
|
|
|
<el-input v-model="queryParams.projectCode" placeholder="请输入项目编号" clearable @keyup.enter="handleQuery" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="项目名称" prop="projectName">
|
|
|
|
|
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter="handleQuery" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="项目状态" prop="projectStatus">
|
|
|
|
|
<el-select v-model="queryParams.projectStatus" placeholder="请选择项目状态" clearable>
|
|
|
|
|
<el-option v-for="dict in project_status" :key="dict.value" :label="dict.label" :value="dict.value" />
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item>
|
|
|
|
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
|
|
|
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
</el-card>
|
|
|
|
|
</div>
|
|
|
|
|
</transition>
|
|
|
|
|
|
|
|
|
|
<el-table :data="projectList" border @row-click="selectProject" style="width: 100%" v-loading="projectLoading" highlight-current-row>
|
|
|
|
|
<el-table-column prop="projectCode" label="项目号" width="150" />
|
|
|
|
|
@ -136,8 +151,8 @@
|
|
|
|
|
<pagination
|
|
|
|
|
v-show="projectTotal > 0"
|
|
|
|
|
:total="projectTotal"
|
|
|
|
|
v-model:page="projectSearchForm.pageNum"
|
|
|
|
|
v-model:limit="projectSearchForm.pageSize"
|
|
|
|
|
v-model:page="queryParams.pageNum"
|
|
|
|
|
v-model:limit="queryParams.pageSize"
|
|
|
|
|
@pagination="getProjectList"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
@ -162,7 +177,9 @@ import { ref, reactive } from 'vue';
|
|
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
|
|
import { listProjectInfo, addErpBudgetInfo, updateErpBudgetInfo, getErpBudgetInfo } from '@/api/oa/erp/budgetInfo';
|
|
|
|
|
import { ProjectInfoVO, ProjectInfoQuery } from '@/api/oa/erp/projectInfo/types';
|
|
|
|
|
import { isDeepEqual } from '@/utils/objHandle';
|
|
|
|
|
import { getUserList } from '@/api/system/user';
|
|
|
|
|
|
|
|
|
|
import { deepEqualArrays } from '@/utils/objHandle';
|
|
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
|
|
|
|
@ -311,18 +328,6 @@ const projectInfo = reactive<ProjectInfoVO>({
|
|
|
|
|
projectCategory: ''
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 市场预算成本数据
|
|
|
|
|
const marketCostData = reactive<CostData>({
|
|
|
|
|
materialCost: 0,
|
|
|
|
|
laborCost: 0,
|
|
|
|
|
installCost: 0,
|
|
|
|
|
travelCost: 0,
|
|
|
|
|
serviceCost: 0,
|
|
|
|
|
literatureCost: 0,
|
|
|
|
|
testingCost: 0,
|
|
|
|
|
otherCost: 0
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 研发预算成本数据
|
|
|
|
|
const costData = reactive<CostData>({
|
|
|
|
|
equipmentCost: 0,
|
|
|
|
|
@ -338,22 +343,66 @@ const costData = reactive<CostData>({
|
|
|
|
|
otherCost: 0
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const userList = ref<UserVO[]>([]);
|
|
|
|
|
/** 查询用户列表 */
|
|
|
|
|
const getUsers = async () => {
|
|
|
|
|
const res = await getUserList({});
|
|
|
|
|
userList.value = res.data;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 项目选择弹窗相关
|
|
|
|
|
const projectSelectDialogVisible = ref(false);
|
|
|
|
|
const selectedProject = ref<ProjectInfoVO | null>(null);
|
|
|
|
|
const projectList = ref<ProjectInfoVO[]>([]);
|
|
|
|
|
const projectTotal = ref(0);
|
|
|
|
|
const projectLoading = ref(true);
|
|
|
|
|
const projectSearchForm = reactive({
|
|
|
|
|
projectCategory: '',
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
pageSize: 10
|
|
|
|
|
const data = reactive<{ queryParams: ProjectInfoQuery }>({
|
|
|
|
|
queryParams: {
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
pageSize: 10,
|
|
|
|
|
contractFlag: undefined,
|
|
|
|
|
projectCode: undefined,
|
|
|
|
|
projectName: undefined,
|
|
|
|
|
businessDirection: undefined,
|
|
|
|
|
projectCategory: undefined,
|
|
|
|
|
spareFlag: undefined,
|
|
|
|
|
projectTypeId: undefined,
|
|
|
|
|
paymentMethod: undefined,
|
|
|
|
|
deptId: undefined,
|
|
|
|
|
managerId: undefined,
|
|
|
|
|
chargeId: undefined,
|
|
|
|
|
deputyId: undefined,
|
|
|
|
|
peopleId: undefined,
|
|
|
|
|
amount: undefined,
|
|
|
|
|
projectStatus: undefined,
|
|
|
|
|
flowStatus: undefined,
|
|
|
|
|
sortOrder: undefined,
|
|
|
|
|
contractId: undefined,
|
|
|
|
|
activeFlag: undefined,
|
|
|
|
|
params: {}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const { queryParams } = toRefs(data);
|
|
|
|
|
|
|
|
|
|
const queryFormRef = ref<ElFormInstance>();
|
|
|
|
|
|
|
|
|
|
/** 搜索按钮操作 */
|
|
|
|
|
const handleQuery = () => {
|
|
|
|
|
queryParams.value.pageNum = 1;
|
|
|
|
|
getProjectList();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** 重置按钮操作 */
|
|
|
|
|
const resetQuery = () => {
|
|
|
|
|
queryFormRef.value?.resetFields();
|
|
|
|
|
handleQuery();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** 查询项目信息列表 */
|
|
|
|
|
const getProjectList = async () => {
|
|
|
|
|
projectLoading.value = true;
|
|
|
|
|
const res = await listProjectInfo(projectSearchForm);
|
|
|
|
|
const res = await listProjectInfo(queryParams.value);
|
|
|
|
|
console.log(searchForm);
|
|
|
|
|
projectList.value = res.rows;
|
|
|
|
|
projectTotal.value = res.total;
|
|
|
|
|
@ -379,21 +428,6 @@ const showProjectSelectDialog = () => {
|
|
|
|
|
getProjectList();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 项目搜索
|
|
|
|
|
const handleProjectSearch = () => {
|
|
|
|
|
projectSearchForm.pageNum = 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 项目分页大小变化
|
|
|
|
|
const handleProjectPageSizeChange = (size: number) => {
|
|
|
|
|
projectSearchForm.pageSize = size;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 项目当前页变化
|
|
|
|
|
const handleProjectCurrentPageChange = (current: number) => {
|
|
|
|
|
projectSearchForm.pageNum = current;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 选择项目
|
|
|
|
|
const selectProject = (row: ProjectInfoVO) => {
|
|
|
|
|
selectedProject.value = row;
|
|
|
|
|
@ -487,7 +521,7 @@ const handleOtherCostUpdate = (data: { totalAmount: number }) => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 更新市场项目预算预算表数据
|
|
|
|
|
const updateBudgetTable = () => {
|
|
|
|
|
const updateBudgetTable = async () => {
|
|
|
|
|
if (!budgetTableRef.value) return;
|
|
|
|
|
|
|
|
|
|
// 获取各tab页的合计数据
|
|
|
|
|
@ -506,7 +540,7 @@ const updateBudgetTable = () => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 更新研发项目预算预算表数据
|
|
|
|
|
const updateRdBudgetTable = () => {
|
|
|
|
|
const updateRdBudgetTable = async () => {
|
|
|
|
|
// 获取各tab页的合计数据
|
|
|
|
|
const equipmentAmount = rdEquipmentCostRef.value?.getTotalAmount();
|
|
|
|
|
const equipmentTotal = equipmentAmount.equipmentTotal || 0;
|
|
|
|
|
@ -577,7 +611,17 @@ const exportBudget = () => {
|
|
|
|
|
ElMessage.success('导出预算成功');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 保存预算
|
|
|
|
|
// 提取用户查找逻辑
|
|
|
|
|
const findUserName = (userList: any[], userId: number): string => {
|
|
|
|
|
const user = userList?.find((item) => item.userId === userId);
|
|
|
|
|
return user?.nickName || '';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 提取数据比较和赋值逻辑
|
|
|
|
|
const assignIfChanged = (targetArray: any[], sourceArray: any[], originalArray: any[]): any[] => {
|
|
|
|
|
return !deepEqualArrays(originalArray, sourceArray) ? sourceArray || [] : [];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleSave = async (status: string, mode: boolean) => {
|
|
|
|
|
if (!searchForm.projectId) {
|
|
|
|
|
ElMessage.warning('请先选择项目');
|
|
|
|
|
@ -586,157 +630,250 @@ const handleSave = async (status: string, mode: boolean) => {
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
buttonLoading.value = true;
|
|
|
|
|
const budgetForm = reactive<budgetInfoForm>({});
|
|
|
|
|
if (searchForm.projectCategory === PROJECT_CATEGORY.RD || searchForm.projectCategory === PROJECT_CATEGORY.PRE_PRODUCTION) {
|
|
|
|
|
updateRdBudgetTable();
|
|
|
|
|
|
|
|
|
|
const budgetDetailData = rdBudgetTableRef.value?.budgetDetailData;
|
|
|
|
|
const isRdProject = [PROJECT_CATEGORY.RD, PROJECT_CATEGORY.PRE_PRODUCTION].includes(searchForm.projectCategory);
|
|
|
|
|
const isMarketProject = [PROJECT_CATEGORY.MARKET, PROJECT_CATEGORY.MARKET_PART].includes(searchForm.projectCategory);
|
|
|
|
|
|
|
|
|
|
Object.assign(budgetForm,
|
|
|
|
|
rdBudgetTableRef.value?.rdBudgetInfoForm || {},
|
|
|
|
|
rdBudgetTableRef.value?.footerForm || {}
|
|
|
|
|
);
|
|
|
|
|
let budgetForm: budgetInfoForm = {};
|
|
|
|
|
|
|
|
|
|
budgetForm.budgetStatus = status === 'draft' ? BUSINESS_STATUS.DRAFT : BUSINESS_STATUS.WAITING;
|
|
|
|
|
budgetForm.flowStatus = status === 'draft' ? 'draft' : 'waiting';
|
|
|
|
|
|
|
|
|
|
budgetForm.erpRdBudgetEquipmentCostList = [];
|
|
|
|
|
budgetForm.erpRdBudgetMaterialCostList = [];
|
|
|
|
|
budgetForm.erpRdBudgetTravelCostList = [];
|
|
|
|
|
budgetForm.erpRdBudgetMeetingCostList = [];
|
|
|
|
|
budgetForm.erpRdBudgetExchangeCostList = [];
|
|
|
|
|
budgetForm.erpRdBudgetTechCostList = [];
|
|
|
|
|
budgetForm.erpRdBudgetLaborCostList = [];
|
|
|
|
|
budgetForm.erpRdBudgetLiteratureCostList = [];
|
|
|
|
|
budgetForm.erpRdBudgetTestingCostList = [];
|
|
|
|
|
budgetForm.erpRdBudgetOtherCostList = [];
|
|
|
|
|
|
|
|
|
|
// console.log(budgetForm);
|
|
|
|
|
budgetForm.erpBudgetDetailList = budgetDetailData;
|
|
|
|
|
if (!isDeepEqual(oriRdBudgetEquipmentCostList.value, rdEquipmentCostRef.value?.equipmentData)) {
|
|
|
|
|
budgetForm.erpRdBudgetEquipmentCostList = rdEquipmentCostRef.value?.equipmentData;
|
|
|
|
|
}
|
|
|
|
|
if (!isDeepEqual(oriRdBudgetMaterialCostList.value, rdMaterialCostRef.value?.allMaterialData)) {
|
|
|
|
|
budgetForm.erpRdBudgetMaterialCostList = rdMaterialCostRef.value?.allMaterialData;
|
|
|
|
|
}
|
|
|
|
|
if (!isDeepEqual(oriRdBudgetTravelCostList.value, rdTravelMeetingExchangeRef.value?.travelList)) {
|
|
|
|
|
budgetForm.erpRdBudgetTravelCostList = rdTravelMeetingExchangeRef.value?.travelList;
|
|
|
|
|
}
|
|
|
|
|
if (!isDeepEqual(oriRdBudgetMeetingCostList.value, rdTravelMeetingExchangeRef.value?.meetingList)) {
|
|
|
|
|
budgetForm.erpRdBudgetMeetingCostList = rdTravelMeetingExchangeRef.value?.meetingList;
|
|
|
|
|
}
|
|
|
|
|
if (!isDeepEqual(oriRdBudgetExchangeCostList.value, rdTravelMeetingExchangeRef.value?.exchangeList)) {
|
|
|
|
|
budgetForm.erpRdBudgetExchangeCostList = rdTravelMeetingExchangeRef.value?.exchangeList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
budgetForm.erpRdBudgetTechCostList = [
|
|
|
|
|
...(!isDeepEqual(oriRdBudgetTechConsultCostList.value, rdLaborServiceRef.value?.techConsultList)
|
|
|
|
|
? rdLaborServiceRef.value?.techConsultList || []
|
|
|
|
|
: []),
|
|
|
|
|
...(!isDeepEqual(oriRdBudgetExpertMeetingCostList.value, rdLaborServiceRef.value?.expertMeetingList)
|
|
|
|
|
? rdLaborServiceRef.value?.expertMeetingList || []
|
|
|
|
|
: []),
|
|
|
|
|
...(!isDeepEqual(oriRdBudgetExpertCommCostList.value, rdLaborServiceRef.value?.expertCommList)
|
|
|
|
|
? rdLaborServiceRef.value?.expertCommList || []
|
|
|
|
|
: [])
|
|
|
|
|
];
|
|
|
|
|
console.log('---');
|
|
|
|
|
console.log(budgetForm.erpRdBudgetTechCostList);
|
|
|
|
|
|
|
|
|
|
budgetForm.erpRdBudgetLaborCostList = [
|
|
|
|
|
...(!isDeepEqual(oriRdBudgetLaborCostList.value, rdLaborServiceRef.value?.laborList) ? rdLaborServiceRef.value?.laborList || [] : []),
|
|
|
|
|
...(!isDeepEqual(oriRdBudgetServiceCostList.value, rdLaborServiceRef.value?.serviceList) ? rdLaborServiceRef.value?.serviceList || [] : [])
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
budgetForm.erpRdBudgetLiteratureCostList = [
|
|
|
|
|
...(!isDeepEqual(oriRdBudgetLiteratureMaterialCostList.value, rdLiteratureCostRef.value?.materialsList)
|
|
|
|
|
? rdLiteratureCostRef.value?.materialsList || []
|
|
|
|
|
: []),
|
|
|
|
|
...(!isDeepEqual(oriRdBudgetLiteratureSofwareCostList.value, rdLiteratureCostRef.value?.softwareList)
|
|
|
|
|
? rdLiteratureCostRef.value?.softwareList || []
|
|
|
|
|
: [])
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
budgetForm.erpRdBudgetLiteratureCostList.push(rdLiteratureCostRef.value?.literatureRetrieval);
|
|
|
|
|
|
|
|
|
|
if (!isDeepEqual(oriRdBudgetTestingCostList.value, rdTestingCostRef.value?.testData)) {
|
|
|
|
|
budgetForm.erpRdBudgetTestingCostList = rdTestingCostRef.value?.testData;
|
|
|
|
|
}
|
|
|
|
|
if (!isDeepEqual(oriRdBudgetOtherCostList.value, rdOtherCostRef.value?.otherCostList)) {
|
|
|
|
|
budgetForm.erpRdBudgetOtherCostList = rdOtherCostRef.value?.otherCostList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (budgetForm.budgetId) {
|
|
|
|
|
budgetForm.toDeletedRdEquipmentCostIdList = rdEquipmentCostRef.value?.toDeletedEquipmentCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdMaterialCostIdList = rdMaterialCostRef.value?.toDeletedMaterialCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdTravelCostIdList = rdTravelMeetingExchangeRef.value?.toDeletedTravelCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdMeetingCostIdList = rdTravelMeetingExchangeRef.value?.toDeletedMeetingCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdExchangeCostIdList = rdTravelMeetingExchangeRef.value?.toDeletedExchangeCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdTechCostIdList = rdLaborServiceRef.value?.toDeletedTechCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdLaborCostIdList = rdLaborServiceRef.value?.toDeletedLaborCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdLiteratureCostIdList = rdLiteratureCostRef.value?.toDeletedLiteratureCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdTestingCostIdList = rdTestingCostRef.value?.toDeletedTestCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdOtherCostIdList = rdOtherCostRef.value?.toDeletedOtherCostIdList;
|
|
|
|
|
}
|
|
|
|
|
} else if (searchForm.projectCategory === PROJECT_CATEGORY.MARKET || searchForm.projectCategory === PROJECT_CATEGORY.MARKET_PART) {
|
|
|
|
|
updateBudgetTable();
|
|
|
|
|
|
|
|
|
|
const budgetDetailData = budgetTableRef.value?.budgetDetailData;
|
|
|
|
|
Object.assign(budgetForm, budgetTableRef.value?.budgetForm);
|
|
|
|
|
budgetForm.budgetStatus = status === 'draft' ? BUSINESS_STATUS.DRAFT : BUSINESS_STATUS.WAITING;
|
|
|
|
|
budgetForm.flowStatus = status === 'draft' ? 'draft' : 'waiting';
|
|
|
|
|
|
|
|
|
|
budgetForm.erpBudgetMaterialCostList = [];
|
|
|
|
|
budgetForm.erpBudgetLaborCostList = [];
|
|
|
|
|
budgetForm.erpBudgetInstallCostList = [];
|
|
|
|
|
budgetForm.erpBudgetTravelCostList = [];
|
|
|
|
|
budgetForm.erpBudgetOtherCostList = [];
|
|
|
|
|
console.log(budgetForm);
|
|
|
|
|
budgetForm.erpBudgetDetailList = budgetDetailData;
|
|
|
|
|
if (!isDeepEqual(oriBudgetMaterialCostList.value, materialCostRef.value?.budgetMaterialCostList)) {
|
|
|
|
|
budgetForm.erpBudgetMaterialCostList = materialCostRef.value?.budgetMaterialCostList;
|
|
|
|
|
}
|
|
|
|
|
if (!isDeepEqual(oriBudgetLaborCostList.value, laborCostRef.value?.budgetLaborCostList)) {
|
|
|
|
|
budgetForm.erpBudgetLaborCostList = laborCostRef.value?.budgetLaborCostList;
|
|
|
|
|
}
|
|
|
|
|
if (!isDeepEqual(oriBudgetInstallCostList.value, installationCostRef.value?.installCostList)) {
|
|
|
|
|
budgetForm.erpBudgetInstallCostList = installationCostRef.value?.installCostList;
|
|
|
|
|
}
|
|
|
|
|
if (!isDeepEqual(oriBudgetTravelCostList.value, travelCostRef.value?.travelCostList)) {
|
|
|
|
|
budgetForm.erpBudgetTravelCostList = travelCostRef.value?.travelCostList;
|
|
|
|
|
}
|
|
|
|
|
if (!isDeepEqual(oriBudgetOtherCostList.value, otherCostRef.value?.otherCostList)) {
|
|
|
|
|
budgetForm.erpBudgetOtherCostList = otherCostRef.value?.otherCostList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (budgetForm.budgetId) {
|
|
|
|
|
budgetForm.toDeletedMaterialCostIdList = materialCostRef.value?.toDeletedMaterialCostIdList;
|
|
|
|
|
budgetForm.toDeletedLaborCostIdList = laborCostRef.value?.toDeletedLaborCostIdList;
|
|
|
|
|
budgetForm.toDeletedInstallCostIdList = installationCostRef.value?.toDeletedInstallCostIdList;
|
|
|
|
|
budgetForm.toDeletedTravelCostIdList = travelCostRef.value?.toDeletedTravelCostIdList;
|
|
|
|
|
budgetForm.toDeletedOtherCostIdList = otherCostRef.value?.toDeletedOtherCostIdList;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (budgetForm.budgetId) {
|
|
|
|
|
await updateErpBudgetInfo(budgetForm).finally(() => (buttonLoading.value = false));
|
|
|
|
|
if (isRdProject) {
|
|
|
|
|
budgetForm = await processRdBudgetForm(status);
|
|
|
|
|
} else if (isMarketProject) {
|
|
|
|
|
budgetForm = await processMarketBudgetForm(status);
|
|
|
|
|
} else {
|
|
|
|
|
await addErpBudgetInfo(budgetForm).finally(() => (buttonLoading.value = false));
|
|
|
|
|
ElMessage.warning('不支持的预算类型');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
proxy?.$modal.msgSuccess('操作成功');
|
|
|
|
|
// 保存成功后关闭之前记录的tab
|
|
|
|
|
const obj = { path: '/budget/erp/budgetInfo', query: { t: Date.now(), pageNum: routeParams.value.pageNum } };
|
|
|
|
|
proxy?.$tab.closeOpenPage(obj);
|
|
|
|
|
// router.go(-1);
|
|
|
|
|
// handleClose();
|
|
|
|
|
|
|
|
|
|
// 统一保存逻辑
|
|
|
|
|
const saveOperation = budgetForm.budgetId ? () => updateErpBudgetInfo(budgetForm) : () => addErpBudgetInfo(budgetForm);
|
|
|
|
|
|
|
|
|
|
await saveOperation();
|
|
|
|
|
|
|
|
|
|
ElMessage.success('操作成功');
|
|
|
|
|
handleSaveSuccess();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
ElMessage.error('保存失败');
|
|
|
|
|
console.error('保存失败:', error);
|
|
|
|
|
ElMessage.error('保存失败');
|
|
|
|
|
} finally {
|
|
|
|
|
buttonLoading.value = false;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理研发预算表单
|
|
|
|
|
const processRdBudgetForm = async (status: string): Promise<budgetInfoForm> => {
|
|
|
|
|
await updateRdBudgetTable();
|
|
|
|
|
|
|
|
|
|
const budgetDetailData = rdBudgetTableRef.value?.budgetDetailData || [];
|
|
|
|
|
const rdBudgetInfoForm = rdBudgetTableRef.value?.rdBudgetInfoForm || {};
|
|
|
|
|
const footerForm = rdBudgetTableRef.value?.footerForm || {};
|
|
|
|
|
|
|
|
|
|
// 合并表单数据
|
|
|
|
|
const budgetForm = {
|
|
|
|
|
...rdBudgetInfoForm,
|
|
|
|
|
// 设置状态
|
|
|
|
|
budgetStatus: getBudgetStatus(status),
|
|
|
|
|
flowStatus: getFlowStatus(status),
|
|
|
|
|
// 设置负责人信息
|
|
|
|
|
managerId: footerForm.managerId,
|
|
|
|
|
managerName: findUserName(userList.value, footerForm.managerId),
|
|
|
|
|
approveUserId: footerForm.approveUserId,
|
|
|
|
|
approveUserName: findUserName(userList.value, footerForm.approveUserId),
|
|
|
|
|
// 预算详情
|
|
|
|
|
erpBudgetDetailList: budgetDetailData,
|
|
|
|
|
// 初始化所有成本列表
|
|
|
|
|
...initializeRdCostLists()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
console.log(budgetForm);
|
|
|
|
|
|
|
|
|
|
// 处理各项成本数据
|
|
|
|
|
processRdCostData(budgetForm);
|
|
|
|
|
|
|
|
|
|
// 如果有预算ID,设置要删除的列表
|
|
|
|
|
if (budgetForm.budgetId) {
|
|
|
|
|
setRdToDeletedLists(budgetForm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return budgetForm;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理市场预算表单
|
|
|
|
|
const processMarketBudgetForm = async (status: string): Promise<budgetInfoForm> => {
|
|
|
|
|
await updateBudgetTable();
|
|
|
|
|
|
|
|
|
|
const budgetDetailData = budgetTableRef.value?.budgetDetailData || [];
|
|
|
|
|
const budgetFormData = budgetTableRef.value?.budgetForm || {};
|
|
|
|
|
|
|
|
|
|
const budgetForm = {
|
|
|
|
|
...budgetFormData,
|
|
|
|
|
budgetStatus: getBudgetStatus(status),
|
|
|
|
|
flowStatus: getFlowStatus(status),
|
|
|
|
|
managerName: findUserName(userList.value, budgetFormData.managerId),
|
|
|
|
|
productManagerName: findUserName(userList.value, budgetFormData.productManagerId),
|
|
|
|
|
erpBudgetDetailList: budgetDetailData,
|
|
|
|
|
// 初始化市场预算成本列表
|
|
|
|
|
...initializeMarketCostLists()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理市场预算成本数据
|
|
|
|
|
processMarketCostData(budgetForm);
|
|
|
|
|
|
|
|
|
|
// 如果有预算ID,设置要删除的列表
|
|
|
|
|
if (budgetForm.budgetId) {
|
|
|
|
|
setMarketToDeletedLists(budgetForm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return budgetForm;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 辅助函数
|
|
|
|
|
const getBudgetStatus = (status: string): string => {
|
|
|
|
|
return status === 'draft' ? BUSINESS_STATUS.DRAFT : BUSINESS_STATUS.WAITING;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getFlowStatus = (status: string): string => {
|
|
|
|
|
return status === 'draft' ? 'draft' : 'waiting';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const initializeRdCostLists = () => ({
|
|
|
|
|
erpRdBudgetEquipmentCostList: [],
|
|
|
|
|
erpRdBudgetMaterialCostList: [],
|
|
|
|
|
erpRdBudgetTravelCostList: [],
|
|
|
|
|
erpRdBudgetMeetingCostList: [],
|
|
|
|
|
erpRdBudgetExchangeCostList: [],
|
|
|
|
|
erpRdBudgetTechCostList: [],
|
|
|
|
|
erpRdBudgetLaborCostList: [],
|
|
|
|
|
erpRdBudgetLiteratureCostList: [],
|
|
|
|
|
erpRdBudgetTestingCostList: [],
|
|
|
|
|
erpRdBudgetOtherCostList: []
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const initializeMarketCostLists = () => ({
|
|
|
|
|
erpBudgetMaterialCostList: [],
|
|
|
|
|
erpBudgetLaborCostList: [],
|
|
|
|
|
erpBudgetInstallCostList: [],
|
|
|
|
|
erpBudgetTravelCostList: [],
|
|
|
|
|
erpBudgetOtherCostList: []
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 处理研发成本数据
|
|
|
|
|
const processRdCostData = (budgetForm: budgetInfoForm) => {
|
|
|
|
|
// 设备成本
|
|
|
|
|
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 || [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 差旅、会议、交流成本
|
|
|
|
|
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 || [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 技术成本
|
|
|
|
|
const laborServiceRef = rdLaborServiceRef.value;
|
|
|
|
|
budgetForm.erpRdBudgetTechCostList = [
|
|
|
|
|
...assignIfChanged([], laborServiceRef?.techConsultList, oriRdBudgetTechConsultCostList.value),
|
|
|
|
|
...assignIfChanged([], laborServiceRef?.expertMeetingList, oriRdBudgetExpertMeetingCostList.value),
|
|
|
|
|
...assignIfChanged([], laborServiceRef?.expertCommList, oriRdBudgetExpertCommCostList.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 || [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 其他成本
|
|
|
|
|
if (assignIfChanged([], rdOtherCostRef.value?.otherCostList, oriRdBudgetOtherCostList.value).length) {
|
|
|
|
|
budgetForm.erpRdBudgetOtherCostList = rdOtherCostRef.value?.otherCostList || [];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 设置研发删除列表
|
|
|
|
|
const setRdToDeletedLists = (budgetForm: budgetInfoForm) => {
|
|
|
|
|
const refs = {
|
|
|
|
|
equipment: rdEquipmentCostRef.value,
|
|
|
|
|
material: rdMaterialCostRef.value,
|
|
|
|
|
travelMeetingExchange: rdTravelMeetingExchangeRef.value,
|
|
|
|
|
laborService: rdLaborServiceRef.value,
|
|
|
|
|
literature: rdLiteratureCostRef.value,
|
|
|
|
|
testing: rdTestingCostRef.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.toDeletedRdTestingCostIdList = refs.testing?.toDeletedTestCostIdList;
|
|
|
|
|
budgetForm.toDeletedRdOtherCostIdList = refs.other?.toDeletedOtherCostIdList;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理市场成本数据
|
|
|
|
|
const processMarketCostData = (budgetForm: budgetInfoForm) => {
|
|
|
|
|
const assignCostData = (targetKey: keyof budgetInfoForm, sourceData: any[], originalData: any[]) => {
|
|
|
|
|
if (!deepEqualArrays(originalData, sourceData)) {
|
|
|
|
|
budgetForm[targetKey] = sourceData || [];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
assignCostData('erpBudgetMaterialCostList', materialCostRef.value?.budgetMaterialCostList, oriBudgetMaterialCostList.value);
|
|
|
|
|
assignCostData('erpBudgetLaborCostList', laborCostRef.value?.budgetLaborCostList, oriBudgetLaborCostList.value);
|
|
|
|
|
assignCostData('erpBudgetInstallCostList', installationCostRef.value?.installCostList, oriBudgetInstallCostList.value);
|
|
|
|
|
assignCostData('erpBudgetTravelCostList', travelCostRef.value?.travelCostList, oriBudgetTravelCostList.value);
|
|
|
|
|
assignCostData('erpBudgetOtherCostList', otherCostRef.value?.otherCostList, oriBudgetOtherCostList.value);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 设置市场删除列表
|
|
|
|
|
const setMarketToDeletedLists = (budgetForm: budgetInfoForm) => {
|
|
|
|
|
budgetForm.toDeletedMaterialCostIdList = materialCostRef.value?.toDeletedMaterialCostIdList;
|
|
|
|
|
budgetForm.toDeletedLaborCostIdList = laborCostRef.value?.toDeletedLaborCostIdList;
|
|
|
|
|
budgetForm.toDeletedInstallCostIdList = installationCostRef.value?.toDeletedInstallCostIdList;
|
|
|
|
|
budgetForm.toDeletedTravelCostIdList = travelCostRef.value?.toDeletedTravelCostIdList;
|
|
|
|
|
budgetForm.toDeletedOtherCostIdList = otherCostRef.value?.toDeletedOtherCostIdList;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 保存成功处理
|
|
|
|
|
const handleSaveSuccess = () => {
|
|
|
|
|
const obj = {
|
|
|
|
|
path: '/budget/erp/budgetInfo',
|
|
|
|
|
query: {
|
|
|
|
|
t: Date.now(),
|
|
|
|
|
pageNum: routeParams.value.pageNum
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
proxy?.$tab.closeOpenPage(obj);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 关闭页面
|
|
|
|
|
const handleClose = () => {
|
|
|
|
|
// 可以添加确认对话框
|
|
|
|
|
@ -748,9 +885,6 @@ const route = useRoute();
|
|
|
|
|
const budgetId = ref();
|
|
|
|
|
// 初始化
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
// 可以在这里加载初始数据
|
|
|
|
|
routeParams.value.type = 'add';
|
|
|
|
|
|
|
|
|
|
nextTick(async () => {
|
|
|
|
|
// 获取路由参数
|
|
|
|
|
routeParams.value = route.query;
|
|
|
|
|
@ -760,7 +894,8 @@ onMounted(() => {
|
|
|
|
|
|
|
|
|
|
const res = await getErpBudgetInfo(budgetId.value);
|
|
|
|
|
Object.assign(searchForm, res.data);
|
|
|
|
|
console.log(res.data)
|
|
|
|
|
console.log(res.data);
|
|
|
|
|
await getUsers();
|
|
|
|
|
if (searchForm.projectCategory === PROJECT_CATEGORY.RD || searchForm.projectCategory === PROJECT_CATEGORY.PRE_PRODUCTION) {
|
|
|
|
|
oriRdBudgetEquipmentCostList.value = JSON.parse(JSON.stringify(res.data.erpRdBudgetEquipmentCostList));
|
|
|
|
|
|
|
|
|
|
@ -891,7 +1026,7 @@ console.log(res.data)
|
|
|
|
|
// isCodeGenerated.value = false;
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
projectSearchForm.projectCategory = searchForm.projectCategory;
|
|
|
|
|
queryParams.value.projectCategory = searchForm.projectCategory;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@ -915,6 +1050,7 @@ import { rdBudgetLaborCostVO } from '@/api/oa/erp/budgetInfo/rd/rdBudgetLaborCos
|
|
|
|
|
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';
|
|
|
|
|
// 路由参数
|
|
|
|
|
const routeParams = ref<Record<string, any>>({});
|
|
|
|
|
// 审批相关组件引用
|
|
|
|
|
|