Bläddra i källkod

perf,feat: 完成人事绩效模块多页面功能迭代与接口优化

1.  新增部门职能部门筛选表单项与绩效用户列表接口
2.  重构月度考核API参数传递方式,新增非干部考核详情与自动生成接口
3.  重写绩效汇总页面API与表格图表逻辑,适配新后端接口
4.  优化非干部月度考核页面表单与交互逻辑,修复ID绑定问题
huoyi 1 månad sedan
förälder
incheckning
5a12523a61

+ 23 - 8
src/api/performance/monthlyAssess.js

@@ -10,11 +10,11 @@ export function listCadreAssessment(query) {
10
 }
10
 }
11
 
11
 
12
 // 生成本月考核数据
12
 // 生成本月考核数据
13
-export function generateCadreAssessment(params) {
13
+export function generateCadreAssessment(data) {
14
   return request({
14
   return request({
15
     url: '/personnel/cadre-assessment/generate',
15
     url: '/personnel/cadre-assessment/generate',
16
     method: 'post',
16
     method: 'post',
17
-    params: params
17
+    data: data
18
   })
18
   })
19
 }
19
 }
20
 
20
 
@@ -27,19 +27,19 @@ export function listNonCadreAssessment(query) {
27
   })
27
   })
28
 }
28
 }
29
 //新增非干部月度考核
29
 //新增非干部月度考核
30
-export function addNonCadreAssessment(params) {
30
+export function addNonCadreAssessment(data) {
31
   return request({
31
   return request({
32
     url: '/personnel/assessment',
32
     url: '/personnel/assessment',
33
     method: 'post',
33
     method: 'post',
34
-    params: params
34
+    data: data
35
   })
35
   })
36
 }
36
 }
37
 //修改非干部月度考核
37
 //修改非干部月度考核
38
-export function updateNonCadreAssessment(params) {
38
+export function updateNonCadreAssessment(data) {
39
   return request({
39
   return request({
40
     url: '/personnel/assessment',
40
     url: '/personnel/assessment',
41
     method: 'put',
41
     method: 'put',
42
-    params: params
42
+    data: data
43
   })
43
   })
44
 }
44
 }
45
 //删除非干部月度考核
45
 //删除非干部月度考核
@@ -50,10 +50,25 @@ export function deleteNonCadreAssessment(ids) {
50
   })
50
   })
51
 }
51
 }
52
 //导出非干部月度考核列表
52
 //导出非干部月度考核列表
53
-export function exportNonCadreAssessment(params) {
53
+export function exportNonCadreAssessment(data) {
54
   return request({
54
   return request({
55
     url: '/personnel/assessment/export',
55
     url: '/personnel/assessment/export',
56
     method: 'post',
56
     method: 'post',
57
-    params: params
57
+    data: data
58
+  })
59
+}
60
+//获取非干部月度考核详细信息
61
+export function getNonCadreAssessment(id) {
62
+  return request({
63
+    url: `/personnel/assessment/${id}`,
64
+    method: 'get'
65
+  })
66
+}
67
+
68
+//自动生成指定月份非干部月度考核数据
69
+export function generateNonCadreAssessment(query) {
70
+  return request({
71
+    url: `/personnel/assessment/autoGenerate/${query.month}`,
72
+    method: 'get',
58
   })
73
   })
59
 }
74
 }

+ 101 - 8
src/api/performance/monthlyAssessSum.js

@@ -1,20 +1,113 @@
1
 import request from '@/utils/request'
1
 import request from '@/utils/request'
2
 
2
 
3
-// 获取非干部月度考核汇总数据
4
-export function getNonCadreMonthlyAssessSummary(query) {
3
+export function getScoreDistribution(query) {
5
   return request({
4
   return request({
6
-    url: '/performance/non-cadre-monthly-assess-summary',
5
+    url: '/personnel/non-cadre-assessment/score-summary/score-distribution',
7
     method: 'get',
6
     method: 'get',
8
     params: query
7
     params: query
9
   })
8
   })
10
 }
9
 }
11
 
10
 
12
-// 导出非干部月度考核汇总数据
13
-export function exportNonCadreMonthlyAssessSummary(query) {
11
+export function getDeptParticipation(query) {
14
   return request({
12
   return request({
15
-    url: '/performance/non-cadre-monthly-assess-summary/export',
13
+    url: '/personnel/non-cadre-assessment/score-summary/dept-participation',
16
     method: 'get',
14
     method: 'get',
17
-    params: query,
18
-    responseType: 'blob'
15
+    params: query
16
+  })
17
+}
18
+
19
+export function getDeptScoreDistribution(query) {
20
+  return request({
21
+    url: '/personnel/non-cadre-assessment/score-summary/dept-score-distribution',
22
+    method: 'get',
23
+    params: query
24
+  })
25
+}
26
+
27
+export function getAssessmentSummary(query) {
28
+  return request({
29
+    url: '/personnel/non-cadre-assessment/score-summary/assessment-summary',
30
+    method: 'get',
31
+    params: query
32
+  })
33
+}
34
+
35
+export function getActualImprovementDistribution(query) {
36
+  return request({
37
+    url: '/personnel/non-cadre-assessment/score-summary/actual-improvement-distribution',
38
+    method: 'get',
39
+    params: query
40
+  })
41
+}
42
+
43
+export function getActualIncompetentDistribution(query) {
44
+  return request({
45
+    url: '/personnel/non-cadre-assessment/score-summary/actual-incompetent-distribution',
46
+    method: 'get',
47
+    params: query
48
+  })
49
+}
50
+
51
+export function getAssessmentTeamImprovementDistribution(query) {
52
+  return request({
53
+    url: '/personnel/non-cadre-assessment/score-summary/assessment-team-improvement-distribution',
54
+    method: 'get',
55
+    params: query
56
+  })
57
+}
58
+
59
+export function getAssessmentTeamIncompetentDistribution(query) {
60
+  return request({
61
+    url: '/personnel/non-cadre-assessment/score-summary/assessment-team-incompetent-distribution',
62
+    method: 'get',
63
+    params: query
64
+  })
65
+}
66
+
67
+export function getDeptAssessmentTeamStatistics(query) {
68
+  return request({
69
+    url: '/personnel/non-cadre-assessment/score-summary/dept-assessment-team-statistics',
70
+    method: 'get',
71
+    params: query
72
+  })
73
+}
74
+
75
+export function getBrigadeImprovementDistribution(query) {
76
+  return request({
77
+    url: '/personnel/non-cadre-assessment/score-summary/brigade-improvement-distribution',
78
+    method: 'get',
79
+    params: query
80
+  })
81
+}
82
+
83
+export function getBrigadeIncompetentDistribution(query) {
84
+  return request({
85
+    url: '/personnel/non-cadre-assessment/score-summary/brigade-incompetent-distribution',
86
+    method: 'get',
87
+    params: query
88
+  })
89
+}
90
+
91
+export function getFunctionalDeptSummary(query) {
92
+  return request({
93
+    url: '/personnel/non-cadre-assessment/score-summary/functional-dept-summary',
94
+    method: 'get',
95
+    params: query
96
+  })
97
+}
98
+
99
+export function getFunctionalDeptPersonnelDistribution(query) {
100
+  return request({
101
+    url: '/personnel/non-cadre-assessment/score-summary/functional-dept-personnel-distribution',
102
+    method: 'get',
103
+    params: query
104
+  })
105
+}
106
+
107
+export function getFunctionalDeptDistributionPie(query) {
108
+  return request({
109
+    url: '/personnel/non-cadre-assessment/score-summary/functional-dept-distribution-pie',
110
+    method: 'get',
111
+    params: query
19
   })
112
   })
20
 }
113
 }

+ 8 - 0
src/api/system/user.js

@@ -158,4 +158,12 @@ export function selectUserLeaderListByCondition(data) {
158
     method: 'post',
158
     method: 'post',
159
     data: data
159
     data: data
160
   })
160
   })
161
+}
162
+//查询人事绩效用户列表
163
+export function listUserPerformance(data) {
164
+  return request({
165
+    url: '/system/user/selectPersonnelUserList',
166
+    method: 'post',
167
+    data: data
168
+  })
161
 }
169
 }

+ 268 - 126
src/views/performanceManage/monthlyAssess/index.vue

@@ -170,22 +170,23 @@
170
 
170
 
171
 
171
 
172
     <!-- 编辑/新增弹窗 -->
172
     <!-- 编辑/新增弹窗 -->
173
-    <el-dialog :title="dialog.title" v-model="dialog.visible" width="80%" :close-on-click-modal="false">
173
+    <el-dialog :title="dialog.title" v-model="dialog.visible" width="80%" :close-on-click-modal="false"
174
+      destroy-on-close>
174
       <!-- 非干部表单 -->
175
       <!-- 非干部表单 -->
175
       <el-form v-if="dialog.type === 'non-cadre'" :model="nonCadreForm" ref="formRef" :rules="nonCadreRules"
176
       <el-form v-if="dialog.type === 'non-cadre'" :model="nonCadreForm" ref="formRef" :rules="nonCadreRules"
176
-        label-width="180px" class="form-container">
177
+        label-width="380px" class="form-container">
177
         <!-- 第一部分:基础信息 -->
178
         <!-- 第一部分:基础信息 -->
178
         <el-row :gutter="20">
179
         <el-row :gutter="20">
179
           <el-col :span="8">
180
           <el-col :span="8">
180
-            <el-form-item label="姓名" prop="userName">
181
-              <el-select v-model="nonCadreForm.userName" placeholder="请选择姓名" style="width: 100%" clearable filterable
181
+            <el-form-item label="姓名" prop="userId" label-width="100px">
182
+              <el-select v-model="nonCadreForm.userId" placeholder="请选择姓名" style="width: 100%" clearable filterable
182
                 @change="handleUserChange">
183
                 @change="handleUserChange">
