Parcourir la source

feat(organProfile): 优化画像页图表布局及排行榜样式

- 新增“实时质控开机年限分布”柱状图
- 增加“服务巡查”折线图以丰富数据展示
- 调整顶部指标卡片及中部图表区的结构,提升视觉一致性
- 优化右侧排行榜头像展示,添加排名徽章和样式区分前3名
- 修正头像显示为姓名后两位,增强辨识度
- 增加头像及排名徽章的样式,改善用户体验
- 统一图表tooltip样式,确保视觉一致性
- 调整部分图表标题文案,提升表述准确性
- 杜绝代码中多余空行,优化模板结构层次
huoyi il y a 2 jours
Parent
commit
3a89beab45
1 fichiers modifiés avec 283 ajouts et 183 suppressions
  1. 283 183
      src/views/portraitManagement/organProfile/index.vue

+ 283 - 183
src/views/portraitManagement/organProfile/index.vue

@@ -1,197 +1,219 @@
1 1
 <template>
2
-  
3
-    <div class="org-profile">
4
-      <!-- 顶部指标卡片 -->
5
-      <div class="metric-row">
6
-        <div class="metric-card" v-for="(m, i) in metricCards" :key="i" :style="{ background: m.bg }">
7
-          <div class="metric-title">{{ m.title }}</div>
8
-          <div class="metric-value" :style="{ color: m.color }">{{ m.value }}</div>
9
-          <div class="metric-change-row">
10
-            <div class="metric-change-info">
11
-              <span class="metric-change-label">环比</span>
12
-              <span class="metric-change" :class="'change-' + m.changeType" :style="{ color: m.changeColor }">
13
-                {{ m.change }}
14
-              </span>
15
-            </div>
16
-            <div class="metric-chart" :ref="el => m._sparkRef = el" />
2
+
3
+  <div class="org-profile">
4
+    <!-- 顶部指标卡片 -->
5
+    <div class="metric-row">
6
+      <div class="metric-card" v-for="(m, i) in metricCards" :key="i" :style="{ background: m.bg }">
7
+        <div class="metric-title">{{ m.title }}</div>
8
+        <div class="metric-value" :style="{ color: m.color }">{{ m.value }}</div>
9
+        <div class="metric-change-row">
10
+          <div class="metric-change-info">
11
+            <span class="metric-change-label">环比</span>
12
+            <span class="metric-change" :class="'change-' + m.changeType" :style="{ color: m.changeColor }">
13
+              {{ m.change }}
14
+            </span>
17 15
           </div>
16
+          <div class="metric-chart" :ref="el => m._sparkRef = el" />
18 17
         </div>
19
-        <div class="metric-side-cards">
20
-          <div class="metric-card metric-warning-top">
21
-            <div class="metric-title">锐甲安语—自愿报告系统</div>
22
-            <div class="metric-value" style="color:#fff">3</div>
23
-          </div>
24
-          <div class="metric-card metric-warning-bottom">
25
-            <div class="metric-title">部门亚健康人员</div>
26
-            <div class="metric-value" style="color:#fff">147</div>
27
-          </div>
18
+      </div>
19
+      <div class="metric-side-cards">
20
+        <div class="metric-card metric-warning-top">
21
+          <div class="metric-title">锐甲安语—自愿报告系统</div>
22
+          <div class="metric-value" style="color:#fff">3</div>
23
+        </div>
24
+        <div class="metric-card metric-warning-bottom">
25
+          <div class="metric-title">部门亚健康人员</div>
26
+          <div class="metric-value" style="color:#fff">147</div>
28 27
         </div>
29 28
       </div>
29
+    </div>
30 30
 
