|
@@ -2,11 +2,11 @@
|
2
|
2
|
* @Author: ysh
|
3
|
3
|
* @Date: 2025-05-07 11:01:39
|
4
|
4
|
* @LastEditors: Please set LastEditors
|
5
|
|
- * @LastEditTime: 2025-05-12 17:51:37
|
|
5
|
+ * @LastEditTime: 2025-05-13 18:05:08
|
6
|
6
|
-->
|
7
|
7
|
<template>
|
8
|
|
- <div class="main">
|
9
|
|
- <h2 class="text-center">项目直接生产成本预算—核算表</h2>
|
|
8
|
+ <div class="main" v-loading="loading">
|
|
9
|
+ <h2 class="text-center">项目直接生产成本预算表</h2>
|
10
|
10
|
<p style="text-align: center">编制人:{{ budgetForm.compilerUser ? budgetForm.compilerUser.nickName : '' }}</p>
|
11
|
11
|
<el-divider></el-divider>
|
12
|
12
|
<el-descriptions :column="3" border class="descriptions">
|
|
@@ -55,7 +55,7 @@
|
55
|
55
|
<td>
|
56
|
56
|
{{ work.deadline }}
|
57
|
57
|
</td>
|
58
|
|
- <td>
|
|
58
|
+ <td class="remark-cell">
|
59
|
59
|
{{ work.remark }}
|
60
|
60
|
</td>
|
61
|
61
|
</tr>
|
|
@@ -81,16 +81,24 @@
|
81
|
81
|
<td>
|
82
|
82
|
{{ work.scaleGrade }}
|
83
|
83
|
</td>
|
84
|
|
- <td>
|
|
84
|
+ <td v-if="taskName == '分管审核'">
|
|
85
|
+ <el-input-number style="width:80px;" :controls="false" v-model="work.workload" :min="0" :step="0.01"
|
|
86
|
+ @change="(val) => updateSettle(work, val, 'workload')"></el-input-number>
|
|
87
|
+ </td>
|
|
88
|
+ <td v-else>
|
85
|
89
|
{{ work.workload }}
|
86
|
90
|
</td>
|
87
|
91
|
<td>{{ work.price }}</td>
|
88
|
92
|
<td>{{ work.unit }}</td>
|
89
|
|
- <td>
|
|
93
|
+ <td v-if="taskName == '分管审核'">
|
|
94
|
+ <el-input-number style="width:80px;" :controls="false" v-model="work.coefficient" :min="0" :step="0.01"
|
|
95
|
+ @change="(val) => updateSettle(work, val, 'coefficient')"></el-input-number>
|
|
96
|
+ </td>
|
|
97
|
+ <td v-else>
|
90
|
98
|
{{ work.coefficient }}
|
91
|
99
|
</td>
|
92
|
100
|
<td style="text-align:right;">{{ work.settle ? work.settle.toFixed(2) : '0.00' }}</td>
|
93
|
|
- <td>{{ work.remark ? work.remark : '' }}</td>
|
|
101
|
+ <td class="remark-cell">{{ work.remark ? work.remark : '' }}</td>
|
94
|
102
|
</tr>
|
95
|
103
|
<tr>
|
96
|
104
|
<td :colspan="7" class="head amount">内业绩效额合计</td>
|
|
@@ -111,20 +119,37 @@
|
111
|
119
|
<td>固定成本合计</td>
|
112
|
120
|
<td>绩效成本合计</td>
|
113
|
121
|
<td style="width:120px">金额</td>
|
|
122
|
+ <td style="width:120px">备注</td>
|
114
|
123
|
</tr>
|
115
|
124
|
<tr v-for="staff, index in innerStaffList" :key="'user' + staff.userId">
|
116
|
125
|
<td>{{ index + 1 }}</td>
|
117
|
126
|
<td>{{ staff.user ? staff.user.nickName : '' }}</td>
|
118
|
127
|
<td>{{ staff.dayCost }}</td>
|
119
|
|
- <td>{{ staff.days }}</td>
|
120
|
|
- <td>{{ (Number(staff.dayCost) * Number(staff.days)).toFixed(2) }}</td>
|
121
|
|
- <td>{{ staff.performance }}</td>
|
122
|
|
- <td>{{ staff.amount }}</td>
|
123
|
|
- </tr>
|
|
128
|
+ <td v-if="taskName == '分管审核'">
|
|
129
|
+ <el-input-number style="width:80px;" :controls="false" v-model="staff.days" :min="0"
|
|
130
|
+ :step="0.01" @change="(val) => updateInnerStaffAmount(staff, val, 'days')"></el-input-number>
|
|
131
|
+ </td>
|
|
132
|
+ <td v-else>{{ staff.days }}</td>
|
|
133
|
+ <td style="text-align:right;">{{ staff.staffCost }}</td>
|
|
134
|
+ <td v-if="taskName == '分管审核'">
|
|
135
|
+ <el-input-number style="width:80px;" :controls="false" v-model="staff.performance" :min="0"
|
|
136
|
+ :step="0.01" @change="(val) => updateInnerStaffAmount(staff, val, 'performance')"></el-input-number>
|
|
137
|
+ </td>
|
|
138
|
+ <td v-else style="text-align:right;">{{ staff.performance }}</td>
|
|
139
|
+ <td style="text-align:right;">{{ staff.amount }}</td>
|
|
140
|
+ <td class="remark-cell">{{ staff.remark }}</td>
|
|
141
|
+ </tr>
|
124
|
142
|
<tr>
|
125
|
|
- <td colspan="5" class="head amount">内业人员成本合计</td>
|
126
|
|
- <td class="head amount">{{ innerStaffList.reduce((sum, staff) => sum + (Number(staff.performance) || 0), 0).toFixed(2) }}</td>
|
127
|
|
- <td class="head amount">{{ innerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0).toFixed(2) }}</td>
|
|
143
|
+ <td colspan="4" class="head amount">内业人员成本合计</td>
|
|
144
|
+ <td class="head amount" style="text-align:right;">{{innerStaffList.reduce((sum, staff) => sum +
|
|
145
|
+ (Number(staff.staffCost) || 0),
|
|
146
|
+ 0).toFixed(2)}}</td>
|
|
147
|
+ <td class="head amount" style="text-align:right;">{{innerStaffList.reduce((sum, staff) => sum +
|
|
148
|
+ (Number(staff.performance) || 0),
|
|
149
|
+ 0).toFixed(2)}}</td>
|
|
150
|
+ <td class="head amount" style="text-align:right;">{{innerStaffList.reduce((sum, staff) => sum +
|
|
151
|
+ (Number(staff.amount) || 0),
|
|
152
|
+ 0).toFixed(2)}}</td>
|
128
|
153
|
</tr>
|
129
|
154
|
</table>
|
130
|
155
|
</el-descriptions-item>
|
|
@@ -140,21 +165,39 @@
|
140
|
165
|
<td>固定成本合计</td>
|
141
|
166
|
<td>绩效成本合计</td>
|
142
|
167
|
<td style="width:120px">金额</td>
|
|
168
|
+ <td style="width:120px">备注</td>
|
143
|
169
|
</tr>
|
144
|
170
|
<tr v-for="staff, index in outerStaffList" :key="'user' + staff.userId">
|
145
|
171
|
<td>{{ index + 1 }}</td>
|
146
|
172
|
<td>{{ staff.user ? staff.user.nickName : '' }}</td>
|
147
|
173
|
<td>{{ staff.dayCost }}</td>
|
148
|
174
|
<td>200</td>
|
149
|
|
- <td>{{ staff.days }}</td>
|
150
|
|
- <td>{{ staff.coefficient }}</td>
|
151
|
|
- <td>{{ (Number(staff.dayCost) * Number(staff.days)).toFixed(2) }}</td>
|
152
|
|
- <td>{{ staff.performance }}</td>
|
153
|
|
- <td>{{ staff.amount }}</td>
|
|
175
|
+ <td v-if="taskName == '分管审核'">
|
|
176
|
+ <el-input-number style="width:80px;" :controls="false" v-model="staff.days" :min="0"
|
|
177
|
+ :step="0.01" @change="(val) => updateOuterStaffAmount(staff, val, 'days')"></el-input-number>
|
|
178
|
+ </td>
|
|
179
|
+ <td v-else>{{ staff.days }}</td>
|
|
180
|
+ <td v-if="taskName == '分管审核'">
|
|
181
|
+ <el-input-number style="width:80px;" :controls="false" v-model="staff.coefficient" :min="0"
|
|
182
|
+ :step="0.01" @change="(val) => updateOuterStaffAmount(staff, val, 'coefficient')"></el-input-number>
|
|
183
|
+ </td>
|
|
184
|
+ <td v-else>{{ staff.coefficient }}</td>
|
|
185
|
+ <td style="text-align:right;">{{ staff.staffCost }}</td>
|
|
186
|
+ <td style="text-align:right;">{{ staff.performance }}</td>
|
|
187
|
+ <td style="text-align:right;">{{ staff.amount }}</td>
|
|
188
|
+ <td class="remark-cell">{{ staff.remark }}</td>
|
154
|
189
|
</tr>
|
155
|
190
|
<tr>
|
156
|
|
- <td colspan="8" class="head amount">外业人员成本合计</td>
|
157
|
|
- <td class="head amount">{{ outerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0).toFixed(2) }}</td>
|
|
191
|
+ <td colspan="6" class="head amount">外业人员成本合计</td>
|
|
192
|
+ <td class="head amount" style="text-align:right;">{{outerStaffList.reduce((sum, staff) => sum +
|
|
193
|
+ (Number(staff.staffCost) || 0),
|
|
194
|
+ 0).toFixed(2)}}</td>
|
|
195
|
+ <td class="head amount" style="text-align:right;">{{outerStaffList.reduce((sum, staff) => sum +
|
|
196
|
+ (Number(staff.performance) || 0),
|
|
197
|
+ 0).toFixed(2)}}</td>
|
|
198
|
+ <td class="head amount" style="text-align:right;">{{outerStaffList.reduce((sum, staff) => sum +
|
|
199
|
+ (Number(staff.amount) || 0),
|
|
200
|
+ 0).toFixed(2)}}</td>
|
158
|
201
|
</tr>
|
159
|
202
|
</table>
|
160
|
203
|
</el-descriptions-item>
|
|
@@ -171,12 +214,18 @@
|
171
|
214
|
<td>{{ index + 1 }}</td>
|
172
|
215
|
<td>{{ car.car ? car.car.licensePlate : '' }}</td>
|
173
|
216
|
<td>{{ car.car ? car.car.dayCost : '' }}</td>
|
174
|
|
- <td>{{ car.days }}</td>
|
175
|
|
- <td>{{ car.amount }}</td>
|
|
217
|
+ <td v-if="taskName == '分管审核'">
|
|
218
|
+ <el-input-number style="width:80px;" :controls="false" v-model="car.days" :min="0"
|
|
219
|
+ :step="0.01" @change="(val) => updateCarAmount(car, val)"></el-input-number>
|
|
220
|
+ </td>
|
|
221
|
+ <td v-else>{{ car.days }}</td>
|
|
222
|
+ <td style="text-align:right;">{{ car.amount }}</td>
|
176
|
223
|
</tr>
|
177
|
224
|
<tr>
|
178
|
225
|
<td colspan="4" class="head amount">车辆成本合计</td>
|
179
|
|
- <td class="head amount">{{ carList.reduce((sum, car) => sum + (Number(car.amount) || 0), 0).toFixed(2) }}</td>
|
|
226
|
+ <td class="head amount" style="text-align:right;">{{carList.reduce((sum, car) => sum + (Number(car.amount)
|
|
227
|
+ || 0), 0).toFixed(2)}}
|
|
228
|
+ </td>
|
180
|
229
|
</tr>
|
181
|
230
|
</table>
|
182
|
231
|
</el-descriptions-item>
|
|
@@ -197,12 +246,18 @@
|
197
|
246
|
<td>{{ device.device ? device.device.series : '' }}</td>
|
198
|
247
|
<td>{{ device.device ? device.device.brand : '' }}</td>
|
199
|
248
|
<td>{{ device.device ? device.device.dayCost : '' }}</td>
|
200
|
|
- <td>{{ device.days }}</td>
|
201
|
|
- <td>{{ device.amount }}</td>
|
|
249
|
+ <td v-if="taskName == '分管审核'">
|
|
250
|
+ <el-input-number style="width:80px;" :controls="false" v-model="device.days" :min="0"
|
|
251
|
+ :step="0.01" @change="(val) => updateDeviceAmount(device, val)"></el-input-number>
|
|
252
|
+ </td>
|
|
253
|
+ <td v-else>{{ device.days }}</td>
|
|
254
|
+ <td style="text-align:right;">{{ device.amount }}</td>
|
202
|
255
|
</tr>
|
203
|
256
|
<tr>
|
204
|
257
|
<td colspan="6" class="head amount">设备成本合计</td>
|
205
|
|
- <td class="head amount">{{ deviceList.reduce((sum, device) => sum + (Number(device.amount) || 0), 0).toFixed(2) }}</td>
|
|
258
|
+ <td class="head amount" style="text-align:right;">{{deviceList.reduce((sum, device) => sum +
|
|
259
|
+ (Number(device.amount) || 0),
|
|
260
|
+ 0).toFixed(2)}}</td>
|
206
|
261
|
</tr>
|
207
|
262
|
</table>
|
208
|
263
|
</el-descriptions-item>
|
|
@@ -217,20 +272,160 @@
|
217
|
272
|
<tr v-for="site, index in siteList" :key="'site' + site.expenseId">
|
218
|
273
|
<td>{{ index + 1 }}</td>
|
219
|
274
|
<td>{{ site.name }}</td>
|
220
|
|
- <td>{{ site.amount }}</td>
|
221
|
|
- <td>{{ site.remark }}</td>
|
|
275
|
+ <td style="text-align:right;">{{ site.amount }}</td>
|
|
276
|
+ <td class="remark-cell">{{ site.remark }}</td>
|
222
|
277
|
</tr>
|
223
|
278
|
<tr>
|
224
|
279
|
<td colspan="2" class="head amount">现场开支合计</td>
|
225
|
|
- <td class="head amount">{{ siteList.reduce((sum, site) => sum + (Number(site.amount) || 0), 0).toFixed(2) }}</td>
|
|
280
|
+ <td class="head amount" style="text-align:right;">{{siteList.reduce((sum, site) => sum +
|
|
281
|
+ (Number(site.amount) || 0), 0).toFixed(2)}}
|
|
282
|
+ </td>
|
226
|
283
|
<td></td>
|
227
|
284
|
</tr>
|
228
|
285
|
</table>
|
229
|
286
|
</el-descriptions-item>
|
230
|
287
|
<el-descriptions-item label="经营相关" :span="3">
|
231
|
|
-
|
|
288
|
+ <div v-if="taskName == '经营审核'" class="alert alert-warning"
|
|
289
|
+ style="padding: 10px; border: 1px solid #f0ad4e; background-color: #fcf8e3; color: #8a6d3b;">
|
|
290
|
+ 请填写以下内容
|
|
291
|
+ </div>
|
|
292
|
+ <table border="1" style="width:100%;" :class="{ 'business-section': taskName == '经营审核' }">
|
|
293
|
+ <tr style="background-color:#f8f8f9">
|
|
294
|
+ <td>序号</td>
|
|
295
|
+ <td>名称</td>
|
|
296
|
+ <td>金额</td>
|
|
297
|
+ <td>备注</td>
|
|
298
|
+ </tr>
|
|
299
|
+ <tr>
|
|
300
|
+ <td>{{ 1 }}</td>
|
|
301
|
+ <td>外协费用</td>
|
|
302
|
+ <td v-if="taskName == '经营审核'">
|
|
303
|
+ <el-input-number style="width:100%;" :controls="false" v-model="budgetForm.outExpense" :min="0"
|
|
304
|
+ :step="0.01" @change="updateTotalJYAmount"></el-input-number>
|
|
305
|
+ </td>
|
|
306
|
+ <td v-else style="text-align:right;">{{ budgetForm.outExpense }}</td>
|
|
307
|
+ <td class="remark-cell">{{ budgetForm.outRemark }}</td>
|
|
308
|
+ </tr>
|
|
309
|
+ <tr>
|
|
310
|
+ <td>{{ 2 }}</td>
|
|
311
|
+ <td>保函费用</td>
|
|
312
|
+ <td v-if="taskName == '经营审核'">
|
|
313
|
+ <el-input-number style="width:100%;" :controls="false" v-model="budgetForm.letterExpense" :min="0"
|
|
314
|
+ :step="0.01" @change="updateTotalJYAmount"></el-input-number>
|
|
315
|
+ </td>
|
|
316
|
+ <td v-else style="text-align:right;">{{ budgetForm.letterExpense }}</td>
|
|
317
|
+ <td class="remark-cell">{{ budgetForm.letterRemark }}</td>
|
|
318
|
+ </tr>
|
|
319
|
+ <tr>
|
|
320
|
+ <td>{{ 3 }}</td>
|
|
321
|
+ <td>中标服务费</td>
|
|
322
|
+ <td v-if="taskName == '经营审核'">
|
|
323
|
+ <el-input-number style="width:100%;" :controls="false" v-model="budgetForm.winExpense" :min="0"
|
|
324
|
+ :step="0.01" @change="updateTotalJYAmount"></el-input-number>
|
|
325
|
+ </td>
|
|
326
|
+ <td v-else style="text-align:right;">{{ budgetForm.winExpense }}</td>
|
|
327
|
+ <td class="remark-cell">{{ budgetForm.winRemark }}</td>
|
|
328
|
+ </tr>
|
|
329
|
+ <tr>
|
|
330
|
+ <td>{{ 4 }}</td>
|
|
331
|
+ <td>税费</td>
|
|
332
|
+ <td v-if="taskName == '经营审核'">
|
|
333
|
+ <el-input-number style="width:100%;" :controls="false" v-model="budgetForm.taxExpense" :min="0"
|
|
334
|
+ :step="0.01" @change="updateTotalJYAmount"></el-input-number>
|
|
335
|
+ </td>
|
|
336
|
+ <td v-else style="text-align:right;">{{ budgetForm.taxExpense }}</td>
|
|
337
|
+ <td class="remark-cell">{{ budgetForm.taxRemark }}</td>
|
|
338
|
+ </tr>
|
|
339
|
+ <tr>
|
|
340
|
+ <td>{{ 5 }}</td>
|
|
341
|
+ <td>管理出差</td>
|
|
342
|
+ <td v-if="taskName == '经营审核'">
|
|
343
|
+ <el-input-number style="width:100%;" :controls="false" v-model="budgetForm.travelExpense" :min="0"
|
|
344
|
+ :step="0.01" @change="updateTotalJYAmount"></el-input-number>
|
|
345
|
+ </td>
|
|
346
|
+ <td v-else style="text-align:right;">{{ budgetForm.travelExpense }}</td>
|
|
347
|
+ <td class="remark-cell">{{ budgetForm.travelRemark }}</td>
|
|
348
|
+ </tr>
|
|
349
|
+ <tr>
|
|
350
|
+ <td colspan="2" class="head amount">经营相关合计</td>
|
|
351
|
+ <td class="head amount" style="text-align:right;">{{ totalJYAmount.toFixed(2) }}
|
|
352
|
+ </td>
|
|
353
|
+ <td></td>
|
|
354
|
+ </tr>
|
|
355
|
+ </table>
|
|
356
|
+ </el-descriptions-item>
|
|
357
|
+ <el-descriptions-item label="预算总额" :span="3">
|
|
358
|
+ <table border="1" style="width:100%;" class="budget-summary">
|
|
359
|
+ <tr class="header">
|
|
360
|
+ <td><b>名称</b></td>
|
|
361
|
+ <td><b>金额</b></td>
|
|
362
|
+ </tr>
|
|
363
|
+ <tr>
|
|
364
|
+ <td>人员成本</td>
|
|
365
|
+ <td style="text-align:right;">{{ isNaN(budgetForm.staffCost) ? 0 : Number(budgetForm.staffCost).toFixed(2) }}</td>
|
|
366
|
+ </tr>
|
|
367
|
+ <tr>
|
|
368
|
+ <td>车辆成本</td>
|
|
369
|
+ <td style="text-align:right;">{{ isNaN(budgetForm.carCost) ? 0 : Number(budgetForm.carCost).toFixed(2) }}</td>
|
|
370
|
+ </tr>
|
|
371
|
+ <tr>
|
|
372
|
+ <td>设备成本</td>
|
|
373
|
+ <td style="text-align:right;">{{ isNaN(budgetForm.deviceCost) ? 0 : Number(budgetForm.deviceCost).toFixed(2) }}</td>
|
|
374
|
+ </tr>
|
|
375
|
+ <tr>
|
|
376
|
+ <td>现场开支成本</td>
|
|
377
|
+ <td style="text-align:right;">{{ isNaN(budgetForm.siteSum) ? 0 : Number(budgetForm.siteSum).toFixed(2) }}</td>
|
|
378
|
+ </tr>
|
|
379
|
+ <tr>
|
|
380
|
+ <td>经营相关成本</td>
|
|
381
|
+ <td style="text-align:right;">{{ isNaN(totalJYAmount) ? 0 : Number(totalJYAmount).toFixed(2) }}</td>
|
|
382
|
+ </tr>
|
|
383
|
+ <tr class="total-budget">
|
|
384
|
+ <td><b>预算总成本</b></td>
|
|
385
|
+ <td style="text-align:right;"><b>{{ isNaN(budgetForm.totalBudget) ? 0 : budgetForm.totalBudget }}</b></td>
|
|
386
|
+ </tr>
|
|
387
|
+ </table>
|
|
388
|
+ </el-descriptions-item>
|
|
389
|
+ <el-descriptions-item label="分管领导审核意见" :span="3">
|
|
390
|
+ <div v-if="taskName == '分管审核' && !budgetForm.managerComment" class="alert alert-warning"
|
|
391
|
+ style="padding: 10px; border: 1px solid #f0ad4e; background-color: #fcf8e3; color: #8a6d3b;">
|
|
392
|
+ 请填写以下内容
|
|
393
|
+ </div>
|
|
394
|
+ <div :class="{ 'business-section': taskName == '分管审核' && !budgetForm.managerComment }">
|
|
395
|
+ <el-input :disabled="taskName != '分管审核'" type="textarea" placeholder="请输入审核意见"
|
|
396
|
+ v-model="budgetForm.managerComment" :autosize="{ minRows: 4 }"></el-input>
|
|
397
|
+ <div class="sign mt10" v-if="budgetForm.manager">
|
|
398
|
+ <div class="mr20">签名:<span class="auditor">{{ getUserName(budgetForm.manager) }}</span>
|
|
399
|
+ </div>
|
|
400
|
+ <div class="ml20"><span>审核时间:{{ budgetForm.managerTime }}</span></div>
|
|
401
|
+ </div>
|
|
402
|
+ </div>
|
|
403
|
+ </el-descriptions-item>
|
|
404
|
+ <el-descriptions-item label="总经理审核意见" :span="3">
|
|
405
|
+ <div v-if="taskName == '总经理审核'" class="alert alert-warning"
|
|
406
|
+ style="padding: 10px; border: 1px solid #f0ad4e; background-color: #fcf8e3; color: #8a6d3b;">
|
|
407
|
+ 请填写以下内容
|
|
408
|
+ </div>
|
|
409
|
+ <div :class="{ 'business-section': taskName == '总经理审核' }">
|
|
410
|
+ <el-input :disabled="taskName != '总经理审核'" type="textarea" placeholder="请输入审核意见"
|
|
411
|
+ v-model="budgetForm.zjlComment" :autosize="{ minRows: 4 }"></el-input>
|
|
412
|
+ <div class="sign mt10" v-if="budgetForm.auditor">
|
|
413
|
+ <div class="mr20">签名:<span class="auditor">{{ getUserName(budgetForm.auditor) }}</span>
|
|
414
|
+ </div>
|
|
415
|
+ <div class="ml20"><span>审核时间:{{ budgetForm.zjlTime }}</span></div>
|
|
416
|
+ </div>
|
|
417
|
+ </div>
|
232
|
418
|
</el-descriptions-item>
|
233
|
419
|
</el-descriptions>
|
|
420
|
+ <div class="text-center mt20 mb20">
|
|
421
|
+ <el-button type="danger" @click="returnOpen = true">退 回</el-button>
|
|
422
|
+ <el-button type="warning" @click="preserve()">保 存</el-button>
|
|
423
|
+ <el-button type="success" @click="confirmSucess()">提交下一个流程</el-button>
|
|
424
|
+ </div>
|
|
425
|
+ <el-dialog title="退回" :visible.sync="returnOpen" width="40%" append-to-body>
|
|
426
|
+ <return-btn :taskForm="taskForm" :comment="commentByRole()" @goBack="$emit('goBack')"
|
|
427
|
+ @cancel="returnOpen = false"></return-btn>
|
|
428
|
+ </el-dialog>
|
234
|
429
|
</div>
|
235
|
430
|
</template>
|
236
|
431
|
|
|
@@ -243,17 +438,23 @@ import { listBudgetStaff } from "@/api/oa/budget/budgetStaff";
|
243
|
438
|
import { listProjectWork } from "@/api/oa/project/projectWork";
|
244
|
439
|
import { listSite } from "@/api/oa/budget/budgetSite.js";
|
245
|
440
|
import { getProject } from "@/api/oa/project/project";
|
|
441
|
+import { getUsersManageLeader, getUserByPost } from "@/api/system/post";
|
|
442
|
+import { complete, getNextFlowNode } from "@/api/flowable/todo";
|
246
|
443
|
import InnerStaffCost from './components/InnerStaffCost.vue';
|
247
|
444
|
import OuterStaffCost from './components/OuterStaffCost.vue';
|
248
|
445
|
import CarCost from './components/CarCost.vue';
|
249
|
446
|
import DeviceCost from './components/DeviceCost.vue';
|
|
447
|
+import ReturnComment from '@/views/flowable/form/components/flowBtn/returnComment.vue';
|
|
448
|
+import ReturnBtn from '@/views/flowable/form/components/flowBtn/returnBtn.vue';
|
250
|
449
|
|
251
|
450
|
export default {
|
252
|
451
|
components: {
|
253
|
452
|
InnerStaffCost,
|
254
|
453
|
OuterStaffCost,
|
255
|
454
|
CarCost,
|
256
|
|
- DeviceCost
|
|
455
|
+ DeviceCost,
|
|
456
|
+ ReturnComment,
|
|
457
|
+ ReturnBtn
|
257
|
458
|
},
|
258
|
459
|
props: {
|
259
|
460
|
taskForm: {
|
|
@@ -276,6 +477,8 @@ export default {
|
276
|
477
|
carList: [],
|
277
|
478
|
deviceList: [],
|
278
|
479
|
siteList: [],
|
|
480
|
+ totalJYAmount: 0,
|
|
481
|
+ returnOpen: false,
|
279
|
482
|
}
|
280
|
483
|
},
|
281
|
484
|
created() {
|
|
@@ -288,22 +491,63 @@ export default {
|
288
|
491
|
listBudget({ pageNum: 1, pageSize: 20, projectId: this.taskForm.formId }).then(async res => {
|
289
|
492
|
this.budgetForm = res.rows[0];
|
290
|
493
|
if (this.budgetForm) {
|
|
494
|
+ this.budgetForm.outExpense = Number(this.budgetForm.outExpense).toFixed(2);
|
|
495
|
+ this.budgetForm.letterExpense = Number(this.budgetForm.letterExpense).toFixed(2);
|
|
496
|
+ this.budgetForm.winExpense = Number(this.budgetForm.winExpense).toFixed(2);
|
|
497
|
+ this.budgetForm.taxExpense = Number(this.budgetForm.taxExpense).toFixed(2);
|
|
498
|
+ this.budgetForm.travelExpense = Number(this.budgetForm.travelExpense).toFixed(2);
|
|
499
|
+ this.budgetForm.totalBudget = Number(this.budgetForm.totalBudget).toFixed(2);
|
|
500
|
+ this.totalJYAmount = Number(this.budgetForm.outExpense || 0) +
|
|
501
|
+ Number(this.budgetForm.letterExpense || 0) +
|
|
502
|
+ Number(this.budgetForm.winExpense || 0) +
|
|
503
|
+ Number(this.budgetForm.taxExpense || 0) +
|
|
504
|
+ Number(this.budgetForm.travelExpense || 0);
|
291
|
505
|
const budgetId = this.budgetForm.budgetId;
|
292
|
506
|
// 获取设备数据
|
293
|
507
|
let deviceRes = await listBudgetDevice({ pageSize: 100, budgetId });
|
294
|
508
|
this.deviceList = deviceRes.rows;
|
|
509
|
+ this.deviceList = this.deviceList.map(device => {
|
|
510
|
+ return {
|
|
511
|
+ ...device,
|
|
512
|
+ amount: Number(device.amount).toFixed(2),
|
|
513
|
+ };
|
|
514
|
+ });
|
295
|
515
|
|
296
|
516
|
// 获取车辆数据
|
297
|
517
|
let carRes = await listBudgetCar({ pageSize: 100, budgetId });
|
298
|
518
|
this.carList = carRes.rows;
|
|
519
|
+ this.carList = this.carList.map(car => {
|
|
520
|
+ return {
|
|
521
|
+ ...car,
|
|
522
|
+ amount: Number(car.amount).toFixed(2),
|
|
523
|
+ };
|
|
524
|
+ });
|
299
|
525
|
|
300
|
526
|
// 获取内业人员数据
|
301
|
527
|
let innerStaffRes = await listBudgetStaff({ pageSize: 100, budgetId, type: '内业' });
|
302
|
528
|
this.innerStaffList = innerStaffRes.rows;
|
|
529
|
+ this.innerStaffList = this.innerStaffList.map(staff => {
|
|
530
|
+ return {
|
|
531
|
+ ...staff,
|
|
532
|
+ dayCost: Number(staff.dayCost).toFixed(2),
|
|
533
|
+ performance: Number(staff.performance).toFixed(2),
|
|
534
|
+ amount: Number(staff.amount).toFixed(2),
|
|
535
|
+ staffCost: Number(staff.staffCost).toFixed(2)
|
|
536
|
+ };
|
|
537
|
+ });
|
303
|
538
|
|
304
|
539
|
// 获取外业人员数据
|
305
|
540
|
let outerStaffRes = await listBudgetStaff({ pageSize: 100, budgetId, type: '外业' });
|
306
|
541
|
this.outerStaffList = outerStaffRes.rows;
|
|
542
|
+ this.outerStaffList = this.outerStaffList.map(staff => {
|
|
543
|
+ return {
|
|
544
|
+ ...staff,
|
|
545
|
+ dayCost: Number(staff.dayCost).toFixed(2),
|
|
546
|
+ performance: Number(staff.performance).toFixed(2),
|
|
547
|
+ amount: Number(staff.amount).toFixed(2),
|
|
548
|
+ staffCost: Number(staff.staffCost).toFixed(2)
|
|
549
|
+ };
|
|
550
|
+ });
|
307
|
551
|
|
308
|
552
|
// 获取内业绩效额数据
|
309
|
553
|
let settleRes = await listBudgetSettle({ pageSize: 100, budgetId });
|
|
@@ -322,12 +566,17 @@ export default {
|
322
|
566
|
// 获取现场开支
|
323
|
567
|
let siteRes = await listSite({ pageSize: 100, budgetId });
|
324
|
568
|
this.siteList = siteRes.rows;
|
|
569
|
+ this.budgetForm.siteSum = this.siteList.reduce((sum, site) => sum + (Number(site.amount) || 0), 0);
|
325
|
570
|
}
|
326
|
571
|
this.loading = false;
|
327
|
572
|
}).catch(() => {
|
328
|
573
|
this.loading = false;
|
329
|
574
|
});
|
330
|
575
|
},
|
|
576
|
+ safeNumber(value) {
|
|
577
|
+ const num = Number(value);
|
|
578
|
+ return isNaN(num) ? 0 : num;
|
|
579
|
+ },
|
331
|
580
|
getProjectWorkList() {
|
332
|
581
|
getProject(this.taskForm.formId).then(res => {
|
333
|
582
|
this.project = res.data;
|
|
@@ -336,38 +585,109 @@ export default {
|
336
|
585
|
this.workContentList = res.rows;
|
337
|
586
|
})
|
338
|
587
|
},
|
339
|
|
- // 处理内业人员数据变化
|
340
|
|
- handleInnerStaffChange(newList) {
|
341
|
|
- this.innerStaffList = newList;
|
342
|
|
- console.log(newList)
|
343
|
|
- // 计算内业人员总成本
|
344
|
|
- const totalAmount = this.innerStaffList.reduce((sum, staff) => {
|
345
|
|
- return sum + (staff.amountAdjust || 0);
|
346
|
|
- }, 0);
|
347
|
|
-
|
348
|
|
- // 更新预算表单中的内业人员成本
|
349
|
|
- if (this.budgetForm) {
|
350
|
|
- this.budgetForm.innerStaffAmount = totalAmount;
|
351
|
|
- // 可以在这里调用API保存数据
|
352
|
|
- // updateBudget(this.budgetForm);
|
|
588
|
+ async preserve() {
|
|
589
|
+ if (this.taskName == '分管审核') {
|
|
590
|
+ this.budgetForm.manager = this.$store.getters.userId;
|
|
591
|
+ this.budgetForm.managerTime = this.parseTime(new Date(), '{y}-{m}-{d}');
|
|
592
|
+ } else if (this.taskName == '总经理审核') {
|
|
593
|
+ this.budgetForm.auditor = this.$store.getters.userId;
|
|
594
|
+ this.budgetForm.zjlTime = this.parseTime(new Date(), '{y}-{m}-{d}');
|
353
|
595
|
}
|
|
596
|
+ await updateBudget(this.budgetForm)
|
|
597
|
+ this.$message.success('保存成功');
|
354
|
598
|
},
|
355
|
|
-
|
356
|
|
- // 处理外业人员数据变化
|
357
|
|
- handleOuterStaffChange(newList) {
|
358
|
|
- this.outerStaffList = newList;
|
359
|
|
- // 计算外业人员总成本
|
360
|
|
- const totalAmount = this.outerStaffList.reduce((sum, staff) => {
|
361
|
|
- return sum + (staff.amountAdjust || 0);
|
362
|
|
- }, 0);
|
363
|
|
-
|
364
|
|
- // 更新预算表单中的外业人员成本
|
365
|
|
- if (this.budgetForm) {
|
366
|
|
- this.budgetForm.outerStaffAmount = totalAmount;
|
367
|
|
- // 可以在这里调用API保存数据
|
368
|
|
- // updateBudget(this.budgetForm);
|
|
599
|
+ confirmSucess() {
|
|
600
|
+ this.preserve();
|
|
601
|
+ this.$modal.confirm('是否提交到下一个流程?').then(async () => {
|
|
602
|
+ if (this.taskName == '经营审核') {
|
|
603
|
+ let managerLeaderRes = await getUsersManageLeader({ userId: this.budgetForm.compiler });
|
|
604
|
+ let managerLeader = managerLeaderRes.data;
|
|
605
|
+ let managerList = managerLeader.map(item => item.userId);
|
|
606
|
+ this.$set(this.taskForm.variables, 'approvalList', managerList);
|
|
607
|
+ }
|
|
608
|
+ else if (this.taskName == '分管审核') {
|
|
609
|
+ if (!this.budgetForm.managerComment) {
|
|
610
|
+ this.$message.error('请填写审核意见')
|
|
611
|
+ return
|
|
612
|
+ }
|
|
613
|
+ let zjlRes = await getUserByPost({ postName: '总经理' });
|
|
614
|
+ let zjlUserId = zjlRes.data.userId;
|
|
615
|
+ this.$set(this.taskForm.variables, 'approval', zjlUserId);
|
|
616
|
+ }
|
|
617
|
+ return
|
|
618
|
+ //提交到下一个流程
|
|
619
|
+ getNextFlowNode({ taskId: this.taskForm.taskId }).then(res => {
|
|
620
|
+ complete(this.taskForm).then(response => {
|
|
621
|
+ this.$modal.msgSuccess(response.msg);
|
|
622
|
+ this.$emit("goBack");
|
|
623
|
+ });
|
|
624
|
+ });
|
|
625
|
+ })
|
|
626
|
+ },
|
|
627
|
+ updateTotalJYAmount() {
|
|
628
|
+ this.totalJYAmount = Number(this.budgetForm.outExpense || 0) +
|
|
629
|
+ Number(this.budgetForm.letterExpense || 0) +
|
|
630
|
+ Number(this.budgetForm.winExpense || 0) +
|
|
631
|
+ Number(this.budgetForm.taxExpense || 0) +
|
|
632
|
+ Number(this.budgetForm.travelExpense || 0);
|
|
633
|
+ // Calculate total budget by adding all components
|
|
634
|
+ const innerStaffTotal = this.innerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
|
|
635
|
+ const outerStaffTotal = this.outerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
|
|
636
|
+ const carTotal = this.carList.reduce((sum, car) => sum + (Number(car.amount) || 0), 0);
|
|
637
|
+ const deviceTotal = this.deviceList.reduce((sum, device) => sum + (Number(device.amount) || 0), 0);
|
|
638
|
+ const siteTotal = this.siteList.reduce((sum, site) => sum + (Number(site.amount) || 0), 0);
|
|
639
|
+ this.budgetForm.totalBudget = (innerStaffTotal +
|
|
640
|
+ outerStaffTotal +
|
|
641
|
+ carTotal +
|
|
642
|
+ deviceTotal +
|
|
643
|
+ siteTotal +
|
|
644
|
+ this.totalJYAmount).toFixed(2);
|
|
645
|
+ },
|
|
646
|
+ commentByRole() {
|
|
647
|
+ if (this.taskName == '分管审核') {
|
|
648
|
+ return this.budgetForm.managerComment
|
|
649
|
+ } else if (this.taskName == '总经理审核') {
|
|
650
|
+ return this.budgetForm.zjlComment
|
|
651
|
+ } else if (this.taskName == '董事长批准') {
|
|
652
|
+ return this.budgetForm.dszComment
|
369
|
653
|
}
|
370
|
654
|
},
|
|
655
|
+ updateSettle(work, value, field) {
|
|
656
|
+ work[field] = value;
|
|
657
|
+ work.settle = (Number(work.workload) * Number(work.price) * Number(work.coefficient)).toFixed(2);
|
|
658
|
+ this.budgetForm.settleExpense = this.workList.reduce((sum, work) => {
|
|
659
|
+ return sum + (Number(work.settle) || 0);
|
|
660
|
+ }, 0);
|
|
661
|
+ this.updateTotalJYAmount();
|
|
662
|
+ },
|
|
663
|
+ updateInnerStaffAmount(staff, value, field) {
|
|
664
|
+ staff[field] = value;
|
|
665
|
+ staff.staffCost = (Number(staff.days) * Number(staff.dayCost)).toFixed(2);
|
|
666
|
+ staff.amount = (Number(staff.staffCost) + Number(staff.performance)).toFixed(2);
|
|
667
|
+ let innerStaffTotal = this.innerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
|
|
668
|
+ let outerStaffTotal = this.outerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
|
|
669
|
+ this.budgetForm.staffCost = (innerStaffTotal + outerStaffTotal).toFixed(2);
|
|
670
|
+ this.updateTotalJYAmount();
|
|
671
|
+ },
|
|
672
|
+ updateOuterStaffAmount(staff, value, field) {
|
|
673
|
+ staff[field] = value;
|
|
674
|
+ staff.performance = (200 * Number(staff.days) * Number(staff.coefficient)).toFixed(2);
|
|
675
|
+ staff.amount = (Number(staff.staffCost) + Number(staff.performance)).toFixed(2);
|
|
676
|
+ let innerStaffTotal = this.innerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
|
|
677
|
+ let outerStaffTotal = this.outerStaffList.reduce((sum, staff) => sum + (Number(staff.amount) || 0), 0);
|
|
678
|
+ this.budgetForm.staffCost = (innerStaffTotal + outerStaffTotal).toFixed(2);
|
|
679
|
+ this.updateTotalJYAmount();
|
|
680
|
+ },
|
|
681
|
+ updateCarAmount(car, value) {
|
|
682
|
+ car.days = value;
|
|
683
|
+ car.amount = (Number(car.car.dayCost) * Number(car.days)).toFixed(2);
|
|
684
|
+ this.updateTotalJYAmount();
|
|
685
|
+ },
|
|
686
|
+ updateDeviceAmount(device, value) {
|
|
687
|
+ device.days = value;
|
|
688
|
+ device.amount = (Number(device.device.dayCost) * Number(device.days)).toFixed(2);
|
|
689
|
+ this.updateTotalJYAmount();
|
|
690
|
+ },
|
371
|
691
|
},
|
372
|
692
|
}
|
373
|
693
|
</script>
|
|
@@ -390,7 +710,7 @@ export default {
|
390
|
710
|
|
391
|
711
|
.amount {
|
392
|
712
|
font-weight: bold;
|
393
|
|
- font-family:Arial, Helvetica, sans-serif;
|
|
713
|
+ font-family: Arial, Helvetica, sans-serif;
|
394
|
714
|
}
|
395
|
715
|
|
396
|
716
|
table {
|
|
@@ -405,11 +725,26 @@ table {
|
405
|
725
|
}
|
406
|
726
|
}
|
407
|
727
|
|
|
728
|
+.remark-cell {
|
|
729
|
+ text-align: left;
|
|
730
|
+}
|
|
731
|
+
|
408
|
732
|
.adjust {
|
409
|
733
|
color: #F56C6C;
|
410
|
734
|
width: 120px;
|
411
|
735
|
}
|
412
|
736
|
|
|
737
|
+.total-budget {
|
|
738
|
+ font-size: 1.5em;
|
|
739
|
+ font-weight: bold;
|
|
740
|
+ color: #4CAF50;
|
|
741
|
+ text-align: center;
|
|
742
|
+ padding: 10px;
|
|
743
|
+ border: 2px solid #4CAF50;
|
|
744
|
+ border-radius: 5px;
|
|
745
|
+ background-color: #f0f8f5;
|
|
746
|
+}
|
|
747
|
+
|
413
|
748
|
::v-deep .el-descriptions .is-bordered .el-descriptions-item__cell {
|
414
|
749
|
border: 1px solid #838894;
|
415
|
750
|
}
|
|
@@ -418,4 +753,45 @@ table {
|
418
|
753
|
color: #434141;
|
419
|
754
|
background: #eaeaea;
|
420
|
755
|
}
|
|
756
|
+
|
|
757
|
+.business-section {
|
|
758
|
+ border: 2px solid #E6A23C !important;
|
|
759
|
+ box-shadow: 0 0 10px rgba(64, 158, 255, 0.2);
|
|
760
|
+
|
|
761
|
+ tr {
|
|
762
|
+ background-color: #f0f7ff;
|
|
763
|
+
|
|
764
|
+ &:hover {
|
|
765
|
+ background-color: #e6f1ff;
|
|
766
|
+ }
|
|
767
|
+ }
|
|
768
|
+
|
|
769
|
+ .el-input-number {
|
|
770
|
+ .el-input__inner {
|
|
771
|
+ background-color: #fff;
|
|
772
|
+ border: 1px solid #E6A23C;
|
|
773
|
+
|
|
774
|
+ &:focus {
|
|
775
|
+ border-color: #e2af62;
|
|
776
|
+ box-shadow: 0 0 5px rgba(64, 158, 255, 0.3);
|
|
777
|
+ }
|
|
778
|
+ }
|
|
779
|
+ }
|
|
780
|
+
|
|
781
|
+ .head.amount {
|
|
782
|
+ background-color: #ecf5ff;
|
|
783
|
+ color: #E6A23C;
|
|
784
|
+ font-weight: bold;
|
|
785
|
+ }
|
|
786
|
+}
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+.sign {
|
|
790
|
+ display: flex;
|
|
791
|
+ justify-content: flex-end;
|
|
792
|
+ align-items: center;
|
|
793
|
+ padding-right: 80px;
|
|
794
|
+ line-height: 30px;
|
|
795
|
+ /* 如果需要垂直居中 */
|
|
796
|
+}
|
421
|
797
|
</style>
|