Browse Source

核算编制新增实际人员、车辆、设备栏;

借款跟预算现场开支挂钩
余思翰 3 months ago
parent
commit
3b832b6f97

+ 27
- 4
oa-ui/src/views/flowable/form/budget/adjust/adjustIndex.vue View File

2
  * @Author: ysh
2
  * @Author: ysh
3
  * @Date: 2025-05-14 16:09:56
3
  * @Date: 2025-05-14 16:09:56
4
  * @LastEditors: Please set LastEditors
4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-05-19 10:47:29
5
+ * @LastEditTime: 2025-05-20 17:13:53
6
 -->
6
 -->
7
 <template>
7
 <template>
8
   <div class="app-container">
8
   <div class="app-container">
31
         </el-form>
31
         </el-form>
32
         <el-table v-loading="loading" :data="budgetList">
32
         <el-table v-loading="loading" :data="budgetList">
33
           <el-table-column label="序号" align="center" type="index" width="60" />
33
           <el-table-column label="序号" align="center" type="index" width="60" />
34
+          <el-table-column label="状态" align="center" width="70">
35
+            <template slot-scope="scope">
36
+              <el-tag v-if="scope.row.disabled" type="warning">已核算</el-tag>
37
+            </template>
38
+          </el-table-column>
34
           <el-table-column label="项目编号" align="center" prop="project.projectNumber" />
39
           <el-table-column label="项目编号" align="center" prop="project.projectNumber" />
35
           <el-table-column label="项目名称" align="center" prop="project.projectName" />
40
           <el-table-column label="项目名称" align="center" prop="project.projectName" />
36
           <el-table-column label="预算总额" align="center" prop="totalBudget" />
41
           <el-table-column label="预算总额" align="center" prop="totalBudget" />
46
           </el-table-column>
51
           </el-table-column>
47
           <el-table-column label="操作" align="center" width="120">
52
           <el-table-column label="操作" align="center" width="120">
48
             <template slot-scope="scope">
53
             <template slot-scope="scope">
49
-              <el-button type="primary" size="mini" @click="handleSelect(scope.row)">选择</el-button>
54
+              <el-button type="primary" size="mini" @click="handleSelect(scope.row)"
55
+                :disabled="scope.row.disabled">选择</el-button>
50
             </template>
56
             </template>
51
           </el-table-column>
57
           </el-table-column>
52
         </el-table>
58
         </el-table>
94
         pageNum: 1,
100
         pageNum: 1,
95
         pageSize: 20,
101
         pageSize: 20,
96
         projectNumber: undefined,
102
         projectNumber: undefined,
97
-        projectName: undefined
103
+        projectName: undefined,
104
+        auditor: 7
98
       },
105
       },
99
       queryType: '1',
106
       queryType: '1',
100
       projectList: [],
107
       projectList: [],