31
-      <!-- 中部图表区 -->
32
-      <div class="charts-row">
33
-        <div class="charts-col charts-col-main">
34
-          <!-- 第一行 -->
35
-          <div class="charts-grid charts-grid-2">
36
-            <WhiteCard title="监察问题统计" bgColor="#dbeafe">
37
-              <div ref="supervisionLineRef" class="chart-box" />
38
-            </WhiteCard>
39
-            <WhiteCard title="问题类型分布" bgColor="#dbeafe">
40
-              <div ref="problemTypeRef" class="chart-box" />
41
-            </WhiteCard>
42
-          </div>
43
-          <!-- 第二行 -->
44
-          <div class="charts-grid charts-grid-2">
45
-            <WhiteCard title="班组问题统计(监察)" bgColor="#dcfce7">
46
-              <div ref="teamSupervisionRef" class="chart-box" />
47
-            </WhiteCard>
48
-            <WhiteCard title="区域问题占比(监察)" bgColor="#fef3c7">
49
-              <div ref="areaPieRef" class="chart-box" />
50
-            </WhiteCard>
51
-          </div>
52
-          <!-- 第三行 -->
53
-          <div class="charts-grid charts-grid-2">
54
-            <WhiteCard title="班组问题统计(实时)" bgColor="#dcfce7">
55
-              <div ref="teamRealtimeRef" class="chart-box" />
56
-            </WhiteCard>
57
-            <WhiteCard title="实时质控拦截情况" bgColor="#dcfce7">
58
-              <div ref="realtimeLineRef" class="chart-box" />
59
-            </WhiteCard>
60
-          </div>
61
-          <!-- 第四行 -->
62
-          <div class="charts-grid charts-grid-2">
63
-            <WhiteCard title="实时质控开机年轮分布" bgColor="#dbeafe">
64
-              <div ref="yearRingRef" class="chart-box" />
65
-            </WhiteCard>
66
-            <WhiteCard title="实时质控围难易度" bgColor="#dbeafe">
67
-              <div ref="difficultyRef" class="chart-box" />
68
-            </WhiteCard>
69
-          </div>
70
-          <!-- 第五行 -->
71
-          <div class="charts-grid charts-grid-2">
72
-            <WhiteCard title="实时拦截物品汇总" bgColor="#dbeafe">
73
-              <div ref="interceptItemsRef" class="chart-box" />
74
-            </WhiteCard>
75
-            <WhiteCard title="服务巡查" bgColor="#dbeafe">
76
-              <div ref="servicePatrolRef" class="chart-box" />
77
-            </WhiteCard>
78
-          </div>
79
-          <!-- 第六行 -->
80
-          <div class="charts-grid charts-grid-2">
81
-            <WhiteCard title="投诉涉及班组情况" bgColor="#fce4ec">
82
-              <div ref="complaintTeamRef" class="chart-box" />
83
-            </WhiteCard>
84
-            <WhiteCard title="不安全事件发生对比" bgColor="#dbeafe">
85
-              <div ref="unsafeCompareRef" class="chart-box" />
86
-            </WhiteCard>
87
-          </div>
88
-          <!-- 第七行 -->
89
-          <div class="charts-grid charts-grid-2">
90
-            <WhiteCard title="亚健康人数占比" bgColor="#fef3c7">
91
-              <div ref="subhealthPieRef" class="chart-box" />
92
-            </WhiteCard>
93
-            <WhiteCard title="各班组健康与亚健康比例" bgColor="#fef3c7">
94
-              <div ref="healthRatioRef" class="chart-box" />
95
-            </WhiteCard>
96
-          </div>
97
-          <!-- 第八行 -->
98
-          <div class="charts-grid charts-grid-1">
99
-            <WhiteCard title="旅检三部人员年龄分布表" bgColor="#dbeafe">
100
-              <div ref="ageDistRef" class="chart-box-wide" />
101
-            </WhiteCard>
102
-          </div>
31
+    <!-- 中部图表区 -->
32
+    <div class="charts-row">
33
+      <div class="charts-col charts-col-main">
34
+        <!-- 第一行 -->
35
+        <div class="charts-grid charts-grid-2">
36
+          <WhiteCard title="监察问题统计" bgColor="#dbeafe">
37
+            <div ref="supervisionLineRef" class="chart-box" />
38
+          </WhiteCard>
39
+          <WhiteCard title="问题类型分布" bgColor="#dbeafe">
40
+            <div ref="problemTypeRef" class="chart-box" />
41
+          </WhiteCard>
42
+        </div>
43
+        <!-- 第二行 -->
44
+        <div class="charts-grid charts-grid-2">
45
+          <WhiteCard title="班组问题统计(监察)" bgColor="#dcfce7">
46
+            <div ref="teamSupervisionRef" class="chart-box" />
47
+          </WhiteCard>
48
+          <WhiteCard title="区域问题占比(监察)" bgColor="#fef3c7">
49
+            <div ref="areaPieRef" class="chart-box" />
50
+          </WhiteCard>
51
+        </div>
52
+        <!-- 第三行 -->
53
+        <div class="charts-grid charts-grid-2">
54
+          <WhiteCard title="班组问题统计(实时)" bgColor="#dcfce7">
55
+            <div ref="teamRealtimeRef" class="chart-box" />
56
+          </WhiteCard>
57
+          <WhiteCard title="实时质控拦截情况" bgColor="#dcfce7">
58
+            <div ref="realtimeLineRef" class="chart-box" />
59
+          </WhiteCard>
60
+        </div>
61
+        <!-- 第四行 -->
62
+        <div class="charts-grid charts-grid-2">
63
+          <WhiteCard title="实时质控开机年龄分布" bgColor="#dbeafe">
64
+            <div ref="yearRingRef" class="chart-box" />
65
+          </WhiteCard>
66
+          <WhiteCard title="实时质控围难易度" bgColor="#dbeafe">
67
+            <div ref="difficultyRef" class="chart-box" />
68
+          </WhiteCard>
103 69
         </div>
