Commit 1612a2ca1037943cfe1871f0a24309bef3ad2dd9

Authored by fengtao
1 parent 747c2cf7

feat:首页新增饼状图和调整部分样式

1 <template> 1 <template>
  2 + <!-- 首页基础信息 -->
2 <div class="md:flex"> 3 <div class="md:flex">
3 <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4" style="color: #666"> 4 <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4" style="color: #666">
4 <div class="flex" style="height: 100px"> 5 <div class="flex" style="height: 100px">
@@ -131,8 +132,12 @@ @@ -131,8 +132,12 @@
131 今日新增 {{ toThousands(growCardList?.customerInfo?.todayAdd) }}</div 132 今日新增 {{ toThousands(growCardList?.customerInfo?.todayAdd) }}</div
132 > 133 >
133 </Card> 134 </Card>
134 -  
135 - <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:ml-4" style="color: #666"> 135 + <Card
  136 + v-if="!isAdmin(role)"
  137 + size="small"
  138 + class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:ml-4"
  139 + style="color: #666"
  140 + >
136 <div class="flex" style="height: 100px"> 141 <div class="flex" style="height: 100px">
137 <div class="mr-4"> 142 <div class="mr-4">
138 <img 143 <img
@@ -188,50 +193,143 @@ @@ -188,50 +193,143 @@
188 > 193 >
189 </Card> 194 </Card>
190 </div> 195 </div>
  196 + <!-- 首页饼图 -->
  197 + <div class="md:flex mt-4" v-if="!isAdmin(role)">
  198 + <Card
  199 + size="small"
  200 + class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4"
  201 + style="color: #666; width: 50%"
  202 + >
  203 + <div class="flex container">
  204 + <div class="mr-4 flex chart-top">
  205 + <PieChartDeviceSub :legendData="legendData" :seriesData="seriesData" :isCircle="true" />
  206 + </div>
  207 + <div class="ml-20 flex justify-around right-text">
  208 + <div class="text">
  209 + 直连设备:{{ growCardList?.deviceInfo?.directConnection ?? 0 }}个
  210 + </div>
  211 + <div class="text"> 网关设备:{{ growCardList?.deviceInfo?.gateWay ?? 0 }}个 </div>
  212 + <div class="text"> 网关子设备:{{ growCardList?.deviceInfo?.sensor ?? 0 }}个 </div>
  213 + </div>
  214 + </div>
  215 + </Card>
  216 + <Card
  217 + size="small"
  218 + class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:ml-1"
  219 + style="color: #666; width: 50%"
  220 + >
  221 + <div class="flex container">
  222 + <div class="mr-4 flex chart-top">
  223 + <PieChartDeviceSub
  224 + :legendData="legendStatusData"
  225 + :seriesData="seriesStatusData"
  226 + :isCircle="false"
  227 + />
  228 + </div>
  229 + <div class="ml-20 flex justify-around right-text">
  230 + <div class="text"> 待激活设备:{{ growCardList?.deviceInfo?.inActive ?? 0 }}个 </div>
  231 + <div class="text"> 在线设备:{{ growCardList?.deviceInfo?.onLine ?? 0 }}个 </div>
  232 + <div class="text"> 离线设备:{{ growCardList?.deviceInfo?.offLine ?? 0 }}个 </div>
  233 + </div>
  234 + </div>
  235 + </Card>
  236 + </div>
191 </template> 237 </template>
192 <script lang="ts" setup> 238 <script lang="ts" setup>
193 - import { ref, onMounted, defineComponent } from 'vue'; 239 + import { ref, onMounted, defineComponent, Ref } from 'vue';
194 import { Card } from 'ant-design-vue'; 240 import { Card } from 'ant-design-vue';
195 import { getHomeData } from '/@/api/dashboard'; 241 import { getHomeData } from '/@/api/dashboard';
196 import { isAdmin } from '/@/enums/roleEnum'; 242 import { isAdmin } from '/@/enums/roleEnum';
197 import { toThousands } from '/@/utils/fnUtils'; 243 import { toThousands } from '/@/utils/fnUtils';
198 import { CountTo } from '/@/components/CountTo/index'; 244 import { CountTo } from '/@/components/CountTo/index';
199 import { Tooltip } from 'ant-design-vue'; 245 import { Tooltip } from 'ant-design-vue';
  246 + import { CardList, seriesDataT } from './props';
  247 + import PieChartDeviceSub from './PieChartDeviceSub.vue';
