Commit 0f7e9f5e0b28608f4d5e638f7f5044086315b1b4

Authored by fengwotao
2 parents cd51bd75 bc34d678

Merge branch 'main' into dev-ft

@@ -14,8 +14,8 @@ VITE_PUBLIC_PATH = / @@ -14,8 +14,8 @@ VITE_PUBLIC_PATH = /
14 # VITE_PROXY = [["/api","http://101.133.234.90:8080/api"]] 14 # VITE_PROXY = [["/api","http://101.133.234.90:8080/api"]]
15 # 线上测试环境 15 # 线上测试环境
16 # VITE_PROXY = [["/api","http://localhost:8080/api"],["/thingskit-drawio","http://localhost:3000/"]] 16 # VITE_PROXY = [["/api","http://localhost:8080/api"],["/thingskit-drawio","http://localhost:3000/"]]
17 -# VITE_PROXY = [["/api","https://dev.thingskit.com/api"],["/thingskit-drawio","http://localhost:3000/"]]  
18 -VITE_PROXY = [["/api","http://121.37.251.8:8080/api"],["/thingskit-drawio","http://localhost:3000/"]] 17 +VITE_PROXY = [["/api","https://dev.thingskit.com/api"],["/thingskit-drawio","http://localhost:3000/"]]
  18 +# VITE_PROXY = [["/api","http://121.37.251.8:8080/api"],["/thingskit-drawio","http://localhost:3000/"]]
19 # VITE_PROXY = [["/api","http://192.168.10.106:8080/api"],["/thingskit-drawio","http://192.168.10.106:8080/api"]] 19 # VITE_PROXY = [["/api","http://192.168.10.106:8080/api"],["/thingskit-drawio","http://192.168.10.106:8080/api"]]
20 20
21 # 实时数据的ws地址 21 # 实时数据的ws地址
1 import { 1 import {
2 AddDataBoardParams, 2 AddDataBoardParams,
3 AddDataComponentParams, 3 AddDataComponentParams,
  4 + ComponentInfoDetail,
4 DataBoardList, 5 DataBoardList,
5 DataComponentRecord, 6 DataComponentRecord,
6 GetDataBoardParams, 7 GetDataBoardParams,
@@ -103,12 +104,10 @@ export const updateDataBoardLayout = (params: UpdateDataBoardLayoutParams) => { @@ -103,12 +104,10 @@ export const updateDataBoardLayout = (params: UpdateDataBoardLayoutParams) => {
103 * @returns 104 * @returns
104 */ 105 */
105 export const getDataComponent = (params: string) => { 106 export const getDataComponent = (params: string) => {
106 - return defHttp.get<{ data: { componentData: DataComponentRecord[]; componentLayout: Layout[] } }>(  
107 - {  
108 - url: `${DataComponentUrl.GET_DATA_COMPONENT}/${params}`,  
109 - // params: { boardId: params },  
110 - }  
111 - ); 107 + return defHttp.get<ComponentInfoDetail>({
  108 + url: `${DataComponentUrl.GET_DATA_COMPONENT}/${params}`,
  109 + // params: { boardId: params },
  110 + });
112 }; 111 };
113 112
114 export const addDataComponent = (params: AddDataComponentParams) => { 113 export const addDataComponent = (params: AddDataComponentParams) => {
@@ -151,7 +150,7 @@ export const updateDataComponent = (params: UpdateDataComponentParams) => { @@ -151,7 +150,7 @@ export const updateDataComponent = (params: UpdateDataComponentParams) => {
151 */ 150 */
152 export const getShareBoardComponentInfo = (params: { boardId: string; tenantId: string }) => { 151 export const getShareBoardComponentInfo = (params: { boardId: string; tenantId: string }) => {
153 const { boardId, tenantId } = params; 152 const { boardId, tenantId } = params;
154 - return defHttp.get({ 153 + return defHttp.get<ComponentInfoDetail>({
155 url: `${DataBoardShareUrl.GET_DATA_COMPONENT}/${boardId}/${tenantId}`, 154 url: `${DataBoardShareUrl.GET_DATA_COMPONENT}/${boardId}/${tenantId}`,
156 }); 155 });
157 }; 156 };
@@ -136,3 +136,7 @@ export interface MasterDeviceList { @@ -136,3 +136,7 @@ export interface MasterDeviceList {
136 id: string; 136 id: string;
137 name: string; 137 name: string;
138 } 138 }
  139 +
  140 +export interface ComponentInfoDetail {
  141 + data: { componentData: DataComponentRecord[]; componentLayout: Layout[] };
  142 +}
@@ -38,6 +38,10 @@ @@ -38,6 +38,10 @@
38 type: Object as PropType<RadioRecord>, 38 type: Object as PropType<RadioRecord>,
39 default: () => DEFAULT_RADIO_RECORD, 39 default: () => DEFAULT_RADIO_RECORD,
40 }, 40 },
  41 + random: {
  42 + type: Boolean,
  43 + default: true,
  44 + },
41 }); 45 });
42 46
43 const getControlsWidgetId = () => `widget-chart-${props.value.id}`; 47 const getControlsWidgetId = () => `widget-chart-${props.value.id}`;
@@ -85,13 +89,24 @@ @@ -85,13 +89,24 @@
85 } 89 }
86 ); 90 );
87 91
  92 + let timeout: Nullable<number> = null;
  93 +
  94 + function handleRandomValue() {
  95 + const newValue = Math.floor(Math.random() * 100);
  96 + const updateFn = getUpdateValueFn(props.layout.componentType);
  97 + unref(chartRef)?.setOption((updateFn(newValue) as unknown as EChartsOption) || {});
  98 + }
  99 +
88 onMounted(() => { 100 onMounted(() => {
89 initChart(); 101 initChart();
90 props.add && props.add(props.value.id, update); 102 props.add && props.add(props.value.id, update);
  103 + if (props.random) timeout = setInterval(handleRandomValue, 2000) as unknown as number;
91 }); 104 });
92 105
93 onUnmounted(() => { 106 onUnmounted(() => {
94 unref(chartRef)?.clear(); 107 unref(chartRef)?.clear();
  108 + clearInterval(timeout as number);
  109 + timeout = null;
95 }); 110 });
96 111
97 defineExpose({ update }); 112 defineExpose({ update });
1 <script lang="ts" setup> 1 <script lang="ts" setup>
2 - import { computed } from 'vue'; 2 + import { computed, onMounted, onUnmounted, ref, unref } from 'vue';
3 import { Space, Tooltip } from 'ant-design-vue'; 3 import { Space, Tooltip } from 'ant-design-vue';
4 - import type { DigitalDashBoardLayout, DigitalDashBoardValue } from './digitalDashBoard.config'; 4 + import {
  5 + DigitalComponentDefaultConfig,
  6 + DigitalDashBoardLayout,
  7 + DigitalDashBoardValue,
  8 + } from './digitalDashBoard.config';
5 import { dateUtil } from '/@/utils/dateUtil'; 9 import { dateUtil } from '/@/utils/dateUtil';
6 import { 10 import {
7 fontSize, 11 fontSize,
8 RadioRecord, 12 RadioRecord,
9 DEFAULT_DATE_FORMAT, 13 DEFAULT_DATE_FORMAT,
10 DEFAULT_RADIO_RECORD, 14 DEFAULT_RADIO_RECORD,
  15 + DEFAULT_ANIMATION_INTERVAL,
11 } from '../../detail/config/util'; 16 } from '../../detail/config/util';
  17 + import { isNaN } from 'lodash';
12 18
13 const props = defineProps<{ 19 const props = defineProps<{
14 layout: DigitalDashBoardLayout; 20 layout: DigitalDashBoardLayout;
15 value: DigitalDashBoardValue; 21 value: DigitalDashBoardValue;
16 radio?: RadioRecord; 22 radio?: RadioRecord;
  23 + random?: boolean;
17 }>(); 24 }>();
18 25
  26 + const changeValue = ref(0);
  27 +
  28 + const getPropsValue = computed(() => {
  29 + return { value: unref(changeValue), ...DigitalComponentDefaultConfig, ...props.value };
  30 + });
  31 +
19 const integerPart = computed(() => { 32 const integerPart = computed(() => {
20 - let { value = 0 } = props.value; 33 + let { value = 0 } = unref(getPropsValue);
21 const { max = 5 } = props.layout; 34 const { max = 5 } = props.layout;
22 if (isNaN(value)) value = 0; 35 if (isNaN(value)) value = 0;
23 let _value = Number(value).toFixed(2).split('.')[0]; 36 let _value = Number(value).toFixed(2).split('.')[0];
@@ -28,7 +41,7 @@ @@ -28,7 +41,7 @@
28 }); 41 });
29 42
30 const decimalPart = computed(() => { 43 const decimalPart = computed(() => {
31 - let { value = 0 } = props.value; 44 + let { value = 0 } = unref(getPropsValue);
32 const { keepNumber = 2 } = props.layout; 45 const { keepNumber = 2 } = props.layout;
33 if (isNaN(value)) value = 0; 46 if (isNaN(value)) value = 0;
34 let _value = Number(value)?.toFixed(2).split('.')[1]; 47 let _value = Number(value)?.toFixed(2).split('.')[1];
@@ -43,6 +56,23 @@ @@ -43,6 +56,23 @@
43 const { radio } = props.radio || DEFAULT_RADIO_RECORD; 56 const { radio } = props.radio || DEFAULT_RADIO_RECORD;
44 return radio; 57 return radio;
45 }); 58 });
  59 +
  60 + let timeout: Nullable<number> = null;
  61 +
  62 + const handleRandom = () => {
  63 + const newValue = Math.floor(Math.random() * 100);
  64 + changeValue.value = newValue;
  65 + };
  66 +
  67 + onMounted(() => {
  68 + if (props.random)
  69 + timeout = setInterval(handleRandom, DEFAULT_ANIMATION_INTERVAL) as unknown as number;
  70 + });
  71 +
  72 + onUnmounted(() => {
  73 + clearInterval(timeout as number);
  74 + timeout = null;
  75 + });
46 </script> 76 </script>
47 77
48 <template> 78 <template>
@@ -56,7 +86,7 @@ @@ -56,7 +86,7 @@
56 :key="number" 86 :key="number"
57 class="border border-gray-400 p-2" 87 class="border border-gray-400 p-2"
58 :style="{ 88 :style="{
59 - color: props.value.fontColor, 89 + color: getPropsValue.fontColor,
60 fontSize: fontSize({ radio: getRadio, basic: 20 }), 90 fontSize: fontSize({ radio: getRadio, basic: 20 }),
61 }" 91 }"
62 > 92 >
@@ -69,7 +99,7 @@ @@ -69,7 +99,7 @@
69 :key="number" 99 :key="number"
70 class="border border-gray-400 p-1" 100 class="border border-gray-400 p-1"
71 :style="{ 101 :style="{
72 - color: props.value.fontColor, 102 + color: getPropsValue.fontColor,
73 fontSize: fontSize({ radio: getRadio, basic: 18 }), 103 fontSize: fontSize({ radio: getRadio, basic: 18 }),
74 }" 104 }"
75 > 105 >
@@ -84,7 +114,7 @@ @@ -84,7 +114,7 @@
84 :style="{ fontSize: fontSize({ radio: getRadio, basic: 18 }) }" 114 :style="{ fontSize: fontSize({ radio: getRadio, basic: 18 }) }"
85 > 115 >
86 <span>{{ props.value.name || '电表' }}</span> 116 <span>{{ props.value.name || '电表' }}</span>
87 - <span class="px-1">({{ 'kw/h' }})</span> 117 + <span class="px-1">({{ getPropsValue.unit }})</span>
88 </div> 118 </div>
89 <div 119 <div
90 class="text-center mt-1 text-gray-400 text-xs truncate" 120 class="text-center mt-1 text-gray-400 text-xs truncate"
1 import { EChartsOption } from 'echarts'; 1 import { EChartsOption } from 'echarts';
2 import { fontSize } from '../../detail/config/util'; 2 import { fontSize } from '../../detail/config/util';
3 import { Gradient, visualOptionField } from '../../detail/config/visualOptions'; 3 import { Gradient, visualOptionField } from '../../detail/config/visualOptions';
4 -import { DataComponentRecord, DataSource, GradientInfo } from '/@/api/dataBoard/model'; 4 +import {
  5 + ComponentInfo,
  6 + DataComponentRecord,
  7 + DataSource,
  8 + GradientInfo,
  9 +} from '/@/api/dataBoard/model';
