Преглед изворни кода

Merge branch 'employeeScreen'

huoyi пре 1 недеља
родитељ
комит
ac17edc212

+ 2 - 2
src/api/ledger/index.js

@@ -1,8 +1,8 @@
1
 import request from '@/utils/request'
1
 import request from '@/utils/request'
2
 
2
 
3
 // ===== 台账一键全量导入(多Sheet合并Excel)=====
3
 // ===== 台账一键全量导入(多Sheet合并Excel)=====
4
-export function importCombinedLedger(data) {
5
-  return request({ url: '/ledger/import/combined', method: 'post', data })
4
+export function importCombinedLedger(data, timeout = 300000) {
5
+  return request({ url: '/ledger/import/combined', method: 'post', data, timeout })
6
 }
6
 }
7
 
7
 
8
 // ===== 台账数据清理(按导入时间范围)=====
8
 // ===== 台账数据清理(按导入时间范围)=====

+ 10 - 10
src/router/index.js

@@ -107,17 +107,17 @@ export const constantRoutes = [
107
       //   meta: { title: '机场安检员考勤管理系统', icon: 'dashboard' }
107
       //   meta: { title: '机场安检员考勤管理系统', icon: 'dashboard' }
108
       // },
108
       // },
109
       // {
109
       // {
110
-	    //   path: '/examQuestionStatistics',
111
-	    //   component: () => import('@/views/dataBigScreen/examQuestionStatistics'),
112
-	    //   name: 'examQuestionStatistics',
113
-	    //   meta: { title: '答题统计', icon: 'dashboard' }
114
-	    // },
110
+      //   path: '/examQuestionStatistics',
111
+      //   component: () => import('@/views/dataBigScreen/examQuestionStatistics'),
112
+      //   name: 'examQuestionStatistics',
113
+      //   meta: { title: '答题统计', icon: 'dashboard' }
114
+      // },
115
       // {
115
       // {
116
-	    //   path: '/abilityPortrait',
117
-	    //   component: () => import('@/views/dataBigScreen/abilityPortrait'),
118
-	    //   name: 'abilityPortrait',
119
-	    //   meta: { title: '能力画像显示大屏', icon: 'dashboard' }
120
-	    // }
116
+      //   path: '/abilityPortrait',
117
+      //   component: () => import('@/views/dataBigScreen/abilityPortrait'),
118
+      //   name: 'abilityPortrait',
119
+      //   meta: { title: '能力画像显示大屏', icon: 'dashboard' }
120
+      // }
121
     ]
121
     ]
122
   },
122
   },
123
 ]
123
 ]

+ 50 - 91
src/views/portraitManagement/components/SearchBar.vue

@@ -52,7 +52,7 @@
52
 </template>
52
 </template>
53
 
53
 
54
 <script setup>
54
 <script setup>
55
-import { ref, nextTick, onMounted, onUnmounted } from 'vue'
55
+import { ref, nextTick, onMounted } from 'vue'
56
 import { searchPortraitUsers } from '@/api/score/index'
56
 import { searchPortraitUsers } from '@/api/score/index'
57
 import { getDeptList, getDeptUserTree } from '@/api/item/items'
57
 import { getDeptList, getDeptUserTree } from '@/api/item/items'
58
 import { listDept } from '@/api/system/dept'
58
 import { listDept } from '@/api/system/dept'
@@ -74,46 +74,36 @@ const treeRef = ref(null)
74
 const currentKey = ref(null)
74
 const currentKey = ref(null)
75
 const curQuery = ref({})
75
 const curQuery = ref({})
76
 
76
 
77
-const defaultIdMap = {
78
-  user: 13,
79
-  BRIGADE: 103,
80
-  STATION: 100,
81
-  MANAGER: 104,
82
-  TEAMS: 110
83
-}
84
-
85
-const findNodeById = (nodes, id) => {
86
-  if (!nodes) return null
87
-  for (const node of nodes) {
88
-    if (node.id === id || node.deptId === id) return node
89
-    if (node.children) {
90
-      const found = findNodeById(node.children, id)
91
-      if (found) return found
92
-    }
77
+const findFirstNodeByDeptType = (nodes, targetType) => {
78
+  if (!nodes || nodes.length === 0) return null
79
+  const first = nodes[0]
80
+  if (first.deptType === targetType || first.nodeType === targetType) return first
81
+  if (first.children && first.children.length > 0) {
82
+    return findFirstNodeByDeptType(first.children, targetType)
93
   }
83
   }
94
   return null
84
   return null
95
 }
85
 }
96
 
86
 
97
-const buildPathForNode = (nodes, targetId, path = []) => {
98
-  if (!nodes) return path
87
+const buildPathForNode = (nodes, targetId) => {
88
+  if (!nodes) return null
99
   for (const node of nodes) {
89
   for (const node of nodes) {
100
     if (node.id === targetId || node.deptId === targetId) {
90
     if (node.id === targetId || node.deptId === targetId) {
101
       // 如果是用户节点,不把用户名字加入 path
91
       // 如果是用户节点,不把用户名字加入 path
102
       if (node.deptType === 'user' || node.nodeType === 'user') {
92
       if (node.deptType === 'user' || node.nodeType === 'user') {
103
-        return path
93
+        return []
104
       }
94
       }
105
       const name = node.nickName || node.deptName || node.name || node.label
95
       const name = node.nickName || node.deptName || node.name || node.label
106
-      return [...path, name]
96
+      return [name]
107
     }
97
     }
108
-    if (node.children) {
109
-      const name = node.deptName || node.name || node.label
110
-      const found = buildPathForNode(node.children, targetId, [...path, name])
111
-      if (found.length > path.length) {
112
-        return found
98
+    if (node.children && node.children.length > 0) {
99
+      const childPath = buildPathForNode(node.children, targetId)
100
+      if (childPath !== null) {
101
+        const name = node.deptName || node.name || node.label
102
+        return [name, ...childPath]
113
       }
103
       }
114
     }
104
     }
115
   }
105
   }
116
-  return path
106
+  return null
117
 }
107
 }
118
 
108
 
