Commit 6f9ac029a1fbb6420ba06f83a2762dbdbbd37a1f

Authored by ww
1 parent e535013c

feat: data dashboard data source add slave device field

  1 +import { RadioRecord } from '/@/views/data/board/detail/config/util';
  2 +
1 export interface AddDataBoardParams { 3 export interface AddDataBoardParams {
2 name: string; 4 name: string;
3 viewType: string; 5 viewType: string;
@@ -75,6 +77,13 @@ export interface DataSource { @@ -75,6 +77,13 @@ export interface DataSource {
75 slaveDeviceId: string; 77 slaveDeviceId: string;
76 isGatewayDevice: boolean; 78 isGatewayDevice: boolean;
77 componentInfo: ComponentInfo; 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 export interface DataComponentRecord { 89 export interface DataComponentRecord {
@@ -99,7 +99,7 @@ @@ -99,7 +99,7 @@
99 99
100 <template> 100 <template>
101 <div class="flex flex-col w-full h-full min-w-3 min-h-3"> 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 <div> 103 <div>
104 <div class="text-center" :style="{ fontSize: fontSize({ radio: getRadio, basic: 16 }) }">{{ 104 <div class="text-center" :style="{ fontSize: fontSize({ radio: getRadio, basic: 16 }) }">{{
105 props.value.name 105 props.value.name
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 const props = defineProps<{ 13 const props = defineProps<{
14 layout: DigitalDashBoardLayout; 14 layout: DigitalDashBoardLayout;
15 value: DigitalDashBoardValue; 15 value: DigitalDashBoardValue;
16 - radio: RadioRecord; 16 + radio?: RadioRecord;
17 }>(); 17 }>();
18 18
19 const integerPart = computed(() => { 19 const integerPart = computed(() => {
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 const props = defineProps<{ 13 const props = defineProps<{
14 layout?: PictureComponentLayout; 14 layout?: PictureComponentLayout;
15 value?: PictureComponentValue; 15 value?: PictureComponentValue;
16 - radio: RadioRecord; 16 + radio?: RadioRecord;
17 }>(); 17 }>();
18 18
19 const fallback = 19 const fallback =
@@ -7,10 +7,12 @@ @@ -7,10 +7,12 @@
7 import { MoreActionEvent } from '../../config/config'; 7 import { MoreActionEvent } from '../../config/config';
8 import { computed } from '@vue/reactivity'; 8 import { computed } from '@vue/reactivity';
9 import { usePermission } from '/@/hooks/web/usePermission'; 9 import { usePermission } from '/@/hooks/web/usePermission';
  10 + import { DataSource } from '/@/api/dataBoard/model';
10 11
11 const emit = defineEmits(['action']); 12 const emit = defineEmits(['action']);
12 const props = defineProps<{ 13 const props = defineProps<{
13 id: string; 14 id: string;
  15 + record: DataSource[];
14 }>(); 16 }>();
15 const { hasPermission } = usePermission(); 17 const { hasPermission } = usePermission();
16 const dropMenuList = computed<DropMenu[]>(() => { 18 const dropMenuList = computed<DropMenu[]>(() => {
@@ -45,20 +47,27 @@ @@ -45,20 +47,27 @@
45 </script> 47 </script>
46 48
47 <template> 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 <Tooltip> 61 <Tooltip>
53 <SvgIcon name="online" prefix="iconfont" class="!fill-emerald-400" /> 62 <SvgIcon name="online" prefix="iconfont" class="!fill-emerald-400" />
54 </Tooltip> 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 </div> 66 </div>
58 </div> 67 </div>
59 - <div class="flex items-center wx-9"> 68 + <div class="flex items-center w-10">
60 <Tooltip title="趋势"> 69 <Tooltip title="趋势">
61 - <LineChartOutlined class="cursor-pointer mx-2" /> 70 + <LineChartOutlined class="cursor-pointer mx-1" />
62 </Tooltip> 71 </Tooltip>
63 <Dropdown 72 <Dropdown
64 v-if="dropMenuList.length" 73 v-if="dropMenuList.length"
1 <script lang="ts" setup> 1 <script lang="ts" setup>
2 - import { onMounted, useSlots } from 'vue'; 2 + import { useSlots } from 'vue';
3 import { useUpdateCenter } from '../../hook/useUpdateCenter'; 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 const props = defineProps<{ 8 const props = defineProps<{
9 - dataSource: DataBoardLayoutInfo['record'][];  
10 - register?: WidgetWrapperRegister; 9 + dataSource: FrontDataSourceRecord[];
11 }>(); 10 }>();
12 11
13 const slot = useSlots(); 12 const slot = useSlots();
14 13
15 const { update, add, remove } = useUpdateCenter(); 14 const { update, add, remove } = useUpdateCenter();
16 15
17 - onMounted(() => {  
18 - props.register && props.register(props.dataSource);  
19 - });  
20 -  
21 defineExpose({ update }); 16 defineExpose({ update });
22 </script> 17 </script>
23 18
@@ -28,7 +23,7 @@ @@ -28,7 +23,7 @@
28 <div class="widget-content" :style="{ height: slot.header ? 'calc(100% - 22px)' : '100%' }"> 23 <div class="widget-content" :style="{ height: slot.header ? 'calc(100% - 22px)' : '100%' }">
29 <div 24 <div
30 v-for="item in props.dataSource" 25 v-for="item in props.dataSource"
31 - :key="item.id" 26 + :key="item.uuid"
32 :style="{ width: `${item.width}%`, height: `${item.height}%` }" 27 :style="{ width: `${item.width}%`, height: `${item.height}%` }"
33 class="widget-item" 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;
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 id: string; 14 id: string;
15 } 15 }
16 16
17 - const emit = defineEmits(['submit']); 17 + const emit = defineEmits(['submit', 'register']);
18 18
19 const ROUTE = useRoute(); 19 const ROUTE = useRoute();
20 20
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 import { ComponentInfo } from '/@/api/dataBoard/model'; 12 import { ComponentInfo } from '/@/api/dataBoard/model';
13 import { computed } from '@vue/reactivity'; 13 import { computed } from '@vue/reactivity';
14 14
15 - const emit = defineEmits(['close']); 15 + const emit = defineEmits(['close', 'register']);
16 16
17 const props = defineProps<{ 17 const props = defineProps<{
18 value?: string; 18 value?: string;
@@ -35,8 +35,7 @@ @@ -35,8 +35,7 @@
35 const [register, { closeModal }] = useModalInner( 35 const [register, { closeModal }] = useModalInner(
36 (data: { recordId: string; componentInfo: ComponentInfo }) => { 36 (data: { recordId: string; componentInfo: ComponentInfo }) => {
37 recordId.value = data.recordId; 37 recordId.value = data.recordId;
38 - console.log(data.componentInfo);  
39 - const gradientInfo = data.componentInfo.gradientInfo; 38 + const gradientInfo = data.componentInfo?.gradientInfo || [];
40 let gradientRecord = {}; 39 let gradientRecord = {};
41 if (gradientInfo && gradientInfo.length) { 40 if (gradientInfo && gradientInfo.length) {
42 const first = gradientInfo.find((item) => item.key === Gradient.FIRST); 41 const first = gradientInfo.find((item) => item.key === Gradient.FIRST);
1 import { getAllDeviceByOrg, getDeviceAttributes, getGatewaySlaveDevice } from '/@/api/dataBoard'; 1 import { getAllDeviceByOrg, getDeviceAttributes, getGatewaySlaveDevice } from '/@/api/dataBoard';
2 -import { MasterDeviceList } from '/@/api/dataBoard/model';  
3 import { getOrganizationList } from '/@/api/system/system'; 2 import { getOrganizationList } from '/@/api/system/system';
4 import { FormSchema } from '/@/components/Form'; 3 import { FormSchema } from '/@/components/Form';
5 import { copyTransFun } from '/@/utils/fnUtils'; 4 import { copyTransFun } from '/@/utils/fnUtils';
1 <script lang="ts" setup> 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 import { GridItem, GridLayout } from 'vue3-grid-layout'; 3 import { GridItem, GridLayout } from 'vue3-grid-layout';
4 import { nextTick, onMounted, ref } from 'vue'; 4 import { nextTick, onMounted, ref } from 'vue';
5 import WidgetWrapper from '../components/WidgetWrapper/WidgetWrapper.vue'; 5 import WidgetWrapper from '../components/WidgetWrapper/WidgetWrapper.vue';
@@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
24 import { WidgetComponentType } from './config/visualOptions'; 24 import { WidgetComponentType } from './config/visualOptions';
25 import Authority from '/@/components/Authority/src/Authority.vue'; 25 import Authority from '/@/components/Authority/src/Authority.vue';
26 import { useSocketConnect } from '../hook/useSocketConnect'; 26 import { useSocketConnect } from '../hook/useSocketConnect';
  27 + import { buildUUID } from '/@/utils/uuid';
27 28
28 const ROUTE = useRoute(); 29 const ROUTE = useRoute();
29 30
@@ -74,6 +75,7 @@ @@ -74,6 +75,7 @@
74 } 75 }
75 76
76 data.record.dataSource = data?.record.dataSource.map((item) => { 77 data.record.dataSource = data?.record.dataSource.map((item) => {
  78 + if (!item.uuid) item.uuid = buildUUID();
77 return { 79 return {
78 ...item, 80 ...item,
79 width, 81 width,
@@ -164,9 +166,11 @@ @@ -164,9 +166,11 @@
164 166
165 const { beginSendMessage } = useSocketConnect(dataBoardList); 167 const { beginSendMessage } = useSocketConnect(dataBoardList);
166 168
  169 + const loading = ref(false);
167 const getDataBoardComponent = async () => { 170 const getDataBoardComponent = async () => {
168 try { 171 try {
169 // dataBoardList.value = []; 172 // dataBoardList.value = [];
  173 + loading.value = true;
170 const data = await getDataComponent(unref(getBoardId)); 174 const data = await getDataComponent(unref(getBoardId));
171 dataBoardList.value = data.data.componentData.map((item) => { 175 dataBoardList.value = data.data.componentData.map((item) => {
172 const index = data.data.componentLayout.findIndex((each) => item.id === each.id); 176 const index = data.data.componentLayout.findIndex((each) => item.id === each.id);
@@ -182,15 +186,15 @@ @@ -182,15 +186,15 @@
182 h: layout.h || DEFAULT_WIDGET_HEIGHT, 186 h: layout.h || DEFAULT_WIDGET_HEIGHT,
183 x: layout.x || 0, 187 x: layout.x || 0,
184 y: layout.y || 0, 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 beginSendMessage(); 193 beginSendMessage();
193 - } catch (error) {} 194 + } catch (error) {
  195 + } finally {
  196 + loading.value = false;
  197 + }
194 }; 198 };
195 199
196 const getComponent = (record: DataComponentRecord) => { 200 const getComponent = (record: DataComponentRecord) => {
@@ -258,56 +262,62 @@ @@ -258,56 +262,62 @@
258 </div> 262 </div>
259 </PageHeader> 263 </PageHeader>
260 <section class="flex-1"> 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 :key="item.i" 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 </section> 321 </section>
312 <DataBindModal @register="register" @submit="getDataBoardComponent" /> 322 <DataBindModal @register="register" @submit="getDataBoardComponent" />
313 </section> 323 </section>
1 import { Layout } from 'vue3-grid-layout'; 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 export type DataBoardLayoutInfo = Layout & { 6 export type DataBoardLayoutInfo = Layout & {
5 - record: DataComponentRecord & { width: number; height: number; radio?: number }; 7 + record: DataComponentRecord;
6 }; 8 };