70
+        <!-- 实时质控开机年限分布 -->
71
+        <div class="charts-grid charts-grid-2">
72
+          <WhiteCard title="实时质控开机年限分布" bgColor="#dcfce7">
73
+            <div ref="yearLimitRef" class="chart-box" />
74
+          </WhiteCard>
75
+          <WhiteCard title="实时拦截物品汇总" bgColor="#dbeafe">
76
+            <div ref="interceptItemsRef" class="chart-box" />
77
+          </WhiteCard>
78
+        </div>
79
+        <!-- 第五行 -->
80
+        <div class="charts-grid charts-grid-2">
81
+
82
+          <WhiteCard title="服务巡查" bgColor="#dbeafe">
83
+            <div ref="servicePatrolRef" class="chart-box" />
84
+          </WhiteCard>
85
+          <WhiteCard title="服务巡查" bgColor="#e8eaf6">
86
+            <div ref="servicePatrolLineRef" class="chart-box" />
87
+          </WhiteCard>
88
+        </div>
89
+        <!-- 第六行 -->
90
+        <div class="charts-grid charts-grid-2">
91
+          <WhiteCard title="投诉涉及班组情况" bgColor="#fce4ec">
92
+            <div ref="complaintTeamRef" class="chart-box" />
93
+          </WhiteCard>
94
+          <WhiteCard title="不安全事件发生对比" bgColor="#dbeafe">
95
+            <div ref="unsafeCompareRef" class="chart-box" />
96
+          </WhiteCard>
97
+        </div>
98
+        <!-- 第七行 -->
99
+        <div class="charts-grid charts-grid-2">
100
+          <WhiteCard title="亚健康人数占比" bgColor="#fef3c7">
101
+            <div ref="subhealthPieRef" class="chart-box" />
102
+          </WhiteCard>
103
+          <WhiteCard title="各班组健康与亚健康比例" bgColor="#fef3c7">
104
+            <div ref="healthRatioRef" class="chart-box" />
105
+          </WhiteCard>
106
+        </div>
107
+        <!-- 第八行 -->
108
+        <div class="charts-grid charts-grid-1">
109
+          <WhiteCard title="旅检三部人员年龄分布表" bgColor="#dbeafe">
110
+            <div ref="ageDistRef" class="chart-box-wide" />
111
+          </WhiteCard>
112
+        </div>
113
+      </div>
104 114
 
