Commit 1717e6bb696f26a79cbf93fd2c8b1042b8b13047

Authored by sqy
1 parent e763f5cf

fix:首页逻辑改动,待完成,暂存拉代码

  1 +import { BasicPageParams } from './../model/baseModel';
1 import { defHttp } from '/@/utils/http/axios'; 2 import { defHttp } from '/@/utils/http/axios';
2 enum HomeEnum { 3 enum HomeEnum {
3 home = '/homepage/left/top', 4 home = '/homepage/left/top',
  5 + TenantExpireTimeList = '/homepage/right',
  6 + EntitiesQueryFind = '/entitiesQuery/find',
4 } 7 }
5 8
6 export const getHomeData = () => { 9 export const getHomeData = () => {
@@ -8,3 +11,54 @@ export const getHomeData = () => { @@ -8,3 +11,54 @@ export const getHomeData = () => {
8 url: HomeEnum.home, 11 url: HomeEnum.home,
9 }); 12 });
10 }; 13 };
  14 +
  15 +// 获取即将过期租户列表
  16 +export const getTenantExpireTimeList = (params: BasicPageParams) => {
  17 + return defHttp.get({
  18 + url: HomeEnum.TenantExpireTimeList,
  19 + params,
  20 + });
  21 +};
  22 +
  23 +// 获取entities实体ID
  24 +export const getEntitiesId = () => {
  25 + return defHttp.post(
  26 + {
  27 + url: HomeEnum.EntitiesQueryFind,
  28 + data: {
  29 + entityFilter: {
  30 + type: 'apiUsageState',
  31 + resolveMultiple: false,
  32 + },
  33 + pageLink: {
  34 + pageSize: 1,
  35 + page: 0,
  36 + sortOrder: {
  37 + key: {
  38 + type: 'ENTITY_FIELD',
  39 + key: 'createdTime',
  40 + },
  41 + direction: 'DESC',
  42 + },
  43 + },
  44 + entityFields: [
  45 + {
  46 + type: 'ENTITY_FIELD',
  47 + key: 'name',
  48 + },
  49 + {
  50 + type: 'ENTITY_FIELD',
  51 + key: 'label',
  52 + },
  53 + {
  54 + type: 'ENTITY_FIELD',
  55 + key: 'additionalInfo',
  56 + },
  57 + ],
  58 + },
  59 + },
  60 + {
  61 + joinPrefix: false,
  62 + }
  63 + );
  64 +};
1 -import { defHttp } from '/@/utils/http/axios';  
2 -  
3 -enum Api {  
4 - // The address does not exist  
5 - Error = '/error',  
6 -}  
7 -  
8 -/**  
9 - * @description: Trigger ajax error  
10 - */  
11 -  
12 -export const fireErrorApi = () => defHttp.get({ url: Api.Error });  
1 -import { defHttp } from '/@/utils/http/axios';  
2 -  
3 -enum Api {  
4 - TREE_OPTIONS_LIST = '/tree/getDemoOptions',  
5 -}  
6 -  
7 -/**  
8 - * @description: Get sample options value  
9 - */  
10 -export const treeOptionsListApi = (params?: Recordable) =>  
11 - defHttp.get<Recordable[]>({ url: Api.TREE_OPTIONS_LIST, params });  
  1 +<template>
  2 + <div ref="chartRef" :style="{ height, width }"></div>
  3 +</template>
  4 +<script lang="ts" setup>
  5 + import { ref, Ref, withDefaults, defineProps } from 'vue';
  6 + import { useECharts } from '/@/hooks/web/useECharts';
  7 +
  8 + interface Props {
  9 + width?: string;
  10 + height?: string;
  11 + }
  12 + withDefaults(defineProps<Props>(), {
  13 + width: '100%',
  14 + height: '280px',
  15 + });
  16 +
  17 + const chartRef = ref<HTMLDivElement | null>(null);
  18 + const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
  19 +</script>
@@ -100,7 +100,9 @@ @@ -100,7 +100,9 @@
100 </template> 100 </template>
101 </Descriptions> 101 </Descriptions>
102 </Card> 102 </Card>
103 - <BasicTable @register="registerTable" v-if="isAdmin(role)" /> 103 + <Card v-if="isAdmin(role)">
  104 + <BasicTable @register="registerTable" />
  105 + </Card>
