Переглянути джерело

feat(warningManage): 优化员工维度评分明细分页排序和筛选逻辑

- 替换静态表格数据为带分页和筛选的计算属性数据
- 添加维度分值列自定义排序功能,支持前端排序切换
- 实现基于日期范围、维度和组织架构的多条件筛选
- 使用 mock 数据模拟两页含事件日期的示例数据
- 移除未使用的接口请求代码,改为本地过滤和排序实现
- 页码和页大小变化触发重新计算展示数据
- 简化并注释禁用路由查询监听相关代码
- 调整跳转逻辑,使用用户ID作为查询参数替代组织架构参数
- 修正部分组件属性格式,提升代码规范性
huoyi 6 годин тому
батько
коміт
c60a9ab283

+ 121 - 79
src/views/warningManage/employeeDimensionDetails/index.vue

@@ -34,14 +34,14 @@
34
                 <span class="title-text">员工维度评分明细</span>
34
                 <span class="title-text">员工维度评分明细</span>
35
                 <span class="title-badge">评分依据: 员工配分表</span>
35
                 <span class="title-badge">评分依据: 员工配分表</span>
36
             </div>
36
             </div>
37
-            <el-table :data="tableData" style="width: 100%;" border stripe>
37
+            <el-table :data="displayData" style="width: 100%;" border stripe @sort-change="handleSortChange">
38
                 <el-table-column prop="userId" label="员工ID" />
38
                 <el-table-column prop="userId" label="员工ID" />
39
                 <el-table-column prop="nickName" label="姓名" />
39
                 <el-table-column prop="nickName" label="姓名" />
40
                 <el-table-column prop="deptName" label="部门" />
40
                 <el-table-column prop="deptName" label="部门" />
41
                 <el-table-column prop="teamName" label="班组" />
41
                 <el-table-column prop="teamName" label="班组" />
42
                 <el-table-column prop="groupName" label="小组" />
42
                 <el-table-column prop="groupName" label="小组" />
43
                 <el-table-column prop="dimName" label="维度名称" />
43
                 <el-table-column prop="dimName" label="维度名称" />
44
-                <el-table-column prop="dimScore" label="维度分值" />
44
+                <el-table-column prop="dimScore" label="维度分值" sortable="custom" />
45
             </el-table>
45
             </el-table>
46
             <el-pagination v-show="total > 0" :total="total" v-model:current-page="queryParams.pageNum"
46
             <el-pagination v-show="total > 0" :total="total" v-model:current-page="queryParams.pageNum"
47
                 v-model:page-size="queryParams.pageSize" :page-sizes="[10, 20, 50, 100]"
47
                 v-model:page-size="queryParams.pageSize" :page-sizes="[10, 20, 50, 100]"
@@ -52,10 +52,9 @@
52
 </template>
52
 </template>
53
 
53
 
54
 <script setup>
54
 <script setup>
55
-import { ref, reactive, onMounted, watch } from 'vue'
55
+import { ref, reactive, computed, onMounted, watch } from 'vue'
56
 import { useRoute } from 'vue-router'
56
 import { useRoute } from 'vue-router'
57
 import { getDeptUserTree } from '@/api/item/items'
57
 import { getDeptUserTree } from '@/api/item/items'
58
-import { getEmployeeDimensionPageData } from '@/api/warningManage/employeeDimensionDetails'
59
 
58
 
60
 const route = useRoute()
59
 const route = useRoute()
61
 
60
 
@@ -71,24 +70,37 @@ const dimensionOptions = ref([
71
     { label: '服务响应能力', value: '服务响应能力' }
70
     { label: '服务响应能力', value: '服务响应能力' }
72
 ])
71
 ])
73
 
72
 