120
     getBudgetList() {
127
     getBudgetList() {
121
       listBudget(this.queryParams).then(res => {
128
       listBudget(this.queryParams).then(res => {
122
         this.budgetList = res.rows;
129
         this.budgetList = res.rows;
130
+        for (let b of this.budgetList) {
131
+          this.isDisabled(b).then(res => {
132
+            if (res) {
133
+              this.$set(b, 'disabled', true);
134
+            } else {
135
+              this.$set(b, 'disabled', false);
136
+            }
137
+          })
138
+        }
123
         this.total = res.total;
139
         this.total = res.total;
124
         this.loading = false;
140
         this.loading = false;
125
       });
141
       });
127
     handleSelect(row) {
143
     handleSelect(row) {
128
       this.projectId = row.projectId;
144
       this.projectId = row.projectId;
129
       this.selectedRows = row;
145
       this.selectedRows = row;
130
-      console.log(row);
146
+    },
147
+    async isDisabled(row) {
148
+      let res = await listCheck({ budgetId: row.budgetId })
149
+      if (res.total > 0) {
150
+        return true;
151
+      } else {
152
+        return false;
153
+      }
131
     },
154
     },
132
     handleBack() {
155
     handleBack() {
133
       this.projectId = '';
156
       this.projectId = '';

+ 87
- 18
oa-ui/src/views/flowable/form/budget/adjust/budgetAdjust.vue View File

2
  * @Author: ysh
2
  * @Author: ysh
3
  * @Date: 2025-05-07 11:01:39
3
  * @Date: 2025-05-07 11:01:39
4
  * @LastEditors: Please set LastEditors
4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-05-19 17:49:04
5
+ * @LastEditTime: 2025-05-20 17:08:40
6
 -->
6
 -->
7
 <template>
7
 <template>
8
   <div class="main" v-loading="loading">
8
   <div class="main" v-loading="loading">
117
           </tr>
117
           </tr>
118
         </table>
118
         </table>
119
       </el-descriptions-item>
119
       </el-descriptions-item>
120
-      <el-descriptions-item label="内业人员成本" :span="3" v-if="innerStaffList.length > 0">
120
+      <el-descriptions-item label="实际参与人员" :span="3" v-if="taskName == '核算编制'">
121
+        <span v-for="participant in actualInfo.participateList" :key="participant">
122
+          <el-tag type="primary" effect="plain" style="margin-right: 10px;">{{ participant }}</el-tag>
123
+        </span>
124
+      </el-descriptions-item>
125
+      <el-descriptions-item label="内业人员成本" :span="3" v-if="taskName == '核算编制' || innerStaffList.length > 0">
121
         <inner-staff-cost :staffList.sync="innerStaffList" :settleExpense="budgetForm.settleExpense"
126
         <inner-staff-cost :staffList.sync="innerStaffList" :settleExpense="budgetForm.settleExpense"
122
           :settleAdjust="budgetForm.settleAdjust" :taskName="taskName"
127
           :settleAdjust="budgetForm.settleAdjust" :taskName="taskName"
123
           @update:staffList="handleInnerStaffChange"></inner-staff-cost>
128
           @update:staffList="handleInnerStaffChange"></inner-staff-cost>
124
       </el-descriptions-item>
129
       </el-descriptions-item>
125
-      <el-descriptions-item label="外业人员成本" :span="3" v-if="outerStaffList.length > 0">
130
+      <el-descriptions-item label="外业人员成本" :span="3" v-if="taskName == '核算编制' || outerStaffList.length > 0">
126
         <outer-staff-cost :staffList.sync="outerStaffList" :taskName="taskName"
131
         <outer-staff-cost :staffList.sync="outerStaffList" :taskName="taskName"
127
           @update:staffList="handleOuterStaffChange"></outer-staff-cost>
132
           @update:staffList="handleOuterStaffChange"></outer-staff-cost>
128
       </el-descriptions-item>
133
       </el-descriptions-item>
129
-      <el-descriptions-item label="车辆成本" :span="3" v-if="carList.length > 0">
134
+      <el-descriptions-item label="实际使用车辆" :span="3" v-if="taskName == '核算编制'">
135
+        <span v-for="car in actualInfo.carList" :key="car.id">
136
+          <el-tag :type="car.isExist ? 'primary' : 'warning'" effect="plain" style="margin-right: 10px;">{{
137
+            car.licensePlate }} - {{ car.series
138
+            }}</el-tag>
139
+        </span>
140
+      </el-descriptions-item>
141
+      <el-descriptions-item label="车辆成本" :span="3" v-if="taskName == '核算编制' || carList.length > 0">
130
         <car-cost :carList.sync="carList" :taskName="taskName" @update:carList="handleCarChange"></car-cost>
142
         <car-cost :carList.sync="carList" :taskName="taskName" @update:carList="handleCarChange"></car-cost>
131
       </el-descriptions-item>
143
       </el-descriptions-item>
132
-      <el-descriptions-item label="设备成本" :span="3" v-if="deviceList.length > 0">
144
+      <el-descriptions-item label="实际使用设备" :span="3" v-if="taskName == '核算编制'">
145
+        <span v-for="device in actualInfo.deviceList" :key="device.id">
146
+          <el-tag :type="device.isExist ? 'primary' : 'warning'" style="margin-right: 10px;margin-bottom: 10px;"
147
+            effect="plain">
148
+            {{ device.name + '【' + (device.brand != null ? device.brand : '') + (device.series != null ? '-' +
149
+              device.series + '】' : '')
150
+              + (device.code != null ? '(出厂编号:' + device.code + ')' : '') }}
151
+          </el-tag>
152
+        </span>
153
+      </el-descriptions-item>
154
+      <el-descriptions-item label="设备成本" :span="3" v-if="taskName == '核算编制' || deviceList.length > 0">
133
         <device-cost :deviceList.sync="deviceList" :taskName="taskName"
155
         <device-cost :deviceList.sync="deviceList" :taskName="taskName"
134
           @update:deviceList="handleDeviceChange"></device-cost>
156
           @update:deviceList="handleDeviceChange"></device-cost>
135
       </el-descriptions-item>
157
       </el-descriptions-item>
145
       </el-descriptions-item>
167
       </el-descriptions-item>
146
       <el-descriptions-item label="统计" :span="3">
168
       <el-descriptions-item label="统计" :span="3">
147
         <table border="1" style="width:100%;" class="budget-summary">
169
         <table border="1" style="width:100%;" class="budget-summary">
148
-          <tr class="header">
170
+          <tr class="header" style="background-color:#f8f8f9">
149
             <td><b>名称</b></td>
171
             <td><b>名称</b></td>
150
             <td><b>预算金额</b></td>
172
             <td><b>预算金额</b></td>
151
             <td><b>核算金额</b></td>
173
             <td><b>核算金额</b></td>
192
             <td style="text-align:right;">{{ isNaN(checkOtherCost) ? 0 : Number(checkOtherCost).toFixed(2) }}</td>
214
             <td style="text-align:right;">{{ isNaN(checkOtherCost) ? 0 : Number(checkOtherCost).toFixed(2) }}</td>
193
             <td style="text-align:right;">{{ (Number(checkOtherCost) - 0).toFixed(2) }}</td>
215
             <td style="text-align:right;">{{ (Number(checkOtherCost) - 0).toFixed(2) }}</td>
194
           </tr>
216
           </tr>
195
-          <tr class="total-budget">
217
+          <tr class="total-budget" style="background-color: #ffeb3b; font-weight: bold;">
196
             <td><b>总计</b></td>
218
             <td><b>总计</b></td>
197
             <td style="text-align:right;"><b>{{ isNaN(budgetForm.totalBudget) ? 0 : budgetForm.totalBudget }}</b></td>
219
             <td style="text-align:right;"><b>{{ isNaN(budgetForm.totalBudget) ? 0 : budgetForm.totalBudget }}</b></td>
198
             <td style="text-align:right;"><b>{{ isNaN(totalBudgetAdjust) ? 0 : totalBudgetAdjust }}</b></td>
220
             <td style="text-align:right;"><b>{{ isNaN(totalBudgetAdjust) ? 0 : totalBudgetAdjust }}</b></td>
293
 </template>
315
 </template>
294
 
316
 
295
 <script>
317
 <script>
296
-import { listCheck, getCheck, delCheck, addCheck, updateCheck } from "@/api/oa/budget/check";
318
+import { getCheck, addCheck, updateCheck } from "@/api/oa/budget/check";
297
 import { listBudget, updateBudget } from "@/api/oa/budget/budget";
319
 import { listBudget, updateBudget } from "@/api/oa/budget/budget";
298
-import { listBudgetCar, updateBudgetCar, addBudgetCar, delBudgetCar } from "@/api/oa/budget/budgetCar";
299
-import { listBudgetDevice, updateBudgetDevice, addBudgetDevice, delBudgetDevice } from "@/api/oa/budget/budgetDevice";
300
-import { listBudgetSettle, updateBudgetSettle, addBudgetSettle, delBudgetSettle } from "@/api/oa/budget/budgetSettle";
320
+import { listBudgetCar, addBudgetCar, delBudgetCar } from "@/api/oa/budget/budgetCar";
321
+import { listBudgetDevice, addBudgetDevice, delBudgetDevice } from "@/api/oa/budget/budgetDevice";
322
+import { listBudgetSettle } from "@/api/oa/budget/budgetSettle";
301
 import { listBudgetStaff, addBudgetStaff, delBudgetStaff } from "@/api/oa/budget/budgetStaff";
323
 import { listBudgetStaff, addBudgetStaff, delBudgetStaff } from "@/api/oa/budget/budgetStaff";
302
-import { listOther, addOther, updateOther, delOther } from "@/api/oa/budget/budgetOther";
324
+import { listOther, addOther, delOther } from "@/api/oa/budget/budgetOther";
303
 import { listProjectWork } from "@/api/oa/project/projectWork";
325
 import { listProjectWork } from "@/api/oa/project/projectWork";
304
-import { listSite, updateSite, delSite, addSite } from "@/api/oa/budget/budgetSite";
326
+import { listSite, updateSite } from "@/api/oa/budget/budgetSite";
305
 import { getProject } from "@/api/oa/project/project";
327
 import { getProject } from "@/api/oa/project/project";
328
+import { getCar } from "@/api/oa/car/car";
329
+import { getDevice } from "@/api/oa/device/device";
306
 import { complete, getNextFlowNode } from "@/api/flowable/todo";
330
 import { complete, getNextFlowNode } from "@/api/flowable/todo";
307
-import { getUsersManageLeader, getUserByPost, getUsersDeptLeader, getUsersDeptLeaderByDept, getUsersViceDeptLeaderByDept } from "@/api/system/post";
331
+import { getUsersManageLeader, getUserByPost, getUsersViceDeptLeaderByDept } from "@/api/system/post";
308
 import InnerStaffCost from './components/InnerStaffCost.vue';
332
 import InnerStaffCost from './components/InnerStaffCost.vue';
309
 import OuterStaffCost from './components/OuterStaffCost.vue';
333
 import OuterStaffCost from './components/OuterStaffCost.vue';
310
 import CarCost from './components/CarCost.vue';
334
 import CarCost from './components/CarCost.vue';
348
           this.row.projectId = res.data.projectId;
372
           this.row.projectId = res.data.projectId;
349
           this.initBudgetForm();
373
           this.initBudgetForm();
350
           this.initCheckForm();
374
           this.initCheckForm();
351
-          this.getProjectWorkList();
375
+          // this.getProjectWorkList();
352
         });
376
         });
