Commit ca0121082fb7ed4935ca61a269172f0c874599a2

Authored by fengtao
1 parent 6c0755f1

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

... ... @@ -131,6 +131,58 @@
131 131 今日新增 {{ toThousands(growCardList?.customerInfo?.todayAdd) }}</div
132 132 >
133 133 </Card>
  134 +
  135 + <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:ml-4" style="color: #666">
  136 + <div class="flex" style="height: 100px">
  137 + <div class="mr-4">
  138 + <img
  139 + v-if="!isAdmin(role)"
  140 + src="/src/assets/images/msg-count.png"
  141 + style="width: 5.625rem; height: 5.625rem"
  142 + />
  143 + <img v-else src="/src/assets/images/kf.png" style="width: 5.625rem; height: 5.625rem" />
  144 + </div>
  145 + <div class="flex-auto">
  146 + <div class="flex justify-between" style="align-items: center">
  147 + <div v-if="!isAdmin(role)" style="font-size: 1.625rem; color: #333; font-weight: bold">
  148 + <CountTo
  149 + v-if="growCardList?.messageInfo?.messageCount"
  150 + :end-val="growCardList.messageInfo.messageCount"
  151 + />
  152 + <CountTo v-else :end-val="0" />
  153 + </div>
  154 + <div style="font-size: 1.625rem; color: #333; font-weight: bold" v-else>
  155 + <CountTo
  156 + v-if="growCardList?.customerInfo?.sumCount"
  157 + :end-val="growCardList.customerInfo.sumCount"
  158 + />
  159 + <CountTo v-else :end-val="0" />
  160 + </div>
  161 + <Tooltip>
  162 + <template #title>
  163 + {{
  164 + !isAdmin(role)
  165 + ? `产品数:${growCardList?.messageInfo?.messageCount} 今日新增 ${toThousands(
  166 + growCardList?.messageInfo?.todayMessageAdd
  167 + )}`
  168 + : `产品数:${growCardList?.customerInfo?.sumCount} 今日新增 ${toThousands(
  169 + growCardList?.messageInfo?.todayMessageAdd
  170 + )}`
  171 + }}
  172 + </template>
  173 + <img src="/src/assets/images/tip.png" style="width: 1.125rem; height: 1.125rem" />
  174 + </Tooltip>
  175 + </div>
  176 + <div> {{ !isAdmin(role) ? `产品数` : '产品数' }}</div>
  177 + </div>
  178 + </div>
  179 + <div v-if="!isAdmin(role)" class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5">
  180 + 今日新增 {{ toThousands(growCardList?.messageInfo?.todayMessageAdd) }}</div
  181 + >
  182 + <div v-else class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5">
  183 + 今日新增 {{ toThousands(growCardList?.customerInfo?.todayAdd) }}</div
  184 + >
  185 + </Card>