183
-                <el-option v-for="user in userList" :key="user.userId" :label="user.userName" :value="user.userName" />
184
+                <el-option v-for="user in userList" :key="user.userId" :label="user.nickName" :value="user.userId" />
184
               </el-select>
185
               </el-select>
185
             </el-form-item>
186
             </el-form-item>
186
           </el-col>
187
           </el-col>
187
           <el-col :span="8">
188
           <el-col :span="8">
188
-            <el-form-item label="考核月份" prop="assessmentMonth">
189
+            <el-form-item label="考核月份" prop="assessmentMonth" label-width="100px">
189
               <el-date-picker v-model="nonCadreForm.assessmentMonth" type="month" placeholder="请选择考核月份"
190
               <el-date-picker v-model="nonCadreForm.assessmentMonth" type="month" placeholder="请选择考核月份"
190
                 value-format="YYYY-MM" style="width: 100%" />
191
                 value-format="YYYY-MM" style="width: 100%" />
191
             </el-form-item>
192
             </el-form-item>
@@ -201,23 +202,22 @@
201
 
202
 
202
         <el-row :gutter="20">
203
         <el-row :gutter="20">
203
           <el-col :span="8">
204
           <el-col :span="8">
204
-            <el-form-item label="用工形式" prop="employmentType">
205
+            <el-form-item label="用工形式" prop="employmentType" label-width="100px">
205
               <el-select v-model="nonCadreForm.employmentType" placeholder="请选择用工形式" style="width: 100%" disabled>
206
               <el-select v-model="nonCadreForm.employmentType" placeholder="请选择用工形式" style="width: 100%" disabled>
206
                 <el-option v-for="item in employment_type" :key="item.value" :label="item.label" :value="item.value" />
207
                 <el-option v-for="item in employment_type" :key="item.value" :label="item.label" :value="item.value" />
207
               </el-select>
208
               </el-select>
208
             </el-form-item>
209
             </el-form-item>
209
           </el-col>
210
           </el-col>
210
           <el-col :span="8">
211
           <el-col :span="8">
211
-            <el-form-item label="角色" prop="roleName">
212
+            <el-form-item label="角色" prop="roleName" label-width="100px">
212
               <el-input v-model="nonCadreForm.roleName" disabled placeholder="角色" />
213
               <el-input v-model="nonCadreForm.roleName" disabled placeholder="角色" />
213
             </el-form-item>
214
             </el-form-item>
214
           </el-col>
215
           </el-col>
215
           <el-col :span="8">
216
           <el-col :span="8">
216
-            <el-form-item label="分管班组长" prop="deputyTeamLeaderName">
217
-              <el-select v-model="nonCadreForm.deputyTeamLeaderName" placeholder="请选择分管班组长" style="width: 100%"
218
-                clearable>
219
-                <el-option v-for="leader in teamLeaderOptions" :key="leader.userId" :label="leader.userName"
220
-                  :value="leader.userName" />
217
+            <el-form-item label="分管班组长" prop="deputyTeamLeaderId" label-width="100px">
218
+              <el-select v-model="nonCadreForm.deputyTeamLeaderId" placeholder="请选择分管班组长" style="width: 100%" clearable>
219
+                <el-option v-for="leader in teamLeaderOptions" :key="leader.userId" :label="leader.nickName"
220
+                  :value="leader.userId" />
221
               </el-select>
221
               </el-select>
222
             </el-form-item>
222
             </el-form-item>
223
           </el-col>
223
           </el-col>
@@ -227,28 +227,30 @@
227
 
227
 
228
         <el-row :gutter="20">
228
         <el-row :gutter="20">
229
           <el-col :span="8">
229
           <el-col :span="8">
230
-            <el-form-item label="分管主管" prop="deputySupervisorName">
231
-              <el-select v-model="nonCadreForm.deputySupervisorName" placeholder="请选择分管主管" style="width: 100%"
232
-                clearable>
233
-                <el-option v-for="supervisor in supervisorOptions" :key="supervisor.userId" :label="supervisor.userName"
234
-                  :value="supervisor.userName" />
230
+            <el-form-item label="分管主管" prop="deputySupervisorId" label-width="100px">
231
+              <el-select v-model="nonCadreForm.deputySupervisorId" placeholder="请选择分管主管" style="width: 100%" clearable>
232
+                <el-option v-for="supervisor in supervisorOptions" :key="supervisor.userId" :label="supervisor.nickName"
233
+                  :value="supervisor.userId" />
235
               </el-select>
234
               </el-select>
236
             </el-form-item>
235
             </el-form-item>
237
           </el-col>
236
           </el-col>
238
           <el-col :span="8">
237
           <el-col :span="8">
239
-            <el-form-item label="分管经理" prop="deputyManagerName">
240
-              <el-input v-model="nonCadreForm.deputyManagerName" placeholder="请输入分管经理" />
238
+            <el-form-item label="分管经理" prop="deputyManagerId" label-width="100px">
239
+              <el-select v-model="nonCadreForm.deputyManagerId" placeholder="请选择分管经理" style="width: 100%" clearable>
240
+                <el-option v-for="manager in managerOptions" :key="manager.userId" :label="manager.nickName"
241
+                  :value="manager.userId" />
242
+              </el-select>
241
             </el-form-item>
243
             </el-form-item>
242
           </el-col>
244
           </el-col>
243
           <el-col :span="8">
245
           <el-col :span="8">
244
-            <el-form-item label="考核组" prop="assessmentTeam">
246
+            <el-form-item label="考核组" prop="assessmentTeam" label-width="100px">
245
               <el-select v-model="nonCadreForm.assessmentTeam" placeholder="请选择考核组" style="width: 100%">
247
               <el-select v-model="nonCadreForm.assessmentTeam" placeholder="请选择考核组" style="width: 100%">
246
                 <el-option v-for="item in assessment_team" :key="item.value" :label="item.label" :value="item.value" />
248
                 <el-option v-for="item in assessment_team" :key="item.value" :label="item.label" :value="item.value" />
247
               </el-select>
249
               </el-select>
248
             </el-form-item>
250
             </el-form-item>
249
           </el-col>
251
           </el-col>
250
           <el-col :span="8">
252
           <el-col :span="8">
251
-            <el-form-item label="岗位" prop="post">
253
+            <el-form-item label="岗位" prop="post" label-width="100px">
252
               <el-select v-model="nonCadreForm.post" placeholder="请选择岗位" style="width: 100%">
254
               <el-select v-model="nonCadreForm.post" placeholder="请选择岗位" style="width: 100%">
253
                 <el-option v-for="item in post" :key="item.value" :label="item.label" :value="item.value" />
255
                 <el-option v-for="item in post" :key="item.value" :label="item.label" :value="item.value" />
254
               </el-select>
256
               </el-select>
@@ -262,11 +264,11 @@
262
           <div v-for="(group, groupIndex) in nonCadreForm.indicatorGroups" :key="groupIndex" class="indicator-group">
264
           <div v-for="(group, groupIndex) in nonCadreForm.indicatorGroups" :key="groupIndex" class="indicator-group">
263
             <div class="indicator-group-title">{{ group.title }}</div>
265
             <div class="indicator-group-title">{{ group.title }}</div>
264
             <div v-for="(item, itemIndex) in group.items" :key="itemIndex" class="indicator-item">
266
             <div v-for="(item, itemIndex) in group.items" :key="itemIndex" class="indicator-item">
265
-              <div class="indicator-name">{{ item.name }}</div>
267
+              <div class="indicator-name">{{ item.indicatorName }}</div>
266
               <div class="indicator-value">{{ item.score }}/次</div>
268
               <div class="indicator-value">{{ item.score }}/次</div>
267
-              <div class="indicator-count">{{ item.count }}次</div>
268
-              <div class="indicator-source">{{ item.source }}</div>
269
-              <div class="indicator-total">{{ item.total }}</div>
269
+              <div class="indicator-count">{{ item.occurCount }}次</div>
270
+              <div class="indicator-qcDeptType">{{ item.qcDeptType }}</div>
271
+              <div class="indicator-total">{{ item.scoreResult }}</div>
270
               <div class="indicator-actions">
272
               <div class="indicator-actions">
271
                 <el-button type="primary" link icon="Edit" @click="editIndicator(groupIndex, itemIndex)"></el-button>
273
                 <el-button type="primary" link icon="Edit" @click="editIndicator(groupIndex, itemIndex)"></el-button>
272
                 <el-button type="danger" link icon="Delete" @click="deleteIndicator(groupIndex, itemIndex)"></el-button>
274
                 <el-button type="danger" link icon="Delete" @click="deleteIndicator(groupIndex, itemIndex)"></el-button>
@@ -286,8 +288,9 @@
286
             </el-col>
288
             </el-col>
287
             <el-col :span="12">
289
             <el-col :span="12">
288
               <el-form-item label="红线指标依据">
290
               <el-form-item label="红线指标依据">
289
-                <span class="detail-link" @click="showDetailModal('红线指标依据', nonCadreForm.redLineBasis)">
290
-                  {{ nonCadreForm.redLineBasis || '查看详情' }}
291
+                <span class="detail-link"
292
+                  @click="showDetailModal('红线指标依据', formatAccordList(nonCadreForm.redLineIndexAccordList))">
293
+                  {{ formatAccordList(nonCadreForm.redLineIndexAccordList) || '查看详情' }}
291
                 </span>
294
                 </span>
292
               </el-form-item>
295
               </el-form-item>
293
             </el-col>
296
             </el-col>
@@ -301,8 +304,9 @@
301
             </el-col>
304
             </el-col>
302
             <el-col :span="12">
305
             <el-col :span="12">
303
               <el-form-item label="核心指标依据">
306
               <el-form-item label="核心指标依据">
304
-                <span class="detail-link" @click="showDetailModal('核心指标依据', nonCadreForm.coreIndicatorBasis)">
305
-                  {{ nonCadreForm.coreIndicatorBasis || '查看详情' }}
307
+                <span class="detail-link"
308
+                  @click="showDetailModal('核心指标依据', formatAccordList(nonCadreForm.coreIndexAccordList))">
309
+                  {{ formatAccordList(nonCadreForm.coreIndexAccordList) || '查看详情' }}
306
                 </span>