105
-        <!-- 右侧排行榜 -->
106
-        <div class="charts-col-side">
107
-          <WhiteCard title="监察问题(总)" bgColor="#f0f4ff">
108
-            <div class="rank-list">
109
-              <div class="rank-avatar-row">
110
-                <div class="rank-avatar-item" v-for="(item, i) in superVisionTop3" :key="i">
111
-                  <div class="rank-avatar" :style="{ background: item.color }">{{ item.name[0] }}</div>
112
-                  <div class="rank-name">{{ item.name }}</div>
113
-                  <div class="rank-num">{{ item.num }}</div>
115
+      <!-- 右侧排行榜 -->
116
+      <div class="charts-col-side">
117
+        <WhiteCard title="监察问题(总)" bgColor="#f0f4ff">
118
+          <div class="rank-list">
119
+            <div class="rank-avatar-row">
120
+              <div class="rank-avatar-item" v-for="(item, i) in superVisionTop3" :key="i">
121
+                <div class="rank-avatar-wrapper" :class="'rank-pos-' + (i + 1)">
122
+                  <div class="rank-avatar" :style="{ background: item.color }">{{ item.name.slice(-2) }}</div>
123
+                  <span class="rank-badge">{{ i + 1 }}</span>
114 124
                 </div>
125
+                <div class="rank-name">{{ item.name }}</div>
126
+                <div class="rank-num">{{ item.num }}</div>
115 127
               </div>
116
-              <div class="rank-table">
117
-                <div class="rank-tr rank-th">
118
-                  <span>排名</span><span>姓名</span><span>问题数</span>
119
-                </div>
120
-                <div class="rank-tr" v-for="(item, i) in superVisionList" :key="i">
121
-                  <span>{{ i + 1 }}</span>
122
-                  <span>{{ item.name }}</span>
123
-                  <span>{{ item.num }}</span>
124
-                </div>
128
+            </div>
129
+            <div class="rank-table">
130
+              <div class="rank-tr rank-th">
131
+                <span>排名</span><span>姓名</span><span>问题数</span>
132
+              </div>
133
+              <div class="rank-tr" v-for="(item, i) in superVisionList" :key="i">
134
+                <span>{{ i + 1 }}</span>
135
+                <span>{{ item.name }}</span>
136
+                <span>{{ item.num }}</span>
125 137
               </div>
126 138
             </div>
127
-          </WhiteCard>
128
-          <WhiteCard title="实时漏洞检情况(总)" bgColor="#f0fdf4">
129
-            <div class="rank-list">
130
-              <div class="rank-avatar-row">
131
-                <div class="rank-avatar-item" v-for="(item, i) in vulnTop3" :key="i">
132
-                  <div class="rank-avatar" :style="{ background: item.color }">{{ item.name[0] }}</div>
133
-                  <div class="rank-name">{{ item.name }}</div>
134
-                  <div class="rank-num">{{ item.num }}</div>
139
+          </div>
140
+        </WhiteCard>
141
+        <WhiteCard title="实时漏洞检情况(总)" bgColor="#f0fdf4">
142
+          <div class="rank-list">
143
+            <div class="rank-avatar-row">
144
+              <div class="rank-avatar-item" v-for="(item, i) in vulnTop3" :key="i">
145
+                <div class="rank-avatar-wrapper" :class="'rank-pos-' + (i + 1)">
146
+                  <div class="rank-avatar" :style="{ background: item.color }">{{ item.name.slice(-2) }}</div>
147
+                  <span class="rank-badge">{{ i + 1 }}</span>
135 148
                 </div>
149
+                <div class="rank-name">{{ item.name }}</div>
150
+                <div class="rank-num">{{ item.num }}</div>
136 151
               </div>
137
-              <div class="rank-table">
138
-                <div class="rank-tr rank-th">
139
-                  <span>排名</span><span>姓名</span><span>问题数</span>
140
-                </div>
141
-                <div class="rank-tr" v-for="(item, i) in vulnList" :key="i">
142
-                  <span>{{ i + 1 }}</span>
143
-                  <span>{{ item.name }}</span>
144
-                  <span>{{ item.num }}</span>
145
-                </div>
152
+            </div>
153
+            <div class="rank-table">
154
+              <div class="rank-tr rank-th">
155
+                <span>排名</span><span>姓名</span><span>问题数</span>
156
+              </div>
157
+              <div class="rank-tr" v-for="(item, i) in vulnList" :key="i">
158
+                <span>{{ i + 1 }}</span>
159
+                <span>{{ item.name }}</span>
160
+                <span>{{ item.num }}</span>
146 161
               </div>