5 import { isArray } from '/@/utils/is'; 10 import { isArray } from '/@/utils/is';
6 import { buildUUID } from '/@/utils/uuid'; 11 import { buildUUID } from '/@/utils/uuid';
7 12
@@ -36,11 +41,13 @@ export interface DashboardComponentLayout { @@ -36,11 +41,13 @@ export interface DashboardComponentLayout {
36 componentType: InstrumentComponentType; 41 componentType: InstrumentComponentType;
37 } 42 }
38 43
39 -export const instrumentComponent1 = (params?: {  
40 - value: number;  
41 - unit: string;  
42 - fontColor: string;  
43 -}): EChartsOption => { 44 +export enum GradientColor {
  45 + FIRST = '#67e0e3',
  46 + SECOND = '#37a2da',
  47 + THIRD = '#fd666d',
  48 +}
  49 +
  50 +export const instrumentComponent1 = (params?: Partial<ComponentInfo>): EChartsOption => {
44 const { value = 10, unit = '°C' } = params || {}; 51 const { value = 10, unit = '°C' } = params || {};
45 return { 52 return {
46 series: [ 53 series: [
@@ -108,7 +115,7 @@ export const instrumentComponent1 = (params?: { @@ -108,7 +115,7 @@ export const instrumentComponent1 = (params?: {
108 }, 115 },
109 data: [ 116 data: [
110 { 117 {
111 - value: value, 118 + value: value as number,
112 }, 119 },
113 ], 120 ],
114 }, 121 },
@@ -146,7 +153,7 @@ export const instrumentComponent1 = (params?: { @@ -146,7 +153,7 @@ export const instrumentComponent1 = (params?: {
146 }, 153 },
147 data: [ 154 data: [
148 { 155 {
149 - value: value, 156 + value: value as number,
150 }, 157 },
151 ], 158 ],
152 }, 159 },
@@ -154,16 +161,11 @@ export const instrumentComponent1 = (params?: { @@ -154,16 +161,11 @@ export const instrumentComponent1 = (params?: {
154 }; 161 };
155 }; 162 };
156 163
157 -export const instrumentComponent2 = (params?: {  
158 - gradient: GradientInfo[];  
159 - value: number;  
160 - unit: string;  
161 - fontColor: string;  
162 -}): EChartsOption => {  
163 - const { gradient = [], value = 0, unit = 'km/h' } = params || {};  
164 - const firstRecord = getGradient(Gradient.FIRST, gradient);  
165 - const secondRecord = getGradient(Gradient.SECOND, gradient);  
166 - const thirdRecord = getGradient(Gradient.THIRD, gradient); 164 +export const instrumentComponent2 = (params?: Partial<ComponentInfo>): EChartsOption => {
  165 + const { gradientInfo = [], value = 0, unit = 'km/h' } = params || {};
  166 + const firstRecord = getGradient(Gradient.FIRST, gradientInfo);
  167 + const secondRecord = getGradient(Gradient.SECOND, gradientInfo);
  168 + const thirdRecord = getGradient(Gradient.THIRD, gradientInfo);
167 169
168 let max = thirdRecord?.value || secondRecord?.value || firstRecord?.value || 70; 170 let max = thirdRecord?.value || secondRecord?.value || firstRecord?.value || 70;
169 max = Number(1 + Array(String(max).length).fill(0).join('')); 171 max = Number(1 + Array(String(max).length).fill(0).join(''));
@@ -182,9 +184,9 @@ export const instrumentComponent2 = (params?: { @@ -182,9 +184,9 @@ export const instrumentComponent2 = (params?: {
182 lineStyle: { 184 lineStyle: {
183 width: 20, 185 width: 20,
184 color: [ 186 color: [
185 - [firstGradient, firstRecord?.color || '#67e0e3'],  
186 - [secondGradient, secondRecord?.color || '#37a2da'],  
187 - [1, thirdRecord?.color || '#fd666d'], 187 + [firstGradient, firstRecord?.color || GradientColor.FIRST],
  188 + [secondGradient, secondRecord?.color || GradientColor.SECOND],
  189 + [1, thirdRecord?.color || GradientColor.THIRD],
188 ], 190 ],
189 }, 191 },
190 }, 192 },
@@ -223,7 +225,7 @@ export const instrumentComponent2 = (params?: { @@ -223,7 +225,7 @@ export const instrumentComponent2 = (params?: {
223 }, 225 },
224 data: [ 226 data: [
225 { 227 {
226 - value: value, 228 + value: value as number,
227 }, 229 },
228 ], 230 ],
229 }, 231 },
@@ -293,14 +295,23 @@ export const update_instrument_2_value = (value) => { @@ -293,14 +295,23 @@ export const update_instrument_2_value = (value) => {
293 295
294 function setGradientInfo(dataSource: DataSource) { 296 function setGradientInfo(dataSource: DataSource) {
295 const componentInfo = dataSource.componentInfo; 297 const componentInfo = dataSource.componentInfo;
296 - return instrumentComponent2({  
297 - unit: componentInfo.unit,  
298 - value: 0,  
299 - gradient: componentInfo.gradientInfo,  
300 - fontColor: componentInfo.fontColor,  
301 - }); 298 + return instrumentComponent2(componentInfo);
302 } 299 }
303 300
  301 +export const Instrument1DefaultConfig: Partial<ComponentInfo> = {
  302 + fontColor: '#FD7347',
  303 +};
  304 +
  305 +export const Instrument2DefaultConfig: Partial<ComponentInfo> = {
  306 + fontColor: GradientColor.FIRST,
  307 + unit: 'km/h',
  308 + gradientInfo: [
  309 + { key: Gradient.FIRST, value: 30, color: GradientColor.FIRST },
  310 + { key: Gradient.SECOND, value: 70, color: GradientColor.SECOND },
  311 + { key: Gradient.THIRD, value: 80, color: GradientColor.THIRD },
  312 + ],
  313 +};
  314 +
304 export const transformDashboardComponentConfig = ( 315 export const transformDashboardComponentConfig = (
305 config: DashboardComponentLayout, 316 config: DashboardComponentLayout,
306 record: DataComponentRecord, 317 record: DataComponentRecord,
  1 +import { ComponentInfo } from '/@/api/dataBoard/model';
  2 +
1 export type DigitalDashBoardComponentType = 'digital-dashboard-component'; 3 export type DigitalDashBoardComponentType = 'digital-dashboard-component';
2 4
3 export interface DigitalDashBoardLayout { 5 export interface DigitalDashBoardLayout {
@@ -12,3 +14,8 @@ export interface DigitalDashBoardValue { @@ -12,3 +14,8 @@ export interface DigitalDashBoardValue {
12 value?: number; 14 value?: number;
13 fontColor?: string; 15 fontColor?: string;
14 } 16 }
  17 +
  18 +export const DigitalComponentDefaultConfig: Partial<ComponentInfo> = {
  19 + fontColor: '#000',
  20 + unit: 'kw/h',
  21 +};
1 import { EChartsOption } from 'echarts'; 1 import { EChartsOption } from 'echarts';
2 import { Component } from 'vue'; 2 import { Component } from 'vue';
3 import { WidgetComponentType } from '../../detail/config/visualOptions'; 3 import { WidgetComponentType } from '../../detail/config/visualOptions';
4 -import { instrumentComponent1, instrumentComponent2 } from './dashBoardComponent.config'; 4 +import {
  5 + Instrument1DefaultConfig,
  6 + Instrument2DefaultConfig,
  7 + instrumentComponent1,
  8 + instrumentComponent2,
  9 + InstrumentComponentType,
  10 +} from './dashBoardComponent.config';
5 import DashBoardComponent from './DashBoardComponent.vue'; 11 import DashBoardComponent from './DashBoardComponent.vue';
6 import DigitalDashBoard from './DigitalDashBoard.vue'; 12 import DigitalDashBoard from './DigitalDashBoard.vue';
7 import { buildUUID } from '/@/utils/uuid'; 13 import { buildUUID } from '/@/utils/uuid';
8 14
9 export interface DashboardComponentLayout { 15 export interface DashboardComponentLayout {
10 chartOption: EChartsOption; 16 chartOption: EChartsOption;
  17 + componentType: InstrumentComponentType;
11 } 18 }
12 19
13 interface InstrumentComponentConfig { 20 interface InstrumentComponentConfig {
@@ -20,13 +27,19 @@ interface InstrumentComponentConfig { @@ -20,13 +27,19 @@ interface InstrumentComponentConfig {
20 export const instrumentComponentConfig: InstrumentComponentConfig[] = [ 27 export const instrumentComponentConfig: InstrumentComponentConfig[] = [
21 { 28 {
22 id: 'instrument-component-1', 29 id: 'instrument-component-1',
23 - layout: { chartOption: instrumentComponent1() }, 30 + layout: {
  31 + chartOption: instrumentComponent1(Instrument1DefaultConfig),
  32 + componentType: 'instrument-component-1',
  33 + },
24 component: DashBoardComponent, 34 component: DashBoardComponent,
25 value: { id: buildUUID() }, 35 value: { id: buildUUID() },
26 }, 36 },
27 { 37 {
28 id: 'instrument-component-2', 38 id: 'instrument-component-2',
29 - layout: { chartOption: instrumentComponent2() }, 39 + layout: {
  40 + chartOption: instrumentComponent2(Instrument2DefaultConfig),
  41 + componentType: 'instrument-component-2',
  42 + },
30 component: DashBoardComponent, 43 component: DashBoardComponent,
31 value: { id: buildUUID() }, 44 value: { id: buildUUID() },
32 }, 45 },
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 DEFAULT_RADIO_RECORD, 7 DEFAULT_RADIO_RECORD,
8 DEFAULT_DATE_FORMAT, 8 DEFAULT_DATE_FORMAT,
9 } from '../../detail/config/util'; 9 } from '../../detail/config/util';
10 - import type { TextComponentLayout, TextComponentValue } from './config'; 10 + import { TextComponentDefaultConfig, TextComponentLayout, TextComponentValue } from './config';
11 import { SvgIcon } from '/@/components/Icon'; 11 import { SvgIcon } from '/@/components/Icon';
12 import { dateUtil } from '/@/utils/dateUtil'; 12 import { dateUtil } from '/@/utils/dateUtil';
13 const props = defineProps({ 13 const props = defineProps({
@@ -17,7 +17,8 @@ @@ -17,7 +17,8 @@
17 }, 17 },
18 value: { 18 value: {
19 type: Object as PropType<TextComponentValue>, 19 type: Object as PropType<TextComponentValue>,
20 - default: () => ({ name: '温度', value: 123 } as TextComponentValue), 20 + default: () =>
  21 + ({ ...TextComponentDefaultConfig, name: '温度', value: 123 } as TextComponentValue),
21 }, 22 },
22 radio: { 23 radio: {
23 type: Object as PropType<RadioRecord>, 24 type: Object as PropType<RadioRecord>,
@@ -65,8 +66,8 @@ @@ -65,8 +66,8 @@
65 prefix="iconfont" 66 prefix="iconfont"
66 :style="{ 67 :style="{
67 color: props.value.iconColor, 68 color: props.value.iconColor,
68 - width: fontSize({ radio: getRadio, basic: 50 }),  
69 - height: fontSize({ radio: getRadio, basic: 50 }), 69 + width: fontSize({ radio: getRadio, basic: 50, min: 16 }),
  70 + height: fontSize({ radio: getRadio, basic: 50, min: 16 }),
70 }" 71 }"
71 /> 72 />
72 </div> 73 </div>
1 -import { formatToDateTime } from '/@/utils/dateUtil';  
2 -import { DataComponentRecord, DataSource } from '/@/api/dataBoard/model'; 1 +import { ComponentInfo, DataComponentRecord, DataSource } from '/@/api/dataBoard/model';
3 export interface TextComponentLayout { 2 export interface TextComponentLayout {
4 id: string; 3 id: string;
5 base?: boolean; 4 base?: boolean;
@@ -26,28 +25,21 @@ export type TextComponentType = @@ -26,28 +25,21 @@ export type TextComponentType =
26 | 'text-component-4' 25 | 'text-component-4'
27 | 'text-component-5'; 26 | 'text-component-5';
28 27
29 -type TextComponentDefault = TextComponentLayout & { value: TextComponentValue }; 28 +type TextComponentDefault = TextComponentLayout;
30 29
31 export const TextComponent1Config: TextComponentDefault = { 30 export const TextComponent1Config: TextComponentDefault = {
32 id: 'text-component-1', 31 id: 'text-component-1',
33 base: true, 32 base: true,
34 - value: { value: 123, name: '温度' },  
35 }; 33 };
36 34
37 export const TextComponent2Config: TextComponentDefault = { 35 export const TextComponent2Config: TextComponentDefault = {
38 id: 'text-component-2', 36 id: 'text-component-2',
39 base: false, 37 base: false,
40 - value: { value: 123, name: '温度' },  
41 }; 38 };
42 export const TextComponent3Config: TextComponentDefault = { 39 export const TextComponent3Config: TextComponentDefault = {
43 id: 'text-component-3', 40 id: 'text-component-3',
44 base: false, 41 base: false,
45 showUpdate: true, 42 showUpdate: true,
46 - value: {  
47 - value: 123,  
48 - name: '温度',  
49 - updateTime: formatToDateTime(new Date(), 'YYYY-MM-DD HH:mm:ss'),  
50 - },  
51 }; 43 };
52 export const TextComponent4Config: TextComponentDefault = { 44 export const TextComponent4Config: TextComponentDefault = {
53 id: 'text-component-4', 45 id: 'text-component-4',
@@ -55,19 +47,19 @@ export const TextComponent4Config: TextComponentDefault = { @@ -55,19 +47,19 @@ export const TextComponent4Config: TextComponentDefault = {
55 showIcon: true, 47 showIcon: true,
56 showUpdate: true, 48 showUpdate: true,
57 showUnit: true, 49 showUnit: true,
58 - value: {  
59 - value: 123,  
60 - name: '温度',  
61 - updateTime: formatToDateTime(new Date(), 'YYYY-MM-DD HH:mm:ss'),  
62 - unit: '℃',  
63 - },  
64 }; 50 };
65 export const TextComponent5Config: TextComponentDefault = { 51 export const TextComponent5Config: TextComponentDefault = {
66 id: 'text-component-5', 52 id: 'text-component-5',
67 base: false, 53 base: false,
68 showIcon: true, 54 showIcon: true,
69 showUnit: true, 55 showUnit: true,
70 - value: { value: 123, name: '温度', unit: '℃' }, 56 +};
  57 +
  58 +export const TextComponentDefaultConfig: Partial<ComponentInfo> = {
  59 + fontColor: '#000',
  60 + unit: '℃',
  61 + iconColor: '#000',
  62 + icon: 'CO2',
71 }; 63 };
72 64
73 export const textComponentConfig: TextComponentDefault[] = [ 65 export const textComponentConfig: TextComponentDefault[] = [
@@ -18,8 +18,8 @@ @@ -18,8 +18,8 @@
18 const { hasPermission } = usePermission(); 18 const { hasPermission } = usePermission();
19 const dropMenuList = computed<DropMenu[]>(() => { 19 const dropMenuList = computed<DropMenu[]>(() => {
20 const basicMenu: DropMenu[] = []; 20 const basicMenu: DropMenu[] = [];
21 - const hasUpdatePermission = hasPermission('api:yt:dataBoardDetail:update');  
22 - const hasDeletePermission = hasPermission('api:yt:dataBoardDetail:delete'); 21 + const hasUpdatePermission = hasPermission('api:yt:data_component:update:update');
  22 + const hasDeletePermission = hasPermission('api:yt:data_component:delete');
23 const hasCopyPermission = hasPermission('api:yt:dataBoardDetail:copy'); 23 const hasCopyPermission = hasPermission('api:yt:dataBoardDetail:copy');
24 if (hasUpdatePermission) 24 if (hasUpdatePermission)
25 basicMenu.push({ 25 basicMenu.push({
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 const props = defineProps<{ 21 const props = defineProps<{
22 record: DataBoardLayoutInfo; 22 record: DataBoardLayoutInfo;
23 frontId?: string; 23 frontId?: string;
  24 + defaultConfig?: Partial<ComponentInfo>;
24 }>(); 25 }>();
25 26
26 const { createMessage } = useMessage(); 27 const { createMessage } = useMessage();
@@ -29,7 +30,9 @@ @@ -29,7 +30,9 @@
29 // ...props.record, 30 // ...props.record,
30 // } as unknown as DataBoardLayoutInfo); 31 // } as unknown as DataBoardLayoutInfo);
31 32
32 - const dataSource = ref<DataSourceEl[]>([{ id: buildUUID() } as unknown as DataSourceEl]); 33 + const dataSource = ref<DataSourceEl[]>([
  34 + { id: buildUUID(), componentInfo: props.defaultConfig || {} } as unknown as DataSourceEl,
  35 + ]);
33 36
34 const [basicRegister, basicMethod] = useForm({ 37 const [basicRegister, basicMethod] = useForm({
35 schemas: basicSchema, 38 schemas: basicSchema,
@@ -65,7 +68,7 @@ @@ -65,7 +68,7 @@
65 const componentInfo = unref(dataSource)[index].componentInfo || {}; 68 const componentInfo = unref(dataSource)[index].componentInfo || {};
66 _dataSource.push({ 69 _dataSource.push({
67 ...value, 70 ...value,
68 - componentInfo: { ...componentInfo }, 71 + componentInfo: { ...(props.defaultConfig || {}), ...componentInfo },
69 }); 72 });
70 } 73 }
71 return _dataSource; 74 return _dataSource;
@@ -96,9 +99,17 @@ @@ -96,9 +99,17 @@
96 createMessage.warning('请先选择可视化组件'); 99 createMessage.warning('请先选择可视化组件');
97 return; 100 return;
98 } 101 }
  102 +
  103 + // const defaultConfig = getComponentDefaultConfig(props.frontId as WidgetComponentType);
  104 +
  105 + const componentInfo: ComponentInfo = {
  106 + ...(props.defaultConfig || {}),
  107 + ...(item.componentInfo || {}),
  108 + };
  109 +
99 openModal(true, { 110 openModal(true, {
100 recordId: item.id, 111 recordId: item.id,
101 - componentInfo: item.componentInfo, 112 + componentInfo,
102 }); 113 });
103 }; 114 };
104 115
@@ -111,6 +122,7 @@ @@ -111,6 +122,7 @@
111 const handleAdd = () => { 122 const handleAdd = () => {
112 unref(dataSource).push({ 123 unref(dataSource).push({
113 id: buildUUID(), 124 id: buildUUID(),
  125 + componentInfo: props.defaultConfig || {},
114 } as unknown as DataSourceEl); 126 } as unknown as DataSourceEl);
115 }; 127 };
116 128
@@ -185,19 +197,19 @@ @@ -185,19 +197,19 @@
185 </div> 197 </div>
186 <div class="flex justify-center gap-3 w-24"> 198 <div class="flex justify-center gap-3 w-24">
187 <Tooltip title="复制"> 199 <Tooltip title="复制">
188 - <CopyOutlined @click="handleCopy(item)" class="cursor-pointer text-lg !leading-52px" /> 200 + <CopyOutlined @click="handleCopy(item)" class="cursor-pointer text-lg !leading-32px" />
189 </Tooltip> 201 </Tooltip>
190 <Tooltip title="设置"> 202 <Tooltip title="设置">
191 <SettingOutlined 203 <SettingOutlined
192 v-show="showSettingButton" 204 v-show="showSettingButton"
193 @click="handleSetting(item)" 205 @click="handleSetting(item)"
194 - class="cursor-pointer text-lg !leading-52px" 206 + class="cursor-pointer text-lg !leading-32px"
195 /> 207 />
196 </Tooltip> 208 </Tooltip>
197 <Tooltip title="删除"> 209 <Tooltip title="删除">
198 <DeleteOutlined 210 <DeleteOutlined
199 @click="handleDelete(item)" 211 @click="handleDelete(item)"
200 - class="cursor-pointer text-lg !leading-52px" 212 + class="cursor-pointer text-lg !leading-32px"
201 /> 213 />
202 </Tooltip> 214 </Tooltip>
203 </div> 215 </div>
@@ -10,12 +10,13 @@ @@ -10,12 +10,13 @@
10 import { DataBoardLayoutInfo } from '../../types/type'; 10 import { DataBoardLayoutInfo } from '../../types/type';
11 import { useMessage } from '/@/hooks/web/useMessage'; 11 import { useMessage } from '/@/hooks/web/useMessage';
12 import { decode } from '../../config/config'; 12 import { decode } from '../../config/config';
  13 + import { ComponentInfo } from '/@/api/dataBoard/model';
13 14
14 interface DataComponentRouteParams extends RouteParams { 15 interface DataComponentRouteParams extends RouteParams {
15 id: string; 16 id: string;
16 } 17 }
17 18
18 - const emit = defineEmits(['submit', 'register']); 19 + const emit = defineEmits(['update', 'create', 'register']);
19 20
20 const ROUTE = useRoute(); 21 const ROUTE = useRoute();
21 22
@@ -31,12 +32,13 @@ @@ -31,12 +32,13 @@
31 32
32 const componentRecord = ref<DataBoardLayoutInfo>({} as unknown as DataBoardLayoutInfo); 33 const componentRecord = ref<DataBoardLayoutInfo>({} as unknown as DataBoardLayoutInfo);
33 34
  35 + const componentDefaultConfig = ref<Partial<ComponentInfo>>({});
  36 +
34 const [register, { closeModal, changeOkLoading }] = useModalInner( 37 const [register, { closeModal, changeOkLoading }] = useModalInner(
35 (data: { isEdit: boolean; record?: DataBoardLayoutInfo }) => { 38 (data: { isEdit: boolean; record?: DataBoardLayoutInfo }) => {
36 componentRecord.value = data.record || ({} as unknown as DataBoardLayoutInfo); 39 componentRecord.value = data.record || ({} as unknown as DataBoardLayoutInfo);
37 frontId.value = data.record?.record?.frontId || ''; 40 frontId.value = data.record?.record?.frontId || '';
38 isEdit.value = data.isEdit || false; 41 isEdit.value = data.isEdit || false;
39 - console.log(unref(isEdit));  
40 } 42 }
41 ); 43 );
42 44
@@ -54,6 +56,10 @@ @@ -54,6 +56,10 @@
54 56
55 const handleAddComponent = async (value: Recordable) => { 57 const handleAddComponent = async (value: Recordable) => {
56 try { 58 try {
  59 + if (!unref(frontId)) {
  60 + createMessage.warning('请选择可视化组件');
  61 + return;
  62 + }
57 changeOkLoading(true); 63 changeOkLoading(true);
58 await addDataComponent({ 64 await addDataComponent({
59 boardId: unref(boardId), 65 boardId: unref(boardId),
@@ -61,7 +67,7 @@ @@ -61,7 +67,7 @@
61 }); 67 });
62 createMessage.success('创建成功'); 68 createMessage.success('创建成功');
63 closeModal(); 69 closeModal();
64 - emit('submit'); 70 + emit('create');
65 } catch (error) { 71 } catch (error) {
66 // createMessage.error('创建失败'); 72 // createMessage.error('创建失败');
67 } finally { 73 } finally {
@@ -72,7 +78,7 @@ @@ -72,7 +78,7 @@
72 const handleUpdateComponent = async (value: Recordable) => { 78 const handleUpdateComponent = async (value: Recordable) => {
73 try { 79 try {
74 changeOkLoading(true); 80 changeOkLoading(true);
75 - await updateDataComponent({ 81 + const res = await updateDataComponent({
76 boardId: unref(boardId), 82 boardId: unref(boardId),
77 record: { 83 record: {
78 id: unref(componentRecord).i, 84 id: unref(componentRecord).i,
@@ -83,13 +89,18 @@ @@ -83,13 +89,18 @@
83 }); 89 });
84 createMessage.success('修改成功'); 90 createMessage.success('修改成功');
85 closeModal(); 91 closeModal();
86 - emit('submit'); 92 + // emit('submit');
  93 + emit('update', res.data.id);
87 } catch (error) { 94 } catch (error) {
88 // createMessage.error('修改失败'); 95 // createMessage.error('修改失败');
89 } finally { 96 } finally {
90 changeOkLoading(false); 97 changeOkLoading(false);
91 } 98 }
92 }; 99 };
  100 +
  101 + const handleComponentCheckedChange = (record: ComponentInfo) => {
  102 + componentDefaultConfig.value = record;
  103 + };
93 </script> 104 </script>
94 105
95 <template> 106 <template>
@@ -108,10 +119,11 @@ @@ -108,10 +119,11 @@
108 ref="basicConfigurationEl" 119 ref="basicConfigurationEl"
109 :front-id="frontId" 120 :front-id="frontId"
110 :record="componentRecord" 121 :record="componentRecord"
  122 + :defaultConfig="componentDefaultConfig"
111 /> 123 />
112 </Tabs.TabPane> 124 </Tabs.TabPane>
113 <Tabs.TabPane key="2" tab="可视化配置"> 125 <Tabs.TabPane key="2" tab="可视化配置">
114 - <VisualConfiguration v-model:value="frontId" /> 126 + <VisualConfiguration v-model:value="frontId" @change="handleComponentCheckedChange" />
115 </Tabs.TabPane> 127 </Tabs.TabPane>
116 </Tabs> 128 </Tabs>
117 </section> 129 </section>
@@ -105,6 +105,7 @@ @@ -105,6 +105,7 @@
105 // 发送请求 105 // 发送请求
106 loading.value = true; 106 loading.value = true;
107 const res = await getDeviceHistoryInfo(searchParams); 107 const res = await getDeviceHistoryInfo(searchParams);
  108 + loading.value = false;
108 // 判断数据对象是否为空 109 // 判断数据对象是否为空
109 if (!Object.keys(res).length) { 110 if (!Object.keys(res).length) {
110 isNull.value = false; 111 isNull.value = false;
@@ -113,7 +114,6 @@ @@ -113,7 +114,6 @@
113 isNull.value = true; 114 isNull.value = true;
114 } 115 }
115 setChartOptions(res, value.keys); 116 setChartOptions(res, value.keys);
116 - loading.value = false;  
117 }, 117 },
118 }); 118 });
119 119
@@ -150,6 +150,7 @@ @@ -150,6 +150,7 @@
150 startTs: Date.now() - 1 * 24 * 60 * 60 * 1000, 150 startTs: Date.now() - 1 * 24 * 60 * 60 * 1000,
151 endTs: Date.now(), 151 endTs: Date.now(),
152 agg: AggregateDataEnum.NONE, 152 agg: AggregateDataEnum.NONE,
  153 + limit: 7,
153 }); 154 });
154 155
155 // 判断对象是否为空 156 // 判断对象是否为空
@@ -218,7 +219,11 @@ @@ -218,7 +219,11 @@
218 <div v-show="isNull" ref="chartRef" :style="{ height: '350px', width: '100%' }"> 219 <div v-show="isNull" ref="chartRef" :style="{ height: '350px', width: '100%' }">
219 <Loading :loading="loading" :absolute="true" /> 220 <Loading :loading="loading" :absolute="true" />
220 </div> 221 </div>
221 - <Empty description="暂无数据,请选择设备查询" v-show="!isNull" /> 222 + <Empty
  223 + class="h-350px flex flex-col justify-center items-center"
  224 + description="暂无数据,请选择设备查询"
  225 + v-show="!isNull"
  226 + />
222 </section> 227 </section>
223 </section> 228 </section>
224 </BasicModal> 229 </BasicModal>
@@ -5,15 +5,19 @@ @@ -5,15 +5,19 @@
5 import { textComponentConfig } from '../../components/TextComponent/config'; 5 import { textComponentConfig } from '../../components/TextComponent/config';
6 import { instrumentComponentConfig } from '../../components/InstrumentComponent'; 6 import { instrumentComponentConfig } from '../../components/InstrumentComponent';
7 import { pictureComponentList } from '../../components/PictureComponent'; 7 import { pictureComponentList } from '../../components/PictureComponent';
  8 + import { getComponentDefaultConfig } from '../config/help';
  9 + import { WidgetComponentType } from '../config/visualOptions';
8 const props = defineProps<{ 10 const props = defineProps<{
9 value: string; 11 value: string;
10 }>(); 12 }>();
11 - const emit = defineEmits(['update:value']); 13 + const emit = defineEmits(['update:value', 'change']);
12 14
13 const grid = { gutter: 10, column: 1, xs: 1, sm: 2, md: 2, lg: 3, xl: 3, xxl: 4 }; 15 const grid = { gutter: 10, column: 1, xs: 1, sm: 2, md: 2, lg: 3, xl: 3, xxl: 4 };
14 16
15 - const handleCheck = (checked: string) => { 17 + const handleCheck = (checked: WidgetComponentType) => {
  18 + const defaultConfig = getComponentDefaultConfig(checked);
16 emit('update:value', checked); 19 emit('update:value', checked);
  20 + emit('change', defaultConfig);
17 }; 21 };
18 </script> 22 </script>
19 23
@@ -59,7 +63,12 @@ @@ -59,7 +63,12 @@
59 :control-id="item.id" 63 :control-id="item.id"
60 @change="handleCheck" 64 @change="handleCheck"
61 > 65 >
62 - <component :is="item.component" :layout="item.layout" :value="item.value" /> 66 + <component
  67 + :is="item.component"
  68 + :random="true"
  69 + :layout="item.layout"
  70 + :value="item.value"
  71 + />
63 </VisualWidgetSelect> 72 </VisualWidgetSelect>
64 </List.Item> 73 </List.Item>
65 </template> 74 </template>
@@ -87,7 +87,7 @@ @@ -87,7 +87,7 @@
87 @register="register" 87 @register="register"
88 @ok="handleClose" 88 @ok="handleClose"
89 title="选项" 89 title="选项"
90 - width="60%" 90 + width="40%"
91 > 91 >
92 <BasicForm class="form" @register="registerForm" :schemas="getSchemas" /> 92 <BasicForm class="form" @register="registerForm" :schemas="getSchemas" />
93 </BasicModal> 93 </BasicModal>
@@ -20,10 +20,10 @@ @@ -20,10 +20,10 @@
20 20
21 <template> 21 <template>
22 <Card 22 <Card
23 - :style="{ borderColor: props.controlId === props.checkedId ? '#1a74e8' : '#f0f0f0' }" 23 + :style="{ borderColor: props.controlId === props.checkedId ? '#1a74e8' : '#dcdfe6' }"
24 hoverable 24 hoverable
25 bordered 25 bordered
26 - class="w-60 h-60 widget-select !bg-light-50" 26 + class="w-60 h-60 widget-select !bg-light-50 cursor-pointer"
27 @click="handleClick" 27 @click="handleClick"
28 > 28 >
29 <div class="widget-container"> 29 <div class="widget-container">
@@ -48,7 +48,7 @@ @@ -48,7 +48,7 @@
48 } 48 }
49 49
50 .widget-select:deep(.ant-card-meta) { 50 .widget-select:deep(.ant-card-meta) {
51 - border-top: 1px solid #efefef; 51 + border-top: 1px solid #dcdfe6;
52 width: 100%; 52 width: 100%;
53 height: 40px; 53 height: 40px;
54 text-align: center; 54 text-align: center;
@@ -6,20 +6,24 @@ import { @@ -6,20 +6,24 @@ import {
6 TextComponent3Config, 6 TextComponent3Config,
7 TextComponent4Config, 7 TextComponent4Config,
8 TextComponent5Config, 8 TextComponent5Config,
  9 + TextComponentDefaultConfig,
9 transformTextComponentConfig, 10 transformTextComponentConfig,
10 } from '../../components/TextComponent/config'; 11 } from '../../components/TextComponent/config';
11 -import { DataComponentRecord, DataSource } from '/@/api/dataBoard/model'; 12 +import { ComponentInfo, DataComponentRecord, DataSource } from '/@/api/dataBoard/model';
12 import DashBoardComponent from '../../components/InstrumentComponent/DashBoardComponent.vue'; 13 import DashBoardComponent from '../../components/InstrumentComponent/DashBoardComponent.vue';
13 import PictureComponent from '../../components/PictureComponent/PictureComponent.vue'; 14 import PictureComponent from '../../components/PictureComponent/PictureComponent.vue';
14 import { transformPictureConfig } from '../../components/PictureComponent/pictureComponent.config'; 15 import { transformPictureConfig } from '../../components/PictureComponent/pictureComponent.config';
15 import { WidgetComponentType } from './visualOptions'; 16 import { WidgetComponentType } from './visualOptions';
16 import { 17 import {
17 DashboardComponentLayout, 18 DashboardComponentLayout,
  19 + Instrument1DefaultConfig,
  20 + Instrument2DefaultConfig,
18 instrumentComponent1, 21 instrumentComponent1,
19 instrumentComponent2, 22 instrumentComponent2,
20 transformDashboardComponentConfig, 23 transformDashboardComponentConfig,
21 } from '../../components/InstrumentComponent/dashBoardComponent.config'; 24 } from '../../components/InstrumentComponent/dashBoardComponent.config';
22 import DigitalDashBoard from '../../components/InstrumentComponent/DigitalDashBoard.vue'; 25 import DigitalDashBoard from '../../components/InstrumentComponent/DigitalDashBoard.vue';
  26 +import { DigitalComponentDefaultConfig } from '../../components/InstrumentComponent/digitalDashBoard.config';
23 export enum FrontComponent { 27 export enum FrontComponent {
24 TEXT_COMPONENT_1 = 'text-component-1', 28 TEXT_COMPONENT_1 = 'text-component-1',
25 TEXT_COMPONENT_2 = 'text-component-2', 29 TEXT_COMPONENT_2 = 'text-component-2',
@@ -42,6 +46,11 @@ export interface ComponentConfig { @@ -42,6 +46,11 @@ export interface ComponentConfig {
42 ) => Recordable; 46 ) => Recordable;
43 } 47 }
44 48
  49 +export const frontComponentDefaultConfigMap = new Map<
  50 + WidgetComponentType,
  51 + Partial<ComponentInfo>
  52 +>();
  53 +
45 export const frontComponentMap = new Map<WidgetComponentType, ComponentConfig>(); 54 export const frontComponentMap = new Map<WidgetComponentType, ComponentConfig>();
46 55
47 frontComponentMap.set(FrontComponent.TEXT_COMPONENT_1, { 56 frontComponentMap.set(FrontComponent.TEXT_COMPONENT_1, {
@@ -103,3 +112,21 @@ frontComponentMap.set(FrontComponent.PICTURE_COMPONENT_1, { @@ -103,3 +112,21 @@ frontComponentMap.set(FrontComponent.PICTURE_COMPONENT_1, {
103 ComponentConfig: {}, 112 ComponentConfig: {},
104 transformConfig: transformPictureConfig, 113 transformConfig: transformPictureConfig,
105 }); 114 });
  115 +
  116 +frontComponentDefaultConfigMap.set(FrontComponent.TEXT_COMPONENT_1, TextComponentDefaultConfig);
  117 +frontComponentDefaultConfigMap.set(FrontComponent.TEXT_COMPONENT_2, TextComponentDefaultConfig);
  118 +frontComponentDefaultConfigMap.set(FrontComponent.TEXT_COMPONENT_3, TextComponentDefaultConfig);
  119 +frontComponentDefaultConfigMap.set(FrontComponent.TEXT_COMPONENT_4, TextComponentDefaultConfig);
  120 +frontComponentDefaultConfigMap.set(FrontComponent.TEXT_COMPONENT_5, TextComponentDefaultConfig);
  121 +
  122 +frontComponentDefaultConfigMap.set(FrontComponent.INSTRUMENT_COMPONENT_1, Instrument1DefaultConfig);
  123 +frontComponentDefaultConfigMap.set(FrontComponent.INSTRUMENT_COMPONENT_2, Instrument2DefaultConfig);
  124 +
  125 +frontComponentDefaultConfigMap.set(
  126 + FrontComponent.DIGITAL_DASHBOARD_COMPONENT,
  127 + DigitalComponentDefaultConfig
  128 +);
  129 +
  130 +export const getComponentDefaultConfig = (key: WidgetComponentType) => {
  131 + return frontComponentDefaultConfigMap.get(key) || {};
  132 +};
@@ -5,6 +5,8 @@ export interface RadioRecord { @@ -5,6 +5,8 @@ export interface RadioRecord {
5 radio: number; 5 radio: number;
6 } 6 }
7 7
  8 +export const DEFAULT_ANIMATION_INTERVAL = 2000;
  9 +
8 export const DEFAULT_RADIO_RECORD: RadioRecord = { 10 export const DEFAULT_RADIO_RECORD: RadioRecord = {
9 width: 300, 11 width: 300,
10 height: 300, 12 height: 300,
@@ -37,8 +39,19 @@ export const calcScale = ( @@ -37,8 +39,19 @@ export const calcScale = (
37 }; 39 };
38 }; 40 };
39 41
40 -export const fontSize = ({ radio, basic, max }: { radio: number; basic: number; max?: number }) => { 42 +export const fontSize = ({
  43 + radio,
  44 + basic,
  45 + max,
  46 + min,
  47 +}: {
  48 + radio: number;
  49 + basic: number;
  50 + max?: number;
  51 + min?: number;
  52 +}) => {
41 let res = basic * radio; 53 let res = basic * radio;
42 if (max && res > max) res = max; 54 if (max && res > max) res = max;
  55 + if (min && res < min) res = min;
43 return res + 'px'; 56 return res + 'px';
44 }; 57 };
@@ -175,7 +175,7 @@ schemasMap.set('text-component-1', modeOne); @@ -175,7 +175,7 @@ schemasMap.set('text-component-1', modeOne);
175 schemasMap.set('text-component-2', modeOne); 175 schemasMap.set('text-component-2', modeOne);
176 schemasMap.set('text-component-3', modeOne); 176 schemasMap.set('text-component-3', modeOne);
177 schemasMap.set('text-component-4', modeTwo); 177 schemasMap.set('text-component-4', modeTwo);
178 -schemasMap.set('text-component-4', modeTwo); 178 +schemasMap.set('text-component-5', modeTwo);
179 schemasMap.set('instrument-component-1', modeOne); 179 schemasMap.set('instrument-component-1', modeOne);
180 schemasMap.set('instrument-component-2', modeThree); 180 schemasMap.set('instrument-component-2', modeThree);
181 schemasMap.set('digital-dashboard-component', modeFour); 181 schemasMap.set('digital-dashboard-component', modeFour);
@@ -24,7 +24,12 @@ @@ -24,7 +24,12 @@
24 } from '/@/api/dataBoard'; 24 } from '/@/api/dataBoard';
25 import { useRoute, useRouter } from 'vue-router'; 25 import { useRoute, useRouter } from 'vue-router';
26 import { computed, unref } from '@vue/reactivity'; 26 import { computed, unref } from '@vue/reactivity';
27 - import { DataComponentRecord, DataSource, Layout } from '/@/api/dataBoard/model'; 27 + import {
  28 + ComponentInfoDetail,
  29 + DataComponentRecord,
  30 + DataSource,
  31 + Layout,
  32 + } from '/@/api/dataBoard/model';
28 import { frontComponentMap } from './config/help'; 33 import { frontComponentMap } from './config/help';
29 import { calcScale } from './config/util'; 34 import { calcScale } from './config/util';
30 import { useMessage } from '/@/hooks/web/useMessage'; 35 import { useMessage } from '/@/hooks/web/useMessage';
@@ -98,6 +103,9 @@ @@ -98,6 +103,9 @@
98 width = 100; 103 width = 100;
99 } 104 }
100 105
  106 + data.width = newWPx;
  107 + data.height = newHPx;
  108 +
101 data.record.dataSource = data?.record.dataSource.map((item) => { 109 data.record.dataSource = data?.record.dataSource.map((item) => {
102 if (!item.uuid) item.uuid = buildUUID(); 110 if (!item.uuid) item.uuid = buildUUID();
103 return { 111 return {
@@ -194,7 +202,7 @@ @@ -194,7 +202,7 @@
194 try { 202 try {
195 return await getDataComponent(unref(getBoardId)); 203 return await getDataComponent(unref(getBoardId));
196 } catch (error) {} 204 } catch (error) {}
197 - return []; 205 + return {} as ComponentInfoDetail;
198 }; 206 };
199 207
200 const getSharePageComponentData = async () => { 208 const getSharePageComponentData = async () => {
@@ -202,7 +210,7 @@ @@ -202,7 +210,7 @@
202 const params = unref(getSharePageParams); 210 const params = unref(getSharePageParams);
203 return await getShareBoardComponentInfo(params); 211 return await getShareBoardComponentInfo(params);
204 } catch (error) {} 212 } catch (error) {}
205 - return []; 213 + return {} as ComponentInfoDetail;
206 }; 214 };
207 215
208 const getDataBoradDetail = async () => { 216 const getDataBoradDetail = async () => {
@@ -211,7 +219,7 @@ @@ -211,7 +219,7 @@
211 ? await getSharePageComponentData() 219 ? await getSharePageComponentData()
212 : await getBasePageComponentData(); 220 : await getBasePageComponentData();
213 } catch (error) {} 221 } catch (error) {}
214 - return []; 222 + return {} as ComponentInfoDetail;
215 }; 223 };
216 224
217 const loading = ref(false); 225 const loading = ref(false);
@@ -245,6 +253,35 @@ @@ -245,6 +253,35 @@
245 } 253 }
246 }; 254 };
247 255
  256 + const handleUpdateComponent = async (id: string) => {
  257 + try {
  258 + loading.value = true;
  259 + const data = await getDataBoradDetail();
  260 + const updateIndex = data.data.componentData.findIndex((item) => item.id === id);
  261 + const originalIndex = unref(dataBoardList).findIndex((item) => item.i === id);
  262 +
  263 + const newUpdateData = data.data.componentData[updateIndex];
  264 + const originalData = unref(dataBoardList)[originalIndex];
  265 + dataBoardList.value[originalIndex] = {
  266 + i: id,
  267 + w: originalData.w || DEFAULT_WIDGET_WIDTH,
  268 + h: originalData.h || DEFAULT_WIDGET_HEIGHT,
  269 + x: originalData.x || 0,
  270 + y: originalData.y || 0,
  271 + width: originalData.width,
  272 + height: originalData.height,
  273 + record: newUpdateData,
  274 + };
  275 +
  276 + updateSize(id, 0, 0, originalData.height || 0, originalData.width || 0);
  277 +
  278 + beginSendMessage();
  279 + } catch (error) {
  280 + } finally {
  281 + loading.value = false;
  282 + }
  283 + };
  284 +
248 const getComponent = (record: DataComponentRecord) => { 285 const getComponent = (record: DataComponentRecord) => {
249 const frontComponent = record.frontId; 286 const frontComponent = record.frontId;
250 const component = frontComponentMap.get(frontComponent as WidgetComponentType); 287 const component = frontComponentMap.get(frontComponent as WidgetComponentType);
@@ -312,7 +349,7 @@ @@ -312,7 +349,7 @@
312 </div> 349 </div>
313 </template> 350 </template>
314 <template #extra> 351 <template #extra>
315 - <Authority value="api:yt:dataBoardDetail:post"> 352 + <Authority value="api:yt:data_component:add:post">
316 <Button v-if="!getIsSharePage" type="primary" @click="handleOpenCreatePanel" 353 <Button v-if="!getIsSharePage" type="primary" @click="handleOpenCreatePanel"
317 >创建组件</Button 354 >创建组件</Button
318 > 355 >
@@ -383,6 +420,7 @@ @@ -383,6 +420,7 @@
383 :update="update" 420 :update="update"
384 :radio="record.radio || {}" 421 :radio="record.radio || {}"
385 v-bind="getComponentConfig(item.record, record)" 422 v-bind="getComponentConfig(item.record, record)"
  423 + :random="false"
386 /> 424 />
387 </template> 425 </template>
388 </WidgetWrapper> 426 </WidgetWrapper>
@@ -391,7 +429,11 @@ @@ -391,7 +429,11 @@
391 <Empty v-if="!dataBoardList.length" /> 429 <Empty v-if="!dataBoardList.length" />
392 </Spin> 430 </Spin>
393 </section> 431 </section>
394 - <DataBindModal @register="register" @submit="getDataBoardComponent" /> 432 + <DataBindModal
  433 + @register="register"
  434 + @update="handleUpdateComponent"
  435 + @create="getDataBoardComponent"
  436 + />
395 <HistoryTrendModal @register="registerHistoryDataModal" /> 437 <HistoryTrendModal @register="registerHistoryDataModal" />
396 </section> 438 </section>
397 </template> 439 </template>
@@ -88,9 +88,9 @@ export function useSocketConnect(dataSourceRef: Ref<DataBoardLayoutInfo[]>) { @@ -88,9 +88,9 @@ export function useSocketConnect(dataSourceRef: Ref<DataBoardLayoutInfo[]>) {
88 throw Error(error as string); 88 throw Error(error as string);
89 } 89 }
90 }, 90 },
91 - onDisconnected() {  
92 - close();  
93 - }, 91 + // onDisconnected() {
  92 + // close();
  93 + // },
94 }); 94 });
95 95
96 const setCmdId = (cmdId: number, record: CmdMapping) => { 96 const setCmdId = (cmdId: number, record: CmdMapping) => {
@@ -64,8 +64,8 @@ @@ -64,8 +64,8 @@
64 64
65 const { hasPermission } = usePermission(); 65 const { hasPermission } = usePermission();
66 const dropMenuList = computed<DropMenu[]>(() => { 66 const dropMenuList = computed<DropMenu[]>(() => {
67 - const hasUpdatePermission = hasPermission('api:yt:dataBoard:update');  
68 - const hasDeletePermission = hasPermission('api:yt:dataBoard:delete'); 67 + const hasUpdatePermission = hasPermission('api:yt:data_board:update:update');
  68 + const hasDeletePermission = hasPermission('api:yt:data_board:delete');
69 const basicMenu: DropMenu[] = []; 69 const basicMenu: DropMenu[] = [];
70 if (hasUpdatePermission) 70 if (hasUpdatePermission)
71 basicMenu.push({ 71 basicMenu.push({
@@ -126,16 +126,17 @@ @@ -126,16 +126,17 @@
126 createMessage.success('删除成功'); 126 createMessage.success('删除成功');
127 await getDatasource(); 127 await getDatasource();
128 } catch (error) { 128 } catch (error) {
129 - createMessage.error('删除失败'); 129 + // createMessage.error('删除失败');
130 } 130 }
131 }; 131 };
132 132
133 const [registerModal, { openModal }] = useModal(); 133 const [registerModal, { openModal }] = useModal();
134 134
135 const handleViewBoard = (record: DataBoardRecord) => { 135 const handleViewBoard = (record: DataBoardRecord) => {
136 - const hasDetailPermission = hasPermission('api:yt:dataBoard:detail'); 136 + const hasDetailPermission = hasPermission('api:yt:data_component:list');
137 if (hasDetailPermission) 137 if (hasDetailPermission)
138 router.push(`/data/board/detail/${encode(record.id)}/${encode(record.name)}`); 138 router.push(`/data/board/detail/${encode(record.id)}/${encode(record.name)}`);
  139 + else createMessage.warning('没有权限');
139 }; 140 };
140 141
141 const handlePagenationPosition = () => { 142 const handlePagenationPosition = () => {
@@ -161,7 +162,7 @@ @@ -161,7 +162,7 @@
161 <PageWrapper> 162 <PageWrapper>
162 <div class="flex mb-6 items-center"> 163 <div class="flex mb-6 items-center">
163 <div class="text-lg mr-6 font-bold">自定义看板</div> 164 <div class="text-lg mr-6 font-bold">自定义看板</div>
164 - <Authority value="api:yt:dataBoard:post"> 165 + <Authority value="api:yt:data_board:add:post">
165 <Button type="primary" @click="handleOpenDetailModal">创建看板</Button> 166 <Button type="primary" @click="handleOpenDetailModal">创建看板</Button>
166 </Authority> 167 </Authority>
167 </div> 168 </div>
@@ -202,11 +203,11 @@ @@ -202,11 +203,11 @@
202 <span> 203 <span>
203 {{ item.viewType === ViewType.PRIVATE_VIEW ? '私有看板' : '公共看板' }} 204 {{ item.viewType === ViewType.PRIVATE_VIEW ? '私有看板' : '公共看板' }}
204 </span> 205 </span>
205 - <span v-if="item.viewType === ViewType.PUBLIC_VIEW"> 206 + <!-- <span v-if="item.viewType === ViewType.PUBLIC_VIEW">
206 <Tooltip title="点击复制分享链接"> 207 <Tooltip title="点击复制分享链接">
207 <ShareAltOutlined class="ml-2" @click.stop="handleCopyShareUrl(item)" /> 208 <ShareAltOutlined class="ml-2" @click.stop="handleCopyShareUrl(item)" />
208 </Tooltip> 209 </Tooltip>
209 - </span> 210 + </span> -->
210 </div> 211 </div>
211 <div>{{ item.updateTime || item.createTime }}</div> 212 <div>{{ item.updateTime || item.createTime }}</div>
212 </div> 213 </div>
@@ -5,4 +5,6 @@ export type FrontDataSourceRecord = DataSource; @@ -5,4 +5,6 @@ export type FrontDataSourceRecord = DataSource;
5 5
6 export type DataBoardLayoutInfo = Layout & { 6 export type DataBoardLayoutInfo = Layout & {
7 record: DataComponentRecord; 7 record: DataComponentRecord;
  8 + width?: number;
  9 + height?: number;
8 }; 10 };
@@ -4,19 +4,22 @@ @@ -4,19 +4,22 @@
4 <div class="right-wrap"> 4 <div class="right-wrap">
5 <BasicTable style="cursor: pointer" @register="registerTable" @rowClick="deviceRowClick"> 5 <BasicTable style="cursor: pointer" @register="registerTable" @rowClick="deviceRowClick">
6 <template #deviceState="{ record }"> 6 <template #deviceState="{ record }">
7 - <Tag :color="  
8 - record.deviceState == DeviceState.INACTIVE  
9 - ? 'warning'  
10 - : record.deviceState == DeviceState.ONLINE  
11 - ? 'success'  
12 - : 'error'  
13 - " class="ml-2"> 7 + <Tag
  8 + :color="
  9 + record.deviceState == DeviceState.INACTIVE
  10 + ? 'warning'
  11 + : record.deviceState == DeviceState.ONLINE
  12 + ? 'success'
  13 + : 'error'
  14 + "
  15 + class="ml-2"
  16 + >
14 {{ 17 {{
15 - record.deviceState == DeviceState.INACTIVE  
16 - ? '待激活'  
17 - : record.deviceState == DeviceState.ONLINE  
18 - ? '在线'  
19 - : '离线' 18 + record.deviceState == DeviceState.INACTIVE
  19 + ? '待激活'
  20 + : record.deviceState == DeviceState.ONLINE
  21 + ? '在线'
  22 + : '离线'
20 }} 23 }}
21 </Tag> 24 </Tag>
22 </template> 25 </template>
@@ -27,393 +30,406 @@ @@ -27,393 +30,406 @@
27 </template> 30 </template>
28 </BasicTable> 31 </BasicTable>
29 </div> 32 </div>
30 - <BasicModal @register="registerModal" title="历史数据" width="70%" :minHeight="400" :footer="null"  
31 - :canFullscreen="false" @cancel="handleCancelModal"> 33 + <BasicModal
  34 + @register="registerModal"
  35 + title="历史数据"
  36 + width="70%"
  37 + :minHeight="400"
  38 + :footer="null"
  39 + :canFullscreen="false"
  40 + @cancel="handleCancelModal"
  41 + >
32 <TimePeriodForm @register="timePeriodRegister" /> 42 <TimePeriodForm @register="timePeriodRegister" />
33 <!-- <BasicForm @register="registerForm" /> --> 43 <!-- <BasicForm @register="registerForm" /> -->
34 <div v-show="isNull" ref="chartRef" :style="{ height: '550px', width }"> 44 <div v-show="isNull" ref="chartRef" :style="{ height: '550px', width }">
35 <Loading :loading="loading" :absolute="true" /> 45 <Loading :loading="loading" :absolute="true" />
36 </div> 46 </div>
37 - <Empty v-show="!isNull" /> 47 + <Empty
  48 + :style="{ height: '550px', width }"
  49 + class="flex flex-col justify-center items-center"
  50 + v-show="!isNull"
  51 + />
38 </BasicModal> 52 </BasicModal>
39 <DeviceDetailDrawer @register="registerDetailDrawer" /> 53 <DeviceDetailDrawer @register="registerDetailDrawer" />
40 </div> 54 </div>
41 </template> 55 </template>
42 <script lang="ts"> 56 <script lang="ts">
43 -import { defineComponent, ref, nextTick, unref, onMounted, Ref, onUnmounted } from 'vue';  
44 -import { useScript } from '/@/hooks/web/useScript';  
45 -import { formSchema, columns } from './config.data';  
46 -import { BasicTable, useTable } from '/@/components/Table';  
47 -import { devicePage } from '/@/api/alarm/contact/alarmContact';  
48 -import { Tag, Empty } from 'ant-design-vue';  
49 -import { DeviceState } from '/@/api/device/model/deviceModel';  
50 -import { BAI_DU_MAP_URL } from '/@/utils/fnUtils';  
51 -import { useModal, BasicModal } from '/@/components/Modal';  
52 -import { useECharts } from '/@/hooks/web/useECharts';  
53 -import {  
54 - getDeviceHistoryInfo,  
55 - getDeviceDataKeys,  
56 - getDeviceActiveTime,  
57 -} from '/@/api/alarm/position';  
58 -import { useDrawer } from '/@/components/Drawer';  
59 -import DeviceDetailDrawer from '/@/views/device/list/cpns/modal/DeviceDetailDrawer.vue';  
60 -import moment from 'moment';  
61 -// 导入一些静态图片,避免打包时不能正确解析  
62 -import djx from '/@/assets/images/djx.png';  
63 -import zx from '/@/assets/images/zx.png';  
64 -import lx from '/@/assets/images/lx.png';  
65 -import djh from '/@/assets/images/djh.png';  
66 -import online from '/@/assets/images/online1.png';  
67 -import lx1 from '/@/assets/images/lx1.png';  
68 -import Loading from '/@/components/Loading/src/Loading.vue';  
69 -import { TimePeriodForm, useTimePeriodForm } from './cpns/TimePeriodForm';  
70 -import { selectDeviceAttrSchema, eChartOptions } from './config.data';  
71 -import { defaultSchemas } from './cpns/TimePeriodForm/config';  
72 -import { QueryWay, SchemaFiled, AggregateDataEnum } from './cpns/TimePeriodForm/config';  
73 -import { dateUtil } from '/@/utils/dateUtil';  
74 -export default defineComponent({  
75 - name: 'BaiduMap',  
76 - components: {  
77 - BasicTable,  
78 - Tag,  
79 - Empty,  
80 - BasicModal,  
81 - DeviceDetailDrawer,  
82 - Loading,  
83 - TimePeriodForm,  
84 - },  
85 - props: {  
86 - width: {  
87 - type: String,  
88 - default: '100%', 57 + import { defineComponent, ref, nextTick, unref, onMounted, Ref, onUnmounted } from 'vue';
  58 + import { useScript } from '/@/hooks/web/useScript';
  59 + import { formSchema, columns } from './config.data';
  60 + import { BasicTable, useTable } from '/@/components/Table';
  61 + import { devicePage } from '/@/api/alarm/contact/alarmContact';
  62 + import { Tag, Empty } from 'ant-design-vue';
  63 + import { DeviceState } from '/@/api/device/model/deviceModel';
  64 + import { BAI_DU_MAP_URL } from '/@/utils/fnUtils';
  65 + import { useModal, BasicModal } from '/@/components/Modal';
  66 + import { useECharts } from '/@/hooks/web/useECharts';
  67 + import {
  68 + getDeviceHistoryInfo,
  69 + getDeviceDataKeys,
  70 + getDeviceActiveTime,
  71 + } from '/@/api/alarm/position';
  72 + import { useDrawer } from '/@/components/Drawer';
  73 + import DeviceDetailDrawer from '/@/views/device/list/cpns/modal/DeviceDetailDrawer.vue';
  74 + import moment from 'moment';
  75 + // 导入一些静态图片,避免打包时不能正确解析
  76 + import djx from '/@/assets/images/djx.png';
  77 + import zx from '/@/assets/images/zx.png';
  78 + import lx from '/@/assets/images/lx.png';
  79 + import djh from '/@/assets/images/djh.png';
  80 + import online from '/@/assets/images/online1.png';
  81 + import lx1 from '/@/assets/images/lx1.png';
  82 + import Loading from '/@/components/Loading/src/Loading.vue';
  83 + import { TimePeriodForm, useTimePeriodForm } from './cpns/TimePeriodForm';
  84 + import { selectDeviceAttrSchema, eChartOptions } from './config.data';
  85 + import { defaultSchemas } from './cpns/TimePeriodForm/config';
  86 + import { QueryWay, SchemaFiled, AggregateDataEnum } from './cpns/TimePeriodForm/config';
  87 + import { dateUtil } from '/@/utils/dateUtil';
  88 + export default defineComponent({
  89 + name: 'BaiduMap',
  90 + components: {
  91 + BasicTable,
  92 + Tag,
  93 + Empty,
  94 + BasicModal,
  95 + DeviceDetailDrawer,
  96 + Loading,
  97 + TimePeriodForm,
89 }, 98 },
90 - height: {  
91 - type: String,  
92 - default: 'calc(100vh - 78px)',  
93 - },  
94 - },  
95 - setup() {  
96 - let entityId = '';  
97 - let globalRecord: any = {};  
98 - const wrapRef = ref<HTMLDivElement | null>(null);  
99 - const chartRef = ref<HTMLDivElement | null>(null);  
100 - const deviceAttrs = ref<string[]>([]);  
101 - const { setOptions, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>);  
102 - const isNull = ref(true);  
103 - const { toPromise } = useScript({ src: BAI_DU_MAP_URL });  
104 - const [registerDetailDrawer, { openDrawer }] = useDrawer();  
105 - const [registerModal, { openModal }] = useModal();  
106 - const loading = ref(false);  
107 -  
108 - const [registerTable] = useTable({  
109 - api: devicePage,  
110 - columns,  
111 - resizeHeightOffset: 32,  
112 - formConfig: {  
113 - schemas: formSchema,  
114 - labelAlign: 'left', 99 + props: {
  100 + width: {
  101 + type: String,
  102 + default: '100%',
115 }, 103 },
116 - showIndexColumn: false,  
117 - useSearchForm: true,  
118 - pagination: {  
119 - showSizeChanger: false, 104 + height: {
  105 + type: String,
  106 + default: 'calc(100vh - 78px)',
120 }, 107 },
121 - }); 108 + },
  109 + setup() {
  110 + let entityId = '';
  111 + let globalRecord: any = {};
  112 + const wrapRef = ref<HTMLDivElement | null>(null);
  113 + const chartRef = ref<HTMLDivElement | null>(null);
  114 + const deviceAttrs = ref<string[]>([]);
  115 + const { setOptions, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>);
  116 + const isNull = ref(true);
  117 + const { toPromise } = useScript({ src: BAI_DU_MAP_URL });
  118 + const [registerDetailDrawer, { openDrawer }] = useDrawer();
  119 + const [registerModal, { openModal }] = useModal();
  120 + const loading = ref(false);
122 121
123 - async function initMap() {  
124 - await toPromise();  
125 - await nextTick();  
126 - const wrapEl = unref(wrapRef);  
127 - const BMap = (window as any).BMap;  
128 - if (!wrapEl) return;  
129 - const map = new BMap.Map(wrapEl); 122 + const [registerTable] = useTable({
  123 + api: devicePage,
  124 + columns,
  125 + resizeHeightOffset: 32,
  126 + formConfig: {
  127 + schemas: formSchema,
  128 + labelAlign: 'left',
  129 + },
  130 + showIndexColumn: false,
  131 + useSearchForm: true,
  132 + pagination: {
  133 + showSizeChanger: false,
  134 + },
  135 + });
  136 +
  137 + async function initMap() {
  138 + await toPromise();
  139 + await nextTick();
  140 + const wrapEl = unref(wrapRef);
  141 + const BMap = (window as any).BMap;
  142 + if (!wrapEl) return;
  143 + const map = new BMap.Map(wrapEl);
130 144
131 - const getLocation = new BMap.Geolocation();  
132 - getLocation.getCurrentPosition((position) => {  
133 - if (position) {  
134 - let preMarker = null;  
135 - const point = new BMap.Point(position.point.lng, position.point.lat);  
136 - let marker = new BMap.Marker(point, { size: 30 });  
137 - if (marker) {  
138 - map.removeOverlay(preMarker); 145 + const getLocation = new BMap.Geolocation();
  146 + getLocation.getCurrentPosition((position) => {
  147 + if (position) {
  148 + let preMarker = null;
  149 + const point = new BMap.Point(position.point.lng, position.point.lat);
  150 + let marker = new BMap.Marker(point, { size: 30 });
  151 + if (marker) {
  152 + map.removeOverlay(preMarker);
  153 + }
  154 + map.addOverlay(marker);
  155 + map.centerAndZoom(point, 15);
  156 + map.enableScrollWheelZoom(true);
  157 + } else {
  158 + const point = new BMap.Point(104.04666605565338, 30.543516387560476);
  159 + map.centerAndZoom(point, 15);
  160 + map.enableScrollWheelZoom(true);
139 } 161 }
140 - map.addOverlay(marker);  
141 - map.centerAndZoom(point, 15);  
142 - map.enableScrollWheelZoom(true);  
143 - } else {  
144 - const point = new BMap.Point(104.04666605565338, 30.543516387560476);  
145 - map.centerAndZoom(point, 15);  
146 - map.enableScrollWheelZoom(true);  
147 - }  
148 - })  
149 - }  
150 - // 点击表格某一行触发  
151 - const deviceRowClick = async (record) => {  
152 - entityId = record.tbDeviceId;  
153 - globalRecord = record;  
154 - const BMap = (window as any).BMap;  
155 - const wrapEl = unref(wrapRef);  
156 - const map = new BMap.Map(wrapEl);  
157 - // if (record.deviceInfo.address) {  
158 - // keys = await getDeviceDataKeys(entityId);  
159 - try {  
160 - deviceAttrs.value = (await getDeviceDataKeys(entityId)) || [];  
161 - } catch (error) { } 162 + });
  163 + }
  164 + // 点击表格某一行触发
  165 + const deviceRowClick = async (record) => {
  166 + entityId = record.tbDeviceId;
  167 + globalRecord = record;
  168 + const BMap = (window as any).BMap;
  169 + const wrapEl = unref(wrapRef);
  170 + const map = new BMap.Map(wrapEl);
  171 + // if (record.deviceInfo.address) {
  172 + // keys = await getDeviceDataKeys(entityId);
  173 + try {
  174 + deviceAttrs.value = (await getDeviceDataKeys(entityId)) || [];
  175 + } catch (error) {}
162 176
163 - const { name, organizationDTO, deviceState, deviceProfile } = record;  
164 - const { longitude, latitude, address } = record.deviceInfo;  
165 - //这里如果没有地理位置 最好设置一个默认位置 不然地图会全蓝  
166 - const point = new BMap.Point(  
167 - longitude == '' ? 104.04666605565338 : longitude,  
168 - latitude == '' ? 30.543516387560476 : latitude  
169 - );  
170 - let options = {  
171 - width: 330, // 信息窗口宽度  
172 - height: 0, // 信息窗口高度  
173 - };  
174 - map.centerAndZoom(point, 15);  
175 - map.enableScrollWheelZoom(true);  
176 - // 创建信息窗口对象  
177 - const res = await getDeviceActiveTime(entityId); 177 + const { name, organizationDTO, deviceState, deviceProfile } = record;
  178 + const { longitude, latitude, address } = record.deviceInfo;
  179 + //这里如果没有地理位置 最好设置一个默认位置 不然地图会全蓝
  180 + const point = new BMap.Point(
  181 + longitude == '' ? 104.04666605565338 : longitude,
  182 + latitude == '' ? 30.543516387560476 : latitude
  183 + );
  184 + let options = {
  185 + width: 330, // 信息窗口宽度
  186 + height: 0, // 信息窗口高度
  187 + };
  188 + map.centerAndZoom(point, 15);
  189 + map.enableScrollWheelZoom(true);
  190 + // 创建信息窗口对象
  191 + const res = await getDeviceActiveTime(entityId);
178 192
179 - let { value: activeStatus, lastUpdateTs } = res[0];  
180 - lastUpdateTs = moment(lastUpdateTs).format('YYYY-MM-DD HH:mm:ss');  
181 - let infoWindow = new BMap.InfoWindow(  
182 - ` 193 + let { value: activeStatus, lastUpdateTs } = res[0];
  194 + lastUpdateTs = moment(lastUpdateTs).format('YYYY-MM-DD HH:mm:ss');
  195 + let infoWindow = new BMap.InfoWindow(
  196 + `
183 <div style="display:flex;justify-content:space-between; margin:20px 0px;"> 197 <div style="display:flex;justify-content:space-between; margin:20px 0px;">
184 <div style="font-size:16px;font-weight:bold">${name}</div> 198 <div style="font-size:16px;font-weight:bold">${name}</div>
185 - ${deviceState === 'INACTIVE'  
186 - ? `<div style="display:flex;align-items:center;"><img style="width:15px;height:15px" src="${djh}" class="mr-1">待激活</div>`  
187 - : deviceState === 'ONLINE'  
188 - ? `<div style="display:flex;align-items:center; "> 199 + ${
  200 + deviceState === 'INACTIVE'
  201 + ? `<div style="display:flex;align-items:center;"><img style="width:15px;height:15px" src="${djh}" class="mr-1">待激活</div>`
  202 + : deviceState === 'ONLINE'
  203 + ? `<div style="display:flex;align-items:center; ">
189 <img style="width:15px;height:15px" src="${online}" class="mr-1">在线</div>` 204 <img style="width:15px;height:15px" src="${online}" class="mr-1">在线</div>`
190 - : `<div style="display:flex;align-items:center;"><img style="width:15px;height:15px" src="${lx1}" class="mr-1">离线</div>`  
191 - } 205 + : `<div style="display:flex;align-items:center;"><img style="width:15px;height:15px" src="${lx1}" class="mr-1">离线</div>`
  206 + }
192 </div> 207 </div>
193 <div>所属组织:${organizationDTO.name}</div> 208 <div>所属组织:${organizationDTO.name}</div>
194 <div style="margin-top:6px;">接入协议:${deviceProfile.transportType}</div> 209 <div style="margin-top:6px;">接入协议:${deviceProfile.transportType}</div>
195 - <div style="margin-top:6px;">设备位置:${address == '' ? '该设备暂无地理位置' : address  
196 - }</div> 210 + <div style="margin-top:6px;">设备位置:${
  211 + address == '' ? '该设备暂无地理位置' : address
  212 + }</div>
197 <div style="margin-top:6px;">${activeStatus ? '在' : '离'}线时间:${lastUpdateTs}</div> 213 <div style="margin-top:6px;">${activeStatus ? '在' : '离'}线时间:${lastUpdateTs}</div>
198 <div style="display:flex;justify-content:end; margin-top:10px"> 214 <div style="display:flex;justify-content:end; margin-top:10px">
199 <button onclick="openDeviceInfoDrawer()" style="margin-right:10px;color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">设备信息</button> 215 <button onclick="openDeviceInfoDrawer()" style="margin-right:10px;color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">设备信息</button>
200 <button onclick="openHistoryModal()" style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">历史数据</button> 216 <button onclick="openHistoryModal()" style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">历史数据</button>
201 </div> 217 </div>
202 `, 218 `,
203 - options  
204 - ); 219 + options
  220 + );
205 221
206 - map.openInfoWindow(infoWindow, map.getCenter());  
207 - let preMarker = null; 222 + map.openInfoWindow(infoWindow, map.getCenter());
  223 + let preMarker = null;
208 224
209 - const rivet = deviceState === 'INACTIVE' ? djx : deviceState === 'ONLINE' ? zx : lx;  
210 - let myIcon = new BMap.Icon(rivet, new BMap.Size(20, 30));  
211 - let marker = new BMap.Marker(point, { icon: myIcon });  
212 - if (marker) {  
213 - map.removeOverlay(preMarker);  
214 - }  
215 - map.addOverlay(marker);  
216 - //标注监听事件  
217 - marker.addEventListener('click', function (e) {  
218 - const point = e.point;  
219 - map.openInfoWindow(infoWindow, point);  
220 - });  
221 - //标注监听事件  
222 - // } else {  
223 - // const point = new BMap.Point(106.63028229687498, 36.06735821600903);  
224 - // let options = {  
225 - // width: 100, // 信息窗口宽度  
226 - // height: 100, // 信息窗口高度  
227 - // title: '提示', // 信息窗口标题  
228 - // };  
229 - // map.centerAndZoom(point, 5);  
230 - // map.enableScrollWheelZoom(true);  
231 - // let infoWindow = new BMap.InfoWindow('该设备暂无地理位置', options); // 创建信息窗口对象  
232 - // map.openInfoWindow(infoWindow, map.getCenter());  
233 - // }  
234 - }; 225 + const rivet = deviceState === 'INACTIVE' ? djx : deviceState === 'ONLINE' ? zx : lx;
  226 + let myIcon = new BMap.Icon(rivet, new BMap.Size(20, 30));
  227 + let marker = new BMap.Marker(point, { icon: myIcon });
  228 + if (marker) {
  229 + map.removeOverlay(preMarker);
  230 + }
  231 + map.addOverlay(marker);
  232 + //标注监听事件
  233 + marker.addEventListener('click', function (e) {
  234 + const point = e.point;
  235 + map.openInfoWindow(infoWindow, point);
  236 + });
  237 + //标注监听事件
  238 + // } else {
  239 + // const point = new BMap.Point(106.63028229687498, 36.06735821600903);
  240 + // let options = {
  241 + // width: 100, // 信息窗口宽度
  242 + // height: 100, // 信息窗口高度
  243 + // title: '提示', // 信息窗口标题
  244 + // };
  245 + // map.centerAndZoom(point, 5);
  246 + // map.enableScrollWheelZoom(true);
  247 + // let infoWindow = new BMap.InfoWindow('该设备暂无地理位置', options); // 创建信息窗口对象
  248 + // map.openInfoWindow(infoWindow, map.getCenter());
  249 + // }
  250 + };
235 251
236 - // 设备信息  
237 - const openDeviceInfoDrawer = async () => {  
238 - const { id, tbDeviceId } = globalRecord;  
239 - openDrawer(true, {  
240 - id,  
241 - tbDeviceId,  
242 - });  
243 - }; 252 + // 设备信息
  253 + const openDeviceInfoDrawer = async () => {
  254 + const { id, tbDeviceId } = globalRecord;
  255 + openDrawer(true, {
  256 + id,
  257 + tbDeviceId,
  258 + });
  259 + };
244 260
245 - const [timePeriodRegister, method] = useTimePeriodForm({  
246 - schemas: [...defaultSchemas, ...selectDeviceAttrSchema],  
247 - async submitFunc() {  
248 - // 表单验证  
249 - await method.validate();  
250 - const value = method.getFieldsValue();  
251 - const searchParams = getSearchParams(value); 261 + const [timePeriodRegister, method] = useTimePeriodForm({
  262 + schemas: [...defaultSchemas, ...selectDeviceAttrSchema],
  263 + async submitFunc() {
  264 + // 表单验证
  265 + await method.validate();
  266 + const value = method.getFieldsValue();
  267 + const searchParams = getSearchParams(value);
252 268
253 - if (!hasDeviceAttr()) return;  
254 - // 发送请求  
255 - loading.value = true;  
256 - const res = await getDeviceHistoryInfo(searchParams);  
257 - // 判断数据对象是否为空  
258 - if (!Object.keys(res).length) {  
259 - isNull.value = false;  
260 - return; 269 + if (!hasDeviceAttr()) return;
  270 + // 发送请求
  271 + loading.value = true;
  272 + const res = await getDeviceHistoryInfo(searchParams);
  273 + // 判断数据对象是否为空
  274 + if (!Object.keys(res).length) {
  275 + isNull.value = false;
  276 + return;
  277 + } else {
  278 + isNull.value = true;
  279 + }
  280 + setChartOptions(res, value.keys);
  281 + loading.value = false;
  282 + },
  283 + });
  284 +
  285 + function getSearchParams(value: Recordable) {
  286 + const { startTs, endTs, interval, agg, limit, keys, way } = value;
  287 + if (way === QueryWay.LATEST) {
  288 + return {
  289 + entityId,
  290 + keys: keys ? keys : unref(deviceAttrs).join(),
  291 + startTs: moment().subtract(startTs, 'ms').valueOf(),
  292 + endTs: Date.now(),
  293 + interval,
  294 + agg,
  295 + limit,
  296 + };
261 } else { 297 } else {
262 - isNull.value = true; 298 + return {
  299 + entityId,
  300 + keys: keys ? keys : unref(deviceAttrs).join(),
  301 + startTs: moment(startTs).valueOf(),
  302 + endTs: moment(endTs).valueOf(),
  303 + interval,
  304 + agg,
  305 + limit,
  306 + };
263 } 307 }
264 - setChartOptions(res, value.keys);  
265 - loading.value = false;  
266 - },  
267 - });  
268 -  
269 - function getSearchParams(value: Recordable) {  
270 - const { startTs, endTs, interval, agg, limit, keys, way } = value;  
271 - if (way === QueryWay.LATEST) {  
272 - return {  
273 - entityId,  
274 - keys: keys ? keys : unref(deviceAttrs).join(),  
275 - startTs: moment().subtract(startTs, 'ms').valueOf(),  
276 - endTs: Date.now(),  
277 - interval,  
278 - agg,  
279 - limit,  
280 - };  
281 - } else {  
282 - return {  
283 - entityId,  
284 - keys: keys ? keys : unref(deviceAttrs).join(),  
285 - startTs: moment(startTs).valueOf(),  
286 - endTs: moment(endTs).valueOf(),  
287 - interval,  
288 - agg,  
289 - limit,  
290 - };  
291 } 308 }
292 - }  
293 309
294 - const openHistoryModal = async () => {  
295 - openModal(true); 310 + const openHistoryModal = async () => {
  311 + openModal(true);
296 312
297 - await nextTick();  
298 - method.updateSchema({  
299 - field: 'keys',  
300 - componentProps: {  
301 - options: unref(deviceAttrs).map((item) => ({ label: item, value: item })),  
302 - },  
303 - }); 313 + await nextTick();
  314 + method.updateSchema({
  315 + field: 'keys',
  316 + componentProps: {
  317 + options: unref(deviceAttrs).map((item) => ({ label: item, value: item })),
  318 + },
  319 + });
304 320
305 - method.setFieldsValue({  
306 - [SchemaFiled.START_TS]: 1 * 24 * 60 * 60 * 1000,  
307 - [SchemaFiled.LIMIT]: 7,  
308 - [SchemaFiled.AGG]: AggregateDataEnum.NONE,  
309 - }); 321 + method.setFieldsValue({
  322 + [SchemaFiled.START_TS]: 1 * 24 * 60 * 60 * 1000,
  323 + [SchemaFiled.LIMIT]: 7,
  324 + [SchemaFiled.AGG]: AggregateDataEnum.NONE,
  325 + });
310 326
311 - if (!hasDeviceAttr()) return; 327 + if (!hasDeviceAttr()) return;
312 328
313 - const res = await getDeviceHistoryInfo({  
314 - entityId,  
315 - keys: unref(deviceAttrs).join(),  
316 - startTs: Date.now() - 1 * 24 * 60 * 60 * 1000,  
317 - endTs: Date.now(),  
318 - agg: AggregateDataEnum.NONE,  
319 - }); 329 + const res = await getDeviceHistoryInfo({
  330 + entityId,
  331 + keys: unref(deviceAttrs).join(),
  332 + startTs: Date.now() - 1 * 24 * 60 * 60 * 1000,
  333 + endTs: Date.now(),
  334 + agg: AggregateDataEnum.NONE,
  335 + });
320 336
321 - // 判断对象是否为空  
322 - if (!Object.keys(res).length) {  
323 - isNull.value = false;  
324 - return;  
325 - } else {  
326 - isNull.value = true;  
327 - }  
328 - setChartOptions(res);  
329 - };  
330 - function hasDeviceAttr() {  
331 - if (!unref(deviceAttrs).length) {  
332 - isNull.value = false;  
333 - return false;  
334 - } else {  
335 - isNull.value = true;  
336 - return true; 337 + // 判断对象是否为空
  338 + if (!Object.keys(res).length) {
  339 + isNull.value = false;
  340 + return;
  341 + } else {
  342 + isNull.value = true;
  343 + }
  344 + setChartOptions(res);
  345 + };
  346 + function hasDeviceAttr() {
  347 + if (!unref(deviceAttrs).length) {
  348 + isNull.value = false;
  349 + return false;
  350 + } else {
  351 + isNull.value = true;
  352 + return true;
  353 + }
337 } 354 }
338 - }  
339 355
340 - function setChartOptions(data, keys?) {  
341 - const dataArray: any[] = [];  
342 - for (const key in data) {  
343 - for (const item1 of data[key]) {  
344 - let { ts, value } = item1;  
345 - const time = dateUtil(ts).format('YYYY-MM-DD HH:mm:ss');  
346 - value = Number(value).toFixed(2);  
347 - dataArray.push([time, value, key]); 356 + function setChartOptions(data, keys?) {
  357 + const dataArray: any[] = [];
  358 + for (const key in data) {
  359 + for (const item1 of data[key]) {
  360 + let { ts, value } = item1;
  361 + const time = dateUtil(ts).format('YYYY-MM-DD HH:mm:ss');
  362 + value = Number(value).toFixed(2);
  363 + dataArray.push([time, value, key]);
  364 + }
348 } 365 }
  366 + keys = keys ? [keys] : unref(deviceAttrs);
  367 + const series: any = keys.map((item) => {
  368 + return {
  369 + name: item,
  370 + type: 'line',
  371 + data: dataArray.filter((item1) => item1[2] === item),
  372 + };
  373 + });
  374 + // 设置数据
  375 + setOptions(eChartOptions(series, keys));
349 } 376 }
350 - keys = keys ? [keys] : unref(deviceAttrs);  
351 - const series: any = keys.map((item) => {  
352 - return {  
353 - name: item,  
354 - type: 'line',  
355 - data: dataArray.filter((item1) => item1[2] === item),  
356 - };  
357 - });  
358 - // 设置数据  
359 - setOptions(eChartOptions(series, keys));  
360 - }  
361 377
362 - const handleCancelModal = () => {  
363 - method.setFieldsValue({  
364 - [SchemaFiled.WAY]: QueryWay.LATEST,  
365 - [SchemaFiled.KEYS]: null,  
366 - [SchemaFiled.DATE_RANGE]: [],  
367 - [SchemaFiled.INTERVAL]: null,  
368 - [SchemaFiled.LIMIT]: 7,  
369 - [SchemaFiled.AGG]: AggregateDataEnum.NONE,  
370 - });  
371 - getInstance()?.clear();  
372 - }; 378 + const handleCancelModal = () => {
  379 + method.setFieldsValue({
  380 + [SchemaFiled.WAY]: QueryWay.LATEST,
  381 + [SchemaFiled.KEYS]: null,
  382 + [SchemaFiled.DATE_RANGE]: [],
  383 + [SchemaFiled.INTERVAL]: null,
  384 + [SchemaFiled.LIMIT]: 7,
  385 + [SchemaFiled.AGG]: AggregateDataEnum.NONE,
  386 + });
  387 + getInstance()?.clear();
  388 + };
373 389
374 - onMounted(() => {  
375 - initMap();  
376 - (window as any).openDeviceInfoDrawer = openDeviceInfoDrawer;  
377 - (window as any).openHistoryModal = openHistoryModal;  
378 - }); 390 + onMounted(() => {
  391 + initMap();
  392 + (window as any).openDeviceInfoDrawer = openDeviceInfoDrawer;
  393 + (window as any).openHistoryModal = openHistoryModal;
  394 + });
379 395
380 - onUnmounted(() => {  
381 - (window as any).openDeviceInfoDrawer = null;  
382 - (window as any).openHistoryModal = null;  
383 - }); 396 + onUnmounted(() => {
  397 + (window as any).openDeviceInfoDrawer = null;
  398 + (window as any).openHistoryModal = null;
  399 + });
384 400
385 - return {  
386 - wrapRef,  
387 - registerTable,  
388 - deviceRowClick,  
389 - DeviceState,  
390 - registerModal,  
391 - chartRef,  
392 - isNull,  
393 - registerDetailDrawer,  
394 - loading,  
395 - timePeriodRegister,  
396 - handleCancelModal,  
397 - };  
398 - },  
399 -}); 401 + return {
  402 + wrapRef,
  403 + registerTable,
  404 + deviceRowClick,
  405 + DeviceState,
  406 + registerModal,
  407 + chartRef,
  408 + isNull,
  409 + registerDetailDrawer,
  410 + loading,
  411 + timePeriodRegister,
  412 + handleCancelModal,
  413 + };
  414 + },
  415 + });
400 </script> 416 </script>
401 <style scoped lang="less"> 417 <style scoped lang="less">
402 -.wrapper {  
403 - position: relative; 418 + .wrapper {
  419 + position: relative;
404 420
405 - :deep(.BMap_shadow) {  
406 - display: none; 421 + :deep(.BMap_shadow) {
  422 + display: none;
  423 + }
407 } 424 }
408 -}  
409 425
410 -.right-wrap {  
411 - padding-top: 10px;  
412 - width: 28%;  
413 - height: 95%;  
414 - position: absolute;  
415 - right: 5%;  
416 - top: 3%;  
417 - background-color: #fff;  
418 -} 426 + .right-wrap {
  427 + padding-top: 10px;
  428 + width: 28%;
  429 + height: 95%;
  430 + position: absolute;
  431 + right: 5%;
  432 + top: 3%;
  433 + background-color: #fff;
  434 + }
419 </style> 435 </style>