104 </div> 106 </div>
105 </template> 107 </template>
106 108
@@ -125,6 +127,7 @@ @@ -125,6 +127,7 @@
125 import { BasicTable, useTable } from '/@/components/Table'; 127 import { BasicTable, useTable } from '/@/components/Table';
126 import { columns } from './props'; 128 import { columns } from './props';
127 import { isAdmin } from '/@/enums/roleEnum'; 129 import { isAdmin } from '/@/enums/roleEnum';
  130 + import { getTenantExpireTimeList } from '/@/api/dashboard';
128 export default defineComponent({ 131 export default defineComponent({
129 components: { 132 components: {
130 Card, 133 Card,
@@ -179,11 +182,17 @@ @@ -179,11 +182,17 @@
179 const onTabChange = (key) => { 182 const onTabChange = (key) => {
180 activeKey.value = key; 183 activeKey.value = key;
181 }; 184 };
182 - const [registerTable] = useTable({ 185 +
  186 + const [registerTable, { redoHeight }] = useTable({
  187 + api: getTenantExpireTimeList,
183 title: '本月即将过期租户', 188 title: '本月即将过期租户',
184 showIndexColumn: false, 189 showIndexColumn: false,
185 useSearchForm: false, 190 useSearchForm: false,
186 columns, 191 columns,
  192 + fetchSetting: {
  193 + listField: 'expireTenant.items',
  194 + totalField: 'expireTenant.total',
  195 + },
187 }); 196 });
188 197
189 const userStore = useUserStore(); 198 const userStore = useUserStore();
@@ -201,6 +210,7 @@ @@ -201,6 +210,7 @@
201 }); 210 });
202 onMounted(async () => { 211 onMounted(async () => {
203 if (isAdmin(props.role)) return; 212 if (isAdmin(props.role)) return;
  213 +
204 const res = await getEnterPriseDetail(); 214 const res = await getEnterPriseDetail();
205 const notice = await notifyMyGetrPageApi({ page: 1, pageSize: 5 }); 215 const notice = await notifyMyGetrPageApi({ page: 1, pageSize: 5 });
206 userStore.setEnterPriseInfo(res); 216 userStore.setEnterPriseInfo(res);
@@ -220,6 +230,7 @@ @@ -220,6 +230,7 @@
220 go, 230 go,
221 registerTable, 231 registerTable,
222 isAdmin, 232 isAdmin,
  233 + redoHeight,
223 }; 234 };
224 }, 235 },
225 }); 236 });
@@ -4,128 +4,82 @@ @@ -4,128 +4,82 @@
4 v-bind="$attrs" 4 v-bind="$attrs"
5 :active-tab-key="activeKey" 5 :active-tab-key="activeKey"
6 @tabChange="onTabChange" 6 @tabChange="onTabChange"
  7 + v-if="!isAdmin(role)"
7 > 8 >
8 - <template #tabBarExtraContent v-if="!isAdmin(role)"> 9 + <template #tabBarExtraContent>
9 <div class="extra-date"> 10 <div class="extra-date">
10 - <template v-for="(item, index) in dateList" :key="item">  
11 - <span @click="changeDate(index)" :class="{ active: index === activeIndex }">{{  
12 - item 11 + <template v-for="(item, index) in dateList" :key="item.value">
  12 + <span @click="changeDate(index, item.value)" :class="{ active: index === activeIndex }">{{
  13 + item.label
13 }}</span> 14 }}</span>
14 </template> 15 </template>
15 <DatePicker @change="onDateChange" /> 16 <DatePicker @change="onDateChange" />
16 </div> 17 </div>
17 </template> 18 </template>
18 <div v-if="activeKey === '1'"> 19 <div v-if="activeKey === '1'">
19 - <p class="center">{{ !isAdmin(role) ? '告警数' : '租户趋势' }}</p> 20 + <p class="center">告警数</p>
  21 + <!-- 折线图 -->
