Commit 7cdf8ee02fb2f456f2c4ba9d52fe3e03965fe746

Authored by ww
1 parent 9b283601

feat: implement TextComponent && DigitalDashboardComponent echo real data

... ... @@ -14,12 +14,14 @@ VITE_PUBLIC_PATH = /
14 14 # VITE_PROXY = [["/api","http://101.133.234.90:8080/api"]]
15 15 # 线上测试环境
16 16 # VITE_PROXY = [["/api","http://localhost:8080/api"],["/thingskit-drawio","http://localhost:3000/"]]
17   -VITE_PROXY = [["/api","https://dev.thingskit.com/api"],["/thingskit-drawio","http://localhost:3000/"]]
  17 +# VITE_PROXY = [["/api","https://dev.thingskit.com/api"],["/thingskit-drawio","http://localhost:3000/"]]
  18 +VITE_PROXY = [["/api","http://121.37.251.8:8080/api"],["/thingskit-drawio","http://localhost:3000/"]]
18 19 # VITE_PROXY = [["/api","http://192.168.10.106:8080/api"],["/thingskit-drawio","http://192.168.10.106:8080/api"]]
19 20
20 21 # 实时数据的ws地址
21 22 # VITE_WEB_SOCKET = ws://localhost:8080/api/ws/plugins/telemetry?token=
22   -VITE_WEB_SOCKET = ws://44.99.141.212:8080/api/ws/plugins/telemetry?token=
  23 +# VITE_WEB_SOCKET = ws://44.99.141.212:8080/api/ws/plugins/telemetry?token=
  24 +VITE_WEB_SOCKET = ws://121.37.251.8:8080/api/ws/plugins/telemetry?token=
23 25
24 26 # Delete console
25 27 VITE_DROP_CONSOLE = true
... ... @@ -37,5 +39,5 @@ VITE_GLOB_API_URL_PREFIX=/yt
37 39 VITE_GLOB_CONFIGURATION = /thingskit-drawio
38 40
39 41 # Content Security Policy
40   -VITE_CONTENT_SECURITY_POLICY = true
  42 +VITE_CONTENT_SECURITY_POLICY = false
41 43
... ...
... ... @@ -6,6 +6,7 @@
6 6 ],
7 7 "commentTranslate.targetLanguage": "en",
8 8 "cSpell.words": [
  9 + "Cmds",
9 10 "unref"
10 11 ]
11 12 }
... ...
... ... @@ -62,6 +62,8 @@ export interface ComponentInfo {
62 62 gradientInfo: GradientInfo[];
63 63 iconColor: string;
64 64 icon: string;
  65 + value?: string | number;
  66 + updateTime?: number;
65 67 }
66 68
67 69 export interface DataSource {
... ...
... ... @@ -122,7 +122,7 @@
122 122 }>();
123 123 const activeKey = ref('1');
124 124 let entityId = null;
125   - // 图表tab切换选项卡
  125 + // 图表tab切换选项卡 1965 1280 1861 836
126 126 const tabListTitle = [
127 127 {
128 128 key: '1',
... ...
... ... @@ -51,6 +51,7 @@
51 51 option && unref(chartRef)?.setOption(option);
52 52 });
53 53 }
  54 +