200 248
201 defineProps<{ 249 defineProps<{
202 role: string; 250 role: string;
203 }>(); 251 }>();
  252 +
204 defineExpose({ 253 defineExpose({
205 isAdmin, 254 isAdmin,
206 toThousands, 255 toThousands,
207 }); 256 });
  257 +
208 defineComponent({ 258 defineComponent({
209 Card, 259 Card,
210 }); 260 });
211 - interface CardList {  
212 - deviceInfo: {  
213 - sumCount: number;  
214 - onLine: number;  
215 - offLine: number;  
216 - inActive: number;  
217 - todayAdd: number;  
218 - };  
219 - tenantInfo?: { sumCount: number; todayAdd: number };  
220 - customerInfo?: { sumCount: number; todayAdd: number };  
221 - alarmInfo?: {  
222 - sumCount: number;  
223 - todayAdd: number;  
224 - };  
225 - messageInfo?: {  
226 - dataPointsCount: number;  
227 - messageCount: number;  
228 - todayDataPointsAdd: number;  
229 - todayMessageAdd: number;  
230 - };  
231 - } 261 +
  262 + const legendData = ref(['网关设备', '直连设备', '网关子设备']);
  263 +
  264 + const seriesData: Ref<seriesDataT[]> = ref([]);
  265 +
  266 + const legendStatusData = ref(['待激活', '在线', '离线']);
  267 +
  268 + const seriesStatusData: Ref<seriesDataT[]> = ref([]);
  269 +
232 const growCardList = ref<CardList>(); 270 const growCardList = ref<CardList>();
  271 +
233 onMounted(async () => { 272 onMounted(async () => {
234 const res = await getHomeData(); 273 const res = await getHomeData();
235 growCardList.value = res; 274 growCardList.value = res;
  275 + const devObj = growCardList.value?.deviceInfo;
  276 + for (let o in devObj) {
  277 + if (o === 'directConnection' || o === 'gateWay' || o === 'sensor') {
  278 + seriesData.value.push({
  279 + value:
  280 + o === 'directConnection'
  281 + ? devObj?.directConnection
  282 + : o === 'gateWay'
  283 + ? devObj?.gateWay
  284 + : devObj?.sensor,
  285 + name: o === 'directConnection' ? '直连设备' : o === 'gateWay' ? '网关设备' : '网关子设备',
  286 + itemStyle:
  287 + o === 'directConnection'
  288 + ? { color: '#5AEEED' }
  289 + : o === 'gateWay'
  290 + ? { color: '#0B55F1' }
  291 + : { color: '#00C678' },
  292 + });
  293 + }
  294 + if (o === 'inActive' || o === 'onLine' || o === 'offLine') {
  295 + seriesStatusData.value.push({
  296 + value:
  297 + o === 'inActive' ? devObj?.inActive : o === 'onLine' ? devObj?.onLine : devObj?.offLine,
  298 + name: o === 'inActive' ? '待激活' : o === 'onLine' ? '在线' : '离线',
  299 + itemStyle:
  300 + o === 'inActive'
  301 + ? { color: '#F9C900' }
  302 + : o === 'onLine'
  303 + ? { color: '#5AEEED' }
  304 + : { color: '#FF9C4A' },
  305 + });
  306 + }
  307 + }
236 }); 308 });
237 </script> 309 </script>
  310 +<style lang="css">
  311 + .right-text {
  312 + width: 40%;
  313 + flex-direction: column;
  314 + height: 240px;
  315 + margin: 10px 0 10px 50px;
  316 + }
  317 +
  318 + .text {
  319 + color: #333;
  320 + font-weight: bold;
  321 + display: flex;
  322 + flex-wrap: nowrap;
  323 + }
  324 +
  325 + .chart-top {
  326 + width: 60%;
  327 + height: 300px;
  328 + align-items: center;
  329 + margin-top: -30px;
  330 + }
  331 +
  332 + .container {
  333 + width: 100%;
  334 + }
  335 +</style>
