Ver código fonte

Merge branch 'employeeScreen'

huoyi 6 dias atrás
pai
commit
cc7c89a744
37 arquivos alterados com 741 adições e 1505 exclusões
  1. 13 0
      src/api/ledger/index.js
  2. 3 3
      src/router/index.js
  3. 180 66
      src/views/assistant/index.vue
  4. 2 2
      src/views/ledger/bannerLetter/index.vue
  5. 2 2
      src/views/ledger/channelPassRate/index.vue
  6. 2 2
      src/views/ledger/complaint/index.vue
  7. 2 2
      src/views/ledger/dailyTraining/index.vue
  8. 2 2
      src/views/ledger/dormFireSafety/index.vue
  9. 2 2
      src/views/ledger/examScore/index.vue
  10. 11 2
      src/views/ledger/import/index.vue
  11. 4 4
      src/views/ledger/leaveSpecial/index.vue
  12. 2 2
      src/views/ledger/patrolInspection/index.vue
  13. 169 0
      src/views/ledger/qualificationCertificateStatus/index.vue
  14. 0 0
      src/views/ledger/qualificationCertificateStatus/职业资格证书情况
  15. 5 5
      src/views/ledger/realtimeInterception/index.vue
  16. 3 3
      src/views/ledger/rewardApproval/index.vue
  17. 2 2
      src/views/ledger/rewardPenalty/index.vue
  18. 2 2
      src/views/ledger/securityTest/index.vue
  19. 2 2
      src/views/ledger/seizureStats/index.vue
  20. 5 5
      src/views/ledger/servicePatrol/index.vue
  21. 5 5
      src/views/ledger/supervisionProblem/index.vue
  22. 3 3
      src/views/ledger/terminalBonus/index.vue
  23. 2 2
      src/views/ledger/trainingIssue/index.vue
  24. 2 2
      src/views/ledger/unsafeEvent/index.vue
  25. 1 1
      src/views/portraitManagement/components/ChannelCheckChart.vue
  26. 21 0
      src/views/portraitManagement/components/ProfileBasicDistribution.vue
  27. 23 2
      src/views/portraitManagement/components/ProfilePositionDistribution.vue
  28. 68 4
      src/views/portraitManagement/components/ProfileRadar.vue
  29. 1 0
      src/views/portraitManagement/components/SeizedItems.vue
  30. 5 1
      src/views/portraitManagement/components/SeizedNum.vue
  31. 1 1
      src/views/portraitManagement/components/SupervisionDistribution.vue
  32. 1 1
      src/views/portraitManagement/deptProfile/component/runData.vue
  33. 95 8
      src/views/portraitManagement/employeeProfile/index.vue
  34. 0 1306
      src/views/portraitManagement/employeeProfile/indexOld.vue
  35. 1 1
      src/views/portraitManagement/teamProfile/component/runData.vue
  36. 18 4
      src/views/score/event/index.vue
  37. 81 56
      src/views/warningPage/index.vue

+ 13 - 0
src/api/ledger/index.js

@@ -285,3 +285,16 @@ export function getTrainingIssue(id) {
285
 export function exportTrainingIssue(query) {
285
 export function exportTrainingIssue(query) {
286
   return request({ url: '/ledger/trainingIssue/export', method: 'post', params: query, responseType: 'blob' })
286
   return request({ url: '/ledger/trainingIssue/export', method: 'post', params: query, responseType: 'blob' })
287
 }
287
 }
288
+
289
+// ===== 资格证书状态 =====
290
+export function listQualificationCertificateStatus(query) {
291
+  return request({ url: '/ledger/qualificationLevel/list', method: 'get', params: query })
292
+}
293
+//导入职业资格等级
294
+export function importQualificationLevel(data) {
295
+  return request({ url: '/ledger/import/qualificationLevel', method: 'post', data })
296
+}
297
+//通过用户id获取职业资格等级获取时间信息
298
+export function getQualificationLevelTime(query) {
299
+  return request({ url: '/ledger/qualificationLevel/user', method: 'get',params: query })
300
+}

+ 3 - 3
src/router/index.js

@@ -92,9 +92,9 @@ export const constantRoutes = [
92
     children: [
92
     children: [
93
       {
93
       {
94
         path: '/index',
94
         path: '/index',
95
-        component: () => import('@/views/warningPage'),
96
-        name: 'WarningPage',
97
-        meta: { title: '预警页面', icon: 'dashboard' }
95
+        component: () => import('@/views/assistant'),
96
+        name: 'Assistant',
97
+        meta: { title: 'AI助手', icon: 'dashboard' }
98
       },
98
       },
99
       // {
99
       // {
100
       //   path: '/dashboard-work',
100
       //   path: '/dashboard-work',

+ 180 - 66
src/views/assistant/index.vue

@@ -60,6 +60,17 @@
60
                       min-width="100" />
60
                       min-width="100" />
61
                   </el-table>
61
                   </el-table>
62
                   <div v-else-if="msg.result.rows" class="no-data">暂无数据</div>
62
                   <div v-else-if="msg.result.rows" class="no-data">暂无数据</div>
63
+                  
64
+                  <!-- SQL 折叠 -->
65
+                  <div v-if="msg.result.sql" class="sql-block">
66
+                    <div class="sql-toggle" @click="toggleSql(msg.id)">
67
+                      <span class="sql-label">SQL</span>
68
+                      <span class="sql-arrow">{{ msg.showSql ? '▲' : '▼' }}</span>
69
+                    </div>
70
+                    <div v-if="msg.showSql" class="sql-code">
71
+                      <pre>{{ msg.result.sql }}</pre>
72
+                    </div>
73
+                  </div>
63
                 </div>
74
                 </div>
64
 
75
 
65
                 <!-- 耗时 -->
76
                 <!-- 耗时 -->
@@ -81,6 +92,11 @@
81
         </div>
92
         </div>
82
       </div>
93
       </div>
83
 
94
 
95
+      <!-- 意图澄清 -->
96
+      <div v-if="clarifyQuestion" class="clarify-bar">
97
+        <span class="clarify-text">{{ clarifyQuestion }}</span>
98
+      </div>
99
+
84
       <!-- 底部输入区 -->
100
       <!-- 底部输入区 -->
85
       <div class="chat-container">
101
       <div class="chat-container">
86
         <div class="quick-action">
102
         <div class="quick-action">
@@ -88,10 +104,9 @@
88
           <el-button class="report-btn" @click="handlePerformanceClick">绩效分析报告</el-button>
104
           <el-button class="report-btn" @click="handlePerformanceClick">绩效分析报告</el-button>
89
           <el-button class="report-btn" @click="handleUseReportClick">使用报表</el-button>
105
           <el-button class="report-btn" @click="handleUseReportClick">使用报表</el-button>
90
         </div>
106
         </div>
91
-        <!--请输入您的问题,按 Enter 发送...-->
92
         <div class="input-container">
107
         <div class="input-container">
93
-          <el-input v-model="inputMessage" type="textarea" :rows="3" placeholder="功能开发中,请敬请期待"
94
-            class="chat-input" @keydown.enter.exact.prevent="handleSend" :disabled="true" />
108
+          <el-input v-model="inputMessage" type="textarea" :rows="3" placeholder="请输入您的问题,按 Enter 发送..."
109
+            class="chat-input" @keydown.enter.exact.prevent="handleSend" />
95
           <el-button :disabled="!inputMessage.trim() || isLoading" circle class="send-btn" @click="handleSend">
110
           <el-button :disabled="!inputMessage.trim() || isLoading" circle class="send-btn" @click="handleSend">
96
             <svg viewBox="0 0 24 24" fill="currentColor" width="18" height="18">
111
             <svg viewBox="0 0 24 24" fill="currentColor" width="18" height="18">
97
               <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" />
112
               <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" />
@@ -114,7 +129,9 @@ import PerformanceAnalysis from './components/performanceAnalysis.vue'
114
 import useUserStore from '@/store/modules/user'
129
 import useUserStore from '@/store/modules/user'
115
 import UseReports from './components/useReports.vue'
130
 import UseReports from './components/useReports.vue'
116
 const userStore = useUserStore()
131
 const userStore = useUserStore()
117
-const AI_SERVICE_URL = import.meta.env.VITE_AI_SERVICE_URL || 'http://localhost:8000'
132
+
133
+const AI_BASE = import.meta.env.VITE_AI_SERVICE_URL || 'http://airport-test.samsundot.com:9015'
134
+const AI_URL = AI_BASE + '/api/query-stream'
118
 
135
 
119
 const inputMessage = ref('')
136
 const inputMessage = ref('')
120
 const isLoading = ref(false)
137
 const isLoading = ref(false)
@@ -123,6 +140,9 @@ const messagesRef = ref(null)
123
 const showDataBoard = ref(false)
140
 const showDataBoard = ref(false)
124
 const showPerformanceAnalysis = ref(false)
141
 const showPerformanceAnalysis = ref(false)
125
 const showUseReports = ref(false)
142
 const showUseReports = ref(false)
143
+const sessionId = ref('app_' + Date.now())
144
+const history = ref([])
145
+const clarifyQuestion = ref('')
126
 
146
 
127
 onMounted(() => resetState())
147
 onMounted(() => resetState())
128
 onActivated(() => resetState())
148
 onActivated(() => resetState())
@@ -135,6 +155,9 @@ const resetState = () => {
135
   messages.value = []
155
   messages.value = []
136
   showUseReports.value = false
156
   showUseReports.value = false
137
   isLoading.value = false
157
   isLoading.value = false
158
+  sessionId.value = 'app_' + Date.now()
159
+  history.value = []
160
+  clarifyQuestion.value = ''
138
 }
161
 }
139
 
162
 
140
 const scrollToBottom = async () => {
163
 const scrollToBottom = async () => {
@@ -144,11 +167,84 @@ const scrollToBottom = async () => {
144
   }
167
   }
145
 }
168
 }
146
 
169
 
170
+const getUserId = () => {
171
+  return String(userStore.id || 1)
172
+}
173
+
174
+const toggleSql = (msgId) => {
175
+  const msg = messages.value.find(m => m.id === msgId)
176
+  if (msg) {
177
+    msg.showSql = !msg.showSql
178
+  }
179
+}
180
+
181
+const handleEvent = (aiMsg, data) => {
182
+  if (data.step !== undefined && data.name) {
183
+    // 进度步骤
184
+    const steps = [...(aiMsg.steps || [])]
185
+    const si = steps.findIndex(s => s.name === data.name)
186
+    const step = { 
187
+      step: si >= 0 ? si : steps.length, 
188
+      name: data.name, 
189
+      status: data.status, 
190
+      duration: data.duration 
191
+    }
192
+    if (si >= 0) {
193
+      steps[si] = step
194
+    } else {
195
+      steps.push(step)
196
+    }
197
+    aiMsg.steps = steps
198
+    messages.value = [...messages.value]
199
+    return
200
+  }
201
+
202
+  if (data.question) {
203
+    // 意图澄清
204
+    clarifyQuestion.value = data.question
205
+    aiMsg.status = 'done'
206
+    messages.value = [...messages.value]
207
+    return
208
+  }
209
+
210
+  if (data.columns !== undefined || data.answer !== undefined) {
211
+    // 最终结果
212
+    aiMsg.steps.forEach(s => { if (s.status === 'running') s.status = 'done' })
213
+    
214
+    // 适配数据结构
215
+    aiMsg.result = {
216
+      query_type: data.answer ? 'knowledge' : 'data',
217
+      answer: data.answer || '',
218
+      message: data.message || '',
219
+      sql: data.sql || '',
220
+      columns: data.columns || [],
221
+      rows: data.rows || [],
222
+      sources: data.sources || [],
223
+      timing: { total: 0 },
224
+      success: data.success !== false
225
+    }
226
+    aiMsg.showSql = false
227
+    aiMsg.isError = !data.success
228
+    aiMsg.status = 'done'
229
+    messages.value = [...messages.value]
230
+    
231
+    // 记录历史
232
+    const prevUserMsg = messages.value.find(m => m.id < aiMsg.id && m.type === 'user')
233
+    if (prevUserMsg) {
234
+      history.value.push({
235
+        question: prevUserMsg.text || '',
236
+        sql: data.sql || '',
237
+      })
238
+    }
239
+  }
240
+}
241
+
147
 const handleSend = async () => {
242
 const handleSend = async () => {
148
   const text = inputMessage.value.trim()
243
   const text = inputMessage.value.trim()
149
   if (!text || isLoading.value) return
244
   if (!text || isLoading.value) return
150
 
245
 
151
   inputMessage.value = ''
246
   inputMessage.value = ''
247
+  clarifyQuestion.value = ''
152
   isLoading.value = true
248
   isLoading.value = true
153
 
249
 
154
   // 添加用户消息
250
   // 添加用户消息
@@ -162,25 +258,27 @@ const handleSend = async () => {
162
     status: 'loading',
258
     status: 'loading',
163
     steps: [],
259
     steps: [],
164
     result: null,
260
     result: null,
165
-    errorText: ''
261
+    errorText: '',
262
+    showSql: false,
263
+    isError: false
166
   }
264
   }
167
   messages.value.push(assistantMsg)
265
   messages.value.push(assistantMsg)
168
   await scrollToBottom()
266
   await scrollToBottom()
169
 
267
 
170
   try {
268
   try {
171
-    const response = await fetch(`${AI_SERVICE_URL}/api/smart-query-stream`, {
269
+    const response = await fetch(AI_URL, {
172
       method: 'POST',
270
       method: 'POST',
173
       headers: { 'Content-Type': 'application/json' },
271
       headers: { 'Content-Type': 'application/json' },
174
       body: JSON.stringify({
272
       body: JSON.stringify({
175
         question: text,
273
         question: text,
176
-        user_id: String(userStore.id || 'anonymous'),
177
-        llm_type: 'claude'
178
-      })
274
+        user_id: getUserId(),
275
+        llm_type: 'qwen',
276
+        session_id: sessionId.value,
277
+        history: history.value.slice(-3),
278
+      }),
179
     })
279
     })
180
 
280
 
181
-    if (!response.ok) {
182
-      throw new Error(`服务请求失败 (${response.status})`)
183
-    }
281
+    if (!response.ok) throw new Error('请求失败 ' + response.status)
184
 
282
 
185
     const reader = response.body.getReader()
283
     const reader = response.body.getReader()
186
     const decoder = new TextDecoder()
284
     const decoder = new TextDecoder()
@@ -191,66 +289,27 @@ const handleSend = async () => {
191
       if (done) break
289
       if (done) break
192
 
290
 
193
       buffer += decoder.decode(value, { stream: true })
291
       buffer += decoder.decode(value, { stream: true })
194
-      // SSE 事件以两个换行符分隔
195
-      const blocks = buffer.split('\n\n')
196
-      buffer = blocks.pop() // 保留未完整的块
197
-
198
-      for (const block of blocks) {
199
-        if (!block.trim()) continue
200
-        const lines = block.split('\n')
201
-        let eventType = ''
202
-        let dataStr = ''
203
-        for (const line of lines) {
204
-          if (line.startsWith('event: ')) eventType = line.slice(7).trim()
205
-          else if (line.startsWith('data: ')) dataStr = line.slice(6).trim()
206
-        }
207
-        if (!dataStr) continue
208
-
209
-        let data
210
-        try { data = JSON.parse(dataStr) } catch { continue }
211
-
212
-        if (eventType === 'progress') {
213
-          const existing = assistantMsg.steps.find(s => s.step === data.step)
214
-          if (existing) {
215
-            Object.assign(existing, data)
216
-          } else {
217
-            assistantMsg.steps.push({ ...data })
218
-          }
219
-          // 触发响应式更新
220
-          messages.value = [...messages.value]
221
-          await scrollToBottom()
222
-
223
-        } else if (eventType === 'result') {
224
-          // 将所有仍在 running 的步骤标记为 done
225
-          assistantMsg.steps.forEach(s => { if (s.status === 'running') s.status = 'done' })
226
-          assistantMsg.result = data
227
-          assistantMsg.status = 'done'
228
-          messages.value = [...messages.value]
229
-          await scrollToBottom()
230
-
231
-        } else if (eventType === 'error') {
232
-          assistantMsg.status = 'error'
233
-          assistantMsg.errorText = data.message || '请求失败,请稍后重试'
234
-          messages.value = [...messages.value]
292
+      const lines = buffer.split('\n')
293
+      buffer = lines.pop()
294
+
295
+      for (const line of lines) {
296
+        if (line.startsWith('data: ')) {
297
+          try {
298
+            const data = JSON.parse(line.slice(6))
299
+            handleEvent(assistantMsg, data)
300
+            await scrollToBottom()
301
+          } catch (e) {}
235
         }
302
         }
236
       }
303
       }
237
     }
304
     }
238
-
239
-    // 若未收到 result 事件
240
-    if (assistantMsg.status === 'loading') {
241
-      assistantMsg.status = 'error'
242
-      assistantMsg.errorText = '未收到服务响应,请检查 AI 服务是否正常运行'
243
-      messages.value = [...messages.value]
244
-    }
245
-
246
-  } catch (e) {
305
+  } catch (err) {
247
     assistantMsg.status = 'error'
306
     assistantMsg.status = 'error'
248
-    assistantMsg.errorText = e.message || '网络错误,请检查 AI 服务连接'
307
+    assistantMsg.errorText = '请求失败,请检查网络后重试'
249
     messages.value = [...messages.value]
308
     messages.value = [...messages.value]
250
-  } finally {
251
-    isLoading.value = false
252
-    await scrollToBottom()
253
   }
309
   }
310
+
311
+  isLoading.value = false
312
+  await scrollToBottom()
254
 }
313
 }
