Commit 2dd02e8806ad55bc455bcda4633446263b20c28f
Merge branch 'perf/chart-mulitple-attr' into 'main_dev'
perf: 优化折线图柱状图属性可以进行多选 See merge request yunteng/thingskit-scada!213
Showing
19 changed files
with
411 additions
and
143 deletions
@@ -92,7 +92,8 @@ export interface NodeDataDataSourceJsonType { | @@ -92,7 +92,8 @@ export interface NodeDataDataSourceJsonType { | ||
92 | deviceId: string | 92 | deviceId: string |
93 | deviceProfileId: string | 93 | deviceProfileId: string |
94 | deviceProfileTemplateId?: string | 94 | deviceProfileTemplateId?: string |
95 | - attr: string | 95 | + attr: string | string[] |
96 | + deviceName?: string | ||
96 | 97 | ||
97 | enable: boolean | 98 | enable: boolean |
98 | chartOption?: ChartOptionType | 99 | chartOption?: ChartOptionType |
@@ -40,11 +40,10 @@ const contentDataStore = useContentDataStoreWithOut() | @@ -40,11 +40,10 @@ const contentDataStore = useContentDataStoreWithOut() | ||
40 | export const getFormSchemas = (event: EventTypeEnum): FormSchema[] => { | 40 | export const getFormSchemas = (event: EventTypeEnum): FormSchema[] => { |
41 | const { getNodeData, getCellInfo, getDeviceInfo } = usePublicFormContext() | 41 | const { getNodeData, getCellInfo, getDeviceInfo } = usePublicFormContext() |
42 | const { dataSourceJson } = unref(getNodeData) || {} | 42 | const { dataSourceJson } = unref(getNodeData) || {} |
43 | - const { deviceProfileId, deviceId } = dataSourceJson || {} | 43 | + const { deviceProfileId } = dataSourceJson || {} |
44 | // transportType:判断是什么类型的设备 code:设备地址码 deviceType:设备类型 | 44 | // transportType:判断是什么类型的设备 code:设备地址码 deviceType:设备类型 |
45 | - let codeType: string | null = '' | ||
46 | - const { transportType, deviceType, codeType: deviceCodeType } = unref(getDeviceInfo) || {} | ||
47 | - codeType = deviceCodeType || (deviceId ? contentDataStore.diveceDetailMap?.[deviceId]?.codeType : null) | 45 | + const { transportType, deviceType, codeType } = unref(getDeviceInfo) || {} |
46 | + | ||
48 | const isTemplate = contentDataStore.isTemplate // 判断是否是模板 | 47 | const isTemplate = contentDataStore.isTemplate // 判断是否是模板 |
49 | 48 | ||
50 | return [ | 49 | return [ |
@@ -63,6 +63,7 @@ export const formSchemas = (componentKey?: string): FormSchema[] => { | @@ -63,6 +63,7 @@ export const formSchemas = (componentKey?: string): FormSchema[] => { | ||
63 | onSelect(value: string, option: DeviceItemType) { | 63 | onSelect(value: string, option: DeviceItemType) { |
64 | formModel[ContentDataFieldsEnum.DEVICE_PROFILE_ID] = value ? option.deviceProfileId : null | 64 | formModel[ContentDataFieldsEnum.DEVICE_PROFILE_ID] = value ? option.deviceProfileId : null |
65 | formModel[ContentDataFieldsEnum.ATTR] = null | 65 | formModel[ContentDataFieldsEnum.ATTR] = null |
66 | + formModel[ContentDataFieldsEnum.DEVICE_NAME] = value ? option.alias || option.name : '' | ||
66 | }, | 67 | }, |
67 | filterOption: (inputValue: string, option: DeviceItemType) => { | 68 | filterOption: (inputValue: string, option: DeviceItemType) => { |
68 | return option.alias?.includes?.(inputValue) || option.name?.includes?.(inputValue) | 69 | return option.alias?.includes?.(inputValue) || option.name?.includes?.(inputValue) |
@@ -71,6 +72,12 @@ export const formSchemas = (componentKey?: string): FormSchema[] => { | @@ -71,6 +72,12 @@ export const formSchemas = (componentKey?: string): FormSchema[] => { | ||
71 | }, | 72 | }, |
72 | }, | 73 | }, |
73 | { | 74 | { |
75 | + field: ContentDataFieldsEnum.DEVICE_NAME, | ||
76 | + label: ContentDataFieldsNameEnum.deviceName, | ||
77 | + component: ComponentEnum.INPUT, | ||
78 | + ifShow: false, | ||
79 | + }, | ||
80 | + { | ||
74 | field: ContentDataFieldsEnum.ATTR, | 81 | field: ContentDataFieldsEnum.ATTR, |
75 | label: ContentDataFieldsNameEnum.ATTR, | 82 | label: ContentDataFieldsNameEnum.ATTR, |
76 | component: ComponentEnum.API_SELECT, | 83 | component: ComponentEnum.API_SELECT, |
@@ -6,3 +6,10 @@ export function useLatestMessageValue(message: SubscriptionData, attr: string) { | @@ -6,3 +6,10 @@ export function useLatestMessageValue(message: SubscriptionData, attr: string) { | ||
6 | const [ts, latestValue = null] = lateset || [] | 6 | const [ts, latestValue = null] = lateset || [] |
7 | return { ts, latestValue } | 7 | return { ts, latestValue } |
8 | } | 8 | } |
9 | + | ||
10 | +export function useLatestMultipleMessageValue(message: SubscriptionData, attr: string[], Fn: (attribute: string, value: any, timespan: number) => void) { | ||
11 | + attr.forEach((item) => { | ||
12 | + const [ts = null, latestValue = null] = message[item][0] || [] | ||
13 | + Fn(item, ts, latestValue) | ||
14 | + }) | ||
15 | +} |
@@ -34,13 +34,11 @@ function initChartInstance() { | @@ -34,13 +34,11 @@ function initChartInstance() { | ||
34 | const { onMessage } = useOnMessage({ | 34 | const { onMessage } = useOnMessage({ |
35 | onReceiveDataSourceMessage(commandSource, message) { | 35 | onReceiveDataSourceMessage(commandSource, message) { |
36 | const { data } = commandSource | 36 | const { data } = commandSource |
37 | - const { deviceInfo, attrInfo } = data || {} | ||
38 | - const { deviceName } = deviceInfo || {} | ||
39 | const { attr } = data as NodeDataDataSourceJsonType | 37 | const { attr } = data as NodeDataDataSourceJsonType |
40 | const { latestValue } = useLatestMessageValue(message.data, attr) | 38 | const { latestValue } = useLatestMessageValue(message.data, attr) |
41 | unref(chartInstance)?.setOption({ | 39 | unref(chartInstance)?.setOption({ |
42 | title: { | 40 | title: { |
43 | - text: `${deviceName || ''}-${attrInfo.name || ''}`, | 41 | + // text: `${deviceName || ''}-${attrInfo.name || ''}`, |
44 | }, | 42 | }, |
45 | series: [{ | 43 | series: [{ |
46 | data: getSetValue(Number(latestValue)), | 44 | data: getSetValue(Number(latestValue)), |
@@ -3,7 +3,8 @@ import { Button, Divider } from 'ant-design-vue' | @@ -3,7 +3,8 @@ import { Button, Divider } from 'ant-design-vue' | ||
3 | import { nextTick, onMounted, ref, unref } from 'vue' | 3 | import { nextTick, onMounted, ref, unref } from 'vue' |
4 | import { formSchemas } from '../config' | 4 | import { formSchemas } from '../config' |
5 | import { ChartComponentEnum } from '..' | 5 | import { ChartComponentEnum } from '..' |
6 | -import { DataSourceForm } from '@/core/Library/components/PublicForm/components/DataSourceForm' | 6 | +import { DataSourceForm } from '../component/index' |
7 | +// import { DataSourceForm } from '@/core/Library/components/PublicForm/components/DataSourceForm' | ||
7 | 8 | ||
8 | import { BasicForm, useForm } from '@/components/Form' | 9 | import { BasicForm, useForm } from '@/components/Form' |
9 | import { FormLayoutEnum } from '@/components/Form/src/enum' | 10 | import { FormLayoutEnum } from '@/components/Form/src/enum' |
@@ -46,7 +47,7 @@ const handleSubmit = async () => { | @@ -46,7 +47,7 @@ const handleSubmit = async () => { | ||
46 | if (contentDataStore.getIsTemplate) | 47 | if (contentDataStore.getIsTemplate) |
47 | dataSourceJson = { ...value, deviceProfileId: value?.deviceProfileTemplateId, deviceId: null } | 48 | dataSourceJson = { ...value, deviceProfileId: value?.deviceProfileTemplateId, deviceId: null } |
48 | 49 | ||
49 | - await saveNodeAllData({ dataSourceJson: { ...dataSourceJson, chartOption: { ...values } } }) | 50 | + await saveNodeAllData({ dataSourceJson: { ...dataSourceJson, attr: typeof value.attr == 'string' ? [value.attr] : value.attr, chartOption: { ...values } } }) |
50 | savePageContent() | 51 | savePageContent() |
51 | createMessage.success('操作成功~') | 52 | createMessage.success('操作成功~') |
52 | } | 53 | } |
@@ -57,9 +58,9 @@ const handleSubmit = async () => { | @@ -57,9 +58,9 @@ const handleSubmit = async () => { | ||
57 | 58 | ||
58 | const handleSetFormValues = async () => { | 59 | const handleSetFormValues = async () => { |
59 | const { dataSourceJson } = unref(getNodeData) || {} | 60 | const { dataSourceJson } = unref(getNodeData) || {} |
60 | - const { deviceId, attr, chartOption, deviceProfileId, deviceProfileTemplateId } = dataSourceJson || {} | 61 | + const { deviceId, attr, chartOption, deviceProfileId, deviceProfileTemplateId, deviceName } = dataSourceJson || {} |
61 | await nextTick() | 62 | await nextTick() |
62 | - unref(dataSourceElRef)?.setFieldsValue({ deviceId, attr, deviceProfileId, deviceProfileTemplateId }) | 63 | + unref(dataSourceElRef)?.setFieldsValue({ deviceId, attr, deviceName, deviceProfileId, deviceProfileTemplateId }) |
63 | setFieldsValue({ ...chartOption }) | 64 | setFieldsValue({ ...chartOption }) |
64 | } | 65 | } |
65 | 66 |
1 | import { isLightboxMode } from '@/utils/env' | 1 | import { isLightboxMode } from '@/utils/env' |
2 | 2 | ||
3 | -const data = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] | ||
4 | -const seriesList = [ | ||
5 | - { value: 120, name: '123', itemStyle: { color: '#5470c6' } }, | ||
6 | - { value: 150, name: '456', itemStyle: { color: '#5470c6' } }, | ||
7 | - { value: 40, name: '789', itemStyle: { color: '#5470c6' } }, | ||
8 | - { value: 139, name: '111', itemStyle: { color: '#5470c6' } }, | ||
9 | - { value: 130, name: '222', itemStyle: { color: '#5470c6' } }, | ||
10 | - { value: 125, name: '333', itemStyle: { color: '#5470c6' } }, | ||
11 | - { value: 110, name: '444', itemStyle: { color: '#5470c6' } }, | ||
12 | -] | ||
13 | export const defaultOption = { | 3 | export const defaultOption = { |
14 | - color: ['#3398DB'], | ||
15 | tooltip: { | 4 | tooltip: { |
16 | - // 提示框 | ||
17 | - trigger: 'item', | ||
18 | - confine: true, | ||
19 | - axisPointer: { | ||
20 | - type: 'shadow', | ||
21 | - }, | ||
22 | }, | 5 | }, |
23 | - xAxis: { | ||
24 | - type: 'category', | ||
25 | - data: isLightboxMode() ? [] : data, | ||
26 | - axisTick: { | ||
27 | - alignWithLabel: true, | 6 | + calculable: true, |
7 | + xAxis: [ | ||
8 | + { | ||
9 | + type: 'category', | ||
10 | + // prettier-ignore | ||
11 | + data: isLightboxMode() ? [] : ['Jan', 'Feb', 'Mar', 'Apr', 'May'], | ||
28 | }, | 12 | }, |
13 | + ], | ||
14 | + legend: { | ||
15 | + top: '8%', | ||
16 | + left: 'center', | ||
17 | + data: [''], | ||
29 | }, | 18 | }, |
19 | + | ||
30 | grid: { | 20 | grid: { |
31 | - top: '10%', | ||
32 | - left: '10%', | ||
33 | - bottom: '10%', | ||
34 | - }, | ||
35 | - yAxis: { | ||
36 | - type: 'value', | 21 | + top: '25%', |
22 | + left: '6%', | ||
23 | + right: '10%', | ||
24 | + bottom: '8%', | ||
25 | + containLabel: true, | ||
37 | }, | 26 | }, |
27 | + yAxis: [ | ||
28 | + { | ||
29 | + type: 'value', | ||
30 | + }, | ||
31 | + ], | ||
38 | series: [ | 32 | series: [ |
39 | { | 33 | { |
40 | - name: '', | 34 | + name: 'Rainfall', |
35 | + type: 'bar', | ||
36 | + data: [ | ||
37 | + 25.6, 76.7, 42.0, 27.0, 23.2, | ||
38 | + ], | ||
39 | + }, | ||
40 | + { | ||
41 | + name: 'Evaporation', | ||
41 | type: 'bar', | 42 | type: 'bar', |
42 | - barWidth: '60%', | ||
43 | - data: isLightboxMode () ? [] : seriesList, | 43 | + data: isLightboxMode() |
44 | + ? [] | ||
45 | + : [ | ||
46 | + 28.7, 32.6, 70.7, 29.0, 26.4, | ||
47 | + ], | ||
44 | }, | 48 | }, |
45 | ], | 49 | ], |
46 | } | 50 | } |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | -import { computed, onMounted, onUnmounted, ref, unref } from 'vue' | 2 | +import { computed, onMounted, onUnmounted, ref, toRaw, unref } from 'vue' |
3 | import { init } from 'echarts' | 3 | import { init } from 'echarts' |
4 | import type { ECharts, EChartsOption } from 'echarts' | 4 | import type { ECharts, EChartsOption } from 'echarts' |
5 | import { defaultOption } from './index.config' | 5 | import { defaultOption } from './index.config' |
@@ -10,6 +10,7 @@ import { SocketSubscriberEnum } from '@/enums/datasource' | @@ -10,6 +10,7 @@ import { SocketSubscriberEnum } from '@/enums/datasource' | ||
10 | import type { SubscriptionData } from '@/core/websocket/type/message' | 10 | import type { SubscriptionData } from '@/core/websocket/type/message' |
11 | import { formatToDateTime } from '@/utils/dateUtil' | 11 | import { formatToDateTime } from '@/utils/dateUtil' |
12 | import type { CommandSource } from '@/core/websocket/processor' | 12 | import type { CommandSource } from '@/core/websocket/processor' |
13 | +import { useProductsStore } from '@/store/modules/products' | ||
13 | 14 | ||
14 | const props = defineProps<{ | 15 | const props = defineProps<{ |
15 | config: CreateComponentType | 16 | config: CreateComponentType |
@@ -21,40 +22,80 @@ const chartElRef = ref<Nullable<HTMLDivElement>>() | @@ -21,40 +22,80 @@ const chartElRef = ref<Nullable<HTMLDivElement>>() | ||
21 | 22 | ||
22 | const chartInstance = ref<Nullable<ECharts>>() | 23 | const chartInstance = ref<Nullable<ECharts>>() |
23 | 24 | ||
25 | +const seriesData = ref<any>([]) | ||
26 | +const XAxisData = ref<any>([]) | ||
27 | +const titleATTR = ref<string[] | any>([]) | ||
28 | + | ||
24 | function initChartInstance() { | 29 | function initChartInstance() { |
25 | chartInstance.value = init(unref(chartElRef)) | 30 | chartInstance.value = init(unref(chartElRef)) |
26 | chartInstance.value.setOption(defaultOption) | 31 | chartInstance.value.setOption(defaultOption) |
27 | } | 32 | } |
28 | 33 | ||
34 | +const productsStore = useProductsStore() | ||
35 | + | ||
29 | const handleHistoryData = (commandSource: CommandSource, message: SubscriptionData) => { | 36 | const handleHistoryData = (commandSource: CommandSource, message: SubscriptionData) => { |
30 | const { data } = commandSource | 37 | const { data } = commandSource |
31 | - const { attrInfo, deviceInfo, attr } = data as NodeDataDataSourceJsonType | ||
32 | - const { deviceName } = deviceInfo || {} | 38 | + const { attr, deviceName } = data as NodeDataDataSourceJsonType as any |
33 | 39 | ||
34 | - const historyData = message[attr] | ||
35 | - const xAxisData: string[] = [] | ||
36 | - const seriesData: number[] = [] | 40 | + attr.forEach((item: any) => { // 得到所有时间 |
41 | + XAxisData.value.push(...message[item].map((item1) => { | ||
42 | + const [ts] = item1 | ||
43 | + return ts | ||
44 | + })) | ||
45 | + }) | ||
46 | + XAxisData.value = Array.from(new Set(XAxisData.value)).sort((a: any, b: any) => a - b)// 去重获取到的时间 | ||
47 | + // 初始化有几个柱 | ||
48 | + seriesData.value.forEach((item: any) => { | ||
49 | + item.data = unref(XAxisData).map((time: any) => ({ name: time, value: '' })) | ||
50 | + }) | ||
37 | 51 | ||
38 | - for (const item of historyData) { | ||
39 | - const [ts, value] = item | ||
40 | - xAxisData.push(formatToDateTime(ts)) | ||
41 | - seriesData.push(value) | ||
42 | - } | 52 | + // 跟每个柱添加数据 |
53 | + seriesData.value.forEach((item: any) => { | ||
54 | + item.data.forEach((item1: any) => { | ||
55 | + message[item.attribute].forEach((messageItem) => { | ||
56 | + const [ts, value] = messageItem | ||
57 | + if (item1.name === ts) | ||
58 | + item1.value = value || '' | ||
59 | + // item1.name = formatToDateTime(item1.name) | ||
60 | + }) | ||
61 | + }) | ||
62 | + }) | ||
43 | 63 | ||
44 | unref(chartInstance)?.setOption({ | 64 | unref(chartInstance)?.setOption({ |
45 | title: { | 65 | title: { |
46 | - text: `${deviceName || ''}-${attrInfo.name || ''}`, | 66 | + text: `${deviceName || ''}`, |
67 | + }, | ||
68 | + xAxis: [ | ||
69 | + { | ||
70 | + type: 'category', | ||
71 | + data: toRaw(unref(XAxisData.value.map((item: string | number) => formatToDateTime(item)))), | ||
72 | + }, | ||
73 | + ], | ||
74 | + legend: { | ||
75 | + data: unref(titleATTR), | ||
47 | }, | 76 | }, |
48 | - xAxis: { data: xAxisData }, | ||
49 | - series: { data: seriesData }, | 77 | + series: toRaw(unref(seriesData).map((item: { type: string; name: string; data: any; attribute: string }) => { |
78 | + const { type, name, data } = item | ||
79 | + return { | ||
80 | + type, | ||
81 | + name, | ||
82 | + data: data.map((item: any) => item.value), | ||
83 | + } | ||
84 | + })), | ||
50 | } as EChartsOption) | 85 | } as EChartsOption) |
51 | } | 86 | } |
52 | 87 | ||
53 | const { onMessage } = useOnMessage({ | 88 | const { onMessage } = useOnMessage({ |
54 | onReceiveDataSourceMessage(commandSource, message) { | 89 | onReceiveDataSourceMessage(commandSource, message) { |
55 | const { data } = commandSource | 90 | const { data } = commandSource |
56 | - const { chartOption } = data as NodeDataDataSourceJsonType | 91 | + const { chartOption, attr, deviceProfileId } = data as NodeDataDataSourceJsonType |
57 | const { queryType } = chartOption || {} | 92 | const { queryType } = chartOption || {} |
93 | + if (!seriesData.value.length) { | ||
94 | + (attr as string[]).forEach((item: string) => { | ||
95 | + titleATTR.value.push(productsStore.getObjectModelByIdWithIdentifier(deviceProfileId, item)?.functionName) | ||
96 | + seriesData.value.push({ attribute: item, data: [], type: 'bar', name: productsStore.getObjectModelByIdWithIdentifier(deviceProfileId, item)?.functionName }) | ||
97 | + }) | ||
98 | + } | ||
58 | 99 | ||
59 | if (queryType === SocketSubscriberEnum.HISTORY_CMDS) | 100 | if (queryType === SocketSubscriberEnum.HISTORY_CMDS) |
60 | handleHistoryData(commandSource, message.data) | 101 | handleHistoryData(commandSource, message.data) |
@@ -36,8 +36,6 @@ onMounted(() => { | @@ -36,8 +36,6 @@ onMounted(() => { | ||
36 | 36 | ||
37 | const onReceiveDataSourceMessage = (commandSource: CommandSource, message: SubscriptionUpdateMsg) => { | 37 | const onReceiveDataSourceMessage = (commandSource: CommandSource, message: SubscriptionUpdateMsg) => { |
38 | const { data } = commandSource | 38 | const { data } = commandSource |
39 | - const { deviceInfo, attrInfo } = data || {} | ||
40 | - const { deviceName } = deviceInfo || {} | ||
41 | const { attr } = data as NodeDataDataSourceJsonType | 39 | const { attr } = data as NodeDataDataSourceJsonType |
42 | const { latestValue } = useLatestMessageValue(message.data, attr) | 40 | const { latestValue } = useLatestMessageValue(message.data, attr) |
43 | unref(chartInstance)?.setOption({ | 41 | unref(chartInstance)?.setOption({ |
@@ -46,7 +44,7 @@ const onReceiveDataSourceMessage = (commandSource: CommandSource, message: Subsc | @@ -46,7 +44,7 @@ const onReceiveDataSourceMessage = (commandSource: CommandSource, message: Subsc | ||
46 | 44 | ||
47 | }], | 45 | }], |
48 | title: { | 46 | title: { |
49 | - text: `${deviceName || ''}-${attrInfo.name || ''}`, | 47 | + // text: `${deviceName || ''}-${attrInfo.name || ''}`, |
50 | }, | 48 | }, |
51 | } as EChartsOption) | 49 | } as EChartsOption) |
52 | } | 50 | } |
@@ -3,7 +3,9 @@ import { Button, Divider } from 'ant-design-vue' | @@ -3,7 +3,9 @@ import { Button, Divider } from 'ant-design-vue' | ||
3 | import { nextTick, onMounted, ref, unref } from 'vue' | 3 | import { nextTick, onMounted, ref, unref } from 'vue' |
4 | import { formSchemas } from '../config' | 4 | import { formSchemas } from '../config' |
5 | import { ChartComponentEnum } from '..' | 5 | import { ChartComponentEnum } from '..' |
6 | -import { DataSourceForm } from '@/core/Library/components/PublicForm/components/DataSourceForm' | 6 | + |
7 | +import { DataSourceForm } from '../component/index' | ||
8 | +// import { DataSourceForm } from '@/core/Library/components/PublicForm/components/DataSourceForm' | ||
7 | 9 | ||
8 | import { BasicForm, useForm } from '@/components/Form' | 10 | import { BasicForm, useForm } from '@/components/Form' |
9 | import { FormLayoutEnum } from '@/components/Form/src/enum' | 11 | import { FormLayoutEnum } from '@/components/Form/src/enum' |
@@ -33,9 +35,9 @@ const dataSourceElRef = ref<Nullable<InstanceType<typeof DataSourceForm>>>() | @@ -33,9 +35,9 @@ const dataSourceElRef = ref<Nullable<InstanceType<typeof DataSourceForm>>>() | ||
33 | 35 | ||
34 | const handleSetFormValues = async () => { | 36 | const handleSetFormValues = async () => { |
35 | const { dataSourceJson } = unref(getNodeData) || {} | 37 | const { dataSourceJson } = unref(getNodeData) || {} |
36 | - const { deviceId, attr, chartOption, deviceProfileId, deviceProfileTemplateId } = dataSourceJson || {} | 38 | + const { deviceId, attr, chartOption, deviceProfileId, deviceProfileTemplateId, deviceName } = dataSourceJson || {} |
37 | await nextTick() | 39 | await nextTick() |
38 | - unref(dataSourceElRef)?.setFieldsValue({ deviceId, attr, deviceProfileId, deviceProfileTemplateId }) | 40 | + unref(dataSourceElRef)?.setFieldsValue({ deviceId, attr, deviceProfileId, deviceProfileTemplateId, deviceName }) |
39 | setFieldsValue({ ...chartOption }) | 41 | setFieldsValue({ ...chartOption }) |
40 | } | 42 | } |
41 | 43 | ||
@@ -54,7 +56,7 @@ const handleSubmit = async () => { | @@ -54,7 +56,7 @@ const handleSubmit = async () => { | ||
54 | if (contentDataStore.getIsTemplate) | 56 | if (contentDataStore.getIsTemplate) |
55 | dataSourceJson = { ...value, deviceProfileId: value?.deviceProfileTemplateId, deviceId: null } | 57 | dataSourceJson = { ...value, deviceProfileId: value?.deviceProfileTemplateId, deviceId: null } |
56 | 58 | ||
57 | - saveNodeAllData({ dataSourceJson: { ...dataSourceJson, chartOption: { ...values } } }) | 59 | + saveNodeAllData({ dataSourceJson: { ...dataSourceJson, attr: typeof value.attr == 'string' ? [value.attr] : value.attr, chartOption: { ...values } } }) |
58 | createMessage.success('操作成功~') | 60 | createMessage.success('操作成功~') |
59 | savePageContent() | 61 | savePageContent() |
60 | } | 62 | } |
@@ -3,31 +3,35 @@ import { isLightboxMode } from '@/utils/env' | @@ -3,31 +3,35 @@ import { isLightboxMode } from '@/utils/env' | ||
3 | 3 | ||
4 | export const getDefaultOption = (): EChartsOption => { | 4 | export const getDefaultOption = (): EChartsOption => { |
5 | return { | 5 | return { |
6 | - tooltip: { | ||
7 | - trigger: 'item', | ||
8 | - confine: true, | 6 | + legend: { |
7 | + top: '10%', | ||
8 | + left: 'center', | ||
9 | + data: [''], | ||
9 | }, | 10 | }, |
10 | grid: { | 11 | grid: { |
11 | - left: '3%', | ||
12 | - right: '4%', | ||
13 | - bottom: '3%', | 12 | + top: '30%', |
13 | + left: '6%', | ||
14 | + right: '10%', | ||
15 | + bottom: '8%', | ||
14 | containLabel: true, | 16 | containLabel: true, |
15 | }, | 17 | }, |
16 | - dataset: { | ||
17 | - source: isLightboxMode() | 18 | + xAxis: { |
19 | + type: 'category', | ||
20 | + }, | ||
21 | + yAxis: { | ||
22 | + type: 'value', | ||
23 | + boundaryGap: [0, '100%'], | ||
24 | + }, | ||
25 | + series: [{ | ||
26 | + type: 'line', | ||
27 | + name: '温度', | ||
28 | + data: isLightboxMode() | ||
18 | ? [] | 29 | ? [] |
19 | : [ | 30 | : [ |
20 | - ['product', '2015', '2016', '2017'], | ||
21 | - ['Matcha Latte', 43.3, 85.8, 93.7], | ||
22 | - ['Milk Tea', 83.1, 73.4, 55.1], | ||
23 | - ['Cheese Cocoa', 86.4, 65.2, 82.5], | ||
24 | - ['Walnut Brownie', 72.4, 53.9, 39.1], | ||
25 | - ], | ||
26 | - }, | ||
27 | - xAxis: { type: 'category' }, | ||
28 | - yAxis: {}, | ||
29 | - series: [ | ||
30 | - { type: 'line' }, | ||
31 | - ], | 31 | + ['Matcha Latte', 43.3], |
32 | + ['Milk Tea', 83.1], | ||
33 | + ['Cheese Cocoa', 86.4], | ||
34 | + ['Walnut Brownie', 72.4]], | ||
35 | + }], | ||
32 | } | 36 | } |
33 | } | 37 | } |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | -import { computed, onMounted, onUnmounted, ref, unref } from 'vue' | ||
3 | -import type { DatasetComponentOption, ECharts, EChartsOption } from 'echarts' | 2 | +import { computed, onMounted, onUnmounted, ref, toRaw, unref } from 'vue' |
3 | +import type { ECharts, EChartsOption } from 'echarts' | ||
4 | import { init } from 'echarts' | 4 | import { init } from 'echarts' |
5 | import { getDefaultOption } from './index.config' | 5 | import { getDefaultOption } from './index.config' |
6 | import type { CreateComponentType, RenderComponentExposeType } from '@/core/Library/types' | 6 | import type { CreateComponentType, RenderComponentExposeType } from '@/core/Library/types' |
@@ -9,8 +9,12 @@ import type { NodeDataDataSourceJsonType } from '@/api/node/model' | @@ -9,8 +9,12 @@ import type { NodeDataDataSourceJsonType } from '@/api/node/model' | ||
9 | import type { SubscriptionData } from '@/core/websocket/type/message' | 9 | import type { SubscriptionData } from '@/core/websocket/type/message' |
10 | import { SocketSubscriberEnum } from '@/enums/datasource' | 10 | import { SocketSubscriberEnum } from '@/enums/datasource' |
11 | import { formatToDateTime } from '@/utils/dateUtil' | 11 | import { formatToDateTime } from '@/utils/dateUtil' |
12 | -import { useLatestMessageValue } from '@/core/Library/hook/useLatestMessageValue' | ||
13 | import type { CommandSource } from '@/core/websocket/processor' | 12 | import type { CommandSource } from '@/core/websocket/processor' |
13 | +import { useLatestMultipleMessageValue } from '@/core/Library/hook/useLatestMessageValue' | ||
14 | +import { useProductsStore } from '@/store/modules/products' | ||
15 | +interface IList { | ||
16 | + time: string | number | ||
17 | +} | ||
14 | 18 | ||
15 | const props = defineProps<{ | 19 | const props = defineProps<{ |
16 | config: CreateComponentType | 20 | config: CreateComponentType |
@@ -22,67 +26,126 @@ const chartElRef = ref<Nullable<HTMLDivElement>>() | @@ -22,67 +26,126 @@ const chartElRef = ref<Nullable<HTMLDivElement>>() | ||
22 | 26 | ||
23 | const chartInstance = ref<Nullable<ECharts>>() | 27 | const chartInstance = ref<Nullable<ECharts>>() |
24 | 28 | ||
29 | +const maxLength = ref<number>(20) | ||
30 | + | ||
31 | +const timeList = ref<number[] | string[] | any>([])// 存储XAxis的值 | ||
32 | +const seriesData = ref<any>([])// 存储series的值 | ||
33 | +const titleATTR = ref<string[] | any>([]) | ||
34 | + | ||
35 | +const productsStore = useProductsStore() | ||
36 | + | ||
25 | function initChartInstance() { | 37 | function initChartInstance() { |
26 | chartInstance.value = init(unref(chartElRef)) | 38 | chartInstance.value = init(unref(chartElRef)) |
27 | chartInstance.value.setOption(getDefaultOption()) | 39 | chartInstance.value.setOption(getDefaultOption()) |
28 | } | 40 | } |
29 | 41 | ||
30 | -const handleHistoryData = (message: SubscriptionData, attr: string) => { | ||
31 | - const data = message[attr] | ||
32 | - const xAxisData: string[] = [] | ||
33 | - const seriesData: number[] = [] | ||
34 | - | ||
35 | - for (const item of data) { | ||
36 | - const [ts, value] = item | ||
37 | - xAxisData.push(formatToDateTime(ts)) | ||
38 | - seriesData.push(value) | ||
39 | - } | 42 | +const handleHistoryData = (commandSource: CommandSource, message: SubscriptionData, attr: string[] | string) => { |
43 | + const { data } = commandSource || {} | ||
44 | + const { deviceName } = data as NodeDataDataSourceJsonType | ||
40 | 45 | ||
46 | + (attr as string[]).forEach((item) => { | ||
47 | + timeList.value.push(...message[item].map((item1) => { | ||
48 | + const [ts] = item1 | ||
49 | + return ts | ||
50 | + })) | ||
51 | + }) | ||
52 | + timeList.value = Array.from(new Set(timeList.value))?.sort((a: any, b: any) => a - b)// 去重获取到的时间 | ||
53 | + seriesData.value.forEach((item: any) => { | ||
54 | + item.data = unref(timeList).map((time: any) => ({ name: time, value: null })) | ||
55 | + }) | ||
56 | + seriesData.value.forEach((item: any) => { | ||
57 | + item.data.forEach((item1: any) => { | ||
58 | + message[item.attribute].forEach((messageItem) => { | ||
59 | + const [ts, value] = messageItem | ||
60 | + if (item1.name === ts) { | ||
61 | + item1.value = value || undefined | ||
62 | + item1.name = formatToDateTime(item1.name) | ||
63 | + } | ||
64 | + }) | ||
65 | + }) | ||
66 | + }) | ||
41 | unref(chartInstance)?.setOption({ | 67 | unref(chartInstance)?.setOption({ |
42 | - xAxis: { data: xAxisData }, | ||
43 | - series: { data: seriesData }, | 68 | + title: { |
69 | + text: `${deviceName || ''}`, | ||
70 | + }, | ||
71 | + xAxis: { | ||
72 | + data: toRaw(unref(timeList.value.map((item: string | number) => formatToDateTime(item)))), | ||
73 | + }, | ||
74 | + series: toRaw( | ||
75 | + unref(seriesData).map((item: { type: string; name: string; data: any }) => { | ||
76 | + const { type, name, data } = item | ||
77 | + return { | ||
78 | + type, | ||
79 | + name, | ||
80 | + data, | ||
81 | + } | ||
82 | + }), | ||
83 | + ), | ||
44 | } as EChartsOption) | 84 | } as EChartsOption) |
45 | } | 85 | } |
46 | 86 | ||
47 | -function sliceData(data: any[], maxLength = 20) { | ||
48 | - if (data.length > maxLength) | ||
49 | - return data.slice(1) | ||
50 | - return data | ||
51 | -} | 87 | +// const contentDataStore = useContentDataStoreWithOut() |
52 | 88 | ||
53 | -const handlerTimeSeriesData = (commandSource: CommandSource, message: SubscriptionData, attr: string) => { | 89 | +const handlerTimeSeriesData = (commandSource: CommandSource, message: SubscriptionData, attr: string[] | string) => { |
54 | const { data } = commandSource | 90 | const { data } = commandSource |
55 | - const { attrInfo, deviceInfo } = data as NodeDataDataSourceJsonType | ||
56 | - const { deviceName } = deviceInfo || {} | ||
57 | - const { ts, latestValue } = useLatestMessageValue(message, attr) | ||
58 | - const option = unref(chartInstance)?.getOption() as EChartsOption | ||
59 | - const oldDataset = (option.dataset as DatasetComponentOption[])?.[0].source as Recordable[] | ||
60 | - oldDataset.push({ | ||
61 | - ts: formatToDateTime(ts), | ||
62 | - [attr]: latestValue, | 91 | + const { deviceName } = data as NodeDataDataSourceJsonType |
92 | + const list: IList | any = {}// 记录时间 | ||
93 | + useLatestMultipleMessageValue(message, attr as any, (attribute, timespan, value) => { | ||
94 | + list.time = timespan || list.time | ||
95 | + seriesData.value.forEach((item: any) => { | ||
96 | + if (item.attribute === attribute) { | ||
97 | + item.data.push({ | ||
98 | + name: formatToDateTime(list.time), | ||
99 | + value: value || undefined, | ||
100 | + }) | ||
101 | + } | ||
102 | + if (item.data.length > unref(maxLength)) | ||
103 | + item.data.shift() | ||
104 | + }) | ||
63 | }) | 105 | }) |
106 | + list.time && timeList.value.push(formatToDateTime(list.time)) | ||
107 | + if (unref(timeList).length > unref(maxLength)) | ||
108 | + timeList.value.shift() | ||
64 | 109 | ||
65 | unref(chartInstance)?.setOption({ | 110 | unref(chartInstance)?.setOption({ |
66 | title: { | 111 | title: { |
67 | - text: `${deviceName || ''}-${attrInfo.name || ''}`, | 112 | + text: `${deviceName || ''}`, |
68 | }, | 113 | }, |
69 | - dataset: { | ||
70 | - dimensions: ['ts', attr], | ||
71 | - source: sliceData(oldDataset), | 114 | + xAxis: { |
115 | + data: toRaw(unref(timeList)), | ||
72 | }, | 116 | }, |
117 | + legend: { | ||
118 | + data: unref(titleATTR), | ||
119 | + } as any, | ||
120 | + series: toRaw( | ||
121 | + unref(seriesData).map((item: { type: string; name: string; data: any }) => { | ||
122 | + const { type, name, data } = item | ||
123 | + return { | ||
124 | + type, | ||
125 | + name, | ||
126 | + data, | ||
127 | + } | ||
128 | + }), | ||
129 | + ), | ||
73 | } as EChartsOption) | 130 | } as EChartsOption) |
74 | } | 131 | } |
75 | 132 | ||
76 | const { onMessage } = useOnMessage({ | 133 | const { onMessage } = useOnMessage({ |
77 | onReceiveDataSourceMessage(commandSource, message) { | 134 | onReceiveDataSourceMessage(commandSource, message) { |
78 | const { data } = commandSource | 135 | const { data } = commandSource |
79 | - const { chartOption, attr } = data as NodeDataDataSourceJsonType | 136 | + const { chartOption, attr, deviceProfileId } = data as NodeDataDataSourceJsonType |
80 | const { queryType } = chartOption || {} | 137 | const { queryType } = chartOption || {} |
138 | + if (!seriesData.value.length) { | ||
139 | + (attr as string[]).forEach((item: string) => { | ||
140 | + titleATTR.value.push(productsStore.getObjectModelByIdWithIdentifier(deviceProfileId, item)?.functionName) | ||
141 | + seriesData.value.push({ attribute: item, data: [], type: 'line', name: productsStore.getObjectModelByIdWithIdentifier(deviceProfileId, item)?.functionName }) | ||
142 | + }) | ||
143 | + } | ||
81 | 144 | ||
82 | if (queryType === SocketSubscriberEnum.TS_SUB_CMDS) | 145 | if (queryType === SocketSubscriberEnum.TS_SUB_CMDS) |
83 | handlerTimeSeriesData(commandSource, message.data, attr) | 146 | handlerTimeSeriesData(commandSource, message.data, attr) |
84 | else if (queryType === SocketSubscriberEnum.HISTORY_CMDS) | 147 | else if (queryType === SocketSubscriberEnum.HISTORY_CMDS) |
85 | - handleHistoryData(message.data, attr) | 148 | + handleHistoryData(commandSource, message.data, attr) |
86 | }, | 149 | }, |
87 | }) | 150 | }) |
88 | 151 |
@@ -34,13 +34,11 @@ function initChartInstance() { | @@ -34,13 +34,11 @@ function initChartInstance() { | ||
34 | const { onMessage } = useOnMessage({ | 34 | const { onMessage } = useOnMessage({ |
35 | onReceiveDataSourceMessage(commandSource, message) { | 35 | onReceiveDataSourceMessage(commandSource, message) { |
36 | const { data } = commandSource | 36 | const { data } = commandSource |
37 | - const { deviceInfo, attrInfo } = data || {} | ||
38 | - const { deviceName } = deviceInfo || {} | ||
39 | const { attr } = data as NodeDataDataSourceJsonType | 37 | const { attr } = data as NodeDataDataSourceJsonType |
40 | const { latestValue } = useLatestMessageValue(message.data, attr) | 38 | const { latestValue } = useLatestMessageValue(message.data, attr) |
41 | unref(chartInstance)?.setOption({ | 39 | unref(chartInstance)?.setOption({ |
42 | title: { | 40 | title: { |
43 | - text: `${deviceName || ''}-${attrInfo.name || ''}`, | 41 | + // text: `${deviceName || ''}-${attrInfo.name || ''}`, |
44 | }, | 42 | }, |
45 | series: [{ | 43 | series: [{ |
46 | data: getSetValue(Number(latestValue)), | 44 | data: getSetValue(Number(latestValue)), |
@@ -26,13 +26,11 @@ function initChartInstance() { | @@ -26,13 +26,11 @@ function initChartInstance() { | ||
26 | const { onMessage } = useOnMessage({ | 26 | const { onMessage } = useOnMessage({ |
27 | onReceiveDataSourceMessage(commandSource, message) { | 27 | onReceiveDataSourceMessage(commandSource, message) { |
28 | const { data } = commandSource | 28 | const { data } = commandSource |
29 | - const { deviceInfo, attrInfo } = (data || {}) as NodeDataDataSourceJsonType | ||
30 | - const { deviceName } = deviceInfo || {} | ||
31 | const { attr } = data as NodeDataDataSourceJsonType | 29 | const { attr } = data as NodeDataDataSourceJsonType |
32 | const { latestValue } = useLatestMessageValue(message.data, attr) | 30 | const { latestValue } = useLatestMessageValue(message.data, attr) |
33 | unref(chartInstance)?.setOption({ | 31 | unref(chartInstance)?.setOption({ |
34 | title: { | 32 | title: { |
35 | - text: `${deviceName || ''}-${attrInfo.name || ''}`, | 33 | + // text: `${deviceName || ''}-${attrInfo.name || ''}`, |
36 | }, | 34 | }, |
37 | series: [{ | 35 | series: [{ |
38 | data: [{ | 36 | data: [{ |
1 | +import { unref } from 'vue' | ||
2 | +import { getDeviceAttributes, getListByConfigurationId, getListByDeviceProfileIds } from '@/api/device' | ||
3 | +import type { DeviceItemType, ThingsModelItemType } from '@/api/device/model' | ||
4 | +import type { FormSchema } from '@/components/Form' | ||
5 | +import { ComponentEnum } from '@/components/Form/src/enum' | ||
6 | +import { ContentDataFieldsEnum, ContentDataFieldsNameEnum, DataTypeEnum } from '@/enums/datasource' | ||
7 | +import { useContentDataStoreWithOut } from '@/store/modules/contentData' | ||
8 | +import type { ProductAndDevice } from '@/api/content/model' | ||
9 | +import { ControlComponentEnum } from '@/core/Library/packages/Control' | ||
10 | +import { useParseParams } from '@/core/LoadData' | ||
11 | + | ||
12 | +const contentDataStore = useContentDataStoreWithOut() | ||
13 | +export const formSchemas = (componentKey?: string): FormSchema[] => { | ||
14 | + const isTemplate = contentDataStore.isTemplate // 判断是否是模板组态 | ||
15 | + const isTemplateLink = contentDataStore.getIsTemplateLink | ||
16 | + const params = useParseParams() | ||
17 | + const { configurationId } = params | ||
18 | + return [ | ||
19 | + { | ||
20 | + field: ContentDataFieldsEnum.DEVICE_PROFILE_ID, | ||
21 | + label: ContentDataFieldsNameEnum.DEVICE_PROFILE_ID, | ||
22 | + component: ComponentEnum.INPUT, | ||
23 | + ifShow: false, | ||
24 | + }, | ||
25 | + { | ||
26 | + field: ContentDataFieldsEnum.DEVICE_PROFILE_TEMPLATE_ID, // 模板产品id | ||
27 | + label: ContentDataFieldsNameEnum.DEVICE_PROFILE_ID, | ||
28 | + component: ComponentEnum.API_SELECT, | ||
29 | + ifShow: !!isTemplate, | ||
30 | + required: !!isTemplate, | ||
31 | + componentProps: ({ formModel }) => { | ||
32 | + return { | ||
33 | + options: (unref(contentDataStore.getProductAndDevice) || []).map((item: ProductAndDevice) => ({ label: item.profileName || item.name, value: item.profileId, transportType: item?.transportType, deviceType: item?.deviceType })), | ||
34 | + placeholder: '请选择产品', | ||
35 | + onSelect(value: string) { | ||
36 | + formModel[ContentDataFieldsEnum.DEVICE_PROFILE_ID] = value | ||
37 | + formModel[ContentDataFieldsEnum.ATTR] = [] | ||
38 | + }, | ||
39 | + getPopupContainer: () => document.body, | ||
40 | + } | ||
41 | + }, | ||
42 | + }, | ||
43 | + { | ||
44 | + field: ContentDataFieldsEnum.DEVICE_ID, | ||
45 | + label: ContentDataFieldsNameEnum.DEVICE_ID, | ||
46 | + component: ComponentEnum.API_SELECT, | ||
47 | + ifShow: !isTemplate, | ||
48 | + required: !isTemplate, | ||
49 | + componentProps: ({ formModel }) => { | ||
50 | + const organizationId = window.useParseParams().organizationId | ||
51 | + if (!organizationId) return | ||
52 | + return { | ||
53 | + showSearch: true, | ||
54 | + api: async (params: Recordable) => { | ||
55 | + if (isTemplateLink) return await getListByConfigurationId(configurationId!) | ||
56 | + return await getListByDeviceProfileIds(params) | ||
57 | + }, | ||
58 | + params: { | ||
59 | + deviceProfileIds: unref(contentDataStore.getProductIds), | ||
60 | + organizationId, | ||
61 | + }, | ||
62 | + aliasField: 'alias', | ||
63 | + fieldNames: { label: 'name', value: 'tbDeviceId' }, | ||
64 | + onSelect(value: string, option: DeviceItemType) { | ||
65 | + formModel[ContentDataFieldsEnum.DEVICE_PROFILE_ID] = value ? option.deviceProfileId : null | ||
66 | + formModel[ContentDataFieldsEnum.ATTR] = [] | ||
67 | + formModel[ContentDataFieldsEnum.DEVICE_NAME] = value ? option.alias || option.name : '' | ||
68 | + }, | ||
69 | + filterOption: (inputValue: string, option: DeviceItemType) => { | ||
70 | + return option.alias?.includes?.(inputValue) || option.name?.includes?.(inputValue) | ||
71 | + }, | ||
72 | + } | ||
73 | + }, | ||
74 | + }, | ||
75 | + { | ||
76 | + field: ContentDataFieldsEnum.DEVICE_NAME, | ||
77 | + label: ContentDataFieldsNameEnum.deviceName, | ||
78 | + component: ComponentEnum.INPUT, | ||
79 | + ifShow: false, | ||
80 | + }, | ||
81 | + { | ||
82 | + field: ContentDataFieldsEnum.ATTR, | ||
83 | + label: ContentDataFieldsNameEnum.ATTR, | ||
84 | + component: ComponentEnum.API_SELECT, | ||
85 | + required: true, | ||
86 | + componentProps: ({ formModel }) => { | ||
87 | + const deviceProfileId = isTemplate ? formModel[ContentDataFieldsEnum.DEVICE_PROFILE_TEMPLATE_ID] : formModel[ContentDataFieldsEnum.DEVICE_PROFILE_ID] | ||
88 | + return { | ||
89 | + showSearch: true, | ||
90 | + mode: 'multiple', | ||
91 | + api: async (params: string) => { | ||
92 | + if (!deviceProfileId) return [] | ||
93 | + const options = await getDeviceAttributes(params) | ||
94 | + if (componentKey === ControlComponentEnum.SWITCH) { // 开关只返回bool | ||
95 | + return options.filter((item) => { | ||
96 | + return item.detail.dataType.type === DataTypeEnum.BOOL | ||
97 | + }) | ||
98 | + } | ||
99 | + return options | ||
100 | + }, | ||
101 | + params: deviceProfileId, | ||
102 | + fieldNames: { label: 'name', value: 'identifier' }, | ||
103 | + filterOption: (inputValue: string, option: ThingsModelItemType) => { | ||
104 | + return option.name.includes(inputValue) | ||
105 | + }, | ||
106 | + } | ||
107 | + }, | ||
108 | + }, | ||
109 | + ] | ||
110 | +} |
1 | +export { default as DataSourceForm } from './index.vue' |
1 | +<script setup lang="ts"> | ||
2 | +import { computed, unref } from 'vue' | ||
3 | +import type { RuleError } from 'ant-design-vue/lib/form/interface' | ||
4 | +import { formSchemas } from './config' | ||
5 | +import { FormLayoutEnum } from '@/components/Form/src/enum' | ||
6 | +import { BasicForm, useForm } from '@/components/Form' | ||
7 | + | ||
8 | +export interface ComponentExposeType { | ||
9 | + getFieldsValue: () => any | ||
10 | + setFieldsValue: (value: any) => void | ||
11 | + validate: () => Promise<RuleError | any> | ||
12 | +} | ||
13 | + | ||
14 | +const props = defineProps<{ componentKey?: string }>() | ||
15 | +defineEmits(['fieldValueChange']) | ||
16 | + | ||
17 | +const getComponentKey = computed(() => { | ||
18 | + return props.componentKey | ||
19 | +}) | ||
20 | + | ||
21 | +const [registerForm, formActionType] = useForm({ | ||
22 | + schemas: formSchemas(unref(getComponentKey)), | ||
23 | + showActionButtonGroup: false, | ||
24 | + layout: FormLayoutEnum.HORIZONTAL, | ||
25 | + labelWidth: 70, | ||
26 | +}) | ||
27 | + | ||
28 | +const getFieldsValue = () => { | ||
29 | + return formActionType.getFieldsValue() | ||
30 | +} | ||
31 | + | ||
32 | +const validate = async () => { | ||
33 | + return await formActionType.validate() | ||
34 | +} | ||
35 | + | ||
36 | +const setFieldsValue = (value: Recordable) => { | ||
37 | + formActionType.setFieldsValue(value) | ||
38 | + formActionType.clearValidate() | ||
39 | +} | ||
40 | + | ||
41 | +defineExpose<ComponentExposeType>({ | ||
42 | + getFieldsValue, | ||
43 | + setFieldsValue, | ||
44 | + validate, | ||
45 | +}) | ||
46 | +</script> | ||
47 | + | ||
48 | +<template> | ||
49 | + <BasicForm @register="registerForm" @field-value-change="$emit('fieldValueChange')" /> | ||
50 | +</template> |
@@ -238,6 +238,7 @@ export enum ContentDataFieldsEnum { | @@ -238,6 +238,7 @@ export enum ContentDataFieldsEnum { | ||
238 | DEVICE_ID = 'deviceId', | 238 | DEVICE_ID = 'deviceId', |
239 | ORG_ID = 'orgId', | 239 | ORG_ID = 'orgId', |
240 | ATTR = 'attr', | 240 | ATTR = 'attr', |
241 | + DEVICE_NAME = 'deviceName', | ||
241 | VIDEO_FILTER = 'videoFilter', | 242 | VIDEO_FILTER = 'videoFilter', |
242 | VIDEO_ID = 'id', | 243 | VIDEO_ID = 'id', |
243 | VIDEO_URL = 'videoUrl', | 244 | VIDEO_URL = 'videoUrl', |
@@ -253,6 +254,7 @@ export enum ContentDataFieldsNameEnum { | @@ -253,6 +254,7 @@ export enum ContentDataFieldsNameEnum { | ||
253 | ORG_ID = '组织', | 254 | ORG_ID = '组织', |
254 | DEVICE_ID = '设备', | 255 | DEVICE_ID = '设备', |
255 | ATTR = '属性', | 256 | ATTR = '属性', |
257 | + deviceName = '设备名称', | ||
256 | VIDEO_ID = '视频流', | 258 | VIDEO_ID = '视频流', |
257 | ACCESS_MODE = 'ACCESS_MODE', | 259 | ACCESS_MODE = 'ACCESS_MODE', |
258 | VIDEO_URL = '视频地址', | 260 | VIDEO_URL = '视频地址', |
1 | import { defineStore } from 'pinia' | 1 | import { defineStore } from 'pinia' |
2 | -import { toRaw, unref } from 'vue' | 2 | +import { toRaw } from 'vue' |
3 | import { store } from '..' | 3 | import { store } from '..' |
4 | import type { NodeDataType } from '@/api/node/model' | 4 | import type { NodeDataType } from '@/api/node/model' |
5 | import type { ProductAndDevice } from '@/api/content/model' | 5 | import type { ProductAndDevice } from '@/api/content/model' |
@@ -7,12 +7,6 @@ import type { CreateComponentType } from '@/core/Library/types' | @@ -7,12 +7,6 @@ import type { CreateComponentType } from '@/core/Library/types' | ||
7 | import { isShareMode } from '@/utils/env' | 7 | import { isShareMode } from '@/utils/env' |
8 | import { ConfigurationAuthEnum, ConfigurationTemplateAuthEnum } from '@/enums/authEnum' | 8 | import { ConfigurationAuthEnum, ConfigurationTemplateAuthEnum } from '@/enums/authEnum' |
9 | 9 | ||
10 | -interface DeviceList { | ||
11 | - deviceId: string | ||
12 | - name: string | ||
13 | - codeType: string | ||
14 | -} | ||
15 | - | ||
16 | interface ContentDataStoreType { | 10 | interface ContentDataStoreType { |
17 | contentData: NodeDataType[] | 11 | contentData: NodeDataType[] |
18 | configurationId: Nullable<string> | 12 | configurationId: Nullable<string> |
@@ -20,7 +14,6 @@ interface ContentDataStoreType { | @@ -20,7 +14,6 @@ interface ContentDataStoreType { | ||
20 | isTemplate?: number | null | string | 14 | isTemplate?: number | null | string |
21 | configurationContentList?: any | 15 | configurationContentList?: any |
22 | configurationContentId: Nullable<string> | 16 | configurationContentId: Nullable<string> |
23 | - diveceDetailMap: Record<string, DeviceList> | ||
24 | hasDesignAuth?: boolean | 17 | hasDesignAuth?: boolean |
25 | hasPerviewAuth?: boolean | 18 | hasPerviewAuth?: boolean |
26 | isTemplateLink?: boolean | 19 | isTemplateLink?: boolean |
@@ -35,7 +28,6 @@ export const useContentDataStore = defineStore('app-content-data', { | @@ -35,7 +28,6 @@ export const useContentDataStore = defineStore('app-content-data', { | ||
35 | productAndDevice: [], | 28 | productAndDevice: [], |
36 | configurationContentList: [], | 29 | configurationContentList: [], |
37 | configurationContentId: null, | 30 | configurationContentId: null, |
38 | - diveceDetailMap: {}, | ||
39 | hasDesignAuth: true, | 31 | hasDesignAuth: true, |
40 | hasPerviewAuth: true, | 32 | hasPerviewAuth: true, |
41 | isTemplateLink: false, | 33 | isTemplateLink: false, |
@@ -70,17 +62,9 @@ export const useContentDataStore = defineStore('app-content-data', { | @@ -70,17 +62,9 @@ export const useContentDataStore = defineStore('app-content-data', { | ||
70 | 62 | ||
71 | setProductAndDevice(list: ProductAndDevice[]) { | 63 | setProductAndDevice(list: ProductAndDevice[]) { |
72 | this.productAndDevice = list | 64 | this.productAndDevice = list |
73 | - this.doBuildDeviceMap() | ||
74 | return list | 65 | return list |
75 | }, | 66 | }, |
76 | 67 | ||
77 | - doBuildDeviceMap() { | ||
78 | - const list = this.productAndDevice.map(item => toRaw(unref(item.deviceList))).flat(1) | ||
79 | - this.diveceDetailMap = list.reduce((prev, next) => { | ||
80 | - return { ...prev, [next?.deviceId]: next } | ||
81 | - }, {} as Record<'string', DeviceList>) | ||
82 | - }, | ||
83 | - | ||
84 | getCurrentNodeDataById(config: CreateComponentType): Nullable<NodeDataType> { | 68 | getCurrentNodeDataById(config: CreateComponentType): Nullable<NodeDataType> { |
85 | const { cellInfo } = config | 69 | const { cellInfo } = config |
86 | const { id } = cellInfo || {} | 70 | const { id } = cellInfo || {} |