20 <VisitAnalysis v-if="!isAdmin(role)" :alarmList="state.alarmList" /> 22 <VisitAnalysis v-if="!isAdmin(role)" :alarmList="state.alarmList" />
21 - <VisitAnalysisBar v-else />  
22 </div> 23 </div>
23 <div v-if="activeKey === '2'"> 24 <div v-if="activeKey === '2'">
24 <p class="center">消息量</p> 25 <p class="center">消息量</p>
25 - <VisitAnalysisBar :dataPointList="state.dataPointList" :messageList="state.messageList" /> 26 + <!-- 柱形图 -->
  27 + <VisitAnalysisBar
  28 + v-if="!isAdmin(role)"
  29 + :dataPointList="state.dataPointList"
  30 + :messageList="state.messageList"
  31 + />
26 </div> 32 </div>
27 </Card> 33 </Card>
28 - <Card v-bind="$attrs" :tab-list="tab1ListTitle" v-if="isAdmin(role)">  
29 - <p class="center">客户趋势</p>  
30 - <VisitAnalysis  
31 - /></Card> 34 + <Card v-bind="$attrs" v-if="isAdmin(role)" title="租户趋势">
  35 + <TenantTrend />
  36 + </Card>
  37 + <Card v-bind="$attrs" v-if="isAdmin(role)" title="客户趋势">
  38 + <CustomerTrend />
  39 + </Card>
32 </template> 40 </template>
33 <script lang="ts" setup> 41 <script lang="ts" setup>
34 - import { ref, defineExpose, reactive } from 'vue'; 42 + import { ref, reactive } from 'vue';
35 import { Card, DatePicker } from 'ant-design-vue'; 43 import { Card, DatePicker } from 'ant-design-vue';
36 import VisitAnalysis from './VisitAnalysis.vue'; 44 import VisitAnalysis from './VisitAnalysis.vue';
37 import VisitAnalysisBar from './VisitAnalysisBar.vue'; 45 import VisitAnalysisBar from './VisitAnalysisBar.vue';
38 - import { defineProps } from 'vue';  
39 import { isAdmin } from '/@/enums/roleEnum'; 46 import { isAdmin } from '/@/enums/roleEnum';
40 import { useWebSocket } from '@vueuse/core'; 47 import { useWebSocket } from '@vueuse/core';
41 import { getAuthCache } from '/@/utils/auth'; 48 import { getAuthCache } from '/@/utils/auth';
  49 + import CustomerTrend from './CustomerTrend.vue';
  50 + import TenantTrend from './TenantTrend.vue';
42 import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; 51 import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum';
43 - 52 + import { formatToDateTime } from '/@/utils/dateUtil';
  53 + import { getEntitiesId } from '/@/api/dashboard/index';
44 defineExpose({ 54 defineExpose({
45 isAdmin, 55 isAdmin,
46 }); 56 });
47 - const props = defineProps<{ 57 + defineProps<{
48 role: string; 58 role: string;
49 }>(); 59 }>();
50 const activeKey = ref('1'); 60 const activeKey = ref('1');
51 -  
52 - // 动态根据登录角色来判断  
53 - const tabListTitle = !isAdmin(props.role)  
54 - ? [  
55 - {  
56 - key: '1',  
57 - tab: '告警数统计',  
58 - },  
59 - {  
60 - key: '2',  
61 - tab: '消息量统计',  
62 - },  
63 - ]  
64 - : [  
65 - {  
66 - key: '1',  
67 - tab: '租户',  
68 - },  
69 - ];  
70 -  
71 - const tab1ListTitle = [ 61 + let entityId = null;
  62 + // 图表tab切换选项卡
  63 + const tabListTitle = [
72 { 64 {
73 key: '1', 65 key: '1',
74 - tab: '客户', 66 + tab: '告警数统计',
  67 + },
  68 + {
  69 + key: '2',
  70 + tab: '消息量统计',
75 }, 71 },
76 ]; 72 ];
77 -  
78 - const dateList = ref(['1小时', '1天', '7天', '30天']); 73 + const activeIndex = ref(0);
  74 + const dateList = ref([
  75 + { label: '1小时', value: 3600000 },
  76 + { label: '1天', value: 86400000 },
  77 + { label: '7天', value: 604800000 },
  78 + { label: '30天', value: 2592000000 },
  79 + ]);