255
 
314
 
256
 const handleReportClick = () => { showDataBoard.value = true }
315
 const handleReportClick = () => { showDataBoard.value = true }
@@ -459,6 +518,61 @@ const handleBack = () => {
459
   font-size: 13px;
518
   font-size: 13px;
460
 }
519
 }
461
 
520
 
521
+/* ===== SQL 折叠样式 ===== */
522
+.sql-block {
523
+  margin-top: 12px;
524
+}
525
+
526
+.sql-toggle {
527
+  display: flex;
528
+  align-items: center;
529
+  gap: 8px;
530
+  cursor: pointer;
531
+  color: #557DDB;
532
+  font-size: 13px;
533
+}
534
+
535
+.sql-label {
536
+  background: #e6f0ff;
537
+  padding: 2px 8px;
538
+  border-radius: 4px;
539
+  font-weight: 600;
540
+}
541
+
542
+.sql-arrow {
543
+  font-size: 12px;
544
+}
545
+
546
+.sql-code {
547
+  margin-top: 8px;
548
+  background: #f5f7fa;
549
+  padding: 12px;
550
+  border-radius: 8px;
551
+  overflow-x: auto;
552
+}
553
+
554
+.sql-code pre {
555
+  margin: 0;
556
+  font-size: 12px;
557
+  color: #333;
558
+  white-space: pre-wrap;
559
+  word-break: break-all;
560
+}
561
+
562
+/* ===== 意图澄清 ===== */
563
+.clarify-bar {
564
+  background: #fff3cd;
565
+  border: 1px solid #ffc107;
566
+  padding: 12px 16px;
567
+  border-radius: 8px;
568
+  margin-bottom: 16px;
569
+}
570
+
571
+.clarify-text {
572
+  color: #856404;
573
+  font-size: 14px;
574
+}
575
+
462
 /* ===== 底部输入区 ===== */
576
 /* ===== 底部输入区 ===== */
