Commit 179744a60385270a0ab088ad8d1daa6b93f53823

Authored by ww
1 parent 5e373602

feat: data component history trend add table mode

@@ -289,7 +289,7 @@ @@ -289,7 +289,7 @@
289 <Alert type="info" show-icon v-if="isMapComponent"> 289 <Alert type="info" show-icon v-if="isMapComponent">
290 <template #description> 290 <template #description>
291 <div> 291 <div>
292 - 地图组件,需绑定两个数据源,且数据源为同一设备。第一数据源为经度,第二数据源为度,否则地图组件不能正常显示。 292 + 地图组件,需绑定两个数据源,且数据源为同一设备。第一数据源为经度,第二数据源为度,否则地图组件不能正常显示。
293 </div> 293 </div>
294 </template> 294 </template>
295 </Alert> 295 </Alert>
1 <script lang="ts" setup> 1 <script lang="ts" setup>
2 import { nextTick, Ref, ref, unref } from 'vue'; 2 import { nextTick, Ref, ref, unref } from 'vue';
3 import { getDeviceHistoryInfo } from '/@/api/alarm/position'; 3 import { getDeviceHistoryInfo } from '/@/api/alarm/position';
4 - import { Empty } from 'ant-design-vue'; 4 + import { Empty, Tooltip, Button } from 'ant-design-vue';
5 import { useECharts } from '/@/hooks/web/useECharts'; 5 import { useECharts } from '/@/hooks/web/useECharts';
6 import { AggregateDataEnum } from '/@/views/device/localtion/config.data'; 6 import { AggregateDataEnum } from '/@/views/device/localtion/config.data';
7 import { useGridLayout } from '/@/hooks/component/useGridLayout'; 7 import { useGridLayout } from '/@/hooks/component/useGridLayout';
@@ -14,17 +14,29 @@ @@ -14,17 +14,29 @@
14 import { useModalInner } from '/@/components/Modal'; 14 import { useModalInner } from '/@/components/Modal';
15 import { getAllDeviceByOrg } from '/@/api/dataBoard'; 15 import { getAllDeviceByOrg } from '/@/api/dataBoard';
16 import { useHistoryData } from '/@/views/device/list/hook/useHistoryData'; 16 import { useHistoryData } from '/@/views/device/list/hook/useHistoryData';
  17 + import { BasicTable, useTable } from '/@/components/Table';
  18 + import { LineChartOutlined, BarsOutlined } from '@ant-design/icons-vue';
  19 + import { formatToDateTime } from '/@/utils/dateUtil';
17 20
18 type DeviceOption = Record<'label' | 'value' | 'organizationId', string>; 21 type DeviceOption = Record<'label' | 'value' | 'organizationId', string>;
19 22
20 defineEmits(['register']); 23 defineEmits(['register']);
21 24
  25 + enum Mode {
  26 + TABLE = 'table',
  27 + CHART = 'chart',
  28 + }
  29 +
  30 + const mode = ref<Mode>(Mode.CHART);
  31 +
22 const chartRef = ref(); 32 const chartRef = ref();
23 33
24 const loading = ref(false); 34 const loading = ref(false);
25 35
26 const isNull = ref(false); 36 const isNull = ref(false);
27 37
  38 + const historyData = ref<{ ts: number; value: string; name: string }[]>([]);
  39 +
