Browse Source

修改网页端预算显示的问题;

新增移动端项目首页。
余思翰 1 week ago
parent
commit
ce8e7dd1e3

+ 10
- 0
oa-ui-app/api/qywx/index.js View File

@@ -0,0 +1,10 @@
1
+import request from '@/utils/request'
2
+
3
+// 发送企业微信消息
4
+export function sendQyMessage(data) {
5
+  return request({
6
+    url: '/qywx/message/send',
7
+    method: 'post',
8
+    data: data
9
+  })
10
+} 

+ 9
- 7
oa-ui-app/pages.json View File

@@ -1,9 +1,3 @@
1
-/*
2
- * @Author: ysh
3
- * @Date: 2025-01-15 14:42:34
4
- * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-02-20 10:20:46
6
- */
7 1
 {
8 2
 	"pages": [{
9 3
 			"path": "pages/login",
@@ -96,7 +90,8 @@
96 90
 		{
97 91
 			"path": "pages/message/myProcess/index",
98 92
 			"style": {
99
-				"navigationBarTitleText": "我的流程"
93
+				"navigationBarTitleText": "我的流程",
94
+				"enablePullDownRefresh": true
100 95
 			}
101 96
 		},
102 97
 		{
@@ -119,6 +114,13 @@
119 114
 			{
120 115
 				"navigationBarTitleText" : "借款审批"
121 116
 			}
117
+		},
118
+		{
119
+			"path" : "pages/project/projectInfo",
120
+			"style" : 
121
+			{
122
+				"navigationBarTitleText" : "项目详情"
123
+			}
122 124
 		}
123 125
 	],
124 126
 	"tabBar": {

+ 84
- 68
oa-ui-app/pages/index.vue View File

@@ -6,7 +6,7 @@
6 6
         <text class="search-title">搜索条件</text>
7 7
         <text class="search-icon">{{ isSearchExpanded ? '收起' : '展开' }}</text>
8 8
       </view>
9
-      
9
+
10 10
       <view class="search-content" v-if="isSearchExpanded">
11 11
         <view class="search-item">
12 12
           <text>项目编号</text>
@@ -47,21 +47,17 @@
47 47
     <view class="list-box">
48 48
       <view class="list-header">
49 49
         <text class="title">测绘项目列表</text>
50
-        <view class="header-btns">
50
+        <!-- <view class="header-btns">
51 51
           <button type="primary" size="mini" @tap="handleRegister">登记项目</button>
52 52
           <button type="default" size="mini" @tap="handleExport">导出项目</button>
53
-        </view>
53
+        </view> -->
54 54
       </view>
55 55
 
56
-      <scroll-view 
57
-        scroll-y 
58
-        class="list-scroll"
59
-        @scrolltolower="loadMore"
60
-        :refresher-enabled="true"
61
-        :refresher-triggered="isRefreshing"
62
-        @refresherrefresh="onRefresh"
63
-      >
56
+      <scroll-view scroll-y class="list-scroll" id="projectList" :scroll-into-view="scrollToId" 
57
+        :scroll-with-animation="true" @scrolltolower="loadMore" :refresher-enabled="true"
58
+        :refresher-triggered="isRefreshing" @refresherrefresh="onRefresh" @scroll="onScroll">
64 59
         <view class="list-content">
60
+          <view id="top"></view>
65 61
           <view class="project-card" v-for="(item, index) in projectList" :key="index">
66 62
             <!-- 卡片头部 -->
67 63
             <view class="card-header">
@@ -110,8 +106,6 @@
110 106
             <!-- 卡片底部 -->
111 107
             <view class="card-footer">
112 108
               <button type="primary" size="mini" @tap="handleView(item)">查看</button>
113
-              <button type="warn" size="mini" @tap="handleDelete(item)">删除</button>
114
-              <button type="default" size="mini" @tap="handleRelate(item)">关联合同</button>
115 109
             </view>
116 110
           </view>
117 111
         </view>
@@ -122,6 +116,13 @@
122 116
         <text v-if="hasMore">上拉加载更多</text>
123 117
         <text v-else>没有更多数据了</text>
124 118
       </view>
119
+
120
+      <!-- 回到顶部按钮 -->
121
+      <view class="back-to-top" v-if="showBackToTop" @tap="scrollToTop">
122
+        <text class="iconfont">
123
+          <uv-icon size="28" name="arrow-upward" color="#fcfcfc"></uv-icon>
124
+        </text>
125
+      </view>
125 126
     </view>
126 127
   </view>
127 128
 </template>
@@ -131,6 +132,7 @@ import { listProject, listProjectFuzzy, delProject } from "@/api/oa/project/proj
131 132
 import { getProjectProgress } from "@/api/oa/project/projectProgress";
132 133
 import { listDept } from '@/api/system/dept';
133 134
 import { listUser } from '@/api/system/user';
135
+import { checkPermi } from '@/utils/permission';
134 136
 
135 137
 export default {
136 138
   data() {
@@ -153,7 +155,10 @@ export default {
153 155
       selectedLeader: '',
154 156
       selectedDept: '',
155 157
       hasMore: true,
156
-      isRefreshing: false
158
+      isRefreshing: false,
159
+      showBackToTop: false,
160
+      scrollTop: 0,
161
+      scrollToId: ''
157 162
     }
158 163
   },
159 164
   onLoad() {
@@ -165,7 +170,7 @@ export default {
165 170
     toggleSearch() {
166 171
       this.isSearchExpanded = !this.isSearchExpanded;
167 172
     },
168
-    
173
+
169 174
     resetQuery() {
170 175
       this.queryParams = {
171 176
         pageNum: 1,
@@ -180,32 +185,39 @@ export default {
180 185
       this.selectedDept = '';
181 186
       this.handleQuery();
182 187
     },
183
-    
188
+
184 189
     async getList() {
185 190
       this.loading = true;
186 191
       try {
187
-        const response = this.queryParams.queryString ? 
188
-          await listProjectFuzzy(this.queryParams) : 
192
+        const deptId = this.$store.getters.deptId;
193
+        if (deptId > 106 && deptId != 109) {
194
+          let response = await checkPermi(['oa:allproject:query'])
195
+          if (response == false) {
196
+            this.queryParams.undertakingDept = deptId
197
+          }
198
+        }
199
+        const response = this.queryParams.queryString ?
200
+          await listProjectFuzzy(this.queryParams) :
189 201
           await listProject(this.queryParams);
190
-        
202
+
191 203
         if (this.queryParams.pageNum === 1) {
192 204
           this.projectList = response.rows;
193 205
         } else {
194 206
           this.projectList = [...this.projectList, ...response.rows];
195 207
         }
196
-        
208
+
197 209
         this.total = response.total;
198 210
         this.hasMore = this.projectList.length < this.total;
199
-        
211
+
200 212
         for (let project of this.projectList) {
201 213
           const res = await getProjectProgress(project.projectId);
202 214
           if (res.data && res.data.length > 0) {
203
-            project.percentage = Number(res.data[res.data.length - 1].percentage);
215
+            this.$set(project, 'percentage', Number(res.data[res.data.length - 1].percentage));
204 216
           } else {
205
-            project.percentage = 0;
217
+            this.$set(project, 'percentage', 0);
206 218
           }
207 219
           if (project.isFinished === '1') {
208
-            project.percentage = 100;
220
+            this.$set(project, 'percentage', 100);
209 221
           }
210 222
         }
211 223
       } catch (error) {
@@ -218,7 +230,7 @@ export default {
218 230
         this.isRefreshing = false;
219 231
       }
220 232
     },
221
-    
233
+
222 234
     async getDeptList() {
223 235
       try {
224 236
         const res = await listDept({});
@@ -233,7 +245,7 @@ export default {
233 245
         });
234 246
       }
235 247
     },
236
-    
248
+
237 249
     async getUserList() {
238 250
       try {
239 251
         const res = await listUser({ pageNum: 1, pageSize: 9999 });
@@ -248,95 +260,76 @@ export default {
248 260
         });
249 261
       }
250 262
     },
251
-    
263
+
252 264
     handleQuery() {
253 265
       this.queryParams.pageNum = 1;
254 266
       this.getList();
255 267
     },
256
-    
268
+
257 269
     handleLeaderChange(e) {
258 270
       const index = e.detail.value;
259 271
       this.queryParams.projectLeader = this.userList[index].value;
260 272
       this.selectedLeader = this.userList[index].text;
261 273
       this.handleQuery();
262 274
     },
263
-    
275
+
264 276
     handleDeptChange(e) {
265 277
       const index = e.detail.value;
266 278
       this.queryParams.undertakingDept = this.deptList[index].value;
267 279
       this.selectedDept = this.deptList[index].text;
268 280
       this.handleQuery();
269 281
     },
270
-    
282
+
271 283
     handleView(row) {
272 284
       uni.navigateTo({
273
-        url: `/pages/project/info?id=${row.projectId}&projectName=${encodeURIComponent(row.projectName)}`
285
+        url: `/pages/project/projectInfo?projectId=${row.projectId}`
274 286
       });
275 287
     },
276
-    
277
-    handleDelete(row) {
278
-      uni.showModal({
279
-        title: '提示',
280
-        content: `是否确认删除项目编号为"${row.projectNumber}"的数据项?`,
281
-        success: async (res) => {
282
-          if (res.confirm) {
283
-            try {
284
-              await delProject(row.projectId);
285
-              this.getList();
286
-              uni.showToast({
287
-                title: '删除成功',
288
-                icon: 'success'
289
-              });
290
-            } catch (error) {
291
-              uni.showToast({
292
-                title: '删除失败',
293
-                icon: 'none'
294
-              });
295
-            }
296
-          }
297
-        }
298
-      });
299
-    },
300
-    
288
+
301 289
     handleRegister() {
302 290
       uni.navigateTo({
303 291
         url: '/pages/project/register'
304 292
       });
305 293
     },
306
-    
294
+
307 295
     handleExport() {
308 296
       uni.showToast({
309 297
         title: '导出功能开发中',
310 298
         icon: 'none'
311 299
       });
312 300
     },
313
-    
314
-    handleRelate(row) {
315
-      uni.showToast({
316
-        title: '关联合同功能开发中',
317
-        icon: 'none'
318
-      });
319
-    },
320
-    
301
+
321 302
     loadMore() {
322 303
       if (this.hasMore) {
323 304
         this.queryParams.pageNum++;
324 305
         this.getList();
325 306
       }
326 307
     },
327
-    
308
+
328 309
     onRefresh() {
329 310
       this.isRefreshing = true;
330 311
       this.queryParams.pageNum = 1;
331 312
       this.getList();
332 313
     },
333
-    
314
+
334 315
     getProgressColor(percentage) {
335 316
       if (!percentage) return '#ff4d4f';
336 317
       if (percentage <= 20) return '#ff4d4f';
337 318
       if (percentage <= 50) return '#faad14';
338 319
       if (percentage <= 80) return '#1890ff';
339 320
       return '#52c41a';
321
+    },
322
+
323
+    onScroll(e) {
324
+      this.scrollTop = e.detail.scrollTop;
325
+      this.showBackToTop = this.scrollTop > 300;
326
+    },
327
+
328
+    scrollToTop() {
329
+      this.scrollToId = 'top';
330
+      setTimeout(() => {
331
+        this.scrollToId = '';
332
+      }, 300);
340 333
     }
341 334
   }
342 335
 }
@@ -524,7 +517,7 @@ export default {
524 517
 }
525 518
 
526 519
 .info-row .label {
527
-  width: 160rpx;
520
+  width: 170rpx;
528 521
   color: #909399;
529 522
   font-size: 28rpx;
530 523
 }
@@ -573,4 +566,27 @@ export default {
573 566
   color: #909399;
574 567
   font-size: 28rpx;
575 568
 }
569
+
570
+.back-to-top {
571
+  position: fixed;
572
+  right: 30rpx;
573
+  bottom: 100rpx;
574
+  width: 80rpx;
575
+  height: 80rpx;
576
+  background-color: rgba(0, 0, 0, 0.5);
577
+  border-radius: 50%;
578
+  display: flex;
579
+  align-items: center;
580
+  justify-content: center;
581
+  z-index: 999;
582
+}
583
+
584
+.back-to-top .iconfont {
585
+  color: #fff;
586
+  font-size: 40rpx;
587
+}
588
+
589
+.icon-top:before {
590
+  content: "↑";
591
+}
576 592
 </style>

+ 134
- 26
oa-ui-app/pages/login.vue View File

@@ -3,7 +3,7 @@
3 3
     <view class="logo-content align-center justify-center flex">
4 4
       <image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix">
5 5
       </image>
6
-      <text class="title">CMC综合办公系统</text>
6
+      <text class="title">CMC智联云枢办公系统</text>
7 7
     </view>
8 8
     <view class="login-form-content">
9 9
       <view class="input-item flex align-center">
@@ -31,6 +31,7 @@
31 31
       <text @click="handleUserAgrement" class="text-blue">《用户协议》</text>
32 32
       <text @click="handlePrivacy" class="text-blue">《隐私协议》</text>
33 33
     </view> -->
34
+    <view class="copyright-info">©2025 CMC智联云枢办公系统 版权所有</view>
34 35
   </view>
35 36
 </template>
36 37
 
@@ -114,43 +115,109 @@
114 115
 
115 116
 <style lang="scss">
116 117
   page {
117
-    background-color: #ffffff;
118
+    background: linear-gradient(135deg, #f5f7fa 0%, #e4e8eb 100%);
119
+    min-height: 100vh;
120
+    position: relative;
121
+    overflow: hidden;
122
+
123
+    &::before,
124
+    &::after {
125
+      content: '';
126
+      position: absolute;
127
+      width: 300px;
128
+      height: 300px;
129
+      border-radius: 50%;
130
+      z-index: 0;
131
+    }
132
+
133
+    &::before {
134
+      background: linear-gradient(45deg, rgba(33, 150, 243, 0.1), rgba(25, 118, 210, 0.1));
135
+      top: -100px;
136
+      right: -100px;
137
+      animation: float 6s ease-in-out infinite;
138
+    }
139
+
140
+    &::after {
141
+      background: linear-gradient(45deg, rgba(33, 150, 243, 0.08), rgba(25, 118, 210, 0.08));
142
+      bottom: -150px;
143
+      left: -150px;
144
+      animation: float 8s ease-in-out infinite reverse;
145
+    }
118 146
   }
119 147
 
120 148
   .normal-login-container {
121 149
     width: 100%;
150
+    padding: 0 30rpx;
151
+    box-sizing: border-box;
152
+    position: relative;
153
+    z-index: 1;
154
+    min-height: 100vh;
155
+    display: flex;
156
+    flex-direction: column;
157
+
158
+    &::before {
159
+      content: '';
160
+      position: absolute;
161
+      top: 50%;
162
+      left: 50%;
163
+      transform: translate(-50%, -50%);
164
+      width: 600px;
165
+      height: 600px;
166
+      background: radial-gradient(circle, rgba(33, 150, 243, 0.03) 0%, rgba(33, 150, 243, 0) 70%);
167
+      z-index: -1;
168
+    }
122 169
 
123 170
     .logo-content {
124 171
       width: 100%;
125 172
       font-size: 21px;
126 173
       text-align: center;
127
-      padding-top: 15%;
174
+      padding-top: 25%;
175
+      animation: fadeInDown 0.8s ease-out;
128 176
 
129 177
       image {
130
-        border-radius: 4px;
178
+        border-radius: 12px;
179
+        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
180
+        transition: transform 0.3s ease;
181
+        
182
+        &:hover {
183
+          transform: scale(1.05);
184
+        }
131 185
       }
132 186
 
133 187
       .title {
134 188
         margin-left: 10px;
189
+        background: linear-gradient(45deg, #2196F3, #1976D2);
190
+        -webkit-background-clip: text;
191
+        color: transparent;
192
+        font-weight: 600;
135 193
       }
136 194
     }
137 195
 
138 196
     .login-form-content {
139 197
       text-align: center;
140 198
       margin: 20px auto;
141
-      margin-top: 15%;
142
-      width: 80%;
199
+      margin-top: 10%;
200
+      width: 90%;
201
+      animation: fadeInUp 0.8s ease-out;
143 202
 
144 203
       .input-item {
145 204
         margin: 20px auto;
146
-        background-color: #f5f6f7;
205
+        background-color: rgba(255, 255, 255, 0.9);
147 206
         height: 45px;
148
-        border-radius: 20px;
207
+        border-radius: 25px;
208
+        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
209
+        transition: all 0.3s ease;
210
+        border: 1px solid transparent;
211
+
212
+        &:focus-within {
213
+          border-color: #2196F3;
214
+          box-shadow: 0 2px 12px rgba(33, 150, 243, 0.1);
215
+        }
149 216
 
150 217
         .icon {
151 218
           font-size: 38rpx;
152
-          margin-left: 10px;
153
-          color: #999;
219
+          margin-left: 20px;
220
+          color: #2196F3;
154 221
         }
155 222
 
156 223
         .input {
@@ -159,32 +226,73 @@
159 226
           line-height: 20px;
160 227
           text-align: left;
161 228
           padding-left: 15px;
229
+          color: #333;
230
+          
231
+          &::placeholder {
232
+            color: #999;
233
+          }
162 234
         }
163
-
164 235
       }
165 236
 
166 237
       .login-btn {
167 238
         margin-top: 40px;
168 239
         height: 45px;
169
-      }
240
+        background: linear-gradient(45deg, #2196F3, #1976D2);
241
+        border: none;
242
+        font-weight: 600;
243
+        letter-spacing: 1px;
244
+        transition: all 0.3s ease;
245
+        box-shadow: 0 4px 12px rgba(33, 150, 243, 0.2);
170 246
 
171
-      .xieyi {
172
-        color: #333;
173
-        margin-top: 20px;
174
-      }
175
-      
176
-      .login-code {
177
-        height: 38px;
178
-        float: right;
179
-      
180
-        .login-code-img {
181
-          height: 38px;
182
-          position: absolute;
183
-          margin-left: 10px;
184
-          width: 200rpx;
247
+        &:active {
248
+          transform: translateY(2px);
249
+          box-shadow: 0 2px 6px rgba(33, 150, 243, 0.2);
185 250
         }
186 251
       }
187 252
     }
188 253
   }
189 254
 
255
+  .copyright-info {
256
+    width: 100%;
257
+    text-align: center;
258
+    position: fixed;
259
+    left: 0;
260
+    bottom: 30rpx;
261
+    color: #666;
262
+    font-size: 22rpx;
263
+    letter-spacing: 1rpx;
264
+    z-index: 1;
265
+    opacity: 0.8;
266
+  }
267
+
268
+  @keyframes float {
269
+    0%, 100% {
270
+      transform: translateY(0) rotate(0deg);
271
+    }
272
+    50% {
273
+      transform: translateY(-20px) rotate(5deg);
274
+    }
275
+  }
276
+
277
+  @keyframes fadeInDown {
278
+    from {
279
+      opacity: 0;
280
+      transform: translateY(-20px);
281
+    }
282
+    to {
283
+      opacity: 1;
284
+      transform: translateY(0);
285
+    }
286
+  }
287
+
288
+  @keyframes fadeInUp {
289
+    from {
290
+      opacity: 0;
291
+      transform: translateY(20px);
292
+    }
293
+    to {
294
+      opacity: 1;
295
+      transform: translateY(0);
296
+    }
297
+  }
190 298
 </style>

+ 2
- 1
oa-ui-app/pages/message/myProcess/index.vue View File

@@ -2,7 +2,7 @@
2 2
  * @Author: ysh
3 3
  * @Date: 2025-02-19 15:36:34
4 4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-05-23 15:42:14
5
+ * @LastEditTime: 2025-05-26 10:46:52
6 6
 -->
7 7
 <template>
8 8
   <view class="page-container">
@@ -158,6 +158,7 @@ export default {
158 158
       this.myProcessList = res.data.list;
159 159
       this.mescroll.endSuccess(res.data.length)
160 160
       this.mescroll.endErr()
161
+      uni.stopPullDownRefresh();
161 162
     },
162 163
     // mescroll上拉加载回调
163 164
     async upCallback(page) {

+ 1034
- 0
oa-ui-app/pages/project/projectInfo.vue
File diff suppressed because it is too large
View File


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

@@ -2,7 +2,7 @@
2 2
  * @Author: ysh
3 3
  * @Date: 2025-05-07 11:01:39
4 4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-05-21 14:16:47
5
+ * @LastEditTime: 2025-05-27 16:27:15
6 6
 -->
7 7
 <template>
8 8
   <div class="main" v-loading="loading">
@@ -33,6 +33,15 @@
33 33
       <el-descriptions-item label="预算表单备注" :span="5">
34 34
         {{ budgetForm.remark }}
35 35
       </el-descriptions-item>
36
+      <el-descriptions-item label="预算附件" :span="5" v-if="budgetForm.document">
37
+        <el-link type="primary" @click="reviewWord(`${baseUrl}${'/profile/upload' + budgetForm.document}`)">
38
+          {{ getFileName(budgetForm.document) }}
39
+        </el-link>
40
+        <el-link class="ml20" type="warning" :href="`${baseUrl}${'/profile/upload' + budgetForm.document}`"
41
+          :underline="false" target="_blank">
42
+          <span class="el-icon-download">下载文件</span>
43
+        </el-link>
44
+      </el-descriptions-item>
36 45
       <el-descriptions-item label="项目计划工作量" :span="3">
37 46
         <div>
38 47
           <table border="1" style="width: 100%;">
@@ -118,7 +127,7 @@
118 127
             <td style="width:120px">金额</td>
119 128
             <td style="width:120px">备注</td>
120 129
           </tr>
121
-          <tr v-for="staff, index in innerStaffList" :key="'user' + staff.userId">
130
+          <tr v-for="staff, index in innerStaffList" :key="'innerUser' + staff.userId">
122 131
             <td>{{ index + 1 }}</td>
123 132
             <td>{{ staff.user ? staff.user.nickName : '' }}</td>
124 133
             <td>{{ staff.dayCost }}</td>
@@ -165,7 +174,7 @@
165 174
             <td style="width:120px">金额</td>
166 175
             <td style="width:120px">备注</td>
167 176
           </tr>
168
-          <tr v-for="staff, index in outerStaffList" :key="'user' + staff.userId">
177
+          <tr v-for="staff, index in outerStaffList" :key="'outUser' + staff.userId">
169 178
             <td>{{ index + 1 }}</td>
170 179
             <td>{{ staff.user ? staff.user.nickName : '' }}</td>
171 180
             <td>{{ staff.dayCost }}</td>
@@ -523,6 +532,7 @@ export default {
523 532
   },
524 533
   data() {
525 534
     return {
535
+      baseUrl: process.env.VUE_APP_BASE_API,
526 536
       loading: true,
527 537
       budgetForm: {},
528 538
       project: {},
@@ -844,7 +854,7 @@ export default {
844 854
 }
845 855
 
846 856
 .main {
847
-  width: 85%;
857
+  width: 90%;
848 858
   margin: 0 auto;
849 859
   text-align: center;
850 860
 }

+ 12
- 8
oa-ui/src/views/flowable/form/budget/budgetInfo.vue View File

@@ -2,7 +2,7 @@
2 2
  * @Author: ysh
3 3
  * @Date: 2024-04-03 16:28:09
4 4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-05-19 17:08:57
5
+ * @LastEditTime: 2025-05-27 15:11:17
6 6
 -->
7 7
 <template>
8 8
   <div class="main">
@@ -123,7 +123,7 @@
123 123
               <td></td>
124 124
               <td style="min-width:80px">金额</td>
125 125
             </tr>
126
-            <tr v-for="user in chooseUser" :key="'user' + user.userId">
126
+            <tr v-for="user, index in chooseUser" :key="'user' + user.userId + index">
127 127
               <td>{{ user.user ? user.user.nickName : '' }}</td>
128 128
               <td>1780</td>
129 129
               <td>
@@ -463,13 +463,17 @@ export default {
463 463
 
464 464
             for (let work of this.workList) {
465 465
               if (work.groundType == '0') {
466
-                work.price = work.cmcPrice.commonPrice
467
-                work.scaleGrade = work.cmcPrice.scaleGrade
468
-                work.unit = work.cmcPrice.unit
466
+                if (work.cmcPrice) {
467
+                  work.price = work.cmcPrice.commonPrice
468
+                  work.scaleGrade = work.cmcPrice.scaleGrade
469
+                  work.unit = work.cmcPrice.unit
470
+                }
469 471
               } else {
470
-                work.price = work.cmcPrice.complexPrice
471
-                work.scaleGrade = work.cmcPrice.scaleGrade
472
-                work.unit = work.cmcPrice.unit
472
+                if (work.cmcPrice) {
473
+                  work.price = work.cmcPrice.complexPrice
474
+                  work.scaleGrade = work.cmcPrice.scaleGrade
475
+                  work.unit = work.cmcPrice.unit
476
+                }
473 477
               }
474 478
             }
475 479
             this.loading = false;

+ 14
- 12
oa-ui/src/views/flowable/form/budget/deviceTable.vue View File

@@ -2,15 +2,15 @@
2 2
   <div>
3 3
     <el-form ref="form" :model="form" style="padding: 20px 100px 0">
4 4
       <el-form-item label="选择设备:">
5
-        <span v-if="chooseDevice.length != 0">
6
-          <el-tag effect="plain" type="success" v-for="item in chooseDevice" style="margin: 5px; font-size: 14px"
5
+        <span v-if="chooseDeviceList.length != 0">
6
+          <el-tag effect="plain" type="success" v-for="item in chooseDeviceList" style="margin: 5px; font-size: 14px"
7 7
             :key="item.code">
8 8
             {{ item.name + "-" + item.series + "-" + item.brand }}
9 9
           </el-tag>
10 10
         </span>
11 11
         <el-button type="success" plain icon="el-icon-plus" @click="openDevice = true" size="mini">选择</el-button>
12 12
       </el-form-item>
13
-      <el-form-item v-if="chooseDevice.length != 0">
13
+      <el-form-item v-if="chooseDeviceList.length != 0">
14 14
         <table border="1">
15 15
           <tr>
16 16
             <td :colspan="6" class="head">设备成本预算</td>
@@ -23,7 +23,7 @@
23 23
             <td style="width: 100px">预算天数</td>
24 24
             <td style="width: 100px">总额</td>
25 25
           </tr>
26
-          <tr v-for="device in chooseDevice" :key="device.deviceId">
26
+          <tr v-for="device in chooseDeviceList" :key="device.deviceId">
27 27
             <td>{{ device.name }}</td>
28 28
             <td>{{ device.series }}</td>
29 29
             <td>{{ device.brand }}</td>
@@ -68,7 +68,7 @@ export default {
68 68
       form: {
69 69
         deviceCost: 0
70 70
       },
71
-      chooseDevice: [],
71
+      chooseDeviceList: [],
72 72
       openDevice: false,
73 73
     }
74 74
   },
@@ -81,7 +81,7 @@ export default {
81 81
     budgetId() {
82 82
       this.initForm()
83 83
     },
84
-    chooseDevice: {
84
+    chooseDeviceList: {
85 85
       handler(newVal) {
86 86
         this.$emit('chooseDevice', newVal)
87 87
       },
@@ -96,8 +96,8 @@ export default {
96 96
     initForm() {
97 97
       if (this.budgetId != '') {
98 98
         listBudgetDevice({ pageSize: 100, budgetId: this.budgetId }).then((res) => {
99
-          this.chooseDevice = res.rows;
100
-          for (let device of this.chooseDevice) {
99
+          this.chooseDeviceList = res.rows;
100
+          for (let device of this.chooseDeviceList) {
101 101
             device.brand = device.device.brand
102 102
             device.depreciation = device.device.dayCost
103 103
             device.name = device.device.name
@@ -109,22 +109,24 @@ export default {
109 109
     },
110 110
     initDeviceCost() {
111 111
       let deviceCost = 0;
112
-      for (let device of this.chooseDevice) {
112
+      for (let device of this.chooseDeviceList) {
113 113
         deviceCost = deviceCost + Number(device.amount);
114 114
       }
115 115
       this.form.deviceCost = deviceCost.toFixed(2)
116 116
     },
117 117
     getChooseDevice(val) {
118
-      this.chooseDevice = val;
118
+      this.chooseDeviceList = val;
119 119
       this.openDevice = false;
120
-      this.chooseDevice.depreciation = val.device.dayCost;
120
+      for (let v of val) {
121
+        v.depreciation = v.dayCost;
122
+      }
121 123
       this.recalculateCost(val, 'amount', 'deviceCost');
122 124
     },
123 125
     calculateDeviceTotal(device) {
124 126
       let total = Number(device.depreciation) * Number(device.days);
125 127
       total = isNaN(total) ? 0 : total
126 128
       this.$set(device, "amount", total.toFixed(2));
127
-      this.getCost("amount", "deviceCost", this.chooseDevice);
129
+      this.getCost("amount", "deviceCost", this.chooseDeviceList);
128 130
     },
129 131
     recalculateCost(arr, name, formName) {
130 132
       let sum = arr.reduce((accumulator, item) => {

+ 1
- 1
oa-ui/src/views/flowable/form/budget/staffTable.vue View File

@@ -314,7 +314,7 @@ export default {
314 314
       let total = 0;
315 315
       if (user.type === '外业') {
316 316
         // 外业人员计算方式
317
-        user.performance = 200 * Number(user.days) * Number(user.coefficient);
317
+        user.performance = (200 * Number(user.days) * Number(user.coefficient)).toFixed(2);
318 318
       }
319 319
       if (!user.dayCost) {
320 320
         user.dayCost = (parseFloat(((user.salary.salary + 1780) * 12) / 365) + user.socialSecurityUnit + user.houseFund).toFixed(2);

+ 1
- 2
oa-ui/src/views/flowable/form/components/conditionDisplay.vue View File

@@ -2,7 +2,7 @@
2 2
  * @Author: ysh
3 3
  * @Date: 2024-04-23 17:08:16
4 4
  * @LastEditors: Please set LastEditors
5
- * @LastEditTime: 2025-05-19 16:30:37
5
+ * @LastEditTime: 2025-05-27 16:07:26
6 6
 -->
7 7
 <template>
8 8
   <div>
@@ -31,7 +31,6 @@
31 31
       v-else-if="taskForm.procDefName == '项目结算'"></settle-form>
32 32
     <settle-other :key="'so' + taskForm.taskId" :taskForm="taskForm" :taskName="''" :disabled="true"
33 33
       v-else-if="taskForm.procDefName == '其他结算'"></settle-other>
34
-    <!-- <budget-in :key="'budget'+taskForm.taskId" :taskForm="taskForm" v-else-if="taskForm.procDefName == '项目预算'"></budget-in> -->
35 34
     <budget-tab :key="'budget' + taskForm.taskId" :taskForm="taskForm"
36 35
       v-else-if="taskForm.procDefName == '项目预算'"></budget-tab>
37 36
     <contract-form :key="'cj' + taskForm.taskId" :taskForm="taskForm" :taskName="''" :formDisabled="true"

+ 13
- 12
oa-ui/src/views/flowable/form/projectProcess/budgetTab.vue View File

@@ -1,8 +1,8 @@
1 1
 <!--
2 2
  * @Author: wrh
3 3
  * @Date: 2024-04-26 17:52:02
4
- * @LastEditors: wrh
5
- * @LastEditTime: 2024-04-29 14:32:50
4
+ * @LastEditors: Please set LastEditors
5
+ * @LastEditTime: 2025-05-27 16:06:46
6 6
 -->
7 7
 <template>
8 8
   <div class="app-container" v-loading="loading">
@@ -10,7 +10,8 @@
10 10
     <div v-if="haveBudget">
11 11
       <!-- <h3 class="text-center">{{ title }}</h3> -->
12 12
       <div>
13
-        <budget-info :taskForm="taskForm"></budget-info>
13
+        <budget-info :taskForm="taskForm" v-if="isOld"></budget-info>
14
+        <new-budget-info :taskForm="taskForm" v-else></new-budget-info>
14 15
       </div>
15 16
     </div>
16 17
   </div>
@@ -24,9 +25,11 @@ import { listBudgetSettle } from "@/api/oa/budget/budgetSettle";
24 25
 import { listBudgetStaff } from "@/api/oa/budget/budgetStaff";
25 26
 import { listProjectWork } from "@/api/oa/project/projectWork";
26 27
 import BudgetInfo from "../budget/budgetInfo.vue";
28
+import NewBudgetInfo from "../budget/adjust/newBudgetInfo.vue";
27 29
 export default {
28 30
   components: {
29 31
     BudgetInfo,
32
+    NewBudgetInfo,
30 33
   },
31 34
   props: {
32 35
     taskForm: Object,
@@ -46,8 +49,8 @@ export default {
46 49
       title: "",
47 50
       form: {},
48 51
       loading: true,
49
-      workList: [],
50
-      budgetId:''
52
+      budgetId: '',
53
+      isOld: false,
51 54
     };
52 55
   },
53 56
   mounted() {
@@ -64,13 +67,11 @@ export default {
64 67
         if (res.total != 0) {
65 68
           this.haveBudget = true;
66 69
           this.budgetId = res.rows[0].budgetId;
67
-          listProjectWork({projectId: projectId}).then(res => {
68
-            if (res.rows) {
69
-              this.workList = res.rows;
70
-            }
71
-            listBudgetSettle({budgetId: this.budgetId}).then(res => {
72
-            });
73
-          });
70
+          if (res.rows[0].project.projectNumber.substring(0, 4) >= 2025) {
71
+            this.isOld = false;
72
+          } else {
73
+            this.isOld = true;
74
+          }
74 75
         }
75 76
       });
76 77
     },

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

@@ -26,23 +26,10 @@
26 26
     </el-form>
27 27
 
28 28
     <el-row :gutter="10" class="mb8">
29
-      <!-- <el-col :span="1.5">
30
-        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
31
-          v-hasPermi="['oa:budget:add']">新增</el-button>
32
-      </el-col> -->
33
-      <!-- <el-col :span="1.5">
34
-        <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
35
-          v-hasPermi="['oa:budget:edit']">修改</el-button>
36
-      </el-col> -->
37
-      <!-- <el-col :span="1.5">
38
-        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
39
-          v-hasPermi="['oa:budget:remove']">删除</el-button>
40
-      </el-col> -->
41 29
       <el-col :span="1.5">
42 30
         <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
43 31
           v-hasPermi="['oa:budget:export']">导出</el-button>
44 32
       </el-col>
45
-      <!-- <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> -->
46 33
     </el-row>
47 34
 
48 35
     <el-table v-loading="loading" :data="budgetList" @selection-change="handleSelectionChange">
@@ -63,14 +50,20 @@
63 50
           {{ getUserName(scope.row.auditor) }}
64 51
         </template>
65 52
       </el-table-column>
53
+      <el-table-column label="是否核算" align="center" class-name="small-padding fixed-width">
54
+        <template slot-scope="scope">
55
+          <el-tag v-if="scope.row.isAdjust" type="success">是</el-tag>
56
+          <el-tag v-else type="danger">否</el-tag>
57
+        </template>
58
+      </el-table-column>
66 59
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
67 60
         <template slot-scope="scope">
68
-          <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)"
69
-            v-hasPermi="['oa:budget:query']">查看</el-button>
70
-          <!-- <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
71
-            v-hasPermi="['oa:budget:edit']">修改</el-button>
72
-          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
73
-            v-hasPermi="['oa:budget:remove']">删除</el-button> -->
61
+          <el-button size="mini" type="text" icon="el-icon-tickets" @click="handleNewView(scope.row)"
62
+            v-hasPermi="['oa:budget:query']">新版预算</el-button>
63
+          <el-button size="mini" type="text" icon="el-icon-document-remove" @click="handleView(scope.row)"
64
+            v-hasPermi="['oa:budget:query']">旧版预算</el-button>
65
+          <el-button size="mini" type="text" icon="el-icon-document-checked" @click="handleAdjust(scope.row)"
66
+            v-hasRole="['leader']" v-if="scope.row.isAdjust">查看核算</el-button>
74 67
         </template>
75 68
       </el-table-column>
76 69
     </el-table>
@@ -83,12 +76,14 @@
83 76
       <form-data :form="form" @close="open = false"></form-data>
84 77
     </el-dialog>
85 78
 
86
-    <el-dialog :title="title" :visible.sync="infoOpen" width="70%" append-to-body>
87
-      <budget-adjust :taskForm="taskForm" :taskName="''" :row="clickRow" v-show="isAdjust"></budget-adjust>
88
-      <div v-show="!isAdjust">
89
-        <budget-info :taskForm="taskForm" :taskName="''" v-show="isOld"></budget-info>
90
-        <new-budget-info :taskForm="taskForm" :taskName="''" v-show="!isOld"></new-budget-info>
91
-      </div>
79
+    <el-dialog title="新版预算" :visible.sync="newInfoOpen" width="70%" append-to-body>
80
+      <new-budget-info :taskForm="taskForm" :taskName="''"></new-budget-info>
81
+    </el-dialog>
82
+    <el-dialog title="旧版预算" :visible.sync="infoOpen" width="70%" append-to-body>
83
+      <budget-info :taskForm="taskForm" :taskName="''"></budget-info>
84
+    </el-dialog>
85
+    <el-dialog title="项目核算" :visible.sync="adjustOpen" width="70%" append-to-body>
86
+      <budget-adjust :taskForm="taskForm" :taskName="''" :row="clickRow"></budget-adjust>
92 87
     </el-dialog>
93 88
   </div>
94 89
 </template>
@@ -162,7 +157,9 @@ export default {
162 157
       queryType: '1',
163 158
       isOld: false,
164 159
       clickRow: {},
165
-      isAdjust: false
160
+      isAdjust: false,
161
+      adjustOpen: false,
162
+      newInfoOpen: false,
166 163
     };
167 164
   },
168 165
   created() {
@@ -172,8 +169,16 @@ export default {
172 169
     /** 查询cmc预算管理列表 */
173 170
     getList() {
174 171
       this.loading = true;
175
-      listBudget(this.queryParams).then(response => {
172
+      listBudget(this.queryParams).then(async response => {
176 173
         this.budgetList = response.rows;
174
+        for (let i of this.budgetList) {
175
+          let res = await listCheck({ budgetId: i.budgetId });
176
+          if (res.rows.length > 0) {
177
+            this.$set(i, 'isAdjust', true);
178
+          } else {
179
+            this.$set(i, 'isAdjust', false);
180
+          }
181
+        }
177 182
         this.total = response.total;
178 183
         this.loading = false;
179 184
       });
@@ -255,28 +260,23 @@ export default {
255 260
       this.title = "添加预算";
256 261
     },
257 262
     async handleView(row) {
258
-      this.isAdjust = this.$store.getters.roles.includes('leader') || this.$store.getters.roles.includes('finance')
259
-        || this.$store.getters.roles.includes('nfinance') || this.$store.getters.roles.includes('admin');
260
-      if (this.isAdjust) {
261
-        let res = await listCheck({ budgetId: row.budgetId });
262
-        if (res.rows.length > 0) {
263
-          this.taskForm.formId = res.rows[0].checkId;
264
-        } else {
265
-          this.taskForm.formId = row.projectId;
266
-          this.isAdjust = false;
267
-        }
268
-      } else {
269
-        this.taskForm.formId = row.projectId;
270
-      }
271 263
       this.clickRow = row;
272
-      let old = Number(row.project.projectNumber.substring(0, 4));
273
-      if (old >= 2025) {
274
-        this.isOld = false;
275
-      } else {
276
-        this.isOld = true;
277
-      }
264
+      this.taskForm.formId = row.projectId;
278 265
       this.infoOpen = true;
279 266
     },
267
+    handleNewView(row) {
268
+      this.taskForm.formId = row.projectId;
269
+      this.clickRow = row;
270
+      this.newInfoOpen = true;
271
+    },
272
+    async handleAdjust(row) {
273
+      let res = await listCheck({ budgetId: row.budgetId });
274
+      if (res.rows.length > 0) {
275
+        this.taskForm.formId = res.rows[0].checkId;
276
+      }
277
+      this.clickRow = row;
278
+      this.adjustOpen = true;
279
+    },
280 280
     /** 修改按钮操作 */
281 281
     handleUpdate(row) {
282 282
       this.reset();

Loading…
Cancel
Save