134 186 </div>
135 187 </template>
136 188 <script lang="ts" setup>
... ...
  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">
  9 + <div class="mr-4 flex chart-top">
  10 + <PieChartDeviceSub :legendData="legendData" :seriesData="seriesData" />
  11 + </div>
  12 + <div class="ml-20 flex justify-around right-text">
  13 + <div class="text"> 直连设备:4个 </div>
  14 + <div class="text"> 网关设备:1个 </div>
  15 + <div class="text"> 网关子设备:6个 </div>
  16 + </div>
  17 + </div>
  18 + </Card>
  19 + <Card
  20 + size="small"
  21 + class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:ml-1"
  22 + style="color: #666; width: 50%"
  23 + >
  24 + <div class="flex">
  25 + <div class="mr-4 flex chart-top">
  26 + <PieChartDeviceSub :legendData="legendStatusData" :seriesData="seriesStatusData" />
  27 + </div>
  28 + <div class="ml-20 flex justify-around right-text">
  29 + <div class="text"> 待激活设备:2个 </div>
  30 + <div class="text"> 在线设备:1个 </div>
  31 + <div class="text"> 离线设备:4个 </div>
  32 + </div>
  33 + </div>
  34 + </Card>
  35 + </div>
  36 +</template>
  37 +<script lang="ts" setup>
  38 + import { ref, onMounted, defineComponent } from 'vue';
  39 + import { Card } from 'ant-design-vue';
  40 + import { getHomeData } from '/@/api/dashboard';
  41 + import { isAdmin } from '/@/enums/roleEnum';
  42 + import { toThousands } from '/@/utils/fnUtils';
  43 + import PieChartDeviceSub from './PieChartDeviceSub.vue';
  44 +
  45 + defineProps<{
  46 + role: string;
  47 + }>();
  48 + defineExpose({
  49 + isAdmin,
  50 + toThousands,
  51 + });
  52 + defineComponent({
  53 + Card,
  54 + });
  55 + interface CardList {
  56 + deviceInfo: {
  57 + sumCount: number;
  58 + onLine: number;
  59 + offLine: number;
  60 + inActive: number;
  61 + todayAdd: number;
  62 + };
  63 + tenantInfo?: { sumCount: number; todayAdd: number };
  64 + customerInfo?: { sumCount: number; todayAdd: number };
  65 + alarmInfo?: {
  66 + sumCount: number;
  67 + todayAdd: number;
  68 + };
  69 + messageInfo?: {
  70 + dataPointsCount: number;
  71 + messageCount: number;
  72 + todayDataPointsAdd: number;
  73 + todayMessageAdd: number;
  74 + };
  75 + }
  76 + const growCardList = ref<CardList>();
  77 + const legendData = ref<string[]>(['gateway', 'directly', 'sub-device']);
  78 + const seriesData = ref([
  79 + { value: 1048, name: 'gateway' },
  80 + { value: 735, name: 'directly' },
  81 + { value: 580, name: 'sub-device' },
  82 + ]);
  83 + const legendStatusData = ref<string[]>(['inactive', 'online', 'offline']);
  84 + const seriesStatusData = ref([
  85 + { value: 1048, name: 'inactive' },
  86 + { value: 735, name: 'online' },
  87 + { value: 580, name: 'offline' },
  88 + ]);
  89 + onMounted(async () => {
  90 + const res = await getHomeData();
  91 + growCardList.value = res;
  92 + });
  93 +</script>
  94 +
  95 +<style lang="css">
  96 + .right-text {
  97 + flex-direction: column;
  98 + height: 200px;
  99 + margin: 10px 0 10px 50px;
  100 + flex-wrap: nowrap;
  101 + }
  102 +
  103 + .text {
  104 + color: #333;
  105 + font-weight: bold;
  106 + }
  107 +
  108 + .chart-top {
  109 + align-items: center;
  110 + margin-top: -30px;
  111 + }
  112 +</style>
... ...
  1 +<template>
  2 + <div ref="chartRef" :style="{ height, width }"></div>
  3 +</template>
  4 +<script lang="ts">
  5 + import { defineComponent, PropType, ref, Ref, onMounted, toRefs } from 'vue';
  6 + import { useECharts } from '/@/hooks/web/useECharts';
  7 +
  8 + export default defineComponent({
  9 + props: {
  10 + width: {
  11 + type: String as PropType<string>,
  12 + default: '300px',
  13 + },
  14 + height: {
  15 + type: String as PropType<string>,
  16 + default: '200px',
  17 + },
  18 + legendData: {
  19 + type: Array,
  20 + default: () => [],
  21 + },
  22 + seriesData: {
  23 + type: Array,
  24 + default: () => [],
  25 + },
  26 + },
  27 + setup(props) {
  28 + const { legendData, seriesData } = toRefs(props);
  29 + const dataSeries = ref<any>([]);
  30 + const legendDatas = ref<any>([]);
  31 + dataSeries.value = seriesData;
  32 + legendDatas.value = legendData;
  33 + const chartRef = ref<HTMLDivElement | null>(null);
  34 + const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
  35 + onMounted(() => {
  36 + setOptions({
  37 + backgroundColor: '#ffffff',
  38 + tooltip: {
  39 + trigger: 'item',
  40 + },
  41 + legend: {
  42 + bottom: 10,
  43 + left: 'center',
  44 + data: legendDatas,
  45 + },
  46 + series: [
  47 + {
  48 + name: 'Access From',
  49 + type: 'pie',
  50 + radius: '50%',
  51 + data: dataSeries,
  52 + emphasis: {
  53 + itemStyle: {
  54 + shadowBlur: 10,
  55 + shadowOffsetX: 0,
  56 + shadowColor: 'rgba(0, 0, 0, 0.5)',
  57 + },
  58 + },
  59 + },
  60 + ],
  61 + });
  62 + });
  63 + return { chartRef };
  64 + },
  65 + });
  66 +</script>
