Commit aa402d4f5d01a718fb6e555a938e26a4544d5f9c

Authored by ww
1 parent 97fdd4f3

perf: histroy data all add table mode && chart mode

1 1 import { RadioRecord } from '../../../views/visual/board/detail/config/util';
2 2 import { DeviceTypeEnum } from '../../device/model/deviceModel';
  3 +import { DataType } from '../../device/model/modelOfMatterModel';
3 4
4 5 export interface AddDataBoardParams {
5 6 name: string;
... ... @@ -149,8 +150,6 @@ export interface ComponentInfoDetail {
149 150 data: { componentData: DataComponentRecord[]; componentLayout: Layout[] };
150 151 }
151 152
152   -export type DataType = 'BOOL' | 'DOUBLE' | 'INT' | 'STRUCT' | 'TExT';
153   -
154 153 export interface DeviceAttributeParams {
155 154 deviceProfileId: string;
156 155 dataType?: DataType;
... ... @@ -159,7 +158,7 @@ export interface DeviceAttributeParams {
159 158 export interface DeviceAttributeRecord {
160 159 name: string;
161 160 identifier: string;
162   - detail: DataType;
  161 + detail: { dataType: DataType };
163 162 }
164 163
165 164 export interface SendCommandParams {
... ...
1   -import { FunctionType } from '/@/views/device/profiles/step/cpns/physical/cpns/config';
  1 +import {
  2 + DataTypeEnum,
  3 + FunctionType,
  4 +} from '/@/views/device/profiles/step/cpns/physical/cpns/config';
2 5
3 6 export interface Specs {
4 7 min: string;
... ... @@ -16,7 +19,7 @@ export interface Specs {
16 19 }
17 20
18 21 export interface DataType {
19   - type: string;
  22 + type: DataTypeEnum;
20 23 specs?: Partial<Specs> | StructJSON[];
21 24 }
22 25
... ...
... ... @@ -3,7 +3,7 @@ import { findDictItemByCode } from '/@/api/system/dict';
3 3 import { FormSchema } from '/@/components/Table';
4 4 import { FormField } from '/@/views/device/profiles/step/cpns/physical/cpns/config';
5 5
6   -export enum DateTypeEnum {
  6 +export enum DataTypeEnum {
7 7 IS_NUMBER_INT = 'INT',
8 8 IS_NUMBER_DOUBLE = 'DOUBLE',
9 9 IS_STRING = 'TEXT',
... ... @@ -84,8 +84,8 @@ export const formSchemas: FormSchema[] = [
84 84 span: 18,
85 85 },
86 86 ifShow: ({ values }) =>
87   - values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_INT ||
88   - values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_DOUBLE,
  87 + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_INT ||
  88 + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_DOUBLE,
89 89 rules: [{ validator: validateValueRange }],
90 90 },
91 91 {
... ... @@ -104,8 +104,8 @@ export const formSchemas: FormSchema[] = [
104 104 },
105 105 },
106 106 ifShow: ({ values }) =>
107   - values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_INT ||
108   - values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_DOUBLE,
  107 + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_INT ||
  108 + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_DOUBLE,
109 109 dynamicRules: ({ model }) => {
110 110 const valueRange = model[FormField.VALUE_RANGE] || {};
111 111 const { min = 0, max = 0 } = valueRange;
... ... @@ -166,8 +166,8 @@ export const formSchemas: FormSchema[] = [
166 166 };
167 167 },
168 168 ifShow: ({ values }) =>
169   - values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_INT ||
170   - values[FormField.TYPE] === DateTypeEnum.IS_NUMBER_DOUBLE,
  169 + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_INT ||
  170 + values[FormField.TYPE] === DataTypeEnum.IS_NUMBER_DOUBLE,
171 171 },
172 172 {
173 173 field: FormField.BOOL_CLOSE,
... ... @@ -180,7 +180,7 @@ export const formSchemas: FormSchema[] = [
180 180 componentProps: {
181 181 placeholder: '如:关',
182 182 },
183   - ifShow: ({ values }) => values[FormField.TYPE] === DateTypeEnum.IS_BOOL,
  183 + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_BOOL,
184 184 dynamicRules: ({ model }) => {
185 185 const close = model[FormField.BOOL_CLOSE];
186 186 const open = model[FormField.BOOL_OPEN];
... ... @@ -205,7 +205,7 @@ export const formSchemas: FormSchema[] = [
205 205 componentProps: {
206 206 placeholder: '如:开',
207 207 },
208   - ifShow: ({ values }) => values[FormField.TYPE] === DateTypeEnum.IS_BOOL,
  208 + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_BOOL,
209 209 dynamicRules: ({ model }) => {
210 210 const close = model[FormField.BOOL_CLOSE];
211 211 const open = model[FormField.BOOL_OPEN];
... ... @@ -236,7 +236,7 @@ export const formSchemas: FormSchema[] = [
236 236 suffix: () => '字节',
237 237 };
238 238 },
239   - ifShow: ({ values }) => values[FormField.TYPE] === DateTypeEnum.IS_STRING,
  239 + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_STRING,
240 240 },
241 241 {
242 242 field: FormField.ACCESS_MODE,
... ... @@ -264,7 +264,7 @@ export const formSchemas: FormSchema[] = [
264 264 valueField: 'value',
265 265 changeEvent: 'update:value',
266 266 colProps: { span: 24 },
267   - ifShow: ({ values }) => values[FormField.TYPE] === DateTypeEnum.IS_STRUCT,
  267 + ifShow: ({ values }) => values[FormField.TYPE] === DataTypeEnum.IS_STRUCT,
268 268 rules: [{ required: true, validator: validateJSON }],
269 269 },
270 270 {
... ...
1   -import { DateTypeEnum } from './config';
  1 +import { DataTypeEnum } from './config';
2 2 import { StructJSON } from '/@/api/device/model/modelOfMatterModel';
3 3 import { FormField } from '/@/views/device/profiles/step/cpns/physical/cpns/config';
4 4
... ... @@ -14,7 +14,7 @@ export interface OpenModalParams {
14 14
15 15 export interface StructFormValue
16 16 extends Partial<Record<Exclude<FormField, FormField.VALUE_RANGE | FormField.STRUCT>, string>> {
17   - [FormField.TYPE]: DateTypeEnum;
  17 + [FormField.TYPE]: DataTypeEnum;
18 18 [FormField.VALUE_RANGE]?: {
19 19 [FormField.MIN]: string;
20 20 [FormField.MAX]: string;
... ...
1 1 import { cloneDeep } from 'lodash-es';
2   -import { DateTypeEnum } from './config';
  2 +import { DataTypeEnum } from './config';
3 3 import { StructFormValue } from './type';
4 4 import { DataType, ModelOfMatterParams, StructJSON } from '/@/api/device/model/modelOfMatterModel';
5 5 import { isArray } from '/@/utils/is';
... ... @@ -24,21 +24,21 @@ export function transfromToStructJSON(value: StructFormValue): StructJSON {
24 24 let dataType = {} as unknown as DataType;
25 25
26 26 switch (type) {
27   - case DateTypeEnum.IS_NUMBER_INT:
  27 + case DataTypeEnum.IS_NUMBER_INT:
28 28 dataType = {
29 29 type,
30 30 specs: { valueRange, step, unit, unitName },
31 31 };
32 32 break;
33 33
34   - case DateTypeEnum.IS_NUMBER_DOUBLE:
  34 + case DataTypeEnum.IS_NUMBER_DOUBLE:
35 35 dataType = {
36 36 type,
37 37 specs: { valueRange, step, unit, unitName },
38 38 };
39 39 break;
40 40
41   - case DateTypeEnum.IS_BOOL:
  41 + case DataTypeEnum.IS_BOOL:
42 42 dataType = {
43 43 type,
44 44 specs: {
... ... @@ -48,14 +48,14 @@ export function transfromToStructJSON(value: StructFormValue): StructJSON {
48 48 };
49 49 break;
50 50
51   - case DateTypeEnum.IS_STRING:
  51 + case DataTypeEnum.IS_STRING:
52 52 dataType = {
53 53 type,
54 54 specs: { length },
55 55 };
56 56 break;
57 57
58   - case DateTypeEnum.IS_STRUCT:
  58 + case DataTypeEnum.IS_STRUCT:
59 59 dataType = {
60 60 type,
61 61 specs: specs! as unknown as ModelOfMatterParams[],
... ...
1 1 <script lang="ts" setup>
2   - import { nextTick, onMounted, onUnmounted, Ref, ref, unref } from 'vue';
  2 + import { computed, nextTick, onMounted, onUnmounted, Ref, ref, unref } from 'vue';
3 3 import { getDeviceHistoryInfo } from '/@/api/alarm/position';
4   - import { Empty, Spin } from 'ant-design-vue';
  4 + import { Empty, Spin, Tooltip, Button } from 'ant-design-vue';
5 5 import { useECharts } from '/@/hooks/web/useECharts';
6 6 import { AggregateDataEnum, selectDeviceAttrSchema } from '/@/views/device/localtion/config.data';
7 7 import { useTimePeriodForm } from '/@/views/device/localtion/cpns/TimePeriodForm';
... ... @@ -11,6 +11,10 @@
11 11 import { useGridLayout } from '/@/hooks/component/useGridLayout';
12 12 import { ColEx } from '/@/components/Form/src/types';
13 13 import { useHistoryData } from '../../hook/useHistoryData';
  14 + import { formatToDateTime } from '/@/utils/dateUtil';
  15 + import { useTable, BasicTable } from '/@/components/Table';
  16 + import { LineChartOutlined, BarsOutlined } from '@ant-design/icons-vue';
  17 + import { DataTypeEnum } from '/@/components/Form/src/externalCompns/components/StructForm/config';
14 18
15 19 interface DeviceDetail {
16 20 tbDeviceId: string;
... ... @@ -22,15 +26,33 @@
22 26 attr?: string;
23 27 }>();
24 28
  29 + enum Mode {
  30 + TABLE = 'table',
  31 + CHART = 'chart',
  32 + }
  33 +
  34 + const mode = ref<Mode>(Mode.CHART);
  35 +
25 36 const chartRef = ref();
26 37
27 38 const loading = ref(false);
28 39
29 40 const isNull = ref(false);
30 41
  42 + const historyData = ref<{ ts: number; value: string; name: string }[]>([]);
  43 +
31 44 const { deviceAttrs, getDeviceKeys, getSearchParams, setChartOptions, getDeviceAttribute } =
32 45 useHistoryData();
33 46
  47 + const getIdentifierNameMapping = computed(() => {
  48 + const mapping = {};
  49 + unref(deviceAttrs).forEach((item) => {
  50 + const { identifier, name } = item;
  51 + mapping[identifier] = name;
  52 + });
  53 + return mapping;
  54 + });
  55 +
34 56 function hasDeviceAttr() {
35 57 if (!unref(deviceAttrs).length) {
36 58 return false;
... ... @@ -39,6 +61,34 @@
39 61 }
40 62 }
41 63
  64 + const [registerTable] = useTable({
  65 + showIndexColumn: false,
  66 + showTableSetting: false,
  67 + dataSource: historyData,
  68 + maxHeight: 300,
  69 + size: 'small',
  70 + columns: [
  71 + {
  72 + title: '属性',
  73 + dataIndex: 'name',
  74 + format: (text) => {
  75 + return unref(getIdentifierNameMapping)[text];
  76 + },
  77 + },
  78 + {
  79 + title: '值',
  80 + dataIndex: 'value',
  81 + },
  82 + {
  83 + title: '更新时间',
  84 + dataIndex: 'ts',
  85 + format: (val) => {
  86 + return formatToDateTime(val, 'YYYY-MM-DD HH:mm:ss');
  87 + },
  88 + },
  89 + ],
  90 + });
  91 +
42 92 const { setOptions, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>);
43 93
44 94 const [register, method] = useTimePeriodForm({
... ... @@ -57,6 +107,7 @@
57 107 ...searchParams,
58 108 entityId: props.deviceDetail.tbDeviceId,
59 109 });
  110 + historyData.value = getTableHistoryData(res);
60 111 // 判断数据对象是否为空
61 112 if (!Object.keys(res).length) {
62 113 isNull.value = false;
... ... @@ -74,11 +125,36 @@
74 125 },
75 126 });
76 127
  128 + const getTableHistoryData = (record: Recordable<{ ts: number; value: string }[]>) => {
  129 + const keys = Object.keys(record);
  130 + const list = keys.reduce((prev, next) => {
  131 + const list = record[next].map((item) => {
  132 + return {
  133 + ...item,
  134 + name: next,
  135 + };
  136 + });
  137 + return [...prev, ...list];
  138 + }, []);
  139 + return list;
  140 + };
  141 +
77 142 const getDeviceDataKey = async () => {
78 143 try {
79 144 await getDeviceAttribute(props.deviceDetail);
80 145 if (props.attr) {
81 146 method.setFieldsValue({ keys: props.attr });
  147 + const attrInfo = unref(deviceAttrs).find((item) => item.identifier === props.attr);
  148 + console.log({ attrInfo });
  149 + if (
  150 + [DataTypeEnum.IS_STRING, DataTypeEnum.IS_STRUCT].includes(
  151 + attrInfo?.detail.dataType.type as unknown as DataTypeEnum
  152 + )
  153 + ) {
  154 + mode.value = Mode.TABLE;
  155 + } else {
  156 + mode.value = Mode.CHART;
  157 + }
82 158 }
83 159 } catch (error) {}
84 160 };
... ... @@ -110,6 +186,7 @@
110 186 agg: AggregateDataEnum.NONE,
111 187 limit: 7,
112 188 });
  189 + historyData.value = getTableHistoryData(res);
113 190
114 191 // 判断对象是否为空
115 192 if (!Object.keys(res).length) {
... ... @@ -123,6 +200,10 @@
123 200 setOptions(setChartOptions(res, selectedKeys));
124 201 };
125 202
  203 + const switchMode = (flag: Mode) => {
  204 + mode.value = flag;
  205 + };
  206 +
126 207 onMounted(async () => {
127 208 await getDeviceDataKey();
128 209 await openHistoryPanel();
... ... @@ -139,10 +220,60 @@
139 220 <TimePeriodForm @register="register" />
140 221 </section>
141 222 <section class="bg-white p-3">
142   - <div v-show="isNull" ref="chartRef" :style="{ height: '400px', width: '100%' }">
143   - <Spin :spinning="loading" :absolute="true" />
144   - </div>
145   - <Empty v-show="!isNull" />
  223 + <Spin :spinning="loading" :absolute="true">
  224 + <div v-show="mode === Mode.CHART" class="flex h-70px items-center justify-end p-2">
  225 + <Tooltip title="图表模式">
  226 + <Button
  227 + :class="[mode === Mode.CHART && '!bg-blue-500 svg:text-light-50']"
  228 + class="!p-2 !children:flex flex justify-center items-center border-r-0"
  229 + @click="switchMode(Mode.CHART)"
  230 + >
  231 + <LineChartOutlined />
  232 + </Button>
  233 + </Tooltip>
  234 +
  235 + <Tooltip title="列表模式">
  236 + <Button
  237 + class="!p-2 !children:flex flex justify-center items-center"
  238 + @click="switchMode(Mode.TABLE)"
  239 + >
  240 + <BarsOutlined />
  241 + </Button>
  242 + </Tooltip>
  243 + </div>
  244 + <div
  245 + v-show="isNull && mode === Mode.CHART"
  246 + ref="chartRef"
  247 + :style="{ height: '400px', width: '100%' }"
  248 + >
  249 + </div>
  250 + <Empty v-show="!isNull && mode === Mode.CHART" />
  251 +
  252 + <BasicTable v-show="mode === Mode.TABLE" @register="registerTable">
  253 + <template #toolbar>
  254 + <div v-show="mode === Mode.TABLE" class="flex h-70px items-center justify-end p-2">
  255 + <Tooltip title="图表模式">
  256 + <Button
  257 + class="!p-2 !children:flex flex justify-center items-center border-r-0"
  258 + @click="switchMode(Mode.CHART)"
  259 + >
  260 + <LineChartOutlined />
  261 + </Button>
  262 + </Tooltip>
  263 +
  264 + <Tooltip title="列表模式">
  265 + <Button
  266 + :class="[mode === Mode.TABLE && '!bg-blue-500 svg:text-light-50']"
  267 + class="!p-2 !children:flex flex justify-center items-center"
  268 + @click="switchMode(Mode.TABLE)"
  269 + >
  270 + <BarsOutlined />
  271 + </Button>
  272 + </Tooltip>
  273 + </div>
  274 + </template>
  275 + </BasicTable>
  276 + </Spin>
146 277 </section>
147 278 </section>
148 279 </template>
... ...
... ... @@ -18,7 +18,7 @@
18 18 import { computed } from '@vue/reactivity';
19 19 import { Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel';
20 20 import { isArray, isObject } from '/@/utils/is';
21   - import { DateTypeEnum } from '/@/components/Form/src/externalCompns/components/StructForm/config';
  21 + import { DataTypeEnum } from '/@/components/Form/src/externalCompns/components/StructForm/config';
22 22
23 23 interface ReceiveMessage {
24 24 data: {
... ... @@ -136,8 +136,8 @@
136 136 : '';
137 137 };
138 138
139   - const isStructAndTextType = (type: DateTypeEnum) => {
140   - return [DateTypeEnum.IS_STRUCT, DateTypeEnum.IS_STRING].includes(type);
  139 + const isStructAndTextType = (type: DataTypeEnum) => {
  140 + return [DataTypeEnum.IS_STRUCT, DataTypeEnum.IS_STRING].includes(type);
141 141 };
142 142
143 143 const { send, close, data } = useWebSocket(socketInfo.origin, {
... ... @@ -170,7 +170,7 @@
170 170 name,
171 171 unit,
172 172 showHistoryDataButton: !isStructAndTextType(
173   - dataInfo?.detail.dataType?.type as unknown as DateTypeEnum
  173 + dataInfo?.detail.dataType?.type as unknown as DataTypeEnum
174 174 ),
175 175 };
176 176 });
... ... @@ -242,13 +242,7 @@
242 242 <span class="text-base font-normal">{{ item.name }}</span>
243 243 </template>
244 244 <template #extra>
245   - <Button
246   - v-if="item.showHistoryDataButton"
247   - type="link"
248   - class="!p-0"
249   - @click="handleShowDetail(item)"
250   - >历史数据</Button
251   - >
  245 + <Button type="link" class="!p-0" @click="handleShowDetail(item)">历史数据</Button>
252 246 </template>
253 247 <section class="min-h-16 flex flex-col justify-between">
254 248 <div class="flex font-bold text-lg mb-4 gap-2">
... ...
... ... @@ -48,15 +48,66 @@
48 48 @cancel="handleCancelModal"
49 49 >
50 50 <TimePeriodForm @register="timePeriodRegister" />
51   - <!-- <BasicForm @register="registerForm" /> -->
52   - <div v-show="isNull" ref="chartRef" :style="{ height: '550px', width }">
53   - <Loading :loading="loading" :absolute="true" />
54   - </div>
55   - <Empty
56   - :style="{ height: '550px', width }"
57   - class="flex flex-col justify-center items-center"
58   - v-show="!isNull"
59   - />
  51 + <section>
  52 + <Spin :spinning="loading">
  53 + <div v-show="mode === Mode.CHART" class="flex h-70px items-center justify-end p-2">
  54 + <Tooltip title="图表模式">
  55 + <Button
  56 + :class="[mode === Mode.CHART && '!bg-blue-500 svg:text-light-50']"
  57 + class="!p-2 !children:flex flex justify-center items-center border-r-0"
  58 + @click="switchMode(Mode.CHART)"
  59 + >
  60 + <LineChartOutlined />
  61 + </Button>
  62 + </Tooltip>
  63 +
  64 + <Tooltip title="列表模式">
  65 + <Button
  66 + class="!p-2 !children:flex flex justify-center items-center"
  67 + @click="switchMode(Mode.TABLE)"
  68 + >
  69 + <BarsOutlined />
  70 + </Button>
  71 + </Tooltip>
  72 + </div>
  73 + <div
  74 + v-show="isNull && mode === Mode.CHART"
  75 + ref="chartRef"
  76 + :style="{ height: '400px', width }"
  77 + >
  78 + </div>
  79 + <Empty
  80 + :style="{ height: '550px', width }"
  81 + class="flex flex-col justify-center items-center"
  82 + v-show="!isNull && mode === Mode.CHART"
  83 + />
  84 +
  85 + <BasicTable v-show="mode === Mode.TABLE" @register="registerAttrTable">
  86 + <template #toolbar>
  87 + <div v-show="mode === Mode.TABLE" class="flex h-70px items-center justify-end p-2">
  88 + <Tooltip title="图表模式">
  89 + <Button
  90 + class="!p-2 !children:flex flex justify-center items-center border-r-0"
  91 + @click="switchMode(Mode.CHART)"
  92 + >
  93 + <LineChartOutlined />
  94 + </Button>
  95 + </Tooltip>
  96 +
  97 + <Tooltip title="列表模式">
  98 + <Button
  99 + :class="[mode === Mode.TABLE && '!bg-blue-500 svg:text-light-50']"
  100 + class="!p-2 !children:flex flex justify-center items-center"
  101 + @click="switchMode(Mode.TABLE)"
  102 + >
  103 + <BarsOutlined />
  104 + </Button>
  105 + </Tooltip>
  106 + </div>
  107 + </template>
  108 + </BasicTable>
  109 + </Spin>
  110 + </section>
60 111 </BasicModal>
61 112 <DeviceDetailDrawer
62 113 @register="registerDetailDrawer"
... ... @@ -69,12 +120,21 @@
69 120 </div>
70 121 </template>
71 122 <script lang="ts">
72   - import { defineComponent, ref, nextTick, unref, onMounted, Ref, onUnmounted } from 'vue';
  123 + import {
  124 + defineComponent,
  125 + ref,
  126 + nextTick,
  127 + unref,
  128 + onMounted,
  129 + Ref,
  130 + onUnmounted,
  131 + computed,
  132 + } from 'vue';
73 133 import { useScript } from '/@/hooks/web/useScript';
74 134 import { formSchema, columns } from './config.data';
75 135 import { BasicTable, useTable } from '/@/components/Table';
76 136 import { devicePage } from '/@/api/alarm/contact/alarmContact';
77   - import { Tag, Empty } from 'ant-design-vue';
  137 + import { Tag, Empty, Spin, Tooltip, Button } from 'ant-design-vue';
78 138 import { DeviceState } from '/@/api/device/model/deviceModel';
79 139 import { BAI_DU_MAP_URL } from '/@/utils/fnUtils';
80 140 import { useModal, BasicModal } from '/@/components/Modal';
... ... @@ -91,14 +151,14 @@
91 151 import djh from '/@/assets/images/djh.png';
92 152 import online from '/@/assets/images/online1.png';
93 153 import lx1 from '/@/assets/images/lx1.png';
94   - import Loading from '/@/components/Loading/src/Loading.vue';
95 154 import { TimePeriodForm, useTimePeriodForm } from './cpns/TimePeriodForm';
96 155 import { selectDeviceAttrSchema } from './config.data';
97 156 import { defaultSchemas } from './cpns/TimePeriodForm/config';
98 157 import { QueryWay, SchemaFiled, AggregateDataEnum } from './cpns/TimePeriodForm/config';
99   - import { Spin } from 'ant-design-vue';
100 158 import { useAsyncQueue } from './useAsyncQueue';
101 159 import { useHistoryData } from '../list/hook/useHistoryData';
  160 + import { LineChartOutlined, BarsOutlined } from '@ant-design/icons-vue';
  161 + import { formatToDateTime } from '/@/utils/dateUtil';
102 162
103 163 interface DeviceInfo {
104 164 alarmStatus: 0 | 1;
... ... @@ -121,9 +181,12 @@
121 181 Empty,
122 182 BasicModal,
123 183 DeviceDetailDrawer,
124   - Loading,
125 184 TimePeriodForm,
126 185 Spin,
  186 + Tooltip,
  187 + Button,
  188 + LineChartOutlined,
  189 + BarsOutlined,
127 190 },
128 191 props: {
129 192 width: {
... ... @@ -136,6 +199,12 @@
136 199 },
137 200 },
138 201 setup() {
  202 + enum Mode {
  203 + TABLE = 'table',
  204 + CHART = 'chart',
  205 + }
  206 +
  207 + const mode = ref<Mode>(Mode.CHART);
139 208 let entityId = '';
140 209 let globalRecord: any = {};
141 210 const wrapRef = ref<HTMLDivElement | null>(null);
... ... @@ -149,11 +218,64 @@
149 218 const [registerModal, { openModal }] = useModal();
150 219 const BMapInstance = ref<Nullable<any>>(null);
151 220
  221 + const historyData = ref<{ ts: number; value: string; name: string }[]>([]);
  222 +
152 223 const loading = ref(false);
153 224
154 225 const { deviceAttrs, getDeviceKeys, getDeviceAttribute, getSearchParams, setChartOptions } =
155 226 useHistoryData();
156 227
  228 + const getTableHistoryData = (record: Recordable<{ ts: number; value: string }[]>) => {
  229 + const keys = Object.keys(record);
  230 + const list = keys.reduce((prev, next) => {
  231 + const list = record[next].map((item) => {
  232 + return {
  233 + ...item,
  234 + name: next,
  235 + };
  236 + });
  237 + return [...prev, ...list];
  238 + }, []);
  239 + return list;
  240 + };
  241 +
  242 + const getIdentifierNameMapping = computed(() => {
  243 + const mapping = {};
  244 + unref(deviceAttrs).forEach((item) => {
  245 + const { identifier, name } = item;
  246 + mapping[identifier] = name;
  247 + });
  248 + return mapping;
  249 + });
  250 +
  251 + const [registerAttrTable] = useTable({
  252 + showIndexColumn: false,
  253 + showTableSetting: false,
  254 + dataSource: historyData,
  255 + maxHeight: 300,
  256 + size: 'small',
  257 + columns: [
  258 + {
  259 + title: '属性',
  260 + dataIndex: 'name',
  261 + format: (text) => {
  262 + return unref(getIdentifierNameMapping)[text];
  263 + },
  264 + },
  265 + {
  266 + title: '值',
  267 + dataIndex: 'value',
  268 + },
  269 + {
  270 + title: '更新时间',
  271 + dataIndex: 'ts',
  272 + format: (val) => {
  273 + return formatToDateTime(val, 'YYYY-MM-DD HH:mm:ss');
  274 + },
  275 + },
  276 + ],
  277 + });
  278 +
157 279 const [registerTable] = useTable({
158 280 api: devicePage,
159 281 columns,
... ... @@ -352,6 +474,7 @@
352 474 loading.value = true;
353 475 const res = await getDeviceHistoryInfo({ ...searchParams, entityId });
354 476 loading.value = false;
  477 + historyData.value = getTableHistoryData(res);
355 478 // 判断数据对象是否为空
356 479 if (!Object.keys(res).length) {
357 480 isNull.value = false;
... ... @@ -397,6 +520,7 @@
397 520 limit: 7,
398 521 });
399 522
  523 + historyData.value = getTableHistoryData(res);
400 524 // 判断对象是否为空
401 525 if (!Object.keys(res).length) {
402 526 isNull.value = false;
... ... @@ -447,7 +571,13 @@
447 571 openGatewayDetailDrawer(true, data);
448 572 };
449 573
  574 + const switchMode = (flag: Mode) => {
  575 + mode.value = flag;
  576 + };
  577 +
450 578 return {
  579 + mode,
  580 + Mode,
451 581 wrapRef,
452 582 registerTable,
453 583 deviceRowClick,
... ... @@ -464,6 +594,8 @@
464 594 registerGatewayDetailDrawer,
465 595 handleOpenTbDeviceDetail,
466 596 handleOpenGatewayDetail,
  597 + switchMode,
  598 + registerAttrTable,
467 599 };
468 600 },
469 601 });
... ...
... ... @@ -42,7 +42,7 @@ export enum AssessMode {
42 42 /**
43 43 * 新增参数 动态显示表单
44 44 */
45   -export enum DateTypeEnum {
  45 +export enum DataTypeEnum {
46 46 IS_NUMBER_INT = 'INT',
47 47 IS_NUMBER_DOUBLE = 'DOUBLE',
48 48 IS_STRING = 'TEXT',
... ... @@ -51,18 +51,18 @@ export enum DateTypeEnum {
51 51 }
52 52
53 53 const isNumber = (type: string) => {
54   - return type === DateTypeEnum.IS_NUMBER_INT || type === DateTypeEnum.IS_NUMBER_DOUBLE;
  54 + return type === DataTypeEnum.IS_NUMBER_INT || type === DataTypeEnum.IS_NUMBER_DOUBLE;
55 55 };
56 56
57 57 const isString = (type: string) => {
58   - return type === DateTypeEnum.IS_STRING;
  58 + return type === DataTypeEnum.IS_STRING;
59 59 };
60 60 const isStruct = (type: string) => {
61   - return type === DateTypeEnum.IS_STRUCT;
  61 + return type === DataTypeEnum.IS_STRUCT;
62 62 };
63 63
64 64 const isBool = (type: string) => {
65   - return type === DateTypeEnum.IS_BOOL;
  65 + return type === DataTypeEnum.IS_BOOL;
66 66 };
67 67
68 68 export const serviceSchemas = (tcpDeviceFlag: boolean): FormSchema[] => {
... ...
1 1 <script lang="ts" setup>
2   - import { nextTick, Ref, ref, unref } from 'vue';
  2 + import { computed, nextTick, Ref, ref, unref } from 'vue';
3 3 import { getDeviceHistoryInfo } from '/@/api/alarm/position';
4   - import { Empty, Tooltip, Button } from 'ant-design-vue';
  4 + import { Empty, Tooltip, Button, Spin } from 'ant-design-vue';
5 5 import { useECharts } from '/@/hooks/web/useECharts';
6 6 import { AggregateDataEnum } from '/@/views/device/localtion/config.data';
7 7 import { useGridLayout } from '/@/hooks/component/useGridLayout';
... ... @@ -9,7 +9,6 @@
9 9 import { DataSource } from '/@/api/dataBoard/model';
10 10 import { useForm, BasicForm } from '/@/components/Form';
11 11 import { formSchema, SchemaFiled } from '../config/historyTrend.config';
12   - import { Loading } from '/@/components/Loading';
13 12 import BasicModal from '/@/components/Modal/src/BasicModal.vue';
14 13 import { useModalInner } from '/@/components/Modal';
15 14 import { getAllDeviceByOrg } from '/@/api/dataBoard';
... ... @@ -43,11 +42,7 @@
43 42 const { setOptions, destory } = useECharts(chartRef as Ref<HTMLDivElement>);
44 43
45 44 function hasDeviceAttr() {
46   - if (!unref(deviceAttrs).length) {
47   - return false;
48   - } else {
49   - return true;
50   - }
  45 + return !!unref(deviceAttrs).length;
51 46 }
52 47
53 48 const [register, method] = useForm({
... ... @@ -107,6 +102,15 @@
107 102 return list;
108 103 };
109 104
  105 + const getIdentifierNameMapping = computed(() => {
  106 + const mapping = {};
  107 + unref(deviceAttrs).forEach((item) => {
  108 + const { identifier, name } = item;
  109 + mapping[identifier] = name;
  110 + });
  111 + return mapping;
  112 + });
  113 +
110 114 const [registerTable] = useTable({
111 115 showIndexColumn: false,
112 116 showTableSetting: false,
... ... @@ -117,6 +121,9 @@
117 121 {
118 122 title: '属性',
119 123 dataIndex: 'name',
  124 + format: (value) => {
  125 + return unref(getIdentifierNameMapping)[value];
  126 + },
120 127 },
121 128 {
122 129 title: '值',
... ... @@ -173,7 +180,7 @@
173 180 });
174 181 historyData.value = getTableHistoryData(res);
175 182 // 判断对象是否为空
176   - if (!Object.keys(unref(historyData)).length) {
  183 + if (!Object.keys(res).length) {
177 184 isNull.value = false;
178 185 return;
179 186 } else {
... ... @@ -261,65 +268,66 @@
261 268 <BasicForm @register="register" />
262 269 </section>
263 270 <section class="bg-white p-3" style="min-height: 350px">
264   - <div v-show="mode === Mode.CHART" class="flex h-70px items-center justify-end p-2">
265   - <Tooltip title="图表模式">
266   - <Button
267   - :class="[mode === Mode.CHART && '!bg-blue-500 svg:text-light-50']"
268   - class="!p-2 !children:flex flex justify-center items-center border-r-0"
269   - @click="switchMode(Mode.CHART)"
270   - >
271   - <LineChartOutlined />
272   - </Button>
273   - </Tooltip>
274   -
275   - <Tooltip title="列表模式">
276   - <Button
277   - class="!p-2 !children:flex flex justify-center items-center"
278   - @click="switchMode(Mode.TABLE)"
279   - >
280   - <BarsOutlined />
281   - </Button>
282   - </Tooltip>
283   - </div>
284   -
285   - <div
286   - v-show="isNull && mode === Mode.CHART"
287   - ref="chartRef"
288   - :style="{ height: '350px', width: '100%' }"
289   - >
290   - <Loading :loading="loading" :absolute="true" />
291   - </div>
292   - <Empty
293   - v-if="mode === Mode.CHART"
294   - class="h-350px flex flex-col justify-center items-center"
295   - description="暂无数据,请选择设备查询"
296   - v-show="!isNull"
297   - />
298   -
299   - <BasicTable v-show="mode === Mode.TABLE" @register="registerTable">
300   - <template #toolbar>
301   - <div v-show="mode === Mode.TABLE" class="flex h-70px items-center justify-end p-2">
302   - <Tooltip title="图表模式">
303   - <Button
304   - class="!p-2 !children:flex flex justify-center items-center border-r-0"
305   - @click="switchMode(Mode.CHART)"
306   - >
307   - <LineChartOutlined />
308   - </Button>
309   - </Tooltip>
310   -
311   - <Tooltip title="列表模式">
312   - <Button
313   - :class="[mode === Mode.TABLE && '!bg-blue-500 svg:text-light-50']"
314   - class="!p-2 !children:flex flex justify-center items-center"
315   - @click="switchMode(Mode.TABLE)"
316   - >
317   - <BarsOutlined />
318   - </Button>
319   - </Tooltip>
320   - </div>
321   - </template>
322   - </BasicTable>
  271 + <Spin :spinning="loading" :absolute="true">
  272 + <div v-show="mode === Mode.CHART" class="flex h-70px items-center justify-end p-2">
  273 + <Tooltip title="图表模式">
  274 + <Button
  275 + :class="[mode === Mode.CHART && '!bg-blue-500 svg:text-light-50']"
  276 + class="!p-2 !children:flex flex justify-center items-center border-r-0"
  277 + @click="switchMode(Mode.CHART)"
  278 + >
  279 + <LineChartOutlined />
  280 + </Button>
  281 + </Tooltip>
  282 +
  283 + <Tooltip title="列表模式">
  284 + <Button
  285 + class="!p-2 !children:flex flex justify-center items-center"
  286 + @click="switchMode(Mode.TABLE)"
  287 + >
  288 + <BarsOutlined />
  289 + </Button>
  290 + </Tooltip>
  291 + </div>
  292 +
  293 + <div
  294 + v-show="isNull && mode === Mode.CHART"
  295 + ref="chartRef"
  296 + :style="{ height: '350px', width: '100%' }"
  297 + >
  298 + </div>
  299 + <Empty
  300 + v-if="mode === Mode.CHART"
  301 + class="h-350px flex flex-col justify-center items-center"
  302 + description="暂无数据,请选择设备查询"
  303 + v-show="!isNull"
  304 + />
  305 +
  306 + <BasicTable v-show="mode === Mode.TABLE" @register="registerTable">
  307 + <template #toolbar>
  308 + <div v-show="mode === Mode.TABLE" class="flex h-70px items-center justify-end p-2">
  309 + <Tooltip title="图表模式">
  310 + <Button
  311 + class="!p-2 !children:flex flex justify-center items-center border-r-0"
  312 + @click="switchMode(Mode.CHART)"
  313 + >
  314 + <LineChartOutlined />
  315 + </Button>
  316 + </Tooltip>
  317 +
  318 + <Tooltip title="列表模式">
  319 + <Button
  320 + :class="[mode === Mode.TABLE && '!bg-blue-500 svg:text-light-50']"
  321 + class="!p-2 !children:flex flex justify-center items-center"
  322 + @click="switchMode(Mode.TABLE)"
  323 + >
  324 + <BarsOutlined />
  325 + </Button>
  326 + </Tooltip>
  327 + </div>
  328 + </template>
  329 + </BasicTable>
  330 + </Spin>
323 331 </section>
324 332 </section>
325 333 </BasicModal>
... ...