74
-const tableData = ref([
75
-    { userId: 397, nickName: '胡婷婷', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '安全响应能力', dimScore: 80.5 },
76
-    { userId: 437, nickName: '李璐', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '服务响应能力', dimScore: 79.2 },
77
-    { userId: 564, nickName: '徐倩', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '安全响应能力', dimScore: 81.3 },
78
-    { userId: 587, nickName: '余杭洋', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '服务响应能力', dimScore: 78.6 },
79
-    { userId: 550, nickName: '肖垚', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '安全响应能力', dimScore: 80.1 },
80
-    { userId: 107, nickName: '刘珊', deptName: '旅检三部', teamName: '安平班组', groupName: '陈行小组', dimName: '服务响应能力', dimScore: 79.8 },
81
-    { userId: 191, nickName: '王佐朝', deptName: '旅检三部', teamName: '安平班组', groupName: '陈行小组', dimName: '安全响应能力', dimScore: 82.0 },
82
-    { userId: 250, nickName: '张元媛', deptName: '旅检三部', teamName: '安平班组', groupName: '陈行小组', dimName: '服务响应能力', dimScore: 78.9 },
83
-    { userId: 293, nickName: '陈凯琳', deptName: '旅检三部', teamName: '安平班组', groupName: '陈行小组', dimName: '安全响应能力', dimScore: 80.7 },
84
-    { userId: 603, nickName: '张霞', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '服务响应能力', dimScore: 79.5 }
73
+// 两页假数据(20条),含事件日期
74
+const allMockData = ref([
75
+    { userId: 397, nickName: '胡婷婷', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '安全响应能力', dimScore: 80.5, eventDate: '2026-05-10' },
76
+    { userId: 437, nickName: '李璐', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '服务响应能力', dimScore: 79.2, eventDate: '2026-05-15' },
77
+    { userId: 564, nickName: '徐倩', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '安全响应能力', dimScore: 81.3, eventDate: '2026-05-20' },
78
+    { userId: 587, nickName: '余杭洋', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '服务响应能力', dimScore: 78.6, eventDate: '2026-05-25' },
79
+    { userId: 550, nickName: '肖垚', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '安全响应能力', dimScore: 80.1, eventDate: '2026-06-01' },
80
+    { userId: 107, nickName: '刘珊', deptName: '旅检三部', teamName: '安平班组', groupName: '陈行小组', dimName: '服务响应能力', dimScore: 79.8, eventDate: '2026-06-05' },
81
+    { userId: 191, nickName: '王佐朝', deptName: '旅检三部', teamName: '安平班组', groupName: '陈行小组', dimName: '安全响应能力', dimScore: 82.0, eventDate: '2026-06-08' },
82
+    { userId: 250, nickName: '张元媛', deptName: '旅检三部', teamName: '安平班组', groupName: '陈行小组', dimName: '服务响应能力', dimScore: 78.9, eventDate: '2026-06-10' },
83
+    { userId: 293, nickName: '陈凯琳', deptName: '旅检三部', teamName: '安平班组', groupName: '陈行小组', dimName: '安全响应能力', dimScore: 80.7, eventDate: '2026-06-12' },
84
+    { userId: 603, nickName: '张霞', deptName: '旅检一部', teamName: '安平班组', groupName: '陈行小组', dimName: '服务响应能力', dimScore: 79.5, eventDate: '2026-04-15' },
85
+    { userId: 412, nickName: '赵敏', deptName: '旅检一部', teamName: '安行班组', groupName: '拓新小组', dimName: '安全响应能力', dimScore: 83.2, eventDate: '2026-04-20' },
86
+    { userId: 528, nickName: '孙磊', deptName: '旅检一部', teamName: '安行班组', groupName: '拓新小组', dimName: '服务响应能力', dimScore: 77.4, eventDate: '2026-03-10' },
87
+    { userId: 631, nickName: '周杰', deptName: '旅检二部', teamName: '木兰班组', groupName: '飞跃小组', dimName: '安全响应能力', dimScore: 85.1, eventDate: '2026-03-15' },
88
+    { userId: 745, nickName: '吴芳', deptName: '旅检二部', teamName: '木兰班组', groupName: '飞跃小组', dimName: '服务响应能力', dimScore: 76.8, eventDate: '2026-02-20' },
89
+    { userId: 802, nickName: '郑浩', deptName: '旅检二部', teamName: '芮茜班组', groupName: '先锋小组', dimName: '安全响应能力', dimScore: 81.9, eventDate: '2026-01-10' },
90
+    { userId: 156, nickName: '冯婷', deptName: '旅检三部', teamName: '拓新班组', groupName: '锐行小组', dimName: '服务响应能力', dimScore: 78.3, eventDate: '2026-01-25' },
91
+    { userId: 267, nickName: '褚伟', deptName: '旅检三部', teamName: '拓新班组', groupName: '锐行小组', dimName: '安全响应能力', dimScore: 84.6, eventDate: '2025-12-05' },
92
+    { userId: 389, nickName: '卫兰', deptName: '旅检一部', teamName: '屹动班组', groupName: '护航小组', dimName: '服务响应能力', dimScore: 77.1, eventDate: '2025-11-18' },
93
+    { userId: 471, nickName: '蒋涛', deptName: '旅检一部', teamName: '屹动班组', groupName: '护航小组', dimName: '安全响应能力', dimScore: 82.7, eventDate: '2025-10-22' },
94
+    { userId: 598, nickName: '沈琳', deptName: '旅检二部', teamName: '安行班组', groupName: '拓新小组', dimName: '服务响应能力', dimScore: 80.0, eventDate: '2025-09-30' }
85
 ])
95
 ])