463
 .chat-container {
577
 .chat-container {
464
   flex-shrink: 0;
578
   flex-shrink: 0;

+ 2 - 2
src/views/ledger/bannerLetter/index.vue

@@ -38,8 +38,8 @@
38
 
38
 
39
     <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
39
     <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
40
       <el-table-column type="selection" width="55" align="center" />
40
       <el-table-column type="selection" width="55" align="center" />
41
-      <el-table-column label="记录日期" align="center" prop="recordDate" width="110">
42
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
41
+      <el-table-column label="记录日期" align="center" prop="recordDate" width="170">
42
+        <template #default="{ row }">{{ row.recordDate }}</template>
43
       </el-table-column>
43
       </el-table-column>
44
       <el-table-column label="部门名称" align="center" prop="deptName" />
44
       <el-table-column label="部门名称" align="center" prop="deptName" />
45
       <el-table-column label="队室/班组" align="center" prop="teamName" />
45
       <el-table-column label="队室/班组" align="center" prop="teamName" />

+ 2 - 2
src/views/ledger/channelPassRate/index.vue

@@ -23,8 +23,8 @@
23
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
23
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
24
     </el-row>
24
     </el-row>
25
     <el-table v-loading="loading" :data="list">
25
     <el-table v-loading="loading" :data="list">
26
-      <el-table-column label="记录日期" align="center" prop="recordDate" width="110">
27
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
26
+      <el-table-column label="记录日期" align="center" prop="recordDate" width="170">
27
+        <template #default="{ row }">{{ row.recordDate }}</template>
28
       </el-table-column>
28
       </el-table-column>
29
       <el-table-column label="部门名称" align="center" prop="deptName" />
29
       <el-table-column label="部门名称" align="center" prop="deptName" />
30
       <el-table-column label="队室/班组" align="center" prop="teamName" />
30
       <el-table-column label="队室/班组" align="center" prop="teamName" />

+ 2 - 2
src/views/ledger/complaint/index.vue

@@ -32,8 +32,8 @@
32
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
32
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
33
     </el-row>
33
     </el-row>
34
     <el-table v-loading="loading" :data="list">
34
     <el-table v-loading="loading" :data="list">
35
-      <el-table-column label="记录日期" align="center" prop="recordDate" width="110">
36
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
35
+      <el-table-column label="记录日期" align="center" prop="recordDate" width="170">
36
+        <template #default="{ row }">{{ row.recordDate }}</template>
37
       </el-table-column>
37
       </el-table-column>
38
       <el-table-column label="部门名称" align="center" prop="deptName" />
38
       <el-table-column label="部门名称" align="center" prop="deptName" />
39
       <el-table-column label="队室/班组" align="center" prop="teamName" />
39
       <el-table-column label="队室/班组" align="center" prop="teamName" />

+ 2 - 2
src/views/ledger/dailyTraining/index.vue

@@ -23,8 +23,8 @@
23
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
23
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
24
     </el-row>
24
     </el-row>
25
     <el-table v-loading="loading" :data="list">
25
     <el-table v-loading="loading" :data="list">
26
-      <el-table-column label="培训日期" align="center" prop="recordDate" width="110">
27
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
26
+      <el-table-column label="培训日期" align="center" prop="recordDate" width="170">
27
+        <template #default="{ row }">{{ row.recordDate }}</template>
28
       </el-table-column>
28
       </el-table-column>
29
       <el-table-column label="班组" align="center" prop="teamName" width="120" />
29
       <el-table-column label="班组" align="center" prop="teamName" width="120" />
30
       <el-table-column label="项目名称" align="center" prop="projectName" min-width="150" show-overflow-tooltip />
30
       <el-table-column label="项目名称" align="center" prop="projectName" min-width="150" show-overflow-tooltip />

+ 2 - 2
src/views/ledger/dormFireSafety/index.vue

@@ -26,8 +26,8 @@
26
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
26
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
27
     </el-row>
27
     </el-row>
28
     <el-table v-loading="loading" :data="list">
28
     <el-table v-loading="loading" :data="list">
29
-      <el-table-column label="检查日期" align="center" prop="checkDate" width="110">
30
-        <template #default="{ row }">{{ parseTime(row.checkDate, '{y}-{m}-{d}') }}</template>
29
+      <el-table-column label="检查日期" align="center" prop="checkDate" width="170">
30
+        <template #default="{ row }">{{ row.checkDate }}</template>
31
       </el-table-column>
31
       </el-table-column>
32
       <el-table-column label="寝室所在位置" align="center" prop="dormLocation" width="120" />
32
       <el-table-column label="寝室所在位置" align="center" prop="dormLocation" width="120" />
33
       <el-table-column label="寝室号" align="center" prop="dormNo" width="90" />
33
       <el-table-column label="寝室号" align="center" prop="dormNo" width="90" />

+ 2 - 2
src/views/ledger/examScore/index.vue

@@ -35,8 +35,8 @@
35
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
35
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
36
     </el-row>
36
     </el-row>
37
     <el-table v-loading="loading" :data="list">
37
     <el-table v-loading="loading" :data="list">
38
-      <el-table-column label="考试日期" align="center" prop="examDate" width="110">
39
-        <template #default="{ row }">{{ parseTime(row.examDate, '{y}-{m}-{d}') }}</template>
38
+      <el-table-column label="考试日期" align="center" prop="examDate" width="170">
39
+        <template #default="{ row }">{{ row.examDate }}</template>
40
       </el-table-column>
40
       </el-table-column>
41
       <el-table-column label="部门名称" align="center" prop="deptName" />
41
       <el-table-column label="部门名称" align="center" prop="deptName" />
42
       <el-table-column label="队室/班组" align="center" prop="teamName" />
42
       <el-table-column label="队室/班组" align="center" prop="teamName" />

+ 11 - 2
src/views/ledger/import/index.vue

@@ -147,7 +147,8 @@ import {
147
   importLeaderDuty,
147
   importLeaderDuty,
148
   importHealthSoldier,
148
   importHealthSoldier,
149
   importDormFireSafety,
149
   importDormFireSafety,
150
-  importTrainingIssue
150
+  importTrainingIssue,
151
+  importQualificationLevel
151
 } from '@/api/ledger/index'
152
 } from '@/api/ledger/index'
152
 
153
 
153
 defineOptions({ name: 'LedgerImport' })
154
 defineOptions({ name: 'LedgerImport' })
@@ -360,7 +361,15 @@ const importItems = reactive([
360
     loading: false,
361
     loading: false,
361
     lastResult: null
362
     lastResult: null
362
   },
363
   },
363
-
364
+  {
365
+    key: 'qualificationLevel',
366
+    title: '职业资格等级',
367
+    desc: '职业资格等级流程记录',
368
+    icon: 'Medal',
369
+    api: importQualificationLevel,
370
+    loading: false,
371
+    lastResult: null
372
+  },
364
   // {
373
   // {
365
   //   key: 'dailyTraining',
374
   //   key: 'dailyTraining',
366
   //   title: '日常培训记录',
375
   //   title: '日常培训记录',

+ 4 - 4
src/views/ledger/leaveSpecial/index.vue

@@ -38,11 +38,11 @@
38
       <el-table-column label="队室/班组" align="center" prop="teamName" />
38
       <el-table-column label="队室/班组" align="center" prop="teamName" />
39
       <el-table-column label="姓名" align="center" prop="personName" />
39
       <el-table-column label="姓名" align="center" prop="personName" />
40
       <el-table-column label="假期类型" align="center" prop="leaveType" />
40
       <el-table-column label="假期类型" align="center" prop="leaveType" />
41
-      <el-table-column label="开始日期" align="center" prop="startDate" width="110">
42
-        <template #default="{ row }">{{ parseTime(row.startDate, '{y}-{m}-{d}') }}</template>
41
+      <el-table-column label="开始日期" align="center" prop="startDate" width="170">
42
+        <template #default="{ row }">{{ row.startDate }}</template>
43
       </el-table-column>
43
       </el-table-column>
44
-      <el-table-column label="结束日期" align="center" prop="endDate" width="110">
45
-        <template #default="{ row }">{{ parseTime(row.endDate, '{y}-{m}-{d}') }}</template>
44
+      <el-table-column label="结束日期" align="center" prop="endDate" width="170">
45
+        <template #default="{ row }">{{ row.endDate }}</template>
46
       </el-table-column>
46
       </el-table-column>
47
       <el-table-column label="天数" align="center" prop="days" />
47
       <el-table-column label="天数" align="center" prop="days" />
48
       <el-table-column label="扣分" align="center" prop="deductScore">
48
       <el-table-column label="扣分" align="center" prop="deductScore">

+ 2 - 2
src/views/ledger/patrolInspection/index.vue

@@ -27,8 +27,8 @@
27
     </el-row>
27
     </el-row>
28
 
28
 
29
     <el-table v-loading="loading" :data="list">
29
     <el-table v-loading="loading" :data="list">
30
-      <el-table-column label="巡查日期" align="center" prop="recordDate" width="110">
31
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
30
+      <el-table-column label="巡查日期" align="center" prop="recordDate" width="170">
31
+        <template #default="{ row }">{{ row.recordDate }}</template>
32
       </el-table-column>
32
       </el-table-column>
33
       <el-table-column label="部门名称" align="center" prop="deptName" />
33
       <el-table-column label="部门名称" align="center" prop="deptName" />
34
       <el-table-column label="队室/班组" align="center" prop="teamName" />
34
       <el-table-column label="队室/班组" align="center" prop="teamName" />

+ 169 - 0
src/views/ledger/qualificationCertificateStatus/index.vue

@@ -0,0 +1,169 @@
1
+<template>
2
+  <div class="app-container">
3
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="80px">
4
+      <el-form-item label="部门名称" prop="deptId">
5
+        <el-select v-model="queryParams.deptId" placeholder="请选择部门" style="width:150px" clearable filterable
6
+          @change="handleQueryDeptChange">
7
+          <el-option v-for="d in queryDeptOptions" :key="d.deptId" :label="d.deptName" :value="d.deptId" />
8
+        </el-select>
9
+      </el-form-item>
10
+      <el-form-item label="队室/班组" prop="teamId">
11
+        <el-select v-model="queryParams.teamId" placeholder="请选择队室/班组" style="width:150px" clearable filterable
12
+          @change="handleQueryTeamChange">
13
+          <el-option v-for="t in queryTeamOptions" :key="t.id" :label="t.label" :value="t.id" />
14
+        </el-select>
15
+      </el-form-item>
16
+      <el-form-item label="小组" prop="groupId">
17
+        <el-select v-model="queryParams.groupId" placeholder="请选择小组" style="width:150px" clearable filterable
18
+          @change="handleQueryGroupChange">
19
+          <el-option v-for="g in queryGroupOptions" :key="g.id" :label="g.label" :value="g.id" />
20
+        </el-select>
21
+      </el-form-item>
22
+      <el-form-item label="员工姓名" prop="personId">
23
+        <el-select v-model="queryParams.personId" placeholder="请选择员工" style="width:150px" clearable filterable>
24
+          <el-option v-for="p in queryPersonOptions" :key="p.userId" :label="p.nickName" :value="p.userId" />
25
+        </el-select>
26
+      </el-form-item>
27
+      <el-form-item label="录入时间">
28
+        <el-date-picker v-model="dateRange" type="daterange" value-format="YYYY-MM-DD" range-separator="-"
29
+          start-placeholder="开始日期" end-placeholder="结束日期" clearable />
30
+      </el-form-item>
31
+      <el-form-item>
32
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
33
+        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
34
+      </el-form-item>
35
+    </el-form>
36
+
37
+    <!-- <el-row :gutter="10" class="mb8">
38
+      <el-col :span="1.5">
39
+        <el-button type="warning" plain icon="Download" @click="handleExport"
40
+          v-hasPermi="['ledger:qualification:export']">导出</el-button>
41
+      </el-col>
42
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
43
+    </el-row> -->
44
+
45
+    <el-table v-loading="loading" :data="list" style="width: 100%;" fit="true"
46
+      :scrollbar-always-on="true">
47
+      <el-table-column label="部门名称" align="center" prop="deptName" min-width="120" resizable />
48
+      <el-table-column label="队室/班组" align="center" prop="teamName" min-width="120" resizable />
49
+      <el-table-column label="小组" align="center" prop="groupName" min-width="120" resizable />
50
+      <el-table-column label="姓名" align="center" prop="personName" width="80" resizable />
51
+      <el-table-column label="一级发证时间" align="center" prop="levelOneTime" width="120" resizable>
52
+        <template #default="{ row }">{{ row.levelOneTime || '-' }}</template>
53
+      </el-table-column>
54
+      <el-table-column label="二级发证时间" align="center" prop="levelTwoTime" width="120" resizable>
55
+        <template #default="{ row }">{{ row.levelTwoTime || '-' }}</template>
56
+      </el-table-column>
57
+      <el-table-column label="三级发证时间" align="center" prop="levelThreeTime" width="120" resizable>
58
+        <template #default="{ row }">{{ row.levelThreeTime || '-' }}</template>
59
+      </el-table-column>
60
+      <el-table-column label="四级发证时间" align="center" prop="levelFourTime" width="120" resizable>
61
+        <template #default="{ row }">{{ row.levelFourTime || '-' }}</template>
62
+      </el-table-column>
63
+      <el-table-column label="五级发证时间" align="center" prop="levelFiveTime" width="120" resizable>
64
+        <template #default="{ row }">{{ row.levelFiveTime || '-' }}</template>
65
+      </el-table-column>
66
+      <el-table-column label="录入时间" align="center" prop="createTime" width="170" resizable>
67
+        <template #default="{ row }">{{ row.createTime }}</template>
68
+      </el-table-column>
69
+    </el-table>
70
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
71
+      v-model:limit="queryParams.pageSize" @pagination="getList" />
72
+  </div>
73
+</template>
74
+
75
+<script setup>
76
+import { ref, reactive, onMounted } from 'vue'
77
+import { listDept } from '@/api/system/dept'
78
+import { deptTreeSelect } from '@/api/system/user'
79
+import { listUser } from '@/api/system/user'
80
+import { listQualificationCertificateStatus } from '@/api/ledger/index'
81
+
82
+defineOptions({ name: 'LedgerQualificationCertificateStatus' })
83
+
84
+const loading = ref(false), list = ref([]), total = ref(0), showSearch = ref(true)
85
+const dateRange = ref([]), queryRef = ref(null)
86
+
87
+const queryParams = reactive({
88
+  pageNum: 1,
89
+  pageSize: 10,
90
+  deptId: null,
91
+  teamId: null,
92
+  groupId: null,
93
+  personId: null
94
+})
95
+
96
+const queryDeptOptions = ref([])
97
+const queryTeamOptions = ref([])
98
+const queryGroupOptions = ref([])
99
+const queryPersonOptions = ref([])
100
+
101
+async function loadQueryDepts() {
102
+  const r = await listDept()
103
+  queryDeptOptions.value = (r.data || []).filter(d => d.deptType === 'BRIGADE')
104
+}
105
+
106
+async function handleQueryDeptChange(deptId) {
107
+  queryParams.teamId = null; queryParams.groupId = null; queryParams.personId = null
108
+  queryTeamOptions.value = []; queryGroupOptions.value = []; queryPersonOptions.value = []
109
+  if (deptId) {
110
+    const r = await deptTreeSelect({ parentId: deptId })
111
+    queryTeamOptions.value = r.data || []
112
+  }
113
+}
114
+
115
+async function handleQueryTeamChange(val) {
116
+  queryParams.groupId = null; queryParams.personId = null
117
+  queryGroupOptions.value = []; queryPersonOptions.value = []
118
+  if (val) {
119
+    const r = await deptTreeSelect({ parentId: val })
120
+    queryGroupOptions.value = r.data || []
121
+  }
122
+}
123
+
124
+async function handleQueryGroupChange(val) {
125
+  queryParams.personId = null
126
+  queryPersonOptions.value = []
127
+  if (val) {
128
+    const r = await listUser({ deptId: val, pageSize: 9999 })
129
+    queryPersonOptions.value = r.rows || []
130
+  }
131
+}
132
+
133
+function getList() {
134
+  loading.value = true
135
+  const p = { ...queryParams }
136
+  if (dateRange.value?.length === 2) {
137
+    p.beginTime = dateRange.value[0]
138
+    p.endTime = dateRange.value[1]
139
+  }
140
+  listQualificationCertificateStatus(p).then(r => {
141
+    list.value = r.rows
142
+    total.value = r.total
143
+  }).finally(() => loading.value = false)
144
+}
145
+
146
+function handleQuery() { queryParams.pageNum = 1; getList() }
147
+
148
+function resetQuery() {
149
+  dateRange.value = []
150
+  Object.assign(queryParams, {
151
+    pageNum: 1,
152
+    pageSize: 10,
153
+    deptId: null,
154
+    teamId: null,
155
+    groupId: null,
156
+    personId: null
157
+  })
158
+  queryTeamOptions.value = []; queryGroupOptions.value = []; queryPersonOptions.value = []
159
+  queryRef.value?.resetFields()
160
+  handleQuery()
161
+}
162
+
163
+
164
+
165
+onMounted(() => {
166
+  loadQueryDepts()
167
+  getList()
168
+})
169
+</script>

+ 0 - 0
src/views/ledger/qualificationCertificateStatus/职业资格证书情况


+ 5 - 5
src/views/ledger/realtimeInterception/index.vue

@@ -7,8 +7,8 @@
7
       <el-form-item label="队室/班组" prop="teamName">
7
       <el-form-item label="队室/班组" prop="teamName">
8
         <el-input v-model="queryParams.teamName" placeholder="请输入队室/班组" clearable @keyup.enter="handleQuery" />
8
         <el-input v-model="queryParams.teamName" placeholder="请输入队室/班组" clearable @keyup.enter="handleQuery" />
9
       </el-form-item>
9
       </el-form-item>
10
-      <el-form-item label="查获人" prop="inspectorName">
11
-        <el-input v-model="queryParams.inspectorName" placeholder="请输入查获人" clearable @keyup.enter="handleQuery" />
10
+      <el-form-item label="责任人" prop="inspectorName">
11
+        <el-input v-model="queryParams.inspectorName" placeholder="请输入责任人" clearable @keyup.enter="handleQuery" />
12
       </el-form-item>
12
       </el-form-item>
13
 
13
 
14
       <el-form-item label="记录日期">
14
       <el-form-item label="记录日期">
@@ -30,12 +30,12 @@
30
     </el-row>
30
     </el-row>
31
 
31
 
32
     <el-table v-loading="loading" :data="list">
32
     <el-table v-loading="loading" :data="list">
33
-      <el-table-column label="记录日期" align="center" prop="recordDate" width="110">
34
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
33
+      <el-table-column label="记录日期" align="center" prop="recordDate" width="170">
34
+        <template #default="{ row }">{{ row.recordDate }}</template>
35
       </el-table-column>
35
       </el-table-column>
36
       <el-table-column label="部门名称" align="center" prop="deptName" />
36
       <el-table-column label="部门名称" align="center" prop="deptName" />
37
       <el-table-column label="队室/班组" align="center" prop="teamName" />
37
       <el-table-column label="队室/班组" align="center" prop="teamName" />
38
-      <el-table-column label="查获人" align="center" prop="inspectorName" />
38
+      <el-table-column label="责任人" align="center" prop="inspectorName" />
39
       <el-table-column label="通道号" align="center" prop="channelNo" />
39
       <el-table-column label="通道号" align="center" prop="channelNo" />
40
       <el-table-column label="旅客姓名" align="center" prop="passengerName" />
40
       <el-table-column label="旅客姓名" align="center" prop="passengerName" />
41
       <el-table-column label="航班号" align="center" prop="flightNo" />
41
       <el-table-column label="航班号" align="center" prop="flightNo" />

+ 3 - 3
src/views/ledger/rewardApproval/index.vue

@@ -10,7 +10,7 @@
10
       <el-form-item label="姓名" prop="personName">
10
       <el-form-item label="姓名" prop="personName">
11
         <el-input v-model="queryParams.personName" placeholder="请输入姓名" clearable @keyup.enter="handleQuery" />
11
         <el-input v-model="queryParams.personName" placeholder="请输入姓名" clearable @keyup.enter="handleQuery" />
12
       </el-form-item>
12
       </el-form-item>
13
-      <el-form-item label="审批日期">
13
+      <el-form-item label="查获(事件)时间">
14
         <el-date-picker v-model="dateRange" type="daterange" value-format="YYYY-MM-DD"
14
         <el-date-picker v-model="dateRange" type="daterange" value-format="YYYY-MM-DD"
15
           range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" clearable />
15
           range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" clearable />
16
       </el-form-item>
16
       </el-form-item>
@@ -26,8 +26,8 @@
26
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
26
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
27
     </el-row>
27
     </el-row>
28
     <el-table v-loading="loading" :data="list">
28
     <el-table v-loading="loading" :data="list">
29
-      <el-table-column label="审批日期" align="center" prop="approveDate" width="110">
30
-        <template #default="{ row }">{{ parseTime(row.approveDate, '{y}-{m}-{d}') }}</template>
29
+      <el-table-column label="查获(事件)时间" align="center" prop="approveDate" width="170">
30
+        <template #default="{ row }">{{ row.approveDate }}</template>
31
       </el-table-column>
31
       </el-table-column>
32
       <el-table-column label="部门名称" align="center" prop="deptName" />
32
       <el-table-column label="部门名称" align="center" prop="deptName" />
33
       <el-table-column label="队室/班组" align="center" prop="teamName" />
33
       <el-table-column label="队室/班组" align="center" prop="teamName" />

+ 2 - 2
src/views/ledger/rewardPenalty/index.vue

@@ -38,8 +38,8 @@
38
 
38
 
39
     <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
39
     <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
40
       <el-table-column type="selection" width="55" align="center" />
40
       <el-table-column type="selection" width="55" align="center" />
41
-      <el-table-column label="记录日期" align="center" prop="recordDate" width="110">
42
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
41
+      <el-table-column label="记录日期" align="center" prop="recordDate" width="170">
42
+        <template #default="{ row }">{{ row.recordDate }}</template>
43
       </el-table-column>
43
       </el-table-column>
44
       <el-table-column label="部门名称" align="center" prop="deptName" />
44
       <el-table-column label="部门名称" align="center" prop="deptName" />
45
       <el-table-column label="队室/班组" align="center" prop="teamName" />
45
       <el-table-column label="队室/班组" align="center" prop="teamName" />

+ 2 - 2
src/views/ledger/securityTest/index.vue

@@ -26,8 +26,8 @@
26
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
26
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
27
     </el-row>
27
     </el-row>
28
     <el-table v-loading="loading" :data="list">
28
     <el-table v-loading="loading" :data="list">
29
-      <el-table-column label="测试日期" align="center" prop="recordDate" width="110">
30
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
29
+      <el-table-column label="测试日期" align="center" prop="recordDate" width="170">
30
+        <template #default="{ row }">{{ row.recordDate }}</template>
31
       </el-table-column>
31
       </el-table-column>
32
       <el-table-column label="部门名称" align="center" prop="deptName" />
32
       <el-table-column label="部门名称" align="center" prop="deptName" />
33
       <el-table-column label="队室/班组" align="center" prop="teamName" />
33
       <el-table-column label="队室/班组" align="center" prop="teamName" />

+ 2 - 2
src/views/ledger/seizureStats/index.vue

@@ -23,8 +23,8 @@
23
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
23
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
24
     </el-row>
24
     </el-row>
25
     <el-table v-loading="loading" :data="list">
25
     <el-table v-loading="loading" :data="list">
26
-      <el-table-column label="查获日期" align="center" prop="recordDate" width="110">
27
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
26
+      <el-table-column label="查获日期" align="center" prop="recordDate" width="170">
27
+        <template #default="{ row }">{{ row.recordDate }}</template>
28
       </el-table-column>
28
       </el-table-column>
29
       <el-table-column label="部门名称" align="center" prop="deptName" />
29
       <el-table-column label="部门名称" align="center" prop="deptName" />
30
       <el-table-column label="队室/班组" align="center" prop="teamName" />
30
       <el-table-column label="队室/班组" align="center" prop="teamName" />

+ 5 - 5
src/views/ledger/servicePatrol/index.vue

@@ -7,8 +7,8 @@
7
       <el-form-item label="队室/班组" prop="teamName">
7
       <el-form-item label="队室/班组" prop="teamName">
8
         <el-input v-model="queryParams.teamName" placeholder="请输入队室/班组" clearable @keyup.enter="handleQuery" />
8
         <el-input v-model="queryParams.teamName" placeholder="请输入队室/班组" clearable @keyup.enter="handleQuery" />
9
       </el-form-item>
9
       </el-form-item>
10
-      <el-form-item label="被查人" prop="inspectedName">
11
-        <el-input v-model="queryParams.inspectedName" placeholder="请输入被查人" clearable @keyup.enter="handleQuery" />
10
+      <el-form-item label="责任人" prop="inspectedName">
11
+        <el-input v-model="queryParams.inspectedName" placeholder="请输入责任人" clearable @keyup.enter="handleQuery" />
12
       </el-form-item>
12
       </el-form-item>
13
 
13
 
14
       <el-form-item label="记录日期">
14
       <el-form-item label="记录日期">
@@ -30,13 +30,13 @@
30
     </el-row>
30
     </el-row>
31
 
31
 
32
     <el-table v-loading="loading" :data="list">
32
     <el-table v-loading="loading" :data="list">
33
-      <el-table-column label="巡查日期" align="center" prop="recordDate" width="110">
34
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
33
+      <el-table-column label="巡查日期" align="center" prop="recordDate" width="170">
34
+        <template #default="{ row }">{{ row.recordDate }}</template>
35
       </el-table-column>
35
       </el-table-column>
36
       <el-table-column label="部门名称" align="center" prop="deptName" />
36
       <el-table-column label="部门名称" align="center" prop="deptName" />
37
       <el-table-column label="队室/班组" align="center" prop="teamName" />
37
       <el-table-column label="队室/班组" align="center" prop="teamName" />
38
       <el-table-column label="巡查人" align="center" prop="inspectorName" />
38
       <el-table-column label="巡查人" align="center" prop="inspectorName" />
39
-      <el-table-column label="被查人" align="center" prop="inspectedName" />
39
+      <el-table-column label="责任人" align="center" prop="inspectedName" />
40
       <el-table-column label="服务类型" align="center" prop="serviceType" />
40
       <el-table-column label="服务类型" align="center" prop="serviceType" />
41
       <el-table-column label="问题描述" align="center" prop="problemDesc" show-overflow-tooltip />
41
       <el-table-column label="问题描述" align="center" prop="problemDesc" show-overflow-tooltip />
42
       <el-table-column label="扣分" align="center" prop="deductScore">
42
       <el-table-column label="扣分" align="center" prop="deductScore">

+ 5 - 5
src/views/ledger/supervisionProblem/index.vue

@@ -10,8 +10,8 @@
10
       <el-form-item label="巡查人" prop="inspectorName">
10
       <el-form-item label="巡查人" prop="inspectorName">
11
         <el-input v-model="queryParams.inspectorName" placeholder="请输入巡查人" clearable @keyup.enter="handleQuery" />
11
         <el-input v-model="queryParams.inspectorName" placeholder="请输入巡查人" clearable @keyup.enter="handleQuery" />
12
       </el-form-item>
12
       </el-form-item>
13
-      <el-form-item label="被查人" prop="inspectedName">
14
-        <el-input v-model="queryParams.inspectedName" placeholder="请输入被查人" clearable @keyup.enter="handleQuery" />
13
+      <el-form-item label="责任人" prop="inspectedName">
14
+        <el-input v-model="queryParams.inspectedName" placeholder="请输入责任人" clearable @keyup.enter="handleQuery" />
15
       </el-form-item>
15
       </el-form-item>
16
       <el-form-item label="记录日期">
16
       <el-form-item label="记录日期">
17
         <el-date-picker v-model="dateRange" type="daterange" value-format="YYYY-MM-DD"
17
         <el-date-picker v-model="dateRange" type="daterange" value-format="YYYY-MM-DD"
@@ -32,14 +32,14 @@
32
     </el-row>
32
     </el-row>
33
 
33
 
34
     <el-table v-loading="loading" :data="list">
34
     <el-table v-loading="loading" :data="list">
35
-      <el-table-column label="记录日期" align="center" prop="recordDate" width="110">
36
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
35
+      <el-table-column label="记录日期" align="center" prop="recordDate" width="170">
36
+        <template #default="{ row }">{{ row.recordDate }}</template>
37
       </el-table-column>
37
       </el-table-column>
38
       <el-table-column label="部门名称" align="center" prop="deptName" />
38
       <el-table-column label="部门名称" align="center" prop="deptName" />
39
       <el-table-column label="队室/班组" align="center" prop="teamName" />
39
       <el-table-column label="队室/班组" align="center" prop="teamName" />
40
       <el-table-column label="小组" align="center" prop="groupName" />
40
       <el-table-column label="小组" align="center" prop="groupName" />
41
       <el-table-column label="巡查人" align="center" prop="inspectorName" />
41
       <el-table-column label="巡查人" align="center" prop="inspectorName" />
42
-      <el-table-column label="被查人" align="center" prop="inspectedName" />
42
+      <el-table-column label="责任人" align="center" prop="inspectedName" />
43
       <el-table-column label="问题类型" align="center" prop="problemType" />
43
       <el-table-column label="问题类型" align="center" prop="problemType" />
44
       <el-table-column label="问题描述" align="center" prop="problemDesc" show-overflow-tooltip />
44
       <el-table-column label="问题描述" align="center" prop="problemDesc" show-overflow-tooltip />
45
       <el-table-column label="问题地点" align="center" prop="location" />
45
       <el-table-column label="问题地点" align="center" prop="location" />

+ 3 - 3
src/views/ledger/terminalBonus/index.vue

@@ -10,7 +10,7 @@
10
       <el-form-item label="姓名" prop="personName">
10
       <el-form-item label="姓名" prop="personName">
11
         <el-input v-model="queryParams.personName" placeholder="请输入姓名" clearable @keyup.enter="handleQuery" />
11
         <el-input v-model="queryParams.personName" placeholder="请输入姓名" clearable @keyup.enter="handleQuery" />
12
       </el-form-item>
12
       </el-form-item>
13
-      <el-form-item label="审核日期">
13
+      <el-form-item label="计分时间">
14
         <el-date-picker v-model="dateRange" type="daterange" value-format="YYYY-MM-DD"
14
         <el-date-picker v-model="dateRange" type="daterange" value-format="YYYY-MM-DD"
15
           range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" clearable />
15
           range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" clearable />
16
       </el-form-item>
16
       </el-form-item>
@@ -26,8 +26,8 @@
26
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
26
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
27
     </el-row>
27
     </el-row>
28
     <el-table v-loading="loading" :data="list">
28
     <el-table v-loading="loading" :data="list">
29
-      <el-table-column label="审核日期" align="center" prop="approveDate" width="110">
30
-        <template #default="{ row }">{{ parseTime(row.approveDate, '{y}-{m}-{d}') }}</template>
29
+      <el-table-column label="计分时间" align="center" prop="scoreDate" width="170">
30
+        <template #default="{ row }">{{ row.scoreDate }}</template>
31
       </el-table-column>
31
       </el-table-column>
32
       <el-table-column label="部门名称" align="center" prop="deptName" />
32
       <el-table-column label="部门名称" align="center" prop="deptName" />
33
       <el-table-column label="队室/班组" align="center" prop="teamName" />
33
       <el-table-column label="队室/班组" align="center" prop="teamName" />

+ 2 - 2
src/views/ledger/trainingIssue/index.vue

@@ -30,8 +30,8 @@
30
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
30
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
31
     </el-row>
31
     </el-row>
32
     <el-table v-loading="loading" :data="list">
32
     <el-table v-loading="loading" :data="list">
33
-      <el-table-column label="问题台账日期" align="center" prop="recordDate" width="120">
34
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
33
+      <el-table-column label="问题台账日期" align="center" prop="recordDate" width="170">
34
+        <template #default="{ row }">{{ row.recordDate }}</template>
35
       </el-table-column>
35
       </el-table-column>
36
       <el-table-column label="班组" align="center" prop="teamName" width="120" />
36
       <el-table-column label="班组" align="center" prop="teamName" width="120" />
37
       <el-table-column label="处理人" align="center" prop="handler" width="100" />
37
       <el-table-column label="处理人" align="center" prop="handler" width="100" />

+ 2 - 2
src/views/ledger/unsafeEvent/index.vue

@@ -26,8 +26,8 @@
26
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
26
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
27
     </el-row>
27
     </el-row>
28
     <el-table v-loading="loading" :data="list">
28
     <el-table v-loading="loading" :data="list">
29
-      <el-table-column label="事件日期" align="center" prop="recordDate" width="110">
30
-        <template #default="{ row }">{{ parseTime(row.recordDate, '{y}-{m}-{d}') }}</template>
29
+      <el-table-column label="事件日期" align="center" prop="recordDate" width="170">
30
+        <template #default="{ row }">{{ row.recordDate }}</template>
31
       </el-table-column>
31
       </el-table-column>
32
       <el-table-column label="部门名称" align="center" prop="deptName" />
32
       <el-table-column label="部门名称" align="center" prop="deptName" />
33
       <el-table-column label="队室/班组" align="center" prop="teamName" />
33
       <el-table-column label="队室/班组" align="center" prop="teamName" />

+ 1 - 1
src/views/portraitManagement/components/ChannelCheckChart.vue

@@ -1,5 +1,5 @@
1
 <template>
1
 <template>
2
-  <Card title="每日通道过检率">
2
+  <Card title="通道高峰过检率">
3
     <div ref="bar" style="width: 100%; height: 100%;"></div>
3
     <div ref="bar" style="width: 100%; height: 100%;"></div>
4
   </Card>
4
   </Card>
5
 </template>
5
 </template>

+ 21 - 0
src/views/portraitManagement/components/ProfileBasicDistribution.vue

@@ -96,6 +96,13 @@ const updateGenderChart = (data) => {
96
       textStyle: { color: '#fff' },
96
       textStyle: { color: '#fff' },
97
       formatter: '{b}: {c} ({d}%)'
97
       formatter: '{b}: {c} ({d}%)'
98
     },
98
     },