79 // web Socket 80 // web Socket
80 const token: string = getAuthCache(JWT_TOKEN_KEY); 81 const token: string = getAuthCache(JWT_TOKEN_KEY);
81 - const sendValue = JSON.stringify({  
82 - entityDataCmds: [  
83 - {  
84 - query: {  
85 - entityFilter: {  
86 - type: 'singleEntity',  
87 - singleEntity: {  
88 - id: '33782740-5d97-11ec-8ac9-f38ed935ea2a',  
89 - entityType: 'API_USAGE_STATE',  
90 - },  
91 - },  
92 - pageLink: {  
93 - pageSize: 1024,  
94 - page: 0,  
95 - sortOrder: {  
96 - key: {  
97 - type: 'ENTITY_FIELD',  
98 - key: 'createdTime',  
99 - },  
100 - direction: 'DESC',  
101 - },  
102 - },  
103 - entityFields: [  
104 - {  
105 - type: 'ENTITY_FIELD',  
106 - key: 'name',  
107 - },  
108 - {  
109 - type: 'ENTITY_FIELD',  
110 - key: 'label',  
111 - },  
112 - {  
113 - type: 'ENTITY_FIELD',  
114 - key: 'additionalInfo',  
115 - },  
116 - ],  
117 - latestValues: [  
118 - {  
119 - type: 'TIME_SERIES',  
120 - key: 'createdAlarmsCountHourly',  
121 - },  
122 - ],  
123 - },  
124 - cmdId: activeKey.value,  
125 - },  
126 - ],  
127 - });  
128 - const activeIndex = ref(0); 82 +
129 const state = reactive({ 83 const state = reactive({
130 server: `${import.meta.env.VITE_WEB_SOCKET}${token}`, 84 server: `${import.meta.env.VITE_WEB_SOCKET}${token}`,
131 alarmList: new Array<[number, string]>(), 85 alarmList: new Array<[number, string]>(),
@@ -136,7 +90,53 @@ @@ -136,7 +90,53 @@
136 MsgCount: new Array<[number, string]>(), 90 MsgCount: new Array<[number, string]>(),
137 }); 91 });
138 const { send, close } = useWebSocket(state.server, { 92 const { send, close } = useWebSocket(state.server, {
139 - onConnected() { 93 + async onConnected() {
  94 + const res = await getEntitiesId();
  95 + entityId = res.data[0].entityId;
  96 + const sendValue = JSON.stringify({
  97 + entityDataCmds: [
  98 + {
  99 + query: {
  100 + entityFilter: {
  101 + type: 'singleEntity',
  102 + singleEntity: entityId,
  103 + },
  104 + pageLink: {
  105 + pageSize: 1024,
  106 + page: 0,
  107 + sortOrder: {
  108 + key: {
  109 + type: 'ENTITY_FIELD',
  110 + key: 'createdTime',
  111 + },
  112 + direction: 'DESC',
  113 + },
  114 + },
  115 + entityFields: [
  116 + {
  117 + type: 'ENTITY_FIELD',
  118 + key: 'name',
  119 + },
  120 + {
  121 + type: 'ENTITY_FIELD',
  122 + key: 'label',
  123 + },
  124 + {
  125 + type: 'ENTITY_FIELD',
  126 + key: 'additionalInfo',
  127 + },
  128 + ],
  129 + latestValues: [
  130 + {
  131 + type: 'TIME_SERIES',
  132 + key: 'createdAlarmsCountHourly',
  133 + },
  134 + ],
  135 + },
  136 + cmdId: activeKey.value,
  137 + },
  138 + ],
  139 + });
140 send(sendValue); 140 send(sendValue);
141 console.log('建立连接了'); 141 console.log('建立连接了');
142 }, 142 },
@@ -144,9 +144,12 @@ @@ -144,9 +144,12 @@
144 const { data, update } = JSON.parse(e.data); 144 const { data, update } = JSON.parse(e.data);
145 if (activeKey.value === '1') { 145 if (activeKey.value === '1') {
146 if (data) { 146 if (data) {
147 - const { createdAlarmsCountHourly } = data.data[0].latest.TIME_SERIES;  
148 - state.alarmItem = [createdAlarmsCountHourly.ts, createdAlarmsCountHourly.value];  
149 - state.alarmList.push([createdAlarmsCountHourly.ts, createdAlarmsCountHourly.value]); 147 + const alarmData = data.data[0]?.latest.TIME_SERIES;
  148 + if (alarmData?.createdAlarmsCountHourly) {
  149 + const { createdAlarmsCountHourly } = alarmData;
  150 + state.alarmItem = [createdAlarmsCountHourly.ts, createdAlarmsCountHourly.value];
  151 + state.alarmList.push([createdAlarmsCountHourly.ts, createdAlarmsCountHourly.value]);
  152 + }
150 } 153 }
151 if (update) { 154 if (update) {
152 const { createdAlarmsCountHourly } = update[0].timeseries; 155 const { createdAlarmsCountHourly } = update[0].timeseries;
@@ -177,8 +180,9 @@ @@ -177,8 +180,9 @@
177 } 180 }
178 if (update) { 181 if (update) {
179 const { transportDataPointsCountHourly, transportMsgCountHourly } = update[0].timeseries; 182 const { transportDataPointsCountHourly, transportMsgCountHourly } = update[0].timeseries;
180 - const newArray: any = [];  
181 - const newArray1: any = []; 183 + const newArray: any[] = [];
  184 + const newArray1: any[] = [];
  185 + console.log(update[0]);
182 for (const item of transportDataPointsCountHourly) { 186 for (const item of transportDataPointsCountHourly) {
183 newArray.push([item.ts, item.value]); 187 newArray.push([item.ts, item.value]);
184 } 188 }
@@ -208,7 +212,7 @@ @@ -208,7 +212,7 @@
208 endTs: 1641370336692, 212 endTs: 1641370336692,
209 interval: 43200000, 213 interval: 43200000,
210 limit: 60, 214 limit: 60,
211 - agg: 'SUM', 215 + agg: 'COUNT',
212 }, 216 },
213 }, 217 },
214 ], 218 ],
@@ -221,10 +225,7 @@ @@ -221,10 +225,7 @@
221 query: { 225 query: {
222 entityFilter: { 226 entityFilter: {
223 type: 'singleEntity', 227 type: 'singleEntity',
224 - singleEntity: {  
225 - id: '33782740-5d97-11ec-8ac9-f38ed935ea2a',  
226 - entityType: 'API_USAGE_STATE',  
227 - }, 228 + singleEntity: entityId,
228 }, 229 },
229 pageLink: { 230 pageLink: {
230 pageSize: 1024, 231 pageSize: 1024,
@@ -285,11 +286,42 @@ @@ -285,11 +286,42 @@
285 send(sendMessageValue2); 286 send(sendMessageValue2);
286 } 287 }
287 } 288 }
288 - function onDateChange(date, dateString) {  
289 - console.log(date, dateString); 289 + function onDateChange(_, dateString) {
  290 + const dateTime = formatToDateTime(dateString, 'x');
  291 + console.log(dateTime);
290 } 292 }
291 - function changeDate(index: number) { 293 + function changeDate(index: number, value: number) {
292 activeIndex.value = index; 294 activeIndex.value = index;
  295 + let limit;
  296 + if (value === 3600000 || value === 86400000) {
  297 + limit = 12;
  298 + } else if (value === 604800000) {
  299 + limit = 7;
  300 + } else if (value === 2592000000) {
  301 + limit = 30;
  302 + }
  303 + // 动态发送ws数据
  304 + const sendValue = JSON.stringify({
  305 + entityDataCmds: [
  306 + {
  307 + cmdId: activeKey.value,
  308 + historyCmd: {
  309 + keys:
  310 + activeKey.value === '1'
  311 + ? ['createdAlarmsCountHourly']
  312 + : ['transportMsgCountHourly', 'transportDataPointsCountHourly'],
  313 + startTs: Date.now() - value,
  314 + endTs: Date.now(),
  315 + interval: value > 3600000 ? 7200000 : 300000,
  316 + limit,
  317 + agg: 'COUNT',
  318 + },
  319 + },
  320 + ],
  321 + });
  322 + send(sendValue);
  323 +
  324 + console.log(value);
293 } 325 }
294 </script> 326 </script>
295 327
  1 +<template>
  2 + <div ref="chartRef" :style="{ height, width }"></div>
  3 +</template>
  4 +<script lang="ts" setup>
  5 + import { ref, Ref, withDefaults, defineProps } from 'vue';
  6 + import { useECharts } from '/@/hooks/web/useECharts';
  7 +
  8 + interface Props {
  9 + width?: string;
  10 + height?: string;
  11 + }
  12 + withDefaults(defineProps<Props>(), {
  13 + width: '100%',
  14 + height: '280px',
  15 + });
  16 +
  17 + const chartRef = ref<HTMLDivElement | null>(null);
  18 + const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
  19 +</script>
@@ -23,7 +23,13 @@ @@ -23,7 +23,13 @@
23 () => [props.dataPointList, props.messageList], 23 () => [props.dataPointList, props.messageList],
24 ([newValue, newValue1]) => { 24 ([newValue, newValue1]) => {
25 setOptions({ 25 setOptions({
26 - tooltip: {}, 26 + tooltip: {
  27 + trigger: 'axis',
  28 + axisPointer: {
  29 + // Use axis to trigger tooltip
  30 + type: 'shadow', // 'shadow' as default; can also be 'line' or 'shadow'
  31 + },
  32 + },
27 xAxis: { 33 xAxis: {
28 type: 'time', 34 type: 'time',
29 }, 35 },
@@ -39,13 +45,14 @@ @@ -39,13 +45,14 @@
39 { 45 {
40 name: '传输数据点', 46 name: '传输数据点',
41 type: 'bar', 47 type: 'bar',
42 - stack: 'one', 48 + stack: 'total',
43 data: newValue, 49 data: newValue,
44 }, 50 },
45 { 51 {
46 name: '传输消息量', 52 name: '传输消息量',
47 type: 'bar', 53 type: 'bar',
48 - stack: 'one', 54 + stack: 'total',
  55 +
49 data: newValue1, 56 data: newValue1,
50 }, 57 },
51 ], 58 ],
@@ -18,12 +18,12 @@ export const basicProps = { @@ -18,12 +18,12 @@ export const basicProps = {
18 export const columns: BasicColumn[] = [ 18 export const columns: BasicColumn[] = [
19 { 19 {
20 title: '租户名称', 20 title: '租户名称',
21 - dataIndex: 'tenantName', 21 + dataIndex: 'name',
22 width: 120, 22 width: 120,
23 }, 23 },
24 { 24 {
25 title: '过期时间', 25 title: '过期时间',
26 - dataIndex: 'createdTime', 26 + dataIndex: 'tenantExpireTime',
27 width: 120, 27 width: 120,
28 }, 28 },
29 ]; 29 ];
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 </div> 10 </div>
11 </div> 11 </div>
12 <div class="md:w-3/10 w-full enter-y"> 12 <div class="md:w-3/10 w-full enter-y">
13 - <HelpDoc :role="role" /> 13 + <HelpDoc :role="role" ref="helpDocRef" />
14 </div> 14 </div>
15 </div> 15 </div>
16 </template> 16 </template>
@@ -29,9 +29,22 @@ @@ -29,9 +29,22 @@
29 29
30 const userInfo: any = getAuthCache(USER_INFO_KEY); 30 const userInfo: any = getAuthCache(USER_INFO_KEY);
31 const role = userInfo.roles[0]; 31 const role = userInfo.roles[0];
  32 +
32 console.log(role); 33 console.log(role);
33 const loading = ref(true); 34 const loading = ref(true);
  35 + const helpDocRef = ref();
34 setTimeout(() => { 36 setTimeout(() => {
35 loading.value = false; 37 loading.value = false;
36 }, 1500); 38 }, 1500);
  39 + window.addEventListener(
  40 + 'scroll',
  41 + () => {
  42 + const scrollBottom =
  43 + document.body.scrollHeight - document.body.scrollTop - document.body.clientHeight;
  44 + if (scrollBottom <= 0) {
  45 + helpDocRef.value.redoHeight();
  46 + }
  47 + },
  48 + true
  49 + );
37 </script> 50 </script>