147 162
             </div>
148
-          </WhiteCard>
149
-          <WhiteCard title="航站楼加分" bgColor="#eff6ff">
150
-            <div class="rank-list">
151
-              <div class="rank-avatar-row">
152
-                <div class="rank-avatar-item" v-for="(item, i) in bonusTop3" :key="i">
153
-                  <div class="rank-avatar" :style="{ background: item.color }">{{ item.name[0] }}</div>
154
-                  <div class="rank-name">{{ item.name }}</div>
155
-                  <div class="rank-num">{{ item.num }}</div>
163
+          </div>
164
+        </WhiteCard>
165
+        <WhiteCard title="航站楼加分" bgColor="#eff6ff">
166
+          <div class="rank-list">
167
+            <div class="rank-avatar-row">
168
+              <div class="rank-avatar-item" v-for="(item, i) in bonusTop3" :key="i">
169
+                <div class="rank-avatar-wrapper" :class="'rank-pos-' + (i + 1)">
170
+                  <div class="rank-avatar" :style="{ background: item.color }">{{ item.name.slice(-2) }}</div>
171
+                  <span class="rank-badge">{{ i + 1 }}</span>
156 172
                 </div>
173
+                <div class="rank-name">{{ item.name }}</div>
174
+                <div class="rank-num">{{ item.num }}</div>
157 175
               </div>
158
-              <div class="rank-table">
159
-                <div class="rank-tr rank-th">
160
-                  <span>排名</span><span>姓名</span><span>加分</span>
161
-                </div>
162
-                <div class="rank-tr" v-for="(item, i) in bonusList" :key="i">
163
-                  <span>{{ i + 1 }}</span>
164
-                  <span>{{ item.name }}</span>
165
-                  <span>{{ item.num }}</span>
166
-                </div>
176
+            </div>
177
+            <div class="rank-table">
178
+              <div class="rank-tr rank-th">
179
+                <span>排名</span><span>姓名</span><span>加分</span>
180
+              </div>
181
+              <div class="rank-tr" v-for="(item, i) in bonusList" :key="i">
182
+                <span>{{ i + 1 }}</span>
183
+                <span>{{ item.name }}</span>
184
+                <span>{{ item.num }}</span>
167 185
               </div>
168 186
             </div>
169
-          </WhiteCard>
170
-          <WhiteCard title="查获数量" bgColor="#f0f4ff">
171
-            <div class="rank-list">
172
-              <div class="rank-avatar-row">
173
-                <div class="rank-avatar-item" v-for="(item, i) in seizureTop3" :key="i">
174
-                  <div class="rank-avatar" :style="{ background: item.color }">{{ item.name[0] }}</div>
175
-                  <div class="rank-name">{{ item.name }}</div>
176
-                  <div class="rank-num">{{ item.num }}</div>
187
+          </div>
188
+        </WhiteCard>
189
+        <WhiteCard title="查获数量" bgColor="#f0f4ff">
190
+          <div class="rank-list">
191
+            <div class="rank-avatar-row">
192
+              <div class="rank-avatar-item" v-for="(item, i) in seizureTop3" :key="i">
193
+                <div class="rank-avatar-wrapper" :class="'rank-pos-' + (i + 1)">
194
+                  <div class="rank-avatar" :style="{ background: item.color }">{{ item.name.slice(-2) }}</div>
195
+                  <span class="rank-badge">{{ i + 1 }}</span>
177 196
                 </div>
197
+                <div class="rank-name">{{ item.name }}</div>
198
+                <div class="rank-num">{{ item.num }}</div>
178 199
               </div>
