Kaynağa Gözat

feat(organProfile): 新增机构画像页面及多样化统计图表展示

- 创建机构画像页面整体模板及样式
- 添加顶部统计卡片展示关键指标
- 实现多种ECharts图表包括折线图、柱状图、饼图等
- 支持监察问题统计、问题类型分布、区域问题占比等多维度数据展示
- 增加安检、航班楼、服务巡检、投诉等专项数据排名展示
- 实现实时质控相关多个统计图表
- 完成健康与亚健康人数比例及值机人员年龄分布等健康数据可视化
- 维护图表实例,支持组件销毁时释放资源
huoyi 3 gün önce
ebeveyn
işleme
2767acc23c
3 değiştirilmiş dosya ile 535 ekleme ve 1 silme
  1. 6 0
      src/pages.json
  2. 528 0
      src/pages/organProfile/index.vue
  3. 1 1
      src/pages/work/index.vue

+ 6 - 0
src/pages.json

@@ -130,6 +130,12 @@
130 130
       }
131 131
     },
132 132
     {
133
+      "path": "pages/organProfile/index",
134
+      "style": {
135
+        "navigationBarTitleText": "组织全景看板"
136
+      }
137
+    },
138
+    {
133 139
       "path": "pages/stationProfile/index",
134 140
       "style": {
135 141
         "navigationBarTitleText": "站画像"

+ 528 - 0
src/pages/organProfile/index.vue

@@ -0,0 +1,528 @@
1
+<template>
2
+    <view class="organ-profile-page">
3
+        <scroll-view scroll-y class="page-scroll">
4
+            <!-- ====== 顶部统计卡片 ====== -->
5
+            <view class="summary-grid">
6
+                <view class="summary-card" v-for="(item, idx) in summaryCards" :key="idx"
7
+                    :style="{ background: item.bg }">
8
+                    <text class="summary-label">{{ item.label }}</text>
9
+                    <text class="summary-value">{{ item.value }}</text>
10
+                    <text class="summary-change" :class="item.change > 0 ? 'up' : 'down'">
11
+                        {{ item.change > 0 ? '↑' : '↓' }}{{ Math.abs(item.change) }}%
12
+                    </text>
13
+                </view>
14
+            </view>
15
+
16
+            <!-- ====== 监察问题统计 ====== -->
17
+            <view class="chart-card">
18
+                <view class="chart-title">监察问题统计</view>
19
+                <view class="chart-box"><div ref="chartSuperviseTrend" class="chart-inner"></div></view>
20
+            </view>
21
+
22
+            <!-- ====== 问题类型分布 ====== -->
23
+            <view class="chart-card">
24
+                <view class="chart-title">问题类型分布</view>
25
+                <view class="chart-box"><div ref="chartIssueType" class="chart-inner"></div></view>
26
+            </view>
27
+
28
+            <!-- ====== 区域问题占比(监察) ====== -->
29
+            <view class="chart-card">
30
+                <view class="chart-title">区域问题占比(监察)</view>
31
+                <view class="chart-box"><div ref="chartRegionPie" class="chart-inner chart-pie"></div></view>
32
+            </view>
33
+
34
+            <!-- ====== 各队问题数(监察) ====== -->
35
+            <view class="chart-card">
36
+                <view class="chart-title">各队问题数(监察)</view>
37
+                <view class="chart-box"><div ref="chartTeamSupervise" class="chart-inner"></div></view>
38
+            </view>
39
+
40
+            <!-- ====== 实时质控拦截情况 ====== -->
41
+            <view class="chart-card">
42
+                <view class="chart-title">实时质控拦截情况</view>
43
+                <view class="chart-box"><div ref="chartIntercept" class="chart-inner"></div></view>
44
+            </view>
45
+
46
+            <!-- ====== 各队问题数(实时质控) ====== -->
47
+            <view class="chart-card">
48
+                <view class="chart-title">各队问题数(实时质控)</view>
49
+                <view class="chart-box"><div ref="chartTeamQuality" class="chart-inner"></div></view>
50
+            </view>
51
+
52
+            <!-- ====== 实时质控开机年龄分布 ====== -->
53
+            <view class="chart-card">
54
+                <view class="chart-title">实时质控开机年龄分布</view>
55
+                <view class="chart-box"><div ref="chartAgeDist" class="chart-inner"></div></view>
56
+            </view>
57
+
58
+            <!-- ====== 实时质控围栏难易度 ====== -->
59
+            <view class="chart-card">
60
+                <view class="chart-title">实时质控围栏难易度</view>
61
+                <view class="chart-box"><div ref="chartFence" class="chart-inner"></div></view>
62
+            </view>
63
+
64
+            <!-- ====== 实时拦截物品汇总 ====== -->
65
+            <view class="chart-card">
66
+                <view class="chart-title">实时拦截物品汇总</view>
67
+                <view class="chart-box"><div ref="chartItems" class="chart-inner"></div></view>
68
+            </view>
69
+
70
+            <!-- ====== 安检情况(合计) ====== -->
71
+            <view class="chart-card">
72
+                <view class="chart-title">安检情况(合计)</view>
73
+                <view class="security-summary">
74
+                    <view class="security-avatars">
75
+                        <view class="sec-avatar" v-for="(item, idx) in securityAvatars" :key="idx">
76
+                            <view class="sec-avatar-circle" :style="{ background: item.color }">
77
+                                <text>{{ item.name }}</text>
78
+                            </view>
79
+                            <text class="sec-avatar-score">{{ item.score }}</text>
80
+                        </view>
81
+                    </view>
82
+                    <view class="security-list">
83
+                        <view class="sec-item" v-for="(item, idx) in securityList" :key="idx">
84
+                            <text class="sec-rank">{{ idx + 1 }}</text>
85
+                            <text class="sec-name">{{ item.name }}</text>
86
+                            <text class="sec-score">{{ item.score }}</text>
87
+                        </view>
88
+                    </view>
89
+                </view>
90
+            </view>
91
+
92
+            <!-- ====== 航班楼加分 ====== -->
93
+            <view class="chart-card">
94
+                <view class="chart-title">航班楼加分</view>
95
+                <view class="security-summary">
96
+                    <view class="security-avatars">
97
+                        <view class="sec-avatar" v-for="(item, idx) in flightAvatars" :key="idx">
98
+                            <view class="sec-avatar-circle" :style="{ background: item.color }">
99
+                                <text>{{ item.name }}</text>
100
+                            </view>
101
+                            <text class="sec-avatar-score">{{ item.score }}</text>
102
+                        </view>
103
+                    </view>
104
+                    <view class="security-list">
105
+                        <view class="sec-item" v-for="(item, idx) in flightList" :key="idx">
106
+                            <text class="sec-rank">{{ idx + 1 }}</text>
107
+                            <text class="sec-name">{{ item.name }}</text>
108
+                            <text class="sec-score">{{ item.score }}</text>
109
+                        </view>
110
+                    </view>
111
+                </view>
112
+            </view>
113
+
114
+            <!-- ====== 服务巡检 ====== -->
115
+            <view class="chart-card">
116
+                <view class="chart-title">服务巡检</view>
117
+                <view class="chart-box"><div ref="chartServiceInspect" class="chart-inner"></div></view>
118
+            </view>
119
+
120
+            <!-- ====== 投诉情况(部门) ====== -->
121
+            <view class="chart-card">
122
+                <view class="chart-title">投诉情况(部门)</view>
123
+                <view class="chart-box"><div ref="chartComplaint" class="chart-inner"></div></view>
124
+            </view>
125
+
126
+            <!-- ====== 不安全事件对比 ====== -->
127
+            <view class="chart-card">
128
+                <view class="chart-title">不安全事件对比</view>
129
+                <view class="chart-box"><div ref="chartUnsafe" class="chart-inner"></div></view>
130
+            </view>
131
+
132
+            <!-- ====== 亚健康人数占比 ====== -->
133
+            <view class="chart-card">
134
+                <view class="chart-title">亚健康人数占比</view>
135
+                <view class="chart-box"><div ref="chartSubHealthPie" class="chart-inner chart-pie"></div></view>
136
+            </view>
137
+
138
+            <!-- ====== 健康人数与亚健康人数比例 ====== -->
139
+            <view class="chart-card">
140
+                <view class="chart-title">健康人数与亚健康人数比例</view>
141
+                <view class="chart-box"><div ref="chartHealthStack" class="chart-inner"></div></view>
142
+            </view>
143
+
144
+            <!-- ====== 值机人员年龄分布 ====== -->
145
+            <view class="chart-card">
146
+                <view class="chart-title">值机人员年龄分布</view>
147
+                <view class="chart-box"><div ref="chartCheckinAge" class="chart-inner"></div></view>
148
+            </view>
149
+
150
+            <!-- ====== 查获数量 ====== -->
151
+            <view class="chart-card">
152
+                <view class="chart-title">查获数量</view>
153
+                <view class="security-summary">
154
+                    <view class="security-avatars">
155
+                        <view class="sec-avatar" v-for="(item, idx) in seizeAvatars" :key="idx">
156
+                            <view class="sec-avatar-circle" :style="{ background: item.color }">
157
+                                <text>{{ item.name }}</text>
158
+                            </view>
159
+                            <text class="sec-avatar-score">{{ item.score }}</text>
160
+                        </view>
161
+                    </view>
162
+                    <view class="security-list">
163
+                        <view class="sec-item" v-for="(item, idx) in seizeList" :key="idx">
164
+                            <text class="sec-rank">{{ idx + 1 }}</text>
165
+                            <text class="sec-name">{{ item.name }}</text>
166
+                            <text class="sec-score">{{ item.score }}</text>
167
+                        </view>
168
+                    </view>
169
+                </view>
170
+            </view>
171
+        </scroll-view>
172
+    </view>
173
+</template>
174
+<script>
175
+import * as echarts from 'echarts'
176
+
177
+export default {
178
+    name: 'OrganProfile',
179
+    data() {
180
+        return {
181
+            summaryCards: [
182
+                { label: '监察问题数(月)', value: '11', change: -57.69, bg: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' },
183
+                { label: '实时巡检数(月)', value: '21', change: 56.25, bg: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)' },
184
+                { label: '服务巡检(月)', value: '4', change: 0, bg: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)' },
185
+                { label: '投诉情况(月)', value: '1', change: -88.89, bg: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)' },
186
+                { label: '不安全事件(本年)', value: '3', change: -57.14, bg: 'linear-gradient(135deg, #fa709a 0%, #fee140 100%)' },
187
+                { label: '部门健康人数', value: '147', change: 0, bg: 'linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%)' }
188
+            ],
189
+            securityAvatars: [
190
+                { name: '安检', score: '11', color: '#667eea' },
191
+                { name: '易舟', score: '9', color: '#f093fb' }
192
+            ],
193
+            securityList: [
194
+                { name: '薛烨轩', score: '11' },
195
+                { name: '黄俊涛', score: '11' },
196
+                { name: '李思思', score: '10' },
197
+                { name: '张明阳', score: '9' },
198
+                { name: '王丽华', score: '8' }
199
+            ],
200
+            flightAvatars: [
201
+                { name: '温', score: '24.5', color: '#4facfe' },
202
+                { name: '杨', score: '34.5', color: '#43e97b' },
203
+                { name: '何', score: '16', color: '#fa709a' }
204
+            ],
205
+            flightList: [
206
+                { name: '潘林', score: '15' },
207
+                { name: '马迪', score: '14.5' },
208
+                { name: '谢琳', score: '14' },
209
+                { name: '周杰', score: '13' },
210
+                { name: '吴芳', score: '12' }
211
+            ],
212
+            seizeAvatars: [
213
+                { name: '郭', score: '113', color: '#667eea' },
214
+                { name: '黄', score: '90', color: '#f5576c' }
215
+            ],
216
+            seizeList: [
217
+                { name: '郭志远', score: '82' },
218
+                { name: '黄晓明', score: '76' },
219
+                { name: '叶伟', score: '75' },
220
+                { name: '陈静', score: '70' },
221
+                { name: '刘洋', score: '68' }
222
+            ],
223
+            chartInstances: {}
224
+        }
225
+    },
226
+    mounted() {
227
+        this.$nextTick(() => {
228
+            this.initSuperviseTrend()
229
+            this.initIssueType()
230
+            this.initRegionPie()
231
+            this.initTeamSupervise()
232
+            this.initIntercept()
233
+            this.initTeamQuality()
234
+            this.initAgeDist()
235
+            this.initFence()
236
+            this.initItems()
237
+            this.initServiceInspect()
238
+            this.initComplaint()
239
+            this.initUnsafe()
240
+            this.initSubHealthPie()
241
+            this.initHealthStack()
242
+            this.initCheckinAge()
243
+        })
244
+    },
245
+    beforeDestroy() {
246
+        Object.values(this.chartInstances).forEach(i => { if (i) i.dispose() })
247
+    },
248
+    methods: {
249
+        _init(refName, option) {
250
+            const dom = this.$refs[refName]
251
+            if (!dom) return
252
+            const inst = echarts.init(dom)
253
+            inst.setOption(option)
254
+            this.chartInstances[refName] = inst
255
+        },
256
+        initSuperviseTrend() {
257
+            this._init('chartSuperviseTrend', {
258
+                tooltip: { trigger: 'axis' },
259
+                grid: { left: '3%', right: '4%', bottom: '10%', top: '8%', containLabel: true },
260
+                xAxis: { type: 'category', data: ['03:00','04:00','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'],
261
+                    axisLabel: { rotate: 45, fontSize: 9, interval: 1 } },
262
+                yAxis: { type: 'value', max: 20 },
263
+                series: [{ type: 'line', data: [17,11,12,9,14,15,10,15,10,7,9,6,4,2,3,1,2,1],
264
+                    smooth: true, lineStyle: { color: '#667eea', width: 2 }, itemStyle: { color: '#667eea' },
265
+                    areaStyle: { color: 'rgba(102,126,234,0.15)' } }]
266
+            })
267
+        },
268
+        initIssueType() {
269
+            this._init('chartIssueType', {
270
+                tooltip: { trigger: 'axis' },
271
+                grid: { left: '3%', right: '4%', bottom: '10%', top: '8%', containLabel: true },
272
+                xAxis: { type: 'category', data: ['岗位不端', '岗位操作'], axisLabel: { fontSize: 10 } },
273
+                yAxis: { type: 'value', max: 120 },
274
+                series: [{ type: 'bar', data: [
275
+                    { value: 75, itemStyle: { color: '#667eea' } },
276
+                    { value: 101, itemStyle: { color: '#f5576c' } }
277
+                ], barWidth: '30%', label: { show: true, position: 'top', fontSize: 10 } }]
278
+            })
279
+        },
280
+        initRegionPie() {
281
+            this._init('chartRegionPie', {
282
+                tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' },
283
+                legend: { bottom: 0, left: 'center', textStyle: { fontSize: 9 } },
284
+                series: [{
285
+                    type: 'pie', radius: ['30%', '55%'], center: ['50%', '40%'],
286
+                    label: { fontSize: 9, formatter: '{d}%' },
287
+                    data: [
288
+                        { value: 39, name: 'T3国内', itemStyle: { color: '#667eea' } },
289
+                        { value: 5, name: 'T3国际', itemStyle: { color: '#f5576c' } },
290
+                        { value: 1, name: 'T3出港', itemStyle: { color: '#43e97b' } },
291
+                        { value: 1, name: 'T3中心实时', itemStyle: { color: '#a18cd1' } }
292
+                    ]
293
+                }]
294
+            })
295
+        },
296
+        initTeamSupervise() {
297
+            this._init('chartTeamSupervise', {
298
+                tooltip: { trigger: 'axis' },
299
+                grid: { left: '3%', right: '4%', bottom: '10%', top: '8%', containLabel: true },
300
+                xAxis: { type: 'category', data: ['安平组','安兴组','木兰组','翁西组','展新组','点云组'],
301
+                    axisLabel: { rotate: 30, fontSize: 9 } },
302
+                yAxis: { type: 'value', max: 50 },
303
+                series: [{ type: 'bar', data: [34,21,2,41,39,34],
304
+                    barWidth: '35%', itemStyle: { color: '#4facfe' },
305
+                    label: { show: true, position: 'top', fontSize: 9 } }]
306
+            })
307
+        },
308
+        initIntercept() {
309
+            this._init('chartIntercept', {
310
+                tooltip: { trigger: 'axis' },
311
+                grid: { left: '3%', right: '4%', bottom: '10%', top: '8%', containLabel: true },
312
+                xAxis: { type: 'category', data: ['04:00','06:00','08:00','10:00','12:00','14:00','16:00','18:00','20:00','22:00','23:00'],
313
+                    axisLabel: { rotate: 45, fontSize: 9, interval: 1 } },
314
+                yAxis: { type: 'value', max: 80 },
315
+                series: [{ type: 'line', data: [5,31,60,44,26,21,65,56,75,30,15],
316
+                    smooth: true, lineStyle: { color: '#f5576c', width: 2 }, itemStyle: { color: '#f5576c' },
317
+                    areaStyle: { color: 'rgba(245,87,108,0.15)' } }]
318
+            })
319
+        },
320
+        initTeamQuality() {
321
+            this._init('chartTeamQuality', {
322
+                tooltip: { trigger: 'axis' },
323
+                grid: { left: '3%', right: '4%', bottom: '10%', top: '8%', containLabel: true },
324
+                xAxis: { type: 'category', data: ['安平组','安兴组','木兰组','翁西组','展新组','点云组'],
325
+                    axisLabel: { rotate: 30, fontSize: 9 } },
326
+                yAxis: { type: 'value', max: 90 },
327
+                series: [{ type: 'bar', data: [60,44,21,65,56,75],
328
+                    barWidth: '35%', itemStyle: { color: '#fa709a' },
329
+                    label: { show: true, position: 'top', fontSize: 9 } }]
330
+            })
331
+        },
332
+        initAgeDist() {
333
+            this._init('chartAgeDist', {
334
+                tooltip: { trigger: 'axis' },
335
+                grid: { left: '3%', right: '4%', bottom: '10%', top: '8%', containLabel: true },
336
+                xAxis: { type: 'category', data: ['1岁','2岁','3岁','4岁','5岁','6岁','7岁','8岁','9岁','10岁','11岁','12岁','13岁','14岁'],
337
+                    axisLabel: { fontSize: 8, interval: 1 } },
338
+                yAxis: { type: 'value', max: 70 },
339
+                series: [{ type: 'bar', data: [5,65,11,14,11,9,16,27,45,31,23,27,8,2],
340
+                    barWidth: '40%', itemStyle: { color: '#667eea' },
341
+                    label: { show: true, position: 'top', fontSize: 8 } }]
342
+            })
343
+        },
344
+        initFence() {
345
+            this._init('chartFence', {
346
+                tooltip: { trigger: 'axis' },
347
+                grid: { left: '3%', right: '4%', bottom: '10%', top: '8%', containLabel: true },
348
+                xAxis: { type: 'category', data: ['0级','1级','2级','3级','4级','5级'], axisLabel: { fontSize: 10 } },
349
+                yAxis: { type: 'value', max: 160 },
350
+                series: [{ type: 'bar', data: [2,145,70,92,16,1],
351
+                    barWidth: '35%', itemStyle: { color: '#43e97b' },
352
+                    label: { show: true, position: 'top', fontSize: 9 } }]
353
+            })
354
+        },
355
+        initItems() {
356
+            this._init('chartItems', {
357
+                tooltip: { trigger: 'axis' },
358
+                grid: { left: '3%', right: '4%', bottom: '10%', top: '8%', containLabel: true },
359
+                xAxis: { type: 'category', data: ['0','1','2','3','4','5+'], axisLabel: { fontSize: 10 } },
360
+                yAxis: { type: 'value', max: 150 },
361
+                series: [{ type: 'bar', data: [14,23,56,19,24,136],
362
+                    barWidth: '35%', itemStyle: { color: '#4facfe' },
363
+                    label: { show: true, position: 'top', fontSize: 9 } }]
364
+            })
365
+        },
366
+        initServiceInspect() {
367
+            this._init('chartServiceInspect', {
368
+                tooltip: { trigger: 'axis' },
369
+                grid: { left: '3%', right: '4%', bottom: '10%', top: '8%', containLabel: true },
370
+                xAxis: { type: 'category', data: ['安平组','安兴组','木兰组','翁西组','展新组','点云组'],
371
+                    axisLabel: { rotate: 30, fontSize: 9 } },
372
+                yAxis: { type: 'value', max: 20 },
373
+                series: [{ type: 'bar', data: [16,7,1,15,14,11],
374
+                    barWidth: '35%', itemStyle: { color: '#43e97b' },
375
+                    label: { show: true, position: 'top', fontSize: 9 } }]
376
+            })
377
+        },
378
+        initComplaint() {
379
+            this._init('chartComplaint', {
380
+                tooltip: { trigger: 'axis' },
381
+                grid: { left: '3%', right: '4%', bottom: '8%', top: '5%', containLabel: true },
382
+                xAxis: { type: 'value', max: 60 },
383
+                yAxis: { type: 'category', data: ['点云组','信武队','翁西组','木兰组','航空组','安平组'],
384
+                    axisLabel: { fontSize: 9 } },
385
+                series: [{ type: 'bar', data: [
386
+                    { value: 50, itemStyle: { color: '#f5576c' } },
387
+                    { value: 30, itemStyle: { color: '#fa709a' } },
388
+                    { value: 45, itemStyle: { color: '#667eea' } },
389
+                    { value: 19, itemStyle: { color: '#43e97b' } },
390
+                    { value: 19, itemStyle: { color: '#4facfe' } },
391
+                    { value: 37, itemStyle: { color: '#a18cd1' } }
392
+                ], barWidth: '50%', label: { show: true, position: 'right', fontSize: 9 } }]
393
+            })
394
+        },
395
+        initUnsafe() {
396
+            this._init('chartUnsafe', {
397
+                tooltip: { trigger: 'axis' },
398
+                grid: { left: '3%', right: '4%', bottom: '10%', top: '8%', containLabel: true },
399
+                xAxis: { type: 'category', data: ['安平组','安兴组','木兰组','翁西组','展新组','点云组'],
400
+                    axisLabel: { rotate: 30, fontSize: 9 } },
401
+                yAxis: { type: 'value', max: 10 },
402
+                series: [{ type: 'bar', data: [3,4,4,8,3,2],
403
+                    barWidth: '35%', itemStyle: { color: '#fa709a' },
404
+                    label: { show: true, position: 'top', fontSize: 9 } }]
405
+            })
406
+        },
407
+        initSubHealthPie() {
408
+            this._init('chartSubHealthPie', {
409
+                tooltip: { trigger: 'item', formatter: '{b}: {c}人 ({d}%)' },
410
+                legend: { bottom: 0, left: 'center', textStyle: { fontSize: 9 } },
411
+                series: [{
412
+                    type: 'pie', radius: ['30%', '55%'], center: ['50%', '40%'],
413
+                    label: { fontSize: 9, formatter: '{d}%' },
414
+                    data: [
415
+                        { value: 28, name: '点云组', itemStyle: { color: '#667eea' } },
416
+                        { value: 23, name: '安平组', itemStyle: { color: '#f5576c' } },
417
+                        { value: 25, name: '翁西组', itemStyle: { color: '#43e97b' } },
418
+                        { value: 20, name: '安兴组', itemStyle: { color: '#4facfe' } },
419
+                        { value: 18, name: '展新组', itemStyle: { color: '#fa709a' } },
420
+                        { value: 15, name: '木兰组', itemStyle: { color: '#a18cd1' } }
421
+                    ]
422
+                }]
423
+            })
424
+        },
425
+        initHealthStack() {
426
+            this._init('chartHealthStack', {
427
+                tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
428
+                legend: { bottom: 0, left: 'center', textStyle: { fontSize: 9 } },
429
+                grid: { left: '3%', right: '4%', bottom: '18%', top: '5%', containLabel: true },
430
+                xAxis: { type: 'category', data: ['安平组','安兴组','木兰组','翁西组','展新组','点云组'],
431
+                    axisLabel: { rotate: 30, fontSize: 8 } },
432
+                yAxis: { type: 'value', max: 60 },
433
+                series: [
434
+                    { name: '健康人数', type: 'bar', stack: 'total', barWidth: '35%',
435
+                        itemStyle: { color: '#4facfe' }, data: [35,20,29,26,22,27] },
436
+                    { name: '亚健康人数', type: 'bar', stack: 'total', barWidth: '35%',
437
+                        itemStyle: { color: '#f5576c' }, data: [23,29,13,27,28,25] }
438
+                ]
439
+            })
440
+        },
441
+        initCheckinAge() {
442
+            this._init('chartCheckinAge', {
443
+                tooltip: { trigger: 'axis' },
444
+                grid: { left: '3%', right: '4%', bottom: '10%', top: '8%', containLabel: true },
445
+                xAxis: { type: 'category', data: ['23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45'],
446
+                    axisLabel: { fontSize: 8, interval: 2 } },
447
+                yAxis: { type: 'value', max: 45 },
448
+                series: [{ type: 'bar', data: [5,8,12,15,18,22,29,36,41,33,19,14,10,8,6,5,4,3,3,2,2,1,1],
449
+                    barWidth: '40%', itemStyle: { color: '#667eea' },
450
+                    label: { show: true, position: 'top', fontSize: 8 } }]
451
+            })
452
+        }
453
+    }
454
+}
455
+</script>
456
+
457
+<style lang="scss" scoped>
458
+.organ-profile-page {
459
+    min-height: 100vh;
460
+    background: #f5f7fa;
461
+}
462
+.page-scroll {
463
+    height: 100vh;
464
+    padding: 16rpx 20rpx 40rpx;
465
+}
466
+.summary-grid {
467
+    display: grid;
468
+    grid-template-columns: 1fr 1fr;
469
+    gap: 12rpx;
470
+    margin-bottom: 16rpx;
471
+}
472
+.summary-card {
473
+    border-radius: 16rpx;
474
+    padding: 20rpx 16rpx;
475
+    color: #fff;
476
+    display: flex;
477
+    flex-direction: column;
478
+    gap: 6rpx;
479
+}
480
+.summary-label { font-size: 22rpx; opacity: 0.9; }
481
+.summary-value { font-size: 44rpx; font-weight: bold; }
482
+.summary-change { font-size: 20rpx; }
483
+.summary-change.up { color: #43e97b; }
484
+.summary-change.down { color: #ffd666; }
485
+.chart-card {
486
+    background: #fff;
487
+    border-radius: 16rpx;
488
+    padding: 24rpx 20rpx;
489
+    margin-bottom: 16rpx;
490
+    box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
491
+}
492
+.chart-title {
493
+    font-size: 28rpx;
494
+    font-weight: 600;
495
+    color: #333;
496
+    margin-bottom: 16rpx;
497
+}
498
+.chart-box { width: 100%; }
499
+.chart-inner { width: 100%; height: 380rpx; }
500
+.chart-pie { height: 420rpx; }
501
+.security-summary { padding: 0 8rpx; }
502
+.security-avatars {
503
+    display: flex;
504
+    justify-content: center;
505
+    gap: 40rpx;
506
+    margin-bottom: 24rpx;
507
+}
508
+.sec-avatar { display: flex; flex-direction: column; align-items: center; gap: 8rpx; }
509
+.sec-avatar-circle {
510
+    width: 80rpx; height: 80rpx; border-radius: 50%;
511
+    display: flex; align-items: center; justify-content: center;
512
+}
513
+.sec-avatar-circle text { color: #fff; font-size: 26rpx; font-weight: bold; }
514
+.sec-avatar-score { font-size: 32rpx; font-weight: bold; color: #333; }
515
+.security-list { display: flex; flex-direction: column; gap: 0; }
516
+.sec-item {
517
+    display: flex; align-items: center; padding: 16rpx 0;
518
+    border-bottom: 1rpx solid #f5f5f5;
519
+}
520
+.sec-item:last-child { border-bottom: none; }
521
+.sec-rank {
522
+    width: 40rpx; height: 40rpx; border-radius: 50%;
523
+    background: #f0f0f0; display: flex; align-items: center; justify-content: center;
524
+    font-size: 22rpx; color: #666; margin-right: 20rpx;
525
+}
526
+.sec-name { flex: 1; font-size: 26rpx; color: #333; }
527
+.sec-score { font-size: 28rpx; font-weight: 600; color: #667eea; }
528
+</style>

+ 1 - 1
src/pages/work/index.vue

@@ -41,7 +41,7 @@
41 41
 import HomeContainer from "@/components/HomeContainer.vue";
42 42
 import { checkRolePermission } from "@/utils/common.js";
43 43
 import { getUserProfile, getAppListByRoleId,getAppList } from "@/api/system/user";
44
-const profileAppNames = ['画像', '部门画像', '班组画像', '小组画像', '员工画像']
44
+const profileAppNames = ['综合信息画像', '部门画像', '班组画像', '小组画像', '员工画像']
45 45
 export default {
46 46
   components: { HomeContainer },
47 47
   data() {