86
-const total = ref(972)
96
+
87
 const queryParams = reactive({
97
 const queryParams = reactive({
88
     pageNum: 1,
98
     pageNum: 1,
89
     pageSize: 10
99
     pageSize: 10
90
 })
100
 })
91
 
101
 
102
+const sortState = ref({ prop: '', order: '' })
103
+
92
 const transformCascadeData = (nodes) => {
104
 const transformCascadeData = (nodes) => {
93
     if (!nodes) return []
105
     if (!nodes) return []
94
     return nodes.map(node => {
106
     return nodes.map(node => {
@@ -152,45 +164,76 @@ const setActiveRange = (range) => {
152
     }
164
     }
153
 }
165
 }
154
 
166
 
155
-const fetchDimensionData = async () => {
156
-    // TODO: 接入真实接口
157
-    // let params = {
158
-    //     pageNum: queryParams.pageNum,
159
-    //     pageSize: queryParams.pageSize
160
-    // }
161
-    // if (startDate.value && endDate.value) {
162
-    //     params.startDate = formatDate(startDate.value)
163
-    //     params.endDate = formatDate(endDate.value)
164
-    // } else {
165
-    //     const range = getDateRangeFromActive()
166
-    //     params.startDate = range.startDate
167
-    //     params.endDate = range.endDate
168
-    // }
169
-    // const selectedInfo = getSelectedInfo(selectedOrg.value)
170
-    // if (selectedInfo) {
171
-    //     const rawId = Number(selectedInfo.value.split('_')[1])
172
-    //     if (selectedInfo.deptType === 'BRIGADE') params.deptId = rawId
173
-    //     else if (selectedInfo.deptType === 'MANAGER') params.teamId = rawId
174
-    //     else if (selectedInfo.deptType === 'TEAMS') params.groupId = rawId
175
-    //     else if (selectedInfo.deptType === 'user') params.userId = rawId
176
-    // }
177
-    // if (selectedDimension.value) {
178
-    //     params.dimName = selectedDimension.value
179
-    // }
180
-    // try {
181
-    //     const res = await getEmployeeDimensionPageData(params)
182
-    //     if (res.data) {
183
-    //         tableData.value = res.data.rows || res.data || []
184
-    //         total.value = res.total || res.data?.total || 0
185
-    //     }
186
-    // } catch (error) {
187
-    //     console.error('获取员工维度评分明细失败:', error)
188
-    // }
167
+// 筛选后的数据(点击搜索才更新)
168
+const filteredData = ref([...allMockData.value])
169
+
170
+const displayData = computed(() => {
171
+    const start = (queryParams.pageNum - 1) * queryParams.pageSize
172
+    const end = start + queryParams.pageSize
173
+    return filteredData.value.slice(start, end)
174
+})
175
+
176
+const total = computed(() => filteredData.value.length)
177
+
178
+// 执行筛选(点击搜索时调用)
179
+const doFilter = () => {
180
+    let data = [...allMockData.value]
181
+
182
+    // 日期范围筛选
183
+    let rangeStart = null
184
+    let rangeEnd = null
185
+    if (startDate.value && endDate.value) {
186
+        rangeStart = formatDate(startDate.value)
187
+        rangeEnd = formatDate(endDate.value)
188
+    } else {
189
+        const range = getDateRangeFromActive()
190
+        rangeStart = range.startDate
191
+        rangeEnd = range.endDate
192
+    }
193
+    if (rangeStart && rangeEnd) {
194
+        data = data.filter(item => item.eventDate >= rangeStart && item.eventDate <= rangeEnd)
195
+    }
196
+
197
+    // 维度筛选
198
+    if (selectedDimension.value) {
199
+        data = data.filter(item => item.dimName === selectedDimension.value)
200
+    }
201
+
202
+    // 组织架构/员工筛选
203
+    const selectedInfo = getSelectedInfo(selectedOrg.value)
204
+    if (selectedInfo) {
205
+        if (selectedInfo.deptType === 'user') {
206
+            const rawId = Number(selectedInfo.value.split('_')[1])
207
+            data = data.filter(item => item.userId === rawId)
208
+        }
209
+    }
210
+
211
+    // 排序(基于全量过滤后数据)
212
+    if (sortState.value.prop && sortState.value.order) {
213
+        const { prop, order } = sortState.value
214
+        data.sort((a, b) => {
215
+            const valA = a[prop]
216
+            const valB = b[prop]
217
+            if (valA == null) return 1
218
+            if (valB == null) return -1
219
+            const result = valA > valB ? 1 : valA < valB ? -1 : 0
220
+            return order === 'ascending' ? result : -result
221
+        })
222
+    }
223
+
224
+    filteredData.value = data
225
+}
226
+
227
+const handleSortChange = ({ prop, order }) => {
228
+    sortState.value = { prop, order }
229
+    queryParams.pageNum = 1
230
+    doFilter()
189
 }
231
 }
190
 
232
 
191
 const handleSearch = () => {
233
 const handleSearch = () => {
192
     queryParams.pageNum = 1
234
     queryParams.pageNum = 1
193
-    fetchDimensionData()
235
+    sortState.value = { prop: '', order: '' }
236
+    doFilter()
194
 }
237
 }
195
 
238
 
196
 const handleReset = () => {
239
 const handleReset = () => {
@@ -200,18 +243,17 @@ const handleReset = () => {
200
     selectedOrg.value = ''
243
     selectedOrg.value = ''
201
     selectedDimension.value = ''
244
     selectedDimension.value = ''
202
     queryParams.pageNum = 1
245
     queryParams.pageNum = 1
203
-    fetchDimensionData()
246
+    sortState.value = { prop: '', order: '' }
247
+    doFilter()
204
 }
248
 }
205
 
249
 
206
 const handlePageChange = (newPage) => {
250
 const handlePageChange = (newPage) => {
207
     queryParams.pageNum = newPage
251
     queryParams.pageNum = newPage
208
-    fetchDimensionData()
209
 }
252
 }
210
 
253
 
211
 const handleSizeChange = (newSize) => {
254
 const handleSizeChange = (newSize) => {
212
     queryParams.pageSize = newSize
255
     queryParams.pageSize = newSize
213
     queryParams.pageNum = 1
256
     queryParams.pageNum = 1
214
-    fetchDimensionData()
215
 }
257
 }
216
 
258
 
217
 onMounted(async () => {
259
 onMounted(async () => {
@@ -223,33 +265,33 @@ onMounted(async () => {
223
     } catch (error) {
265
     } catch (error) {
224
         console.error('获取组织架构数据失败:', error)
266
         console.error('获取组织架构数据失败:', error)
225
     }
267
     }
226
-    fetchDimensionData()
268
+    doFilter()
227
 })
269
 })
228
 
270
 
229
-watch(() => route.query, (query) => {
230
-    const { id, org, startDate: sd, endDate: ed, activeRange: ar, dimension } = query
231
-    if (id) {
232
-        selectedOrg.value = `user_${id}`
233
-    } else if (org) {
234
-        selectedOrg.value = org
235
-    } else {
236
-        selectedOrg.value = ''
237
-    }
238
-    if (sd && ed) {
239
-        startDate.value = sd
240
-        endDate.value = ed
241
-        activeRange.value = 'custom'
242
-    } else {
243
-        startDate.value = null
244
-        endDate.value = null
245
-        activeRange.value = ar || 'month'
246
-    }
247
-    if (dimension) {
248
-        selectedDimension.value = dimension
249
-    }
250
-    queryParams.pageNum = 1
251
-    fetchDimensionData()
252
-}, { immediate: true })
271
+// watch(() => route.query, (query) => {
272
+//     const { id, org, startDate: sd, endDate: ed, activeRange: ar, dimension } = query
273
+//     if (id) {
274
+//         selectedOrg.value = `user_${id}`
275
+//     } else if (org) {
276
+//         selectedOrg.value = org
277
+//     } else {
278
+//         selectedOrg.value = ''
279
+//     }
280
+//     if (sd && ed) {
281
+//         startDate.value = sd
282
+//         endDate.value = ed
283
+//         activeRange.value = 'custom'
284
+//     } else {
285
+//         startDate.value = null
286
+//         endDate.value = null
287
+//         activeRange.value = ar || 'month'
288
+//     }
289
+//     if (dimension) {
290
+//         selectedDimension.value = dimension
291
+//     }
292
+//     queryParams.pageNum = 1
293
+//     sortState.value = { prop: '', order: '' }
294
+// }, { immediate: true })
253
 </script>
295
 </script>
254
 
296
 
255
 <style scoped>
297
 <style scoped>

+ 1 - 4
src/views/warningManage/redLineWarning/index.vue

@@ -30,8 +30,7 @@
30
                 </div>
30
                 </div>
31
                 <el-tree-select v-model="selectedOrg" :data="cascadeOptions"
31
                 <el-tree-select v-model="selectedOrg" :data="cascadeOptions"
32
                     :props="{ label: 'label', value: 'value', children: 'children' }" node-key="value"
32
                     :props="{ label: 'label', value: 'value', children: 'children' }" node-key="value"
33
-                    placeholder="组织架构/员工" clearable filterable check-strictly style="width: 480px;"
34
-                     />
33
+                    placeholder="组织架构/员工" clearable filterable check-strictly style="width: 480px;" />
35
             </div>
34
             </div>
36
             <div class="filter-group">
35
             <div class="filter-group">
37
                 <el-select v-model="selectedAlertLevel" placeholder="预警等级" clearable style="width: 250px;">
36
                 <el-select v-model="selectedAlertLevel" placeholder="预警等级" clearable style="width: 250px;">
@@ -376,8 +375,6 @@ watch(() => route.query, (query) => {
376
     // 回显员工选择
375
     // 回显员工选择
377
     if (id) {
376
     if (id) {
378
         selectedOrg.value = `user_${id}`
377
         selectedOrg.value = `user_${id}`
379
-    } else if (org) {
380
-        selectedOrg.value = org
381
     } else {
378
     } else {
382
         selectedOrg.value = ''
379
         selectedOrg.value = ''
383
     }
380
     }

+ 2 - 2
src/views/warningManage/warningPage/index.vue

@@ -451,8 +451,8 @@ const goToDetail = (row) => {
451
   if (selectedAlertLevel.value) {
451
   if (selectedAlertLevel.value) {
452
     query.alertLevel = selectedAlertLevel.value;
452
     query.alertLevel = selectedAlertLevel.value;
453
   }
453
   }
454
-  if (selectedOrg.value) {
455
-    query.org = selectedOrg.value;
454
+  if (row.userId) {
455
+    query.id = row.userId || "";
456
   }
456
   }
457
   router.push({ path: "/warningManage/redLineWarning", query });
457
   router.push({ path: "/warningManage/redLineWarning", query });
458
 };
458
 };