54 55 const getRadio = computed(() => {
55 56 const { radio } = props.radio;
56 57 return radio;
... ... @@ -93,10 +94,12 @@
93 94 >
94 95 <Tooltip
95 96 placement="topLeft"
96   - :title="props.value.updateTime || dateUtil().format(DEFAULT_DATE_FORMAT)"
  97 + :title="dateUtil(props?.value?.updateTime || new Date()).format(DEFAULT_DATE_FORMAT)"
97 98 >
98 99 <span class="mr-2">更新时间:</span>
99   - <span> {{ props.value.updateTime || dateUtil().format(DEFAULT_DATE_FORMAT) }}</span>
  100 + <span>
  101 + {{ dateUtil(props?.value?.updateTime || new Date()).format(DEFAULT_DATE_FORMAT) }}
  102 + </span>
100 103 </Tooltip>
101 104 </div>
102 105 </div>
... ...
... ... @@ -17,20 +17,21 @@
17 17 }>();
18 18
19 19 const integerPart = computed(() => {
20   - const { value = 0 } = props.value;
  20 + let { value = 0 } = props.value;
21 21 const { max = 5 } = props.layout;
22   - let _value = value?.toFixed(2).split('.')[0];
  22 + if (isNaN(value)) value = 0;
  23 + let _value = Number(value).toFixed(2).split('.')[0];
23 24 if (_value.length < max) _value = _value.padStart(5, '0');
24   -
25 25 if (_value.length > max) _value = ''.padStart(5, '9');
26 26
27 27 return _value;
28 28 });
29 29
30 30 const decimalPart = computed(() => {
31   - const { value = 0 } = props.value;
  31 + let { value = 0 } = props.value;
32 32 const { keepNumber = 2 } = props.layout;
33   - let _value = value?.toFixed(2).split('.')[1];
  33 + if (isNaN(value)) value = 0;
  34 + let _value = Number(value)?.toFixed(2).split('.')[1];
34 35 if (_value.length < keepNumber) _value = _value.padStart(5, '0');
35 36
36 37 if (_value.length > keepNumber) _value = ''.padStart(5, '0');
... ... @@ -91,10 +92,12 @@
91 92 >
92 93 <Tooltip
93 94 placement="topLeft"
94   - :title="props.value.updateTime || dateUtil().format(DEFAULT_DATE_FORMAT)"
  95 + :title="dateUtil(props?.value?.updateTime || new Date()).format(DEFAULT_DATE_FORMAT)"
95 96 >
96 97 <span class="mr-1">更新时间:</span>
97   - <span>{{ props.value.updateTime || dateUtil().format(DEFAULT_DATE_FORMAT) }}</span>
  98 + <span>
  99 + {{ dateUtil(props?.value?.updateTime || new Date()).format(DEFAULT_DATE_FORMAT) }}
  100 + </span>
98 101 </Tooltip>
99 102 </div>
100 103 </div>
... ...
... ... @@ -288,9 +288,9 @@ export const transformDashboardComponentConfig = (
288 288 value: {
289 289 id: buildUUID(),
290 290 name: dataSourceRecord.attributeRename || dataSourceRecord.attribute,
291   - // value: record.va
  291 + value: dataSourceRecord.componentInfo.value,
292 292 unit: dataSourceRecord.componentInfo.unit,
293   - updateTime: record.updateTime || record.createTime,
  293 + updateTime: dataSourceRecord.componentInfo.updateTime,
294 294 fontColor: dataSourceRecord.componentInfo.fontColor,
295 295 gradientInfo: dataSourceRecord.componentInfo.gradientInfo,
296 296 },
... ...
... ... @@ -90,14 +90,14 @@
90 90 <div v-if="getShowUpdate" class="text-center text-xs text-gray-400 truncate">
91 91 <Tooltip
92 92 placement="topLeft"
93   - :title="props.value.updateTime || dateUtil().format(DEFAULT_DATE_FORMAT)"
  93 + :title="dateUtil(props?.value?.updateTime || new Date()).format(DEFAULT_DATE_FORMAT)"
94 94 >
95 95 <span>更新时间:</span>
96 96 <span
97 97 :style="{ fontSize: fontSize({ radio: getRadio, basic: 12, max: 16 }) }"
98 98 class="truncate"
99 99 >
100   - {{ props.value.updateTime || dateUtil().format(DEFAULT_DATE_FORMAT) }}
  100 + {{ dateUtil(props?.value?.updateTime || new Date()).format(DEFAULT_DATE_FORMAT) }}
101 101 </span>
102 102 </Tooltip>
103 103 </div>
... ...
... ... @@ -88,10 +88,10 @@ export const transformTextComponentConfig = (
88 88 } as TextComponentLayout,
89 89 value: {
90 90 name: dataSourceRecord.attributeRename || dataSourceRecord.attribute,
91   - // value: record.va
  91 + value: dataSourceRecord.componentInfo.value,
92 92 icon: dataSourceRecord.componentInfo.icon,
93 93 unit: dataSourceRecord.componentInfo.unit,
94   - updateTime: record.updateTime || record.createTime,
  94 + updateTime: dataSourceRecord.componentInfo.updateTime,
95 95 fontColor: dataSourceRecord.componentInfo.fontColor,
96 96 iconColor: dataSourceRecord.componentInfo.iconColor,
97 97 } as TextComponentValue,
... ...
... ... @@ -23,6 +23,7 @@
23 23 import { DataBoardLayoutInfo } from '../types/type';
24 24 import { WidgetComponentType } from './config/visualOptions';
25 25 import Authority from '/@/components/Authority/src/Authority.vue';
  26 + import { useSocketConnect } from '../hook/useSocketConnect';
26 27
27 28 const ROUTE = useRoute();
28 29
... ... @@ -43,9 +44,6 @@
43 44 const GirdLayoutColNum = 24;
44 45 const GridLayoutMargin = 10;
45 46
46   - const defaultWidth = 6;
47   - const defaultHeight = 6;
48   -
49 47 const handleBack = () => {
50 48 ROUTER.go(-1);
51 49 };
... ... @@ -164,6 +162,8 @@
164 162 } catch (error) {}
165 163 };
166 164
  165 + const { beginSendMessage } = useSocketConnect(dataBoardList);
  166 +
167 167 const getDataBoardComponent = async () => {
168 168 try {
169 169 // dataBoardList.value = [];
... ... @@ -178,8 +178,8 @@
178 178 }
179 179 return {
180 180 i: item.id,
181   - w: layout.w || defaultWidth,
182   - h: layout.h || defaultHeight,
  181 + w: layout.w || DEFAULT_WIDGET_WIDTH,
  182 + h: layout.h || DEFAULT_WIDGET_HEIGHT,
183 183 x: layout.x || 0,
184 184 y: layout.y || 0,
185 185 record: {
... ... @@ -189,6 +189,7 @@
189 189 },
190 190 };
191 191 });
  192 + beginSendMessage();
192 193 } catch (error) {}
193 194 };
194 195
... ...
  1 +import { useWebSocket } from '@vueuse/core';
  2 +import { Ref, unref } from 'vue';
  3 +import { DataBoardLayoutInfo } from '../types/type';
  4 +import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum';
  5 +import { getAuthCache } from '/@/utils/auth';
  6 +
  7 +interface SocketMessage {
  8 + tsSubCmds: SocketMessageItem[];
  9 +}
  10 +
  11 +interface SocketMessageItem {
  12 + entityType: string;
  13 + entityId: string;
  14 + scope: string;
  15 + cmdId: number;
  16 + keys: string;
  17 +}
  18 +
  19 +interface CmdMapping {
  20 + componentId: string;
  21 + deviceId: string;
  22 + recordIndex: number;
  23 + dataSourceIndex: number;
  24 + attribute: string;
  25 +}
  26 +
  27 +interface ResponseMessage {
  28 + subscriptionId: number;
  29 + errorCode: number;
  30 + errorMsg: Nullable<string>;
  31 + data: {
  32 + [key: string]: [[number, string]];
  33 + };
  34 + latestValues: {
  35 + [key: string]: number;
  36 + };
  37 +}
  38 +
  39 +const generateMessage = (deviceId: string, cmdId: number, attr: string): SocketMessageItem => {
  40 + return {
  41 + entityType: 'DEVICE',
  42 + entityId: deviceId,
  43 + scope: 'LATEST_TELEMETRY',
  44 + cmdId,
  45 + keys: attr,
  46 + };
  47 +};
  48 +
  49 +export function useSocketConnect(dataSourceRef: Ref<DataBoardLayoutInfo[]>) {
  50 + const token = getAuthCache(JWT_TOKEN_KEY);
  51 +
  52 + const cmdIdMapping = new Map<number, CmdMapping>();
  53 +
  54 + const waitSendQueue: string[] = [];
  55 +
  56 + const config = {
  57 + server: `${import.meta.env.VITE_WEB_SOCKET}${token}`,
  58 + };
  59 +
  60 + const getNeedUpdateValueById = (componentId: string, deviceId: string) => {};
  61 +
  62 + const getNeedUpdateValueByIndex = (recordIndex: number, dataSourceIndex: number) => {
  63 + return unref(dataSourceRef)[recordIndex].record.dataSource[dataSourceIndex];
  64 + };
  65 +
  66 + const { close, send, open, status } = useWebSocket(config.server, {
  67 + onConnected() {
  68 + if (waitSendQueue.length) {
  69 + waitSendQueue.forEach((string) => {
  70 + send(string);
  71 + });
  72 + waitSendQueue.length = 0;
  73 + }
  74 + },
  75 + onMessage(ws, message) {
  76 + try {
  77 + const res: ResponseMessage = JSON.parse(message.data);
  78 + const { subscriptionId, data = {} } = res;
  79 + const mappingRecord = cmdIdMapping.get(subscriptionId);
  80 + if (!mappingRecord) return;
  81 + const { attribute, recordIndex, dataSourceIndex } = mappingRecord;
  82 + const [[timespan, value]] = data[attribute];
  83 + const record = getNeedUpdateValueByIndex(recordIndex, dataSourceIndex);
  84 + record.componentInfo.value = value;
  85 + record.componentInfo.updateTime = timespan;
  86 + } catch (error) {
  87 + throw Error(error as string);
  88 + }
  89 + },
  90 + onDisconnected() {
  91 + close();
  92 + },
  93 + });
  94 +
  95 + const setCmdId = (cmdId: number, record: CmdMapping) => {
  96 + cmdIdMapping.set(cmdId, record);
  97 + };
  98 +
  99 + const transformSocketMessageItem = () => {
  100 + const messageList: SocketMessageItem[] = [];
  101 + console.log(dataSourceRef);
  102 + unref(dataSourceRef).forEach((record, recordIndex) => {
  103 + const componentId = record.record.id;
  104 + record.record.dataSource.forEach((dataSource, dataSourceIndex) => {
  105 + const { deviceId, attribute } = dataSource;
  106 + const cmdId = recordIndex * dataSourceIndex + recordIndex;
  107 + setCmdId(cmdId, {
  108 + componentId,
  109 + deviceId,
  110 + recordIndex,
  111 + dataSourceIndex,
  112 + attribute,
  113 + });
  114 +
  115 + messageList.push(generateMessage(deviceId, cmdId, attribute));
  116 + });
  117 + });
  118 + return {
  119 + tsSubCmds: messageList,
  120 + } as SocketMessage;
  121 + };
  122 +
  123 + const beginSendMessage = () => {
  124 + // close();
  125 + cmdIdMapping.clear();
  126 +
  127 + // open();
  128 + const messageList = transformSocketMessageItem();
  129 +
  130 + if (unref(status) !== 'OPEN') {
  131 + waitSendQueue.push(JSON.stringify(messageList));
  132 + return;
  133 + }
  134 + send(JSON.stringify(messageList));
  135 + };
  136 +
  137 + return {
  138 + close,
  139 + send,
  140 + open,
  141 + beginSendMessage,
  142 + };
  143 +}
... ...