Commit 8b8e41b099a9b9faff1ee992c81c84fc1457e874

Authored by ww
1 parent 416ae516

perf: 优化首页统计块展示

1 import { BasicPageParams } from './../model/baseModel'; 1 import { BasicPageParams } from './../model/baseModel';
  2 +import { HomeStatisticsRecordType } from './model';
2 import { defHttp } from '/@/utils/http/axios'; 3 import { defHttp } from '/@/utils/http/axios';
3 enum HomeEnum { 4 enum HomeEnum {
4 home = '/homepage/left/top', 5 home = '/homepage/left/top',
@@ -9,7 +10,7 @@ enum HomeEnum { @@ -9,7 +10,7 @@ enum HomeEnum {
9 } 10 }
10 11
11 export const getHomeData = () => { 12 export const getHomeData = () => {
12 - return defHttp.get({ 13 + return defHttp.get<HomeStatisticsRecordType>({
13 url: HomeEnum.home, 14 url: HomeEnum.home,
14 }); 15 });
15 }; 16 };
1 -<template>  
2 - <div>  
3 - <!-- 首页基础信息 -->  
4 - <div class="md:flex">  
5 - <Card  
6 - v-if="!isAdmin(role)"  
7 - size="small"  
8 - class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4"  
9 - style="color: #666"  
10 - >  
11 - <div class="flex" style="height: 100px">  
12 - <div class="mr-4">  
13 - <img  
14 - v-if="!isAdmin(role)"  
15 - src="/src/assets/images/product.png"  
16 - style="width: 5.625rem; height: 5.625rem"  
17 - />  
18 - <img  
19 - v-else  
20 - src="/src/assets/images/product.png"  
21 - style="width: 5.625rem; height: 5.625rem"  
22 - />  
23 - </div>  
24 - <div class="flex-auto">  
25 - <div class="flex justify-between" style="align-items: center">  
26 - <div  
27 - v-if="!isAdmin(role)"  
28 - style="font-size: 1.625rem; color: #333; font-weight: bold"  
29 - >  
30 - <CountTo  
31 - v-if="growCardList?.productInfo?.sumCount"  
32 - :end-val="growCardList.productInfo.sumCount"  
33 - />  
34 - <CountTo v-else :end-val="0" />  
35 - </div>  
36 - <div style="font-size: 1.625rem; color: #333; font-weight: bold" v-else>  
37 - <CountTo  
38 - v-if="growCardList?.productInfo?.sumCount"  
39 - :end-val="growCardList.productInfo?.sumCount"  
40 - />  
41 - <CountTo v-else :end-val="0" />  
42 - </div>  
43 - <Tooltip>  
44 - <template #title>  
45 - {{  
46 - !isAdmin(role)  
47 - ? `产品数:${growCardList?.productInfo?.sumCount} 今日新增 ${toThousands(  
48 - growCardList?.productInfo?.todayAdd  
49 - )}`  
50 - : `产品数:${growCardList?.customerInfo?.sumCount} 今日新增 ${toThousands(  
51 - growCardList?.productInfo?.todayAdd  
52 - )}`  
53 - }}  
54 - </template>  
55 - <img src="/src/assets/images/tip.png" style="width: 1.125rem; height: 1.125rem" />  
56 - </Tooltip>  
57 - </div>  
58 - <div> {{ !isAdmin(role) ? `产品数` : '产品数' }}</div>  
59 - </div>  
60 - </div>  
61 - <div v-if="!isAdmin(role)" class="pt-4" style="border-top: 2px solid #f0f2f5">  
62 - 今日新增 {{ toThousands(growCardList?.productInfo?.todayAdd) }}</div  
63 - >  
64 - <div v-else class="pt-4" style="border-top: 2px solid #f0f2f5">  
65 - 今日新增 {{ toThousands(growCardList?.productInfo?.todayAdd) }}</div  
66 - >  
67 - </Card>  
68 - <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4" style="color: #666">  
69 - <div class="flex" style="height: 100px">  
70 - <div class="mr-4"  
71 - ><img  
72 - src="/src/assets/images/device-count.png"  
73 - style="width: 5.625rem; height: 5.625rem"  
74 - /></div>  
75 - <div class="flex-auto">  
76 - <div class="flex justify-between" style="align-items: center">  
77 - <div style="font-size: 1.625rem; color: #333; font-weight: bold">  
78 - <CountTo  
79 - v-if="growCardList?.deviceInfo?.sumCount"  
80 - :endVal="growCardList.deviceInfo.sumCount"  
81 - />  
82 - <CountTo v-else :endVal="0" />  
83 - </div>  
84 - <Tooltip>  
85 - <template #title>  
86 - 设备数 : {{ growCardList?.deviceInfo.sumCount }} 今日新增  
87 - {{ toThousands(growCardList?.deviceInfo?.todayAdd) }}  
88 - </template>  
89 - <img src="/src/assets/images/tip.png" style="width: 1.125rem; height: 1.125rem" />  
90 - </Tooltip>  
91 - </div>  
92 - <div> 设备数 </div>  
93 - </div>  
94 - </div>  
95 - <div class="pt-4" style="border-top: 2px solid #f0f2f5">  
96 - 今日新增 {{ toThousands(growCardList?.deviceInfo?.todayAdd) }}  
97 - </div>  
98 - </Card>  
99 - <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:ml-4" style="color: #666">  
100 - <div class="flex" style="height: 100px">  
101 - <div class="mr-4">  
102 - <img  
103 - v-if="!isAdmin(role)"  
104 - src="/src/assets/images/alarm-count.png"  
105 - style="width: 5.625rem; height: 5.625rem"  
106 - />  
107 - <img v-else src="/src/assets/images/zh.png" style="width: 5.625rem; height: 5.625rem" />  
108 - </div>  
109 - <div class="flex-auto">  
110 - <div class="flex justify-between" style="align-items: center">  
111 - <div  
112 - v-if="!isAdmin(role)"  
113 - style="font-size: 1.625rem; color: #333; font-weight: bold"  
114 - >  
115 - <CountTo  
116 - v-if="growCardList?.alarmInfo?.sumCount"  
117 - :end-val="growCardList.alarmInfo.sumCount"  
118 - />  
119 - <CountTo v-else :end-val="0" />  
120 - </div>  
121 - <div style="font-size: 1.625rem; color: #333; font-weight: bold" v-else>  
122 - <CountTo  
123 - v-if="growCardList?.tenantInfo?.sumCount"  
124 - :end-val="growCardList.tenantInfo.sumCount"  
125 - />  
126 - <CountTo v-else :end-val="0" />  
127 - </div>  
128 - <Tooltip>  
129 - <template #title>  
130 - {{  
131 - !isAdmin(role)  
132 - ? `告警数:${growCardList?.alarmInfo?.sumCount} 今日新增 ${toThousands(  
133 - growCardList?.alarmInfo?.todayAdd  
134 - )}`  
135 - : `租户总量:${growCardList?.tenantInfo?.sumCount} 今日新增 ${toThousands(  
136 - growCardList?.tenantInfo?.todayAdd  
137 - )}`  
138 - }}  
139 - </template>  
140 - <img src="/src/assets/images/tip.png" style="width: 1.125rem; height: 1.125rem" />  
141 - </Tooltip>  
142 - </div>  
143 - <div> {{ !isAdmin(role) ? `告警数` : '租户总量' }}</div>  
144 - </div>  
145 - </div>  
146 - <div v-if="!isAdmin(role)" class="pt-4" style="border-top: 2px solid #f0f2f5">  
147 - 今日新增 {{ toThousands(growCardList?.alarmInfo?.todayAdd) }}</div  
148 - >  
149 - <div v-else class="pt-4" style="border-top: 2px solid #f0f2f5">  
150 - 今日新增 {{ toThousands(growCardList?.tenantInfo?.todayAdd) }}</div  
151 - >  
152 - </Card>  
153 - <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:ml-4" style="color: #666">  
154 - <div class="flex" style="height: 100px">  
155 - <div class="mr-4">  
156 - <img  
157 - v-if="!isAdmin(role)"  
158 - src="/src/assets/images/msg-count.png"  
159 - style="width: 5.625rem; height: 5.625rem"  
160 - />  
161 - <img v-else src="/src/assets/images/kf.png" style="width: 5.625rem; height: 5.625rem" />  
162 - </div>  
163 - <div class="flex-auto">  
164 - <div class="flex justify-between" style="align-items: center">  
165 - <div  
166 - v-if="!isAdmin(role)"  
167 - style="font-size: 1.625rem; color: #333; font-weight: bold"  
168 - >  
169 - <CountTo  
170 - v-if="growCardList?.messageInfo?.messageCount"  
171 - :end-val="growCardList.messageInfo.messageCount"  
172 - />  
173 - <CountTo v-else :end-val="0" />  
174 - </div>  
175 - <div style="font-size: 1.625rem; color: #333; font-weight: bold" v-else>  
176 - <CountTo  
177 - v-if="growCardList?.customerInfo?.sumCount"  
178 - :end-val="growCardList.customerInfo.sumCount"  
179 - />  
180 - <CountTo v-else :end-val="0" />  
181 - </div>  
182 - <Tooltip>  
183 - <template #title>  
184 - {{  
185 - !isAdmin(role)  
186 - ? `今日消息数:${  
187 - growCardList?.messageInfo?.todayMessageAdd  
188 - } 今日消息点数 ${toThousands(  
189 - growCardList?.messageInfo?.todayDataPointsAdd  
190 - )}`  
191 - : `客户总量:${growCardList?.customerInfo?.sumCount} 今日新增 ${toThousands(  
192 - growCardList?.customerInfo?.todayAdd  
193 - )}`  
194 - }}  
195 - </template>  
196 - <img  
197 - v-if="isAdmin(role)"  
198 - src="/src/assets/images/tip.png"  
199 - style="width: 1.125rem; height: 1.125rem"  
200 - />  
201 - </Tooltip>  
202 - </div>  
203 - <div> {{ !isAdmin(role) ? `消息数` : '客户总量' }}</div>  
204 - </div>  
205 - <div class="flex-auto" v-if="!isAdmin(role)">  
206 - <div class="flex justify-between" style="align-items: center">  
207 - <div  
208 - v-if="!isAdmin(role)"  
209 - style="font-size: 1.625rem; color: #333; font-weight: bold"  
210 - >  
211 - <CountTo  
212 - v-if="growCardList?.messageInfo?.dataPointsCount"  
213 - :end-val="growCardList.messageInfo.dataPointsCount"  
214 - />  
215 - <CountTo v-else :end-val="0" />  
216 - </div>  
217 - <Tooltip>  
218 - <template #title>  
219 - {{  
220 - !isAdmin(role)  
221 - ? `今日消息数:${  
222 - growCardList?.messageInfo?.todayMessageAdd  
223 - } 今日消息点数 ${toThousands(  
224 - growCardList?.messageInfo?.todayDataPointsAdd  
225 - )}`  
226 - : `客户总量:${growCardList?.customerInfo?.sumCount} 今日新增 ${toThousands(  
227 - growCardList?.customerInfo?.todayAdd  
228 - )}`  
229 - }}  
230 - </template>  
231 - <img src="/src/assets/images/tip.png" style="width: 1.125rem; height: 1.125rem" />  
232 - </Tooltip>  
233 - </div>  
234 - <div> {{ !isAdmin(role) ? `消息点数` : '' }}</div>  
235 - </div>  
236 - </div>  
237 - <div class="flex justify-between" style="border-top: 2px solid #f0f2f5">  
238 - <div v-if="!isAdmin(role)" class="pt-4">  
239 - 今日消息数 {{ toThousands(growCardList?.messageInfo?.todayMessageAdd) }}</div  
240 - >  
241 - <div v-if="!isAdmin(role)" class="pt-4">  
242 - 今日消息点数 {{ toThousands(growCardList?.messageInfo?.todayDataPointsAdd) }}</div  
243 - >  
244 - <div v-else class="pt-4">  
245 - 近30日新增 {{ toThousands(growCardList?.customerInfo?.todayAdd) }}</div  
246 - >  
247 - </div>  
248 - </Card>  
249 - </div>  
250 - <!-- 首页饼图 -->  
251 - <div class="md:flex mt-4" v-if="!isAdmin(role)">  
252 - <Card  
253 - size="small"  
254 - class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4"  
255 - style="color: #666; width: 50%"  
256 - title="设备数量统计"  
257 - >  
258 - <a-row type="flex" justify="space-between" align="middle">  
259 - <a-col :span="12">  
260 - <PieChartDeviceSub  
261 - v-if="seriesData.length > 0"  
262 - :legendData="legendData"  
263 - :seriesData="seriesData"  
264 - :isCircle="false"  
265 - /></a-col>  
266 - <a-col :span="12">  
267 - <a-row type="flex" justify="space-between" align="middle" style="row-gap: 30px">  
268 - <a-col :offset="8" class="flex items-center">  
269 - <span class="left-icon-d-color"></span>  
270 - 直连设备:  
271 - <span class="bold-text">{{ growCardList?.deviceInfo?.directConnection ?? 0 }}</span  
272 - >个</a-col  
273 - >  
274 - <a-col :offset="8" class="flex items-center">  
275 - <span class="left-icon-g-color"></span>  
276 - 网关设备:  
277 - <span class="bold-text">{{ growCardList?.deviceInfo?.gateWay ?? 0 }}</span  
278 - >个</a-col  
279 - >  
280 - <a-col :offset="8" class="flex items-center">  
281 - <span class="left-icon-s-color"></span>  
282 - 网关子设备:<span class="bold-text">{{  
283 - growCardList?.deviceInfo?.sensor ?? 0  
284 - }}</span  
285 - >个</a-col  
286 - >  
287 - </a-row>  
288 - </a-col>  
289 - </a-row>  
290 - </Card>  
291 - <Card  
292 - size="small"  
293 - class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:ml-1"  
294 - style="color: #666; width: 50%"  
295 - title="设备状态统计"  
296 - >  
297 - <a-row type="flex" justify="space-between" align="middle">  
298 - <a-col :span="12">  
299 - <PieChartDeviceStatus  
300 - v-if="seriesStatusData.length > 0"  
301 - :seriesStatusData="seriesStatusData"  
302 - />  
303 - <div class="empty-box" v-else><Empty :image="Empty.PRESENTED_IMAGE_SIMPLE" /></div>  
304 - </a-col>  
305 - <a-col :span="12">  
306 - <a-row type="flex" justify="space-between" align="middle" style="row-gap: 30px">  
307 - <a-col :offset="8" class="flex items-center">  
308 - <span class="right-icon-d-color"></span>  
309 - 待激活设备:  
310 - <span class="bold-text">{{ growCardList?.deviceInfo?.inActive ?? 0 }}</span  
311 - >个</a-col  
312 - >  
313 - <a-col :offset="8" class="flex items-center">  
314 - <span class="right-icon-g-color"></span>  
315 - 在线设备:<span class="bold-text">{{ growCardList?.deviceInfo?.onLine ?? 0 }}</span  
316 - >个</a-col  
317 - >  
318 - <a-col :offset="8" class="flex items-center">  
319 - <span class="right-icon-s-color"></span>  
320 - 离线设备:<span class="bold-text">{{ growCardList?.deviceInfo?.offLine ?? 0 }}</span  
321 - >个</a-col  
322 - >  
323 - </a-row>  
324 - </a-col>  
325 - </a-row>  
326 - </Card>  
327 - </div>  
328 - </div>  
329 -</template>  
330 -<script lang="ts" setup>  
331 - import { ref, onMounted, defineComponent, Ref } from 'vue';  
332 - import { Card } from 'ant-design-vue';  
333 - import { getHomeData } from '/@/api/dashboard';  
334 - import { isAdmin } from '/@/enums/roleEnum';  
335 - import { toThousands } from '/@/utils/fnUtils';  
336 - import { CountTo } from '/@/components/CountTo/index';  
337 - import { Tooltip } from 'ant-design-vue';  
338 - import { CardList, seriesDataT } from './props';  
339 - import PieChartDeviceSub from './PieChartDeviceSub.vue';  
340 - import PieChartDeviceStatus from './PieChartDeviceStatus.vue';  
341 - import { Empty } from 'ant-design-vue';  
342 -  
343 - defineProps<{  
344 - role: string;  
345 - }>();  
346 -  
347 - defineExpose({  
348 - isAdmin,  
349 - toThousands,  
350 - });  
351 -  
352 - defineComponent({  
353 - Card,  
354 - });  
355 -  
356 - const legendData = ref(['网关设备', '直连设备', '网关子设备']);  
357 -  
358 - const seriesData: Ref<seriesDataT[]> = ref([]);  
359 -  
360 - const seriesStatusData: Ref<seriesDataT[]> = ref([]);  
361 -  
362 - const growCardList = ref<CardList>();  
363 -  
364 - const devicePieColor = [  
365 - { key: 'directConnection', itemStyle: { color: '#5C7BD9' }, value: '直连设备' },  
366 - { key: 'gateWay', itemStyle: { color: '#91CC75' }, value: '网关设备' },  
367 - { key: 'sensor', itemStyle: { color: '#FAC859' }, value: '网关子设备' },  
368 - { key: 'inActive', itemStyle: { color: '#5C7BD9' }, value: '待激活' },  
369 - { key: 'onLine', itemStyle: { color: '#91CC75 ' }, value: '在线' },  
370 - { key: 'offLine', itemStyle: { color: '#EC4040' }, value: '离线' },  
371 - ];  
372 -  
373 - onMounted(async () => {  
374 - const res = await getHomeData();  
375 - growCardList.value = res;  
376 - const { deviceInfo } = growCardList.value!;  
377 - let data = Object.entries(deviceInfo).map(([key, value]) => {  
378 - const name = devicePieColor?.find((f) => f.key === key)?.value;  
379 - const itemStyle = devicePieColor?.find((f) => f.key === key)?.itemStyle;  
380 - return { key, value, itemStyle, name };  
381 - });  
382 - seriesData.value = data.filter(  
383 - (f) => f.key === 'directConnection' || f.key === 'gateWay' || f.key === 'sensor'  
384 - );  
385 - seriesStatusData.value = data.filter(  
386 - (f) => f.key === 'inActive' || f.key === 'onLine' || f.key === 'offLine'  
387 - );  
388 - });  
389 -</script>  
390 -<style lang="less">  
391 - .text {  
392 - color: #333;  
393 - display: flex;  
394 - flex-wrap: nowrap;  
395 - }  
396 -  
397 - .bold-text {  
398 - font-weight: bold;  
399 - }  
400 -  
401 - .base-left-icon-color {  
402 - border-radius: 50%;  
403 - width: 0.75rem;  
404 - height: 0.75rem;  
405 - display: block;  
406 - position: relative;  
407 - right: 0.5rem;  
408 - }  
409 -  
410 - .left-icon-d-color :extend(.base-left-icon-color) {  
411 - background-color: #5c7bd9 !important;  
412 - }  
413 - .left-icon-g-color :extend(.base-left-icon-color) {  
414 - background-color: #91cc75 !important;  
415 - }  
416 - .left-icon-s-color :extend(.base-left-icon-color) {  
417 - background-color: #fac859 !important;  
418 - }  
419 - .right-icon-d-color :extend(.base-left-icon-color) {  
420 - background-color: #5c7bd9;  
421 - }  
422 - .right-icon-g-color :extend(.base-left-icon-color) {  
423 - background-color: #91cc75;  
424 - }  
425 - .right-icon-s-color :extend(.base-left-icon-color) {  
426 - background-color: #ec4040;  
427 - }  
428 -</style> 1 +<template>
  2 + <div>
  3 + <!-- 首页基础信息 -->
  4 + <section class="flex gap-4">
  5 + <StatisticalCard
  6 + :style="{ width: `${100 / statisticalPanelList.length}%` }"
  7 + v-for="(item, index) in statisticalPanelList"
  8 + :key="index"
  9 + :value="item"
  10 + />
  11 + </section>
  12 + <!-- 首页饼图 -->
  13 + <div class="md:flex mt-4" v-if="!isAdmin(role)">
  14 + <Card
  15 + size="small"
  16 + class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4"
  17 + style="color: #666; width: 50%"
  18 + title="设备数量统计"
  19 + >
  20 + <a-row type="flex" justify="space-between" align="middle">
  21 + <a-col :span="12">
  22 + <PieChartDeviceSub
  23 + v-if="seriesData.length > 0"
  24 + :legendData="legendData"
  25 + :seriesData="seriesData"
  26 + :isCircle="false"
  27 + /></a-col>
  28 + <a-col :span="12">
  29 + <a-row type="flex" justify="space-between" align="middle" style="row-gap: 30px">
  30 + <a-col :offset="8" class="flex items-center">
  31 + <span class="left-icon-d-color"></span>
  32 + 直连设备:
  33 + <span class="bold-text">{{ growCardList?.deviceInfo?.directConnection ?? 0 }}</span
  34 + >个</a-col
  35 + >
  36 + <a-col :offset="8" class="flex items-center">
  37 + <span class="left-icon-g-color"></span>
  38 + 网关设备:
  39 + <span class="bold-text">{{ growCardList?.deviceInfo?.gateWay ?? 0 }}</span
  40 + >个</a-col
  41 + >
  42 + <a-col :offset="8" class="flex items-center">
  43 + <span class="left-icon-s-color"></span>
  44 + 网关子设备:<span class="bold-text">{{
  45 + growCardList?.deviceInfo?.sensor ?? 0
  46 + }}</span
  47 + >个</a-col
  48 + >
  49 + </a-row>
  50 + </a-col>
  51 + </a-row>
  52 + </Card>
  53 + <Card
  54 + size="small"
  55 + class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:ml-1"
  56 + style="color: #666; width: 50%"
  57 + title="设备状态统计"
  58 + >
  59 + <a-row type="flex" justify="space-between" align="middle">
  60 + <a-col :span="12">
  61 + <PieChartDeviceStatus
  62 + v-if="seriesStatusData.length > 0"
  63 + :seriesStatusData="seriesStatusData"
  64 + />
  65 + <div class="empty-box" v-else><Empty :image="Empty.PRESENTED_IMAGE_SIMPLE" /></div>
  66 + </a-col>
  67 + <a-col :span="12">
  68 + <a-row type="flex" justify="space-between" align="middle" style="row-gap: 30px">
  69 + <a-col :offset="8" class="flex items-center">
  70 + <span class="right-icon-d-color"></span>
  71 + 待激活设备:
  72 + <span class="bold-text">{{ growCardList?.deviceInfo?.inActive ?? 0 }}</span
  73 + >个</a-col
  74 + >
  75 + <a-col :offset="8" class="flex items-center">
  76 + <span class="right-icon-g-color"></span>
  77 + 在线设备:<span class="bold-text">{{ growCardList?.deviceInfo?.onLine ?? 0 }}</span
  78 + >个</a-col
  79 + >
  80 + <a-col :offset="8" class="flex items-center">
  81 + <span class="right-icon-s-color"></span>
  82 + 离线设备:<span class="bold-text">{{ growCardList?.deviceInfo?.offLine ?? 0 }}</span
  83 + >个</a-col
  84 + >
  85 + </a-row>
  86 + </a-col>
  87 + </a-row>
  88 + </Card>
  89 + </div>
  90 + </div>
  91 +</template>
  92 +<script lang="ts" setup>
  93 + import { ref, onMounted, defineComponent, Ref } from 'vue';
  94 + import { Card } from 'ant-design-vue';
  95 + import { getHomeData } from '/@/api/dashboard';
  96 + import { isAdmin } from '/@/enums/roleEnum';
  97 + import { toThousands } from '/@/utils/fnUtils';
  98 + import { CardList, seriesDataT } from './props';
  99 + import PieChartDeviceSub from './PieChartDeviceSub.vue';
  100 + import PieChartDeviceStatus from './PieChartDeviceStatus.vue';
  101 + import { Empty } from 'ant-design-vue';
  102 + import StatisticalCard from './StatisticalCard.vue';
  103 + import { HomeStatisticsRecordType } from '/@/api/dashboard/model';
  104 + import { useRole } from '/@/hooks/business/useRole';
  105 + import { unref } from 'vue';
  106 +
  107 + interface RecordType {
  108 + value: number;
  109 + label: string;
  110 + }
  111 +
  112 + interface StatisticalItemType {
  113 + images: string;
  114 + totals: RecordType[];
  115 + tooltips: RecordType[];
  116 + todayTotals: RecordType[];
  117 + }
  118 +
  119 + defineProps<{
  120 + role: string;
  121 + }>();
  122 +
  123 + defineExpose({
  124 + isAdmin,
  125 + toThousands,
  126 + });
  127 +
  128 + defineComponent({
  129 + Card,
  130 + });
  131 +
  132 + const legendData = ref(['网关设备', '直连设备', '网关子设备']);
  133 +
  134 + const seriesData: Ref<seriesDataT[]> = ref([]);
  135 +
  136 + const seriesStatusData: Ref<seriesDataT[]> = ref([]);
  137 +
  138 + const growCardList = ref<CardList>();
  139 +
  140 + const statisticalPanelList = ref<StatisticalItemType[]>([]);
  141 +
  142 + const devicePieColor = [
  143 + { key: 'directConnection', itemStyle: { color: '#5C7BD9' }, value: '直连设备' },
  144 + { key: 'gateWay', itemStyle: { color: '#91CC75' }, value: '网关设备' },
  145 + { key: 'sensor', itemStyle: { color: '#FAC859' }, value: '网关子设备' },
  146 + { key: 'inActive', itemStyle: { color: '#5C7BD9' }, value: '待激活' },
  147 + { key: 'onLine', itemStyle: { color: '#91CC75 ' }, value: '在线' },
  148 + { key: 'offLine', itemStyle: { color: '#EC4040' }, value: '离线' },
  149 + ];
  150 +
  151 + const { isSysadmin, isPlatformAdmin } = useRole();
  152 + const handleTransformStatisticalInfo = (record: HomeStatisticsRecordType) => {
  153 + const { deviceInfo, productInfo, alarmInfo, messageInfo, customerInfo, tenantInfo } = record;
  154 +
  155 + const productTotal: StatisticalItemType = {
  156 + images: '/src/assets/images/product.png',
  157 + totals: [{ label: '产品数', value: productInfo?.sumCount }],
  158 + tooltips: [
  159 + { label: '产品数', value: productInfo?.sumCount },
  160 + { label: '今日新增', value: productInfo?.todayAdd },
  161 + ],
  162 + todayTotals: [{ label: '今日新增', value: productInfo?.todayAdd }],
  163 + };
  164 +
  165 + const deviceTotal: StatisticalItemType = {
  166 + images: '/src/assets/images/device-count.png',
  167 + totals: [{ label: '设备数', value: deviceInfo?.sumCount }],
  168 + tooltips: [
  169 + { label: '设备数', value: deviceInfo?.sumCount },
  170 + { label: '今日新增', value: deviceInfo?.todayAdd },
  171 + ],
  172 + todayTotals: [{ label: '今日新增', value: deviceInfo?.todayAdd }],
  173 + };
  174 +
  175 + const alarmTotal: StatisticalItemType = {
  176 + images: '/src/assets/images/alarm-count.png',
  177 + totals: [{ label: '告警数', value: alarmInfo?.sumCount }],
  178 + tooltips: [
  179 + { label: '告警数', value: alarmInfo?.sumCount },
  180 + { label: '今日新增', value: alarmInfo?.todayAdd },
  181 + ],
  182 + todayTotals: [{ label: '今日新增', value: alarmInfo?.todayAdd }],
  183 + };
  184 +
  185 + const messageTotal: StatisticalItemType = {
  186 + images: '/src/assets/images/msg-count.png',
  187 + totals: [
  188 + { label: '消息数', value: messageInfo?.messageCount },
  189 + { label: '消息点数', value: messageInfo?.dataPointsCount },
  190 + ],
  191 + tooltips: [
  192 + { label: '今日消息数', value: messageInfo?.todayMessageAdd },
  193 + { label: '今日消息点数', value: messageInfo?.todayDataPointsAdd },
  194 + ],
  195 + todayTotals: [
  196 + { label: '今日消息数', value: messageInfo?.todayMessageAdd },
  197 + { label: '今日消息点数', value: messageInfo?.todayDataPointsAdd },
  198 + ],
  199 + };
  200 +
  201 + const tenantTotal: StatisticalItemType = {
  202 + images: '/src/assets/images/zh.png',
  203 + totals: [{ label: '租户总量', value: tenantInfo?.sumCount }],
  204 + tooltips: [
  205 + { label: '租户总量', value: tenantInfo?.sumCount },
  206 + { label: '今日新增', value: tenantInfo?.todayAdd },
  207 + ],
  208 + todayTotals: [{ label: '今日新增', value: tenantInfo?.todayAdd }],
  209 + };
  210 +
  211 + const customerTotal: StatisticalItemType = {
  212 + images: '/src/assets/images/kf.png',
  213 + totals: [{ label: '客户总量', value: customerInfo?.sumCount }],
  214 + tooltips: [
  215 + { label: '客户总量', value: customerInfo?.sumCount },
  216 + { label: '今日新增', value: customerInfo?.todayAdd },
  217 + ],
  218 + todayTotals: [{ label: '今日新增', value: customerInfo?.todayAdd }],
  219 + };
  220 +
  221 + if (unref(isSysadmin) || unref(isPlatformAdmin)) {
  222 + statisticalPanelList.value = [deviceTotal, tenantTotal, customerTotal];
  223 + } else {
  224 + statisticalPanelList.value = [productTotal, deviceTotal, alarmTotal, messageTotal];
  225 + }
  226 + };
  227 +
  228 + onMounted(async () => {
  229 + const res = await getHomeData();
  230 + growCardList.value = res;
  231 + handleTransformStatisticalInfo(res);
  232 + const { deviceInfo } = growCardList.value!;
  233 + let data = Object.entries(deviceInfo).map(([key, value]) => {
  234 + const name = devicePieColor?.find((f) => f.key === key)?.value;
  235 + const itemStyle = devicePieColor?.find((f) => f.key === key)?.itemStyle;
  236 + return { key, value, itemStyle, name };
  237 + });
  238 + seriesData.value = data.filter(
  239 + (f) => f.key === 'directConnection' || f.key === 'gateWay' || f.key === 'sensor'
  240 + );
  241 + seriesStatusData.value = data.filter(
  242 + (f) => f.key === 'inActive' || f.key === 'onLine' || f.key === 'offLine'
  243 + );
  244 + });
  245 +</script>
  246 +<style lang="less">
  247 + .text {
  248 + color: #333;
  249 + display: flex;
  250 + flex-wrap: nowrap;
  251 + }
  252 +
  253 + .bold-text {
  254 + font-weight: bold;
  255 + }
  256 +
  257 + .base-left-icon-color {
  258 + border-radius: 50%;
  259 + width: 0.75rem;
  260 + height: 0.75rem;
  261 + display: block;
  262 + position: relative;
  263 + right: 0.5rem;
  264 + }
  265 +
  266 + .left-icon-d-color :extend(.base-left-icon-color) {
  267 + background-color: #5c7bd9 !important;
  268 + }
  269 + .left-icon-g-color :extend(.base-left-icon-color) {
  270 + background-color: #91cc75 !important;
  271 + }
  272 + .left-icon-s-color :extend(.base-left-icon-color) {
  273 + background-color: #fac859 !important;
  274 + }
  275 + .right-icon-d-color :extend(.base-left-icon-color) {
  276 + background-color: #5c7bd9;
  277 + }
  278 + .right-icon-g-color :extend(.base-left-icon-color) {
  279 + background-color: #91cc75;
  280 + }
  281 + .right-icon-s-color :extend(.base-left-icon-color) {
  282 + background-color: #ec4040;
  283 + }
  284 +</style>