Commit 179744a60385270a0ab088ad8d1daa6b93f53823
1 parent
5e373602
feat: data component history trend add table mode
Showing
2 changed files
with
137 additions
and
26 deletions
| @@ -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> |