| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003 |
- <!--
- * @Author: ysh
- * @Date: 2025-05-07 11:01:39
- * @LastEditors: wrh
- * @LastEditTime: 2025-12-31 16:22:00
- -->
- <template>
- <div class="main" v-loading="loading">
- <h2 class="text-center">项目直接生产成本预算表</h2>
- <p style="text-align: center">编制人:{{ budgetForm.compilerUser ? budgetForm.compilerUser.nickName : '' }} | 编制时间:{{ budgetForm.createTime }} </p>
- <el-divider></el-divider>
- <div class="mt20 mb20" v-if="showAlter && taskName">
- <el-alert title="任务被退回,请修改后重新提交" type="error" :closable="false">
- <return-comment :taskForm="taskForm" @isReturn="isReturn"></return-comment>
- </el-alert>
- </div>
- <el-descriptions :column="3" border class="descriptions">
- <el-descriptions-item label="项目编号">
- {{ project.projectNumber }}
- </el-descriptions-item>
- <el-descriptions-item label="项目名称">
- {{ project.projectName }}
- </el-descriptions-item>
- <el-descriptions-item label="项目负责人">
- {{ getUserName(project.projectLeader) }}
- </el-descriptions-item>
- <el-descriptions-item label="承担部门">
- {{ getDeptNames(project.undertakingDept) }}
- </el-descriptions-item>
- <el-descriptions-item label="项目备注" :span="3">
- {{ project.remark }}
- </el-descriptions-item>
- <el-descriptions-item label="预算表单备注" :span="5">
- {{ budgetForm.remark }}
- </el-descriptions-item>
- <el-descriptions-item label="预算附件" :span="5" v-if="budgetForm.document">
- <el-link type="primary" @click="reviewWord(`${baseUrl}${'/profile/upload' + budgetForm.document}`)">
- {{ getFileName(budgetForm.document) }}
- </el-link>
- <el-link class="ml20" type="warning" :href="`${baseUrl}${'/profile/upload' + budgetForm.document}`"
- :underline="false" target="_blank">
- <span class="el-icon-download">下载文件</span>
- </el-link>
- </el-descriptions-item>
- <el-descriptions-item label="项目计划工作量" :span="3">
- <div>
- <table border="1" style="width: 100%;">
- <tr style="background-color:#f8f8f9">
- <td style="width: 250px">工作内容</td>
- <td style="width: 100px">比例尺/等级</td>
- <td style="width: 100px">单位</td>
- <td style="width: 100px">工作量</td>
- <td style="width: 100px">要求完成时间</td>
- <td style="width: 200px">备注</td>
- </tr>
- <tr v-for="(work, index) in workContentList" :key="index">
- <td>{{ work.content }}</td>
- <td>{{ work.scale }} </td>
- <td>{{ work.unit }}</td>
- <td>{{ work.workload }}</td>
- <td>{{ work.deadline }}</td>
- <td class="remark-cell">{{ work.remark }}
- </td>
- </tr>
- </table>
- </div>
- </el-descriptions-item>
- <el-descriptions-item label="内业绩效额" :span="3">
- <table border="1" style="width:100%">
- <tr style="background-color:#f8f8f9" v-if="workList.length != 0">
- <td style="min-width:50px">工作简述</td>
- <td style="min-width:50px">工作内容</td>
- <td style="min-width:50px">内容细项</td>
- <td style="min-width:50px">比例尺/等级</td>
- <td style="min-width:50px">数量</td>
- <td style="min-width:50px">单价</td>
- <td style="min-width:50px">单位</td>
- <td style="min-width:50px">系数</td>
- <td style="min-width:80px">金额</td>
- <td style="min-width: 150px;">备注</td>
- </tr>
- <tr v-for="work in workList">
- <td>{{ work.content }}</td>
- <td>{{ work.workItem }}</td>
- <td>{{ work.subItem }}</td>
- <td>
- {{ work.scaleGrade }}
- </td>
- <td v-if="taskName == '分管审核'">
- <el-input-number style="width:80px;" :controls="false" v-model="work.workload" :min="0" :step="0.01"
- @change="(val) => updateSettle(work, val, 'workload')"></el-input-number>
- </td>
- <td v-else>
- {{ work.workload }}
- </td>
- <td>{{ work.price }}</td>
- <td>{{ work.unit }}</td>
- <td v-if="taskName == '分管审核'">
- <el-input-number style="width:80px;" :controls="false" v-model="work.coefficient" :min="0" :step="0.01"
- @change="(val) => updateSettle(work, val, 'coefficient')"></el-input-number>
- </td>
- <td v-else>
- {{ work.coefficient }}
- </td>
- <td style="text-align:right;">{{ work.settle ? Number(work.settle).toFixed(2) : '0.00' }}</td>
- <td class="remark-cell">{{ work.remark ? work.remark : '' }}</td>
- </tr>
- <tr>
- <td :colspan="8" class="head amount">内业绩效额合计</td>
- <td :colspan="1" class="head amount" :class="{ 'performance-error': isPerformanceExceeded() }"
- style="text-align:right;">
- {{ budgetForm.settleExpense ? budgetForm.settleExpense.toFixed(2) : '0.00' }}
- </td>
- <td></td>
- </tr>
- </table>
- </el-descriptions-item>
- <el-descriptions-item label="内业人员成本" :span="3" v-if="innerStaffList.length > 0">
- <table border="1" style="width:100%">
- <tr style="background-color:#f8f8f9">
- <td>序号</td>
- <td>姓名</td>
- <td>固定成本(天)</td>
- <td style="width:120px">预算天数</td>
- <td>固定成本小计</td>
- <td>绩效成本小计</td>
- <td style="width:120px">金额</td>
- <td style="width:120px">备注</td>
- </tr>
- <tr v-for="staff, index in innerStaffList" :key="'innerUser' + staff.userId">
- <td>{{ index + 1 }}</td>
- <td>{{ staff.user ? staff.user.nickName : '' }}</td>
- <td>{{ staff.dayCost }}</td>
- <td v-if="taskName == '分管审核'">
- <el-input-number style="width:80px;" :controls="false" v-model="staff.days" :min="0" :step="0.01"
- @change="(val) => updateInnerStaffAmount(staff, val, 'days')"></el-input-number>
- </td>
- <td v-else>{{ staff.days }}</td>
- <td style="text-align:right;">{{ staff.staffCost }}</td>
- <td v-if="taskName == '分管审核'">
- <el-input-number style="width:80px;" :controls="false" v-model="staff.performance" :min="0" :step="0.01"
- @change="(val) => updateInnerStaffAmount(staff, val, 'performance')"></el-input-number>
- </td>
- <td v-else style="text-align:right;">{{ staff.performance }}</td>
- <td style="text-align:right;">{{ staff.amount }}</td>
- <td class="remark-cell">{{ staff.remark }}</td>
- </tr>
- <tr>
- <td colspan="4" class="head amount">内业人员成本合计</td>
- <td class="head amount" style="text-align:right;">{{innerStaffList.reduce((sum, staff) => sum +
- (Number(staff.staffCost) || 0),
- 0).toFixed(2)}}</td>
- <td class="head amount" :class="{ 'performance-error': isPerformanceExceeded() }" style="text-align:right;">
- {{innerStaffList.reduce((sum, staff) => sum +
- (Number(staff.performance) || 0),
- 0).toFixed(2)}}</td>
- <td class="head amount" style="text-align:right;">{{innerStaffList.reduce((sum, staff) => sum +
- (Number(staff.amount) || 0),
- 0).toFixed(2)}}</td>
- </tr>
- </table>
- </el-descriptions-item>
- <el-descriptions-item label="外业人员成本" :span="3" v-if="outerStaffList.length > 0">
- <table border="1" style="width:100%">
- <tr style="background-color:#f8f8f9">
- <td>序号</td>
- <td>姓名</td>
- <td>固定成本(天)</td>
- <td>单价</td>
- <td style="width:120px">预算天数</td>
- <td>预算系数</td>
- <td>固定成本小计</td>
- <td>绩效成本小计</td>
- <td style="width:120px">金额</td>
- <td style="width:120px">备注</td>
- </tr>
- <tr v-for="staff, index in outerStaffList" :key="'outUser' + staff.userId">
- <td>{{ index + 1 }}</td>
- <td>{{ staff.user ? staff.user.nickName : '' }}</td>
- <td>{{ staff.dayCost }}</td>
- <td>200</td>
- <td v-if="taskName == '分管审核'">
- <el-input-number style="width:80px;" :controls="false" v-model="staff.days" :min="0" :step="0.01"
- @change="(val) => updateOuterStaffAmount(staff, val, 'days')"></el-input-number>
- </td>
- <td v-else>{{ staff.days }}</td>
- <td v-if="taskName == '分管审核'">
- <el-input-number style="width:80px;" :controls="false" v-model="staff.coefficient" :min="0" :step="0.01"
- @change="(val) => updateOuterStaffAmount(staff, val, 'coefficient')"></el-input-number>
- </td>
- <td v-else>{{ staff.coefficient }}</td>
- <td style="text-align:right;">{{ staff.staffCost }}</td>
- <td style="text-align:right;">{{ staff.performance }}</td>
- <td style="text-align:right;">{{ staff.amount }}</td>
- <td class="remark-cell">{{ staff.remark }}</td>
- </tr>
- <tr>
- <td colspan="4" class="head amount">外业人员成本合计</td>
- <td class="head amount" style="text-align:right;">{{outerStaffList.reduce((sum, staff) => sum +
- (Number(staff.days) || 0),
- 0).toFixed(2)}}</td>
- <td>——</td>
- <td class="head amount" style="text-align:right;">{{outerStaffList.reduce((sum, staff) => sum +
- (Number(staff.staffCost) || 0),
- 0).toFixed(2)}}</td>
- <td class="head amount" style="text-align:right;">{{outerStaffList.reduce((sum, staff) => sum +
- (Number(staff.performance) || 0),
- 0).toFixed(2)}}</td>
- <td class="head amount" style="text-align:right;">{{outerStaffList.reduce((sum, staff) => sum +
- (Number(staff.amount) || 0),
- 0).toFixed(2)}}</td>
- </tr>
- </table>
- </el-descriptions-item>
- <el-descriptions-item label="车辆成本" :span="3" v-if="carList.length > 0">
- <table border="1" style="width:100%;">
- <tr style="background-color:#f8f8f9">
- <td>序号</td>
- <td>车牌号</td>
- <td>折旧成本(天)</td>
- <td>预算天数</td>
- <td>金额</td>
- </tr>
- <tr v-for="car, index in carList" :key="'car' + car.carId">
- <td>{{ index + 1 }}</td>
- <td>{{ car.car ? car.car.licensePlate : '' }}</td>
- <td>{{ car.car ? car.car.dayCost : '' }}</td>
- <td v-if="taskName == '分管审核'">
- <el-input-number style="width:80px;" :controls="false" v-model="car.days" :min="0" :step="0.01"
- @change="(val) => updateCarAmount(car, val)"></el-input-number>
- </td>
- <td v-else>{{ car.days }}</td>
- <td style="text-align:right;">{{ car.amount }}</td>
- </tr>
- <tr>
- <td colspan="4" class="head amount">车辆成本合计</td>
- <td class="head amount" style="text-align:right;">{{carList.reduce((sum, car) => sum + (Number(car.amount)
- || 0), 0).toFixed(2)}}
- </td>
- </tr>
- </table>
- </el-descriptions-item>
- <el-descriptions-item label="设备成本" :span="3" v-if="deviceList.length > 0">
- <table border="1" style="width:100%;">
- <tr style="background-color:#f8f8f9">
- <td>序号</td>
- <td>设备名称</td>
- <td>规格型号</td>
- <td>品牌</td>
- <td>折旧成本(天)</td>
- <td>预算天数</td>
- <td>金额</td>
- </tr>
- <tr v-for="device, index in deviceList" :key="'device' + device.deviceId">
- <td>{{ index + 1 }}</td>
- <td>{{ device.device ? device.device.name : '' }}</td>
- <td>{{ device.device ? device.device.series : '' }}</td>
- <td>{{ device.device ? device.device.brand : '' }}</td>
- <td>{{ device.device ? device.device.dayCost : '' }}</td>
- <td v-if="taskName == '分管审核'">
- <el-input-number style="width:80px;" :controls="false" v-model="device.days" :min="0" :step="0.01"
- @change="(val) => updateDeviceAmount(device, val)"></el-input-number>
- </td>
- <td v-else>{{ device.days }}</td>
- <td style="text-align:right;">{{ device.amount }}</td>
- </tr>
- <tr>
- <td colspan="6" class="head amount">设备成本合计</td>
- <td class="head amount" style="text-align:right;">{{deviceList.reduce((sum, device) => sum +
- (Number(device.amount) || 0),
- 0).toFixed(2)}}</td>
- </tr>
- </table>
- </el-descriptions-item>
- <el-descriptions-item label="现场开支" :span="3" v-if="siteList.length > 0">
- <table border="1" style="width:100%;">
- <tr style="background-color:#f8f8f9">
- <td style="min-width:50px">序号</td>
- <td style="min-width:120px">开支项</td>
- <td style="min-width:120px">金额</td>
- <td>备注</td>
- </tr>
- <tr v-for="site, index in siteList" :key="'site' + site.expenseId">
- <td>{{ index + 1 }}</td>
- <td>{{ site.name }}</td>
- <td v-if="taskName == '分管审核'">
- <el-input-number style="width:100%;" :controls="false" v-model="site.amount" :min="0" :step="0.01"
- @change="(val) => updateSiteAmount(site, val)"></el-input-number>
- </td>
- <td v-else style="text-align:right;">{{ site.amount }}</td>
- <td class="remark-cell">{{ site.remark }}</td>
- </tr>
- <tr>
- <td colspan="2" class="head amount">现场开支合计</td>
- <td class="head amount" style="text-align:right;">{{siteList.reduce((sum, site) => sum +
- (Number(site.amount) || 0), 0).toFixed(2)}}
- </td>
- <td></td>
- </tr>
- </table>
- </el-descriptions-item>
- <el-descriptions-item label="经营相关" :span="3">
- <div v-if="taskName == '经营审核'" class="alert alert-warning"
- style="padding: 10px; border: 1px solid #f0ad4e; background-color: #fcf8e3; color: #8a6d3b;">
- 请填写以下内容
- </div>
- <table border="1" style="width:100%;" :class="{ 'business-section': taskName == '经营审核' }">
- <tr style="background-color:#f8f8f9">
- <td style="min-width:50px">序号</td>
- <td style="min-width:120px">名称</td>
- <td style="min-width:120px">金额</td>
- <td>备注</td>
- </tr>
- <tr>
- <td>{{ 1 }}</td>
- <td>外协费用</td>
- <td v-if="taskName == '经营审核'">
- <el-input-number style="width:100%;" :controls="false" v-model="budgetForm.outExpense" :min="0"
- :step="0.01" @change="updateTotalJYAmount"></el-input-number>
- </td>
- <td v-else style="text-align:right;">{{ budgetForm.outExpense }}</td>
- <td class="remark-cell">{{ budgetForm.outRemark }}</td>
- </tr>
- <tr>
- <td>{{ 2 }}</td>
- <td>保函费用</td>
- <td v-if="taskName == '经营审核'">
- <el-input-number style="width:100%;" :controls="false" v-model="budgetForm.letterExpense" :min="0"
- :step="0.01" @change="updateTotalJYAmount"></el-input-number>
- </td>
- <td v-else style="text-align:right;">{{ budgetForm.letterExpense }}</td>
- <td class="remark-cell">{{ budgetForm.letterRemark }}</td>
- </tr>
- <tr>
- <td>{{ 3 }}</td>
- <td>中标服务费</td>
- <td v-if="taskName == '经营审核'">
- <el-input-number style="width:100%;" :controls="false" v-model="budgetForm.winExpense" :min="0"
- :step="0.01" @change="updateTotalJYAmount"></el-input-number>
- </td>
- <td v-else style="text-align:right;">{{ budgetForm.winExpense }}</td>
- <td class="remark-cell">{{ budgetForm.winRemark }}</td>
- </tr>
- <tr>
- <td>{{ 4 }}</td>
- <td>税费</td>
- <td v-if="taskName == '经营审核'">
- <el-input-number style="width:100%;" :controls="false" v-model="budgetForm.taxExpense" :min="0"
- :step="0.01" @change="updateTotalJYAmount"></el-input-number>
- </td>
- <td v-else style="text-align:right;">{{ budgetForm.taxExpense }}</td>
- <td class="remark-cell">{{ budgetForm.taxRemark }}</td>
- </tr>
- <tr>
- <td>{{ 5 }}</td>
- <td>管理出差</td>
- <td v-if="taskName == '经营审核'">
- <el-input-number style="width:100%;" :controls="false" v-model="budgetForm.travelExpense" :min="0"
- :step="0.01" @change="updateTotalJYAmount"></el-input-number>
- </td>
- <td v-else style="text-align:right;">{{ budgetForm.travelExpense }}</td>
- <td class="remark-cell">{{ budgetForm.travelRemark }}</td>
- </tr>
- <tr>
- <td colspan="2" class="head amount">经营相关合计</td>
- <td class="head amount" style="text-align:right;">{{ totalJYAmount.toFixed(2) }}
- </td>
- <td></td>
- </tr>
- </table>
- </el-descriptions-item>
- <el-descriptions-item label="预算总额" :span="3">
- <table border="1" style="width:100%;" class="budget-summary">
- <tr class="header">
- <td><b>名称</b></td>
- <td><b>金额</b></td>
- </tr>
- <tr>
- <td>人员成本</td>
- <td style="text-align:right;">{{ isNaN(budgetForm.staffCost) ? 0 : Number(budgetForm.staffCost).toFixed(2)
- }}</td>
- </tr>
- <tr>
- <td>车辆成本</td>
- <td style="text-align:right;">{{ isNaN(budgetForm.carCost) ? 0 : Number(budgetForm.carCost).toFixed(2) }}
- </td>
- </tr>
- <tr>
- <td>设备成本</td>
- <td style="text-align:right;">{{ isNaN(budgetForm.deviceCost) ? 0 : Number(budgetForm.deviceCost).toFixed(2)
- }}</td>
- </tr>
- <tr>
- <td>现场开支成本</td>
- <td style="text-align:right;">{{ isNaN(budgetForm.siteSum) ? 0 : Number(budgetForm.siteSum).toFixed(2) }}
- </td>
- </tr>
- <tr>
- <td>经营相关成本</td>
- <td style="text-align:right;">{{ isNaN(totalJYAmount) ? 0 : Number(totalJYAmount).toFixed(2) }}</td>
- </tr>
- <tr class="total-budget">
- <td><b>预算总成本</b></td>
- <td style="text-align:right;"><b>{{ isNaN(budgetForm.totalBudget) ? 0 : budgetForm.totalBudget }}</b></td>
- </tr>
- </table>
- </el-descriptions-item>
- <el-descriptions-item label="合同总价" :span="3" v-hasRole="['leader', 'finance', 'nfinance', 'admin']">
- <table border="1" style="width:100%;" v-if="contractList.length > 0">
- <tr style="background-color:#f8f8f9">
- <td>序号</td>
- <td>合同名称</td>
- <td>合同总价</td>
- </tr>
- <tr v-for="contract, index in contractList" :key="contract.contractId">
- <td>{{ index + 1 }}</td>
- <td>{{ contract.contractName }}</td>
- <td>{{ contract.amount }}</td>
- </tr>
- </table>
- <div v-else>
- <div class="alert alert-warning">
- 暂无合同信息
- </div>
- </div>
- </el-descriptions-item>
- <el-descriptions-item label="分包合同总价" :span="3" v-hasRole="['leader', 'finance', 'nfinance', 'admin']">
- <table border="1" style="width:100%;" v-if="subContractList.length > 0">
- <tr style="background-color:#f8f8f9">
- <td>序号</td>
- <td>分包合同名称</td>
- <td>分包合同总价</td>
- </tr>
- <tr v-for="subContract, index in subContractList" :key="subContract.subContractId">
- <td>{{ index + 1 }}</td>
- <td>{{ subContract.subContractName }}</td>
- <td>{{ subContract.subAmount }}</td>
- </tr>
- </table>
- <div v-else>
- <div class="alert alert-warning">
- 暂无分包合同信息
- </div>
- </div>
- </el-descriptions-item>
- <el-descriptions-item label="分管领导审核意见" :span="3">
- <div v-if="taskName == '分管审核' && !budgetForm.managerComment" class="alert alert-warning"
- style="padding: 10px; border: 1px solid #f0ad4e; background-color: #fcf8e3; color: #8a6d3b;">
- 请填写以下内容
- </div>
- <div :class="{ 'business-section': taskName == '分管审核' && !budgetForm.managerComment }">
- <el-input :disabled="taskName != '分管审核'" type="textarea" placeholder="请输入审核意见"
- v-model="budgetForm.managerComment" :autosize="{ minRows: 4 }"></el-input>
- <div class="sign mt10" v-if="budgetForm.manager">
- <div class="mr20">签名:<span class="auditor">{{ getUserName(budgetForm.manager) }}</span>
- </div>
- <div class="ml20"><span>审核时间:{{ budgetForm.managerTime }}</span></div>
- </div>
- </div>
- </el-descriptions-item>
- <el-descriptions-item label="总经理审核意见" :span="3">
- <div v-if="taskName == '总经理审核'" class="alert alert-warning"
- style="padding: 10px; border: 1px solid #f0ad4e; background-color: #fcf8e3; color: #8a6d3b;">
- 请填写以下内容
- </div>
- <div :class="{ 'business-section': taskName == '总经理审核' }">
- <el-input :disabled="taskName != '总经理审核'" type="textarea" placeholder="请输入审核意见"
- v-model="budgetForm.zjlComment" :autosize="{ minRows: 4 }"></el-input>
- <div class="sign mt10" v-if="budgetForm.auditor">
- <div class="mr20">签名:<span class="auditor">{{ getUserName(budgetForm.auditor) }}</span>
- </div>
- <div class="ml20"><span>审核时间:{{ budgetForm.zjlTime }}</span></div>
- </div>
- </div>
- </el-descriptions-item>
- </el-descriptions>
- <div class="text-center mt20 mb20" v-if="taskName">
- <el-button type="danger" @click="returnOpen = true">退 回</el-button>
- <el-button type="warning" @click="preserve()">保 存</el-button>
- <el-button type="success" @click="confirmSucess()">提交下一个流程</el-button>
- </div>
- <el-dialog title="退回" :visible.sync="returnOpen" width="40%" append-to-body>
- <return-btn :taskForm="taskForm" :comment="commentByRole()" @goBack="$emit('goBack')"
- @cancel="returnOpen = false"></return-btn>
- </el-dialog>
- </div>
- </template>
-
- <script>
- import { listBudget, updateBudget } from "@/api/oa/budget/budget";
- import { listBudgetCar, updateBudgetCar } from "@/api/oa/budget/budgetCar";
- import { listBudgetDevice, updateBudgetDevice } from "@/api/oa/budget/budgetDevice";
- import { listBudgetSettle, updateBudgetSettle } from "@/api/oa/budget/budgetSettle";
- import { listBudgetStaff, updateBudgetStaff } from "@/api/oa/budget/budgetStaff";
- import { listProjectWork } from "@/api/oa/project/projectWork";
- import { listSite, updateSite } from "@/api/oa/budget/budgetSite.js";
- import { getProject } from "@/api/oa/project/project";
- import { getUsersManageLeader, getUserByPost } from "@/api/system/post";
- import { complete, getNextFlowNode } from "@/api/flowable/todo";
- import { listProjectContract } from "@/api/oa/contract/projectContract";
- import { listProjectSubcontract } from "@/api/oa/contract/projectSubcontract";
- import { getContract } from "@/api/oa/contract/contract";
- import { getSubContract } from "@/api/oa/contract/subContract";
- import { currentNodeByFormId } from "@/api/flowable/definition";
- import InnerStaffCost from './components/InnerStaffCost.vue';
- import OuterStaffCost from './components/OuterStaffCost.vue';
- import CarCost from './components/CarCost.vue';
- import DeviceCost from './components/DeviceCost.vue';
- import ReturnComment from '@/views/flowable/form/components/flowBtn/returnComment.vue';
- import ReturnBtn from '@/views/flowable/form/components/flowBtn/returnBtn.vue';
-
- export default {
- components: {
- InnerStaffCost,
- OuterStaffCost,
- CarCost,
- DeviceCost,
- ReturnComment,
- ReturnBtn
- },
- props: {
- taskForm: {
- type: Object,
- require: true
- },
- taskName: {
- type: String,
- }
- },
- watch: {
- 'taskForm.procInsId'() {
- this.initBudgetForm();
- this.getProjectWorkList();
- this.getContractInfo();
- this.getSubContractInfo();
- }
- },
- data() {
- return {
- baseUrl: process.env.VUE_APP_BASE_API,
- loading: true,
- budgetForm: {},
- project: {},
- workContentList: [],
- workList: [],
- innerStaffList: [],
- outerStaffList: [],
- carList: [],
- deviceList: [],
- siteList: [],
- totalJYAmount: 0,
- returnOpen: false,
- contractList: [],
- showAlter: true,
- subContractList: [],
- }
- },
- created() {
- this.initBudgetForm();
- this.getProjectWorkList();
- this.getContractInfo();
- this.getSubContractInfo();
- },
- methods: {
- initBudgetForm() {
- this.loading = true;
- listBudget({ pageNum: 1, pageSize: 20, projectId: this.taskForm.formId, procInstId:this.taskForm.procInsId }).then(async res => {
-
- this.budgetForm = res.rows[0];
- if (this.budgetForm) {
- this.budgetForm.outExpense = Number(this.budgetForm.outExpense).toFixed(2);
- this.budgetForm.letterExpense = Number(this.budgetForm.letterExpense).toFixed(2);
- this.budgetForm.winExpense = Number(this.budgetForm.winExpense).toFixed(2);
- this.budgetForm.taxExpense = Number(this.budgetForm.taxExpense).toFixed(2);
- this.budgetForm.travelExpense = Number(this.budgetForm.travelExpense).toFixed(2);
- this.budgetForm.totalBudget = Number(this.budgetForm.totalBudget).toFixed(2);
- this.totalJYAmount = Number(this.budgetForm.outExpense || 0) +
- Number(this.budgetForm.letterExpense || 0) +
- Number(this.budgetForm.winExpense || 0) +
- Number(this.budgetForm.taxExpense || 0) +
- Number(this.budgetForm.travelExpense || 0);
- const budgetId = this.budgetForm.budgetId;
- // 获取设备数据
- let deviceRes = await listBudgetDevice({ pageSize: 100, budgetId });
- this.deviceList = deviceRes.rows;
- this.deviceList = this.deviceList.map(device => {
- return {
- ...device,
- amount: Number(device.amount).toFixed(2),
- };
- });
-
- // 获取车辆数据
- let carRes = await listBudgetCar({ pageSize: 100, budgetId });
- this.carList = carRes.rows;
- this.carList = this.carList.map(car => {
- return {
- ...car,
- amount: Number(car.amount).toFixed(2),
- };
- });
-
- // 获取内业人员数据
- let innerStaffRes = await listBudgetStaff({ pageSize: 100, budgetId, type: '内业' });
- this.innerStaffList = innerStaffRes.rows;
- this.innerStaffList = this.innerStaffList.map(staff => {
- return {
- ...staff,
- dayCost: Number(staff.dayCost).toFixed(2),
- performance: Number(staff.performance).toFixed(2),
- amount: Number(staff.amount).toFixed(2),
- staffCost: Number(staff.staffCost).toFixed(2)
- };
- });
-
- // 获取外业人员数据
- let outerStaffRes = await listBudgetStaff({ pageSize: 100, budgetId, type: '外业' });
- this.outerStaffList = outerStaffRes.rows;
- this.outerStaffList = this.outerStaffList.map(staff => {
- return {
- ...staff,
- dayCost: Number(staff.dayCost).toFixed(2),
- performance: Number(staff.performance).toFixed(2),
- amount: Number(staff.amount).toFixed(2),
- staffCost: Number(staff.staffCost).toFixed(2)
- };
- });
-
- // 获取内业绩效额数据
- let settleRes = await listBudgetSettle({ pageSize: 100, budgetId });
- this.workList = settleRes.rows;
- for (let work of this.workList) {
- if (work.checkPriceId) {
- work.workType = work.cmcCheckPrice.workType
- work.workItem = work.cmcCheckPrice.workItem
- work.subItem = work.cmcCheckPrice.subItem
- work.scaleGrade = work.cmcCheckPrice.scaleGrade
- work.unit = work.cmcCheckPrice.unit
- if (work.groundType == '0') {
- work.price = work.cmcCheckPrice.commonPrice
- } else {
- work.price = work.cmcCheckPrice.complexPrice
- }
- } else {
- work.workType = work.cmcPrice.workType
- work.workItem = work.cmcPrice.workItem
- work.subItem = work.cmcPrice.subItem
- work.scaleGrade = work.cmcPrice.scaleGrade
- work.unit = work.cmcPrice.unit
- if (work.groundType == '0') {
- work.price = work.cmcPrice.commonPrice
- } else {
- work.price = work.cmcPrice.complexPrice
- }
- }
- }
- // 获取现场开支
- let siteRes = await listSite({ pageSize: 100, budgetId });
- this.siteList = siteRes.rows;
- this.siteList = this.siteList.map(site => {
- return {
- ...site,
- amount: Number(site.amount).toFixed(2),
- };
- });
- this.budgetForm.siteSum = this.siteList.reduce((sum, site) => sum + (Number(site.amount) || 0), 0);
-
- // 检查内业人员绩效总额是否超过内业绩效总额
- const totalPerformance = this.innerStaffList.reduce((sum, staff) => sum + (Number(staff.performance) || 0), 0);
- if (totalPerformance > Number(this.budgetForm.settleExpense)) {
- this.$message.warning('内业人员绩效总额超过内业绩效总额,请检查');
- }
- this.getCurrentTaskName(this.budgetForm.projectId).then(response => {
- if (response != '总经理审核' && response != '预算批准') {
- this.$set(this.budgetForm, 'managerComment', undefined);
- this.$set(this.budgetForm, 'manager', undefined);
- this.$set(this.budgetForm, 'managerTime', undefined);
- }
- if (response != '预算批准') {
- this.$set(this.budgetForm, 'zjlComment', undefined);
- this.$set(this.budgetForm, 'auditor', undefined);
- this.$set(this.budgetForm, 'zjlTime', undefined);
- }
- })
- }
- this.loading = false;
- }).catch(() => {
- this.loading = false;
- });
- },
- getContractInfo() {
- listProjectContract({ projectId: this.taskForm.formId }).then(res => {
- let contractIds = res.rows;
- this.contractList = [];
- for (let contractId of contractIds) {
- getContract(contractId.contractId).then(response => {
- this.contractList.push(response.data);
- })
- }
- })
- },
- getSubContractInfo() {
- listProjectSubcontract({ projectId: this.taskForm.formId }).then(res => {
- let subContractIds = res.rows;
- this.subContractList = [];
- for (let subContract of subContractIds) {
- getSubContract(subContract.subContractId).then(response => {
- this.subContractList.push(response.data);
- })
- }
- })
- },
- safeNumber(value) {
- const num = Number(value);
- return isNaN(num) ? 0 : num;
- },
- getProjectWorkList() {
- getProject(this.taskForm.formId).then(res => {
- this.project = res.data;
- })
- listProjectWork({ pageSize: 999, projectId: this.taskForm.formId }).then(res => {
- this.workContentList = res.rows;
- })
- },
- async getCurrentTaskName(projectId) {
- let resData = await currentNodeByFormId({ formId: projectId, name: '3045' })
- if (resData.code == 200) {
- return resData.msg;
- }
- else
- return ''
- },
- async preserve() {
- this.$message.warning('正在保存,请勿关闭页面');
- if (this.taskName == '分管审核') {
- this.budgetForm.manager = this.$store.getters.userId;
- this.budgetForm.managerTime = this.parseTime(new Date(), '{y}-{m}-{d}');
- } else if (this.taskName == '总经理审核') {
- this.budgetForm.auditor = this.$store.getters.userId;
- this.budgetForm.zjlTime = this.parseTime(new Date(), '{y}-{m}-{d}');
- }
- if (this.taskName != '经营审核') {
- await Promise.all([
- ...this.carList.map(car => updateBudgetCar(car)),
- ...this.deviceList.map(device => updateBudgetDevice(device)),
- ...this.innerStaffList.map(staff => updateBudgetStaff(staff)),
- ...this.outerStaffList.map(staff => updateBudgetStaff(staff)),
- ...this.workList.map(work => updateBudgetSettle(work)),
- ...this.siteList.map(site => updateSite(site))
- ]);
- }
- await updateBudget(this.budgetForm)
- this.$message.success('保存成功');
- },
- confirmSucess() {
- this.preserve();
- this.$modal.confirm('是否提交到下一个流程?').then(async () => {
- if (this.taskName == '经营审核') {
- let managerLeaderRes = await getUsersManageLeader({ userId: this.budgetForm.compiler });
- let managerLeader = managerLeaderRes.data;
- let managerList = managerLeader.map(item => item.userId);
- this.$set(this.taskForm.variables, 'approvalList', managerList);
- }
- else if (this.taskName == '分管审核') {
- if (!this.budgetForm.managerComment) {
- this.$message.error('请填写审核意见')
- return
- }
- let zjlRes = await getUserByPost({ postName: '总经理' });
- let zjlUserId = zjlRes.data[0].userId;
- this.$set(this.taskForm.variables, 'approval', zjlUserId);
- }
- else if (this.taskName == '总经理审核') {
- if (!this.budgetForm.zjlComment) {
- this.$message.error('请填写审核意见')
- return
- }
- let dszRes = await getUserByPost({ postName: '董事长' });
- let dszUserId = dszRes.data[0].userId;
- this.$set(this.taskForm.variables, 'approval', dszUserId);
- this.$set(this.taskForm.variables, "skip", true);
- }
- //提交到下一个流程
- getNextFlowNode({ taskId: this.taskForm.taskId }).then(res => {
- complete(this.taskForm).then(response => {
- this.$modal.msgSuccess(response.msg);
- this.$emit("goBack");
- });
- });
- })
- },
- updateTotalJYAmount() {
- this.totalJYAmount = Number(this.budgetForm.outExpense || 0) +
- Number(this.budgetForm.letterExpense || 0) +
- Number(this.budgetForm.winExpense || 0) +
- Number(this.budgetForm.taxExpense || 0) +
- Number(this.budgetForm.travelExpense || 0);
- const innerStaffTotal = this.innerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
- const outerStaffTotal = this.outerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
- const carTotal = this.carList.reduce((sum, car) => sum + (Number(car.amount) || 0), 0);
- const deviceTotal = this.deviceList.reduce((sum, device) => sum + (Number(device.amount) || 0), 0);
- const siteTotal = this.siteList.reduce((sum, site) => sum + (Number(site.amount) || 0), 0);
- this.budgetForm.totalBudget = (innerStaffTotal +
- outerStaffTotal +
- carTotal +
- deviceTotal +
- siteTotal +
- this.totalJYAmount).toFixed(2);
- },
- commentByRole() {
- if (this.taskName == '分管审核') {
- return this.budgetForm.managerComment
- } else if (this.taskName == '总经理审核') {
- return this.budgetForm.zjlComment
- } else if (this.taskName == '董事长批准') {
- return this.budgetForm.dszComment
- }
- },
- updateSettle(work, value, field) {
- work[field] = value;
- work.settle = (Number(work.workload) * Number(work.price) * Number(work.coefficient)).toFixed(2);
- this.budgetForm.settleExpense = this.workList.reduce((sum, work) => {
- return sum + (Number(work.settle) || 0);
- }, 0);
- this.updateTotalJYAmount();
- },
- updateInnerStaffAmount(staff, value, field) {
- staff[field] = value;
- staff.staffCost = (Number(staff.days) * Number(staff.dayCost)).toFixed(2);
- staff.amount = (Number(staff.staffCost) + Number(staff.performance)).toFixed(2);
- let innerStaffTotal = this.innerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
- let outerStaffTotal = this.outerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
- let innerStaffPerformance = this.innerStaffList.reduce((sum, staff) => sum + (Number(staff.performance) || 0), 0);
- this.budgetForm.staffCost = (innerStaffTotal + outerStaffTotal).toFixed(2);
- this.updateTotalJYAmount();
- if (innerStaffPerformance > this.budgetForm.settleExpense) {
- this.$message.error('内业人员成本超过内业绩效总额,请修改');
- return;
- }
- },
- updateOuterStaffAmount(staff, value, field) {
- staff[field] = value;
- staff.performance = (200 * Number(staff.days) * Number(staff.coefficient)).toFixed(2);
- staff.amount = (Number(staff.staffCost) + Number(staff.performance)).toFixed(2);
- let innerStaffTotal = this.innerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
- let outerStaffTotal = this.outerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
- this.budgetForm.staffCost = (innerStaffTotal + outerStaffTotal).toFixed(2);
- this.updateTotalJYAmount();
- },
- updateCarAmount(car, value) {
- car.days = value;
- car.amount = (Number(car.car.dayCost) * Number(car.days)).toFixed(2);
- let carTotal = this.carList.reduce((sum, car) => sum + (Number(car.amount) || 0), 0);
- this.budgetForm.carCost = carTotal.toFixed(2);
- this.updateTotalJYAmount();
- },
- updateDeviceAmount(device, value) {
- device.days = value;
- device.amount = (Number(device.device.dayCost) * Number(device.days)).toFixed(2);
- let deviceTotal = this.deviceList.reduce((sum, device) => sum + (Number(device.amount) || 0), 0);
- this.budgetForm.deviceCost = deviceTotal.toFixed(2);
- this.updateTotalJYAmount();
- },
- updateSiteAmount(site, value) {
- site.amount = value;
- let siteTotal = this.siteList.reduce((sum, site) => sum + (Number(site.amount) || 0), 0);
- this.budgetForm.siteSum = siteTotal.toFixed(2);
- this.updateTotalJYAmount();
- },
- isPerformanceExceeded() {
- const totalPerformance = this.innerStaffList.reduce((sum, staff) => sum + (Number(staff.performance) || 0), 0);
- return totalPerformance > Number(this.budgetForm.settleExpense);
- },
- isReturn(val) {
- this.showAlter = val;
- },
- },
- }
- </script>
-
- <style lang="scss" scoped>
- @import "@/assets/styles/element-reset.scss";
-
- .mylabel {
- font-weight: bold;
- }
-
- .main {
- width: 90%;
- margin: 0 auto;
- text-align: center;
- }
-
- .descriptions {
- width: 100%;
- margin: 0 auto;
- }
-
- .amount {
- font-weight: bold;
- font-family: Arial, Helvetica, sans-serif;
- }
-
- table {
- text-align: center;
- border-collapse: collapse;
- margin: 0 auto;
-
- /*设置背景颜色*/
- /* background-color: #bfa; */
- td {
- padding: 5px;
- }
- }
-
- .remark-cell {
- text-align: left;
- }
-
- .adjust {
- color: #F56C6C;
- width: 120px;
- }
-
- .total-budget {
- font-size: 16px;
- font-weight: bold;
- color: #4CAF50;
- text-align: center;
- padding: 10px;
- border: 2px solid #4CAF50;
- border-radius: 5px;
- background-color: #f0f8f5;
- }
-
- ::v-deep .el-descriptions .is-bordered .el-descriptions-item__cell {
- border: 1px solid #838894;
- }
-
- ::v-deep .el-descriptions-item__label.is-bordered-label {
- color: #434141;
- background: #eaeaea;
- }
-
- .business-section {
- border: 2px solid #E6A23C !important;
- box-shadow: 0 0 10px rgba(64, 158, 255, 0.2);
-
- tr {
- background-color: #f0f7ff;
-
- &:hover {
- background-color: #e6f1ff;
- }
- }
-
- .el-input-number {
- .el-input__inner {
- background-color: #fff;
- border: 1px solid #E6A23C;
-
- &:focus {
- border-color: #e2af62;
- box-shadow: 0 0 5px rgba(64, 158, 255, 0.3);
- }
- }
- }
-
- .head.amount {
- background-color: #ecf5ff;
- color: #E6A23C;
- font-weight: bold;
- }
- }
-
-
- .sign {
- display: flex;
- justify-content: flex-end;
- align-items: center;
- padding-right: 80px;
- line-height: 30px;
- /* 如果需要垂直居中 */
- }
-
- .performance-error {
- background-color: #fef0f0 !important;
- color: #f56c6c !important;
- border: 1px solid #fbc4c4 !important;
- }
-
- .performance-error:hover {
- background-color: #fde2e2 !important;
- }
-
- .performance-error .el-input-number {
- .el-input__inner {
- background-color: #fef0f0;
- border-color: #f56c6c;
- color: #f56c6c;
- }
- }
- </style>
|