... ...
... ... @@ -47,7 +47,7 @@
47 47 </div>
48 48 </Card>
49 49 <div v-if="isAdmin(role)">
50   - <Card
  50 + <!-- <Card
51 51 v-bind="$attrs"
52 52 title="租户趋势"
53 53 style="height: 26.75rem"
... ... @@ -70,7 +70,7 @@
70 70 </div>
71 71 </template>
72 72 <TenantTrend :tenantTrendList="tenantTrendList" />
73   - </Card>
  73 + </Card> -->
74 74 <Card
75 75 v-bind="$attrs"
76 76 title="客户趋势"
... ... @@ -109,7 +109,7 @@
109 109 import { formatToDateTime } from '/@/utils/dateUtil';
110 110 import { getEntitiesId } from '/@/api/dashboard/index';
111 111 import CustomerTrend from './CustomerTrend.vue';
112   - import TenantTrend from './TenantTrend.vue';
  112 + // import TenantTrend from './TenantTrend.vue';
113 113 import CustomerAlarmMessage from './CustomerAlarmMessage.vue';
114 114 import { useDate } from '../hooks/useDate';
115 115 import { getTrendData } from '/@/api/dashboard';
... ... @@ -129,10 +129,10 @@
129 129 key: '1',
130 130 tab: '告警数统计',
131 131 },
132   - {
133   - key: '2',
134   - tab: '消息量统计',
135   - },
  132 + // {
  133 + // key: '2',
  134 + // tab: '消息量统计',
  135 + // },