310
                 </span>
307
               </el-form-item>
311
               </el-form-item>
308
             </el-col>
312
             </el-col>
@@ -316,8 +320,9 @@
316
             </el-col>
320
             </el-col>
317
             <el-col :span="12">
321
             <el-col :span="12">
318
               <el-form-item label="其他指标中的安全指标(仅含SOC/站品控检查扣分)依据">
322
               <el-form-item label="其他指标中的安全指标(仅含SOC/站品控检查扣分)依据">
319
-                <span class="detail-link" @click="showDetailModal('其他指标中的安全指标依据', nonCadreForm.safetyWithSocBasis)">
320
-                  {{ nonCadreForm.safetyWithSocBasis || '查看详情' }}
323
+                <span class="detail-link"
324
+                  @click="showDetailModal('其他指标中的安全指标依据', formatAccordList(nonCadreForm.otherIndexSafetyScoreWithSocStationQcAccordList))">
325
+                  {{ formatAccordList(nonCadreForm.otherIndexSafetyScoreWithSocStationQcAccordList) || '查看详情' }}
321
                 </span>
326
                 </span>
322
               </el-form-item>
327
               </el-form-item>
323
             </el-col>
328
             </el-col>
@@ -331,8 +336,9 @@
331
             </el-col>
336
             </el-col>
332
             <el-col :span="12">
337
             <el-col :span="12">
333
               <el-form-item label="其他指标中的非安全指标依据">
338
               <el-form-item label="其他指标中的非安全指标依据">
334
-                <span class="detail-link" @click="showDetailModal('其他指标中的非安全指标依据', nonCadreForm.nonSafetyIndicatorBasis)">
335
-                  {{ nonCadreForm.nonSafetyIndicatorBasis || '查看详情' }}
339
+                <span class="detail-link"
340
+                  @click="showDetailModal('其他指标中的非安全指标依据', formatAccordList(nonCadreForm.otherIndexNonSafetyAccordList))">
341
+                  {{ formatAccordList(nonCadreForm.otherIndexNonSafetyAccordList) || '查看详情' }}
336
                 </span>
342
                 </span>
337
               </el-form-item>
343
               </el-form-item>
338
             </el-col>
344
             </el-col>
@@ -346,8 +352,9 @@
346
             </el-col>
352
             </el-col>
347
             <el-col :span="12">
353
             <el-col :span="12">
348
               <el-form-item label="SOC/站品控检查的涉及核心、安全指标扣分依据">
354
               <el-form-item label="SOC/站品控检查的涉及核心、安全指标扣分依据">
349
-                <span class="detail-link" @click="showDetailModal('SOC/站品控检查的涉及核心、安全指标扣分依据', nonCadreForm.socSafetyCoreDeductionBasis)">
350
-                  {{ nonCadreForm.socSafetyCoreDeductionBasis || '查看详情' }}
355
+                <span class="detail-link"
356
+                  @click="showDetailModal('SOC/站品控检查的涉及核心、安全指标扣分依据', formatAccordList(nonCadreForm.socStationQcInvolvedCoreSafetyAccordList))">
357
+                  {{ formatAccordList(nonCadreForm.socStationQcInvolvedCoreSafetyAccordList) || '查看详情' }}
351
                 </span>
358
                 </span>
352
               </el-form-item>
359
               </el-form-item>
353
             </el-col>
360
             </el-col>
@@ -382,15 +389,17 @@
382
           <el-row :gutter="20">
389
           <el-row :gutter="20">
383
             <el-col :span="12">
390
             <el-col :span="12">
384
               <el-form-item label="奖励明细">
391
               <el-form-item label="奖励明细">
385
-                <span class="detail-link" @click="showDetailModal('奖励明细', nonCadreForm.rewardDetailsSummary)">
386
-                  {{ nonCadreForm.rewardDetailsSummary || '查看详情' }}
392
+                <span class="detail-link"
393
+                  @click="showDetailModal('奖励明细', formatAccordList(nonCadreForm.rewardAccordList))">
394
+                  {{ formatAccordList(nonCadreForm.rewardAccordList) || '查看详情' }}
387
                 </span>
395
                 </span>
388
               </el-form-item>
396
               </el-form-item>
389
             </el-col>
397
             </el-col>
390
             <el-col :span="12">
398
             <el-col :span="12">
391
               <el-form-item label="惩罚明细">
399
               <el-form-item label="惩罚明细">
392
-                <span class="detail-link" @click="showDetailModal('惩罚明细', nonCadreForm.penaltyDetailsSummary)">
393
-                  {{ nonCadreForm.penaltyDetailsSummary || '查看详情' }}
400
+                <span class="detail-link"
401
+                  @click="showDetailModal('惩罚明细', formatAccordList(nonCadreForm.punishmentAccordList))">
402
+                  {{ formatAccordList(nonCadreForm.punishmentAccordList) || '查看详情' }}
394
                 </span>
403
                 </span>
395
               </el-form-item>
404
               </el-form-item>
396
             </el-col>
405
             </el-col>
@@ -473,13 +482,13 @@
473
     <!-- 第二个模态框:添加/编辑扣分指标 -->
482
     <!-- 第二个模态框:添加/编辑扣分指标 -->
474
     <el-dialog :title="indicatorDialog.title" v-model="indicatorDialog.visible" width="60%">
483
     <el-dialog :title="indicatorDialog.title" v-model="indicatorDialog.visible" width="60%">
475
       <el-form label-width="150px" class="indicator-form">
484
       <el-form label-width="150px" class="indicator-form">
476
-        <el-form-item label="指标名称">
485
+        <el-form-item label="指标名称" prop="indicatorId">
477
           <div style="display: flex; align-items: center; gap: 10px; width: 100%;">
486
           <div style="display: flex; align-items: center; gap: 10px; width: 100%;">
478
-            <el-select v-model="indicatorDialog.form.name" placeholder="搜索指标名称" filterable remote reserve-keyword
487
+            <el-select v-model="indicatorDialog.form.indicatorId" placeholder="搜索指标名称" filterable remote reserve-keyword
479
               :remote-method="searchIndicators" :loading="indicatorDialog.loading" style="flex: 1;"
488
               :remote-method="searchIndicators" :loading="indicatorDialog.loading" style="flex: 1;"
480
               @change="onIndicatorNameChange">
489
               @change="onIndicatorNameChange">
481
               <el-option v-for="item in indicatorDialog.indicatorOptions" :key="item.id" :label="item.name"
490
               <el-option v-for="item in indicatorDialog.indicatorOptions" :key="item.id" :label="item.name"
482
-                :value="item.name" />
491
+                :value="item.id" />
483
             </el-select>
492
             </el-select>
484
           </div>
493
           </div>
485
         </el-form-item>
494
         </el-form-item>
@@ -493,14 +502,14 @@
493
 
502
 
494
         <el-form-item label="发生次数">
503
         <el-form-item label="发生次数">
495
           <div style="display: flex; align-items: center; gap: 10px;">
504
           <div style="display: flex; align-items: center; gap: 10px;">
496
-            <el-input-number v-model="indicatorDialog.form.count" :min="1" style="width: 200px;"
505
+            <el-input-number v-model="indicatorDialog.form.occurCount" :min="1" style="width: 200px;"
497
               @change="updateTotal" />
506
               @change="updateTotal" />
498
 
507
 
499
           </div>
508
           </div>
500
         </el-form-item>
509
         </el-form-item>
501
 
510
 
502
         <el-form-item label="检查部门">
511
         <el-form-item label="检查部门">
503
-          <el-select v-model="indicatorDialog.form.source" placeholder="请选择" style="width: 200px;">
512
+          <el-select v-model="indicatorDialog.form.qcDeptType" placeholder="请选择" style="width: 200px;">
504
             <el-option v-for="item in base_performance_indicator_qc_dept_type" :key="item.value" :label="item.label"
513
             <el-option v-for="item in base_performance_indicator_qc_dept_type" :key="item.value" :label="item.label"
505
               :value="item.value" />
514
               :value="item.value" />
506
           </el-select>
515
           </el-select>
@@ -540,7 +549,7 @@
540
     <!-- 详情模态框 -->
549
     <!-- 详情模态框 -->
541
     <el-dialog :title="detailModal.title" v-model="detailModal.visible" width="60%">
550
     <el-dialog :title="detailModal.title" v-model="detailModal.visible" width="60%">
542
       <div class="detail-content">
551
       <div class="detail-content">
543
-        {{ detailModal.content || '暂无内容' }}
552
+        {{ detailModal?.content || '暂无内容' }}
544
       </div>
553
       </div>
545
       <template #footer>
554
       <template #footer>
546
         <div class="dialog-footer">
555
         <div class="dialog-footer">
@@ -556,8 +565,8 @@ import { ref, reactive, onMounted, getCurrentInstance, watch } from 'vue'
556
 import { ElMessage, ElMessageBox } from 'element-plus'
565
 import { ElMessage, ElMessageBox } from 'element-plus'
557
 
566
 
558
 // API导入(需要根据实际API路径调整)
567
 // API导入(需要根据实际API路径调整)
559
-import { listCadreAssessment, generateCadreAssessment, listNonCadreAssessment, addNonCadreAssessment, updateNonCadreAssessment, deleteNonCadreAssessment, exportNonCadreAssessment } from '@/api/performance/monthlyAssess.js'
560
-import { selectUserLeaderListByCondition, listAllUser } from '@/api/system/user.js'
568
+import { listCadreAssessment, generateCadreAssessment, listNonCadreAssessment, addNonCadreAssessment, updateNonCadreAssessment, deleteNonCadreAssessment, exportNonCadreAssessment, generateNonCadreAssessment, getNonCadreAssessment } from '@/api/performance/monthlyAssess.js'
569
+import { selectUserLeaderListByCondition, listUserPerformance } from '@/api/system/user.js'
561
 import { listIndicator } from '@/api/system/classificationAssess.js'