99
+    legend: {
100
+      show: true,
101
+      textStyle: { color: '#fff' },
102
+      top: 0,
103
+      itemWidth: 10,
104
+      itemHeight: 10
105
+    },
99
     series: [{
106
     series: [{
100
       type: 'pie',
107
       type: 'pie',
101
       radius: ['38%', '55%'],
108
       radius: ['38%', '55%'],
@@ -120,6 +127,13 @@ const updateNationChart = (data) => {
120
       textStyle: { color: '#fff' },
127
       textStyle: { color: '#fff' },
121
       formatter: '{b}: {c} ({d}%)'
128
       formatter: '{b}: {c} ({d}%)'
122
     },
129
     },
130
+    legend: {
131
+      show: true,
132
+      textStyle: { color: '#fff' },
133
+      top: 0,
134
+      itemWidth: 10,
135
+      itemHeight: 10
136
+    },
123
     series: [{
137
     series: [{
124
       type: 'pie',
138
       type: 'pie',
125
       radius: ['38%', '55%'],
139
       radius: ['38%', '55%'],
@@ -144,6 +158,13 @@ const updatePoliticalChart = (data) => {
144
       textStyle: { color: '#fff' },
158
       textStyle: { color: '#fff' },
145
       formatter: '{b}: {c} ({d}%)'
159
       formatter: '{b}: {c} ({d}%)'
146
     },
160
     },
161
+    legend: {
162
+      show: true,
163
+      textStyle: { color: '#fff' },
164
+      top: 0,
165
+      itemWidth: 10,
166
+      itemHeight: 10
167
+    },
147
     series: [{
168
     series: [{
148
       type: 'pie',
169
       type: 'pie',
149
       radius: ['38%', '55%'],
170
       radius: ['38%', '55%'],

+ 23 - 2
src/views/portraitManagement/components/ProfilePositionDistribution.vue

@@ -96,6 +96,12 @@ const updateSkillChart = (data) => {
96
       textStyle: { color: '#fff' },
96
       textStyle: { color: '#fff' },
97
       formatter: '{b}: {c}'
97
       formatter: '{b}: {c}'
98
     },
98
     },
99
+    legend: {
100
+      show: true,
101
+      textStyle: { color: '#fff' },
102
+      top: 0,
103
+      data: ['职业资格等级']
104
+    },
99
     xAxis: {
105
     xAxis: {
100
       type: 'category',
106
       type: 'category',
101
       data: chartData.categories,
107
       data: chartData.categories,
@@ -110,6 +116,7 @@ const updateSkillChart = (data) => {
110
     },
116
     },
111
     series: [{
117
     series: [{
112
       type: 'bar',
118
       type: 'bar',
119
+      name: '职业资格等级',
113
       data: chartData.values,
120
       data: chartData.values,
114
       itemStyle: {
121
       itemStyle: {
115
         color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
122
         color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
@@ -137,10 +144,16 @@ const updateOperateChart = (data) => {
137
       textStyle: { color: '#fff' },
144
       textStyle: { color: '#fff' },
138
       formatter: '{b}: {c}'
145
       formatter: '{b}: {c}'
139
     },
146
     },
147
+    legend: {
148
+      show: true,
149
+      textStyle: { color: '#fff' },
150
+      top: 0,
151
+      data: ['开机年限']
152
+    },
140
     xAxis: {
153
     xAxis: {
141
       type: 'category',
154
       type: 'category',
142
       data: chartData.categories,
155
       data: chartData.categories,
143
-      axisLabel: { color: '#a0c4ff', fontSize: 10 },
156
+      axisLabel: { color: '#a0c4ff', fontSize: 10,rotate: 30 },
144
       axisLine: { lineStyle: { color: 'rgba(15,70,250,0.3)' } }
157
       axisLine: { lineStyle: { color: 'rgba(15,70,250,0.3)' } }
145
     },
158
     },
146
     yAxis: {
159
     yAxis: {
@@ -151,6 +164,7 @@ const updateOperateChart = (data) => {
151
     },
164
     },
152
     series: [{
165
     series: [{
153
       type: 'bar',
166
       type: 'bar',
167
+      name: '开机年限',
154
       data: chartData.values,
168
       data: chartData.values,
155
       itemStyle: {
169
       itemStyle: {
156
         color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
170
         color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
@@ -177,10 +191,16 @@ const updatePostChart = (data) => {
177
       textStyle: { color: '#fff' },
191
       textStyle: { color: '#fff' },
178
       formatter: '{b}: {c}'
192
       formatter: '{b}: {c}'
179
     },
193
     },
194
+    legend: {
195
+      show: true,
196
+      textStyle: { color: '#fff' },
197
+      top: 0,
198
+      data: ['岗位资质']
199
+    },
180
     xAxis: {
200
     xAxis: {
181
       type: 'category',
201
       type: 'category',
182
       data: chartData.categories,
202
       data: chartData.categories,
183
-      axisLabel: { color: '#a0c4ff', fontSize: 10 },
203
+      axisLabel: { color: '#a0c4ff', fontSize: 10,rotate: 30 },
184
       axisLine: { lineStyle: { color: 'rgba(15,70,250,0.3)' } }
204
       axisLine: { lineStyle: { color: 'rgba(15,70,250,0.3)' } }
185
     },
205
     },
186
     yAxis: {
206
     yAxis: {
@@ -191,6 +211,7 @@ const updatePostChart = (data) => {
191
     },
211
     },
192
     series: [{
212
     series: [{
193
       type: 'bar',
213
       type: 'bar',
214
+      name: '岗位资质',
194
       data: chartData.values,
215
       data: chartData.values,
195
       itemStyle: {
216
       itemStyle: {
196
         color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
217
         color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [

+ 68 - 4
src/views/portraitManagement/components/ProfileRadar.vue

@@ -1,17 +1,25 @@
1
 <template>
1
 <template>
2
   <InfoCard :title="title">
2
   <InfoCard :title="title">
3
     <div class="radar-section">
3
     <div class="radar-section">
4
-      <div ref="radarChartRef" class="radar-chart"></div>
4
+      <div>
5
+        <div class="chart-legend">
6
+          <div class="legend-item legend-warning"><span></span>预警线(低于75分)</div>
7
+          <!-- <div class="legend-item legend-normal"><span></span>正常线(75~90分)</div> -->
8
+          <div class="legend-item legend-excellent"><span></span>优秀线(高于90分)</div>
9
+          <div class="legend-item legend-current"><span></span>当前分值</div>
10
+        </div>
11
+        <div ref="radarChartRef" class="radar-chart"></div>
12
+      </div>
5
       <div class="radar-list">
13
       <div class="radar-list">
6
         <div class="radar-item" v-for="(item, index) in computedRadarData" :key="index">
14
         <div class="radar-item" v-for="(item, index) in computedRadarData" :key="index">
7
           <span class="item-label">{{ item.name }}</span>
15
           <span class="item-label">{{ item.name }}</span>
8
           <div class="progress-row">
16
           <div class="progress-row">
9
             <div class="progress-bar">
17
             <div class="progress-bar">
10
-            <div class="progress-fill"
11
-              :style="{ width: ((item.finalScore || 0) / (computedMaxScore || 1) * 100) + '%', background: `linear-gradient(90deg, ${item.color}33, ${item.color})` }">
18
+              <div class="progress-fill"
19
+                :style="{ width: ((item.finalScore || 0) / (computedMaxScore || 1) * 100) + '%', background: `linear-gradient(90deg, ${item.color}33, ${item.color})` }">
12
                 <span class="progress-end" :style="{ background: item.color }"></span>
20
                 <span class="progress-end" :style="{ background: item.color }"></span>
21
+              </div>
13
             </div>
22
             </div>
14
-          </div>
15
             <span class="item-value">{{ item.finalScore || 0 }}</span>
23
             <span class="item-value">{{ item.finalScore || 0 }}</span>
16
           </div>
24
           </div>
17
         </div>
25
         </div>
@@ -181,6 +189,62 @@ onUnmounted(() => {
181
   gap: 20px;
189
   gap: 20px;
182
   min-height: 400px;
190
   min-height: 400px;
183
 
191
 
192
+  .chart-legend {
193
+    display: flex;
194
+    justify-content: center;
195
+    align-items: center;
196
+    flex-wrap: wrap;
197
+    gap: 10px 18px;
198
+    padding-top: 8px;
199
+    color: #fff;
200
+    font-size: 14px;
201
+  }
202
+
203
+  .legend-item {
204
+    display: flex;
205
+    align-items: center;
206
+    gap: 6px;
207
+
208
+    span {
209
+      width: 24px;
210
+      height: 10px;
211
+      border: 2px solid currentColor;
212
+      border-radius: 2px;
213
+    }
214
+  }
215
+
216
+  .legend-warning {
217
+    color: #fe4322;
218
+
219
+    span {
220
+      background-color: #fe4322;
221
+    }
222
+  }
223
+
224
+  .legend-normal {
225
+    color: #fff;
226
+
227
+    span {
228
+      background-color: #fff;
229
+    }
230
+  }
231
+
232
+  .legend-excellent {
233
+    color: #8EC742;
234
+
235
+    span {
236
+      background-color: #8EC742;
237
+    }
238
+  }
239
+
240
+  .legend-current {
241
+    color: #1890ff;
242
+
243
+    span {
244
+      background-color: #1890ff;
245
+    }
246
+  }
247
+
184
   .radar-chart {
248
   .radar-chart {
185
     flex: 1;
249
     flex: 1;
186
     min-width: 300px;
250
     min-width: 300px;

+ 1 - 0
src/views/portraitManagement/components/SeizedItems.vue

@@ -31,6 +31,7 @@ const setChartsOptionsBar = computed(() => {
31
       textStyle: { color: '#fff' }
31
       textStyle: { color: '#fff' }
32
     },
32
     },
33
     legend: {
33
     legend: {
34
+      type: 'scroll',
34
       top: 'center',
35
       top: 'center',
35
       left: '0%',
36
       left: '0%',
36
       orient: 'vertical',
37
       orient: 'vertical',

+ 5 - 1
src/views/portraitManagement/components/SeizedNum.vue

@@ -1,5 +1,5 @@
1
 <template>
1
 <template>
2
-  <Card title="每日查获数量(个人对比)">
2
+  <Card :title="title">
3
     <div ref="bar" style="width: 100%; height: 100%;"></div>
3
     <div ref="bar" style="width: 100%; height: 100%;"></div>
4
   </Card>
4
   </Card>
5
 </template>
5
 </template>
@@ -10,6 +10,10 @@
10
   import { useECharts } from '@/hooks/useEcharts.js';
10
   import { useECharts } from '@/hooks/useEcharts.js';
11
   const bar = ref(null)
11
   const bar = ref(null)
12
   const props = defineProps({
12
   const props = defineProps({
13
+    title: {
14
+      type: String,
15
+      default: '每日查获数量(个人对比)'
16
+    },
13
     chartsData: {
17
     chartsData: {
14
       type: Array,
18
       type: Array,
15
       default: () => []
19
       default: () => []

+ 1 - 1
src/views/portraitManagement/components/SupervisionDistribution.vue

@@ -33,7 +33,7 @@ const setChartsOptionsBar = computed(() => {
33
     xAxis: {
33
     xAxis: {
34
       type: 'category',
34
       type: 'category',
35
       data: labels,
35
       data: labels,
36
-      axisLabel: { color: '#fff', fontSize: 14 },
36
+      axisLabel: { color: '#fff', fontSize: 13, rotate: 30 },
37
       axisLine: { lineStyle: { color: '#344067' } }
37
       axisLine: { lineStyle: { color: '#344067' } }
38
     },
38
     },
39
     yAxis: [
39
     yAxis: [

+ 1 - 1
src/views/portraitManagement/deptProfile/component/runData.vue

@@ -16,7 +16,7 @@
16
         <SeizedNumAll :chartsData="countSeizureTotalQuantityData"/>
16
         <SeizedNumAll :chartsData="countSeizureTotalQuantityData"/>
17
       </div>
17
       </div>
18
       <div class="col">
18
       <div class="col">
19
-        <SeizedNum :chartsData="countSeizureSingleQuantityData" />
19
+        <SeizedNum :chartsData="countSeizureSingleQuantityData" :title="'每日查获数量(班组对比)'"/>
20
       </div>
20
       </div>
21
     </div>
21
     </div>
22
     <div class="row">
22
     <div class="row">

+ 95 - 8
src/views/portraitManagement/employeeProfile/index.vue

@@ -65,7 +65,10 @@
65
                   </div>
65
                   </div>
66
                   <div class="info-item-content">
66
                   <div class="info-item-content">
67
                     <div class="info-item-label">技能等级:</div>
67
                     <div class="info-item-label">技能等级:</div>
68
-                    <div class="info-item-value">{{ portrait.qualificationLevelText || '-' }}</div>
68
+                    <div class="info-item-value">
69
+                      {{ portrait.qualificationLevelText || '-' }}
70
+                      <span class="info-item-tag" style="margin-left: 10px;margin-top: 2px;" v-if="!!portrait.xrayOperatorStarttime">X射线安检仪操作岗位</span>
71
+                    </div>
69
                   </div>
72
                   </div>
70
                 </div>
73
                 </div>
71
                 <div class="info-item">
74
                 <div class="info-item">
@@ -84,19 +87,20 @@
84
                 <div class="score-progress">
87
                 <div class="score-progress">
85
                   <el-progress type="circle" :width="160" :stroke-width="18" color="#5BE39E" :percentage="(portrait.totalScore || -2) + 2">
88
                   <el-progress type="circle" :width="160" :stroke-width="18" color="#5BE39E" :percentage="(portrait.totalScore || -2) + 2">
86
                     <div class="percentage-content">
89
                     <div class="percentage-content">
87
-                      <span class="percentage-value">{{ (portrait.totalScore || -2) + 2 }}</span>
90
+                      <span class="percentage-value">{{ (portrait.totalScore || 0)  }}</span>
88
                       <span class="percentage-text">综合得分</span>
91
                       <span class="percentage-text">综合得分</span>
89
                     </div>
92
                     </div>
90
                   </el-progress>
93
                   </el-progress>
91
                 </div>
94
                 </div>
92
                 <div class="score-box">
95
                 <div class="score-box">
93
-                  <div class="score-row">
96
+                  <!-- <div class="score-row">
94
                     <span class="score-col">评分:</span>
97
                     <span class="score-col">评分:</span>
95
                     <span class="score-col-2">{{ portrait.totalScore || 0 }}</span>
98
                     <span class="score-col-2">{{ portrait.totalScore || 0 }}</span>
96
-                  </div>
99
+                  </div> -->
97
                   <div class="score-row">
100
                   <div class="score-row">
98
-                    <span class="score-col">标签得分:</span>
99
-                    <span class="score-col-2">{{ tagScoreData != null ? (typeof tagScoreData === 'object' ? (tagScoreData.totalScore ?? tagScoreData.score ?? tagScoreData) : tagScoreData) : 0 }}</span>
101
+                    <span class="score-col">附加分:</span>
102
+                    <span class="score-col-2">{{ portrait?.userTags?.split(',').length || 0 }}分</span>
103
+                    <!-- <span class="score-col-2">{{ tagScoreData != null ? (typeof tagScoreData === 'object' ? (tagScoreData.totalScore ?? tagScoreData.score ?? tagScoreData) : tagScoreData) : 0 }}</span> -->
100
                   </div>
104
                   </div>
101
                 </div>
105
                 </div>
102
               </div>
106
               </div>
@@ -126,9 +130,21 @@
126
                 </div>
130
                 </div>
127
               </div>
131
               </div>
128
             </Card>
132
             </Card>
133
+            <Card title="职业资格证书情况">
134
+              <div class="cert-info">
135
+                <span class="cert-name">证书名称:{{ portrait?.qualificationLevelText || '-' }} 时间:{{ getQualificationTime|| '-' }}</span>
136
+              
137
+              </div>
138
+            </Card>
129
           </div>
139
           </div>
130
           <div class="content-bottom-center">
140
           <div class="content-bottom-center">
131
             <Card title="个人能力">
141
             <Card title="个人能力">
142
+              <div class="chart-legend">
143
+                <div class="legend-item legend-warning"><span></span>预警线(低于75分)</div>
144
+                <!-- <div class="legend-item legend-normal"><span></span>正常线(75~90分)</div> -->
145
+                <div class="legend-item legend-excellent"><span></span>优秀线(高于90分)</div>
146
+                <div class="legend-item legend-current"><span></span>当前员工分值</div>
147
+              </div>
132
               <div ref="abilityChart" class="chart-box" @click="goToWarningPage" />
148
               <div ref="abilityChart" class="chart-box" @click="goToWarningPage" />
133
             </Card>
149
             </Card>
134
           </div>
150
           </div>
@@ -225,6 +241,7 @@ import { getEmployeePortrait } from '@/api/score/index'
225
 import { countTagScore } from '@/api/portraitManagement/portraitManagement'
241
 import { countTagScore } from '@/api/portraitManagement/portraitManagement'
226
 import { onMounted, onUnmounted, reactive, ref, computed, watch } from 'vue'
242
 import { onMounted, onUnmounted, reactive, ref, computed, watch } from 'vue'
227
 import { useDict } from '@/utils/dict'
243
 import { useDict } from '@/utils/dict'
244
+import { getQualificationLevelTime } from '@/api/ledger/index'
228
 import { useECharts } from '@/hooks/useEcharts'
245
 import { useECharts } from '@/hooks/useEcharts'
229
 import useUserStore from '@/store/modules/user'
246
 import useUserStore from '@/store/modules/user'
230
 import { useRouter } from 'vue-router'
247
 import { useRouter } from 'vue-router'
@@ -243,6 +260,7 @@ const abilityChart = ref(null)
243
 const activeDimName = ref(null)
260
 const activeDimName = ref(null)
244
 const tagScoreData = ref(null)
261
 const tagScoreData = ref(null)
245
 const currentQuery = ref(null)
262
 const currentQuery = ref(null)
263
+const qualificationData = ref(null)
246
 
264
 
247
 const scoreDetails = computed(() => portrait.value?.scoreDetails || [])
265
 const scoreDetails = computed(() => portrait.value?.scoreDetails || [])
248
 
266
 
@@ -279,6 +297,25 @@ const deductTotal = computed(() => {
279
   return s.toFixed(2)
297
   return s.toFixed(2)
280
 })
298
 })
281
 
299
 
300
+// 职业资格等级枚举
301
+const qualificationLevelMap = [
302
+  { label: '一级', field: 'levelOneTime' },
303
+  { label: '二级', field: 'levelTwoTime' },
304
+  { label: '三级', field: 'levelThreeTime' },
305
+  { label: '四级', field: 'levelFourTime' },
306
+  { label: '五级', field: 'levelFiveTime' }
307
+]
308
+
309
+const getQualificationTime = computed(() => {
310
+  const certName = portrait.value?.qualificationLevelText || '-';
311
+  
312
+  const item = qualificationLevelMap.find(l => l.label === certName)
313
+  if (item) {
314
+    return qualificationData.value?.[item.field] || '-'
315
+  }
316
+  return '-'
317
+})
318
+
282
 
319
 
283
 const getSchooling = (schooling) => {
320
 const getSchooling = (schooling) => {
284
   const result = (sys_user_schooling.value || []).find(item => item.value === schooling) || { label: schooling }
321
   const result = (sys_user_schooling.value || []).find(item => item.value === schooling) || { label: schooling }
@@ -345,7 +382,12 @@ const invokerEmployeePortrait = (query) => {
345
       tagScoreData.value = data
382
       tagScoreData.value = data
346
     }
383
     }
347
   })
384
   })
348
-  return Promise.all([portraitPromise, tagPromise]).finally(() => {
385
+  const qualificationPromise = getQualificationLevelTime({ userId }).then(res => {
386
+    qualificationData.value = res.data || null
387
+  }).catch(() => {
388
+    qualificationData.value = null
389
+  })
390
+  return Promise.all([portraitPromise, tagPromise, qualificationPromise]).finally(() => {
349
     loading.value = false
391
     loading.value = false
350
   })
392
   })
351
 }
393
 }
@@ -764,9 +806,54 @@ onUnmounted(() => {
764
       & > * {
806
       & > * {
765
         height: 100%;
807
         height: 100%;
766
       }
808
       }
809
+      .chart-legend {
810
+        display: flex;
811
+        justify-content: center;
812
+        align-items: center;
813
+        flex-wrap: wrap;
814
+        gap: 10px 18px;
815
+        padding-top: 8px;
816
+        color: #fff;
817
+        font-size: 14px;
818
+      }
819
+      .legend-item {
820
+        display: flex;
821
+        align-items: center;
822
+        gap: 6px;
823
+        span {
824
+          width: 24px;
825
+          height: 10px;
826
+          border: 2px solid currentColor;
827
+          border-radius: 2px;
828
+        }
829
+      }
830
+      .legend-warning {
831
+        color: #fe4322;
832
+        span { 
833
+          background-color: #fe4322;
834
+        }
835
+      }
836
+      .legend-normal {
837
+        color: #fff;
838
+        span { 
839
+          background-color: #fff;
840
+        }
841
+      }
842
+      .legend-excellent {
843
+        color: #8EC742;
844
+        span { 
845
+          background-color: #8EC742;
846
+        }
847
+      }
848
+      .legend-current {
849
+        color: #1890ff;
850
+        span { 
851
+          background-color: #1890ff;
852
+        }
853
+      }
767
       .chart-box {
854
       .chart-box {
768
         width: 100%;
855
         width: 100%;
769
-        height: 100%;
856
+        height: calc(100% - 34px);
770
         overflow: hidden;
857
         overflow: hidden;
771
       }
858
       }
772
     }
859
     }

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 1306
src/views/portraitManagement/employeeProfile/indexOld.vue


+ 1 - 1
src/views/portraitManagement/teamProfile/component/runData.vue

@@ -16,7 +16,7 @@
16
         <SeizedNumAll :chartsData="countSeizureTotalQuantityData" />
16
         <SeizedNumAll :chartsData="countSeizureTotalQuantityData" />
17
       </div>
17
       </div>
18
       <div class="col">
18
       <div class="col">
19
-        <SeizedNum :chartsData="countSeizureSingleQuantityData" />
19
+        <SeizedNum :chartsData="countSeizureSingleQuantityData" :title="'每日查获数量(小组对比)'"/>
20
       </div>
20
       </div>
21
     </div>
21
     </div>
22
     <div class="row">
22
     <div class="row">

+ 18 - 4
src/views/score/event/index.vue

@@ -96,14 +96,14 @@
96
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
96
       <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
97
     </el-row>
97
     </el-row>
98
 
98
 
99
-    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange" style="width: 100%;" fit="true"
100
-      :scrollbar-always-on="true">
99
+    <el-table v-loading="loading" :data="list" @selection-change="handleSelectionChange" @sort-change="handleSortChange" style="width: 100%;" fit="true"
100
+      :scrollbar-always-on="true" :default-sort="{ prop: sortField, order: sortOrder }">
101
       <el-table-column type="selection" width="55" align="center" resizable />
101
       <el-table-column type="selection" width="55" align="center" resizable />
102
       <el-table-column label="配分层级" align="center" prop="org" width="110" resizable>
102
       <el-table-column label="配分层级" align="center" prop="org" width="110" resizable>
103
         <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>
104
       </el-table-column>
104
       </el-table-column>
105
-      <el-table-column label="事件时间" align="center" prop="eventTime" width="120" resizable>
106
-        <template #default="{ row }">{{ parseTime(row.eventTime, '{y}-{m}-{d}') }}</template>
105
+      <el-table-column label="事件时间" align="center" prop="eventTime" width="170" resizable sortable="custom">
106
+        <template #default="{ row }">{{ row.eventTime }}</template>
107
       </el-table-column>
107
       </el-table-column>
108
       <el-table-column label="维度" align="center" prop="dimensionName" width="150" resizable />
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 />
109
       <el-table-column label="二级指标" align="center" prop="level2Name" min-width="250" show-overflow-tooltip resizable />
@@ -332,6 +332,8 @@ const channelOptions = ref([])
332
 const postTreeData = ref([])
332
 const postTreeData = ref([])
333
 
333
 
334
 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 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 })
335
+const sortField = ref('eventTime')
336
+const sortOrder = ref('descending')
335
 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 })
337
 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 })
336
 const formChannelOptions = ref([])
338
 const formChannelOptions = ref([])
337
 const rules = computed(() => {
339
 const rules = computed(() => {
@@ -540,9 +542,21 @@ function getList() {
540
   loading.value = true
542
   loading.value = true
541
   const p = { ...queryParams }
543
   const p = { ...queryParams }
542
   if (dateRange.value?.length === 2) { p['params[beginTime]'] = dateRange.value[0]; p['params[endTime]'] = dateRange.value[1] }
544
   if (dateRange.value?.length === 2) { p['params[beginTime]'] = dateRange.value[0]; p['params[endTime]'] = dateRange.value[1] }
545
+  // 添加排序参数
546
+  if (sortField.value && sortOrder.value) {
547
+    const orderType = sortOrder.value === 'ascending' ? 'asc' : 'desc'
548
+    p[`sorts[${sortField.value}]`] = orderType
549
+  }
543
   listScoreEvent(p).then(r => { list.value = r.rows; total.value = r.total }).finally(() => loading.value = false)
550
   listScoreEvent(p).then(r => { list.value = r.rows; total.value = r.total }).finally(() => loading.value = false)
544
 }
551
 }
545
 
552
 
553
+function handleSortChange({ prop, order }) {
554
+  sortField.value = prop
555
+  sortOrder.value = order
556
+  queryParams.pageNum = 1
557
+  getList()
558
+}
559
+
546
 function handleQuery() { queryParams.pageNum = 1; getList() }
560
 function handleQuery() { queryParams.pageNum = 1; getList() }
547
 function resetQuery() {
561
 function resetQuery() {
548
   dateRange.value = []
562
   dateRange.value = []

+ 81 - 56
src/views/warningPage/index.vue

@@ -74,52 +74,56 @@
74
             </div>
74
             </div>
75
             <div class="employee-card">
75
             <div class="employee-card">
76
                 <div style="overflow-x: auto;">
76
                 <div style="overflow-x: auto;">
77
-                    <table class="data-table" style="width:100%;">
78
-                        <thead>
79
-                            <tr>
80
-                                <th>员工ID</th>
81
-                                <th>姓名</th>
82
-                                <th>所属部门</th>
83
-                                <th>综合评估得分</th>
84
-                                <th>预警等级</th>
85
-                                <th>核心风险/优秀事迹</th>
86
-                                <th>状态标签</th>
87
-                            </tr>
88
-                        </thead>
89
-                        <tbody>
90
-                            <tr v-for="emp in filteredEmployees" :key="emp.id" :class="getRowClass(emp.overallScore)">
91
-                                <td>{{ emp.userId }}</td>
92
-                                <td><strong>{{ emp.nickName }}</strong></td>
93
-                                <td>{{ emp.deptName }}</td>
94
-                                <td>
95
-                                    <span v-if="emp.overallScore < 75" class="score-danger">{{ emp.overallScore }}
96
-                                        分</span>
97
-                                    <span v-else-if="emp.overallScore >= 90" class="score-excellent">{{ emp.overallScore
98
-                                        }}
99
-                                        分</span>
100
-                                    <span v-else style="font-weight:600;">{{ emp.overallScore }} 分</span>
101
-                                </td>
102
-                                <td>
103
-                                    <span v-if="emp.overallScore < 75" class="status-badge"
104
-                                        style="animation: subtlePulse 1s infinite;"><i
105
-                                            class="fas fa-exclamation-triangle"></i> 红色预警</span>
106
-                                    <span v-else-if="emp.overallScore >= 90" class="status-excellent"
107
-                                        style="background:#d1fae5; color:#065f46;"><i class="fas fa-star"></i>
108
-                                        优秀标杆</span>
109
-                                    <span v-else class="status-warning">正常范围</span>
110
-                                </td>
111
-                                <td style="font-size:0.75rem;">{{ emp.coreRisksOrOutstandingAchievements }}</td>
112
-                                <td>
113
-                                    <span v-if="emp.overallScore < 75" style="color:#b91c1c;"><i
114
-                                            class="fas fa-bell"></i>
115
-                                        {{ getAlertLabel(emp.statusLabel) }}</span>
116
-                                    <span v-else-if="emp.overallScore >= 90" style="color:#15803d;"><i
117
-                                            class="fas fa-crown"></i> {{ getAlertLabel(emp.statusLabel) }}</span>
118
-                                    <span v-else>{{ getAlertLabel(emp.statusLabel) }}</span>
119
-                                </td>
120
-                            </tr>
121
-                        </tbody>
122
-                    </table>
77
+                    <el-table :data="filteredEmployees" :row-class-name="getRowClass" style="width:100%;" border stripe>
78
+                        <el-table-column prop="userId" label="员工ID" />
79
+                        <el-table-column prop="nickName" label="姓名">
80
+                            <template #default="{ row }">
81
+                                <strong>{{ row.nickName }}</strong>
82
+                            </template>
83
+                        </el-table-column>
84
+                        <el-table-column prop="deptName" label="所属部门" />
85
+                        <el-table-column prop="eventTime" label="事件时间" sortable width="180" />
86
+                        <el-table-column prop="overallScore" label="综合评估得分" sortable>
87
+                            <template #default="{ row }">
88
+                                <span v-if="row.overallScore < 75" class="score-danger">{{ row.overallScore }} 分</span>
89
+                                <span v-else-if="row.overallScore >= 90" class="score-excellent">{{ row.overallScore }} 分</span>
90
+                                <span v-else style="font-weight:600;">{{ row.overallScore }} 分</span>
91
+                            </template>
92
+                        </el-table-column>
93
+                        <el-table-column prop="overallScore" label="预警等级">
94
+                            <template #default="{ row }">
95
+                                <span v-if="row.overallScore < 75" class="status-badge"
96
+                                    style="animation: subtlePulse 1s infinite;"><i
97
+                                        class="fas fa-exclamation-triangle"></i> 红色预警</span>
98
+                                <span v-else-if="row.overallScore >= 90" class="status-excellent"
99
+                                    style="background:#d1fae5; color:#065f46;"><i class="fas fa-star"></i>
100
+                                    优秀标杆</span>
101
+                                <span v-else class="status-warning">正常范围</span>
102
+                            </template>
103
+                        </el-table-column>
104
+                        <el-table-column prop="coreRisksOrOutstandingAchievements" label="核心风险/优秀事迹" />
105
+                        <el-table-column prop="statusLabel" label="状态标签">
106
+                            <template #default="{ row }">
107
+                                <span v-if="row.overallScore < 75" style="color:#b91c1c;"><i
108
+                                        class="fas fa-bell"></i>
109
+                                    {{ getAlertLabel(row.statusLabel) }}</span>
110
+                                <span v-else-if="row.overallScore >= 90" style="color:#15803d;"><i
111
+                                        class="fas fa-crown"></i> {{ getAlertLabel(row.statusLabel) }}</span>
112
+                                <span v-else>{{ getAlertLabel(row.statusLabel) }}</span>
113
+                            </template>
114
+                        </el-table-column>
115
+                    </el-table>
116
+                    <el-pagination
117
+                        v-show="total > 0"
118
+                        :total="total"
119
+                        v-model:current-page="queryParams.pageNum"
120
+                        v-model:page-size="queryParams.pageSize"
121
+                        :page-sizes="[10, 20, 50, 100]"
122
+                        layout="total, sizes, prev, pager, next, jumper"
123
+                        @size-change="handleSizeChange"
124
+                        @current-change="handlePageChange"
125
+                        style="margin-top: 16px; justify-content: flex-end;"
126
+                    />
123
                 </div>
127
                 </div>
124
                 <div class="warning-summary">
128
                 <div class="warning-summary">
125
                     <div><i class="fas fa-circle" style="color:#ef4444;"></i> <strong>红色预警</strong> (综合评估 &lt; 75分) 共计
129
                     <div><i class="fas fa-circle" style="color:#ef4444;"></i> <strong>红色预警</strong> (综合评估 &lt; 75分) 共计
@@ -190,6 +194,10 @@ const coreRisksOrOutstandingAchievementsList = [
190
 ]
194
 ]
191
 
195
 
192
 const employeesData = ref([])
196
 const employeesData = ref([])
197
+const queryParams = reactive({
198
+  pageNum: 1,
199
+  pageSize: 10
200
+})
193
 
201
 
194
 for (let i = 0; i < newNames.length; i++) {
202
 for (let i = 0; i < newNames.length; i++) {
195
     employeesData.value.push({
203
     employeesData.value.push({
@@ -250,10 +258,8 @@ const getSelectedInfo = (selectedValue) => {
250
     return findNodeByValue(cascadeOptions.value, selectedValue)
258
     return findNodeByValue(cascadeOptions.value, selectedValue)
251
 }
259
 }
252
 
260
 
253
-const filteredEmployees = computed(() => {
254
-    let result = employeesData.value.ledgerWarningDetailItemList
255
-
256
-
261
+const allFilteredEmployees = computed(() => {
262
+    let result = employeesData.value.ledgerWarningDetailItemList || []
257
 
263
 
258
     // 预警等级筛选
264
     // 预警等级筛选
259
     if (selectedAlertLevel.value) {
265
     if (selectedAlertLevel.value) {
@@ -272,11 +278,26 @@ const filteredEmployees = computed(() => {
272
         }
278
         }
273
     }
279
     }
274
 
280
 
275
-
276
-
277
     return result
281
     return result
278
 })
282
 })
279
 
283
 
284
+const filteredEmployees = computed(() => {
285
+    const start = (queryParams.pageNum - 1) * queryParams.pageSize
286
+    const end = start + queryParams.pageSize
287
+    return allFilteredEmployees.value.slice(start, end)
288
+})
289
+
290
+const total = computed(() => allFilteredEmployees.value.length)
291
+
292
+function handlePageChange(newPage) {
293
+    queryParams.pageNum = newPage
294
+}
295
+
296
+function handleSizeChange(newSize) {
297
+    queryParams.pageSize = newSize
298
+    queryParams.pageNum = 1
299
+}
300
+
280
 const redAlertCount = computed(() => {
301
 const redAlertCount = computed(() => {
281
     return employeesData.value?.redAlertNum || 0
302
     return employeesData.value?.redAlertNum || 0
282
 })
303
 })
@@ -289,9 +310,9 @@ const avgScore = computed(() => {
289
     return employeesData.value?.averageComprehensiveScore || 0
310
     return employeesData.value?.averageComprehensiveScore || 0
290
 })
311
 })
291
 
312
 
292
-const getRowClass = (score) => {
293
-    if (score < 75) return "employee-warning-row"
294
-    if (score >= 90) return "employee-excellent-row"
313
+const getRowClass = ({ row }) => {
314
+    if (row.overallScore < 75) return "employee-warning-row"
315
+    if (row.overallScore >= 90) return "employee-excellent-row"
295
     return ""
316
     return ""
296
 }
317
 }
297
 
318
 
@@ -348,7 +369,7 @@ const warningDataMap = {
348
 }
369
 }
349
 
370
 
350
 const fetchWarningData = async () => {
371
 const fetchWarningData = async () => {
351
-    
372
+    queryParams.pageNum = 1
352
     let params = {}
373
     let params = {}
353
     if (startDate.value && endDate.value) {
374
     if (startDate.value && endDate.value) {
354
         params.startDate = formatDate(startDate.value)
375
         params.startDate = formatDate(startDate.value)
@@ -419,6 +440,10 @@ watch(cascadeOptions, (val) => {
419
     }
440
     }
420
 })
441
 })
421
 
442
 
443
+watch(selectedAlertLevel, () => {
444
+    queryParams.pageNum = 1
445
+})
446
+
422
 // 监听路由参数变化,回显到级联选择器
447
 // 监听路由参数变化,回显到级联选择器
423
 watch(() => route.query, (query) => {
448
 watch(() => route.query, (query) => {
424
     const { id } = query
449
     const { id } = query