136 136 ];
137 137 // 快速选择日期
138 138 const activeIndex = ref(3);
... ... @@ -453,15 +453,15 @@
453 453 }
454 454 }
455 455 const {
456   - tenantDateValue,
  456 + // tenantDateValue,
457 457 customerDateValue,
458   - tenantTrendList,
  458 + // tenantTrendList,
459 459 customerTrendList,
460   - activeTenantIndex,
  460 + // activeTenantIndex,
461 461 activeCustomerIndex,
462 462 TenantOrCustomerDateList,
463 463 quickQueryTenantOrCustomerTime,
464   - onDateTenantChange,
  464 + // onDateTenantChange,
465 465 onDateCustomerChange,
466 466 } = useDate();
467 467 </script>
... ...
  1 +<template>
  2 + <Card
  3 + :tab-list="tabListTitle"
  4 + v-bind="$attrs"
  5 + :active-tab-key="activeKey"
  6 + @tabChange="onTabChange"
  7 + v-if="!isAdmin(role)"
  8 + >
  9 + <template #tabBarExtraContent>
  10 + <div class="extra-date">
  11 + <template v-for="(item, index) in dateList" :key="item.value">
  12 + <span
  13 + @click="quickQueryDate(index, item.value, role === 'CUSTOMER_USER' && 'customer')"
  14 + :class="{ active: index === activeIndex }"
  15 + >{{ item.label }}</span
  16 + >
  17 + </template>
  18 + <DatePicker
  19 + @change="
  20 + (_, DateString) => onDateChange(_, DateString, role === 'CUSTOMER_USER' && 'customer')
  21 + "
  22 + v-model:value="dateValue"
  23 + />
  24 + </div>
  25 + </template>
  26 + <div v-if="activeKey === '1'">
  27 + <!-- 折线图 -->
  28 + <CustomerAlarmMessage
  29 + v-if="role === 'CUSTOMER_USER'"
  30 + type="CUSTOMER_ALARM_STATISTICAL"
  31 + :customerList="customerAlarmList"
  32 + />
  33 + <VisitAnalysis v-else :alarmList="state.alarmList" />
  34 + </div>
  35 + <div v-if="activeKey === '2'">
  36 + <!-- 柱形图 -->
  37 + <CustomerAlarmMessage
  38 + v-if="role === 'CUSTOMER_USER'"
  39 + type="CUSTOMER_MESSAGE_STATISTICAL"
  40 + :customerList="customerMessageList"
  41 + />
  42 + <VisitAnalysisBar
  43 + v-else
  44 + :dataPointList="state.dataPointList"
  45 + :messageList="state.messageList"
  46 + />
  47 + </div>
  48 + </Card>
  49 + <div v-if="isAdmin(role)">
  50 + <Card
  51 + v-bind="$attrs"
  52 + title="租户趋势"
  53 + style="height: 26.75rem"
  54 + :bodyStyle="{ padding: '0 24px' }"
  55 + >
  56 + <template #extra>
  57 + <div class="extra-date">
  58 + <template v-for="(item, index) in TenantOrCustomerDateList" :key="item.value">
  59 + <span
  60 + @click="quickQueryTenantOrCustomerTime(index, item.value, 'tenant')"
  61 + :class="{ active: index === activeTenantIndex }"
  62 + >{{ item.label }}</span
  63 + >
  64 + </template>
  65 + <DatePicker.RangePicker
  66 + @change="onDateTenantChange"
  67 + size="small"
  68 + v-model:value="tenantDateValue"
  69 + />
  70 + </div>
  71 + </template>
  72 + <TenantTrend :tenantTrendList="tenantTrendList" />
  73 + </Card>
  74 + <!-- <Card
  75 + v-bind="$attrs"
  76 + title="客户趋势"
  77 + style="height: 26.75rem"
  78 + :bodyStyle="{ padding: '0 24px' }"
  79 + >
  80 + <template #extra>
  81 + <div class="extra-date">
  82 + <template v-for="(item, index) in TenantOrCustomerDateList" :key="item.value">
  83 + <span
  84 + @click="quickQueryTenantOrCustomerTime(index, item.value)"
  85 + :class="{ active: index === activeCustomerIndex }"
  86 + >{{ item.label }}</span
  87 + >
  88 + </template>
  89 + <DatePicker.RangePicker
  90 + @change="onDateCustomerChange"
  91 + size="small"
  92 + v-model:value="customerDateValue"
  93 + />
  94 + </div>
  95 + </template>
  96 + <CustomerTrend :customerTrendList="customerTrendList" />
  97 + </Card> -->
  98 + </div>
  99 +</template>
  100 +<script lang="ts" setup>
  101 + import { ref, reactive } from 'vue';
  102 + import { Card, DatePicker } from 'ant-design-vue';
  103 + import VisitAnalysis from './VisitAnalysis.vue';
  104 + import VisitAnalysisBar from './VisitAnalysisBar.vue';
  105 + import { isAdmin } from '/@/enums/roleEnum';
  106 + import { useWebSocket } from '@vueuse/core';
  107 + import { getAuthCache } from '/@/utils/auth';
  108 + import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum';
  109 + import { formatToDateTime } from '/@/utils/dateUtil';
  110 + import { getEntitiesId } from '/@/api/dashboard/index';
  111 + // import CustomerTrend from './CustomerTrend.vue';
  112 + import TenantTrend from './TenantTrend.vue';
  113 + import CustomerAlarmMessage from './CustomerAlarmMessage.vue';
  114 + import { useDate } from '../hooks/useDate';
  115 + import { getTrendData } from '/@/api/dashboard';
  116 + import { useGlobSetting } from '/@/hooks/setting';
  117 +
  118 + defineExpose({
  119 + isAdmin,
  120 + });
  121 + const props = defineProps<{
  122 + role: string;
  123 + }>();
  124 + const activeKey = ref('2');
  125 + let entityId = null;
  126 + // 图表tab切换选项卡 1965 1280 1861 836
  127 + const tabListTitle = [
  128 + // {
  129 + // key: '1',
  130 + // tab: '告警数统计',
  131 + // },
  132 + {
  133 + key: '2',
  134 + tab: '消息量统计',
  135 + },
  136 + ];
  137 + // 快速选择日期
  138 + const activeIndex = ref(3);
  139 + const dateValue = ref();
  140 + const dateList = ref([
  141 + { label: '1小时', value: 3600000 },
  142 + { label: '1天', value: 86400000 },
  143 + { label: '7天', value: 604800000 },
  144 + { label: '30天', value: 2592000000 },
  145 + ]);
  146 +
  147 + // web Socket
  148 + const token: string = getAuthCache(JWT_TOKEN_KEY);
  149 + const { socketUrl } = useGlobSetting();
  150 + const state = reactive({
  151 + server: `${socketUrl}${token}`,
  152 + alarmList: new Array<[number, string]>(),
  153 + alarmItem: new Array<[number, string]>(),
  154 + dataPointList: new Array<[number, string]>(),
  155 + messageList: new Array<[number, string]>(),
  156 + dataPoint: new Array<[number, string]>(),
  157 + MsgCount: new Array<[number, string]>(),
  158 + });
  159 + const { send, close } = useWebSocket(state.server, {
  160 + async onConnected() {
  161 + if (isAdmin(props.role)) return;
  162 + const res = await getEntitiesId();
  163 + entityId = res.data[0]?.entityId;
  164 + const sendValue = JSON.stringify({
  165 + entityDataCmds: [
  166 + {
  167 + query: {
  168 + entityFilter: {
  169 + type: 'singleEntity',
  170 + singleEntity: entityId,
  171 + },
  172 + pageLink: {
  173 + pageSize: 1024,
  174 + page: 0,
  175 + sortOrder: {
  176 + key: {
  177 + type: 'ENTITY_FIELD',
  178 + key: 'createdTime',
  179 + },
  180 + direction: 'DESC',
  181 + },
  182 + },
  183 + entityFields: [
  184 + {
  185 + type: 'ENTITY_FIELD',
  186 + key: 'name',
  187 + },
  188 + {
  189 + type: 'ENTITY_FIELD',
  190 + key: 'label',
  191 + },
  192 + {
  193 + type: 'ENTITY_FIELD',
  194 + key: 'additionalInfo',
  195 + },
  196 + ],
  197 + latestValues: [
  198 + {
  199 + type: 'TIME_SERIES',
  200 + key: 'createdAlarmsCountHourly',
  201 + },
  202 + ],
  203 + },
  204 + cmdId: activeKey.value,
  205 + },
  206 + ],
  207 + });
  208 + const sendValue1 = JSON.stringify({
  209 + entityDataCmds: [
  210 + {
  211 + cmdId: activeKey.value,
  212 + historyCmd: {
  213 + keys: ['createdAlarmsCountHourly'],
  214 + startTs: Date.now() - 2592000000,
  215 + endTs: Date.now(),
  216 + interval: 86400000,
  217 + agg: 'SUM',
  218 + },
  219 + },
  220 + ],
  221 + });
  222 + send(sendValue);
  223 + send(sendValue1);
  224 + },
  225 + onMessage(_, e) {
  226 + const { data, update } = JSON.parse(e.data);
  227 + if (activeKey.value === '1') {
  228 + if (data) {
  229 + const { createdAlarmsCountHourly } = data.data[0].latest.TIME_SERIES;
  230 + state.alarmItem = [createdAlarmsCountHourly.ts, createdAlarmsCountHourly.value];
  231 + state.alarmList.push([createdAlarmsCountHourly.ts, createdAlarmsCountHourly.value]);
  232 + }
  233 + if (update) {
  234 + const { createdAlarmsCountHourly } = update[0].timeseries;
  235 + const newArray: any = [];
  236 + for (const item of createdAlarmsCountHourly) {
  237 + newArray.push([item.ts, item.value]);
  238 + }
  239 + state.alarmList = newArray;
  240 + }
  241 + } else {
  242 + if (data) {
  243 + const { transportDataPointsCountHourly, transportMsgCountHourly } =
  244 + data.data[0].latest.TIME_SERIES;
  245 + state.dataPoint = [
  246 + transportDataPointsCountHourly.ts,
  247 + transportDataPointsCountHourly.value,
  248 + ];
  249 + state.MsgCount = [
  250 + transportDataPointsCountHourly.ts,
  251 + transportDataPointsCountHourly.value,
  252 + ];
  253 + state.dataPointList.push([
  254 + transportDataPointsCountHourly.ts,
  255 + transportDataPointsCountHourly.value,
  256 + ]);
  257 + state.messageList.push([transportMsgCountHourly.ts, transportMsgCountHourly.value]);
  258 + }
  259 + if (update) {
  260 + const { transportDataPointsCountHourly, transportMsgCountHourly } = update[0].timeseries;
  261 + const newArray: any[] = [];
  262 + const newArray1: any[] = [];
  263 + for (const item of transportDataPointsCountHourly) {
  264 + newArray.push([item.ts, item.value]);
  265 + }
  266 + for (const item of transportMsgCountHourly) {
  267 + newArray1.push([item.ts, item.value]);
  268 + }
  269 + state.dataPointList = newArray;
  270 + state.messageList = newArray1;
  271 + }
  272 + }
  273 + },
  274 + onDisconnected() {
  275 + console.log('断开连接了');
  276 + close();
  277 + },
  278 + });
  279 +
  280 + // 切换tab页
  281 + function onTabChange(key: string) {
  282 + activeKey.value = key;
  283 + activeIndex.value = 3;
  284 + dateValue.value = '';
  285 + const sendValue = JSON.stringify({
  286 + entityDataCmds: [
  287 + {
  288 + cmdId: activeKey.value,
  289 + historyCmd: {
  290 + keys:
  291 + activeKey.value === '1'
  292 + ? ['createdAlarmsCountHourly']
  293 + : ['transportMsgCountHourly', 'transportDataPointsCountHourly'],
  294 + startTs: Date.now() - 2592000000,
  295 + endTs: Date.now(),
  296 + interval: 86400000,
  297 + agg: 'SUM',
  298 + },
  299 + },
  300 + ],
  301 + });
  302 + if (key === '2') {
  303 + const sendMessageValue = JSON.stringify({
  304 + entityDataCmds: [
  305 + {
  306 + query: {
  307 + entityFilter: {
  308 + type: 'singleEntity',
  309 + singleEntity: entityId,
  310 + },
  311 + pageLink: {
  312 + pageSize: 1024,
  313 + page: 0,
  314 + sortOrder: {
  315 + key: {
  316 + type: 'ENTITY_FIELD',
  317 + key: 'createdTime',
  318 + },
  319 + direction: 'DESC',
  320 + },
  321 + },
  322 + entityFields: [
  323 + {
  324 + type: 'ENTITY_FIELD',
  325 + key: 'name',
  326 + },
  327 + {
  328 + type: 'ENTITY_FIELD',
  329 + key: 'label',
  330 + },
  331 + {
  332 + type: 'ENTITY_FIELD',
  333 + key: 'additionalInfo',
  334 + },
  335 + ],
  336 + latestValues: [
  337 + {
  338 + type: 'TIME_SERIES',
  339 + key: 'transportMsgCountHourly',
  340 + },
  341 + {
  342 + type: 'TIME_SERIES',
  343 + key: 'transportDataPointsCountHourly',
  344 + },
  345 + ],
  346 + },
  347 + cmdId: activeKey.value,
  348 + },
  349 + ],
  350 + });
  351 + send(sendMessageValue);
  352 + }
  353 + send(sendValue);
  354 + }
  355 + // 选择日期
  356 + async function onDateChange(_, dateString, roleType = '') {
  357 + console.log(_, dateString, roleType);
  358 + activeIndex.value = -1;
  359 + const dateTime = Number(formatToDateTime(dateString, 'x'));
  360 + if (!dateString) return;
  361 + if (roleType === 'customer') {
  362 + if (activeKey.value === '1') {
  363 + const data = await getTrendData({
  364 + startTs: dateTime,
  365 + endTs: dateTime + 86400000,
  366 + interval: 7200000,
  367 + trend: 'CUSTOMER_ALARM_STATISTICAL',
  368 + });
  369 + customerAlarmList.value = data;
  370 + } else if (activeKey.value === '2') {
  371 + const data = await getTrendData({
  372 + startTs: dateTime,
  373 + endTs: dateTime + 86400000,
  374 + interval: 7200000,
  375 + trend: 'CUSTOMER_MESSAGE_STATISTICAL',
  376 + });
  377 + customerMessageList.value = data;
  378 + }
  379 + } else {
  380 + // 动态发送ws数据
  381 + const sendValue = JSON.stringify({
  382 + entityDataCmds: [
  383 + {
  384 + cmdId: activeKey.value,
  385 + historyCmd: {
  386 + keys:
  387 + activeKey.value === '1'
  388 + ? ['createdAlarmsCountHourly']
  389 + : ['transportMsgCountHourly', 'transportDataPointsCountHourly'],
  390 + startTs: dateTime,
  391 + endTs: dateTime + 86400000,
  392 + interval: 7200000,
  393 + limit: 12,
  394 + agg: 'SUM',
  395 + },
  396 + },
  397 + ],
  398 + });
  399 + send(sendValue);
  400 + }
  401 + }
  402 + const customerAlarmList = ref([]);
  403 + const customerMessageList = ref([]);
  404 + // 快速选择时间
  405 + async function quickQueryDate(index: number, value: number, roleType = '') {
  406 + if (activeIndex.value === index) return;
  407 + activeIndex.value = index;
  408 + dateValue.value = '';
  409 + let interval = 300000;
  410 + if (value === 86400000) {
  411 + interval = 7200000;
  412 + } else if (value === 604800000 || value === 2592000000) {
  413 + interval = 86400000;
  414 + }
  415 + if (roleType === 'customer') {
  416 + if (activeKey.value === '1') {
  417 + const data = await getTrendData({
  418 + startTs: Date.now() - value,
  419 + endTs: Date.now(),
  420 + interval,
  421 + trend: 'CUSTOMER_ALARM_STATISTICAL',
  422 + });
  423 + customerAlarmList.value = data;
  424 + } else if (activeKey.value === '2') {
  425 + const data = await getTrendData({
  426 + startTs: Date.now() - value,
  427 + endTs: Date.now(),
  428 + interval,
  429 + trend: 'CUSTOMER_MESSAGE_STATISTICAL',
  430 + });
  431 + customerMessageList.value = data;
  432 + }
  433 + } else {
  434 + // 动态发送ws数据
  435 + const sendValue = JSON.stringify({
  436 + entityDataCmds: [
  437 + {
  438 + cmdId: activeKey.value,
  439 + historyCmd: {
  440 + keys:
  441 + activeKey.value === '1'
  442 + ? ['createdAlarmsCountHourly']
  443 + : ['transportMsgCountHourly', 'transportDataPointsCountHourly'],
  444 + startTs: Date.now() - value,
  445 + endTs: Date.now(),
  446 + interval,
  447 + agg: 'SUM',
  448 + },
  449 + },
  450 + ],
  451 + });
  452 + send(sendValue);
  453 + }
  454 + }
  455 + const {
  456 + tenantDateValue,
  457 + // customerDateValue,
  458 + tenantTrendList,
  459 + // customerTrendList,
  460 + activeTenantIndex,
  461 + // activeCustomerIndex,
  462 + TenantOrCustomerDateList,
  463 + quickQueryTenantOrCustomerTime,
  464 + onDateTenantChange,
  465 + // onDateCustomerChange,
  466 + } = useDate();
  467 +</script>
  468 +
  469 +<style lang="less">
  470 + .center {
  471 + display: flex;
  472 + justify-content: center;
  473 + font-size: 16px;
  474 + }
  475 +
  476 + .active {
  477 + color: #0960bd;
  478 + font-weight: 500;
  479 + }
  480 +
  481 + .extra-date {
  482 + display: flex;
  483 + align-items: center;
  484 + justify-content: space-between;
  485 +
  486 + span {
  487 + margin-right: 20px;
  488 + cursor: pointer;
  489 + }
  490 + }
  491 +</style>
... ...
... ... @@ -2,6 +2,8 @@
2 2 <div class="p-4 md:flex">
3 3 <div class="md:w-7/10 w-full !mr-4 enter-y">
4 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 7 <SiteAnalysis class="!my-4 enter-y" :loading="loading" :role="role" />
6 8 <div class="md:flex enter-y" v-if="!isAdmin(role)">
7 9 <Card title="核心流程指南" style="width: 100%">
... ... @@ -23,11 +25,14 @@
23 25 import { ref } from 'vue';
24 26 import GrowCard from './components/GrowCard.vue';
25 27 import SiteAnalysis from './components/SiteAnalysis.vue';
  28 + import SiteAnalysisMessage from './components/SiteAnalysisMessage.vue';
26 29 import { Card } from 'ant-design-vue';
27 30 import HelpDoc from './components/HelpDoc.vue';
28 31 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
29 32 import { getAuthCache } from '/@/utils/auth';
30 33 import { isAdmin } from '/@/enums/roleEnum';
  34 + import PieChartDevice from './components/PieChartDevice.vue';
  35 +
31 36 defineExpose({
32 37 isAdmin,
33 38 });
... ...