570
 import { listIndicator } from '@/api/system/classificationAssess.js'
562
 
571
 
563
 const { proxy } = getCurrentInstance()
572
 const { proxy } = getCurrentInstance()
@@ -575,6 +584,8 @@ watch(() => currentTab.value, () => {
575
   getList()
584
   getList()
576
 })
585
 })
577
 
586
 
587
+
588
+
578
 // 查询参数
589
 // 查询参数
579
 const queryParams = reactive({
590
 const queryParams = reactive({
580
   pageNum: 1,
591
   pageNum: 1,
@@ -583,18 +594,24 @@ const queryParams = reactive({
583
   assessmentMonth: ''
594
   assessmentMonth: ''
584
 })
595
 })
585
 
596
 
586
-// 非干部表单数据
587
-const nonCadreForm = reactive({
597
+const currentMonthDefault = `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}`
598
+
599
+const getEmptyNonCadreForm = () => ({
600
+  id: '',
588
   userId: '',
601
   userId: '',
589
   userName: '',
602
   userName: '',
603
+  roleKey: '',
604
+  roleId: '',
605
+  roleName: '',
590
   employmentType: '',
606
   employmentType: '',
591
   post: '',
607
   post: '',
592
-  assessmentMonth: '',
608
+  assessmentMonth: currentMonthDefault,
593
   assessmentTeam: '',
609
   assessmentTeam: '',
594
   deputyTeamLeaderId: '',
610
   deputyTeamLeaderId: '',
595
   deputyTeamLeaderName: '',
611
   deputyTeamLeaderName: '',
596
   deputySupervisorId: '',
612
   deputySupervisorId: '',
597
   deputySupervisorName: '',
613
   deputySupervisorName: '',
614
+  deputyManagerId: '',
598
   deputyManagerName: '',
615
   deputyManagerName: '',
599
   inChargeEmployeeCount: 0,
616
   inChargeEmployeeCount: 0,
600
   totalScore: 0,
617
   totalScore: 0,
@@ -607,14 +624,64 @@ const nonCadreForm = reactive({
607
   punishmentAmount: 0,
624
   punishmentAmount: 0,
608
   assessmentRemark: '',
625
   assessmentRemark: '',
609
   applicationMethodRemark: '',
626
   applicationMethodRemark: '',
610
-  indicatorGroups: []
627
+  indicatorGroups: [],
628
+  redLineTriggerCount: '',
629
+  coreIndicatorScore: '',
630
+  safetyWithSocScore: '',
631
+  nonSafetyIndicatorScore: '',
632
+  socSafetyCoreDeduction: '',
633
+  nonCoreSafetyCoreDeduction: '',
634
+  averageDeduction: '',
635
+  rewardDetailsSummary: '',
636
+  penaltyDetailsSummary: '',
637
+  redLineIndexAccordList: [],
638
+  coreIndexAccordList: [],
639
+  otherIndexSafetyScoreWithSocStationQcAccordList: [],
640
+  otherIndexNonSafetyAccordList: [],
641
+  socStationQcInvolvedCoreSafetyAccordList: [],
642
+  rewardAccordList: [],
643
+  punishmentAccordList: []
611
 })
644
 })
612
 
645
 
646
+const nonCadreForm = reactive(getEmptyNonCadreForm())
647
+
648
+watch(() => nonCadreForm.assessmentMonth, (newVal) => {
649
+  if (newVal) {
650
+    const month = newVal.replace('-', '')
651
+    loadUserList(month)
652
+  }
653
+})
654
+
655
+watch(() => nonCadreForm.deputyTeamLeaderId, (newVal) => {
656
+  if (newVal) {
657
+    const leader = teamLeaderOptions.value.find(u => u.userId === newVal)
658
+    nonCadreForm.deputyTeamLeaderName = leader?.nickName || ''
659
+  } else {
660
+    nonCadreForm.deputyTeamLeaderName = ''
661
+  }
662
+})
663
+
664
+watch(() => nonCadreForm.deputySupervisorId, (newVal) => {
665
+  if (newVal) {
666
+    const supervisor = supervisorOptions.value.find(u => u.userId === newVal)
667
+    nonCadreForm.deputySupervisorName = supervisor?.nickName || ''
668
+  } else {
669
+    nonCadreForm.deputySupervisorName = ''
670
+  }
671
+})
672
+
673
+watch(() => nonCadreForm.deputyManagerId, (newVal) => {
674
+  if (newVal) {
675
+    const manager = managerOptions.value.find(u => u.userId === newVal)
676
+    nonCadreForm.deputyManagerName = manager?.nickName || ''
677
+  } else {
678
+    nonCadreForm.deputyManagerName = ''
679
+  }
680
+})
613
 
681
 
614
 
682
 
615
 function addIndicatorToGroup(item) {
683
 function addIndicatorToGroup(item) {
616
   const categoryName = item.categoryNameOne || '未分类'
684
   const categoryName = item.categoryNameOne || '未分类'
617
-
618
   let group = nonCadreForm.indicatorGroups.length == 0 ? null : nonCadreForm.indicatorGroups.find(g => g.title === categoryName);
685
   let group = nonCadreForm.indicatorGroups.length == 0 ? null : nonCadreForm.indicatorGroups.find(g => g.title === categoryName);
619
 
686
 
620
   if (!group) {
687
   if (!group) {
@@ -638,11 +705,12 @@ const indicatorDialog = reactive({
638
   loading: false,
705
   loading: false,
639
   indicatorOptions: [],
706
   indicatorOptions: [],
640
   form: {
707
   form: {
708
+    indicatorId: '',
641
     name: '',
709
     name: '',
642
-    score: -3,
643
-    count: 1,
644
-    source: '',
645
-    total: 0,
710
+    score: 0,
711
+    occurCount: 1,
712
+    qcDeptType: '',
713
+    scoreResult: 0,
646
     rewardDetails: '',
714
     rewardDetails: '',
647
     reward: 0,
715
     reward: 0,
648
     penaltyDetails: '',
716
     penaltyDetails: '',
@@ -668,24 +736,7 @@ async function searchIndicators(query) {
668
   }
736
   }
669
 }
737
 }
670
 
738
 
671
-// 干部表单数据
672
-const cadreForm = reactive({
673
-  employeeName: '',
674
-  position: '',
675
-  area: '',
676
-  assessmentMonth: '',
677
-  redLineDeduction: 0,
678
-  redLineExemption: '',
679
-  violationRankingDeduction: 0,
680
-  violationRankingExemption: '',
681
-  skillRankingDeduction: 0,
682
-  skillRankingExemption: '',
683
-  totalScore: 0,
684
-  assessmentResult: '',
685
-  applicationMethod: '',
686
-  assessmentResultRemark: '',
687
-  applicationMethodRemark: ''
688
-})
739
+
689
 
740
 
690
 // 弹窗配置
741
 // 弹窗配置
691
 const dialog = reactive({
742
 const dialog = reactive({
@@ -708,6 +759,16 @@ const showDetailModal = (title, content) => {
708
   detailModal.visible = true
759
   detailModal.visible = true
709
 }
760
 }
710
 
761
 
762
+const formatAccordList = (list) => {
763
+  if (!list || !Array.isArray(list) || list.length === 0) return ''
764
+  return list.map(item => {
765
+    const name = item.indicatorName || item.name || ''
766
+    const score = item.score !== undefined ? item.score : ''
767
+    const count = item.occurCount !== undefined ? item.occurCount : ''
768
+    return `${name} ${score}分 x ${count}次`
769
+  }).join('\n')
770
+}
771
+
711
 // 数据列表
772
 // 数据列表
712
 const nonCadreList = ref([])
773
 const nonCadreList = ref([])
713
 const cadreList = ref([])
774
 const cadreList = ref([])
@@ -715,22 +776,20 @@ const cadreList = ref([])
715
 const userList = ref([])
776
 const userList = ref([])
716
 const teamLeaderOptions = ref([])
777
 const teamLeaderOptions = ref([])
717
 const supervisorOptions = ref([])
778
 const supervisorOptions = ref([])
779
+const managerOptions = ref([])
718
 
780
 
719
 
781
 
720
 
782
 
721
 // 非干部表单验证规则
783
 // 非干部表单验证规则
722
 const nonCadreRules = {
784
 const nonCadreRules = {
723
-  userName: [{ required: true, message: '员工姓名不能为空', trigger: 'change' }],
724
-  employmentType: [{ required: true, message: '用工形式不能为空', trigger: 'change' }],
725
-  assessmentTeam: [{ required: true, message: '考核组不能为空', trigger: 'change' }],
726
-  assessmentMonth: [{ required: true, message: '考核月份不能为空', trigger: 'change' }]
785
+  userId: [{ required: true, message: '姓名不能为空', trigger: 'change' }]
727
 }
786
 }
728
 
787
 
729
 
788
 
730
 
789
 
731
-async function loadUserList() {
790
+async function loadUserList(month) {
732
   try {
791
   try {
733
-    const res = await listAllUser()
792
+    const res = await listUserPerformance({ month })
734
     userList.value = res.data || []
793
     userList.value = res.data || []
735
   } catch (error) {
794
   } catch (error) {
736
     console.error('获取员工列表失败:', error)
795
     console.error('获取员工列表失败:', error)
@@ -755,23 +814,52 @@ async function loadSupervisorOptions(userId) {
755
   }
814
   }
756
 }
815
 }
757
 
816
 
758
-async function handleUserChange(userName) {
759
-  if (!userName) {
817
+async function loadManagerOptions(userId) {
818
+  try {
819
+    const res = await selectUserLeaderListByCondition({ roleKeyList: ['jingli'], userId })
820
+    managerOptions.value = res.data || []
821
+  } catch (error) {
822
+    console.error('获取经理列表失败:', error)
823
+  }
824
+}
825
+
826
+async function handleUserChange(userId) {
827
+  if (!userId) {
760
     teamLeaderOptions.value = []
828
     teamLeaderOptions.value = []
761
     supervisorOptions.value = []
829
     supervisorOptions.value = []
830
+    managerOptions.value = []
831
+    nonCadreForm.deputyTeamLeaderId = ''
762
     nonCadreForm.deputyTeamLeaderName = ''
832
     nonCadreForm.deputyTeamLeaderName = ''
833
+    nonCadreForm.deputySupervisorId = ''
763
     nonCadreForm.deputySupervisorName = ''
834
     nonCadreForm.deputySupervisorName = ''
835
+    nonCadreForm.deputyManagerId = ''
836
+    nonCadreForm.deputyManagerName = ''
764
     return
837
     return
765
   }
838
   }
766
 
839
 
767
-  const user = userList.value.find(u => u.userName === userName)
768
-  if (user && user.userId) {
840
+  const user = userList.value.find(u => u.userId === userId)
841
+  if (user && user.nickName) {
769
     await Promise.all([
842
     await Promise.all([
770
       loadTeamLeaderOptions(user.userId),
843
       loadTeamLeaderOptions(user.userId),
771
-      loadSupervisorOptions(user.userId)
844
+      loadSupervisorOptions(user.userId),
845
+      loadManagerOptions(user.userId)
772
     ])
846
     ])
847
+    const role = user.roles && user.roles[0] || {}
848
+    nonCadreForm.userName = user.nickName
849
+    nonCadreForm.roleName = role?.roleName
850
+    nonCadreForm.roleKey = role?.roleKey
851
+    nonCadreForm.roleId = role?.roleId
852
+    nonCadreForm.employmentType = user.employmentType
853
+    nonCadreForm.post = user.post
854
+    nonCadreForm.assessmentTeam = user.assessmentTeam
855
+    nonCadreForm.assessmentTeamDesc = user.assessmentTeamDesc
856
+
857
+    nonCadreForm.deputyTeamLeaderId = ''
773
     nonCadreForm.deputyTeamLeaderName = ''
858
     nonCadreForm.deputyTeamLeaderName = ''
859
+    nonCadreForm.deputySupervisorId = ''
774
     nonCadreForm.deputySupervisorName = ''
860
     nonCadreForm.deputySupervisorName = ''
861
+    nonCadreForm.deputyManagerId = ''
862
+    nonCadreForm.deputyManagerName = ''
775
   }
863
   }
776
 }
864
 }
777
 
865
 
@@ -832,40 +920,67 @@ const handleAdd = () => {
832
   dialog.title = currentTab.value === 'non-cadre' ? '新增非干部月度考核' : '新增干部月度考核'
920
   dialog.title = currentTab.value === 'non-cadre' ? '新增非干部月度考核' : '新增干部月度考核'
833
 
921
 
834
   if (currentTab.value === 'non-cadre') {
922
   if (currentTab.value === 'non-cadre') {
835
-    loadUserList()
923
+    const emptyForm = getEmptyNonCadreForm()
924
+    Object.keys(emptyForm).forEach(key => {
925
+      nonCadreForm[key] = emptyForm[key]
926
+    })
927
+    const month = nonCadreForm.assessmentMonth.replace('-', '')
928
+    loadUserList(month)
836
     teamLeaderOptions.value = []
929
     teamLeaderOptions.value = []
837
     supervisorOptions.value = []
930
     supervisorOptions.value = []
838
-  }
839
-
840
-  // 重置表单数据
841
-  if (currentTab.value === 'non-cadre') {
842
-
843
-    nonCadreForm.indicatorGroups = []
931
+    managerOptions.value = []
844
   }
932
   }
845
 }
933
 }
846
 
934
 
847
 // 编辑
935
 // 编辑
848
-const handleEdit = (row, type) => {
936
+const handleEdit = async (row, type) => {
849
   dialog.visible = true
937
   dialog.visible = true
850
   dialog.type = type
938
   dialog.type = type
851
   dialog.title = '编辑非干部月度考核'
939
   dialog.title = '编辑非干部月度考核'
852
 
940
 
853
   if (type === 'non-cadre') {
941
   if (type === 'non-cadre') {
854
-    loadUserList().then(() => {
855
-      if (row.userName) {
856
-        loadTeamLeaderOptions(row.userId)
857
-        loadSupervisorOptions(row.userId)
858
-      }
859
-    })
860
-  }
861
-
862
-  // 填充表单数据
863
-  if (type === 'non-cadre') {
864
-    Object.keys(nonCadreForm).forEach(key => {
865
-      if (row[key] !== undefined) {
866
-        nonCadreForm[key] = row[key]
867
-      }
868
-    })
942
+    const month = nonCadreForm.assessmentMonth.replace('-', '')
943
+    loadUserList(month)
944
+    loadTeamLeaderOptions(row.userId)
945
+    loadSupervisorOptions(row.userId)
946
+    loadManagerOptions(row.userId)
947
+
948
+    try {
949
+      const res = await getNonCadreAssessment(row.id)
950
+
951
+      const detailList = res.data.personnelMonthlyAssessmentIndicatorDetailList || []
952
+      const indicatorGroupsMap = {}
953
+      detailList.forEach(item => {
954
+        const categoryKey = item.categoryCodeOne || item.categoryNameOne || '未分类'
955
+        if (!indicatorGroupsMap[categoryKey]) {
956
+          indicatorGroupsMap[categoryKey] = {
957
+            title: item.categoryNameOne || '未分类',
958
+            items: []
959
+          }
960
+        }
961
+        indicatorGroupsMap[categoryKey].items.push({
962
+          ...item
963
+        })
964
+      })
965
+      const indicatorGroups = Object.values(indicatorGroupsMap)
966
+
967
+      Object.keys(res.data).forEach(key => {
968
+        if (key === 'assessmentMonth' && res.data[key]) {
969
+          const val = res.data[key]
970
+          if (typeof val === 'string' && val.length === 6 && /^\d+$/.test(val)) {
971
+            nonCadreForm[key] = val.substring(0, 4) + '-' + val.substring(4, 6)
972
+          } else {
973
+            nonCadreForm[key] = val
974
+          }
975
+        } else if (key !== 'personnelMonthlyAssessmentIndicatorDetailList') {
976
+          nonCadreForm[key] = res.data[key]
977
+        }
978
+      })
979
+      nonCadreForm.indicatorGroups = indicatorGroups
980
+    } catch (error) {
981
+      console.error('获取详情失败:', error)
982
+      ElMessage.error('获取详情失败')
983
+    }
869
   }
984
   }
870
 }
985
 }
871
 
986
 
@@ -895,15 +1010,29 @@ const submitForm = async () => {
895
 
1010
 
896
   try {
1011
   try {
897
     if (dialog.type === 'non-cadre') {
1012
     if (dialog.type === 'non-cadre') {
1013
+      const submitData = { ...nonCadreForm }
1014
+
1015
+      if (submitData.assessmentMonth) {
1016
+        submitData.assessmentMonth = submitData.assessmentMonth.replace('-', '')
1017
+      }
1018
+
1019
+      if (submitData.indicatorGroups && submitData.indicatorGroups.length > 0) {
1020
+        submitData.personnelMonthlyAssessmentIndicatorDetailList = submitData.indicatorGroups.flatMap(group =>
1021
+          group.items.map(item => ({
1022
+            ...item
1023
+          }))
1024
+        )
1025
+        delete submitData.indicatorGroups
1026
+      }
1027
+
898
       if (dialog.title === '新增非干部月度考核') {
1028
       if (dialog.title === '新增非干部月度考核') {
899
-        await addNonCadreAssessment(nonCadreForm)
1029
+        await addNonCadreAssessment(submitData)
900
         ElMessage.success('新增成功')
1030
         ElMessage.success('新增成功')
901
       } else {
1031
       } else {
902
-        await updateNonCadreAssessment(nonCadreForm)
1032
+        await updateNonCadreAssessment(submitData)
903
         ElMessage.success('更新成功')
1033
         ElMessage.success('更新成功')
904
       }
1034
       }
905
     } else {
1035
     } else {
906
-      // 干部数据API(待实现)
907
       ElMessage.success('操作成功')
1036
       ElMessage.success('操作成功')
908
     }
1037
     }
909
 
1038
 
@@ -941,20 +1070,27 @@ const handleExport = async () => {
941
 // 生成本月考核表
1070
 // 生成本月考核表
942
 const generateMonthlyAssessment = async () => {
1071
 const generateMonthlyAssessment = async () => {
943
   try {
1072
   try {
944
-    ElMessageBox.confirm('是否生成本月干部考核数据?', '提示', {
1073
+    const tabText = currentTab.value === 'non-cadre' ? '非干部' : '干部'
1074
+    ElMessageBox.confirm(`是否生成本月${tabText}考核数据?`, '提示', {
945
       confirmButtonText: '确定',
1075
       confirmButtonText: '确定',
946
       cancelButtonText: '取消',
1076
       cancelButtonText: '取消',
947
       type: 'warning'
1077
       type: 'warning'
948
     }).then(async () => {
1078
     }).then(async () => {
949
       loading.value = true
1079
       loading.value = true
950
-      // 使用当前年月的日期
951
       const now = new Date()
1080
       const now = new Date()
952
-      const params = {
953
-        year: now.getFullYear(),
954
-        month: now.getMonth() + 1
1081
+      const currentMonth = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}`
1082
+
1083
+      if (currentTab.value === 'non-cadre') {
1084
+        const res = await generateNonCadreAssessment({ month: currentMonth })
1085
+        ElMessage.success('生成成功')
1086
+      } else {
1087
+        const params = {
1088
+          year: now.getFullYear(),
1089
+          month: now.getMonth() + 1
1090
+        }
1091
+        const res = await generateCadreAssessment(params)
1092
+        ElMessage.success('生成成功')
955
       }
1093
       }
956
-      const res = await generateCadreAssessment(params)
957
-      ElMessage.success('生成成功')
958
       getList()
1094
       getList()
959
     }).catch(() => { })
1095
     }).catch(() => { })
960
   } catch (error) {
1096
   } catch (error) {
@@ -986,9 +1122,9 @@ const addIndicator = () => {
986
   indicatorDialog.form = {
1122
   indicatorDialog.form = {
987
     name: '',
1123
     name: '',
988
     score: -3,
1124
     score: -3,
989
-    count: 1,
990
-    source: '',
991
-    total: 0,
1125
+    occurCount: 1,
1126
+    qcDeptType: '',
1127
+    scoreResult: 0,
992
     rewardDetails: '',
1128
     rewardDetails: '',
993
     reward: 0,
1129
     reward: 0,
994
     penaltyDetails: '',
1130
     penaltyDetails: '',
@@ -1021,20 +1157,26 @@ const deleteIndicator = (groupIndex, itemIndex) => {
1021
 
1157
 
1022
 // 指标名称变化时更新分值
1158
 // 指标名称变化时更新分值
1023
 const onIndicatorNameChange = (value) => {
1159
 const onIndicatorNameChange = (value) => {
1024
-  const selected = indicatorDialog.indicatorOptions.find(item => item.name === value)
1160
+  console.log(value, indicatorDialog.indicatorOptions, "indicatorDialog.indicatorOptions")
1161
+  const selected = indicatorDialog.indicatorOptions.find(item => item.id === value)
1025
   if (selected) {
1162
   if (selected) {
1026
-    indicatorDialog.form = { ...selected, count: 1 }
1163
+    indicatorDialog.form = { ...selected, occurCount: 1 }
1027
     updateTotal()
1164
     updateTotal()
1028
   }
1165
   }
1029
 }
1166
 }
1030
 
1167
 
1031
 // 更新总分
1168
 // 更新总分
1032
 const updateTotal = () => {
1169
 const updateTotal = () => {
1033
-  indicatorDialog.form.total = indicatorDialog.form.score * indicatorDialog.form.count
1170
+  indicatorDialog.form.scoreResult = indicatorDialog.form.score * indicatorDialog.form.occurCount
1034
 }
1171
 }
1035
 
1172
 
1036
 // 保存指标
1173
 // 保存指标
1037
 const saveIndicator = () => {
1174
 const saveIndicator = () => {
1175
+  if (!indicatorDialog.form.indicatorId) {
1176
+    ElMessage.error('请选择指标名称')
1177
+    return
1178
+  }
1179
+
1038
   if (indicatorDialog.mode === 'add') {
1180
   if (indicatorDialog.mode === 'add') {
1039
     addIndicatorToGroup({ ...indicatorDialog.form })
1181
     addIndicatorToGroup({ ...indicatorDialog.form })
1040
     ElMessage.success('添加成功')
1182
     ElMessage.success('添加成功')
@@ -1186,7 +1328,7 @@ onMounted(() => {
1186
 
1328
 
1187
 .indicator-value,
1329
 .indicator-value,
1188
 .indicator-count,
1330
 .indicator-count,
1189
-.indicator-source,
1331
+.indicator-qcDeptType,
1190
 .indicator-total {
1332
 .indicator-total {
1191
   flex: 1;
1333
   flex: 1;
1192
   font-size: 16px;
1334
   font-size: 16px;

+ 259 - 69
src/views/performanceManage/monthlyAssessSum/index.vue

@@ -29,9 +29,9 @@
29
       
29
       
30
       <!-- 第一行:两个区块 -->
30
       <!-- 第一行:两个区块 -->
31
       <div class="chart-row">
31
       <div class="chart-row">
32
-        <!-- 整体分分布柱状图 -->
32
+        <!-- 整体分分布柱状图 -->
33
         <el-card class="chart-card">
33
         <el-card class="chart-card">
34
-          <div class="chart-header">整体分分布柱状图</div>
34
+          <div class="chart-header">整体分分布柱状图</div>
35
           <div ref="overallBarChart" class="chart-container"></div>
35
           <div ref="overallBarChart" class="chart-container"></div>
36
         </el-card>
36
         </el-card>
37
         
37
         
@@ -44,9 +44,9 @@
44
 
44
 
45
       <!-- 第二行:两个区块 -->
45
       <!-- 第二行:两个区块 -->
46
       <div class="chart-row">
46
       <div class="chart-row">
47
-        <!-- 各部门分分布对比图 -->
47
+        <!-- 各部门分分布对比图 -->
48
         <el-card class="chart-card">
48
         <el-card class="chart-card">
49
-          <div class="chart-header">各部门分分布对比图</div>
49
+          <div class="chart-header">各部门分分布对比图</div>
50
           <div ref="departmentComparisonChart" class="chart-container"></div>
50
           <div ref="departmentComparisonChart" class="chart-container"></div>
51
         </el-card>
51
         </el-card>
52
         
52
         
@@ -54,11 +54,9 @@
54
         <el-card class="chart-card">
54
         <el-card class="chart-card">
55
           <div class="chart-header">汇总表</div>
55
           <div class="chart-header">汇总表</div>
56
           <el-table :data="summaryTableData" border style="width: 100%; margin-top: 10px;">
56
           <el-table :data="summaryTableData" border style="width: 100%; margin-top: 10px;">
57
-            <el-table-column prop="range" label="区间" align="center" min-width="100" />
58
-            <el-table-column prop="simulationScore" label="2026年1月模拟分数汇总" align="center" min-width="150" />
59
-            <el-table-column prop="team1" label="一队" align="center" min-width="100" />
60
-            <el-table-column prop="team2" label="二队" align="center" min-width="100" />
61
-            <el-table-column prop="team3" label="三队" align="center" min-width="100" />
57
+            <el-table-column prop="rangeLabel" label="区间" align="center" min-width="100" />
58
+            <el-table-column prop="totalCount" :label="summaryTableTitle" align="center" min-width="150" />
59
+            <el-table-column v-for="col in summaryTableColumns" :key="col.deptId" :prop="'team' + col.deptId" :label="col.deptName" align="center" min-width="100" />
62
           </el-table>
60
           </el-table>
63
         </el-card>
61
         </el-card>
64
       </div>
62
       </div>
@@ -72,14 +70,14 @@
72
       <el-card class="summary-table-card">
70
       <el-card class="summary-table-card">
73
         <div class="chart-header">汇总统计</div>
71
         <div class="chart-header">汇总统计</div>
74
         <el-table :data="classificationTableData" border style="width: 100%; margin-top: 10px;">
72
         <el-table :data="classificationTableData" border style="width: 100%; margin-top: 10px;">
75
-          <el-table-column prop="assessmentGroup" label="考核组人数" align="center" min-width="120" />
76
-          <el-table-column prop="calculatedImprovement" label="测算待改进人数" align="center" min-width="140" />
77
-          <el-table-column prop="totalImprovement" label="待改进总人数" align="center" min-width="120" />
78
-          <el-table-column prop="exemption1" label="豁免" align="center" min-width="80" />
79
-          <el-table-column prop="actualImprovement" label="实际待改进总人数" align="center" min-width="140" />
80
-          <el-table-column prop="totalUnqualified" label="不称职总人数" align="center" min-width="120" />
81
-          <el-table-column prop="exemption2" label="豁免" align="center" min-width="80" />
82
-          <el-table-column prop="actualUnqualified" label="实际不称职人数" align="center" min-width="140" />
73
+          <el-table-column prop="assessmentTeamCount" label="考核组人数" align="center" min-width="120" />
74
+          <el-table-column prop="estimatedImprovementCount" label="测算待改进人数" align="center" min-width="140" />
75
+          <el-table-column prop="improvementTotalCount" label="待改进总人数" align="center" min-width="120" />
76
+          <el-table-column prop="improvementExemptedCount" label="待改进豁免" align="center" min-width="100" />
77
+          <el-table-column prop="actualImprovementCount" label="实际待改进总人数" align="center" min-width="140" />
78
+          <el-table-column prop="incompetentTotalCount" label="不称职总人数" align="center" min-width="120" />
79
+          <el-table-column prop="incompetentExemptedCount" label="不称职豁免" align="center" min-width="100" />
80
+          <el-table-column prop="actualIncompetentCount" label="实际不称职人数" align="center" min-width="140" />
83
         </el-table>
81
         </el-table>
84
       </el-card>
82
       </el-card>
85
 
83
 
@@ -113,16 +111,15 @@
113
           <!-- 左边表格 -->
111
           <!-- 左边表格 -->
114
           <div class="table-section">
112
           <div class="table-section">
115
             <el-table :data="item.tableData" border style="width: 100%;">
113
             <el-table :data="item.tableData" border style="width: 100%;">
116
-              <el-table-column prop="brigade" label="大队" align="center" min-width="100" />
117
-              <el-table-column prop="assessmentGroup" label="考核组" align="center" min-width="100" />
118
-              <el-table-column prop="groupCount" label="考核组人数" align="center" min-width="120" />
119
-              <el-table-column prop="calculatedImprovement" label="测算待改进人数" align="center" min-width="140" />
120
-              <el-table-column prop="improvementCount" label="待改进人数" align="center" min-width="120" />
121
-              <el-table-column prop="exemption1" label="豁免" align="center" min-width="80" />
122
-              <el-table-column prop="actualImprovement" label="实际待改进人数" align="center" min-width="140" />
123
-              <el-table-column prop="unqualifiedCount" label="不称职人数" align="center" min-width="120" />
124
-              <el-table-column prop="exemption2" label="豁免" align="center" min-width="80" />
125
-              <el-table-column prop="actualUnqualified" label="实际不称职人数" align="center" min-width="140" />
114
+              <el-table-column prop="assessmentTeam" label="考核组" align="center" min-width="100" />
115
+              <el-table-column prop="assessmentTeamCount" label="考核组人数" align="center" min-width="120" />
116
+              <el-table-column prop="estimatedImprovementCount" label="测算待改进人数" align="center" min-width="140" />
117
+              <el-table-column prop="improvementTotalCount" label="待改进总人数" align="center" min-width="120" />
118
+              <el-table-column prop="improvementExemptedCount" label="待改进豁免人数" align="center" min-width="140" />
119
+              <el-table-column prop="actualImprovementCount" label="实际待改进人数" align="center" min-width="140" />
120
+              <el-table-column prop="incompetentTotalCount" label="不称职总人数" align="center" min-width="120" />
121
+              <el-table-column prop="incompetentExemptedCount" label="不称职豁免人数" align="center" min-width="140" />
122
+              <el-table-column prop="actualIncompetentCount" label="实际不称职人数" align="center" min-width="140" />
126
             </el-table>
123
             </el-table>
127
           </div>
124
           </div>
128
           
125
           
@@ -180,20 +177,45 @@
180
 </template>
177
 </template>
181
 
178
 
182
 <script setup>
179
 <script setup>
183
-import { ref, reactive, onMounted, nextTick } from 'vue'
180
+import { ref, reactive, onMounted, nextTick, computed } from 'vue'
184
 import { ElMessage } from 'element-plus'
181
 import { ElMessage } from 'element-plus'
185
 import * as echarts from 'echarts'
182
 import * as echarts from 'echarts'
186
 
183
 
187
 // API导入
184
 // API导入
188
-//import {  } from '@/api/performance/monthlyAssessSum.js'
185
+import {
186
+  getScoreDistribution,
187
+  getDeptParticipation,
188
+  getDeptScoreDistribution,
189
+  getAssessmentSummary,
190
+  getActualImprovementDistribution,
191
+  getActualIncompetentDistribution,
192
+  getAssessmentTeamImprovementDistribution,
193
+  getAssessmentTeamIncompetentDistribution,
194
+  getDeptAssessmentTeamStatistics,
195
+  getBrigadeImprovementDistribution,
196
+  getBrigadeIncompetentDistribution,
197
+  getFunctionalDeptSummary,
198
+  getFunctionalDeptPersonnelDistribution,
199
+  getFunctionalDeptDistributionPie
200
+} from '@/api/performance/monthlyAssessSum.js'
189
 
201
 
190
 // 响应式数据
202
 // 响应式数据
191
 const loading = ref(false)
203
 const loading = ref(false)
192
 const queryFormRef = ref()
204
 const queryFormRef = ref()
193
 
205
 
194
 // 查询参数
206
 // 查询参数
207
+const currentMonth = `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}`
208
+
195
 const queryParams = reactive({
209
 const queryParams = reactive({
196
-  assessmentMonth: ''
210
+  assessmentMonth: currentMonth
211
+})
212
+
213
+const summaryTableTitle = computed(() => {
214
+  if (queryParams.assessmentMonth) {
215
+    const [year, month] = queryParams.assessmentMonth.split('-')
216
+    return `${year}年${parseInt(month)}月模拟分数汇总`
217
+  }
218
+  return '模拟分数汇总'
197
 })
219
 })
198
 
220
 
199
 // 图表引用
221
 // 图表引用
@@ -209,49 +231,20 @@ const positionPieChart2 = ref(null)
209
 const traversalChartsRefs = ref({})
231
 const traversalChartsRefs = ref({})
210
 
232
 
211
 // 表格数据
233
 // 表格数据
212
-const summaryTableData = ref([
213
-  { range: '90-100分', simulationScore: '85', team1: '15', team2: '20', team3: '25' },
214
-  { range: '80-89分', simulationScore: '120', team1: '30', team2: '35', team3: '40' },
215
-  { range: '70-79分', simulationScore: '95', team1: '25', team2: '30', team3: '35' },
216
-  { range: '60-69分', simulationScore: '60', team1: '15', team2: '20', team3: '25' },
217
-  { range: '60分以下', simulationScore: '20', team1: '5', team2: '8', team3: '7' }
218
-])
234
+const summaryTableData = ref([])
235
+const summaryTableColumns = ref([])
219
 
236
 
220
 const classificationTableData = ref([
237
 const classificationTableData = ref([
221
-  { 
222
-    assessmentGroup: '100', 
223
-    calculatedImprovement: '15', 
224
-    totalImprovement: '12', 
225
-    exemption1: '2', 
226
-    actualImprovement: '10', 
227
-    totalUnqualified: '5', 
228
-    exemption2: '1', 
229
-    actualUnqualified: '4'
230
-  }
238
+
231
 ])
239
 ])
232
 
240
 
233
 // 遍历数据
241
 // 遍历数据
234
 const traversalData1 = ref([
242
 const traversalData1 = ref([
235
-  {
236
-    title: '大队考核统计',
237
-    tableData: [
238
-      { brigade: '一大队', assessmentGroup: '一组', groupCount: 50, calculatedImprovement: 8, improvementCount: 6, exemption1: 1, actualImprovement: 5, unqualifiedCount: 2, exemption2: 0, actualUnqualified: 2 },
239
-      { brigade: '一大队', assessmentGroup: '二组', groupCount: 45, calculatedImprovement: 7, improvementCount: 5, exemption1: 1, actualImprovement: 4, unqualifiedCount: 1, exemption2: 0, actualUnqualified: 1 },
240
-      { brigade: '二大队', assessmentGroup: '一组', groupCount: 55, calculatedImprovement: 9, improvementCount: 7, exemption1: 1, actualImprovement: 6, unqualifiedCount: 3, exemption2: 1, actualUnqualified: 2 },
241
-      { brigade: '二大队', assessmentGroup: '二组', groupCount: 48, calculatedImprovement: 6, improvementCount: 5, exemption1: 0, actualImprovement: 5, unqualifiedCount: 2, exemption2: 0, actualUnqualified: 2 }
242
-    ]
243
-  }
243
+  
244
 ])
244
 ])
245
 
245
 
246
 const traversalData2 = ref([
246
 const traversalData2 = ref([
247
-  {
248
-    title: '岗位考核统计',
249
-    tableData: [
250
-      { brigade: '安检员', assessmentGroup: '一组', groupCount: 60, calculatedImprovement: 10, improvementCount: 8, exemption1: 1, actualImprovement: 7, unqualifiedCount: 3, exemption2: 0, actualUnqualified: 3 },
251
-      { brigade: '安检员', assessmentGroup: '二组', groupCount: 55, calculatedImprovement: 8, improvementCount: 6, exemption1: 1, actualImprovement: 5, unqualifiedCount: 2, exemption2: 0, actualUnqualified: 2 },
252
-      { brigade: '设备操作员', assessmentGroup: '一组', groupCount: 40, calculatedImprovement: 5, improvementCount: 4, exemption1: 0, actualImprovement: 4, unqualifiedCount: 1, exemption2: 0, actualUnqualified: 1 }
253
-    ]
254
-  }
247
+  
255
 ])
248
 ])
256
 
249
 
257
 // 图表实例
250
 // 图表实例
@@ -266,7 +259,7 @@ let positionPieChart2Instance = null
266
 // 初始化图表
259
 // 初始化图表
267
 const initCharts = () => {
260
 const initCharts = () => {
268
   nextTick(() => {
261
   nextTick(() => {
269
-    // 整体分分布柱状图
262
+    // 整体分分布柱状图
270
     if (overallBarChart.value) {
263
     if (overallBarChart.value) {
271
       overallBarChartInstance = echarts.init(overallBarChart.value)
264
       overallBarChartInstance = echarts.init(overallBarChart.value)
272
       overallBarChartInstance.setOption({
265
       overallBarChartInstance.setOption({
@@ -293,7 +286,7 @@ const initCharts = () => {
293
       })
286
       })
294
     }
287
     }
295
 
288
 
296
-    // 各部门分分布对比图
289
+    // 各部门分分布对比图
297
     if (departmentComparisonChart.value) {
290
     if (departmentComparisonChart.value) {
298
       departmentComparisonChartInstance = echarts.init(departmentComparisonChart.value)
291
       departmentComparisonChartInstance = echarts.init(departmentComparisonChart.value)
299
       departmentComparisonChartInstance.setOption({
292
       departmentComparisonChartInstance.setOption({
@@ -485,9 +478,206 @@ const handleResize = () => {
485
 const getList = async () => {
478
 const getList = async () => {
486
   loading.value = true
479
   loading.value = true
487
   try {
480
   try {
488
-    // const res = await getNonCadreMonthlyScoreSum(queryParams)
489
-    // // 这里可以根据实际API返回的数据更新图表和表格数据
490
-    // console.log('获取汇总数据:', res)
481
+    const results = await Promise.allSettled([
482
+      getScoreDistribution(queryParams),
483
+      getDeptParticipation(queryParams),
484
+      getDeptScoreDistribution(queryParams),
485
+      getAssessmentSummary(queryParams),
486
+      getActualImprovementDistribution(queryParams),
487
+      getActualIncompetentDistribution(queryParams),
488
+      getAssessmentTeamImprovementDistribution(queryParams),
489
+      getAssessmentTeamIncompetentDistribution(queryParams),
490
+      getDeptAssessmentTeamStatistics(queryParams),
491
+      getBrigadeImprovementDistribution(queryParams),
492
+      getBrigadeIncompetentDistribution(queryParams),
493
+      getFunctionalDeptSummary(queryParams),
494
+      getFunctionalDeptPersonnelDistribution(queryParams),
495
+      getFunctionalDeptDistributionPie(queryParams)
496
+    ])
497
+
498
+    const [scoreDistRes, deptPartRes, deptScoreRes, assessmentSumRes, actualImproveRes, actualIncompRes, teamImproveRes, teamIncompRes, deptTeamStatRes, brigadeImproveRes, brigadeIncompRes, functionalDeptRes, functionalDeptPersonnelRes, functionalDeptPieRes] = results
499
+
500
+    if (scoreDistRes.status === 'fulfilled' && scoreDistRes.value.data) {
501
+      const data = scoreDistRes.value.data
502
+      if (overallBarChartInstance && Array.isArray(data)) {
503
+        overallBarChartInstance.setOption({
504
+          xAxis: { data: data.map(item => item.scoreRange) },
505
+          series: [{ data: data.map(item => item.count) }]
506
+        })
507
+      }
508
+    }
509
+
510
+    if (deptPartRes.status === 'fulfilled' && deptPartRes.value.data) {
511
+      const data = deptPartRes.value.data
512
+      if (participantPieChartInstance && Array.isArray(data)) {
513
+        participantPieChartInstance.setOption({
514
+          series: [{ data: data.map(item => ({ name: item.deptName, value: item.count })) }]
515
+        })
516
+      }
517
+    }
518
+
519
+    if (deptScoreRes.status === 'fulfilled' && deptScoreRes.value.data) {
520
+      const data = deptScoreRes.value.data
521
+      if (departmentComparisonChartInstance && Array.isArray(data)) {
522
+        const xAxisData = data.map(item => item.rangeLabel)
523
+        const firstDeptCounts = data.length > 0 ? data[0].deptCounts : []
524
+        
525
+        const series = firstDeptCounts.map(dept => ({
526
+          name: dept.deptName,
527
+          type: 'bar',
528
+          data: data.map(item => {
529
+            const deptData = item.deptCounts.find(d => d.deptId === dept.deptId)
530
+            return deptData ? deptData.count : 0
531
+          })
532
+        }))
533
+
534
+        departmentComparisonChartInstance.setOption({
535
+          legend: { data: firstDeptCounts.map(d => d.deptName) },
536
+          xAxis: { data: xAxisData },
537
+          series: series
538
+        })
539
+
540
+        summaryTableColumns.value = firstDeptCounts
541
+        summaryTableData.value = data.map(item => {
542
+          const row = {
543
+            rangeLabel: item.rangeLabel,
544
+            totalCount: item.totalCount
545
+          }
546
+          item.deptCounts.forEach(dept => {
547
+            row['team' + dept.deptId] = dept.count
548
+          })
549
+          return row
550
+        })
551
+      }
552
+    }
553
+
554
+    if (assessmentSumRes.status === 'fulfilled' && assessmentSumRes.value.data) {
555
+      const data = assessmentSumRes.value.data
556
+      if (data && typeof data === 'object') {
557
+        classificationTableData.value = [data]
558
+      }
559
+    }
560
+
561
+    if (actualImproveRes.status === 'fulfilled' && actualImproveRes.value.data) {
562
+      const data = actualImproveRes.value.data
563
+      if (brigadePieChart1Instance && Array.isArray(data)) {
564
+        brigadePieChart1Instance.setOption({
565
+          series: [{ data: data.map(item => ({ name: item.deptName, value: item.count })) }]
566
+        })
567
+      }
568
+    }
569
+
570
+    if (actualIncompRes.status === 'fulfilled' && actualIncompRes.value.data) {
571
+      const data = actualIncompRes.value.data
572
+      if (brigadePieChart2Instance && Array.isArray(data)) {
573
+        brigadePieChart2Instance.setOption({
574
+          series: [{ data: data.map(item => ({ name: item.deptName, value: item.count })) }]
575
+        })
576
+      }
577
+    }
578
+
579
+    if (teamImproveRes.status === 'fulfilled' && teamImproveRes.value.data) {
580
+      const data = teamImproveRes.value.data
581
+      if (positionPieChart1Instance && Array.isArray(data)) {
582
+        positionPieChart1Instance.setOption({
583
+          series: [{ data: data.map(item => ({ name: item.assessmentTeam, value: item.count })) }]
584
+        })
585
+      }
586
+    }
587
+
588
+    if (teamIncompRes.status === 'fulfilled' && teamIncompRes.value.data) {
589
+      const data = teamIncompRes.value.data
590
+      if (positionPieChart2Instance && Array.isArray(data)) {
591
+        positionPieChart2Instance.setOption({
592
+          series: [{ data: data.map(item => ({ name: item.assessmentTeam, value: item.count })) }]
593
+        })
594
+      }
595
+    }
596
+
597
+    if (deptTeamStatRes.status === 'fulfilled' && deptTeamStatRes.value.data) {
598
+      const statistics = deptTeamStatRes.value.data || []
599
+      const brigadeImproveData = brigadeImproveRes.status === 'fulfilled' ? (brigadeImproveRes.value.data || []) : []
600
+      const brigadeIncompData = brigadeIncompRes.status === 'fulfilled' ? (brigadeIncompRes.value.data || []) : []
601
+      
602
+      const brigadeMap = {}
603
+      brigadeImproveData.forEach(item => {
604
+        if (!brigadeMap[item.deptName]) {
605
+          brigadeMap[item.deptName] = { brigade: item.deptName, assessmentGroup: '', improvementCount: 0, exemption1: 0, unqualifiedCount: 0, exemption2: 0 }
606
+        }
607
+        brigadeMap[item.deptName].improvementCount += item.count
608
+        brigadeMap[item.deptName].exemption1 += (item.exemptedCount || 0)
609
+      })
610
+      brigadeIncompData.forEach(item => {
611
+        if (!brigadeMap[item.deptName]) {
612
+          brigadeMap[item.deptName] = { brigade: item.deptName, assessmentGroup: '', improvementCount: 0, exemption1: 0, unqualifiedCount: 0, exemption2: 0 }
613
+        }
614
+        brigadeMap[item.deptName].unqualifiedCount += item.count
615
+        brigadeMap[item.deptName].exemption2 += (item.exemptedCount || 0)
616
+      })
617
+      
618
+      const groupCount = statistics.reduce((sum, item) => sum + (item.count || 0), 0)
619
+      const calculatedImprovement = statistics.reduce((sum, item) => sum + (item.calculatedImprovementCount || 0), 0)
620
+      const actualImprovement = statistics.reduce((sum, item) => sum + (item.actualImprovementCount || 0), 0)
621
+      const actualUnqualified = statistics.reduce((sum, item) => sum + (item.actualIncompetentCount || 0), 0)
622
+      
623
+      const tableData = Object.values(brigadeMap).map(item => ({
624
+        ...item,
625
+        groupCount,
626
+        calculatedImprovement,
627
+        actualImprovement,
628
+        actualUnqualified
629
+      }))
630
+      
631
+      if (tableData.length > 0) {
632
+        traversalData1.value = [{ title: '大队考核统计', tableData }]
633
+      }
634
+    }
635
+
636
+    if (functionalDeptRes.status === 'fulfilled' && functionalDeptRes.value.data) {
637
+      const summaryData = functionalDeptRes.value.data || []
638
+      
639
+      traversalData2.value = summaryData.map(item => ({
640
+        title: item.deptName,
641
+        deptId: item.deptId,
642
+        tableData: item.assessmentTeams || []
643
+      }))
644
+      
645
+      const personnelData = functionalDeptPersonnelRes.status === 'fulfilled' ? (functionalDeptPersonnelRes.value.data || []) : []
646
+      const pieData = functionalDeptPieRes.status === 'fulfilled' ? (functionalDeptPieRes.value.data || []) : []
647
+      
648
+      personnelData.forEach(item => {
649
+        const deptItem = traversalData2.value.find(d => d.deptId === item.deptId)
650
+        if (deptItem) {
651
+          deptItem.personnelCount = item.assessmentTeamCount || 0
652
+          deptItem.actualImprovement = item.actualImprovementCount || 0
653
+          deptItem.actualUnqualified = item.actualIncompetentCount || 0
654
+        }
655
+      })
656
+      
657
+      nextTick(() => {
658
+        pieData.forEach(pieItem => {
659
+          const deptIndex = traversalData2.value.findIndex(d => d.deptId === pieItem.deptId)
660
+          const chartKey = `barChart_${deptIndex}`
661
+          const pieChartKey = `pieChart3_${deptIndex}`
662
+          
663
+          const filteredData = pieData.filter(p => p.deptId === pieItem.deptId).map(p => ({ name: p.assessmentTeam, value: p.count }))
664
+          
665
+          if (traversalChartsRefs.value[chartKey]) {
666
+            const barChart = echarts.init(traversalChartsRefs.value[chartKey])
667
+            barChart.setOption({
668
+              series: [{ data: filteredData }]
669
+            })
670
+          }
671
+          
672
+          if (traversalChartsRefs.value[pieChartKey]) {
673
+            const pieChart = echarts.init(traversalChartsRefs.value[pieChartKey])
674
+            pieChart.setOption({
675
+              series: [{ data: filteredData }]
676
+            })
677
+          }
678
+        })
679
+      })
680
+    }
491
   } catch (error) {
681
   } catch (error) {
492
     console.error('获取汇总数据失败:', error)
682
     console.error('获取汇总数据失败:', error)
493
     ElMessage.error('获取汇总数据失败')
683
     ElMessage.error('获取汇总数据失败')

+ 8 - 0
src/views/system/dept/index.vue

@@ -125,6 +125,14 @@
125
                   </el-form-item>
125
                   </el-form-item>
126
                </el-col>
126
                </el-col>
127
                <el-col :span="12">
127
                <el-col :span="12">
128
+                  <el-form-item label="职能部门" prop="isFunctionalDept">
129
+                     <el-select v-model="form.isFunctionalDept" placeholder="请选择">
130
+                        <el-option :label="'是'" :value="'1'" />
131
+                        <el-option :label="'否'" :value="'0'" />
132
+                     </el-select>
133
+                  </el-form-item>
134
+               </el-col>
135
+               <el-col :span="12">
128
                   <el-form-item label="显示排序" prop="orderNum">
136
                   <el-form-item label="显示排序" prop="orderNum">
129
                      <el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
137
                      <el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
130
                   </el-form-item>
138
                   </el-form-item>