179
-              <div class="rank-table">
180
-                <div class="rank-tr rank-th">
181
-                  <span>排名</span><span>姓名</span><span>查获数</span>
182
-                </div>
183
-                <div class="rank-tr" v-for="(item, i) in seizureList" :key="i">
184
-                  <span>{{ i + 1 }}</span>
185
-                  <span>{{ item.name }}</span>
186
-                  <span>{{ item.num }}</span>
187
-                </div>
200
+            </div>
201
+            <div class="rank-table">
202
+              <div class="rank-tr rank-th">
203
+                <span>排名</span><span>姓名</span><span>查获数</span>
204
+              </div>
205
+              <div class="rank-tr" v-for="(item, i) in seizureList" :key="i">
206
+                <span>{{ i + 1 }}</span>
207
+                <span>{{ item.name }}</span>
208
+                <span>{{ item.num }}</span>
188 209
               </div>
189 210
             </div>
190
-          </WhiteCard>
191
-        </div>
211
+          </div>
212
+        </WhiteCard>
192 213
       </div>
193 214
     </div>
194
- 
215
+  </div>
216
+
195 217
 </template>
196 218
 
197 219
 <script setup>
@@ -218,9 +240,11 @@ const areaPieRef = ref(null)
218 240
 const teamRealtimeRef = ref(null)
219 241
 const realtimeLineRef = ref(null)
220 242
 const yearRingRef = ref(null)
243
+const yearLimitRef = ref(null)
221 244
 const difficultyRef = ref(null)
222 245
 const interceptItemsRef = ref(null)
223 246
 const servicePatrolRef = ref(null)
247
+const servicePatrolLineRef = ref(null)
224 248
 const complaintTeamRef = ref(null)
225 249
 const unsafeCompareRef = ref(null)
226 250
 const subhealthPieRef = ref(null)
@@ -298,7 +322,16 @@ const realtimeLineOpt = computed(() => ({
298 322
   tooltip: { trigger: 'axis', backgroundColor: tooltipBg, borderColor: tooltipBorder, textStyle: { color: tooltipText } }
299 323
 }))
300 324
 
