Commit 6f9ac029a1fbb6420ba06f83a2762dbdbbd37a1f
1 parent
e535013c
feat: data dashboard data source add slave device field
Showing
12 changed files
with
108 additions
and
85 deletions
1 | +import { RadioRecord } from '/@/views/data/board/detail/config/util'; | |
2 | + | |
1 | 3 | export interface AddDataBoardParams { |
2 | 4 | name: string; |
3 | 5 | viewType: string; |
... | ... | @@ -75,6 +77,13 @@ export interface DataSource { |
75 | 77 | slaveDeviceId: string; |
76 | 78 | isGatewayDevice: boolean; |
77 | 79 | componentInfo: ComponentInfo; |
80 | + deviceName?: string; | |
81 | + | |
82 | + // front usage | |
83 | + uuid?: string; | |
84 | + width?: number; | |
85 | + height?: number; | |
86 | + radio?: RadioRecord; | |
78 | 87 | } |
79 | 88 | |
80 | 89 | export interface DataComponentRecord { | ... | ... |
... | ... | @@ -99,7 +99,7 @@ |
99 | 99 | |
100 | 100 | <template> |
101 | 101 | <div class="flex flex-col w-full h-full min-w-3 min-h-3"> |
102 | - <div :id="getControlsWidgetId()" class="widget-charts flex-auto"></div> | |
102 | + <div :id="getControlsWidgetId()" class="widget-charts min-w-1 min-h-1 flex-auto"></div> | |
103 | 103 | <div> |
104 | 104 | <div class="text-center" :style="{ fontSize: fontSize({ radio: getRadio, basic: 16 }) }">{{ |
105 | 105 | props.value.name | ... | ... |
... | ... | @@ -7,10 +7,12 @@ |
7 | 7 | import { MoreActionEvent } from '../../config/config'; |
8 | 8 | import { computed } from '@vue/reactivity'; |
9 | 9 | import { usePermission } from '/@/hooks/web/usePermission'; |
10 | + import { DataSource } from '/@/api/dataBoard/model'; | |
10 | 11 | |
11 | 12 | const emit = defineEmits(['action']); |
12 | 13 | const props = defineProps<{ |
13 | 14 | id: string; |
15 | + record: DataSource[]; | |
14 | 16 | }>(); |
15 | 17 | const { hasPermission } = usePermission(); |
16 | 18 | const dropMenuList = computed<DropMenu[]>(() => { |
... | ... | @@ -45,20 +47,27 @@ |
45 | 47 | </script> |
46 | 48 | |
47 | 49 | <template> |
48 | - <div class="flex justify-between"> | |
49 | - <div class="flex flex-auto"> | |
50 | - <div v-for="item in 1" class="flex mx-2" :key="item"> | |
51 | - <div class="flex items-center"> | |
50 | + <div class="flex justify-between w-full"> | |
51 | + <div class="flex" :style="{ width: `calc(100% - 60px)` }"> | |
52 | + <div | |
53 | + v-for="(item, index) in props.record" | |
54 | + class="box-border truncate" | |
55 | + :style="{ width: `${100 / props.record.length}%` }" | |
56 | + :key="index" | |
57 | + > | |
58 | + <SvgIcon name="" prefix="iconfont" class="!fill-emerald-400" /> | |
59 | + {{ item.deviceName }} | |
60 | + <!-- <div class="flex items-center"> | |
52 | 61 | <Tooltip> |
53 | 62 | <SvgIcon name="online" prefix="iconfont" class="!fill-emerald-400" /> |
54 | 63 | </Tooltip> |
55 | - <span class="truncate max-w-25 ml-2">设备名称{{ item }}</span> | |
56 | - </div> | |
64 | + <div class="truncate">{{ item.deviceName || item.deviceId }}</div> | |
65 | + </div> --> | |
57 | 66 | </div> |
58 | 67 | </div> |
59 | - <div class="flex items-center wx-9"> | |
68 | + <div class="flex items-center w-10"> | |
60 | 69 | <Tooltip title="趋势"> |
61 | - <LineChartOutlined class="cursor-pointer mx-2" /> | |
70 | + <LineChartOutlined class="cursor-pointer mx-1" /> | |
62 | 71 | </Tooltip> |
63 | 72 | <Dropdown |
64 | 73 | v-if="dropMenuList.length" | ... | ... |
1 | 1 | <script lang="ts" setup> |
2 | - import { onMounted, useSlots } from 'vue'; | |
2 | + import { useSlots } from 'vue'; | |
3 | 3 | import { useUpdateCenter } from '../../hook/useUpdateCenter'; |
4 | - import { DataBoardLayoutInfo } from '../../types/type'; | |
5 | - import type { WidgetWrapperRegister } from './type'; | |
6 | - import { DataSource } from '/@/api/dataBoard/model'; | |
4 | + import { FrontDataSourceRecord } from '../../types/type'; | |
5 | + // import type { WidgetWrapperRegister } from './type'; | |
6 | + // import { DataSource } from '/@/api/dataBoard/model'; | |
7 | 7 | |
8 | 8 | const props = defineProps<{ |
9 | - dataSource: DataBoardLayoutInfo['record'][]; | |
10 | - register?: WidgetWrapperRegister; | |
9 | + dataSource: FrontDataSourceRecord[]; | |
11 | 10 | }>(); |
12 | 11 | |
13 | 12 | const slot = useSlots(); |
14 | 13 | |
15 | 14 | const { update, add, remove } = useUpdateCenter(); |
16 | 15 | |
17 | - onMounted(() => { | |
18 | - props.register && props.register(props.dataSource); | |
19 | - }); | |
20 | - | |
21 | 16 | defineExpose({ update }); |
22 | 17 | </script> |
23 | 18 | |
... | ... | @@ -28,7 +23,7 @@ |
28 | 23 | <div class="widget-content" :style="{ height: slot.header ? 'calc(100% - 22px)' : '100%' }"> |
29 | 24 | <div |
30 | 25 | v-for="item in props.dataSource" |
31 | - :key="item.id" | |
26 | + :key="item.uuid" | |
32 | 27 | :style="{ width: `${item.width}%`, height: `${item.height}%` }" |
33 | 28 | class="widget-item" |
34 | 29 | > | ... | ... |
1 | -import { DataBoardLayoutInfo } from '../../types/type'; | |
1 | +// import { DataBoardLayoutInfo } from '../../types/type'; | |
2 | 2 | |
3 | -export type WidgetWrapperRegister = (dataSource: DataBoardLayoutInfo['record'][]) => any; | |
3 | +// export type WidgetWrapperRegister = (dataSource: DataBoardLayoutInfo['record'][]) => any; | ... | ... |
... | ... | @@ -12,7 +12,7 @@ |
12 | 12 | import { ComponentInfo } from '/@/api/dataBoard/model'; |
13 | 13 | import { computed } from '@vue/reactivity'; |
14 | 14 | |
15 | - const emit = defineEmits(['close']); | |
15 | + const emit = defineEmits(['close', 'register']); | |
16 | 16 | |
17 | 17 | const props = defineProps<{ |
18 | 18 | value?: string; |
... | ... | @@ -35,8 +35,7 @@ |
35 | 35 | const [register, { closeModal }] = useModalInner( |
36 | 36 | (data: { recordId: string; componentInfo: ComponentInfo }) => { |
37 | 37 | recordId.value = data.recordId; |
38 | - console.log(data.componentInfo); | |
39 | - const gradientInfo = data.componentInfo.gradientInfo; | |
38 | + const gradientInfo = data.componentInfo?.gradientInfo || []; | |
40 | 39 | let gradientRecord = {}; |
41 | 40 | if (gradientInfo && gradientInfo.length) { |
42 | 41 | const first = gradientInfo.find((item) => item.key === Gradient.FIRST); | ... | ... |
1 | 1 | import { getAllDeviceByOrg, getDeviceAttributes, getGatewaySlaveDevice } from '/@/api/dataBoard'; |
2 | -import { MasterDeviceList } from '/@/api/dataBoard/model'; | |
3 | 2 | import { getOrganizationList } from '/@/api/system/system'; |
4 | 3 | import { FormSchema } from '/@/components/Form'; |
5 | 4 | import { copyTransFun } from '/@/utils/fnUtils'; | ... | ... |
1 | 1 | <script lang="ts" setup> |
2 | - import { Button, PageHeader, Empty } from 'ant-design-vue'; | |
2 | + import { Button, PageHeader, Empty, Spin } from 'ant-design-vue'; | |
3 | 3 | import { GridItem, GridLayout } from 'vue3-grid-layout'; |
4 | 4 | import { nextTick, onMounted, ref } from 'vue'; |
5 | 5 | import WidgetWrapper from '../components/WidgetWrapper/WidgetWrapper.vue'; |
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | import { WidgetComponentType } from './config/visualOptions'; |
25 | 25 | import Authority from '/@/components/Authority/src/Authority.vue'; |
26 | 26 | import { useSocketConnect } from '../hook/useSocketConnect'; |
27 | + import { buildUUID } from '/@/utils/uuid'; | |
27 | 28 | |
28 | 29 | const ROUTE = useRoute(); |
29 | 30 | |
... | ... | @@ -74,6 +75,7 @@ |
74 | 75 | } |
75 | 76 | |
76 | 77 | data.record.dataSource = data?.record.dataSource.map((item) => { |
78 | + if (!item.uuid) item.uuid = buildUUID(); | |
77 | 79 | return { |
78 | 80 | ...item, |
79 | 81 | width, |
... | ... | @@ -164,9 +166,11 @@ |
164 | 166 | |
165 | 167 | const { beginSendMessage } = useSocketConnect(dataBoardList); |
166 | 168 | |
169 | + const loading = ref(false); | |
167 | 170 | const getDataBoardComponent = async () => { |
168 | 171 | try { |
169 | 172 | // dataBoardList.value = []; |
173 | + loading.value = true; | |
170 | 174 | const data = await getDataComponent(unref(getBoardId)); |
171 | 175 | dataBoardList.value = data.data.componentData.map((item) => { |
172 | 176 | const index = data.data.componentLayout.findIndex((each) => item.id === each.id); |
... | ... | @@ -182,15 +186,15 @@ |
182 | 186 | h: layout.h || DEFAULT_WIDGET_HEIGHT, |
183 | 187 | x: layout.x || 0, |
184 | 188 | y: layout.y || 0, |
185 | - record: { | |
186 | - ...item, | |
187 | - width: 100, | |
188 | - height: 100, | |
189 | - }, | |
189 | + record: item, | |
190 | 190 | }; |
191 | 191 | }); |
192 | + | |
192 | 193 | beginSendMessage(); |
193 | - } catch (error) {} | |
194 | + } catch (error) { | |
195 | + } finally { | |
196 | + loading.value = false; | |
197 | + } | |
194 | 198 | }; |
195 | 199 | |
196 | 200 | const getComponent = (record: DataComponentRecord) => { |
... | ... | @@ -258,56 +262,62 @@ |
258 | 262 | </div> |
259 | 263 | </PageHeader> |
260 | 264 | <section class="flex-1"> |
261 | - <GridLayout | |
262 | - v-model:layout="dataBoardList" | |
263 | - :col-num="GirdLayoutColNum" | |
264 | - :row-height="30" | |
265 | - :margin="[GridLayoutMargin, GridLayoutMargin]" | |
266 | - :is-draggable="draggable" | |
267 | - :is-resizable="resizable" | |
268 | - :vertical-compact="true" | |
269 | - :use-css-transforms="true" | |
270 | - style="width: 100%" | |
271 | - > | |
272 | - <GridItem | |
273 | - v-for="item in dataBoardList" | |
274 | - :key="item.i" | |
275 | - :static="item.static" | |
276 | - :x="item.x" | |
277 | - :y="item.y" | |
278 | - :w="item.w" | |
279 | - :h="item.h" | |
280 | - :i="item.i" | |
281 | - :style="{ display: 'flex', flexWrap: 'wrap' }" | |
282 | - class="grid-item-layout" | |
283 | - @resized="itemResized" | |
284 | - @resize="itemResize" | |
285 | - @moved="itemMoved" | |
286 | - @container-resized="itemContainerResized" | |
265 | + <Spin :spinning="loading"> | |
266 | + <GridLayout | |
267 | + v-model:layout="dataBoardList" | |
268 | + :col-num="GirdLayoutColNum" | |
269 | + :row-height="30" | |
270 | + :margin="[GridLayoutMargin, GridLayoutMargin]" | |
271 | + :is-draggable="draggable" | |
272 | + :is-resizable="resizable" | |
273 | + :vertical-compact="true" | |
274 | + :use-css-transforms="true" | |
275 | + style="width: 100%" | |
287 | 276 | > |
288 | - <WidgetWrapper | |
277 | + <GridItem | |
278 | + v-for="item in dataBoardList" | |
289 | 279 | :key="item.i" |
290 | - :ref="(el: Element) => setComponentRef(el, item)" | |
291 | - :data-source="item.record.dataSource" | |
280 | + :static="item.static" | |
281 | + :x="item.x" | |
282 | + :y="item.y" | |
283 | + :w="item.w" | |
284 | + :h="item.h" | |
285 | + :i="item.i" | |
286 | + :style="{ display: 'flex', flexWrap: 'wrap' }" | |
287 | + class="grid-item-layout" | |
288 | + @resized="itemResized" | |
289 | + @resize="itemResize" | |
290 | + @moved="itemMoved" | |
291 | + @container-resized="itemContainerResized" | |
292 | 292 | > |
293 | - <template #header> | |
294 | - <!-- <div>header</div> --> | |
295 | - <BaseWidgetHeader :id="item.record.id" @action="handleMoreAction" /> | |
296 | - </template> | |
297 | - <template #controls="{ record, add, remove, update }"> | |
298 | - <component | |
299 | - :is="getComponent(item.record)" | |
300 | - :add="add" | |
301 | - :remove="remove" | |
302 | - :update="update" | |
303 | - :radio="record.radio" | |
304 | - v-bind="getComponentConfig(item.record, record)" | |
305 | - /> | |
306 | - </template> | |
307 | - </WidgetWrapper> | |
308 | - </GridItem> | |
309 | - </GridLayout> | |
310 | - <Empty v-if="!dataBoardList.length" /> | |
293 | + <WidgetWrapper | |
294 | + :key="item.i" | |
295 | + :ref="(el: Element) => setComponentRef(el, item)" | |
296 | + :data-source="item.record.dataSource" | |
297 | + > | |
298 | + <template #header> | |
299 | + <!-- <div>header</div> --> | |
300 | + <BaseWidgetHeader | |
301 | + :record="item.record.dataSource" | |
302 | + :id="item.record.id" | |
303 | + @action="handleMoreAction" | |
304 | + /> | |
305 | + </template> | |
306 | + <template #controls="{ record, add, remove, update }"> | |
307 | + <component | |
308 | + :is="getComponent(item.record)" | |
309 | + :add="add" | |
310 | + :remove="remove" | |
311 | + :update="update" | |
312 | + :radio="record.radio || {}" | |
313 | + v-bind="getComponentConfig(item.record, record)" | |
314 | + /> | |
315 | + </template> | |
316 | + </WidgetWrapper> | |
317 | + </GridItem> | |
318 | + </GridLayout> | |
319 | + <Empty v-if="!dataBoardList.length" /> | |
320 | + </Spin> | |
311 | 321 | </section> |
312 | 322 | <DataBindModal @register="register" @submit="getDataBoardComponent" /> |
313 | 323 | </section> | ... | ... |
1 | 1 | import { Layout } from 'vue3-grid-layout'; |
2 | -import { DataComponentRecord } from '/@/api/dataBoard/model'; | |
2 | +import { DataComponentRecord, DataSource } from '/@/api/dataBoard/model'; | |
3 | + | |
4 | +export type FrontDataSourceRecord = DataSource; | |
3 | 5 | |
4 | 6 | export type DataBoardLayoutInfo = Layout & { |
5 | - record: DataComponentRecord & { width: number; height: number; radio?: number }; | |
7 | + record: DataComponentRecord; | |
6 | 8 | }; | ... | ... |