353
       } else {
377
       } else {
354
         this.initBudgetForm();
378
         this.initBudgetForm();
355
         this.initCheckForm();
379
         this.initCheckForm();
356
-        this.getProjectWorkList();
380
+        // this.getProjectWorkList();
357
       }
381
       }
358
 
382
 
359
     }
383
     }
383
       checkOtherCost: 0,
407
       checkOtherCost: 0,
384
       checkJYAmount: 0,
408
       checkJYAmount: 0,
385
       totalBudgetAdjust: 0,
409
       totalBudgetAdjust: 0,
410
+      actualInfo: {
411
+        deviceList: [],
412
+        carList: [],
413
+        participateList: []
414
+      }
386
     }
415
     }
387
   },
416
   },
388
   async created() {
417
   async created() {
392
     }
421
     }
393
     this.initBudgetForm();
422
     this.initBudgetForm();
394
     this.initCheckForm();
423
     this.initCheckForm();
395
-    this.getProjectWorkList();
396
   },
424
   },
397
   methods: {
425
   methods: {
398
     initBudgetForm() {
426
     initBudgetForm() {
450
               amountAdjust: car.amountAdjust ? Number(car.amountAdjust).toFixed(2) : 0
478
               amountAdjust: car.amountAdjust ? Number(car.amountAdjust).toFixed(2) : 0
451
             };
479
             };
452
           });
480
           });
453
-          this.checkCarCost = this.carList.reduce((sum, car) => sum + (Number(car.amountAdjust) || 0).toFixed(2), 0);
481
+          this.checkCarCost = this.carList.reduce((sum, car) => sum + Number(car.amountAdjust || 0), 0).toFixed(2);
454
 
482
 
455
           // 获取内业人员数据
483
           // 获取内业人员数据
456
           let innerStaffRes = await listBudgetStaff({ pageSize: 100, budgetId, type: '内业' });
484
           let innerStaffRes = await listBudgetStaff({ pageSize: 100, budgetId, type: '内业' });
550
           this.checkOtherCost = this.otherList.reduce((sum, other) => sum + Number(other.amountAdjust || 0), 0).toFixed(2);
578
           this.checkOtherCost = this.otherList.reduce((sum, other) => sum + Number(other.amountAdjust || 0), 0).toFixed(2);
551
           this.totalBudgetAdjust = (Number(this.checkStaffCost) + Number(this.checkCarCost) + Number(this.checkDeviceCost)
579
           this.totalBudgetAdjust = (Number(this.checkStaffCost) + Number(this.checkCarCost) + Number(this.checkDeviceCost)
552
             + Number(this.checkSiteCost) + Number(this.checkJYAmount) + Number(this.checkOtherCost)).toFixed(2);
580
             + Number(this.checkSiteCost) + Number(this.checkJYAmount) + Number(this.checkOtherCost)).toFixed(2);
581
+
582
+          this.getProjectWorkList();
553
         }
583
         }
554
         this.loading = false;
584
         this.loading = false;
555
       }).catch(() => {
585
       }).catch(() => {
576
         }
606
         }
577
       })
607
       })
578
     },
608
     },