28 const { deviceAttrs, getDeviceKeys, getSearchParams, setChartOptions, getDeviceAttribute } = 40 const { deviceAttrs, getDeviceKeys, getSearchParams, setChartOptions, getDeviceAttribute } =
29 useHistoryData(); 41 useHistoryData();
30 42
@@ -52,30 +64,74 @@ @@ -52,30 +64,74 @@
52 loading: loading as unknown as boolean, 64 loading: loading as unknown as boolean,
53 }, 65 },
54 async submitFunc() { 66 async submitFunc() {
55 - // 表单验证  
56 - await method.validate();  
57 - const value = method.getFieldsValue();  
58 - const searchParams = getSearchParams(value);  
59 - if (!hasDeviceAttr()) return;  
60 - // 发送请求  
61 - loading.value = true;  
62 - const res = await getDeviceHistoryInfo(searchParams);  
63 - loading.value = false;  
64 - // 判断数据对象是否为空  
65 - if (!Object.keys(res).length) {  
66 - isNull.value = false;  
67 - return;  
68 - } else {  
69 - isNull.value = true;  
70 - }  
71 -  
72 - const selectedKeys = unref(deviceAttrs).find(  
73 - (item) => item.identifier === value[SchemaFiled.KEYS]  
74 - );  
75 - setOptions(setChartOptions(res, selectedKeys)); 67 + search();
76 }, 68 },
77 }); 69 });
78 70
  71 + const search = async () => {
  72 + // 表单验证
  73 + await method.validate();
  74 + const value = method.getFieldsValue();
  75 + const searchParams = getSearchParams(value);
  76 + if (!hasDeviceAttr()) return;
  77 + // 发送请求
  78 + loading.value = true;
  79 + const res = await getDeviceHistoryInfo(searchParams);
  80 + historyData.value = getTableHistoryData(res);
  81 + loading.value = false;
  82 + // 判断数据对象是否为空
  83 + if (!Object.keys(res).length) {
  84 + isNull.value = false;
  85 + return;
  86 + } else {
  87 + isNull.value = true;
  88 + }
  89 +
  90 + const selectedKeys = unref(deviceAttrs).find(
  91 + (item) => item.identifier === value[SchemaFiled.KEYS]
  92 + );
  93 + setOptions(setChartOptions(res, selectedKeys));
  94 + };
  95 +
  96 + const getTableHistoryData = (record: Recordable<{ ts: number; value: string }[]>) => {
  97 + const keys = Object.keys(record);
  98 + const list = keys.reduce((prev, next) => {
  99 + const list = record[next].map((item) => {
  100 + return {
  101 + ...item,
  102 + name: next,
  103 + };
  104 + });
  105 + return [...prev, ...list];
  106 + }, []);
  107 + return list;
  108 + };
  109 +
  110 + const [registerTable] = useTable({
  111 + showIndexColumn: false,
  112 + showTableSetting: false,
  113 + dataSource: historyData,
  114 + maxHeight: 300,
  115 + size: 'small',
  116 + columns: [
  117 + {
  118 + title: '属性',
  119 + dataIndex: 'name',
  120 + },
  121 + {
  122 + title: '值',
  123 + dataIndex: 'value',
  124 + },
  125 + {
  126 + title: '更新时间',
  127 + dataIndex: 'ts',
  128 + format: (val) => {
  129 + return formatToDateTime(val, 'YYYY-MM-DD HH:mm:ss');
  130 + },
  131 + },
  132 + ],
  133 + });
  134 +
79 const getDeviceDataKey = async (record: DeviceOption) => { 135 const getDeviceDataKey = async (record: DeviceOption) => {
80 const { organizationId, value } = record; 136 const { organizationId, value } = record;
81 try { 137 try {
@@ -115,9 +171,9 @@ @@ -115,9 +171,9 @@
115 agg: AggregateDataEnum.NONE, 171 agg: AggregateDataEnum.NONE,
116 limit: 7, 172 limit: 7,
117 }); 173 });
118 - 174 + historyData.value = getTableHistoryData(res);
119 // 判断对象是否为空 175 // 判断对象是否为空
120 - if (!Object.keys(res).length) { 176 + if (!Object.keys(unref(historyData)).length) {
121 isNull.value = false; 177 isNull.value = false;
122 return; 178 return;
123 } else { 179 } else {
@@ -181,6 +237,10 @@ @@ -181,6 +237,10 @@
181 const handleCancel = () => { 237 const handleCancel = () => {
182 destory(); 238 destory();
183 }; 239 };
  240 +
  241 + const switchMode = (flag: Mode) => {
  242 + mode.value = flag;
  243 + };
184 </script> 244 </script>
185 245
186 <template> 246 <template>
@@ -201,14 +261,65 @@ @@ -201,14 +261,65 @@
201 <BasicForm @register="register" /> 261 <BasicForm @register="register" />
202 </section> 262 </section>
203 <section class="bg-white p-3" style="min-height: 350px"> 263 <section class="bg-white p-3" style="min-height: 350px">
204 - <div v-show="isNull" ref="chartRef" :style="{ height: '350px', width: '100%' }"> 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 + >
205 <Loading :loading="loading" :absolute="true" /> 290 <Loading :loading="loading" :absolute="true" />
206 </div> 291 </div>
207 <Empty 292 <Empty
  293 + v-if="mode === Mode.CHART"
208 class="h-350px flex flex-col justify-center items-center" 294 class="h-350px flex flex-col justify-center items-center"
209 description="暂无数据,请选择设备查询" 295 description="暂无数据,请选择设备查询"
210 v-show="!isNull" 296 v-show="!isNull"
211 /> 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>
212 </section> 323 </section>
213 </section> 324 </section>
214 </BasicModal> 325 </BasicModal>