Commit 128a5ebdb2fc8c44107a4752d92b422ac4e8c83c
1 parent
29b5c630
wip: implement digitalDashboardComponent && DashboardComponent
Showing
17 changed files
with
585 additions
and
108 deletions
@@ -7,6 +7,7 @@ import { | @@ -7,6 +7,7 @@ import { | ||
7 | Layout, | 7 | Layout, |
8 | UpdateDataBoardLayoutParams, | 8 | UpdateDataBoardLayoutParams, |
9 | UpdateDataBoardParams, | 9 | UpdateDataBoardParams, |
10 | + UpdateDataComponentParams, | ||
10 | } from './model'; | 11 | } from './model'; |
11 | import { defHttp } from '/@/utils/http/axios'; | 12 | import { defHttp } from '/@/utils/http/axios'; |
12 | 13 | ||
@@ -22,6 +23,7 @@ enum DataComponentUrl { | @@ -22,6 +23,7 @@ enum DataComponentUrl { | ||
22 | GET_DATA_COMPONENT = '/data_component', | 23 | GET_DATA_COMPONENT = '/data_component', |
23 | ADD_DATA_COMPONENT = '/data_component', | 24 | ADD_DATA_COMPONENT = '/data_component', |
24 | DELETE_DATA_COMPONENT = '/data_component', | 25 | DELETE_DATA_COMPONENT = '/data_component', |
26 | + UPDATE_DATA_COMPONENT = '/data_component', | ||
25 | } | 27 | } |
26 | 28 | ||
27 | /** | 29 | /** |
@@ -118,3 +120,15 @@ export const deleteDataComponent = (params: string[]) => { | @@ -118,3 +120,15 @@ export const deleteDataComponent = (params: string[]) => { | ||
118 | }, | 120 | }, |
119 | }); | 121 | }); |
120 | }; | 122 | }; |
123 | + | ||
124 | +/** | ||
125 | + * @description 更新数据组件 | ||
126 | + * @param params | ||
127 | + * @returns | ||
128 | + */ | ||
129 | +export const updateDataComponent = (params: UpdateDataComponentParams) => { | ||
130 | + return defHttp.post({ | ||
131 | + url: `${DataComponentUrl.UPDATE_DATA_COMPONENT}/${params.boardId}/update`, | ||
132 | + params: params.record, | ||
133 | + }); | ||
134 | +}; |
@@ -111,3 +111,8 @@ export interface UpdateDataBoardLayoutParams { | @@ -111,3 +111,8 @@ export interface UpdateDataBoardLayoutParams { | ||
111 | boardId: string; | 111 | boardId: string; |
112 | layout: Layout[]; | 112 | layout: Layout[]; |
113 | } | 113 | } |
114 | + | ||
115 | +export interface UpdateDataComponentParams { | ||
116 | + boardId: string; | ||
117 | + record: Partial<DataComponentRecord>; | ||
118 | +} |
@@ -3,67 +3,31 @@ | @@ -3,67 +3,31 @@ | ||
3 | import type { PropType } from 'vue'; | 3 | import type { PropType } from 'vue'; |
4 | import { nextTick, onMounted, onUnmounted, ref, unref } from 'vue'; | 4 | import { nextTick, onMounted, onUnmounted, ref, unref } from 'vue'; |
5 | import { init } from 'echarts'; | 5 | import { init } from 'echarts'; |
6 | - | ||
7 | - interface DataSource { | ||
8 | - id: string | number; | ||
9 | - } | 6 | + import { instrumentComponent1 } from './dashBoardComponent.config'; |
7 | + import { dateUtil } from '/@/utils/dateUtil'; | ||
10 | 8 | ||
11 | const props = defineProps({ | 9 | const props = defineProps({ |
12 | - dataSource: { | ||
13 | - type: Object as PropType<DataSource>, | ||
14 | - required: true, | ||
15 | - }, | ||
16 | - chartOption: { | ||
17 | - type: Object as PropType<EChartsOption>, | ||
18 | - // required: true, | ||
19 | - }, | ||
20 | add: { | 10 | add: { |
21 | type: Function, | 11 | type: Function, |
22 | - required: true, | 12 | + }, |
13 | + layout: { | ||
14 | + type: Object as PropType<Recordable>, | ||
15 | + default: () => ({}), | ||
16 | + }, | ||
17 | + value: { | ||
18 | + type: Object as PropType<Recordable>, | ||
19 | + default: () => ({}), | ||
23 | }, | 20 | }, |
24 | }); | 21 | }); |
25 | 22 | ||
26 | - const getControlsWidgetId = () => `widget-chart-${props.dataSource.id}`; | 23 | + const getControlsWidgetId = () => `widget-chart-${props.value.id}`; |
27 | 24 | ||
28 | const chartRef = ref<Nullable<ECharts>>(null); | 25 | const chartRef = ref<Nullable<ECharts>>(null); |
29 | 26 | ||
30 | function initChart() { | 27 | function initChart() { |
31 | const chartDom = document.getElementById(getControlsWidgetId())!; | 28 | const chartDom = document.getElementById(getControlsWidgetId())!; |
32 | chartRef.value = init(chartDom); | 29 | chartRef.value = init(chartDom); |
33 | - const option: EChartsOption = props.chartOption || { | ||
34 | - tooltip: { | ||
35 | - trigger: 'item', | ||
36 | - // confine: true, | ||
37 | - extraCssText: 'position: fixed;', | ||
38 | - position: (point, params, dom) => { | ||
39 | - const parentEl = (dom as HTMLDivElement).parentElement!; | ||
40 | - | ||
41 | - const { top = 0, left = 0 } = parentEl.getBoundingClientRect()!; | ||
42 | - return [left, top]; | ||
43 | - }, | ||
44 | - }, | ||
45 | - series: [ | ||
46 | - { | ||
47 | - name: 'Access From', | ||
48 | - type: 'pie', | ||
49 | - radius: '50%', | ||
50 | - data: [ | ||
51 | - { value: 1048, name: 'Search Engine' }, | ||
52 | - { value: 735, name: 'Direct' }, | ||
53 | - { value: 580, name: 'Email' }, | ||
54 | - { value: 484, name: 'Union Ads' }, | ||
55 | - { value: 300, name: 'Video Ads' }, | ||
56 | - ], | ||
57 | - emphasis: { | ||
58 | - itemStyle: { | ||
59 | - shadowBlur: 10, | ||
60 | - shadowOffsetX: 0, | ||
61 | - shadowColor: 'rgba(0, 0, 0, 0.5)', | ||
62 | - }, | ||
63 | - }, | ||
64 | - }, | ||
65 | - ], | ||
66 | - }; | 30 | + const option: EChartsOption = props.layout || instrumentComponent1(); |
67 | 31 | ||
68 | nextTick(() => { | 32 | nextTick(() => { |
69 | option && unref(chartRef)?.setOption(option); | 33 | option && unref(chartRef)?.setOption(option); |
@@ -76,7 +40,7 @@ | @@ -76,7 +40,7 @@ | ||
76 | 40 | ||
77 | onMounted(() => { | 41 | onMounted(() => { |
78 | initChart(); | 42 | initChart(); |
79 | - props.add(props.dataSource.id, update); | 43 | + props.add && props.add(props.value.id, update); |
80 | }); | 44 | }); |
81 | 45 | ||
82 | onUnmounted(() => { | 46 | onUnmounted(() => { |
@@ -89,7 +53,13 @@ | @@ -89,7 +53,13 @@ | ||
89 | <template> | 53 | <template> |
90 | <div class="flex flex-col w-full h-full min-w-3 min-h-3"> | 54 | <div class="flex flex-col w-full h-full min-w-3 min-h-3"> |
91 | <div :id="getControlsWidgetId()" class="widget-charts w-full h-full"></div> | 55 | <div :id="getControlsWidgetId()" class="widget-charts w-full h-full"></div> |
92 | - <div class="text-xs text-center text-gray-400">更新时间:</div> | 56 | + <div>{{}}</div> |
57 | + <div class="text-xs text-center text-gray-400"> | ||
58 | + <span>更新时间:</span> | ||
59 | + <span> | ||
60 | + {{ props.value.updateTime || dateUtil().format('YYYY-MM-DD HH:mm:ss') }} | ||
61 | + </span> | ||
62 | + </div> | ||
93 | </div> | 63 | </div> |
94 | </template> | 64 | </template> |
95 | 65 |
1 | -<script lang="ts" setup></script> | 1 | +<script lang="ts" setup> |
2 | + import { computed } from 'vue'; | ||
3 | + import { Space } from 'ant-design-vue'; | ||
4 | + import type { DigitalDashBoardLayout, DigitalDashBoardValue } from './digitalDashBoard.config'; | ||
5 | + import { dateUtil } from '/@/utils/dateUtil'; | ||
2 | 6 | ||
3 | -<template> </template> | 7 | + const props = defineProps<{ |
8 | + layout: DigitalDashBoardLayout; | ||
9 | + value: DigitalDashBoardValue; | ||
10 | + }>(); | ||
11 | + | ||
12 | + const integerPart = computed(() => { | ||
13 | + const { value = 0 } = props.value; | ||
14 | + const { max = 5 } = props.layout; | ||
15 | + let _value = value?.toFixed(2).split('.')[0]; | ||
16 | + if (_value.length < max) _value = _value.padStart(5, '0'); | ||
17 | + | ||
18 | + if (_value.length > max) _value = ''.padStart(5, '9'); | ||
19 | + | ||
20 | + return _value; | ||
21 | + }); | ||
22 | + | ||
23 | + const decimalPart = computed(() => { | ||
24 | + const { value = 0 } = props.value; | ||
25 | + const { keepNumber = 2 } = props.layout; | ||
26 | + let _value = value?.toFixed(2).split('.')[1]; | ||
27 | + if (_value.length < keepNumber) _value = _value.padStart(5, '0'); | ||
28 | + | ||
29 | + if (_value.length > keepNumber) _value = ''.padStart(5, '0'); | ||
30 | + | ||
31 | + return _value; | ||
32 | + }); | ||
33 | +</script> | ||
34 | + | ||
35 | +<template> | ||
36 | + <section class="w-full h-full"> | ||
37 | + <div class="flex flex-col w-full h-full"> | ||
38 | + <div class="flex-1 flex justify-center items-center"> | ||
39 | + <div class="flex flex-col"> | ||
40 | + <Space justify="end" class="justify-end"> | ||
41 | + <div | ||
42 | + v-for="number in integerPart" | ||
43 | + :key="number" | ||
44 | + class="border border-gray-400 p-2" | ||
45 | + :style="{ color: props.value.valueColor }" | ||
46 | + > | ||
47 | + {{ number }} | ||
48 | + </div> | ||
49 | + </Space> | ||
50 | + <Space justify="end" class="justify-end mt-2"> | ||
51 | + <div | ||
52 | + v-for="number in decimalPart" | ||
53 | + :key="number" | ||
54 | + class="border border-gray-400 p-1" | ||
55 | + :style="{ color: props.value.valueColor }" | ||
56 | + > | ||
57 | + {{ number }} | ||
58 | + </div> | ||
59 | + </Space> | ||
60 | + </div> | ||
61 | + </div> | ||
62 | + | ||
63 | + <div class="text-center"> | ||
64 | + <span>{{ props.value.name || '电表' }}</span> | ||
65 | + <span class="px-1">({{ props.value.unit || 'kw/h' }})</span> | ||
66 | + </div> | ||
67 | + <div class="text-center mt-1 text-gray-400 text-xs"> | ||
68 | + <span class="mr-1">更新时间:</span> | ||
69 | + <span>{{ props.value.updateTime || dateUtil().format('YYYY-MM-DD HH:mm:ss') }}</span> | ||
70 | + </div> | ||
71 | + </div> | ||
72 | + <div></div> | ||
73 | + </section> | ||
74 | +</template> |
1 | +import { EChartsOption } from 'echarts'; | ||
2 | +import { visualOptionField } from '../../detail/config/visualOptions'; | ||
3 | + | ||
4 | +export type InstrumentComponentType = 'instrument-component-1' | 'instrument-component-2'; | ||
5 | + | ||
6 | +export type GradientKey = | ||
7 | + | visualOptionField.FIRST_PHASE_COLOR | ||
8 | + | visualOptionField.FIRST_PHASE_VALUE | ||
9 | + | visualOptionField.SECOND_PHASE_COLOR | ||
10 | + | visualOptionField.SECOND_PHASE_VALUE | ||
11 | + | visualOptionField.THIRD_PHASE_COLOR | ||
12 | + | visualOptionField.THIRD_PHASE_VALUE; | ||
13 | +export interface GradientInfoRecord { | ||
14 | + key: GradientKey; | ||
15 | + value: number | string; | ||
16 | +} | ||
17 | + | ||
18 | +export interface DashBoardValue { | ||
19 | + unit?: string; | ||
20 | + name?: string; | ||
21 | + updateTime?: string; | ||
22 | + value?: number; | ||
23 | + valueColor?: string; | ||
24 | + gradientInfo?: GradientInfoRecord[]; | ||
25 | +} | ||
26 | + | ||
27 | +export const instrumentComponent1 = (params?: { value: number; unit: string }): EChartsOption => { | ||
28 | + const { value = 10, unit = '°C' } = params || {}; | ||
29 | + return { | ||
30 | + series: [ | ||
31 | + { | ||
32 | + type: 'gauge', | ||
33 | + center: ['50%', '60%'], | ||
34 | + startAngle: 200, | ||
35 | + endAngle: -20, | ||
36 | + min: 0, | ||
37 | + max: 60, | ||
38 | + splitNumber: 12, | ||
39 | + itemStyle: { | ||
40 | + color: '#FFAB91', | ||
41 | + }, | ||
42 | + progress: { | ||
43 | + show: true, | ||
44 | + width: 30, | ||
45 | + }, | ||
46 | + pointer: { | ||
47 | + show: false, | ||
48 | + }, | ||
49 | + axisLine: { | ||
50 | + lineStyle: { | ||
51 | + width: 30, | ||
52 | + }, | ||
53 | + }, | ||
54 | + axisTick: { | ||
55 | + distance: -45, | ||
56 | + splitNumber: 5, | ||
57 | + lineStyle: { | ||
58 | + width: 2, | ||
59 | + color: '#999', | ||
60 | + }, | ||
61 | + }, | ||
62 | + splitLine: { | ||
63 | + distance: -52, | ||
64 | + length: 14, | ||
65 | + lineStyle: { | ||
66 | + width: 3, | ||
67 | + color: '#999', | ||
68 | + }, | ||
69 | + }, | ||
70 | + axisLabel: { | ||
71 | + distance: -20, | ||
72 | + color: '#999', | ||
73 | + fontSize: 20, | ||
74 | + }, | ||
75 | + anchor: { | ||
76 | + show: false, | ||
77 | + }, | ||
78 | + title: { | ||
79 | + show: false, | ||
80 | + }, | ||
81 | + detail: { | ||
82 | + valueAnimation: true, | ||
83 | + width: '60%', | ||
84 | + lineHeight: 40, | ||
85 | + borderRadius: 8, | ||
86 | + offsetCenter: [0, '-15%'], | ||
87 | + fontSize: 16, | ||
88 | + fontWeight: 'bolder', | ||
89 | + formatter: `{value} ${unit}`, | ||
90 | + color: 'auto', | ||
91 | + }, | ||
92 | + data: [ | ||
93 | + { | ||
94 | + value: value, | ||
95 | + }, | ||
96 | + ], | ||
97 | + }, | ||
98 | + { | ||
99 | + type: 'gauge', | ||
100 | + center: ['50%', '60%'], | ||
101 | + startAngle: 200, | ||
102 | + endAngle: -20, | ||
103 | + min: 0, | ||
104 | + max: 60, | ||
105 | + itemStyle: { | ||
106 | + color: '#FD7347', | ||
107 | + }, | ||
108 | + progress: { | ||
109 | + show: true, | ||
110 | + width: 8, | ||
111 | + }, | ||
112 | + pointer: { | ||
113 | + show: false, | ||
114 | + }, | ||
115 | + axisLine: { | ||
116 | + show: false, | ||
117 | + }, | ||
118 | + axisTick: { | ||
119 | + show: false, | ||
120 | + }, | ||
121 | + splitLine: { | ||
122 | + show: false, | ||
123 | + }, | ||
124 | + axisLabel: { | ||
125 | + show: false, | ||
126 | + }, | ||
127 | + detail: { | ||
128 | + show: false, | ||
129 | + }, | ||
130 | + data: [ | ||
131 | + { | ||
132 | + value: value, | ||
133 | + }, | ||
134 | + ], | ||
135 | + }, | ||
136 | + ], | ||
137 | + }; | ||
138 | +}; | ||
139 | + | ||
140 | +export const instrumentComponent2 = (params?: { | ||
141 | + gradient: GradientInfoRecord[]; | ||
142 | + value: number; | ||
143 | + unit: string; | ||
144 | +}): EChartsOption => { | ||
145 | + const { gradient = [], value = 0, unit = 'km/h' } = params || {}; | ||
146 | + return { | ||
147 | + series: [ | ||
148 | + { | ||
149 | + type: 'gauge', | ||
150 | + axisLine: { | ||
151 | + lineStyle: { | ||
152 | + width: 30, | ||
153 | + color: [ | ||
154 | + [ | ||
155 | + 0.3, | ||
156 | + (getGradientValue(visualOptionField.FIRST_PHASE_COLOR, gradient) as string) || | ||
157 | + '#67e0e3', | ||
158 | + ], | ||
159 | + [ | ||
160 | + 0.7, | ||
161 | + (getGradientValue(visualOptionField.SECOND_PHASE_COLOR, gradient) as string) || | ||
162 | + '#37a2da', | ||
163 | + ], | ||
164 | + [ | ||
165 | + 1, | ||
166 | + (getGradientValue(visualOptionField.THIRD_PHASE_COLOR, gradient) as string) || | ||
167 | + '#fd666d', | ||
168 | + ], | ||
169 | + ], | ||
170 | + }, | ||
171 | + }, | ||
172 | + pointer: { | ||
173 | + itemStyle: { | ||
174 | + color: 'auto', | ||
175 | + }, | ||
176 | + }, | ||
177 | + axisTick: { | ||
178 | + distance: -30, | ||
179 | + length: 8, | ||
180 | + lineStyle: { | ||
181 | + color: '#fff', | ||
182 | + width: 2, | ||
183 | + }, | ||
184 | + }, | ||
185 | + splitLine: { | ||
186 | + distance: -30, | ||
187 | + length: 30, | ||
188 | + lineStyle: { | ||
189 | + color: '#fff', | ||
190 | + width: 4, | ||
191 | + }, | ||
192 | + }, | ||
193 | + axisLabel: { | ||
194 | + color: 'auto', | ||
195 | + distance: 40, | ||
196 | + fontSize: 14, | ||
197 | + }, | ||
198 | + detail: { | ||
199 | + valueAnimation: true, | ||
200 | + formatter: `{value} ${unit}`, | ||
201 | + color: 'auto', | ||
202 | + fontSize: '16', | ||
203 | + }, | ||
204 | + data: [ | ||
205 | + { | ||
206 | + value: value, | ||
207 | + }, | ||
208 | + ], | ||
209 | + }, | ||
210 | + ], | ||
211 | + }; | ||
212 | +}; | ||
213 | + | ||
214 | +export const getGradientValue = (key: GradientKey, record: GradientInfoRecord[]) => { | ||
215 | + return record.find((item) => item.key === key)?.value; | ||
216 | +}; |
1 | +export type DigitalDashBoardComponentType = 'digital-dashboard'; | ||
2 | + | ||
3 | +export interface DigitalDashBoardLayout { | ||
4 | + max: number; | ||
5 | + keepNumber: number; | ||
6 | +} | ||
7 | + | ||
8 | +export interface DigitalDashBoardValue { | ||
9 | + unit?: string; | ||
10 | + name?: string; | ||
11 | + updateTime?: string; | ||
12 | + value?: number; | ||
13 | + valueColor?: string; | ||
14 | +} |
1 | +import { Component } from 'vue'; | ||
2 | +import { WidgetComponentType } from '../../detail/config/visualOptions'; | ||
3 | +import { instrumentComponent1, instrumentComponent2 } from './dashBoardComponent.config'; | ||
4 | +import DashBoardComponent from './DashBoardComponent.vue'; | ||
5 | +import DigitalDashBoard from './DigitalDashBoard.vue'; | ||
6 | +import { buildUUID } from '/@/utils/uuid'; | ||
7 | + | ||
8 | +interface InstrumentComponentConfig { | ||
9 | + id: WidgetComponentType; | ||
10 | + layout: Recordable; | ||
11 | + component: Component; | ||
12 | + value: Recordable; | ||
13 | +} | ||
14 | + | ||
15 | +export const instrumentComponentConfig: InstrumentComponentConfig[] = [ | ||
16 | + { | ||
17 | + id: 'instrument-component-1', | ||
18 | + layout: instrumentComponent1(), | ||
19 | + component: DashBoardComponent, | ||
20 | + value: { id: buildUUID() }, | ||
21 | + }, | ||
22 | + { | ||
23 | + id: 'instrument-component-2', | ||
24 | + layout: instrumentComponent2(), | ||
25 | + component: DashBoardComponent, | ||
26 | + value: { id: buildUUID() }, | ||
27 | + }, | ||
28 | + { | ||
29 | + id: 'digital-dashboard', | ||
30 | + layout: {}, | ||
31 | + component: DigitalDashBoard, | ||
32 | + value: {}, | ||
33 | + }, | ||
34 | +]; |
@@ -18,6 +18,13 @@ export interface TextComponentValue { | @@ -18,6 +18,13 @@ export interface TextComponentValue { | ||
18 | iconColor?: string; | 18 | iconColor?: string; |
19 | } | 19 | } |
20 | 20 | ||
21 | +export type TextComponentType = | ||
22 | + | 'text-component-1' | ||
23 | + | 'text-component-2' | ||
24 | + | 'text-component-3' | ||
25 | + | 'text-component-4' | ||
26 | + | 'text-component-5'; | ||
27 | + | ||
21 | type TextComponentDefault = TextComponentLayout & { value: TextComponentValue }; | 28 | type TextComponentDefault = TextComponentLayout & { value: TextComponentValue }; |
22 | 29 | ||
23 | export const TextComponent1Config: TextComponentDefault = { | 30 | export const TextComponent1Config: TextComponentDefault = { |
@@ -10,8 +10,6 @@ | @@ -10,8 +10,6 @@ | ||
10 | 10 | ||
11 | const slot = useSlots(); | 11 | const slot = useSlots(); |
12 | 12 | ||
13 | - console.log({ dataSource: props.dataSource }); | ||
14 | - | ||
15 | const { update, add, remove } = useUpdateCenter(); | 13 | const { update, add, remove } = useUpdateCenter(); |
16 | 14 | ||
17 | onMounted(() => { | 15 | onMounted(() => { |
@@ -4,27 +4,28 @@ | @@ -4,27 +4,28 @@ | ||
4 | import { FormActionType, useForm } from '/@/components/Form'; | 4 | import { FormActionType, useForm } from '/@/components/Form'; |
5 | import { basicSchema, dataSourceSchema } from '../config/basicConfiguration'; | 5 | import { basicSchema, dataSourceSchema } from '../config/basicConfiguration'; |
6 | import BasicForm from '/@/components/Form/src/BasicForm.vue'; | 6 | import BasicForm from '/@/components/Form/src/BasicForm.vue'; |
7 | - import { onMounted, reactive, ref, shallowReactive, unref, nextTick } from 'vue'; | 7 | + import { reactive, ref, shallowReactive, unref, nextTick, watch } from 'vue'; |
8 | import VisualOptionsModal from './VisualOptionsModal.vue'; | 8 | import VisualOptionsModal from './VisualOptionsModal.vue'; |
9 | import { useModal } from '/@/components/Modal'; | 9 | import { useModal } from '/@/components/Modal'; |
10 | import { buildUUID } from '/@/utils/uuid'; | 10 | import { buildUUID } from '/@/utils/uuid'; |
11 | - import type { DataComponentRecord, ComponentInfo, DataSource } from '/@/api/dataBoard/model'; | 11 | + import type { ComponentInfo, DataSource } from '/@/api/dataBoard/model'; |
12 | import { useMessage } from '/@/hooks/web/useMessage'; | 12 | import { useMessage } from '/@/hooks/web/useMessage'; |
13 | + import { DataBoardLayoutInfo } from '../../types/type'; | ||
13 | 14 | ||
14 | type DataSourceFormEL = { [key: string]: Nullable<FormActionType> }; | 15 | type DataSourceFormEL = { [key: string]: Nullable<FormActionType> }; |
15 | 16 | ||
16 | type DataSourceEl = DataSource & { id: string }; | 17 | type DataSourceEl = DataSource & { id: string }; |
17 | 18 | ||
18 | const props = defineProps<{ | 19 | const props = defineProps<{ |
19 | - record: DataComponentRecord; | 20 | + record: DataBoardLayoutInfo; |
20 | frontId?: string; | 21 | frontId?: string; |
21 | }>(); | 22 | }>(); |
22 | 23 | ||
23 | const { createMessage } = useMessage(); | 24 | const { createMessage } = useMessage(); |
24 | 25 | ||
25 | - const componentRecord = reactive<DataComponentRecord>({ | ||
26 | - id: 'string', | ||
27 | - } as unknown as DataComponentRecord); | 26 | + // const componentRecord = reactive<DataBoardLayoutInfo>({ |
27 | + // ...props.record, | ||
28 | + // } as unknown as DataBoardLayoutInfo); | ||
28 | 29 | ||
29 | const dataSource = ref<DataSourceEl[]>([{ id: buildUUID() } as unknown as DataSourceEl]); | 30 | const dataSource = ref<DataSourceEl[]>([{ id: buildUUID() } as unknown as DataSourceEl]); |
30 | 31 | ||
@@ -38,7 +39,6 @@ | @@ -38,7 +39,6 @@ | ||
38 | 39 | ||
39 | const setFormEl = (el: any, id: string) => { | 40 | const setFormEl = (el: any, id: string) => { |
40 | if (!dataSourceEl[id] && el) { | 41 | if (!dataSourceEl[id] && el) { |
41 | - console.log({ el, id }); | ||
42 | const { formActionType } = el as unknown as { formActionType: FormActionType }; | 42 | const { formActionType } = el as unknown as { formActionType: FormActionType }; |
43 | dataSourceEl[id] = formActionType; | 43 | dataSourceEl[id] = formActionType; |
44 | } | 44 | } |
@@ -59,12 +59,12 @@ | @@ -59,12 +59,12 @@ | ||
59 | for (const id of hasExistEl) { | 59 | for (const id of hasExistEl) { |
60 | const index = unref(dataSource).findIndex((item) => item.id === id); | 60 | const index = unref(dataSource).findIndex((item) => item.id === id); |
61 | const value = (dataSourceEl[id] as FormActionType).getFieldsValue() as DataSource; | 61 | const value = (dataSourceEl[id] as FormActionType).getFieldsValue() as DataSource; |
62 | + if (!~index) continue; | ||
62 | const componentInfo = unref(dataSource)[index].componentInfo || {}; | 63 | const componentInfo = unref(dataSource)[index].componentInfo || {}; |
63 | - ~index && | ||
64 | - _dataSource.push({ | ||
65 | - ...value, | ||
66 | - componentInfo: { ...componentInfo }, | ||
67 | - }); | 64 | + _dataSource.push({ |
65 | + ...value, | ||
66 | + componentInfo: { ...componentInfo }, | ||
67 | + }); | ||
68 | } | 68 | } |
69 | return _dataSource; | 69 | return _dataSource; |
70 | }; | 70 | }; |
@@ -113,19 +113,38 @@ | @@ -113,19 +113,38 @@ | ||
113 | }; | 113 | }; |
114 | 114 | ||
115 | const echoDataSource = () => { | 115 | const echoDataSource = () => { |
116 | - basicMethod.setFieldsValue(props.record); | ||
117 | - // dataSourceMethod.setFieldsValue(props.record); | 116 | + basicMethod.setFieldsValue(props.record.record); |
117 | + dataSource.value = []; | ||
118 | + dataSource.value = props.record.record.dataSource.map((item) => { | ||
119 | + const id = buildUUID(); | ||
120 | + | ||
121 | + dataSource.value.push({ | ||
122 | + id, | ||
123 | + ...item, | ||
124 | + }); | ||
125 | + | ||
126 | + nextTick(() => { | ||
127 | + (dataSourceEl[id] as FormActionType).setFieldsValue(item); | ||
128 | + }); | ||
129 | + return { | ||
130 | + id, | ||
131 | + ...item, | ||
132 | + }; | ||
133 | + }); | ||
118 | }; | 134 | }; |
119 | 135 | ||
136 | + watch( | ||
137 | + () => props.record, | ||
138 | + () => { | ||
139 | + if (Object.keys(props.record).length) echoDataSource(); | ||
140 | + } | ||
141 | + ); | ||
142 | + | ||
120 | const handleRowComponentInfo = (recordId: string, value: ComponentInfo) => { | 143 | const handleRowComponentInfo = (recordId: string, value: ComponentInfo) => { |
121 | const index = unref(dataSource).findIndex((item) => item.id === recordId); | 144 | const index = unref(dataSource).findIndex((item) => item.id === recordId); |
122 | ~index && (unref(dataSource)[index].componentInfo = value); | 145 | ~index && (unref(dataSource)[index].componentInfo = value); |
123 | }; | 146 | }; |
124 | 147 | ||
125 | - onMounted(() => { | ||
126 | - echoDataSource(); | ||
127 | - }); | ||
128 | - | ||
129 | defineExpose({ | 148 | defineExpose({ |
130 | getAllDataSourceFieldValue, | 149 | getAllDataSourceFieldValue, |
131 | }); | 150 | }); |
@@ -179,7 +198,11 @@ | @@ -179,7 +198,11 @@ | ||
179 | <div class="text-center"> | 198 | <div class="text-center"> |
180 | <Button type="primary" @click="handleAdd">添加数据源</Button> | 199 | <Button type="primary" @click="handleAdd">添加数据源</Button> |
181 | </div> | 200 | </div> |
182 | - <VisualOptionsModal @close="handleRowComponentInfo" @register="registerVisualOptionModal" /> | 201 | + <VisualOptionsModal |
202 | + :value="props.frontId" | ||
203 | + @close="handleRowComponentInfo" | ||
204 | + @register="registerVisualOptionModal" | ||
205 | + /> | ||
183 | </section> | 206 | </section> |
184 | </template> | 207 | </template> |
185 | 208 |
@@ -4,11 +4,12 @@ | @@ -4,11 +4,12 @@ | ||
4 | import BasicConfiguration from './BasicConfiguration.vue'; | 4 | import BasicConfiguration from './BasicConfiguration.vue'; |
5 | import VisualConfiguration from './VisualConfiguration.vue'; | 5 | import VisualConfiguration from './VisualConfiguration.vue'; |
6 | import { computed, ref, unref } from 'vue'; | 6 | import { computed, ref, unref } from 'vue'; |
7 | - import type { DataComponentRecord } from '/@/api/dataBoard/model'; | ||
8 | import { RouteParams, useRoute } from 'vue-router'; | 7 | import { RouteParams, useRoute } from 'vue-router'; |
9 | - import { addDataComponent, updateDataBoardLayout } from '/@/api/dataBoard'; | 8 | + import { addDataComponent, updateDataBoardLayout, updateDataComponent } from '/@/api/dataBoard'; |
10 | import { useModalInner } from '/@/components/Modal'; | 9 | import { useModalInner } from '/@/components/Modal'; |
11 | import { DEFAULT_WIDGET_HEIGHT, DEFAULT_WIDGET_WIDTH } from '../../config/config'; | 10 | import { DEFAULT_WIDGET_HEIGHT, DEFAULT_WIDGET_WIDTH } from '../../config/config'; |
11 | + import { DataBoardLayoutInfo } from '../../types/type'; | ||
12 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
12 | 13 | ||
13 | interface DataComponentRouteParams extends RouteParams { | 14 | interface DataComponentRouteParams extends RouteParams { |
14 | id: string; | 15 | id: string; |
@@ -18,11 +19,7 @@ | @@ -18,11 +19,7 @@ | ||
18 | 19 | ||
19 | const ROUTE = useRoute(); | 20 | const ROUTE = useRoute(); |
20 | 21 | ||
21 | - const [register, { closeModal }] = useModalInner(); | ||
22 | - | ||
23 | - const basicConfigurationEl = ref<{ | ||
24 | - getAllDataSourceFieldValue: Fn<any, Recordable>; | ||
25 | - }>(); | 22 | + const { createMessage } = useMessage(); |
26 | 23 | ||
27 | const boardId = computed(() => { | 24 | const boardId = computed(() => { |
28 | return (ROUTE.params as DataComponentRouteParams).id; | 25 | return (ROUTE.params as DataComponentRouteParams).id; |
@@ -30,12 +27,26 @@ | @@ -30,12 +27,26 @@ | ||
30 | 27 | ||
31 | const frontId = ref(''); | 28 | const frontId = ref(''); |
32 | 29 | ||
33 | - const componentRecord = ref<DataComponentRecord>({} as unknown as DataComponentRecord); | 30 | + const isEdit = ref(false); |
31 | + | ||
32 | + const componentRecord = ref<DataBoardLayoutInfo>({} as unknown as DataBoardLayoutInfo); | ||
33 | + | ||
34 | + const [register, { closeModal }] = useModalInner( | ||
35 | + (record: DataBoardLayoutInfo & { isEdit: boolean }) => { | ||
36 | + componentRecord.value = record; | ||
37 | + frontId.value = record.record.frontId; | ||
38 | + isEdit.value = record.isEdit; | ||
39 | + } | ||
40 | + ); | ||
41 | + | ||
42 | + const basicConfigurationEl = ref<{ | ||
43 | + getAllDataSourceFieldValue: Fn<any, Recordable>; | ||
44 | + }>(); | ||
34 | 45 | ||
35 | const handleSubmit = () => { | 46 | const handleSubmit = () => { |
36 | const { getAllDataSourceFieldValue } = unref(basicConfigurationEl)!; | 47 | const { getAllDataSourceFieldValue } = unref(basicConfigurationEl)!; |
37 | const value = getAllDataSourceFieldValue(); | 48 | const value = getAllDataSourceFieldValue(); |
38 | - handleAddComponent(value); | 49 | + unref(isEdit) ? handleUpdateComponent(value) : handleAddComponent(value); |
39 | }; | 50 | }; |
40 | 51 | ||
41 | const handleAddComponent = async (value: Recordable) => { | 52 | const handleAddComponent = async (value: Recordable) => { |
@@ -44,6 +55,7 @@ | @@ -44,6 +55,7 @@ | ||
44 | boardId: unref(boardId), | 55 | boardId: unref(boardId), |
45 | record: { dataBoardId: unref(boardId), frontId: unref(frontId), ...value }, | 56 | record: { dataBoardId: unref(boardId), frontId: unref(frontId), ...value }, |
46 | }); | 57 | }); |
58 | + createMessage.success('创建成功'); | ||
47 | const id = data.data.id; | 59 | const id = data.data.id; |
48 | await updateDataBoardLayout({ | 60 | await updateDataBoardLayout({ |
49 | boardId: unref(boardId), | 61 | boardId: unref(boardId), |
@@ -51,7 +63,28 @@ | @@ -51,7 +63,28 @@ | ||
51 | }); | 63 | }); |
52 | closeModal(); | 64 | closeModal(); |
53 | emit('submit'); | 65 | emit('submit'); |
54 | - } catch (error) {} | 66 | + } catch (error) { |
67 | + // createMessage.error('创建失败'); | ||
68 | + } | ||
69 | + }; | ||
70 | + | ||
71 | + const handleUpdateComponent = async (value: Recordable) => { | ||
72 | + try { | ||
73 | + await updateDataComponent({ | ||
74 | + boardId: unref(boardId), | ||
75 | + record: { | ||
76 | + id: unref(componentRecord).i, | ||
77 | + dataBoardId: unref(boardId), | ||
78 | + frontId: unref(frontId), | ||
79 | + ...value, | ||
80 | + }, | ||
81 | + }); | ||
82 | + createMessage.success('修改成功'); | ||
83 | + closeModal(); | ||
84 | + emit('submit'); | ||
85 | + } catch (error) { | ||
86 | + // createMessage.error('修改失败'); | ||
87 | + } | ||
55 | }; | 88 | }; |
56 | </script> | 89 | </script> |
57 | 90 | ||
@@ -61,6 +94,7 @@ | @@ -61,6 +94,7 @@ | ||
61 | @register="register" | 94 | @register="register" |
62 | title="自定义组件" | 95 | title="自定义组件" |
63 | width="70%" | 96 | width="70%" |
97 | + destroy-on-close | ||
64 | @ok="handleSubmit" | 98 | @ok="handleSubmit" |
65 | > | 99 | > |
66 | <section> | 100 | <section> |
@@ -3,6 +3,7 @@ | @@ -3,6 +3,7 @@ | ||
3 | import VisualWidgetSelect from './VisualWidgetSelect.vue'; | 3 | import VisualWidgetSelect from './VisualWidgetSelect.vue'; |
4 | import TextComponent from '../../components/TextComponent/TextComponent.vue'; | 4 | import TextComponent from '../../components/TextComponent/TextComponent.vue'; |
5 | import { textComponentConfig } from '../../components/TextComponent/config'; | 5 | import { textComponentConfig } from '../../components/TextComponent/config'; |
6 | + import { instrumentComponentConfig } from '../../components/InstrumentComponent'; | ||
6 | const props = defineProps<{ | 7 | const props = defineProps<{ |
7 | value: string; | 8 | value: string; |
8 | }>(); | 9 | }>(); |
@@ -35,7 +36,22 @@ | @@ -35,7 +36,22 @@ | ||
35 | </List> | 36 | </List> |
36 | </Tabs.TabPane> | 37 | </Tabs.TabPane> |
37 | <Tabs.TabPane key="2" tab="仪表组件"> | 38 | <Tabs.TabPane key="2" tab="仪表组件"> |
38 | - <div>仪表组件</div> | 39 | + <List |
40 | + :grid="{ gutter: 10, column: 3, xs: 3, sm: 3, md: 3, lg: 3, xl: 3, xxl: 3 }" | ||
41 | + :data-source="instrumentComponentConfig" | ||
42 | + > | ||
43 | + <template #renderItem="{ item }"> | ||
44 | + <List.Item class="!flex !justify-center"> | ||
45 | + <VisualWidgetSelect | ||
46 | + :checked-id="props.value" | ||
47 | + :control-id="item.id" | ||
48 | + @change="handleCheck" | ||
49 | + > | ||
50 | + <component :is="item.component" :layout="item.layout" :value="item.value" /> | ||
51 | + </VisualWidgetSelect> | ||
52 | + </List.Item> | ||
53 | + </template> | ||
54 | + </List> | ||
39 | </Tabs.TabPane> | 55 | </Tabs.TabPane> |
40 | </Tabs> | 56 | </Tabs> |
41 | </section> | 57 | </section> |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | - import { onMounted, ref, unref } from 'vue'; | ||
3 | - import { modeOne, modeTwo, modeThree, modeFour } from '../config/visualOptions'; | 2 | + import { ref, unref } from 'vue'; |
3 | + import { WidgetComponentType, schemasMap } from '../config/visualOptions'; | ||
4 | import { useForm, BasicForm } from '/@/components/Form'; | 4 | import { useForm, BasicForm } from '/@/components/Form'; |
5 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 5 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
6 | import { ComponentInfo } from '/@/api/dataBoard/model'; | 6 | import { ComponentInfo } from '/@/api/dataBoard/model'; |
7 | + import { computed } from '@vue/reactivity'; | ||
7 | 8 | ||
8 | const emit = defineEmits(['close']); | 9 | const emit = defineEmits(['close']); |
9 | 10 | ||
11 | + const props = defineProps<{ | ||
12 | + value?: string; | ||
13 | + }>(); | ||
14 | + | ||
10 | const recordId = ref(''); | 15 | const recordId = ref(''); |
11 | 16 | ||
17 | + const getSchemas = computed(() => { | ||
18 | + return schemasMap.get((props.value as WidgetComponentType) || 'text-component-1'); | ||
19 | + }); | ||
20 | + | ||
12 | const [registerForm, method] = useForm({ | 21 | const [registerForm, method] = useForm({ |
13 | - schemas: modeTwo, | ||
14 | showActionButtonGroup: false, | 22 | showActionButtonGroup: false, |
15 | labelWidth: 120, | 23 | labelWidth: 120, |
16 | baseColProps: { | 24 | baseColProps: { |
@@ -45,6 +53,6 @@ | @@ -45,6 +53,6 @@ | ||
45 | title="选项" | 53 | title="选项" |
46 | width="60%" | 54 | width="60%" |
47 | > | 55 | > |
48 | - <BasicForm @register="registerForm" /> | 56 | + <BasicForm @register="registerForm" :schemas="getSchemas" /> |
49 | </BasicModal> | 57 | </BasicModal> |
50 | </template> | 58 | </template> |
1 | +import { InstrumentComponentType } from '../../components/InstrumentComponent/dashBoardComponent.config'; | ||
2 | +import { DigitalDashBoardComponentType } from '../../components/InstrumentComponent/digitalDashBoard.config'; | ||
3 | +import { TextComponentType } from '../../components/TextComponent/config'; | ||
1 | import { FormSchema } from '/@/components/Form'; | 4 | import { FormSchema } from '/@/components/Form'; |
2 | export enum defaultOptions { | 5 | export enum defaultOptions { |
3 | fontColor = '#rer', | 6 | fontColor = '#rer', |
4 | } | 7 | } |
5 | 8 | ||
9 | +export type WidgetComponentType = | ||
10 | + | TextComponentType | ||
11 | + | InstrumentComponentType | ||
12 | + | DigitalDashBoardComponentType; | ||
13 | + | ||
6 | export enum visualOptionField { | 14 | export enum visualOptionField { |
7 | FONT_COLOR = 'fontColor', | 15 | FONT_COLOR = 'fontColor', |
8 | UNIT = 'unit', | 16 | UNIT = 'unit', |
@@ -137,3 +145,13 @@ export const modeFour: FormSchema[] = [ | @@ -137,3 +145,13 @@ export const modeFour: FormSchema[] = [ | ||
137 | }, | 145 | }, |
138 | }, | 146 | }, |
139 | ]; | 147 | ]; |
148 | + | ||
149 | +export const schemasMap = new Map<WidgetComponentType, FormSchema[]>(); | ||
150 | + | ||
151 | +schemasMap.set('text-component-1', modeOne); | ||
152 | +schemasMap.set('text-component-2', modeOne); | ||
153 | +schemasMap.set('text-component-3', modeOne); | ||
154 | +schemasMap.set('text-component-4', modeTwo); | ||
155 | +schemasMap.set('text-component-4', modeTwo); | ||
156 | +schemasMap.set('instrument-component-1', modeOne); | ||
157 | +schemasMap.set('instrument-component-2', modeThree); |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | import { Button, PageHeader } from 'ant-design-vue'; | 2 | import { Button, PageHeader } from 'ant-design-vue'; |
3 | - import { GridItem, GridLayout, Layout } 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'; |
6 | import BaseWidgetHeader from '../components/WidgetHeader/BaseWidgetHeader.vue'; | 6 | import BaseWidgetHeader from '../components/WidgetHeader/BaseWidgetHeader.vue'; |
7 | import { DropMenu } from '/@/components/Dropdown'; | 7 | import { DropMenu } from '/@/components/Dropdown'; |
8 | import DataBindModal from './components/DataBindModal.vue'; | 8 | import DataBindModal from './components/DataBindModal.vue'; |
9 | import { useModal } from '/@/components/Modal'; | 9 | import { useModal } from '/@/components/Modal'; |
10 | - import { MoreActionEvent } from '../config/config'; | ||
11 | - import { deleteDataComponent, getDataComponent } from '/@/api/dataBoard'; | 10 | + import { DEFAULT_WIDGET_HEIGHT, DEFAULT_WIDGET_WIDTH, MoreActionEvent } from '../config/config'; |
11 | + import { | ||
12 | + addDataComponent, | ||
13 | + deleteDataComponent, | ||
14 | + getDataComponent, | ||
15 | + updateDataBoardLayout, | ||
16 | + } from '/@/api/dataBoard'; | ||
12 | import { useRoute } from 'vue-router'; | 17 | import { useRoute } from 'vue-router'; |
13 | import { computed, unref } from '@vue/reactivity'; | 18 | import { computed, unref } from '@vue/reactivity'; |
14 | - import { DataComponentRecord, DataSource, Layout as LayoutRecord } from '/@/api/dataBoard/model'; | 19 | + import { DataComponentRecord, DataSource } from '/@/api/dataBoard/model'; |
15 | import { frontComponentMap, FrontComponentType } from './config/help'; | 20 | import { frontComponentMap, FrontComponentType } from './config/help'; |
16 | import { useMessage } from '/@/hooks/web/useMessage'; | 21 | import { useMessage } from '/@/hooks/web/useMessage'; |
17 | - const handleBack = () => {}; | ||
18 | - | ||
19 | - type DataBoardRecord = DataComponentRecord & { layout: LayoutRecord }; | ||
20 | - | ||
21 | - type DataBoardLayoutInfo = Layout & { | ||
22 | - record: DataComponentRecord & { width: number; height: number }; | ||
23 | - }; | 22 | + import { DataBoardLayoutInfo } from '../types/type'; |
24 | 23 | ||
25 | const ROUTE = useRoute(); | 24 | const ROUTE = useRoute(); |
26 | 25 | ||
27 | - const { createMessage } = useMessage(); | 26 | + const { createMessage, createConfirm } = useMessage(); |
28 | const getBoardId = computed(() => { | 27 | const getBoardId = computed(() => { |
29 | return (ROUTE.params as { id: string }).id; | 28 | return (ROUTE.params as { id: string }).id; |
30 | }); | 29 | }); |
@@ -74,7 +73,7 @@ | @@ -74,7 +73,7 @@ | ||
74 | height, | 73 | height, |
75 | }; | 74 | }; |
76 | }); | 75 | }); |
77 | - console.log(unref(dataBoardList)); | 76 | + |
78 | nextTick(() => { | 77 | nextTick(() => { |
79 | const updateFn = widgetEl.get(i); | 78 | const updateFn = widgetEl.get(i); |
80 | if (updateFn) updateFn(); | 79 | if (updateFn) updateFn(); |
@@ -83,6 +82,7 @@ | @@ -83,6 +82,7 @@ | ||
83 | 82 | ||
84 | const itemResized = (i: string, newH: number, newW: number, newHPx: number, newWPx: number) => { | 83 | const itemResized = (i: string, newH: number, newW: number, newHPx: number, newWPx: number) => { |
85 | updateSize(i, newH, newW, newHPx, newWPx); | 84 | updateSize(i, newH, newW, newHPx, newWPx); |
85 | + console.log({ newH, newW, newHPx, newWPx }); | ||
86 | }; | 86 | }; |
87 | 87 | ||
88 | const itemContainerResized = ( | 88 | const itemContainerResized = ( |
@@ -111,8 +111,15 @@ | @@ -111,8 +111,15 @@ | ||
111 | const [register, { openModal }] = useModal(); | 111 | const [register, { openModal }] = useModal(); |
112 | 112 | ||
113 | const handleMoreAction = (event: DropMenu, id: string) => { | 113 | const handleMoreAction = (event: DropMenu, id: string) => { |
114 | - if (event.event === MoreActionEvent.EDIT) openModal(true); | ||
115 | - if (event.event === MoreActionEvent.DELETE) handleDelete(id); | 114 | + if (event.event === MoreActionEvent.DELETE) { |
115 | + createConfirm({ | ||
116 | + iconType: 'warning', | ||
117 | + content: '是否确认删除?', | ||
118 | + onOk: () => handleDelete(id), | ||
119 | + }); | ||
120 | + } | ||
121 | + if (event.event === MoreActionEvent.EDIT) handleUpdate(id); | ||
122 | + if (event.event === MoreActionEvent.COPY) handleCopy(id); | ||
116 | }; | 123 | }; |
117 | 124 | ||
118 | const handleOpenCreatePanel = () => { | 125 | const handleOpenCreatePanel = () => { |
@@ -124,7 +131,12 @@ | @@ -124,7 +131,12 @@ | ||
124 | const data = await getDataComponent(unref(getBoardId)); | 131 | const data = await getDataComponent(unref(getBoardId)); |
125 | dataBoardList.value = data.data.componentData.map((item) => { | 132 | dataBoardList.value = data.data.componentData.map((item) => { |
126 | const index = data.data.componentLayout.findIndex((each) => item.id === each.id); | 133 | const index = data.data.componentLayout.findIndex((each) => item.id === each.id); |
127 | - const layout = data.data.componentLayout[index]; | 134 | + let layout; |
135 | + if (!~index) { | ||
136 | + layout = {}; | ||
137 | + } else { | ||
138 | + layout = data.data.componentLayout[index]; | ||
139 | + } | ||
128 | return { | 140 | return { |
129 | i: item.id, | 141 | i: item.id, |
130 | w: layout.w || defaultWidth, | 142 | w: layout.w || defaultWidth, |
@@ -138,6 +150,7 @@ | @@ -138,6 +150,7 @@ | ||
138 | }, | 150 | }, |
139 | }; | 151 | }; |
140 | }); | 152 | }); |
153 | + console.log(unref(dataBoardList)); | ||
141 | } catch (error) {} | 154 | } catch (error) {} |
142 | }; | 155 | }; |
143 | 156 | ||
@@ -153,13 +166,40 @@ | @@ -153,13 +166,40 @@ | ||
153 | return component?.transformConfig(component.ComponentConfig, record, dataSourceRecord); | 166 | return component?.transformConfig(component.ComponentConfig, record, dataSourceRecord); |
154 | }; | 167 | }; |
155 | 168 | ||
169 | + const handleUpdate = async (id: string) => { | ||
170 | + const record = unref(dataBoardList).find((item) => item.i === id); | ||
171 | + openModal(true, { isEdit: true, ...record }); | ||
172 | + }; | ||
173 | + | ||
174 | + const handleCopy = async (id: string) => { | ||
175 | + const record = unref(dataBoardList).find((item) => item.i === id); | ||
176 | + console.log({ record }); | ||
177 | + try { | ||
178 | + const data = await addDataComponent({ | ||
179 | + boardId: unref(getBoardId), | ||
180 | + record: { | ||
181 | + dataBoardId: unref(getBoardId), | ||
182 | + frontId: record?.record.frontId, | ||
183 | + dataSource: record?.record.dataSource, | ||
184 | + }, | ||
185 | + }); | ||
186 | + createMessage.success('复制成功'); | ||
187 | + const id = data.data.id; | ||
188 | + await updateDataBoardLayout({ | ||
189 | + boardId: unref(getBoardId), | ||
190 | + layout: [{ id, w: DEFAULT_WIDGET_WIDTH, h: DEFAULT_WIDGET_HEIGHT, x: 0, y: 0 }], | ||
191 | + }); | ||
192 | + getDataBoardComponent(); | ||
193 | + } catch (error) {} | ||
194 | + }; | ||
195 | + | ||
156 | const handleDelete = async (id: string) => { | 196 | const handleDelete = async (id: string) => { |
157 | try { | 197 | try { |
158 | await deleteDataComponent([id]); | 198 | await deleteDataComponent([id]); |
159 | createMessage.success('删除成功'); | 199 | createMessage.success('删除成功'); |
160 | await getDataBoardComponent(); | 200 | await getDataBoardComponent(); |
161 | } catch (error) { | 201 | } catch (error) { |
162 | - createMessage.error('删除失败'); | 202 | + // createMessage.error('删除失败'); |
163 | } | 203 | } |
164 | }; | 204 | }; |
165 | 205 | ||
@@ -170,11 +210,14 @@ | @@ -170,11 +210,14 @@ | ||
170 | 210 | ||
171 | <template> | 211 | <template> |
172 | <section class="bg-light-50 flex flex-col overflow-hidden h-full w-full"> | 212 | <section class="bg-light-50 flex flex-col overflow-hidden h-full w-full"> |
173 | - <PageHeader title="水电表看板" @back="handleBack"> | 213 | + <PageHeader title="水电表看板"> |
174 | <template #extra> | 214 | <template #extra> |
175 | <Button type="primary" @click="handleOpenCreatePanel">创建组件</Button> | 215 | <Button type="primary" @click="handleOpenCreatePanel">创建组件</Button> |
176 | </template> | 216 | </template> |
177 | - <div>已创建组件: 3个</div> | 217 | + <div> |
218 | + <span class="mr-3 text-gray-400">已创建组件:</span> | ||
219 | + <span class="text-cyan-400"> {{ dataBoardList.length }}个</span> | ||
220 | + </div> | ||
178 | </PageHeader> | 221 | </PageHeader> |
179 | <section class="flex-1"> | 222 | <section class="flex-1"> |
180 | <GridLayout | 223 | <GridLayout |
@@ -159,7 +159,7 @@ | @@ -159,7 +159,7 @@ | ||
159 | {{ item.viewType === ViewType.PRIVATE_VIEW ? '私有看板' : '公共看板' }} | 159 | {{ item.viewType === ViewType.PRIVATE_VIEW ? '私有看板' : '公共看板' }} |
160 | </span> | 160 | </span> |
161 | <span v-if="item.viewType === ViewType.PUBLIC_VIEW"> | 161 | <span v-if="item.viewType === ViewType.PUBLIC_VIEW"> |
162 | - <Tooltip title="分享链接"> | 162 | + <Tooltip title="点击复制分享链接"> |
163 | <ShareAltOutlined class="ml-2" @click="handleCopyShareUrl(item)" /> | 163 | <ShareAltOutlined class="ml-2" @click="handleCopyShareUrl(item)" /> |
164 | </Tooltip> | 164 | </Tooltip> |
165 | </span> | 165 | </span> |