1 -<template>  
2 - <div class="md:flex mt-4">  
3 - <Card  
4 - size="small"  
5 - class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4"  
6 - style="color: #666; width: 50%"  
7 - >  
8 - <div class="flex container">  
9 - <div class="mr-4 flex chart-top">  
10 - <PieChartDeviceSub  
11 - :legendData="legendData"  
12 - :seriesData="seriesData"  
13 - :radisData="radisData"  
14 - />  
15 - </div>  
16 - <div class="ml-20 flex justify-around right-text">  
17 - <div class="text"> 直连设备:4个 </div>  
18 - <div class="text"> 网关设备:1个 </div>  
19 - <div class="text"> 网关子设备:6个 </div>  
20 - </div>  
21 - </div>  
22 - </Card>  
23 - <Card  
24 - size="small"  
25 - class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:ml-1"  
26 - style="color: #666; width: 50%"  
27 - >  
28 - <div class="flex container">  
29 - <div class="mr-4 flex chart-top">  
30 - <PieChartDeviceSub  
31 - :legendData="legendStatusData"  
32 - :seriesData="seriesStatusData"  
33 - :radisData="radisStatusData"  
34 - />  
35 - </div>  
36 - <div class="ml-20 flex justify-around right-text">  
37 - <div class="text"> 待激活设备:2个 </div>  
38 - <div class="text"> 在线设备:1个 </div>  
39 - <div class="text"> 离线设备:4个 </div>  
40 - </div>  
41 - </div>  
42 - </Card>  
43 - </div>  
44 -</template>  
45 -<script lang="ts" setup>  
46 - import { ref, onMounted, defineComponent, Ref } from 'vue';  
47 - import { Card } from 'ant-design-vue';  
48 - import { getHomeData } from '/@/api/dashboard';  
49 - import { isAdmin } from '/@/enums/roleEnum';  
50 - import { toThousands } from '/@/utils/fnUtils';  
51 - import PieChartDeviceSub from './PieChartDeviceSub.vue';  
52 -  
53 - defineProps<{  
54 - role: string;  
55 - }>();  
56 - defineExpose({  
57 - isAdmin,  
58 - toThousands,  
59 - });  
60 - defineComponent({  
61 - Card,  
62 - });  
63 - interface CardList {  
64 - deviceInfo: {  
65 - sumCount: number;  
66 - onLine: number;  
67 - offLine: number;  
68 - inActive: number;  
69 - todayAdd: number;  
70 - };  
71 - tenantInfo?: { sumCount: number; todayAdd: number };  
72 - customerInfo?: { sumCount: number; todayAdd: number };  
73 - alarmInfo?: {  
74 - sumCount: number;  
75 - todayAdd: number;  
76 - };  
77 - messageInfo?: {  
78 - dataPointsCount: number;  
79 - messageCount: number;  
80 - todayDataPointsAdd: number;  
81 - todayMessageAdd: number;  
82 - };  
83 - }  
84 - type seriesDataT = {  
85 - value: number;  
86 - name: string;  
87 - itemStyle: object;  
88 - };  
89 - const radisData: any = ref('70%');  
90 - const radisStatusData = ref<string[]>(['40%', '70%']);  
91 - const growCardList = ref<CardList>();  
92 - const legendData = ref(['gateway', 'directly', 'sub-device']);  
93 - const seriesData: Ref<seriesDataT[]> = ref([  
94 - { value: 1048, name: 'gateway', itemStyle: { color: '#3079FF' } },  
95 - { value: 735, name: 'directly', itemStyle: { color: '#36cbcb' } },  
96 - { value: 580, name: 'sub-device', itemStyle: { color: '#4ecb73' } },  
97 - ]);  
98 - const legendStatusData = ref(['inactive', 'online', 'offline']);  
99 - const seriesStatusData: Ref<seriesDataT[]> = ref([  
100 - { value: 1048, name: 'inactive', itemStyle: { color: '#3079FF' } },  
101 - { value: 735, name: 'online', itemStyle: { color: '#36cbcb' } },  
102 - { value: 580, name: 'offline', itemStyle: { color: '#4ecb73' } },  
103 - ]);  
104 - onMounted(async () => {  
105 - const res = await getHomeData();  
106 - growCardList.value = res;  
107 - });  
108 -</script>  
109 -  
110 -<style lang="css">  
111 - .right-text {  
112 - width: 40%;  
113 - flex-direction: column;  
114 - height: 240px;  
115 - margin: 10px 0 10px 50px;  
116 - }  
117 -  
118 - .text {  
119 - color: #333;  
120 - font-weight: bold;  
121 - display: flex;  
122 - flex-wrap: nowrap;  
123 - }  
124 -  
125 - .chart-top {  
126 - width: 60%;  
127 - height: 300px;  
128 - align-items: center;  
129 - margin-top: -30px;  
130 - }  
131 -  
132 - .container {  
133 - width: 100%;  
134 - }  
135 -</style>  
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 import { defineComponent, PropType, ref, Ref, onMounted, toRefs } from 'vue'; 8 import { defineComponent, PropType, ref, Ref, onMounted, toRefs } from 'vue';
9 import { useECharts } from '/@/hooks/web/useECharts'; 9 import { useECharts } from '/@/hooks/web/useECharts';
10 import { Empty } from 'ant-design-vue'; 10 import { Empty } from 'ant-design-vue';
  11 + import { seriesDataT } from './props';