609
+    async initActualInfo(project) {
610
+      let deviceIds = project.devices.split(',');
611
+      let carIds = project.cars.split(',');
612
+      let participateIds = project.participates.split(',');
613
+      let actualDeviceList = [];
614
+      let actualCarList = [];
615
+      let actualParticipateList = [];
616
+      actualDeviceList = await Promise.all(deviceIds.map(async deviceId => {
617
+        const res = await getDevice(deviceId);
618
+        return res.data;
619
+      }));
620
+
621
+      actualCarList = await Promise.all(carIds.map(async carId => {
622
+        const res = await getCar(carId);
623
+        return res.data;
624
+      }));
625
+
626
+      actualParticipateList = participateIds.map(participateId => this.getUserName(Number(participateId)));
627
+      actualDeviceList = actualDeviceList.map(actualDevice => {
628
+        const isExist = this.deviceList.some(device => device.deviceId === actualDevice.deviceId);
629
+        return {
630
+          ...actualDevice,
631
+          isExist: isExist
632
+        };
633
+      });
634
+      actualCarList = actualCarList.map(actualCar => {
635
+        const isExist = this.carList.some(car => car.carId === actualCar.carId);
636
+        return {
637
+          ...actualCar,
638
+          isExist: isExist
639
+        };
640
+      });
641
+      this.actualInfo = {
642
+        deviceList: actualDeviceList,
643
+        carList: actualCarList,
644
+        participateList: actualParticipateList
645
+      }
646
+    },
579
     getProjectWorkList() {
647
     getProjectWorkList() {
580
       getProject(this.row.projectId).then(res => {
648
       getProject(this.row.projectId).then(res => {
581
         this.project = res.data;
649
         this.project = res.data;
650
+        this.initActualInfo(this.project);
582
       })
651
       })
583
       listProjectWork({ pageSize: 999, projectId: this.row.projectId }).then(res => {
652
       listProjectWork({ pageSize: 999, projectId: this.row.projectId }).then(res => {
584
         this.workContentList = res.rows;
653
         this.workContentList = res.rows;

+ 4
- 2
oa-ui/src/views/flowable/form/budget/adjust/components/CarCost.vue View File

2
  * @Author: ysh
2
  * @Author: ysh
3
  * @Date: 2025-05-08 14:18:15
3
  * @Date: 2025-05-08 14:18:15
4
  * @LastEditors: Please set LastEditors
4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-05-19 16:25:04
5
+ * @LastEditTime: 2025-05-20 16:47:13
6
 -->
6
 -->
7
 <template>
7
 <template>
8
   <div class="car-cost">
8
   <div class="car-cost">
11
         <td></td>
11
         <td></td>
12
         <td>序号</td>
12
         <td>序号</td>
13
         <td>车牌号</td>
13
         <td>车牌号</td>
14
+        <td>品牌</td>
14
         <td>折旧成本(天)</td>
15
         <td>折旧成本(天)</td>
15
         <td>预算天数</td>
16
         <td>预算天数</td>
16
         <td>金额</td>
17
         <td>金额</td>
25
         </td>
26
         </td>
26
         <td>{{ index + 1 }}</td>
27
         <td>{{ index + 1 }}</td>
27
         <td>{{ car.car ? car.car.licensePlate : '' }}</td>
28
         <td>{{ car.car ? car.car.licensePlate : '' }}</td>
29
+        <td>{{ car.car ? car.car.brand : '' }}</td>
28
         <td style="text-align:right;">{{ car.car ? car.car.dayCost : '' }}</td>
30
         <td style="text-align:right;">{{ car.car ? car.car.dayCost : '' }}</td>
29
         <td style="text-align:right;">{{ car.days }}</td>
31
         <td style="text-align:right;">{{ car.days }}</td>
30
         <td style="text-align:right;">{{ car.amount }}</td>
32
         <td style="text-align:right;">{{ car.amount }}</td>
40
         </td>
42
         </td>
41
       </tr>
43
       </tr>
42
       <tr>
44
       <tr>
43
-        <td colspan="3" class="amount">车辆成本合计</td>
45
+        <td colspan="4" class="amount">车辆成本合计</td>
44
         <td class="amount" style="text-align:right;">{{carList.reduce((sum, car) => sum +
46
         <td class="amount" style="text-align:right;">{{carList.reduce((sum, car) => sum +
45
           (Number(car.depreciation) || 0), 0).toFixed(2)}}</td>
47
           (Number(car.depreciation) || 0), 0).toFixed(2)}}</td>
46
         <td class="amount" style="text-align:right;">{{carList.reduce((sum, car) => sum +
48
         <td class="amount" style="text-align:right;">{{carList.reduce((sum, car) => sum +

+ 12
- 11
oa-ui/src/views/flowable/form/budget/siteExpenses.vue View File

60
 </template>
60
 </template>
61
 
61
 
62
 <script>
62
 <script>
63
-import { listData, getData, delData, addData, updateData } from "@/api/system/dict/data";
64
-import { listSite, getSite, delSite, addSite, updateSite } from "@/api/oa/budget/budgetSite.js";
63
+import { addData, getDicts } from "@/api/system/dict/data";
64
+import { listSite, delSite } from "@/api/oa/budget/budgetSite.js";
65
 export default {
65
 export default {
66
   dicts: ['cmc_borrow_expense', 'cmc_unit'],
66
   dicts: ['cmc_borrow_expense', 'cmc_unit'],
67
   props: {
67
   props: {
180
             this.open = false;
180
             this.open = false;
181
             this.newExpenseForm.name = '';
181
             this.newExpenseForm.name = '';
182
             // 刷新字典数据
182
             // 刷新字典数据
183
-            this.getDicts("cmc_borrow_expense").then(response => {
184
-              console.log(response.data);
185
-              // 更新字典数据
186
-              this.dict.type.cmc_borrow_expense = response.data;
187
-              // 重新加载字典数据后,更新当前选中项
188
-              if (this.expensesList.length > 0) {
189
-                const lastItem = this.expensesList[this.expensesList.length - 1];
190
-                lastItem.name = this.newExpenseForm.dictValue;
183
+            getDicts("cmc_borrow_expense").then(res => {
184
+              let arr = [];
185
+              for (let i = 0; i < res.data.length; i++) {
186
+                arr.push({
187
+                  label: res.data[i].dictLabel,
188
+                  value: res.data[i].dictValue,
189
+                  raw: res.data[i]
190
+                })
191
               }
191
               }
192
-            });
192
+              this.dict.type.cmc_borrow_expense = arr;
193
+            })
193
           });
194
           });
194
         }
195
         }
195
       })
196
       })

+ 87
- 27
oa-ui/src/views/flowable/form/finance/borrowForm.vue View File

80
                 {{ index + 1 }}
80
                 {{ index + 1 }}
81
               </td>
81
               </td>
82
               <td>
82
               <td>
83
-                <!-- <el-input v-model="detail.borrowItem" type="textarea" :disabled="taskName != '借款申请'"></el-input> -->
84
-                <el-autocomplete v-model="detail.borrowItem" :fetch-suggestions="querySearchAsync" placeholder="请输入内容"
85
-                  :disabled="taskName != '借款申请'"></el-autocomplete>
83
+                <!-- <el-autocomplete v-model="detail.borrowItem" :fetch-suggestions="querySearchAsync" placeholder="请输入内容"
84
+                  :disabled="taskName != '借款申请'"></el-autocomplete> -->
85
+                <el-select v-model="detail.borrowItem" placeholder="请选择开支项" clearable @change="handleExpenseChange"
86
+                  style="width: 100%;" :disabled="taskName != '借款申请'">
87
+                  <el-option v-for="dict in dict.type.cmc_borrow_expense" clearable :key="dict.value"
88
+                    :label="dict.label" :value="dict.value" />
89
+                  <el-option label="+新增更多开支项..." value="new_expense" />
90
+                </el-select>
86
               </td>
91
               </td>
87
               <td>
92
               <td>
88
                 <el-input v-model="detail.unit" :disabled="taskName != '借款申请'"></el-input>
93
                 <el-input v-model="detail.unit" :disabled="taskName != '借款申请'"></el-input>
98
               <td>
103
               <td>
99
                 <el-input v-model="detail.applyAmount" :disabled="taskName != '借款申请'"></el-input>
104
                 <el-input v-model="detail.applyAmount" :disabled="taskName != '借款申请'"></el-input>
100
               </td>
105
               </td>
101
-              <!-- <td v-if="form.borrowUsage == 0 || form.borrowUsage == 1">
102
-                  <el-input v-model="detail.xmAmount" :disabled="taskName != '项目部审核'"
103
-                    @change="calculateXmAmount(detail)"></el-input>
104
-                </td> -->
105
               <td v-if="form.borrowUsage == 0 || form.borrowUsage == 1">
106
               <td v-if="form.borrowUsage == 0 || form.borrowUsage == 1">
106
                 <el-input v-model="detail.managerAmount" :disabled="taskName != '分管审核'"
107
                 <el-input v-model="detail.managerAmount" :disabled="taskName != '分管审核'"
107
                   @blur="calculateManagerAmount(detail)"></el-input>
108
                   @blur="calculateManagerAmount(detail)"></el-input>
117
 
118
 
118
           <el-form-item label="最大借款金额" v-if="isSelect">
119
           <el-form-item label="最大借款金额" v-if="isSelect">
119
             <el-tag>
120
             <el-tag>
120
-              <span class="low-money">{{ totalBudget.toFixed(2) }}</span>
121
-              <span class="up-money">(大写:{{ formatNumberWithWan(totalBudget) }})</span>
121
+              <span class="low-money">{{ siteExpenses.toFixed(2) }}</span>
122
+              <span class="up-money">(大写:{{ formatNumberWithWan(siteExpenses) }})</span>
122
             </el-tag>
123
             </el-tag>
123
           </el-form-item>
124
           </el-form-item>
124
           <el-form-item label="已申请借款" v-if="isSelect">
125
           <el-form-item label="已申请借款" v-if="isSelect">
129
           </el-form-item>
130
           </el-form-item>
130
           <el-form-item label="可用借款" v-if="isSelect">
131
           <el-form-item label="可用借款" v-if="isSelect">
131
             <el-tag type="success">
132
             <el-tag type="success">
132
-              <span class="low-money">{{ (totalBudget - hasBorrow).toFixed(2) }}</span>
133
-              <span class="up-money">(大写:{{ formatNumberWithWan((totalBudget - hasBorrow)) }})</span>
133
+              <span class="low-money">{{ (siteExpenses - hasBorrow).toFixed(2) }}</span>
134
+              <span class="up-money">(大写:{{ formatNumberWithWan((siteExpenses - hasBorrow)) }})</span>
134
             </el-tag>
135
             </el-tag>
135
           </el-form-item>
136
           </el-form-item>
136
 
137
 
320
       <return-btn :taskForm="taskForm" :comment="commentByRole()" @goBack="$emit('goBack')" @saves=""
321
       <return-btn :taskForm="taskForm" :comment="commentByRole()" @goBack="$emit('goBack')" @saves=""
321
         @cancel="returnOpen = false"></return-btn>
322
         @cancel="returnOpen = false"></return-btn>
322
     </el-dialog>
323
     </el-dialog>
324
+    <el-dialog title="新增开支项" :visible.sync="openNewExpense" width="400px" append-to-body>
325
+      <el-form ref="newExpenseForm" :model="newExpenseForm" :rules="newExpenseRules" label-width="120px">
326
+        <el-form-item label="开支项名称" prop="name">
327
+          <el-input v-model="newExpenseForm.name" placeholder="请输入开支项名称" />
328
+        </el-form-item>
329
+      </el-form>
330
+      <div slot="footer" class="dialog-footer">
331
+        <el-button type="primary" @click="submitNewExpense">确 定</el-button>
332
+        <el-button @click="openNewExpense = false">取 消</el-button>
333
+      </div>
334
+    </el-dialog>
323
     <el-button type="success" @click="printOpen = true">打印</el-button>
335
     <el-button type="success" @click="printOpen = true">打印</el-button>
324
   </div>
336
   </div>
325
 </template>
337
 </template>
330
 import { listBorrow, getBorrow, delBorrow, addBorrow, updateBorrow } from "@/api/oa/borrow/borrow";
342
 import { listBorrow, getBorrow, delBorrow, addBorrow, updateBorrow } from "@/api/oa/borrow/borrow";
331
 import { listBorrowDetail, addBorrowDetail, updateBorrowDetail, delBorrowDetail } from "@/api/oa/borrow/borrowDetail";
343
 import { listBorrowDetail, addBorrowDetail, updateBorrowDetail, delBorrowDetail } from "@/api/oa/borrow/borrowDetail";
332
 import { listProject, getProject } from "@/api/oa/project/project";
344
 import { listProject, getProject } from "@/api/oa/project/project";
345
+import { addData, getDicts } from "@/api/system/dict/data";
346
+import { listSite, delSite } from "@/api/oa/budget/budgetSite.js";
333
 import { getUserByPost } from "@/api/system/post";
347
 import { getUserByPost } from "@/api/system/post";
334
 import flow from '@/views/flowable/task/todo/detail/flow'
348
 import flow from '@/views/flowable/task/todo/detail/flow'
335
 import { flowXmlAndNode } from "@/api/flowable/definition";
349
 import { flowXmlAndNode } from "@/api/flowable/definition";
343
 import ReturnBtn from '@/views/flowable/form/components/flowBtn/returnBtn.vue';
357
 import ReturnBtn from '@/views/flowable/form/components/flowBtn/returnBtn.vue';
344
 
358
 
345
 export default {
359
 export default {
360
+  dicts: ['cmc_borrow_expense', 'cmc_unit'],
346
   components: {
361
   components: {
347
     flow,
362
     flow,
348
     projectChoose,
363
     projectChoose,
425
       exceed: false, //是否超预算
440
       exceed: false, //是否超预算
426
       deptId: undefined,
441
       deptId: undefined,
427
       dgtLabel: '工会审核意见',
442
       dgtLabel: '工会审核意见',
428
-      totalBudget: 0,
443
+      siteExpenses: 0,
429
       hasBorrow: 0,
444
       hasBorrow: 0,
430
       printOpen: false,
445
       printOpen: false,
431
       showAlter: true,
446
       showAlter: true,
432
       returnOpen: false,
447
       returnOpen: false,
433
-      borrowItemList: []
448
+      borrowItemList: [],
449
+      openNewExpense: false,
450
+      newExpenseForm: {
451
+        name: ''
452
+      },
453
+      newExpenseRules: {
454
+        name: [
455
+          { required: true, message: '请输入开支项名称', trigger: 'blur' }
456
+        ]
457
+      }
434
     };
458
     };
435
   },
459
   },
436
   created() {
460
   created() {
566
       let budgetData = await listBudget({ projectId: this.form.projectId })
590
       let budgetData = await listBudget({ projectId: this.form.projectId })
567
       if (budgetData.total == 1) {
591
       if (budgetData.total == 1) {
568
         let budget = budgetData.rows[0];
592
         let budget = budgetData.rows[0];
569
-        this.totalBudget = Number(budget.settleExpense) + Number(budget.otherExpense) +  Number(budget.rentExpense)
593
+        let siteRes = await listSite({ budgetId: budget.budgetId });
594
+        let maxExpense = siteRes.rows.reduce((sum, site) => sum + (Number(site.amount) || 0), 0);
595
+        this.siteExpenses = maxExpense
570
       }
596
       }
571
       if (budgetData.total == 0) {
597
       if (budgetData.total == 0) {
572
-        this.totalBudget = 0
573
-      }
574
-      if (this.form.borrowUsage == '0') {
575
-        if ((this.totalBudget - this.form.applyAmount) < 0) {
576
-          this.exceed = true;
577
-        } else {
578
-          this.exceed = false;
579
-        }
580
-      } else {
581
-        this.exceed = false;
598
+        this.siteExpenses = 0
582
       }
599
       }
583
       let borrow = await listBorrow({ projectId: this.form.projectId })
600
       let borrow = await listBorrow({ projectId: this.form.projectId })
584
       if (borrow.total != 0) {
601
       if (borrow.total != 0) {
595
         });
612
         });
596
         this.hasBorrow = hasBorrow
613
         this.hasBorrow = hasBorrow
597
       }
614
       }
615
+      if (this.form.borrowUsage == '0') {
616
+        if ((this.siteExpenses - this.hasBorrow - this.form.applyAmount) < 0) {
617
+          this.exceed = true;
618
+        } else {
619
+          this.exceed = false;
620
+        }
621
+      } else {
622
+        this.exceed = false;
623
+      }
598
     },
624
     },
599
     // 查询项目列表
625
     // 查询项目列表
600
     getProjectList() {
626
     getProjectList() {
933
     // 验证金额
959
     // 验证金额
934
     VerificationAmount() {
960
     VerificationAmount() {
935
       if (this.isSelect) {
961
       if (this.isSelect) {
936
-        if (this.form.applyAmount > (this.totalBudget - this.hasBorrow)) {
962
+        if (this.form.applyAmount > (this.siteExpenses - this.hasBorrow)) {
937
           return this.$confirm('借款总额已经超过项目预算,将走《超预算或预算外支付(报销)》流程', '提示', {
963
           return this.$confirm('借款总额已经超过项目预算,将走《超预算或预算外支付(报销)》流程', '提示', {
938
             confirmButtonText: '确定',
964
             confirmButtonText: '确定',
939
             type: 'warning'
965
             type: 'warning'
955
     getMoreAmount(type) {
981
     getMoreAmount(type) {
956
       let result;
982
       let result;
957
       if (type == '0') {
983
       if (type == '0') {
958
-        result = this.form.applyAmount - (this.totalBudget - this.hasBorrow);
984
+        result = this.form.applyAmount - (this.siteExpenses - this.hasBorrow);
959
       } else {
985
       } else {
960
-        result = this.form.managerAmount - (this.totalBudget - this.hasBorrow);
986
+        result = this.form.managerAmount - (this.siteExpenses - this.hasBorrow);
961
       }
987
       }
962
       return result.toFixed(2)
988
       return result.toFixed(2)
963
     },
989
     },
988
       return (borrowItem) => {
1014
       return (borrowItem) => {
989
         return (borrowItem.value.indexOf(queryString) === 0);
1015
         return (borrowItem.value.indexOf(queryString) === 0);
990
       };
1016
       };
1017
+    },
1018
+    handleExpenseChange(value) {
1019
+      if (value === 'new_expense') {
1020
+        this.openNewExpense = true;
1021
+      }
1022
+    },
1023
+    submitNewExpense() {
1024
+      this.$refs["newExpenseForm"].validate(valid => {
1025
+        if (valid) {
1026
+          let length = this.dict.type.cmc_borrow_expense.length;
1027
+          this.newExpenseForm.dictType = 'cmc_borrow_expense';
1028
+          this.newExpenseForm.dictLabel = this.newExpenseForm.name;
1029
+          this.newExpenseForm.dictValue = this.newExpenseForm.name;
1030
+          this.newExpenseForm.listClass = 'default'
1031
+          this.newExpenseForm.dictSort = length;
1032
+          addData(this.newExpenseForm).then(res => {
1033
+            this.$modal.msgSuccess("新增成功");
1034
+            this.openNewExpense = false;
1035
+            this.newExpenseForm.name = '';
1036
+            // 刷新字典数据
1037
+            getDicts("cmc_borrow_expense").then(res => {
1038
+              let arr = [];
1039
+              for (let i = 0; i < res.data.length; i++) {
1040
+                arr.push({
1041
+                  label: res.data[i].dictLabel,
1042
+                  value: res.data[i].dictValue,
1043
+                  raw: res.data[i]
1044
+                })
1045
+              }
1046
+              this.dict.type.cmc_borrow_expense = arr;
1047
+            })
1048
+          })
1049
+        }
1050
+      })
991
     }
1051
     }
992
   }
1052
   }
993
 };
1053
 };

+ 4
- 4
oa-ui/src/views/index.vue View File

2
  * @Author: ysh
2
  * @Author: ysh
3
  * @Date: 2024-01-03 09:23:11
3
  * @Date: 2024-01-03 09:23:11
4
  * @LastEditors: Please set LastEditors
4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-03-14 16:57:31
5
+ * @LastEditTime: 2025-05-20 09:31:22
6
 -->
6
 -->
7
 
7
 
8
 <template>
8
 <template>
234
           privilege: ['oa:salary:list']
234
           privilege: ['oa:salary:list']
235
         }, {
235
         }, {
236
           id: 9,
236
           id: 9,
237
-          name: '项目算',
237
+          name: '项目算',
238
           icon: 'settle',
238
           icon: 'settle',
239
           bgColor: '#ff6f61',
239
           bgColor: '#ff6f61',
240
           boxShadow: '0 5px 20px rgba(255,111,97,0.5)',
240
           boxShadow: '0 5px 20px rgba(255,111,97,0.5)',
241
-          path: '/product/settle/project',
242
-          privilege: ['oa:settle:list']
241
+          path: '/product/budget/scheme',
242
+          privilege: ['oa:budget:list']
243
         }, {
243
         }, {
244
           id: 10,
244
           id: 10,
245
           name: '借款管理',
245
           name: '借款管理',

+ 4
- 4
oa-ui/src/views/oa/budget/index.vue View File

88
     </el-dialog>
88
     </el-dialog>
89
 
89
 
90
     <el-dialog :title="title" :visible.sync="infoOpen" width="70%" append-to-body>
90
     <el-dialog :title="title" :visible.sync="infoOpen" width="70%" append-to-body>
91
-      <budget-adjust :taskForm="taskForm" :taskName="''" :row="clickRow" v-if="isAdjust"></budget-adjust>
92
-      <div v-else>
93
-        <budget-info v-if="isOld" :taskForm="taskForm" :taskName="''"></budget-info>
94
-        <new-budget-info v-if="!isOld" :taskForm="taskForm" :taskName="''"></new-budget-info>
91
+      <budget-adjust :taskForm="taskForm" :taskName="''" :row="clickRow" v-show="isAdjust"></budget-adjust>
92
+      <div v-show="!isAdjust">
93
+        <budget-info :taskForm="taskForm" :taskName="''" v-show="isOld"></budget-info>
94
+        <new-budget-info :taskForm="taskForm" :taskName="''" v-show="!isOld"></new-budget-info>
95
       </div>
95
       </div>
96
     </el-dialog>
96
     </el-dialog>
97
   </div>
97
   </div>

+ 27
- 97
oa-ui/src/views/oa/study/components/studyRight.vue View File

2
  * @Author: ysh
2
  * @Author: ysh
3
  * @Date: 2025-03-05 15:36:17
3
  * @Date: 2025-03-05 15:36:17
4
  * @LastEditors: Please set LastEditors
4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-03-26 09:12:56
5
+ * @LastEditTime: 2025-05-20 11:35:06
6
 -->
6
 -->
7
 <template>
7
 <template>
8
   <div>
8
   <div>
11
         <resource-tree :isModify="false" @clickNode="queryField"></resource-tree>
11
         <resource-tree :isModify="false" @clickNode="queryField"></resource-tree>
12
       </el-col>
12
       </el-col>
13
       <el-col :span="16">
13
       <el-col :span="16">
14
-        <el-form :model="videoParams" size="small" :inline="true" label-width="68px" @submit.native.prevent>
14
+        <el-form :model="queryParams" size="small" :inline="true" label-width="68px" @submit.native.prevent>
15
           <el-form-item label="资料名称" prop="title">
15
           <el-form-item label="资料名称" prop="title">
16
-            <el-input v-model="videoParams.title" placeholder="请输入资料名称" clearable
16
+            <el-input v-model="queryParams.title" placeholder="请输入资料名称" clearable
17
               @keyup.enter.native="handleVideoQuery" />
17
               @keyup.enter.native="handleVideoQuery" />
18
           </el-form-item>
18
           </el-form-item>
19
           <el-form-item>
19
           <el-form-item>
20
             <el-button type="primary" icon="el-icon-search" size="mini" @click="handleVideoQuery">搜索</el-button>
20
             <el-button type="primary" icon="el-icon-search" size="mini" @click="handleVideoQuery">搜索</el-button>
21
           </el-form-item>
21
           </el-form-item>
22
         </el-form>
22
         </el-form>
23
-        <el-table :data="videoList" style="width: 100%">
23
+        <el-table :data="resourceList" style="width: 100%">
24
           <el-table-column align="center" label="序号" type="index" />
24
           <el-table-column align="center" label="序号" type="index" />
25
           <el-table-column align="center" label="名称" prop="title" />
25
           <el-table-column align="center" label="名称" prop="title" />
26
           <el-table-column align="center" label="类型" prop="type" />
26
           <el-table-column align="center" label="类型" prop="type" />
33
             </template>
33
             </template>
34
           </el-table-column>
34
           </el-table-column>
35
         </el-table>
35
         </el-table>
36
-        <pagination v-show="videoTotal > 0" :total="videoTotal" :page.sync="videoParams.pageNum"
37
-          :layout="'total, prev, pager, next,jumper'" :limit.sync="videoParams.pageSize" :autoScroll="false"
38
-          @pagination="getVideoList" />
36
+        <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
37
+          :limit.sync="queryParams.pageSize" :autoScroll="false" @pagination="getResourceList" />
39
       </el-col>
38
       </el-col>
40
     </el-row>
39
     </el-row>
41
-    <!-- <div class="video">
42
-      <el-tabs v-model="videoTab" type="card">
43
-        <el-form :model="videoParams" size="small" :inline="true" label-width="68px" @submit.native.prevent>
44
-          <el-form-item label="视频名称" prop="title">
45
-            <el-input v-model="videoParams.title" placeholder="请输入资料名称" clearable
46
-              @keyup.enter.native="handleVideoQuery" />
47
-          </el-form-item>
48
-          <el-form-item>
49
-            <el-button type="primary" icon="el-icon-search" size="mini" @click="handleVideoQuery">搜索</el-button>
50
-          </el-form-item>
51
-        </el-form>
52
-        <el-tab-pane label="视频" name="video">
53
-          <el-table :data="videoList" style="width: 100%">
54
-            <el-table-column align="center" label="序号" type="index" />
55
-            <el-table-column align="center" label="名称" prop="title" />
56
-            <el-table-column align="center" label="学时" prop="hours" />
57
-            <el-table-column align="center" label="操作">
58
-              <template slot-scope="{row}">
59
-                <el-button type="text" @click="addToStudy(row)">
60
-                  添加课程
61
-                </el-button>
62
-              </template>
63
-      </el-table-column>
64
-      </el-table>
65
-      <pagination v-show="videoTotal > 0" :total="videoTotal" :page.sync="videoParams.pageNum"
66
-        :layout="'total, prev, pager, next,jumper'" :limit.sync="videoParams.pageSize" :autoScroll="false"
67
-        @pagination="getVideoList" />
68
-      </el-tab-pane>
69
-      </el-tabs>
70
-    </div>
71
-    <div class="pdf">
72
-      <el-tabs v-model="pdfTab" type="card">
73
-        <el-form :model="pdfParams" size="small" :inline="true" label-width="68px">
74
-          <el-form-item label="文档名称" prop="title">
75
-            <el-input v-model="pdfParams.title" placeholder="请输入资料名称" clearable @keyup.enter.native="handlePdfQuery" />
76
-          </el-form-item>
77
-          <el-form-item>
78
-            <el-button type="primary" icon="el-icon-search" size="mini" @click="handlePdfQuery">搜索</el-button>
79
-          </el-form-item>
80
-        </el-form>
81
-        <el-tab-pane label="文档" name="pdf">
82
-          <el-table :data="pdfList" style="width: 100%">
83
-            <el-table-column align="center" label="序号" type="index" />
84
-            <el-table-column align="center" label="名称" prop="title" />
85
-            <el-table-column align="center" label="学时" prop="hours" />
86
-            <el-table-column align="center" label="操作">
87
-              <template slot-scope="{row}">
88
-                    <el-button type="text" @click="addToStudy(row)">
89
-                      添加课程
90
-                    </el-button>
91
-                  </template>
92
-            </el-table-column>
93
-          </el-table>
94
-          <pagination v-show="pdfTotal > 0" :total="pdfTotal" :page.sync="pdfParams.pageNum"
95
-            :layout="'total, prev, pager, next,jumper'" :limit.sync="pdfParams.pageSize" :autoScroll="false"
96
-            @pagination="getPdfList" />
97
-        </el-tab-pane>
98
-      </el-tabs>
99
-    </div> -->
100
   </div>
40
   </div>
101
 </template>
41
 </template>
102
 
42
 
109
   components: { resourceTree },
49
   components: { resourceTree },
110
   data() {
50
   data() {
111
     return {
51
     return {
112
-      videoList: [],
52
+      resourceList: [],
113
       pdfList: [],
53
       pdfList: [],
114
       videoTab: 'video',
54
       videoTab: 'video',
115
       pdfTab: 'pdf',
55
       pdfTab: 'pdf',
116
-      videoParams: {},
56
+      queryParams: {
57
+        pageNum: 1,
58
+        pageSize: 10
59
+      },
117
       pdfParams: {},
60
       pdfParams: {},
118
-      videoTotal: 0,
61
+      total: 0,
119
       pdfTotal: 0,
62
       pdfTotal: 0,
120
     }
63
     }
121
   },
64
   },
122
   created() {
65
   created() {
123
-    this.getVideoList();
124
-    this.getPdfList();
66
+    this.getResourceList();
125
   },
67
   },
126
   methods: {
68
   methods: {
127
-    getVideoList() {
128
-      // this.videoParams.type = '视频'
129
-      listResource(this.videoParams).then(response => {
130
-        this.videoList = response.rows;
131
-        this.videoTotal = response.total;
69
+    getResourceList() {
70
+      listResource(this.queryParams).then(response => {
71
+        this.resourceList = response.rows;
72
+        this.total = response.total;
132
       });
73
       });
133
     },
74
     },
134
     getList() {
75
     getList() {
135
-      listResource(this.videoParams).then(response => {
136
-        this.videoList = response.rows;
137
-        this.videoTotal = response.total;
76
+      listResource(this.queryParams).then(response => {
77
+        this.resourceList = response.rows;
78
+        this.total = response.total;
138
       });
79
       });
139
     },
80
     },
140
     getAllListByFiedldId() {
81
     getAllListByFiedldId() {
141
       this.loading = true;
82
       this.loading = true;
142
-      getListBelow(this.videoParams).then(response => {
143
-        this.videoList = response.rows;
144
-        this.videoTotal = response.total;
83
+      getListBelow(this.queryParams).then(response => {
84
+        this.resourceList = response.rows;
85
+        this.total = response.total;
145
       })
86
       })
146
     },
87
     },
147
-    getPdfList() {
148
-      this.pdfParams.type = '文档'
149
-      listResource(this.pdfParams).then(response => {
150
-        this.pdfList = response.rows;
151
-        this.pdfTotal = response.total;
152
-      });
153
-    },
154
     handleVideoQuery() {
88
     handleVideoQuery() {
155
-      this.videoParams.pageNum = 1;
156
-      this.getVideoList();
157
-    },
158
-    handlePdfQuery() {
159
-      this.pdfParams.pageNum = 1;
160
-      this.getPdfList();
89
+      this.queryParams.pageNum = 1;
90
+      this.getResourceList();
161
     },
91
     },
162
     addToStudy(row) {
92
     addToStudy(row) {
163
       this.$modal.confirm('是否添加资料名称为"' + row.title + '"到我的学习记录?').then(async res => {
93
       this.$modal.confirm('是否添加资料名称为"' + row.title + '"到我的学习记录?').then(async res => {
181
     },
111
     },
182
     queryField(data) {
112
     queryField(data) {
183
       if (data.fieldId) {
113
       if (data.fieldId) {
184
-        this.videoParams.fieldId = data.fieldId
114
+        this.queryParams.fieldId = data.fieldId
185
         this.getAllListByFiedldId();
115
         this.getAllListByFiedldId();
186
       } else {
116
       } else {
187
-        this.videoParams.fieldId = null
117
+        this.queryParams.fieldId = null
188
         this.getList();
118
         this.getList();
189
       }
119
       }
190
     }
120
     }

Loading…
Cancel
Save