dev
lh 2 weeks ago
commit 1cf1234aa5

@ -74,3 +74,15 @@ export function getErpAfterSalesList (query) {
params: query
});
};
/**
*
* @param data
*/
export const submitAfterSalesAndFlowStart = (data: any) => {
return request({
url: '/oa/erp/afterSales/submitAndFlowStart',
method: 'post',
data: data
});
};

@ -57,6 +57,18 @@ export const updateErpBudgetInfo = (data: budgetInfoForm) => {
});
};
/**
*
* @param data
*/
export const changeErpBudgetInfo = (data: budgetInfoForm) => {
return request({
url: '/oa/erp/budgetInfo/change',
method: 'post',
data: data
});
};
/**
*
* @param budgetId

@ -56,6 +56,11 @@ export interface ProjectPurchaseVO {
*/
deputyName?: string;
/**
*
*/
version?: number;
/**
*
*/
@ -164,6 +169,11 @@ export interface ProjectPurchaseForm extends BaseEntity {
*/
deputyId?: string | number;
/**
*
*/
version?: number;
/**
* ID
*/
@ -332,6 +342,11 @@ export interface ProjectPurchaseQuery extends PageQuery {
*
*/
params?: any;
/**
*
*/
managerName?: string;
}

@ -100,5 +100,9 @@ export enum FlowCodeEnum {
/**
* KEY
*/
PROJECT_REPRORT_CODE = 'XMZB'
PROJECT_REPRORT_CODE = 'XMZB',
/**
* KEY
*/
AFTER_SALES_KEY = 'OAAS'
}

@ -3,7 +3,7 @@
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width='100px'>
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
<el-form-item label="供应商名称" prop="supplierName">
<el-input v-model="queryParams.supplierName" placeholder="请输入供应商名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
@ -99,10 +99,14 @@
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['oa/crm:crmSupplierInfo:add']"> </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/crm:crmSupplierInfo:edit']"></el-button>
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['oa/crm:crmSupplierInfo:edit']"
>修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa/crm:crmSupplierInfo:remove']"></el-button>
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['oa/crm:crmSupplierInfo:remove']"
>删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['oa/crm:crmSupplierInfo:export']"> </el-button>
@ -163,7 +167,13 @@
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/crm:crmSupplierInfo:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa/crm:crmSupplierInfo:remove']"></el-button>
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['oa/crm:crmSupplierInfo:remove']"
></el-button>
</el-tooltip>
</template>
</el-table-column>
@ -193,24 +203,13 @@
<el-col :md="12" :sm="24">
<el-form-item label="供应商类型" prop="supplierType">
<el-select v-model="form.supplierType" placeholder="请选择供应商类型">
<el-option
v-for="dict in supplier_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
<el-option v-for="dict in supplier_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
<el-form-item label="成立日期" prop="establishmentDate">
<el-date-picker
v-model="form.establishmentDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择成立日期"
clearable
/>
<el-date-picker v-model="form.establishmentDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择成立日期" clearable />
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
@ -324,32 +323,39 @@
<span class="section-title">附件与其他</span>
</template>
<el-row :gutter="16">
<el-col :md="12" :sm="24">
<!-- <el-col :md="12" :sm="24">-->
<el-form-item label="附件" prop="ossId">
<FileUpload v-model="form.ossId" :limit="1" :is-show-tip="true" :file-size="10" />
<span class="upload-tip">仅支持单文件上传大小不超过10MB</span>
<div v-if="form.attachmentList?.length" class="mt-2">
<el-tag
v-for="item in form.attachmentList"
:key="item.ossId"
size="small"
class="mr-2 mb-2"
>
<el-link :href="item.url" target="_blank" type="primary">
{{ item.originalName || item.name }}
</el-link>
</el-tag>
</div>
<!-- <span class="upload-tip">仅支持单文件上传大小不超过10MB</span>-->
<!-- <div v-if="form.attachmentList?.length" class="mt-2">-->
<!-- <el-tag-->
<!-- v-for="item in form.attachmentList"-->
<!-- :key="item.ossId"-->
<!-- size="small"-->
<!-- class="mr-2 mb-2"-->
<!-- >-->
<!-- <el-link :href="item.url" target="_blank" type="primary">-->
<!-- {{ item.originalName || item.name }}-->
<!-- </el-link>-->
<!-- </el-tag>-->
<!-- </div>-->
</el-form-item>
</el-col>
<el-col :md="12" :sm="24">
<!-- </el-col>-->
<!-- <el-col :md="12" :sm="24">-->
<!-- <el-form-item label="激活标识" prop="activeFlag">-->
<!-- <el-radio-group v-model="form.activeFlag">-->
<!-- <el-radio-->
<!-- v-for="dict in active_flag"-->
<!-- :key="dict.value"-->
<!-- :value="dict.value"-->
<!-- >{{ dict.label }}</el-radio>-->
<!-- </el-radio-group>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :md="24">
<el-form-item label="激活标识" prop="activeFlag">
<el-radio-group v-model="form.activeFlag">
<el-radio
v-for="dict in active_flag"
:key="dict.value"
:value="dict.value"
>{{ dict.label }}</el-radio>
<el-radio v-for="dict in active_flag" :key="dict.value" :value="dict.value">{{ dict.label }} </el-radio>
</el-radio-group>
</el-form-item>
</el-col>
@ -429,7 +435,7 @@
{ key: 25, label: `备注`, visible: true },
{ key: 26, label: `激活标识`, visible: true },
{ key: 27, label: `创建时间`, visible: true },
{ key: 28, label: `创建人`, visible: true },
{ key: 28, label: `创建人`, visible: true }
]);
const initFormData: CrmSupplierInfoForm = {
@ -460,8 +466,8 @@
remark: undefined,
activeFlag: undefined,
ownerName: undefined,
createName: undefined,
}
createName: undefined
};
const data = reactive<PageData<CrmSupplierInfoForm, CrmSupplierInfoQuery>>({
form: { ...initFormData },
queryParams: {
@ -493,22 +499,13 @@
activeFlag: undefined,
ownerName: undefined,
createName: undefined,
params: {
}
params: {}
},
rules: {
supplierName: [
{ required: true, message: "供应商名称不能为空", trigger: "blur" }
],
mnemonicName: [
{ required: true, message: "助记名称不能为空", trigger: "blur" }
],
supplierType: [
{ required: true, message: "供应商类型不能为空", trigger: "change" }
],
mainIndustry: [
{ required: true, message: "主营行业不能为空", trigger: "blur" }
]
supplierName: [{ required: true, message: '供应商名称不能为空', trigger: 'blur' }],
mnemonicName: [{ required: true, message: '助记名称不能为空', trigger: 'blur' }],
supplierType: [{ required: true, message: '供应商类型不能为空', trigger: 'change' }],
mainIndustry: [{ required: true, message: '主营行业不能为空', trigger: 'blur' }]
}
});
@ -521,62 +518,62 @@
crmSupplierInfoList.value = res.rows;
total.value = res.total;
loading.value = false;
}
};
/** 获取用户列表 */
const getUserList = async () => {
const res = await listUser({ pageNum: 1, pageSize: 1000 });
userList.value = res.rows;
}
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
}
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
crmSupplierInfoFormRef.value?.resetFields();
}
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
}
};
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
}
};
/** 多选框选中数据 */
const handleSelectionChange = (selection: CrmSupplierInfoVO[]) => {
ids.value = selection.map(item => item.supplierId);
ids.value = selection.map((item) => item.supplierId);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
form.value.activeFlag = '1';
dialog.visible = true;
dialog.title = "添加供应商信息";
}
dialog.title = '添加供应商信息';
};
/** 修改按钮操作 */
const handleUpdate = async (row?: CrmSupplierInfoVO) => {
reset();
const _supplierId = row?.supplierId || ids.value[0]
const _supplierId = row?.supplierId || ids.value[0];
const res = await getCrmSupplierInfo(_supplierId);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = "修改供应商信息";
}
dialog.title = '修改供应商信息';
};
/** 提交按钮 */
const submitForm = () => {
@ -584,32 +581,36 @@
if (valid) {
buttonLoading.value = true;
if (form.value.supplierId) {
await updateCrmSupplierInfo(form.value).finally(() => buttonLoading.value = false);
await updateCrmSupplierInfo(form.value).finally(() => (buttonLoading.value = false));
} else {
await addCrmSupplierInfo(form.value).finally(() => buttonLoading.value = false);
await addCrmSupplierInfo(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess("操作成功");
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
}
};
/** 删除按钮操作 */
const handleDelete = async (row?: CrmSupplierInfoVO) => {
const _supplierIds = row?.supplierId || ids.value;
await proxy?.$modal.confirm('是否确认删除供应商信息编号为"' + _supplierIds + '"的数据项?').finally(() => loading.value = false);
await proxy?.$modal.confirm('是否确认删除供应商信息编号为"' + _supplierIds + '"的数据项?').finally(() => (loading.value = false));
await delCrmSupplierInfo(_supplierIds);
proxy?.$modal.msgSuccess("删除成功");
proxy?.$modal.msgSuccess('删除成功');
await getList();
}
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download('oa/crm/crmSupplierInfo/export', {
proxy?.download(
'oa/crm/crmSupplierInfo/export',
{
...queryParams.value
}, `crmSupplierInfo_${new Date().getTime()}.xlsx`)
}
},
`crmSupplierInfo_${new Date().getTime()}.xlsx`
);
};
onMounted(() => {
getList();

File diff suppressed because it is too large Load Diff

@ -18,7 +18,7 @@
<el-option v-for="dict in after_sales_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="售后问题是否解决" prop="solveStatus">
<el-form-item label="是否解决" prop="solveStatus">
<el-select v-model="queryParams.solveStatus" placeholder="请选择售后问题是否解决" clearable>
<el-option v-for="dict in solve_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
@ -68,45 +68,45 @@
<el-table v-loading="loading" border :data="afterSalesList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="售后ID" align="center" prop="afterSalesId" v-if="columns[0].visible" />
<el-table-column label="售后编号" align="center" prop="afterSalesCode" v-if="columns[2].visible" />
<el-table-column label="售后编号" align="center" prop="afterSalesCode" width="140" v-if="columns[2].visible" />
<el-table-column label="售后主题" align="center" prop="afterSalesSubject" v-if="columns[3].visible" />
<el-table-column label="项目ID" align="center" prop="projectId" v-if="columns[4].visible" />
<el-table-column label="项目编号" align="center" prop="projectCode" v-if="columns[5].visible" />
<el-table-column label="项目名称" align="center" prop="projectName" v-if="columns[6].visible" />
<el-table-column label="项目编号" align="center" prop="projectCode" width="130" v-if="columns[5].visible" />
<el-table-column label="项目名称" align="center" prop="projectName" width="130" v-if="columns[6].visible" />
<el-table-column label="客户ID" align="center" prop="customerId" v-if="columns[7].visible" />
<el-table-column label="客户名称" align="center" prop="customerName" v-if="columns[8].visible" />
<el-table-column label="客户名称" align="center" prop="customerName" width="130" v-if="columns[8].visible" />
<el-table-column label="联系人" align="center" prop="contactPerson" v-if="columns[9].visible" />
<el-table-column label="联系电话" align="center" prop="contactPhone" v-if="columns[10].visible" />
<el-table-column label="售后日期" align="center" prop="afterSalesDate" width="180" v-if="columns[11].visible">
<el-table-column label="联系电话" align="center" prop="contactPhone" width="130" v-if="columns[10].visible" />
<el-table-column label="售后日期" align="center" prop="afterSalesDate" width="100" v-if="columns[11].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.afterSalesDate, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
<span>{{ parseTime(scope.row.afterSalesDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="合同ID" align="center" prop="contractId" v-if="columns[12].visible" />
<el-table-column label="合同号" align="center" prop="contractCode" v-if="columns[13].visible">
<el-table-column label="合同号" align="center" prop="contractCode" width="140" v-if="columns[13].visible">
<template #default="scope">
<!-- 如果有编号显示编号否则显示 '无编号' -->
{{ scope.row.contractCode ? scope.row.contractCode : '无编号' }}
</template>
</el-table-column>
<el-table-column label="售后类型" align="center" prop="afterSalesType" v-if="columns[14].visible">
<el-table-column label="售后类型" align="center" prop="afterSalesType" width="100" v-if="columns[14].visible">
<template #default="scope">
<dict-tag :options="after_sales_type" :value="scope.row.afterSalesType" />
</template>
</el-table-column>
<el-table-column label="客户干系人" align="center" prop="stakeholderName" v-if="columns[15].visible" />
<el-table-column label="客户干系人" align="center" prop="stakeholderName" width="130" v-if="columns[15].visible" />
<el-table-column label="处理人" align="center" prop="handlerName" v-if="columns[16].visible" />
<el-table-column label="问题描述" align="center" prop="problemDescription" v-if="columns[17].visible" />
<el-table-column label="售后总工时" align="center" prop="totalWorkHours" v-if="columns[18].visible" />
<el-table-column label="售后总成本" align="center" prop="totalCost" v-if="columns[19].visible" />
<el-table-column label="售后总工时" align="center" prop="totalWorkHours" width="90" v-if="columns[18].visible" />
<el-table-column label="售后总成本" align="center" prop="totalCost" width="90" v-if="columns[19].visible" />
<el-table-column label="售后问题是否解决" align="center" prop="solveStatus" v-if="columns[20].visible">
<template #default="scope">
<dict-tag :options="solve_status" :value="scope.row.solveStatus" />
</template>
</el-table-column>
<el-table-column label="完成日期" align="center" prop="completionDate" width="180" v-if="columns[21].visible">
<el-table-column label="完成日期" align="center" prop="completionDate" width="100" v-if="columns[21].visible">
<template #default="scope">
<span>{{ parseTime(scope.row.completionDate, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
<span>{{ parseTime(scope.row.completionDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="处理结果" align="center" prop="processingResult" v-if="columns[22].visible" />
@ -128,11 +128,11 @@
<el-table-column label="备注" align="center" prop="remark" v-if="columns[26].visible" />
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-tooltip content="修改" placement="top" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'back'">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['oa/erp:afterSales:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['oa/erp:afterSales:remove']"></el-button>
<el-tooltip content="查看详情" placement="top" v-if="scope.row.flowStatus !== 'draft'">
<el-button link type="info" icon="DocumentChecked" @click="handleView(scope.row)"></el-button>
</el-tooltip>
</template>
</el-table-column>
@ -343,7 +343,7 @@ const handleView = (row?: AfterSalesVO) => {
const _afterSalesId = row?.afterSalesId;
proxy.$tab.closePage(route);
router.push({
path: '/erp/afterSales/edit',
path: '/project/afterSales/edit',
query: {
id: _afterSalesId,
type: 'view'

@ -175,11 +175,12 @@
<script setup lang="ts" name="BudgetInfoEdit">
import { ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';
import { listProjectInfo, addErpBudgetInfo, updateErpBudgetInfo, getErpBudgetInfo } from '@/api/oa/erp/budgetInfo';
import { listProjectInfo, addErpBudgetInfo, updateErpBudgetInfo, changeErpBudgetInfo, getErpBudgetInfo } from '@/api/oa/erp/budgetInfo';
import { ProjectInfoVO, ProjectInfoQuery } from '@/api/oa/erp/projectInfo/types';
import { getUserList } from '@/api/system/user';
import { deepEqualArrays } from '@/utils/objHandle';
import { cloneDeep } from 'lodash-es';
const router = useRouter();
@ -644,11 +645,20 @@ const handleSave = async (status: string, mode: boolean) => {
ElMessage.warning('不支持的预算类型');
return;
}
console.log('----');
console.log(budgetForm);
//
const saveOperation = budgetForm.budgetId ? () => updateErpBudgetInfo(budgetForm) : () => addErpBudgetInfo(budgetForm);
await saveOperation();
if (budgetForm.budgetId) {
await updateErpBudgetInfo(budgetForm);
} else {
if (routeParams.value.changeFlag === '1') {
await changeErpBudgetInfo(budgetForm);
} else {
budgetForm.budgetVersion = 1;
await addErpBudgetInfo(budgetForm);
}
}
ElMessage.success('操作成功');
handleSaveSuccess();
@ -685,8 +695,6 @@ const processRdBudgetForm = async (status: string): Promise<budgetInfoForm> => {
...initializeRdCostLists()
};
console.log(budgetForm);
//
processRdCostData(budgetForm);
@ -760,6 +768,8 @@ 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 || [];
}
@ -883,153 +893,437 @@ const handleClose = () => {
const route = useRoute();
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',
//
erpBudgetMaterialCostList: 'materialCostId',
erpBudgetLaborCostList: 'laborCostId',
erpBudgetInstallCostList: 'installCostId',
erpBudgetTravelCostList: 'travelCostId',
erpBudgetOtherCostList: 'otherCostId',
//
erpBudgetDetailList: 'budgetDetailId',
erpBudgetInfo: 'budgetId',
//
default: 'id'
} as const;
//
const COMMON_FIELDS_TO_REMOVE = ['budgetId', 'createDept', 'createBy', 'createTime', 'updateBy', 'updateTime', 'delFlag'];
onMounted(() => {
nextTick(async () => {
//
await loadBudgetData();
});
});
async function loadBudgetData() {
routeParams.value = route.query;
budgetId.value = routeParams.value.id as string | number;
if (budgetId.value && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) {
if (!budgetId.value || !['update', 'view', 'approval'].includes(routeParams.value.type as string)) {
handleAddMode();
return;
}
await handleLoadMode();
}
function handleAddMode() {
searchForm.projectCategory = routeParams.value.projectCategory;
queryParams.value.projectCategory = searchForm.projectCategory;
}
async function handleLoadMode() {
proxy?.$modal.loading('正在加载数据,请稍后...');
try {
const res = await getErpBudgetInfo(budgetId.value);
Object.assign(searchForm, res.data);
console.log(res.data);
if (routeParams.value.changeFlag === '1') {
searchForm.flowStatus = 'draft';
}
await getUsers();
if (searchForm.projectCategory === PROJECT_CATEGORY.RD || searchForm.projectCategory === PROJECT_CATEGORY.PRE_PRODUCTION) {
oriRdBudgetEquipmentCostList.value = JSON.parse(JSON.stringify(res.data.erpRdBudgetEquipmentCostList));
const erpRdBudgetMaterialCostList = res.data.erpRdBudgetMaterialCostList;
const groupedRdBudgetMaterialCostListByMaterialType = erpRdBudgetMaterialCostList.reduce((acc, item) => {
const materialType = item.materialType;
if (!acc[materialType]) {
acc[materialType] = [];
if (isRdOrPreProductionCategory()) {
await handleRdOrPreProductionData(res.data);
} else if (isMarketCategory()) {
await handleMarketCategoryData(res.data);
}
acc[materialType].push(item);
return acc;
}, {});
const rdBudgetMainMaterialCostList = groupedRdBudgetMaterialCostListByMaterialType[MATERIAL_TYPE.MAIN] || [];
const rdBudgetOtherMaterialCostList = groupedRdBudgetMaterialCostListByMaterialType[MATERIAL_TYPE.OTHER] || [];
oriRdBudgetMaterialCostList.value = JSON.parse(JSON.stringify(erpRdBudgetMaterialCostList));
oriRdBudgetTravelCostList.value = JSON.parse(JSON.stringify(res.data.erpRdBudgetTravelCostList));
oriRdBudgetMeetingCostList.value = JSON.parse(JSON.stringify(res.data.erpRdBudgetMeetingCostList));
oriRdBudgetExchangeCostList.value = JSON.parse(JSON.stringify(res.data.erpRdBudgetExchangeCostList));
const erpRdBudgetTechCostList = res.data.erpRdBudgetTechCostList;
const groupedRdBudgetTechCostListByTechType = erpRdBudgetTechCostList.reduce((acc, item) => {
const techType = item.techType;
if (!acc[techType]) {
acc[techType] = [];
}
acc[techType].push(item);
return acc;
}, {});
const rdBudgetTechConsultCostList = groupedRdBudgetTechCostListByTechType[TECH_TYPE.TECH_CONSULT] || [];
const rdBudgetExpertMeetingCostList = groupedRdBudgetTechCostListByTechType[TECH_TYPE.EXPERT_MEETING] || [];
const rdBudgetExpertCommCostList = groupedRdBudgetTechCostListByTechType[TECH_TYPE.EXPERT_COMM] || [];
oriRdBudgetTechConsultCostList.value = JSON.parse(JSON.stringify(rdBudgetTechConsultCostList)); //
oriRdBudgetExpertMeetingCostList.value = JSON.parse(JSON.stringify(rdBudgetExpertMeetingCostList)); //
oriRdBudgetExpertCommCostList.value = JSON.parse(JSON.stringify(rdBudgetExpertCommCostList)); //
const erpRdBudgetLaborCostList = res.data.erpRdBudgetLaborCostList;
const groupedRdBudgetLaborCostListByLaborType = erpRdBudgetLaborCostList.reduce((acc, item) => {
const laborType = item.laborType;
if (!acc[laborType]) {
acc[laborType] = [];
}
acc[laborType].push(item);
return acc;
}, {});
const rdBudgetLaborCostList = groupedRdBudgetLaborCostListByLaborType[LABOR_TYPE.LABOR] || [];
const rdBudgetServiceCostList = groupedRdBudgetLaborCostListByLaborType[LABOR_TYPE.SERVICE] || [];
oriRdBudgetLaborCostList.value = JSON.parse(JSON.stringify(rdBudgetLaborCostList)); //
oriRdBudgetServiceCostList.value = JSON.parse(JSON.stringify(rdBudgetServiceCostList)); //
const erpRdBudgetLiteratureCostList = res.data.erpRdBudgetLiteratureCostList;
const groupedRdBudgetLiteratureCostListByLiteratureType = erpRdBudgetLiteratureCostList.reduce((acc, item) => {
const literatureType = item.literatureType;
if (!acc[literatureType]) {
acc[literatureType] = [];
}
acc[literatureType].push(item);
return acc;
}, {});
const rdBudgetLiteratureMaterialCostList = groupedRdBudgetLiteratureCostListByLiteratureType[LITERATURE_TYPE.MATERIAL] || [];
const rdBudgetLiteratureSoftwareCostList = groupedRdBudgetLiteratureCostListByLiteratureType[LITERATURE_TYPE.SOFTWARE] || [];
oriRdBudgetLiteratureMaterialCostList.value = JSON.parse(JSON.stringify(rdBudgetLiteratureMaterialCostList)); //
oriRdBudgetLiteratureSofwareCostList.value = JSON.parse(JSON.stringify(rdBudgetLiteratureSoftwareCostList)); //
const rdBudgetLiteratureRetrievalCostList = groupedRdBudgetLiteratureCostListByLiteratureType[LITERATURE_TYPE.DOCUMENT] || []; //
oriRdBudgetTestingCostList.value = JSON.parse(JSON.stringify(res.data.erpRdBudgetTestingCostList));
oriRdBudgetOtherCostList.value = JSON.parse(JSON.stringify(res.data.erpRdBudgetOtherCostList));
nextTick(() => {
console.log(rdBudgetTableRef.value?.budgetForm);
Object.assign(rdBudgetTableRef.value?.rdBudgetInfoForm, res.data);
Object.assign(rdBudgetTableRef.value?.footerForm, res.data);
Object.assign(rdBudgetTableRef.value?.budgetDetailData || [], res.data.erpBudgetDetailList);
Object.assign(rdEquipmentCostRef.value?.equipmentData || [], res.data.erpRdBudgetEquipmentCostList);
Object.assign(rdMaterialCostRef.value?.materialData || [], rdBudgetMainMaterialCostList);
Object.assign(rdMaterialCostRef.value?.otherMaterial || [], rdBudgetOtherMaterialCostList[0]);
Object.assign(rdTravelMeetingExchangeRef.value?.travelList || [], res.data.erpRdBudgetTravelCostList);
Object.assign(rdTravelMeetingExchangeRef.value?.meetingList || [], res.data.erpRdBudgetMeetingCostList);
Object.assign(rdTravelMeetingExchangeRef.value?.exchangeList || [], res.data.erpRdBudgetExchangeCostList);
Object.assign(rdLaborServiceRef.value?.techConsultList || [], rdBudgetTechConsultCostList);
Object.assign(rdLaborServiceRef.value?.expertMeetingList || [], rdBudgetExpertMeetingCostList);
Object.assign(rdLaborServiceRef.value?.expertCommList || [], rdBudgetExpertCommCostList);
Object.assign(rdLaborServiceRef.value?.laborList || [], rdBudgetLaborCostList);
Object.assign(rdLaborServiceRef.value?.serviceList || [], rdBudgetServiceCostList);
Object.assign(rdLiteratureCostRef.value?.materialsList || [], rdBudgetLiteratureMaterialCostList);
Object.assign(rdLiteratureCostRef.value?.softwareList || [], rdBudgetLiteratureSoftwareCostList);
Object.assign(
rdLiteratureCostRef.value?.literatureRetrieval || [],
rdBudgetLiteratureRetrievalCostList.length > 0 ? rdBudgetLiteratureRetrievalCostList[0] : {}
);
Object.assign(rdTestingCostRef.value?.testData || [], res.data.erpRdBudgetTestingCostList);
Object.assign(rdOtherCostRef.value?.otherCostList || [], res.data.erpRdBudgetOtherCostList);
});
} else if (searchForm.projectCategory === PROJECT_CATEGORY.MARKET || searchForm.projectCategory === PROJECT_CATEGORY.MARKET_PART) {
//
oriBudgetMaterialCostList.value = JSON.parse(JSON.stringify(res.data.erpBudgetMaterialCostList));
oriBudgetLaborCostList.value = JSON.parse(JSON.stringify(res.data.erpBudgetLaborCostList));
oriBudgetInstallCostList.value = JSON.parse(JSON.stringify(res.data.erpBudgetInstallCostList));
oriBudgetTravelCostList.value = JSON.parse(JSON.stringify(res.data.erpBudgetTravelCostList));
oriBudgetOtherCostList.value = JSON.parse(JSON.stringify(res.data.erpBudgetOtherCostList));
nextTick(() => {
console.log(budgetTableRef.value?.budgetForm);
Object.assign(budgetTableRef.value?.budgetForm, res.data);
Object.assign(budgetTableRef.value?.budgetDetailData, res.data.erpBudgetDetailList);
Object.assign(materialCostRef.value?.budgetMaterialCostList, res.data.erpBudgetMaterialCostList);
Object.assign(laborCostRef.value?.budgetLaborCostList, res.data.erpBudgetLaborCostList);
Object.assign(installationCostRef.value?.installCostList, res.data.erpBudgetInstallCostList);
Object.assign(travelCostRef.value?.travelCostList, res.data.erpBudgetTravelCostList);
Object.assign(otherCostRef.value?.otherCostList, res.data.erpBudgetOtherCostList);
});
}
} finally {
proxy?.$modal.closeLoading();
} else {
searchForm.projectCategory = routeParams.value.projectCategory;
//
// if (form.value.contractCode) {
// isCodeGenerated.value = true;
// } else if (form.value.contractFlag === '1') {
// //
// isCodeGenerated.value = false;
// }
}
queryParams.value.projectCategory = searchForm.projectCategory;
}
function isRdOrPreProductionCategory(): boolean {
return searchForm.projectCategory === PROJECT_CATEGORY.RD || searchForm.projectCategory === PROJECT_CATEGORY.PRE_PRODUCTION;
}
function isMarketCategory(): boolean {
return searchForm.projectCategory === PROJECT_CATEGORY.MARKET || searchForm.projectCategory === PROJECT_CATEGORY.MARKET_PART;
}
async function handleRdOrPreProductionData(data: any) {
const isChangeType = routeParams.value.changeFlag === '1';
//
if (!isChangeType) {
initOriginalRdData(data);
}
//
const groupedMaterialData = groupByField(data.erpRdBudgetMaterialCostList, 'materialType');
const groupedTechData = groupByField(data.erpRdBudgetTechCostList, 'techType');
const groupedLaborData = groupByField(data.erpRdBudgetLaborCostList, 'laborType');
const groupedLiteratureData = groupByField(data.erpRdBudgetLiteratureCostList, 'literatureType');
//
const categorizedData = {
rdBudgetMainMaterialCostList: handleChangeTypeIds(groupedMaterialData[MATERIAL_TYPE.MAIN] || [], 'erpRdBudgetMaterialCostList', isChangeType),
rdBudgetOtherMaterialCostList: handleChangeTypeIds(groupedMaterialData[MATERIAL_TYPE.OTHER] || [], 'erpRdBudgetMaterialCostList', 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
)
};
await nextTick();
assignRdDataToComponents(data, categorizedData, isChangeType);
}
async function handleMarketCategoryData(data: any) {
const isChangeType = routeParams.value.changeFlag === '1';
//
if (!isChangeType) {
initOriginalMarketData(data);
}
//
const processedLists = {
materialCostList: handleChangeTypeIds(data.erpBudgetMaterialCostList, 'erpBudgetMaterialCostList', isChangeType),
laborCostList: handleChangeTypeIds(data.erpBudgetLaborCostList, 'erpBudgetLaborCostList', isChangeType),
installCostList: handleChangeTypeIds(data.erpBudgetInstallCostList, 'erpBudgetInstallCostList', isChangeType),
travelCostList: handleChangeTypeIds(data.erpBudgetTravelCostList, 'erpBudgetTravelCostList', isChangeType),
otherCostList: handleChangeTypeIds(data.erpBudgetOtherCostList, 'erpBudgetOtherCostList', isChangeType),
detailList: handleChangeTypeIds(data.erpBudgetDetailList, 'erpBudgetDetailList', isChangeType)
};
await nextTick();
assignMarketDataToComponents(data, processedLists, isChangeType);
}
//
function getPrimaryKeyField(listName: string): string {
return PRIMARY_KEY_MAP[listName] || PRIMARY_KEY_MAP.default;
}
// ID
function handleChangeTypeIds(data: any[], listName: string, isChangeType: boolean): any[] {
if (!isChangeType || !data || data.length === 0) {
return data || [];
}
const primaryKey = getPrimaryKeyField(listName);
return data.map((item) => {
return processFormDataForChange(item, primaryKey);
});
}
//
function processFormDataForChange(data: any, primaryKey: string): any {
const processedData = { ...data };
//
if (primaryKey in processedData) {
delete processedData[primaryKey];
}
//
COMMON_FIELDS_TO_REMOVE.forEach((field) => {
if (field in processedData) {
delete processedData[field];
}
});
// "Id"
// Object.keys(newItem).forEach((key) => {
// if (key.endsWith('Id') && key !== primaryKey) {
// delete newItem[key];
// }
// });
return processedData;
}
function groupByField(array: any[], field: string): Record<string, any[]> {
if (!array) return {};
return array.reduce((acc, item) => {
const key = item[field];
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(item);
return acc;
}, {});
}
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);
oriRdBudgetTestingCostList.value = deepClone(data.erpRdBudgetTestingCostList);
oriRdBudgetOtherCostList.value = deepClone(data.erpRdBudgetOtherCostList);
//
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);
oriBudgetLaborCostList.value = deepClone(data.erpBudgetLaborCostList);
oriBudgetInstallCostList.value = deepClone(data.erpBudgetInstallCostList);
oriBudgetTravelCostList.value = deepClone(data.erpBudgetTravelCostList);
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);
//
const budgetDetailList = isChangeType
? handleChangeTypeIds(data.erpBudgetDetailList, 'erpBudgetDetailList', true)
: deepClone(data.erpBudgetDetailList || []);
//
if (rdBudgetTableRef.value.budgetDetailData) {
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);
}
//
if (categorizedData.rdBudgetOtherMaterialCostList.length > 0) {
rdMaterialCostRef.value.otherMaterial = deepClone(categorizedData.rdBudgetOtherMaterialCostList[0]);
}
}
// //
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);
}
}
// /
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);
}
}
// //
if (rdLiteratureCostRef.value) {
//
if (rdLiteratureCostRef.value.materialsList) {
rdLiteratureCostRef.value.materialsList = deepClone(categorizedData.rdBudgetLiteratureMaterialCostList);
}
//
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]);
}
}
// //
const testingData = isChangeType
? handleChangeTypeIds(data.erpRdBudgetTestingCostList, 'erpRdBudgetTestingCostList', true)
: oriRdBudgetTestingCostList.value;
if (rdTestingCostRef.value?.testData) {
rdTestingCostRef.value.testData = deepClone(testingData);
}
//
const otherData = isChangeType
? handleChangeTypeIds(data.erpRdBudgetOtherCostList, 'erpRdBudgetOtherCostList', true)
: oriRdBudgetOtherCostList.value;
if (rdOtherCostRef.value?.otherCostList) {
rdOtherCostRef.value.otherCostList = deepClone(otherData);
}
}
// assignMarketDataToComponents isChangeType
function assignMarketDataToComponents(data: any, processedLists: any, isChangeType: boolean) {
if (!budgetTableRef.value) return;
//
const formData = isChangeType ? processFormDataForChange(data, 'budgetId') : data;
Object.assign(budgetTableRef.value.budgetForm, formData);
//
if (budgetTableRef.value.budgetDetailData) {
budgetTableRef.value.budgetDetailData = deepClone(processedLists.detailList);
}
//
if (materialCostRef.value?.budgetMaterialCostList) {
materialCostRef.value.budgetMaterialCostList = deepClone(processedLists.materialCostList);
}
//
if (laborCostRef.value?.budgetLaborCostList) {
laborCostRef.value.budgetLaborCostList = deepClone(processedLists.laborCostList);
}
//
if (installationCostRef.value?.installCostList) {
installationCostRef.value.installCostList = deepClone(processedLists.installCostList);
}
//
if (travelCostRef.value?.travelCostList) {
travelCostRef.value.travelCostList = deepClone(processedLists.travelCostList);
}
//
if (otherCostRef.value?.otherCostList) {
otherCostRef.value.otherCostList = deepClone(processedLists.otherCostList);
}
}
function deepClone<T>(obj: T): T {
return cloneDeep(obj);
}
import SubmitVerify from '@/components/Process/submitVerify.vue';
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
import ApprovalButton from '@/components/Process/approvalButton.vue';

@ -73,6 +73,7 @@
</el-table-column>
<el-table-column label="项目号" align="center" prop="projectCode" v-if="columns[6].visible" />
<el-table-column label="项目名称" align="center" prop="projectName" v-if="columns[7].visible" />
<el-table-column label="版本" align="center" prop="budgetVersion" v-if="columns[34].visible" width="60"/>
<el-table-column label="项目经理" align="center" prop="managerName" v-if="columns[8].visible" width="100px;"/>
<el-table-column label="产品经理" align="center" prop="productManagerName" v-if="columns[10].visible" />
<el-table-column label="合同额(万元)" align="center" prop="contractAmount" v-if="columns[14].visible" />
@ -80,7 +81,7 @@
<el-table-column label="预算成本(万元)" align="center" prop="budgetCost" v-if="columns[16].visible" />
<el-table-column label="预算毛利率" align="center" prop="budgetRate" v-if="columns[17].visible">
<template #default="scope">
{{ formatRate(scope.row.reduceBudgetRate) }}
{{ formatRate(scope.row.budgetRate) }}
</template>
</el-table-column>
<el-table-column label="降成本后预算成本(万元)" align="center" prop="reduceBudgetCost" v-if="columns[18].visible" />
@ -117,7 +118,7 @@
</el-tooltip>
<el-tooltip content="导出" placement="top">
<el-button
type="primary"
type="success"
icon="Download"
size="small"
@click="handleExport(scope.row)"
@ -129,8 +130,8 @@
size="small"
type="warning"
icon="Delete"
@click="handleUpdate(scope.row,'change')"
v-if="scope.row.budgetStatus === BUDGET_STATUS.DRAFT"
@click="handleChange(scope.row)"
v-if="scope.row.budgetStatus === BUDGET_STATUS.AVAILABLE"
v-hasPermi="['oa:erp/budgetInfo:change']"
>变更&nbsp;</el-button>
</el-tooltip>
@ -154,7 +155,7 @@
</template>
<script setup name="budgetInfo" lang="ts">
import { listErpBudgetInfo, getErpBudgetInfo, delErpBudgetInfo, addErpBudgetInfo, updateErpBudgetInfo } from '@/api/oa/erp/budgetInfo';
import { listErpBudgetInfo, delErpBudgetInfo } from '@/api/oa/erp/budgetInfo';
import { budgetInfoVO, budgetInfoQuery, budgetInfoForm } from '@/api/oa/erp/budgetInfo/types';
import router from '@/router';
import { getUserList } from '@/api/system/user';
@ -220,7 +221,8 @@ const columns = ref<FieldOption[]>([
{ key: 30, label: `创建人`, visible: true },
{ key: 31, label: `创建时间`, visible: true },
{ key: 32, label: `更新人`, visible: true },
{ key: 33, label: `更新时间`, visible: true }
{ key: 33, label: `更新时间`, visible: true },
{ key: 34, label: `版本`, visible: true }
]);
const initFormData: budgetInfoForm = {
@ -364,7 +366,7 @@ const handleSelectionChange = (selection: budgetInfoVO[]) => {
/** 新增市场项目预算按钮操作 */
const handleAdd = () => {
router.push({
path: '/budget/budget-add/index',
path: '/budget/budgetInfo/edit',
query: {
type: 'add',
projectCategory: PROJECT_CATEGORY.MARKET,
@ -381,7 +383,7 @@ const handleAdd = () => {
/** 新增研发项目按钮操作 */
const handleAddRd = () => {
router.push({
path: '/budget/budget-add/index',
path: '/budget/budgetInfo/edit',
query: {
type: 'add',
pageNum: queryParams.value.pageNum,
@ -390,13 +392,14 @@ const handleAddRd = () => {
});
};
/** 查询、修改和变更按钮操作 */
const handleUpdate = async (row?: budgetInfoVO, type?: string) => {
/** 查询、修改按钮操作 */
const handleUpdate = async (row?: budgetInfoVO, type?: string, changeFlag?: string) => {
router.push({
path: '/budget/budget-add/index',
path: '/budget/budgetInfo/edit',
query: {
type: type,
id: row.budgetId,
changeFlag: changeFlag,
pageNum: queryParams.value.pageNum,
projectCategory: row.projectCategory
}
@ -406,13 +409,14 @@ const handleUpdate = async (row?: budgetInfoVO, type?: string) => {
// proxy.$tab.openPage('/oa/erp/budgetInfo/edit', '', params);
};
/** 修改按钮操作 */
const handleView = async (row?: budgetInfoVO) => {
/** 变更按钮操作 */
const handleChange = async (row?: budgetInfoVO) => {
router.push({
path: '/budget/budget-add/index',
path: '/budget/budgetInfo/change',
query: {
type: 'view',
type: 'update',
id: row.budgetId,
changeFlag: '1',
pageNum: queryParams.value.pageNum,
projectCategory: row.projectCategory
}

@ -253,7 +253,7 @@ const getSummaries = ({ columns, data }: any) => {
}
}, 0);
sums[index] = formatNumber(sums[index]);
footerForm.budgetCost = sums[index];
rdBudgetInfoForm.budgetCost = sums[index];
} else {
sums[index] = '';
}

@ -141,7 +141,9 @@ const materialData = ref<rdBudgetMaterialCostVO[]>([]);
const toDeletedMaterialCostIdList = ref([]);
//
const otherMaterial = reactive({
const otherMaterialData = ref<rdBudgetMaterialCostVO>();
const defaultOtherMaterial = ref({
sortOrder: 1,
materialName: '其他材料费',
materialType: MATERIAL_TYPE.OTHER,
@ -150,10 +152,12 @@ const otherMaterial = reactive({
amount: undefined,
price: 0
});
//
const otherMaterial = ref(defaultOtherMaterial);
// +
const allMaterialData = computed(() => {
return [...materialData.value, otherMaterial];
return [...materialData.value, otherMaterial.value];
});
const unitOptions = ref<UnitInfoVO[]>([]);
@ -192,6 +196,19 @@ const checkSelectable = (row: rdBudgetMaterialCostVO, index: number) => {
return row.materialType === MATERIAL_TYPE.MAIN;
};
// otherMaterialData
watch(
otherMaterialData,
(newVal) => {
if (newVal) {
otherMaterial.value = newVal;
} else {
otherMaterial.value = defaultOtherMaterial.value;
}
},
{ immediate: true }
); // immediate: true
//
watch(
() => [materialData, otherMaterial],
@ -221,7 +238,7 @@ const addSpecifiedRows = async () => {
price: 0
});
}
otherMaterial.sortOrder = currentSortOrder + 1 + addRowCount.value;
otherMaterial.value.sortOrder = currentSortOrder + 1 + addRowCount.value;
// DOM
await nextTick();
scrollToBottom();
@ -251,7 +268,7 @@ const handleDelete = (index: number, row: rdBudgetMaterialCostVO) => {
if (row.materialCostId) {
toDeletedMaterialCostIdList.value.push(row.materialCostId);
}
otherMaterial.sortOrder = otherMaterial.sortOrder - 1;
otherMaterial.value.sortOrder = otherMaterial.value.sortOrder - 1;
calculateTotal();
};
@ -272,7 +289,7 @@ const handleBatchDelete = () => {
materialData.value.forEach((item, index) => {
item.sortOrder = index + 1;
});
otherMaterial.sortOrder = otherMaterial.sortOrder - selectedRows.value.length;
otherMaterial.value.sortOrder = otherMaterial.value.sortOrder - selectedRows.value.length;
calculateTotal();
selectedRows.value = [];
};
@ -285,7 +302,7 @@ const calculateAmount = () => {
});
//
otherMaterial.price = (otherMaterial.amount || 0) * (otherMaterial.unitPrice || 0);
otherMaterial.value.price = (otherMaterial.value.amount || 0) * (otherMaterial.value.unitPrice || 0);
//
calculateTotal();
@ -294,7 +311,7 @@ const calculateAmount = () => {
//
const calculateTotal = () => {
const mainAmount = parseFloat(((Number(mainMaterialTotalAmount.value) || 0) / 10000).toFixed(2));
const otherAmount = parseFloat(((Number(otherMaterial.price) || 0) / 10000).toFixed(2));
const otherAmount = parseFloat(((Number(otherMaterial.value.price) || 0) / 10000).toFixed(2));
totalAmount.value = (mainAmount + otherAmount).toFixed(2);
};
@ -328,8 +345,8 @@ const resetData = () => {
//
// otherMaterial.unit = '';
// otherMaterial.quantity = 0;
otherMaterial.unitPrice = 0;
otherMaterial.amount = 0;
// otherMaterial.unitPrice = 0;
// otherMaterial.amount = 0;
};
//
@ -346,6 +363,7 @@ const getFormData = () => {
defineExpose({
materialData,
otherMaterial,
otherMaterialData,
allMaterialData,
toDeletedMaterialCostIdList,
getTotalAmount

@ -4,17 +4,17 @@
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
<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="purchaseCode">
<el-input v-model="queryParams.purchaseCode" placeholder="请输入采购编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<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="managerId">
<el-input v-model="queryParams.managerId" placeholder="请输入项目经理" clearable @keyup.enter="handleQuery" />
<el-form-item label="项目经理" prop="managerName">
<el-input v-model="queryParams.managerName" placeholder="请输入项目经理" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="项目采购状态" prop="projectPurchaseStatus">
<el-select v-model="queryParams.projectPurchaseStatus" placeholder="请选择项目采购状态" clearable>
@ -59,6 +59,11 @@
<el-table-column label="项目经理" align="center" prop="managerName" width="120" v-if="columns[5].visible" />
<el-table-column label="部门负责人" align="center" prop="chargeName" width="120" v-if="columns[6].visible" />
<el-table-column label="分管副总" align="center" prop="deputyName" width="120" v-if="columns[7].visible" />
<el-table-column label="版本" align="center" prop="version" width="100" v-if="columns[8].visible">
<template #default="scope">
<span>v{{ scope.row.version }}.0</span>
</template>
</el-table-column>
<el-table-column label="提报人" align="center" prop="reporterName" width="120" v-if="columns[9].visible" />
<el-table-column label="收货人" align="center" prop="consigneeUser" width="120" v-if="columns[10].visible" />
<el-table-column label="收货地址" align="center" prop="consigneeAddress" width="200" show-overflow-tooltip v-if="columns[11].visible" />

Loading…
Cancel
Save