11 12
12 export default defineComponent({ 13 export default defineComponent({
13 components: { Empty }, 14 components: { Empty },
@@ -28,19 +29,17 @@ @@ -28,19 +29,17 @@
28 type: Array, 29 type: Array,
29 default: () => [], 30 default: () => [],
30 }, 31 },
31 - radisData: {  
32 - type: Array || String,  
33 - default: () => ['40%', '70%'] || '70%', 32 + isCircle: {
  33 + type: Boolean,
  34 + default: true,
34 }, 35 },
35 }, 36 },
36 setup(props) { 37 setup(props) {
37 - const { legendData, seriesData, radisData } = toRefs(props);  
38 - const dataSeries = ref<any>([]);  
39 - const legendDatas = ref<any>([]);  
40 - const radisDatas = ref<any>([]);  
41 - dataSeries.value = seriesData.value;  
42 - legendDatas.value = legendData.value;  
43 - radisDatas.value = radisData.value; 38 + const { legendData, seriesData } = toRefs(props);
  39 + const dataSeries: Ref<seriesDataT[]> = ref([]);
  40 + const legendDatas: Ref<seriesDataT[]> = ref([]);
  41 + dataSeries.value = seriesData.value as unknown as seriesDataT[];
  42 + legendDatas.value = legendData.value as unknown as seriesDataT[];
44 43
45 const chartRef = ref<HTMLDivElement | null>(null); 44 const chartRef = ref<HTMLDivElement | null>(null);
46 const { setOptions, resize } = useECharts(chartRef as Ref<HTMLDivElement>); 45 const { setOptions, resize } = useECharts(chartRef as Ref<HTMLDivElement>);
@@ -60,8 +59,9 @@ @@ -60,8 +59,9 @@
60 }, 59 },
61 series: [ 60 series: [
62 { 61 {
  62 + avoidLabelOverlap: false,
63 type: 'pie', 63 type: 'pie',
64 - radius: radisDatas.value, 64 + radius: props.isCircle ? '60%' : ['40%', '60%'],
65 data: dataSeries.value, 65 data: dataSeries.value,
66 emphasis: { 66 emphasis: {
67 itemStyle: { 67 itemStyle: {
@@ -70,6 +70,12 @@ @@ -70,6 +70,12 @@
70 shadowColor: 'rgba(0, 0, 0, 0.5)', 70 shadowColor: 'rgba(0, 0, 0, 0.5)',
71 }, 71 },
72 }, 72 },
  73 + labelLine: {
  74 + normal: {
  75 + show: true,
  76 + length2: 1,
  77 + },
  78 + },
73 }, 79 },
74 ], 80 ],
75 }); 81 });
@@ -243,7 +243,6 @@ @@ -243,7 +243,6 @@
243 } 243 }
244 } else { 244 } else {
245 if (data) { 245 if (data) {
246 - console.log('消息数', data);  
247 if (data) { 246 if (data) {
248 const { transportDataPointsCountHourly, transportMsgCountHourly } = 247 const { transportDataPointsCountHourly, transportMsgCountHourly } =
249 data.data[0].latest.TIME_SERIES; 248 data.data[0].latest.TIME_SERIES;
@@ -259,9 +258,7 @@ @@ -259,9 +258,7 @@
259 transportDataPointsCountHourly?.ts, 258 transportDataPointsCountHourly?.ts,
260 transportDataPointsCountHourly?.value, 259 transportDataPointsCountHourly?.value,
261 ]); 260 ]);
262 - console.log('state.dataPointList', state.dataPointList);  
263 state.messageList.push([transportMsgCountHourly?.ts, transportMsgCountHourly?.value]); 261 state.messageList.push([transportMsgCountHourly?.ts, transportMsgCountHourly?.value]);
264 - console.log('state.messageList', state.messageList);  
265 } 262 }
266 } 263 }
267 if (update) { 264 if (update) {
@@ -276,8 +273,6 @@ @@ -276,8 +273,6 @@
276 } 273 }
277 state.dataPointList = newArray; 274 state.dataPointList = newArray;
278 state.messageList = newArray1; 275 state.messageList = newArray1;
279 - console.log('newArray', state.dataPointList);  
280 - console.log('newArray1', state.messageList);  
281 } 276 }
282 } 277 }
283 }, 278 },
@@ -13,3 +13,33 @@ export const basicProps = { @@ -13,3 +13,33 @@ export const basicProps = {
13 default: '280px', 13 default: '280px',
14 }, 14 },
15 }; 15 };
  16 +
  17 +export interface CardList {
  18 + deviceInfo: {
  19 + sumCount: number;
  20 + onLine: number;
  21 + offLine: number;
  22 + inActive: number;
  23 + todayAdd: number;
  24 + directConnection: number;
  25 + gateWay: number;
  26 + sensor: number;
  27 + };
  28 + tenantInfo?: { sumCount: number; todayAdd: number };
  29 + customerInfo?: { sumCount: number; todayAdd: number };
  30 + alarmInfo?: {
  31 + sumCount: number;
  32 + todayAdd: number;
  33 + };
  34 + messageInfo?: {
  35 + dataPointsCount: number;
  36 + messageCount: number;
  37 + todayDataPointsAdd: number;
  38 + todayMessageAdd: number;
  39 + };
  40 +}
  41 +export type seriesDataT = {
  42 + value: number | undefined;
  43 + name: string;
  44 + itemStyle: object;
  45 +};