301
-// 7. 实时质控开机年轮分布
325
+// 7. 实时质控开机年限分布
326
+const yearLimitOpt = computed(() => ({
327
+  grid: { top: 15, bottom: 25, left: 40, right: 15 },
328
+  xAxis: { type: 'category', data: Array.from({ length: 14 }, (_, i) => i + 1), axisLabel: { color: axisLabelColor, fontSize: 11 }, axisLine: { lineStyle: { color: axisLineColor } } },
329
+  yAxis: { type: 'value', axisLabel: { color: axisLabelColor, fontSize: 11 }, splitLine: { lineStyle: { color: splitLineColor } } },
330
+  series: [{ type: 'bar', data: [5, 32, 65, 11, 14, 11, 9, 16, 27, 45, 31, 23, 27, 8], barWidth: '55%', itemStyle: { color: '#3b82f6', borderRadius: [3, 3, 0, 0] }, label: { show: true, position: 'top', color: '#1e293b', fontSize: 11 } }],
331
+  tooltip: { trigger: 'axis', backgroundColor: tooltipBg, borderColor: tooltipBorder, textStyle: { color: tooltipText } }
332
+}))
333
+
334
+// 8. 实时质控开机年龄分布
302 335
 const yearRingOpt = computed(() => ({
303 336
   grid: { top: 15, bottom: 25, left: 40, right: 15 },
304 337
   xAxis: { type: 'category', data: Array.from({ length: 42 }, (_, i) => i + 1), axisLabel: { color: axisLabelColor, fontSize: 10, interval: 4 }, axisLine: { lineStyle: { color: axisLineColor } } },
@@ -307,7 +340,7 @@ const yearRingOpt = computed(() => ({
307 340
   tooltip: { trigger: 'axis', backgroundColor: tooltipBg, borderColor: tooltipBorder, textStyle: { color: tooltipText } }
308 341
 }))
309 342
 
310
-// 8. 实时质控围难易度
343
+// 9. 实时质控围难易度
311 344
 const difficultyOpt = computed(() => ({
312 345
   grid: { top: 15, bottom: 20, left: 40, right: 15 },
313 346
   xAxis: { type: 'category', data: ['0', '1', '2', '3', '4', '5'], axisLabel: { color: axisLabelColor, fontSize: 11 }, axisLine: { lineStyle: { color: axisLineColor } } },
@@ -334,7 +367,17 @@ const servicePatrolOpt = computed(() => ({
334 367
   tooltip: { trigger: 'axis', backgroundColor: tooltipBg, borderColor: tooltipBorder, textStyle: { color: tooltipText } }
335 368
 }))
336 369
 
337
-// 11. 投诉涉及班组情况-条形图
370
+// 11. 服务巡查-折线图
371
+const servicePatrolLineOpt = computed(() => ({
372
+  legend: { data: ['计数'], textStyle: { color: axisLabelColor, fontSize: 12 }, top: 0, left: 0, icon: 'circle' },
373
+  grid: { top: 30, bottom: 35, left: 40, right: 15 },
374
+  xAxis: { type: 'category', data: ['05:00', '06:00', '07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00', '21:00', '空值'], axisLabel: { color: axisLabelColor, fontSize: 11, rotate: 30 }, axisLine: { lineStyle: { color: axisLineColor } } },
375
+  yAxis: { type: 'value', min: 0, max: 7, axisLabel: { color: axisLabelColor, fontSize: 11 }, splitLine: { lineStyle: { color: splitLineColor } } },
376
+  series: [{ name: '计数', type: 'line', data: [2, 5, 5, 5, 3, 4, 3, 2, 6, 5, 5, 3, 7, 3, 2, 3, 3, 1], lineStyle: { color: '#3b82f6', width: 2 }, itemStyle: { color: '#3b82f6' }, symbol: 'circle', symbolSize: 6, label: { show: true, position: 'top', color: '#1e293b', fontSize: 11 } }],
377
+  tooltip: { trigger: 'axis', backgroundColor: tooltipBg, borderColor: tooltipBorder, textStyle: { color: tooltipText } }
378
+}))
379
+
380
+// 12. 投诉涉及班组情况-条形图
338 381
 const complaintTeamOpt = computed(() => ({
339 382
   grid: { top: 15, bottom: 20, left: 100, right: 30 },
340 383
   xAxis: { type: 'value', axisLabel: { color: axisLabelColor, fontSize: 11 }, splitLine: { lineStyle: { color: splitLineColor } } },
@@ -343,7 +386,7 @@ const complaintTeamOpt = computed(() => ({
343 386
   tooltip: { trigger: 'axis', backgroundColor: tooltipBg, borderColor: tooltipBorder, textStyle: { color: tooltipText } }
344 387
 }))
345 388
 
346
-// 12. 不安全事件发生对比-柱状图
389
+// 13. 不安全事件发生对比-柱状图
347 390
 const unsafeCompareOpt = computed(() => ({
348 391
   grid: { top: 15, bottom: 25, left: 40, right: 15 },
349 392
   xAxis: { type: 'category', data: ['安平班组', '安行班组', '木兰班组', '芮茜班组', '拓新班组', '屹动班组'], axisLabel: { color: axisLabelColor, fontSize: 11, rotate: 15 }, axisLine: { lineStyle: { color: axisLineColor } } },
@@ -352,7 +395,7 @@ const unsafeCompareOpt = computed(() => ({
352 395
   tooltip: { trigger: 'axis', backgroundColor: tooltipBg, borderColor: tooltipBorder, textStyle: { color: tooltipText } }
353 396
 }))
354 397
 
355
-// 13. 亚健康人数占比-环形图
398
+// 14. 亚健康人数占比-环形图
356 399
 const subhealthPieOpt = computed(() => ({
357 400
   tooltip: { trigger: 'item', backgroundColor: tooltipBg, borderColor: tooltipBorder, textStyle: { color: tooltipText } },
358 401
   series: [{
@@ -371,7 +414,7 @@ const subhealthPieOpt = computed(() => ({
371 414
   }]
372 415
 }))
373 416
 
374
-// 14. 各班组健康与亚健康比例-双柱图
417
+// 15. 各班组健康与亚健康比例-双柱图
375 418
 const healthRatioOpt = computed(() => ({
376 419
   grid: { top: 20, bottom: 25, left: 45, right: 15 },
377 420
   legend: { data: ['健康人员', '亚健康人员'], textStyle: { color: '#475569', fontSize: 11 }, top: 0 },
@@ -384,7 +427,7 @@ const healthRatioOpt = computed(() => ({
384 427
   tooltip: { trigger: 'axis', backgroundColor: tooltipBg, borderColor: tooltipBorder, textStyle: { color: tooltipText } }
385 428
 }))
386 429
 
387
-// 15. 年龄分布-柱状图
430
+// 16. 年龄分布-柱状图
388 431
 const ageDistOpt = computed(() => {
389 432
   const ages = Array.from({ length: 23 }, (_, i) => i + 23)
390 433
   const data = [8, 12, 18, 24, 30, 36, 41, 36, 33, 28, 22, 18, 14, 10, 8, 6, 4, 3, 2, 2, 1, 1, 1]
@@ -405,9 +448,11 @@ useECharts(areaPieRef, areaPieOpt)
405 448
 useECharts(teamRealtimeRef, teamRealtimeOpt)
406 449
 useECharts(realtimeLineRef, realtimeLineOpt)
407 450
 useECharts(yearRingRef, yearRingOpt)
451
+useECharts(yearLimitRef, yearLimitOpt)
408 452
 useECharts(difficultyRef, difficultyOpt)
409 453
 useECharts(interceptItemsRef, interceptItemsOpt)
410 454
 useECharts(servicePatrolRef, servicePatrolOpt)
455
+useECharts(servicePatrolLineRef, servicePatrolLineOpt)
411 456
 useECharts(complaintTeamRef, complaintTeamOpt)
412 457
 useECharts(unsafeCompareRef, unsafeCompareOpt)
413 458
 useECharts(subhealthPieRef, subhealthPieOpt)
@@ -649,6 +694,7 @@ onMounted(() => {
649 694
       display: flex;
650 695
       justify-content: center;
651 696
       gap: 20px;
697
+      margin-top: 15px;
652 698
       margin-bottom: 12px;
653 699
 
654 700
       .rank-avatar-item {
@@ -657,16 +703,70 @@ onMounted(() => {
657 703
         align-items: center;
658 704
         gap: 6px;
659 705
 
660
-        .rank-avatar {
661
-          width: 44px;
662
-          height: 44px;
663
-          border-radius: 50%;
664
-          display: flex;
706
+        &:nth-child(2) {
707
+          transform: translateY(-10px);
708
+        }
709
+
710
+        .rank-avatar-wrapper {
711
+          position: relative;
712
+          display: inline-flex;
665 713
           align-items: center;
666 714
           justify-content: center;
667
-          color: #fff;
668
-          font-size: 16px;
669
-          font-weight: bold;
715
+          border-radius: 50%;
716
+
717
+
718
+          &.rank-pos-1 {
719
+            border: 3px solid #94a3b8;
720
+
721
+            .rank-badge {
722
+              background: #94a3b8;
723
+            }
724
+
725
+          }
726
+
727
+          &.rank-pos-2 {
728
+            border: 3px solid #fbbf24;
729
+
730
+            .rank-badge {
731
+              background: #fbbf24;
732
+            }
733
+          }
734
+
735
+          &.rank-pos-3 {
736
+            border: 3px solid #fb923c;
737
+
738
+            .rank-badge {
739
+              background: #fb923c;
740
+            }
741
+          }
742
+
743
+          .rank-avatar {
744
+            width: 44px;
745
+            height: 44px;
746
+            border-radius: 50%;
747
+            display: flex;
748
+            align-items: center;
749
+            justify-content: center;
750
+            color: #fff;
751
+            font-size: 16px;
752
+            font-weight: bold;
753
+          }
754
+
755
+          .rank-badge {
756
+            position: absolute;
757
+            bottom: -8px;
758
+            left: 50%;
759
+            transform: translateX(-50%);
760
+            width: 12px;
761
+            height: 12px;
762
+            border-radius: 50%;
763
+            display: flex;
764
+            align-items: center;
765
+            justify-content: center;
766
+            font-size: 11px;
767
+            font-weight: bold;
768
+            color: #fff;
769
+          }
670 770
         }
671 771
 
672 772
         .rank-name {