119
 const queryUsers = async (query, cb) => {
109
 const queryUsers = async (query, cb) => {
@@ -123,7 +113,7 @@ const queryUsers = async (query, cb) => {
123
     const mapped = (res.data || []).map(u => {
113
     const mapped = (res.data || []).map(u => {
124
       let path = []
114
       let path = []
125
       if (u.deptId) {
115
       if (u.deptId) {
126
-        path = buildPathForNode(departments.value, u.deptId)
116
+        path = buildPathForNode(departments.value, u.deptId) || []
127
       }
117
       }
128
       return { ...u, value: u.nickName, path }
118
       return { ...u, value: u.nickName, path }
129
     })
119
     })
@@ -138,7 +128,7 @@ const queryDept = async (query, cb) => {
138
     const mapped = (res.data || []).map(d => {
128
     const mapped = (res.data || []).map(d => {
139
       let path = []
129
       let path = []
140
       if (d.id || d.deptId) {
130
       if (d.id || d.deptId) {
141
-        path = buildPathForNode(departments.value, d.deptId || d.id)
131
+        path = buildPathForNode(departments.value, d.deptId || d.id) || []
142
       }
132
       }
143
       return { ...d, value: d.deptName, path }
133
       return { ...d, value: d.deptName, path }
144
     })
134
     })
@@ -149,14 +139,14 @@ const queryDept = async (query, cb) => {
149
 const handleSelect = (item) => {
139
 const handleSelect = (item) => {
150
   
140
   
151
   if (props.deptType === 'user') {
141
   if (props.deptType === 'user') {
152
-    const path = item.path && item.path.length > 0 ? item.path : (item.deptId ? buildPathForNode(departments.value, item.deptId) : [])
142
+    const path = item.path && item.path.length > 0 ? item.path : (item.deptId ? buildPathForNode(departments.value, item.deptId) || [] : [])
153
     const name = item.nickName
143
     const name = item.nickName
154
 
144
 
155
     personName.value = path.length > 0 ? `${path.join(' / ')} / ${name}` : name
145
     personName.value = path.length > 0 ? `${path.join(' / ')} / ${name}` : name
156
     curQuery.value = { personName: item.nickName,id:item.id }
146
     curQuery.value = { personName: item.nickName,id:item.id }
157
     searchHandler(curQuery.value)
147
     searchHandler(curQuery.value)
158
   } else {
148
   } else {
159
-    const path = item.path && item.path.length > 0 ? item.path : ((item.id || item.deptId) ? buildPathForNode(departments.value, item.deptId || item.id) : [])
149
+    const path = item.path && item.path.length > 0 ? item.path : ((item.id || item.deptId) ? buildPathForNode(departments.value, item.deptId || item.id) || [] : [])
160
     const name = item.deptName || item.name || item.label
150
     const name = item.deptName || item.name || item.label
161
     personName.value = path.length > 0 ? path.join(' / ') : name
151
     personName.value = path.length > 0 ? path.join(' / ') : name
162
     if (props.deptType === 'BRIGADE' || props.deptType === 'STATION') {
152
     if (props.deptType === 'BRIGADE' || props.deptType === 'STATION') {
@@ -239,7 +229,7 @@ const handleNodeClick = (node) => {
239
   if (props.deptType === 'user') {
229
   if (props.deptType === 'user') {
240
     if (node.nodeType === 'user') {
230
     if (node.nodeType === 'user') {
241
    
231
    
242
-      const path = buildPathForNode(departments.value, node.deptId || node.id)
232
+      const path = buildPathForNode(departments.value, node.deptId || node.id) || []
243
       const name = node.label
233
       const name = node.label
244
       
234
       
245
       personName.value = path.length > 0 ? `${path.join(' / ')} / ${name}` : name
235
       personName.value = path.length > 0 ? `${path.join(' / ')} / ${name}` : name
@@ -248,7 +238,7 @@ const handleNodeClick = (node) => {
248
     }
238
     }
249
   } else {
239
   } else {
250
     if (node.deptType === props.deptType) {
240
     if (node.deptType === props.deptType) {
251
-      const path = buildPathForNode(departments.value, node.deptId || node.id)
241
+      const path = buildPathForNode(departments.value, node.deptId || node.id) || []
252
       const name = node.deptName || node.name || node.label;
242
       const name = node.deptName || node.name || node.label;
253
       personName.value = path.length > 0 ? path.join(' / ') : name
243
       personName.value = path.length > 0 ? path.join(' / ') : name
254
       if (props.deptType === 'BRIGADE' || props.deptType === 'STATION') {
244
       if (props.deptType === 'BRIGADE' || props.deptType === 'STATION') {
@@ -265,32 +255,7 @@ const handleNodeClick = (node) => {
265
   }
255
   }
266
 }
256
 }
267
 
257
 
268
-const setStyle = () => {
269
-  const root = document.querySelector(':root')
270
-  root.style.setProperty('--el-bg-color-overlay', '#1c1936')
271
-  root.style.setProperty('--el-border-color-extra-light', '#5c676d')
272
-  root.style.setProperty('--el-border-color-light', 'transparent')
273
-  root.style.setProperty('--el-popover-padding', '0px')
274
-  root.style.setProperty('--el-text-color-regular', '#fff')
275
-  root.style.setProperty('--el-fill-color-light', '#5c676d')
276
-  root.style.setProperty('--el-text-color-primary', '#fff')
277
-}
278
-
279
-const resetStyle = () => {
280
-  const root = document.querySelector(':root')
281
-  root.style.setProperty('--el-bg-color-overlay', '#ffffff')
282
-  root.style.setProperty('--el-border-color-extra-light', '#f2f6fc')
283
-  root.style.setProperty('--el-border-color-light', '#e4e7ed')
284
-  root.style.setProperty('--el-popover-padding', '12px')
285
-  root.style.setProperty('--el-text-color-regular', '#606266')
286
-  root.style.setProperty('--el-fill-color-light', '#f5f7fa')
287
-  root.style.setProperty('--el-text-color-primary', '#303133')
288
-
289
-}
290
-
291
 onMounted(async () => {
258
 onMounted(async () => {
292
-  setStyle()
293
-
294
   if (props.deptType === 'user') {
259
   if (props.deptType === 'user') {
295
     const res = await getDeptUserTree()
260
     const res = await getDeptUserTree()
296
     departments.value = res.data
261
     departments.value = res.data
@@ -299,48 +264,42 @@ onMounted(async () => {
299
     departments.value = filterDeptTree(res.data, props.deptType)
264
     departments.value = filterDeptTree(res.data, props.deptType)
300
   }
265
   }
301
 
266
 
302
-  const defaultId = defaultIdMap[props.deptType]
303
-  if (defaultId) {
304
-    const defaultNode = findNodeById(departments.value, defaultId)
305
-    if (defaultNode) {
306
-      currentKey.value = defaultId
307
-      if (props.deptType === 'user') {
308
-        const path = buildPathForNode(departments.value, defaultNode.deptId || defaultNode.id)
309
-        const name = defaultNode.label
310
-        personName.value = path.length > 0 ? `${path.join(' / ')} / ${name}` : name
311
-        curQuery.value = { personName: defaultNode.label,id:defaultNode.id }
312
-        searchHandler(curQuery.value)
313
-      } else {
314
-        const path = buildPathForNode(departments.value, defaultNode.deptId || defaultNode.id)
315
-        const name = defaultNode.deptName || defaultNode.name || defaultNode.label
316
-        personName.value = path.length > 0 ? path.join(' / ') : name
317
-        if (props.deptType === 'BRIGADE' || props.deptType === 'STATION') {
318
-          curQuery.value = { deptId: defaultNode.deptId || defaultNode.id }
319
-        }
320
-        if (props.deptType === 'MANAGER') {
321
-          curQuery.value = { teamId: defaultNode.deptId || defaultNode.id, deptId: defaultNode.deptId || defaultNode.id }
322
-        }
323
-        if (props.deptType === 'TEAMS') {
324
-          curQuery.value = { groupId: defaultNode.deptId || defaultNode.id, deptId: defaultNode.deptId || defaultNode.id }
325
-        }
326
-        searchHandler(curQuery.value)
267
+  const targetType = props.deptType === 'user' ? 'user' : props.deptType
268
+  const defaultNode = findFirstNodeByDeptType(departments.value, targetType)
269
+  if (defaultNode) {
270
+    const nodeId = defaultNode.deptId || defaultNode.id
271
+    currentKey.value = nodeId
272
+    if (props.deptType === 'user') {
273
+      const path = buildPathForNode(departments.value, nodeId) || []
274
+      const name = defaultNode.label
275
+      personName.value = path.length > 0 ? `${path.join(' / ')} / ${name}` : name
276
+      curQuery.value = { personName: defaultNode.label, id: defaultNode.id }
277
+      searchHandler(curQuery.value)
278
+    } else {
279
+      const path = buildPathForNode(departments.value, nodeId) || []
280
+      const name = defaultNode.deptName || defaultNode.name || defaultNode.label
281
+      personName.value = path.length > 0 ? path.join(' / ') : name
282
+      if (props.deptType === 'BRIGADE' || props.deptType === 'STATION') {
283
+        curQuery.value = { deptId: nodeId }
284
+      }
285
+      if (props.deptType === 'MANAGER') {
286
+        curQuery.value = { teamId: nodeId, deptId: nodeId }
327
       }
287
       }
328
-      nextTick(() => {
329
-        treeRef.value?.setCurrentKey(defaultId)
330
-      })
288
+      if (props.deptType === 'TEAMS') {
289
+        curQuery.value = { groupId: nodeId, deptId: nodeId }
290
+      }
291
+      searchHandler(curQuery.value)
331
     }
292
     }
293
+    nextTick(() => {
294
+      treeRef.value?.setCurrentKey(nodeId)
295
+    })
332
   }
296
   }
333
 })
297
 })
334
-onUnmounted(() => {
335
-  resetStyle()
336
-})
337
 
298
 
338
 defineExpose({
299
 defineExpose({
339
   getDefQuery() {
300
   getDefQuery() {
340
-
341
     return {
301
     return {
342
       ...getTimeRange(),
302
       ...getTimeRange(),
343
-
344
     }
303
     }
345
   }
304
   }
346
 })
305
 })

+ 4 - 3
src/views/portraitManagement/components/TestResult.vue

@@ -31,9 +31,10 @@ const setChartsOptionsBar = computed(() => {
31
       textStyle: { color: '#fff' }
31
       textStyle: { color: '#fff' }
32
     },
32
     },
33
     legend: {
33
     legend: {
34
-      top: '10%',
35
-      left: '0%',
36
-      orient: 'vertical',
34
+      type: 'scroll',
35
+      top: '0%',
36
+      left: 'center',
37
+      orient: 'horizontal',
37
       textStyle: { color: '#fff' }
38
       textStyle: { color: '#fff' }
38
     },
39
     },
39
     series: [{
40
     series: [{

+ 2 - 1
src/views/portraitManagement/deptProfile/index.vue

@@ -31,9 +31,10 @@ const queryParams = ref({})
31
 
31
 
32
 const pentagonItems = ref([])
32
 const pentagonItems = ref([])
33
 const invokerCountDeptTeamStats = (params) => {
33
 const invokerCountDeptTeamStats = (params) => {
34
+  console.log(params,999)
34
   const copyParams = {
35
   const copyParams = {
35
     deptId: params.deptId,
36
     deptId: params.deptId,
36
-
37
+    ...params
37
   }
38
   }
38
   countDeptTeamStats(copyParams).then(res => {
39
   countDeptTeamStats(copyParams).then(res => {
39
     if (res.code === 200 && res.data) {
40
     if (res.code === 200 && res.data) {

+ 25 - 7
src/views/portraitManagement/employeeProfile/index.vue

@@ -187,9 +187,9 @@
187
         <!-- 加分区域 -->
187
         <!-- 加分区域 -->
188
         <div class="tooltip-section">
188
         <div class="tooltip-section">
189
           <div class="section-list">
189
           <div class="section-list">
190
-            <div v-if="addList.length" class="list-item" v-for="(item, i) in addList" :key="i">
191
-              <span>{{ item.level3Name }}:</span>
192
-              <span class="add-text">{{ item.totalScore }}分</span>
190
+            <div v-if="addGroupList.length" class="list-item" v-for="(item, i) in addGroupList" :key="i">
191
+              <span>{{ item.name }}:</span>
192
+              <span class="add-text">+{{ item.total }}分</span>
193
             </div>
193
             </div>
194
             <div v-else class="p-empty">暂无加分记录</div>
194
             <div v-else class="p-empty">暂无加分记录</div>
195
           </div>
195
           </div>
@@ -201,11 +201,11 @@
201
         <!-- 扣分区域 -->
201
         <!-- 扣分区域 -->
202
         <div class="tooltip-section">
202
         <div class="tooltip-section">
203
           <div class="section-list">
203
           <div class="section-list">
204
-            <div v-if="deductList.length" class="list-item" v-for="(item, i) in deductList" :key="i">
205
-              <span>{{ item.level3Name }}:</span>
206
-              <span class="deduct-text">{{ item.totalScore }}分</span>
204
+            <div v-if="deductGroupList.length" class="list-item" v-for="(item, i) in deductGroupList" :key="i">
205
+              <span>{{ item.name }}:</span>
206
+              <span class="deduct-text">{{ item.total }}分</span>
207
             </div>
207
             </div>
208
-            <div v-if="!deductList.length" class="p-empty">暂无扣分记录</div>
208
+            <div v-if="!deductGroupList.length" class="p-empty">暂无扣分记录</div>
209
           </div>
209
           </div>
210
           <div class="section-total deduct">
210
           <div class="section-total deduct">
211
             <span>合计扣分:</span>
211
             <span>合计扣分:</span>
@@ -229,6 +229,8 @@ import { useECharts } from '@/hooks/useEcharts'
229
 import useUserStore from '@/store/modules/user'
229
 import useUserStore from '@/store/modules/user'
230
 import { useRouter } from 'vue-router'
230
 import { useRouter } from 'vue-router'
231
 
231
 
232
+defineOptions({ name: 'ProfileEmployeeProfile' })
233
+
232
 const router = useRouter()
234
 const router = useRouter()
233
 let radarChartInstance = null
235
 let radarChartInstance = null
234
 
236
 
@@ -252,6 +254,22 @@ const deductList = computed(() => {
252
   const all = scoreDetails.value.filter(d => d.totalScore != null && Number(d.totalScore) < 0)
254
   const all = scoreDetails.value.filter(d => d.totalScore != null && Number(d.totalScore) < 0)
253
   return activeDimName.value ? all.filter(d => d.dimensionName === activeDimName.value) : all
255
   return activeDimName.value ? all.filter(d => d.dimensionName === activeDimName.value) : all
254
 })
256
 })
257
+const addGroupList = computed(() => {
258
+  const groups = {}
259
+  addList.value.forEach(d => {
260
+    const key = d.level2Name || '其他'
261
+    groups[key] = (groups[key] || 0) + Number(d.totalScore)
262
+  })
263
+  return Object.entries(groups).map(([name, total]) => ({ name, total: total.toFixed(2) }))
264
+})
265
+const deductGroupList = computed(() => {
266
+  const groups = {}
267
+  deductList.value.forEach(d => {
268
+    const key = d.level2Name || '其他'
269
+    groups[key] = (groups[key] || 0) + Number(d.totalScore)
270
+  })
271
+  return Object.entries(groups).map(([name, total]) => ({ name, total: total.toFixed(2) }))
272
+})
255
 const addTotal = computed(() => {
273
 const addTotal = computed(() => {
256
   const s = addList.value.reduce((acc, d) => acc + Number(d.totalScore), 0)
274
   const s = addList.value.reduce((acc, d) => acc + Number(d.totalScore), 0)
257
   return (s > 0 ? '+' : '') + s.toFixed(2)
275
   return (s > 0 ? '+' : '') + s.toFixed(2)

+ 1 - 1
src/views/portraitManagement/employeeProfile/indexOld.vue

@@ -380,7 +380,7 @@ import { searchPortraitUsers, getEmployeePortrait } from '@/api/score/index'
380
 import { getDeptUserTree } from '@/api/item/items'
380
 import { getDeptUserTree } from '@/api/item/items'
381
 import { useDict } from '@/utils/dict'
381
 import { useDict } from '@/utils/dict'
382
 
382
 
383
-defineOptions({ name: 'EmployeeProfile' })
383
+// defineOptions({ name: 'EmployeeProfile' })
384
 
384
 
385
 const route = useRoute()
385
 const route = useRoute()
386
 const currentTime = ref('year')
386
 const currentTime = ref('year')

+ 3 - 1
src/views/portraitManagement/groupProfile/index.vue

@@ -33,7 +33,9 @@ const queryParams = ref({})
33
 const pentagonItems = ref([])
33
 const pentagonItems = ref([])
34
 const invokerCountDeptTeamStats = (params) => {
34
 const invokerCountDeptTeamStats = (params) => {
35
   const copyParams = {
35
   const copyParams = {
36
-    deptId: params.groupId
36
+    deptId: params.groupId,
37
+    startDate: params.startDate,
38
+    endDate: params.endDate
37
   }
39
   }
38
   countDeptTeamStats(copyParams).then(res => {
40
   countDeptTeamStats(copyParams).then(res => {
39
     if (res.code === 200 && res.data) {
41
     if (res.code === 200 && res.data) {

+ 3 - 1
src/views/portraitManagement/teamProfile/index.vue

@@ -31,7 +31,9 @@ const queryParams = ref({})
31
 const pentagonItems = ref([])
31
 const pentagonItems = ref([])
32
 const invokerCountDeptTeamStats = (params) => {
32
 const invokerCountDeptTeamStats = (params) => {
33
   const copyParams = {
33
   const copyParams = {
34
-    deptId: params.teamId
34
+    deptId: params.teamId,
35
+    startDate: params.startDate,
36
+    endDate: params.endDate
35
   }
37
   }
36
   countDeptTeamStats(copyParams).then(res => {
38
   countDeptTeamStats(copyParams).then(res => {
37
     if (res.code === 200 && res.data) {
39
     if (res.code === 200 && res.data) {

+ 222 - 58
src/views/score/event/index.vue

@@ -45,6 +45,27 @@
45
         <el-date-picker v-model="dateRange" type="daterange" value-format="YYYY-MM-DD" range-separator="-"
45
         <el-date-picker v-model="dateRange" type="daterange" value-format="YYYY-MM-DD" range-separator="-"
46
           start-placeholder="开始日期" end-placeholder="结束日期" clearable />
46
           start-placeholder="开始日期" end-placeholder="结束日期" clearable />
47
       </el-form-item>
47
       </el-form-item>
48
+      <el-form-item label="扣分类型" prop="scoreType">
49
+        <el-select v-model="queryParams.scoreType" placeholder="全部类型" clearable style="width:150px">
50
+          <el-option v-for="dict in score_type" :key="dict.value" :label="dict.label" :value="dict.value" />
51
+        </el-select>
52
+      </el-form-item>
53
+      <el-form-item label="区域" prop="regionalId">
54
+        <el-select v-model="queryParams.regionalId" placeholder="请选择区域" clearable filterable style="width:200px"
55
+          @change="handleRegionalChange">
56
+          <el-option v-for="item in regionalOptions" :key="item.id" :label="item.name" :value="item.id" />
57
+        </el-select>
58
+      </el-form-item>
59
+      <el-form-item label="工作点" prop="channelId">
60
+        <el-select v-model="queryParams.channelId" placeholder="请选择工作点" clearable filterable style="width:150px">
61
+          <el-option v-for="item in channelOptions" :key="item.id" :label="item.positionName" :value="item.id" />
62
+        </el-select>
63
+      </el-form-item>
64
+      <el-form-item label="岗位" prop="postId">
65
+        <el-tree-select v-model="queryParams.postId" :data="postTreeData"
66
+          :props="{ value: 'postId', label: 'postName', children: 'children' }" clearable filterable placeholder="请选择岗位"
67
+          check-strictly />
68
+      </el-form-item>
48
       <el-form-item>
69
       <el-form-item>
49
         <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
70
         <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
50
         <el-button icon="Refresh" @click="resetQuery">重置</el-button>
71
         <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -67,36 +88,40 @@
67
         <el-button type="warning" plain icon="Download" @click="handleExport"
88
         <el-button type="warning" plain icon="Download" @click="handleExport"
68
           v-hasPermi="['score:event:export']">导出</el-button>
89
           v-hasPermi="['score:event:export']">导出</el-button>
69
       </el-col>
90
       </el-col>
70
-      <el-col :span="1.5">
91
+      <!-- <el-col :span="1.5">
71
         <el-upload :show-file-list="false" accept=".xlsx,.xls" :auto-upload="false" :on-change="handleImportFile">
92
         <el-upload :show-file-list="false" accept=".xlsx,.xls" :auto-upload="false" :on-change="handleImportFile">
72
           <el-button type="info" plain icon="Upload" v-hasPermi="['score:event:import']">导入</el-button>
93
           <el-button type="info" plain icon="Upload" v-hasPermi="['score:event:import']">导入</el-button>
73
         </el-upload>
94
         </el-upload>
74
-      </el-col>
95
+      </el-col> -->
75
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
96
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
76
     </el-row>
97
     </el-row>
77
 
98
 
78
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
79
-      <el-table-column type="selection" width="55" align="center" />
80
-      <el-table-column label="配分层级" align="center" prop="org" width="110">
99
+    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange" style="width: 100%;" fit="true"
100
+      :scrollbar-always-on="true">
101
+      <el-table-column type="selection" width="55" align="center" resizable />
102
+      <el-table-column label="配分层级" align="center" prop="org" width="110" resizable>
81
         <template #default="{ row }"><dict-tag :options="score_level" :value="row.org" /></template>
103
         <template #default="{ row }"><dict-tag :options="score_level" :value="row.org" /></template>
82
       </el-table-column>
104
       </el-table-column>
83
-      <el-table-column label="事件时间" align="center" prop="eventTime" width="120">
105
+      <el-table-column label="事件时间" align="center" prop="eventTime" width="120" resizable>
84
         <template #default="{ row }">{{ parseTime(row.eventTime, '{y}-{m}-{d}') }}</template>
106
         <template #default="{ row }">{{ parseTime(row.eventTime, '{y}-{m}-{d}') }}</template>
85
       </el-table-column>
107
       </el-table-column>
86
-      <el-table-column label="维度" align="center" prop="dimensionName" width="110" />
87
-      <el-table-column label="二级指标" align="center" prop="level2Name" show-overflow-tooltip />
88
-      <el-table-column label="三级指标" align="center" prop="level3Name" show-overflow-tooltip />
89
-      <el-table-column label="责任人" align="center" prop="personName" width="80" />
90
-      <el-table-column label="部门" align="center" prop="deptName" />
91
-      <el-table-column label="班组" align="center" prop="teamName" />
92
-      <el-table-column label="基础分值" align="center" prop="scoreValue" width="90">
108
+      <el-table-column label="维度" align="center" prop="dimensionName" width="150" resizable />
109
+      <el-table-column label="二级指标" align="center" prop="level2Name" min-width="250" show-overflow-tooltip resizable />
110
+      <el-table-column label="三级指标" align="center" prop="level3Name" min-width="250" show-overflow-tooltip resizable />
111
+      <el-table-column label="责任人" align="center" prop="personName" width="80" resizable />
112
+      <el-table-column label="部门" align="center" prop="deptName" min-width="120" resizable />
113
+      <el-table-column label="班组" align="center" prop="teamName" min-width="120" resizable />
114
+      <el-table-column label="区域" align="center" prop="regionalName" min-width="200" resizable />
115
+      <el-table-column label="工作点" align="center" prop="channelName" min-width="100" resizable />
116
+      <el-table-column label="岗位" align="center" prop="postName" min-width="190" resizable />
117
+      <el-table-column label="基础分值" align="center" prop="scoreValue" width="90" resizable>
93
         <template #default="{ row }">
118
         <template #default="{ row }">
94
           <span :style="{ color: row.scoreValue > 0 ? '#67c23a' : row.scoreValue < 0 ? '#f56c6c' : '' }">
119
           <span :style="{ color: row.scoreValue > 0 ? '#67c23a' : row.scoreValue < 0 ? '#f56c6c' : '' }">
95
             {{ row.scoreValue > 0 ? '+' : '' }}{{ row.scoreValue }}
120
             {{ row.scoreValue > 0 ? '+' : '' }}{{ row.scoreValue }}
96
           </span>
121
           </span>
97
         </template>
122
         </template>
98
       </el-table-column>
123
       </el-table-column>
99
-      <el-table-column label="叠加分" align="center" prop="cascadeScore" width="80">
124
+      <el-table-column label="叠加分" align="center" prop="cascadeScore" width="80" resizable>
100
         <template #default="{ row }">
125
         <template #default="{ row }">
101
           <span v-if="row.cascadeScore" :style="{ color: row.cascadeScore > 0 ? '#67c23a' : '#f56c6c' }">
126
           <span v-if="row.cascadeScore" :style="{ color: row.cascadeScore > 0 ? '#67c23a' : '#f56c6c' }">
102
             {{ row.cascadeScore > 0 ? '+' : '' }}{{ row.cascadeScore }}
127
             {{ row.cascadeScore > 0 ? '+' : '' }}{{ row.cascadeScore }}
@@ -104,22 +129,22 @@
104
           <span v-else style="color:#c0c4cc">-</span>
129
           <span v-else style="color:#c0c4cc">-</span>
105
         </template>
130
         </template>
106
       </el-table-column>
131
       </el-table-column>
107
-      <el-table-column label="总分值" align="center" prop="totalScore" width="90">
132
+      <el-table-column label="总分值" align="center" prop="totalScore" width="90" resizable>
108
         <template #default="{ row }">
133
         <template #default="{ row }">
109
           <strong :style="{ color: row.totalScore > 0 ? '#67c23a' : row.totalScore < 0 ? '#f56c6c' : '' }">
134
           <strong :style="{ color: row.totalScore > 0 ? '#67c23a' : row.totalScore < 0 ? '#f56c6c' : '' }">
110
             {{ row.totalScore > 0 ? '+' : '' }}{{ row.totalScore }}
135
             {{ row.totalScore > 0 ? '+' : '' }}{{ row.totalScore }}
111
           </strong>
136
           </strong>
112
         </template>
137
         </template>
113
       </el-table-column>
138
       </el-table-column>
114
-      <el-table-column label="来源" align="center" width="90">
139
+      <el-table-column label="来源" align="center" width="90" resizable>
115
         <template #default="{ row }">
140
         <template #default="{ row }">
116
           <el-tag :type="row.sourceType === '1' ? 'primary' : 'warning'" size="small">
141
           <el-tag :type="row.sourceType === '1' ? 'primary' : 'warning'" size="small">
117
             {{ row.sourceType === '1' ? '手动录入' : '台账同步' }}
142
             {{ row.sourceType === '1' ? '手动录入' : '台账同步' }}
118
           </el-tag>
143
           </el-tag>
119
         </template>
144
         </template>
120
       </el-table-column>
145
       </el-table-column>
121
-      <el-table-column label="事件描述" align="center" prop="eventDesc" show-overflow-tooltip />
122
-      <el-table-column label="操作" align="center" width="180">
146
+      <el-table-column label="事件描述" min-width="450" align="center" prop="eventDesc" show-overflow-tooltip resizable />
147
+      <el-table-column label="操作" align="center" width="180" resizable fixed="right">
123
         <template #default="{ row }">
148
         <template #default="{ row }">
124
           <el-button link type="primary" icon="Edit" @click="handleUpdate(row)"
149
           <el-button link type="primary" icon="Edit" @click="handleUpdate(row)"
125
             v-hasPermi="['score:event:edit']">修改</el-button>
150
             v-hasPermi="['score:event:edit']">修改</el-button>
@@ -180,8 +205,18 @@
180
             </el-form-item>
205
             </el-form-item>
181
           </el-col>
206
           </el-col>
182
           <el-col :span="12">
207
           <el-col :span="12">
183
-            <el-form-item label="位置">
184
-              <el-input v-model="form.location" placeholder="区域/通道" />
208
+            <el-form-item label="区域">
209
+              <el-select v-model="form.regionalId" placeholder="请选择区域" clearable filterable style="width:100%"
210
+                @change="handleFormRegionalChange">
211
+                <el-option v-for="item in regionalOptions" :key="item.id" :label="item.name" :value="item.id" />
212
+              </el-select>
213
+            </el-form-item>
214
+          </el-col>
215
+          <el-col :span="12">
216
+            <el-form-item label="工作点">
217
+              <el-select v-model="form.channelId" placeholder="请选择工作点" clearable filterable style="width:100%">
218
+                <el-option v-for="item in formChannelOptions" :key="item.id" :label="item.name" :value="item.id" />
219
+              </el-select>
185
             </el-form-item>
220
             </el-form-item>
186
           </el-col>
221
           </el-col>
187
           <el-col :span="12">
222
           <el-col :span="12">
@@ -217,6 +252,13 @@
217
             </el-form-item>
252
             </el-form-item>
218
           </el-col>
253
           </el-col>
219
           <el-col :span="12">
254
           <el-col :span="12">
255
+            <el-form-item label="岗位">
256
+              <el-tree-select v-model="form.postId" :data="postTreeData"
257
+                :props="{ value: 'postId', label: 'postName', children: 'children' }" clearable filterable
258
+                placeholder="请选择岗位" style="width:100%" check-strictly />
259
+            </el-form-item>
260
+          </el-col>
261
+          <el-col :span="12">
220
             <el-form-item label="基础分值" prop="scoreValue">
262
             <el-form-item label="基础分值" prop="scoreValue">
221
               <el-input-number v-model="form.scoreValue" :precision="2" style="width:100%" placeholder="正数=加分 负数=扣分" />
263
               <el-input-number v-model="form.scoreValue" :precision="2" style="width:100%" placeholder="正数=加分 负数=扣分" />
222
             </el-form-item>
264
             </el-form-item>
@@ -251,6 +293,8 @@ import { ref, reactive, computed, watch, onMounted, getCurrentInstance } from 'v
251
 import { ElMessage, ElMessageBox } from 'element-plus'
293
 import { ElMessage, ElMessageBox } from 'element-plus'
252
 import { useRoute } from 'vue-router'
294
 import { useRoute } from 'vue-router'
253
 import { listUser, getDeptOrgInfo, getUserOrgInfo } from '@/api/system/user'
295
 import { listUser, getDeptOrgInfo, getUserOrgInfo } from '@/api/system/user'
296
+import { listPosition } from '@/api/system/position'
297
+import { listAllTree } from '@/api/system/post'
254
 import {
298
 import {
255
   listScoreEvent, addScoreEvent, updateScoreEvent, delScoreEvent,
299
   listScoreEvent, addScoreEvent, updateScoreEvent, delScoreEvent,
256
   exportScoreEvent, importScoreEvent
300
   exportScoreEvent, importScoreEvent
@@ -263,7 +307,7 @@ import { parseTime } from '@/utils/ruoyi'
263
 defineOptions({ name: 'ScoreEvent' })
307
 defineOptions({ name: 'ScoreEvent' })
264
 
308
 
265
 const { proxy } = getCurrentInstance()
309
 const { proxy } = getCurrentInstance()
266
-const { score_level } = proxy.useDict('score_level')
310
+const { score_level, score_type } = proxy.useDict('score_level', 'score_type')
267
 
311
 
268
 const loading = ref(false), list = ref([]), total = ref(0), showSearch = ref(true)
312
 const loading = ref(false), list = ref([]), total = ref(0), showSearch = ref(true)
269
 const dateRange = ref([]), queryRef = ref(null), formRef = ref(null)
313
 const dateRange = ref([]), queryRef = ref(null), formRef = ref(null)
@@ -282,9 +326,13 @@ const queryDeptOptions = ref([])
282
 const queryTeamOptions = ref([])
326
 const queryTeamOptions = ref([])
283
 const queryGroupOptions = ref([])
327
 const queryGroupOptions = ref([])
284
 const queryPersonOptions = ref([])
328
 const queryPersonOptions = ref([])
329
+const regionalOptions = ref([])
330
+const channelOptions = ref([])
331
+const postTreeData = ref([])
285
 
332
 
286
-const queryParams = reactive({ pageNum: 1, pageSize: 10, personId: null, personName: '', deptId: null, deptName: '', teamId: null, teamName: '', groupId: null, groupName: '', dimensionId: null, sourceType: '', org: '' })
287
-const form = reactive({ id: null, dimensionId: null, dimensionName: '', indicatorId: null, level2Id: null, level2Name: '', level3Id: null, level3Name: '', level4Id: null, level4Name: '', eventTime: '', location: '', personId: null, deptName: '', deptId: null, teamId: null, groupId: null, scoreValue: 0, cascadeScore: 0, eventDesc: '', remark: '', org: '' })
333
+const queryParams = reactive({ pageNum: 1, pageSize: 10, personId: null, personName: '', deptId: null, deptName: '', teamId: null, teamName: '', groupId: null, groupName: '', dimensionId: null, sourceType: '', org: '', scoreType: null, regionalId: null, channelId: null, postId: null })
334
+const form = reactive({ id: null, dimensionId: null, dimensionName: '', indicatorId: null, level2Id: null, level2Name: '', level3Id: null, level3Name: '', level4Id: null, level4Name: '', eventTime: '', location: '', personId: null, deptName: '', deptId: null, teamId: null, groupId: null, scoreValue: 0, cascadeScore: 0, eventDesc: '', remark: '', org: '', regionalId: null, channelId: null, postId: null })
335
+const formChannelOptions = ref([])
288
 const rules = computed(() => {
336
 const rules = computed(() => {
289
   return {
337
   return {
290
     org: [{ required: true, message: '请选择配分层级', trigger: 'submit' }],
338
     org: [{ required: true, message: '请选择配分层级', trigger: 'submit' }],
@@ -300,6 +348,7 @@ const rules = computed(() => {
300
 
348
 
301
 // 搜索表单责任人选项:未选择部门/班组/小组时使用全量人员,否则使用过滤后的人员
349
 // 搜索表单责任人选项:未选择部门/班组/小组时使用全量人员,否则使用过滤后的人员
302
 const searchPersonOptions = computed(() => {
350
 const searchPersonOptions = computed(() => {
351
+
303
   if (queryParams.deptId || queryParams.teamId || queryParams.groupId) {
352
   if (queryParams.deptId || queryParams.teamId || queryParams.groupId) {
304
     return queryPersonOptions.value
353
     return queryPersonOptions.value
305
   }
354
   }
@@ -328,6 +377,10 @@ async function handleFormLevelChange() {
328
   teamOptions.value = []; groupOptions.value = []; personOptions.value = []
377
   teamOptions.value = []; groupOptions.value = []; personOptions.value = []
329
 
378
 
330
   const org = form.org
379
   const org = form.org
380
+
381
+
382
+  const r = await getDimensionAll({ pageNum: 1, pageSize: 100, org })
383
+  dimensionOptions.value = r.data || []
331
   // if (org === '2') {
384
   // if (org === '2') {
332
   await loadAllTeams()
385
   await loadAllTeams()
333
   // } else if (org === '3') {
386
   // } else if (org === '3') {
@@ -335,9 +388,6 @@ async function handleFormLevelChange() {
335
   // } else if (org === '4') {
388
   // } else if (org === '4') {
336
   await loadAllPersons()
389
   await loadAllPersons()
337
   // }
390
   // }
338
-
339
-  const r = await getDimensionAll({ pageNum: 1, pageSize: 100, org })
340
-  dimensionOptions.value = r.data || []
341
 }
391
 }
342
 
392
 
343
 async function loadAllTeams() {
393
 async function loadAllTeams() {
@@ -357,9 +407,33 @@ async function loadAllGroups() {
357
 
407
 
358
 async function loadAllPersons() {
408
 async function loadAllPersons() {
359
   const r = await listUser({ pageSize: 9999 })
409
   const r = await listUser({ pageSize: 9999 })
410
+
360
   personOptions.value = r.rows || []
411
   personOptions.value = r.rows || []
361
 }
412
 }
362
 
413
 
414
+async function loadRegions() {
415
+  const r = await listPosition({ positionType: 'REGIONAL' })
416
+  regionalOptions.value = r.data || []
417
+}
418
+
419
+async function handleRegionalChange(val) {
420
+  queryParams.channelId = null
421
+  channelOptions.value = []
422
+  if (val) {
423
+    const r = await listPosition({ parentId: val })
424
+    channelOptions.value = r.data || []
425
+  }
426
+}
427
+
428
+async function handleFormRegionalChange(val) {
429
+  form.channelId = null
430
+  formChannelOptions.value = []
431
+  if (val) {
432
+    const r = await listPosition({ parentId: val })
433
+    formChannelOptions.value = r.data || []
434
+  }
435
+}
436
+
363
 function handleBrigadeChange() {
437
 function handleBrigadeChange() {
364
 }
438
 }
365
 
439
 
@@ -443,60 +517,90 @@ function getList() {
443
 function handleQuery() { queryParams.pageNum = 1; getList() }
517
 function handleQuery() { queryParams.pageNum = 1; getList() }
444
 function resetQuery() {
518
 function resetQuery() {
445
   dateRange.value = []
519
   dateRange.value = []
446
-  Object.assign(queryParams, { 
447
-    pageNum: 1, 
448
-    pageSize: 10, 
449
-    personId: null, 
450
-    personName: '', 
451
-    deptId: null, 
452
-    deptName: '', 
453
-    teamId: null, 
454
-    teamName: '', 
455
-    groupId: null, 
456
-    groupName: '', 
457
-    dimensionId: null, 
458
-    sourceType: '', 
459
-    org: '' 
520
+  Object.assign(queryParams, {
521
+    pageNum: 1,
522
+    pageSize: 10,
523
+    personId: null,
524
+    personName: '',
525
+    deptId: null,
526
+    deptName: '',
527
+    teamId: null,
528
+    teamName: '',
529
+    groupId: null,
530
+    groupName: '',
531
+    dimensionId: null,
532
+    sourceType: '',
533
+    org: '',
534
+    scoreType: null,
535
+    regionalId: null,
536
+    channelId: null,
537
+    postId: null
460
   })
538
   })
461
-  queryTeamOptions.value = []; queryGroupOptions.value = []; queryPersonOptions.value = []
539
+  queryTeamOptions.value = []; queryGroupOptions.value = []; queryPersonOptions.value = []; channelOptions.value = []
462
   queryRef.value?.resetFields()
540
   queryRef.value?.resetFields()
463
   handleQuery()
541
   handleQuery()
464
 }
542
 }
465
 function handleSelectionChange(sel) { ids.value = sel.map(s => s.id); single.value = sel.length !== 1; multiple.value = !sel.length }
543
 function handleSelectionChange(sel) { ids.value = sel.map(s => s.id); single.value = sel.length !== 1; multiple.value = !sel.length }
466
 
544
 
467
 function resetForm() {
545
 function resetForm() {
468
-  Object.assign(form, { id: null, dimensionId: null, dimensionName: '', indicatorId: null, level2Id: null, level2Name: '', level3Id: null, level3Name: '', level4Id: null, level4Name: '', eventTime: '', location: '', personId: null, deptName: '', deptId: null, teamId: null, groupId: null, scoreValue: 0, cascadeScore: 0, eventDesc: '', remark: '', org: '' })
546
+  Object.assign(form, { id: null, dimensionId: null, dimensionName: '', indicatorId: null, level2Id: null, level2Name: '', level3Id: null, level3Name: '', level4Id: null, level4Name: '', eventTime: '', location: '', personId: null, deptName: '', deptId: null, teamId: null, groupId: null, scoreValue: 0, cascadeScore: 0, eventDesc: '', remark: '', org: '', regionalId: null, channelId: null, postId: null })
469
   level2Options.value = []; level3Options.value = []; level4Options.value = []
547
   level2Options.value = []; level3Options.value = []; level4Options.value = []
470
-  teamOptions.value = []; groupOptions.value = []; personOptions.value = []
548
+  teamOptions.value = []; groupOptions.value = []; personOptions.value = []; formChannelOptions.value = []
471
 }
549
 }
472
 
550
 
473
 function handleAdd() { resetForm(); dialogTitle.value = '新增配分事项'; dialogVisible.value = true }
551
 function handleAdd() { resetForm(); dialogTitle.value = '新增配分事项'; dialogVisible.value = true }
474
-function handleUpdate(row) {
552
+async function handleUpdate(row) {
475
   resetForm()
553
   resetForm()
476
   const record = row?.id ? row : list.value.find(r => r.id === ids.value[0])
554
   const record = row?.id ? row : list.value.find(r => r.id === ids.value[0])
477
   if (record) {
555
   if (record) {
478
     Object.assign(form, record)
556
     Object.assign(form, record)
479
     const org = String(record.org)
557
     const org = String(record.org)
480
     form.org = org
558
     form.org = org
559
+
560
+    // 加载区域和工作点
561
+    if (record.regionalId) {
562
+      await handleFormRegionalChange(record.regionalId)
563
+    }
564
+
565
+    // 加载队室/班组和通道/小组
566
+    if (record.deptId) {
567
+      // 先加载队室/班组
568
+      const r = await deptTreeSelect({ parentId: record.deptId })
569
+      teamOptions.value = r.data || []
570
+
571
+      if (record.teamId) {
572
+        // 再加载通道/小组
573
+        const r2 = await deptTreeSelect({ parentId: record.teamId })
574
+        groupOptions.value = r2.data || []
575
+
576
+        // 最后加载责任人
577
+        if (record.groupId) {
578
+          const r3 = await listUser({ deptId: record.groupId })
579
+          personOptions.value = r3.rows || []
580
+        }
581
+      }
582
+    } else if (org === '2') {
583
+      await loadAllTeams()
584
+    } else if (org === '3') {
585
+      await loadAllGroups()
586
+    } else if (org === '4') {
587
+      await loadAllPersons()
588
+    }
589
+
481
     if (org === '1') {
590
     if (org === '1') {
482
       form.deptId = record.deptId || null
591
       form.deptId = record.deptId || null
483
     } else if (org === '2') {
592
     } else if (org === '2') {
484
-      loadAllTeams().then(() => {
485
-        form.teamId = record.teamId || null
486
-        if (form.teamId) handleDepartmentChange(form.teamId)
487
-      })
593
+      form.teamId = record.teamId || null
594
+      if (form.teamId) await handleDepartmentChange(form.teamId)
488
     } else if (org === '3') {
595
     } else if (org === '3') {
489
-      loadAllGroups().then(() => {
490
-        form.groupId = record.groupId || null
491
-        if (form.groupId) handleGroupChange(form.groupId)
492
-      })
596
+      form.groupId = record.groupId || null
597
+      if (form.groupId) await handleGroupChange(form.groupId)
493
     } else if (org === '4') {
598
     } else if (org === '4') {
494
-      loadAllPersons().then(() => {
495
-        form.personId = record.personId || null
496
-        if (form.personId) handlePersonChange(form.personId)
497
-      })
599
+      form.personId = record.personId || null
600
+      if (form.personId) await handlePersonChange(form.personId)
498
     }
601
     }
499
-    if (record.dimensionId) onDimensionChange(record.dimensionId, true)
602
+
603
+    if (record.dimensionId) await onDimensionChange(record.dimensionId, true)
500
     if (record.level2Id) onLevel2Change(record.level2Id, true)
604
     if (record.level2Id) onLevel2Change(record.level2Id, true)
501
     if (record.level3Id) onLevel3Change(record.level3Id, true)
605
     if (record.level3Id) onLevel3Change(record.level3Id, true)
502
     if (record.level4Id) onLevel4Change(record.level4Id, true)
606
     if (record.level4Id) onLevel4Change(record.level4Id, true)
@@ -548,6 +652,20 @@ function onLevel4Change(val) {
548
   }
652
   }
549
 }
653
 }
550
 
654
 
655
+// 递归查找树形结构中的节点
656
+const findTreeNode = (nodes, targetId, idKey, nameKey) => {
657
+  for (const node of nodes) {
658
+    if (node[idKey] === targetId) {
659
+      return node
660
+    }
661
+    if (node.children) {
662
+      const found = findTreeNode(node.children, targetId, idKey, nameKey)
663
+      if (found) return found
664
+    }
665
+  }
666
+  return null
667
+}
668
+
551
 async function submitForm() {
669
 async function submitForm() {
552
   await formRef.value.validate()
670
   await formRef.value.validate()
553
   let copyForm = { ...form }
671
   let copyForm = { ...form }
@@ -568,6 +686,18 @@ async function submitForm() {
568
     const g = groupOptions.value.find(g => g.id === copyForm.groupId)
686
     const g = groupOptions.value.find(g => g.id === copyForm.groupId)
569
     if (g) copyForm.groupName = g.label
687
     if (g) copyForm.groupName = g.label
570
   }
688
   }
689
+  if (copyForm.regionalId) {
690
+    const r = regionalOptions.value.find(r => r.id === copyForm.regionalId)
691
+    if (r) copyForm.regionalName = r.name
692
+  }
693
+  if (copyForm.channelId) {
694
+    const c = formChannelOptions.value.find(c => c.id === copyForm.channelId)
695
+    if (c) copyForm.channelName = c.name || c.positionName
696
+  }
697
+  if (copyForm.postId) {
698
+    const postNode = findTreeNode(postTreeData.value, copyForm.postId, 'postId', 'postName')
699
+    if (postNode) copyForm.postName = postNode.postName
700
+  }
571
 
701
 
572
   if (form.id) { await updateScoreEvent(copyForm); ElMessage.success('修改成功') }
702
   if (form.id) { await updateScoreEvent(copyForm); ElMessage.success('修改成功') }
573
   else { await addScoreEvent(copyForm); ElMessage.success('新增成功') }
703
   else { await addScoreEvent(copyForm); ElMessage.success('新增成功') }
@@ -619,5 +749,39 @@ watch(() => route.query, (query) => {
619
   isInit = false
749
   isInit = false
620
 }, { immediate: true })
750
 }, { immediate: true })
621
 
751
 
622
-onMounted(() => { loadDimensions(); loadDepts(); loadQueryDepts(); loadAllPersons(); getList() })
752
+// 递归处理岗位树,禁用第一级
753
+const processPostTree = (nodes, isFirstLevel = true) => {
754
+  return nodes.map(node => {
755
+    const newNode = { ...node, disabled: isFirstLevel }
756
+    if (node.children) {
757
+      newNode.children = processPostTree(node.children, false)
758
+    }
759
+    return newNode
760
+  })
761
+}
762
+
763
+onMounted(() => {
764
+  loadDimensions();
765
+  loadDepts();
766
+  loadQueryDepts();
767
+  loadAllPersons();
768
+  loadRegions();
769
+  listAllTree().then(res => {
770
+    postTreeData.value = processPostTree(res.data || [])
771
+  });
772
+  getList()
773
+})
623
 </script>
774
 </script>
775
+
776
+<style scoped lang="less">
777
+/* Element Plus表格横向滚动配置 */
778
+.table-container :deep(.el-table) {
779
+  width: 100%;
780
+  min-width: 100%;
781
+}
782
+
783
+.table-container :deep(.el-table .el-table__header-wrapper),
784
+.table-container :deep(.el-table .el-table__body-wrapper) {
785
+  overflow-x: auto !important;
786
+}
787
+</style>