@@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@
2 <div class="p-4 md:flex"> 2 <div class="p-4 md:flex">
3 <div class="md:w-7/10 w-full !mr-4 enter-y"> 3 <div class="md:w-7/10 w-full !mr-4 enter-y">
4 <GrowCard :loading="loading" class="enter-y" :role="role" /> 4 <GrowCard :loading="loading" class="enter-y" :role="role" />
5 - <PieChartDevice :loading="loading" class="enter-y" :role="role" />  
6 <SiteAnalysisMessage class="!my-4 enter-y" :loading="loading" :role="role" /> 5 <SiteAnalysisMessage class="!my-4 enter-y" :loading="loading" :role="role" />
7 <SiteAnalysis class="!my-4 enter-y" :loading="loading" :role="role" /> 6 <SiteAnalysis class="!my-4 enter-y" :loading="loading" :role="role" />
8 <div class="md:flex enter-y" v-if="!isAdmin(role)"> 7 <div class="md:flex enter-y" v-if="!isAdmin(role)">
@@ -31,15 +30,17 @@ @@ -31,15 +30,17 @@
31 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 30 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
32 import { getAuthCache } from '/@/utils/auth'; 31 import { getAuthCache } from '/@/utils/auth';
33 import { isAdmin } from '/@/enums/roleEnum'; 32 import { isAdmin } from '/@/enums/roleEnum';
34 - import PieChartDevice from './components/PieChartDevice.vue';  
35 33
36 defineExpose({ 34 defineExpose({
37 isAdmin, 35 isAdmin,
38 }); 36 });
39 37
40 const userInfo: any = getAuthCache(USER_INFO_KEY); 38 const userInfo: any = getAuthCache(USER_INFO_KEY);
  39 +
41 const role: string = userInfo?.roles[0]; 40 const role: string = userInfo?.roles[0];
  41 +
42 const loading = ref(true); 42 const loading = ref(true);
  43 +
43 setTimeout(() => { 44 setTimeout(() => {
44 loading.value = false; 45 loading.value = false;
45 }, 1500); 46 }, 1500);