Commit 66beda45970fc3a2b084db8583e0a1ff1434e306
Merge branch 'perf/data-board' into 'main_dev'
perf: 优化数据看板控制组件&&数据源绑定 See merge request yunteng/thingskit-front!1179
Showing
59 changed files
with
1308 additions
and
1266 deletions
@@ -137,7 +137,7 @@ export const createOrEditDevice = (data) => { | @@ -137,7 +137,7 @@ export const createOrEditDevice = (data) => { | ||
137 | 137 | ||
138 | // 查询设备详情 | 138 | // 查询设备详情 |
139 | export const getDeviceDetail = (id: string) => { | 139 | export const getDeviceDetail = (id: string) => { |
140 | - return defHttp.get({ | 140 | + return defHttp.get<DeviceRecord>({ |
141 | url: DeviceManagerApi.DEVICE_URL + `/${id}`, | 141 | url: DeviceManagerApi.DEVICE_URL + `/${id}`, |
142 | }); | 142 | }); |
143 | }; | 143 | }; |
1 | import { DataTypeEnum } from '/@/enums/objectModelEnum'; | 1 | import { DataTypeEnum } from '/@/enums/objectModelEnum'; |
2 | -import { FunctionType } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | 2 | +import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; |
3 | 3 | ||
4 | export interface Specs { | 4 | export interface Specs { |
5 | min: string; | 5 | min: string; |
@@ -9,7 +9,7 @@ export interface Specs { | @@ -9,7 +9,7 @@ export interface Specs { | ||
9 | 9 | ||
10 | dataType?: string; | 10 | dataType?: string; |
11 | name?: string; | 11 | name?: string; |
12 | - value?: string; | 12 | + value?: string | number; |
13 | step: string; | 13 | step: string; |
14 | length: string; | 14 | length: string; |
15 | boolOpen: string; | 15 | boolOpen: string; |
@@ -26,6 +26,13 @@ export interface DataType { | @@ -26,6 +26,13 @@ export interface DataType { | ||
26 | specsList?: Specs[]; | 26 | specsList?: Specs[]; |
27 | } | 27 | } |
28 | 28 | ||
29 | +export interface ExtensionDesc { | ||
30 | + zoomFactor?: number; | ||
31 | + actionType?: string; | ||
32 | + dataType: string; | ||
33 | + registerAddress: number; | ||
34 | +} | ||
35 | + | ||
29 | export interface StructJSON { | 36 | export interface StructJSON { |
30 | functionName?: string; | 37 | functionName?: string; |
31 | identifier: string; | 38 | identifier: string; |
@@ -46,7 +53,7 @@ export interface ModelOfMatterParams { | @@ -46,7 +53,7 @@ export interface ModelOfMatterParams { | ||
46 | deviceProfileId?: string; | 53 | deviceProfileId?: string; |
47 | functionJson: FunctionJson; | 54 | functionJson: FunctionJson; |
48 | functionName: string; | 55 | functionName: string; |
49 | - functionType: FunctionType; | 56 | + functionType: FunctionTypeEnum; |
50 | identifier: string; | 57 | identifier: string; |
51 | remark: string; | 58 | remark: string; |
52 | id?: string; | 59 | id?: string; |
@@ -54,11 +61,11 @@ export interface ModelOfMatterParams { | @@ -54,11 +61,11 @@ export interface ModelOfMatterParams { | ||
54 | callType?: string; | 61 | callType?: string; |
55 | eventType?: string; | 62 | eventType?: string; |
56 | accessMode?: string; | 63 | accessMode?: string; |
57 | - extensionDesc?: Recordable; | 64 | + extensionDesc?: ExtensionDesc; |
58 | } | 65 | } |
59 | 66 | ||
60 | export interface GetModelTslParams { | 67 | export interface GetModelTslParams { |
61 | - functionType: FunctionType; | 68 | + functionType: FunctionTypeEnum; |
62 | deviceProfileId: string; | 69 | deviceProfileId: string; |
63 | ifShowClass?: string | Boolean; | 70 | ifShowClass?: string | Boolean; |
64 | } | 71 | } |
@@ -85,3 +92,26 @@ export interface ModelOfMatterItemRecordType { | @@ -85,3 +92,26 @@ export interface ModelOfMatterItemRecordType { | ||
85 | status: number; | 92 | status: number; |
86 | deviceProfileId: string; | 93 | deviceProfileId: string; |
87 | } | 94 | } |
95 | + | ||
96 | +export interface BatchGetObjectModelItemType { | ||
97 | + id: string; | ||
98 | + name: string; | ||
99 | + transportType: string; | ||
100 | + deviceType: string; | ||
101 | + tsl: Tsl[]; | ||
102 | +} | ||
103 | + | ||
104 | +export interface Tsl { | ||
105 | + functionName: string; | ||
106 | + identifier: string; | ||
107 | + functionType: string; | ||
108 | + accessMode?: string; | ||
109 | + specs?: { | ||
110 | + dataType: DataType; | ||
111 | + }; | ||
112 | + extensionDesc: ExtensionDesc; | ||
113 | + eventType?: string; | ||
114 | + outputData?: StructJSON[]; | ||
115 | + callType?: string; | ||
116 | + inputData?: StructJSON[]; | ||
117 | +} |
1 | import { BasicPageParams } from '../model/baseModel'; | 1 | import { BasicPageParams } from '../model/baseModel'; |
2 | import { | 2 | import { |
3 | + BatchGetObjectModelItemType, | ||
3 | GetModelTslParams, | 4 | GetModelTslParams, |
4 | ImportModelOfMatterType, | 5 | ImportModelOfMatterType, |
5 | ModelOfMatterItemRecordType, | 6 | ModelOfMatterItemRecordType, |
6 | ModelOfMatterParams, | 7 | ModelOfMatterParams, |
7 | } from './model/modelOfMatterModel'; | 8 | } from './model/modelOfMatterModel'; |
9 | +import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; | ||
8 | import { defHttp } from '/@/utils/http/axios'; | 10 | import { defHttp } from '/@/utils/http/axios'; |
9 | -import { FunctionType } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | ||
10 | 11 | ||
11 | enum ModelOfMatter { | 12 | enum ModelOfMatter { |
12 | CREATE = '/things_model', | 13 | CREATE = '/things_model', |
@@ -26,12 +27,14 @@ enum ModelOfMatter { | @@ -26,12 +27,14 @@ enum ModelOfMatter { | ||
26 | 27 | ||
27 | IMPORT_CSV = '/things_model/csvImport', | 28 | IMPORT_CSV = '/things_model/csvImport', |
28 | EXCEL_EXPORT = '/things_model/downloadTemplate', | 29 | EXCEL_EXPORT = '/things_model/downloadTemplate', |
30 | + | ||
31 | + BATCH_GET_TSL_BY_DEVICE_PROFILES = '/things_model/batch/get_tsl', | ||
29 | } | 32 | } |
30 | 33 | ||
31 | export const getModelList = ( | 34 | export const getModelList = ( |
32 | params: BasicPageParams & { | 35 | params: BasicPageParams & { |
33 | deviceProfileId?: string; | 36 | deviceProfileId?: string; |
34 | - functionTyp?: FunctionType; | 37 | + functionTyp?: FunctionTypeEnum; |
35 | nameOrIdentifier?: string; | 38 | nameOrIdentifier?: string; |
36 | selectType?: string | undefined; | 39 | selectType?: string | undefined; |
37 | id?: string; | 40 | id?: string; |
@@ -181,3 +184,16 @@ export const excelExport = () => { | @@ -181,3 +184,16 @@ export const excelExport = () => { | ||
181 | responseType: 'blob', | 184 | responseType: 'blob', |
182 | }); | 185 | }); |
183 | }; | 186 | }; |
187 | + | ||
188 | +export const batchGetObjectModel = ({ | ||
189 | + deviceProfileIds, | ||
190 | + functionTypeEnum = 'all', | ||
191 | +}: { | ||
192 | + deviceProfileIds: string[]; | ||
193 | + functionTypeEnum?: FunctionTypeEnum | 'all'; | ||
194 | +}) => { | ||
195 | + return defHttp.post<BatchGetObjectModelItemType[]>({ | ||
196 | + url: ModelOfMatter.BATCH_GET_TSL_BY_DEVICE_PROFILES, | ||
197 | + data: { deviceProfileIds, functionTypeEnum }, | ||
198 | + }); | ||
199 | +}; |
@@ -59,7 +59,7 @@ export interface GenModbusCommandType { | @@ -59,7 +59,7 @@ export interface GenModbusCommandType { | ||
59 | crc: string; | 59 | crc: string; |
60 | deviceCode: string; | 60 | deviceCode: string; |
61 | method: string; | 61 | method: string; |
62 | - registerAddress: string; | 62 | + registerAddress: number; |
63 | registerNumber?: number; | 63 | registerNumber?: number; |
64 | registerValues?: number[]; | 64 | registerValues?: number[]; |
65 | } | 65 | } |
@@ -11,6 +11,7 @@ export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.v | @@ -11,6 +11,7 @@ export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.v | ||
11 | export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue'; | 11 | export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue'; |
12 | export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue'; | 12 | export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue'; |
13 | export { default as ApiUpload } from './src/components/ApiUpload.vue'; | 13 | export { default as ApiUpload } from './src/components/ApiUpload.vue'; |
14 | +export { default as ApiCascader } from './src/components/ApiCascader.vue'; | ||
14 | 15 | ||
15 | export { default as StructForm } from './src/components/StructForm/StructForm.vue'; | 16 | export { default as StructForm } from './src/components/StructForm/StructForm.vue'; |
16 | export { default as JavaScriptFunctionEditor } from './src/components/JavaScriptFunctionEditor.vue'; | 17 | export { default as JavaScriptFunctionEditor } from './src/components/JavaScriptFunctionEditor.vue'; |
1 | +<script setup lang="ts"> | ||
2 | + import { Cascader } from 'ant-design-vue'; | ||
3 | + import { LoadingOutlined } from '@ant-design/icons-vue'; | ||
4 | + import { CascaderOptionType } from 'ant-design-vue/lib/cascader'; | ||
5 | + import { get } from 'lodash'; | ||
6 | + import { ref, unref, watch, watchEffect } from 'vue'; | ||
7 | + import { useRuleFormItem } from '/@/hooks/component/useFormItem'; | ||
8 | + import { useI18n } from '/@/hooks/web/useI18n'; | ||
9 | + import { isFunction } from '/@/utils/is'; | ||
10 | + | ||
11 | + const { t } = useI18n(); | ||
12 | + | ||
13 | + const props = withDefaults( | ||
14 | + defineProps<{ | ||
15 | + value?: (string | number)[]; | ||
16 | + immediate?: boolean; | ||
17 | + params?: any; | ||
18 | + api?: Fn<any, Promise<any>>; | ||
19 | + options?: CascaderOptionType[]; | ||
20 | + resultField?: string; | ||
21 | + fieldNames?: Record<'label' | 'value' | 'children', string>; | ||
22 | + }>(), | ||
23 | + { | ||
24 | + value: () => [], | ||
25 | + immediate: true, | ||
26 | + fieldNames: () => ({ label: 'label', value: 'value', children: 'children' }), | ||
27 | + } | ||
28 | + ); | ||
29 | + | ||
30 | + const emit = defineEmits(['change', 'options-change', 'update:value']); | ||
31 | + | ||
32 | + const options = ref<CascaderOptionType[]>([]); | ||
33 | + const loading = ref(false); | ||
34 | + const isFirstLoad = ref(true); | ||
35 | + const emitData = ref<any[]>([]); | ||
36 | + | ||
37 | + // Embedded in the form, just use the hook binding to perform form verification | ||
38 | + const [state] = useRuleFormItem(props, 'value', 'update:value', emitData); | ||
39 | + | ||
40 | + watchEffect(() => { | ||
41 | + props.immediate && fetch(); | ||
42 | + }); | ||
43 | + | ||
44 | + watch( | ||
45 | + () => props.params, | ||
46 | + () => { | ||
47 | + !unref(isFirstLoad) && fetch(); | ||
48 | + }, | ||
49 | + { deep: true } | ||
50 | + ); | ||
51 | + | ||
52 | + async function fetch() { | ||
53 | + const api = props.api; | ||
54 | + if (!api || !isFunction(api)) return; | ||
55 | + options.value = []; | ||
56 | + try { | ||
57 | + loading.value = true; | ||
58 | + const res = await api(props.params); | ||
59 | + if (Array.isArray(res)) { | ||
60 | + options.value = res; | ||
61 | + emitChange(); | ||
62 | + return; | ||
63 | + } | ||
64 | + if (props.resultField) { | ||
65 | + options.value = get(res, props.resultField) || []; | ||
66 | + } | ||
67 | + emitChange(); | ||
68 | + } catch (error) { | ||
69 | + console.warn(error); | ||
70 | + } finally { | ||
71 | + loading.value = false; | ||
72 | + } | ||
73 | + } | ||
74 | + | ||
75 | + async function handleFetch(open) { | ||
76 | + if (open) { | ||
77 | + await fetch(); | ||
78 | + } | ||
79 | + } | ||
80 | + | ||
81 | + function emitChange() { | ||
82 | + emit('options-change', options); | ||
83 | + } | ||
84 | + | ||
85 | + function handleChange(_, ...args) { | ||
86 | + emitData.value = args; | ||
87 | + } | ||
88 | +</script> | ||
89 | + | ||
90 | +<template> | ||
91 | + <Cascader | ||
92 | + v-bind="$attrs" | ||
93 | + @change="handleChange" | ||
94 | + :fieldNames="fieldNames" | ||
95 | + :options="options" | ||
96 | + v-model:value="state" | ||
97 | + @popupVisibleChange="handleFetch" | ||
98 | + > | ||
99 | + <template #notFoundContent v-if="loading"> | ||
100 | + <span> | ||
101 | + <LoadingOutlined spin class="mr-1" /> | ||
102 | + {{ t('component.form.apiSelectNotFound') }} | ||
103 | + </span> | ||
104 | + </template> | ||
105 | + </Cascader> | ||
106 | +</template> |
@@ -117,6 +117,7 @@ export type ComponentType = | @@ -117,6 +117,7 @@ export type ComponentType = | ||
117 | | 'ColorPicker' | 117 | | 'ColorPicker' |
118 | | 'IconDrawer' | 118 | | 'IconDrawer' |
119 | | 'ApiUpload' | 119 | | 'ApiUpload' |
120 | + | 'ApiCascader' | ||
120 | | 'ApiSearchSelect' | 121 | | 'ApiSearchSelect' |
121 | | 'StructForm' | 122 | | 'StructForm' |
122 | | 'ApiSelectScrollLoad' | 123 | | 'ApiSelectScrollLoad' |
@@ -7,6 +7,12 @@ export enum DataTypeEnum { | @@ -7,6 +7,12 @@ export enum DataTypeEnum { | ||
7 | ENUM = 'ENUM', | 7 | ENUM = 'ENUM', |
8 | } | 8 | } |
9 | 9 | ||
10 | +export enum FunctionTypeEnum { | ||
11 | + PROPERTIES = 'properties', | ||
12 | + EVENTS = 'events', | ||
13 | + SERVICE = 'services', | ||
14 | +} | ||
15 | + | ||
10 | export enum RegisterDataTypeEnum { | 16 | export enum RegisterDataTypeEnum { |
11 | UN_SHORT = 'unshort', | 17 | UN_SHORT = 'unshort', |
12 | } | 18 | } |
@@ -26,3 +32,7 @@ export enum RegisterActionTypeNameEnum { | @@ -26,3 +32,7 @@ export enum RegisterActionTypeNameEnum { | ||
26 | INT = '06写入单个保持寄存器', | 32 | INT = '06写入单个保持寄存器', |
27 | DOUBLE = '16写入多个保持寄存器', | 33 | DOUBLE = '16写入多个保持寄存器', |
28 | } | 34 | } |
35 | + | ||
36 | +export enum ModbusCRCEnum { | ||
37 | + CRC_16_LOWER = 'CRC_16_LOWER', | ||
38 | +} |
@@ -2,8 +2,7 @@ import { BasicColumn, FormSchema } from '/@/components/Table'; | @@ -2,8 +2,7 @@ import { BasicColumn, FormSchema } from '/@/components/Table'; | ||
2 | import { findDictItemByCode } from '/@/api/system/dict'; | 2 | import { findDictItemByCode } from '/@/api/system/dict'; |
3 | import { h, unref } from 'vue'; | 3 | import { h, unref } from 'vue'; |
4 | import { Tooltip } from 'ant-design-vue'; | 4 | import { Tooltip } from 'ant-design-vue'; |
5 | - | ||
6 | -import { FunctionType } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | 5 | +import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; |
7 | import { useMessage } from '/@/hooks/web/useMessage'; | 6 | import { useMessage } from '/@/hooks/web/useMessage'; |
8 | import { useClipboard } from '@vueuse/core'; | 7 | import { useClipboard } from '@vueuse/core'; |
9 | import { DictEnum } from '/@/enums/dictEnum'; | 8 | import { DictEnum } from '/@/enums/dictEnum'; |
@@ -26,10 +25,10 @@ export const columns: BasicColumn[] = [ | @@ -26,10 +25,10 @@ export const columns: BasicColumn[] = [ | ||
26 | }, | 25 | }, |
27 | ]; | 26 | ]; |
28 | 27 | ||
29 | -export const formatFunctionType: Record<FunctionType, string> = { | ||
30 | - [FunctionType.PROPERTIES]: '属性', | ||
31 | - [FunctionType.EVENTS]: '事件', | ||
32 | - [FunctionType.SERVICE]: '服务', | 28 | +export const formatFunctionType: Record<FunctionTypeEnum, string> = { |
29 | + [FunctionTypeEnum.PROPERTIES]: '属性', | ||
30 | + [FunctionTypeEnum.EVENTS]: '事件', | ||
31 | + [FunctionTypeEnum.SERVICE]: '服务', | ||
33 | }; | 32 | }; |
34 | 33 | ||
35 | const handleCopy = async (value: string) => { | 34 | const handleCopy = async (value: string) => { |
@@ -45,7 +44,7 @@ export const columnsDrawer: BasicColumn[] = [ | @@ -45,7 +44,7 @@ export const columnsDrawer: BasicColumn[] = [ | ||
45 | title: '功能类型', | 44 | title: '功能类型', |
46 | dataIndex: 'functionType', | 45 | dataIndex: 'functionType', |
47 | width: 90, | 46 | width: 90, |
48 | - format: (text: FunctionType) => { | 47 | + format: (text: FunctionTypeEnum) => { |
49 | return formatFunctionType[text]; | 48 | return formatFunctionType[text]; |
50 | }, | 49 | }, |
51 | }, | 50 | }, |
@@ -5,7 +5,8 @@ import { MessageEnum } from '/@/enums/messageEnum'; | @@ -5,7 +5,8 @@ import { MessageEnum } from '/@/enums/messageEnum'; | ||
5 | import { numberRule } from '/@/utils/rules'; | 5 | import { numberRule } from '/@/utils/rules'; |
6 | 6 | ||
7 | import { deviceConfigGetRuleChain } from '/@/api/device/deviceConfigApi'; | 7 | import { deviceConfigGetRuleChain } from '/@/api/device/deviceConfigApi'; |
8 | -import { FormField, FunctionType } from './step/cpns/physical/cpns/config'; | 8 | +import { FormField } from './step/cpns/physical/cpns/config'; |
9 | +import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; | ||
9 | import { h, unref } from 'vue'; | 10 | import { h, unref } from 'vue'; |
10 | import { Tag, Tooltip } from 'ant-design-vue'; | 11 | import { Tag, Tooltip } from 'ant-design-vue'; |
11 | import { EventType, EventTypeColor, EventTypeName } from '../list/cpns/tabs/EventManage/config'; | 12 | import { EventType, EventTypeColor, EventTypeName } from '../list/cpns/tabs/EventManage/config'; |
@@ -68,10 +69,10 @@ export const steps = [ | @@ -68,10 +69,10 @@ export const steps = [ | ||
68 | }, | 69 | }, |
69 | ]; | 70 | ]; |
70 | 71 | ||
71 | -export const formatFunctionType: Record<FunctionType, string> = { | ||
72 | - [FunctionType.PROPERTIES]: '属性', | ||
73 | - [FunctionType.EVENTS]: '事件', | ||
74 | - [FunctionType.SERVICE]: '服务', | 72 | +export const formatFunctionType: Record<FunctionTypeEnum, string> = { |
73 | + [FunctionTypeEnum.PROPERTIES]: '属性', | ||
74 | + [FunctionTypeEnum.EVENTS]: '事件', | ||
75 | + [FunctionTypeEnum.SERVICE]: '服务', | ||
75 | }; | 76 | }; |
76 | 77 | ||
77 | export const physicalColumn: BasicColumn[] = [ | 78 | export const physicalColumn: BasicColumn[] = [ |
@@ -79,7 +80,7 @@ export const physicalColumn: BasicColumn[] = [ | @@ -79,7 +80,7 @@ export const physicalColumn: BasicColumn[] = [ | ||
79 | title: '功能类型', | 80 | title: '功能类型', |
80 | dataIndex: FormField.FUNCTION_TYPE, | 81 | dataIndex: FormField.FUNCTION_TYPE, |
81 | width: 90, | 82 | width: 90, |
82 | - format: (text: FunctionType) => { | 83 | + format: (text: FunctionTypeEnum) => { |
83 | return formatFunctionType[text]; | 84 | return formatFunctionType[text]; |
84 | }, | 85 | }, |
85 | }, | 86 | }, |
@@ -153,9 +154,12 @@ export const modelOfMatterForm: FormSchema[] = [ | @@ -153,9 +154,12 @@ export const modelOfMatterForm: FormSchema[] = [ | ||
153 | colProps: { span: 8 }, | 154 | colProps: { span: 8 }, |
154 | componentProps: { | 155 | componentProps: { |
155 | options: [ | 156 | options: [ |
156 | - { label: formatFunctionType[FunctionType.PROPERTIES], value: FunctionType.PROPERTIES }, | ||
157 | - { label: formatFunctionType[FunctionType.EVENTS], value: FunctionType.EVENTS }, | ||
158 | - { label: formatFunctionType[FunctionType.SERVICE], value: FunctionType.SERVICE }, | 157 | + { |
158 | + label: formatFunctionType[FunctionTypeEnum.PROPERTIES], | ||
159 | + value: FunctionTypeEnum.PROPERTIES, | ||
160 | + }, | ||
161 | + { label: formatFunctionType[FunctionTypeEnum.EVENTS], value: FunctionTypeEnum.EVENTS }, | ||
162 | + { label: formatFunctionType[FunctionTypeEnum.SERVICE], value: FunctionTypeEnum.SERVICE }, | ||
159 | ], | 163 | ], |
160 | }, | 164 | }, |
161 | }, | 165 | }, |
@@ -156,7 +156,7 @@ | @@ -156,7 +156,7 @@ | ||
156 | import { isObject } from '/@/utils/is'; | 156 | import { isObject } from '/@/utils/is'; |
157 | import { useRole } from '/@/hooks/business/useRole'; | 157 | import { useRole } from '/@/hooks/business/useRole'; |
158 | import { ExportModelCategory } from '/@/api/device/modelOfMatter'; | 158 | import { ExportModelCategory } from '/@/api/device/modelOfMatter'; |
159 | - import { FunctionType } from './cpns/physical/cpns/config'; | 159 | + import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; |
160 | import SelectImport from '../components/SelectImport.vue'; | 160 | import SelectImport from '../components/SelectImport.vue'; |
161 | 161 | ||
162 | const { isPlatformAdmin, isSysadmin } = useRole(); | 162 | const { isPlatformAdmin, isSysadmin } = useRole(); |
@@ -287,15 +287,15 @@ | @@ -287,15 +287,15 @@ | ||
287 | return Promise.all([ | 287 | return Promise.all([ |
288 | ExportModelCategory({ | 288 | ExportModelCategory({ |
289 | deviceProfileId, | 289 | deviceProfileId, |
290 | - functionType: FunctionType.EVENTS, | 290 | + functionType: FunctionTypeEnum.EVENTS, |
291 | }), | 291 | }), |
292 | ExportModelCategory({ | 292 | ExportModelCategory({ |
293 | deviceProfileId, | 293 | deviceProfileId, |
294 | - functionType: FunctionType.PROPERTIES, | 294 | + functionType: FunctionTypeEnum.PROPERTIES, |
295 | }), | 295 | }), |
296 | ExportModelCategory({ | 296 | ExportModelCategory({ |
297 | deviceProfileId, | 297 | deviceProfileId, |
298 | - functionType: FunctionType.SERVICE, | 298 | + functionType: FunctionTypeEnum.SERVICE, |
299 | }), | 299 | }), |
300 | ]); | 300 | ]); |
301 | }; | 301 | }; |
@@ -23,24 +23,24 @@ | @@ -23,24 +23,24 @@ | ||
23 | v-model:activeKey="activeKey" | 23 | v-model:activeKey="activeKey" |
24 | :size="size" | 24 | :size="size" |
25 | > | 25 | > |
26 | - <TabPane :key="FunctionType.PROPERTIES" tab="属性" /> | ||
27 | - <TabPane :key="FunctionType.SERVICE" :disabled="isTCPGatewaySubDevice" tab="服务" /> | ||
28 | - <TabPane :key="FunctionType.EVENTS" tab="事件" :disabled="isTCPGatewaySubDevice" /> | 26 | + <TabPane :key="FunctionTypeEnum.PROPERTIES" tab="属性" /> |
27 | + <TabPane :key="FunctionTypeEnum.SERVICE" :disabled="isTCPGatewaySubDevice" tab="服务" /> | ||
28 | + <TabPane :key="FunctionTypeEnum.EVENTS" tab="事件" :disabled="isTCPGatewaySubDevice" /> | ||
29 | </Tabs> | 29 | </Tabs> |
30 | <Attribute | 30 | <Attribute |
31 | - v-if="activeKey === FunctionType.PROPERTIES" | 31 | + v-if="activeKey === FunctionTypeEnum.PROPERTIES" |
32 | :openModalMode="openModalMode" | 32 | :openModalMode="openModalMode" |
33 | :transportType="record?.transportType" | 33 | :transportType="record?.transportType" |
34 | ref="AttrRef" | 34 | ref="AttrRef" |
35 | /> | 35 | /> |
36 | <Service | 36 | <Service |
37 | - v-if="activeKey === FunctionType.SERVICE" | 37 | + v-if="activeKey === FunctionTypeEnum.SERVICE" |
38 | :record="$props.record" | 38 | :record="$props.record" |
39 | :openModalMode="openModalMode" | 39 | :openModalMode="openModalMode" |
40 | ref="ServiceRef" | 40 | ref="ServiceRef" |
41 | /> | 41 | /> |
42 | <Events | 42 | <Events |
43 | - v-if="activeKey === FunctionType.EVENTS" | 43 | + v-if="activeKey === FunctionTypeEnum.EVENTS" |
44 | :openModalMode="openModalMode" | 44 | :openModalMode="openModalMode" |
45 | ref="EventsRef" | 45 | ref="EventsRef" |
46 | /> | 46 | /> |
@@ -69,7 +69,7 @@ | @@ -69,7 +69,7 @@ | ||
69 | import { DeviceRecord, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | 69 | import { DeviceRecord, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
70 | import { useMessage } from '/@/hooks/web/useMessage'; | 70 | import { useMessage } from '/@/hooks/web/useMessage'; |
71 | import { OpenModelMode, OpenModelOfMatterModelParams } from './types/index'; | 71 | import { OpenModelMode, OpenModelOfMatterModelParams } from './types/index'; |
72 | - import { FunctionType } from './cpns/config'; | 72 | + import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; |
73 | import { useRole } from '/@/hooks/business/useRole'; | 73 | import { useRole } from '/@/hooks/business/useRole'; |
74 | 74 | ||
75 | const { isPlatformAdmin, isSysadmin } = useRole(); | 75 | const { isPlatformAdmin, isSysadmin } = useRole(); |
@@ -87,7 +87,7 @@ | @@ -87,7 +87,7 @@ | ||
87 | }); | 87 | }); |
88 | 88 | ||
89 | const blockContent = `属性一般是指设备的运行状态,如当前温度等;服务是指设备可被调用的方法,支持定义参数,如执行某项任务;事件则是指设备上报的通知,如告警,需要被及时处理。`; | 89 | const blockContent = `属性一般是指设备的运行状态,如当前温度等;服务是指设备可被调用的方法,支持定义参数,如执行某项任务;事件则是指设备上报的通知,如告警,需要被及时处理。`; |
90 | - const activeKey = ref<FunctionType>(FunctionType.PROPERTIES); | 90 | + const activeKey = ref<FunctionTypeEnum>(FunctionTypeEnum.PROPERTIES); |
91 | const size = ref('small'); | 91 | const size = ref('small'); |
92 | 92 | ||
93 | const AttrRef = ref<InstanceType<typeof Attribute>>(); | 93 | const AttrRef = ref<InstanceType<typeof Attribute>>(); |
@@ -98,7 +98,7 @@ | @@ -98,7 +98,7 @@ | ||
98 | const openModalMode = ref<OpenModelMode>(OpenModelMode.CREATE); | 98 | const openModalMode = ref<OpenModelMode>(OpenModelMode.CREATE); |
99 | const openModalParams = ref<OpenModelOfMatterModelParams>(); | 99 | const openModalParams = ref<OpenModelOfMatterModelParams>(); |
100 | 100 | ||
101 | - const functionType = ref<FunctionType>(); | 101 | + const functionType = ref<FunctionTypeEnum>(); |
102 | const { createMessage } = useMessage(); | 102 | const { createMessage } = useMessage(); |
103 | 103 | ||
104 | const setAttrFormData = (data: ModelOfMatterParams) => AttrRef.value?.setFormData(data); | 104 | const setAttrFormData = (data: ModelOfMatterParams) => AttrRef.value?.setFormData(data); |
@@ -106,12 +106,12 @@ | @@ -106,12 +106,12 @@ | ||
106 | const setEventsFormData = (data: ModelOfMatterParams) => EventsRef.value?.setFormData(data); | 106 | const setEventsFormData = (data: ModelOfMatterParams) => EventsRef.value?.setFormData(data); |
107 | 107 | ||
108 | const enums = { | 108 | const enums = { |
109 | - [FunctionType.PROPERTIES]: setAttrFormData, | ||
110 | - [FunctionType.SERVICE]: setServiceFormData, | ||
111 | - [FunctionType.EVENTS]: setEventsFormData, | 109 | + [FunctionTypeEnum.PROPERTIES]: setAttrFormData, |
110 | + [FunctionTypeEnum.SERVICE]: setServiceFormData, | ||
111 | + [FunctionTypeEnum.EVENTS]: setEventsFormData, | ||
112 | }; | 112 | }; |
113 | 113 | ||
114 | - function setFormData(type: FunctionType, value: ModelOfMatterParams) { | 114 | + function setFormData(type: FunctionTypeEnum, value: ModelOfMatterParams) { |
115 | const setFn = enums[type]; | 115 | const setFn = enums[type]; |
116 | setFn(value); | 116 | setFn(value); |
117 | } | 117 | } |
@@ -147,7 +147,7 @@ | @@ -147,7 +147,7 @@ | ||
147 | AttrRef.value?.resetFormData(); | 147 | AttrRef.value?.resetFormData(); |
148 | ServiceRef.value?.resetFormData(); | 148 | ServiceRef.value?.resetFormData(); |
149 | EventsRef.value?.resetFormData(); | 149 | EventsRef.value?.resetFormData(); |
150 | - activeKey.value = FunctionType.PROPERTIES; | 150 | + activeKey.value = FunctionTypeEnum.PROPERTIES; |
151 | if (flag) { | 151 | if (flag) { |
152 | closeModal(); | 152 | closeModal(); |
153 | } | 153 | } |
@@ -158,9 +158,9 @@ | @@ -158,9 +158,9 @@ | ||
158 | setModalProps({ loading: false, okButtonProps: { loading: true } }); | 158 | setModalProps({ loading: false, okButtonProps: { loading: true } }); |
159 | 159 | ||
160 | let params: Partial<ModelOfMatterParams>; | 160 | let params: Partial<ModelOfMatterParams>; |
161 | - if (activeKey.value == FunctionType.PROPERTIES) { | 161 | + if (activeKey.value == FunctionTypeEnum.PROPERTIES) { |
162 | params = (await AttrRef.value?.getFormData()) || {}; | 162 | params = (await AttrRef.value?.getFormData()) || {}; |
163 | - } else if (activeKey.value == FunctionType.SERVICE) { | 163 | + } else if (activeKey.value == FunctionTypeEnum.SERVICE) { |
164 | params = (await ServiceRef.value?.getFormData()) || {}; | 164 | params = (await ServiceRef.value?.getFormData()) || {}; |
165 | } else { | 165 | } else { |
166 | params = (await EventsRef.value?.getFormData()) || {}; | 166 | params = (await EventsRef.value?.getFormData()) || {}; |
@@ -24,7 +24,7 @@ | @@ -24,7 +24,7 @@ | ||
24 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; | 24 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
25 | import { Button } from 'ant-design-vue'; | 25 | import { Button } from 'ant-design-vue'; |
26 | import { getModelTsl } from '/@/api/device/modelOfMatter'; | 26 | import { getModelTsl } from '/@/api/device/modelOfMatter'; |
27 | - import { FunctionType } from './cpns/config'; | 27 | + import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; |
28 | import { isObject } from '/@/utils/is'; | 28 | import { isObject } from '/@/utils/is'; |
29 | 29 | ||
30 | defineEmits(['register']); | 30 | defineEmits(['register']); |
@@ -75,15 +75,15 @@ | @@ -75,15 +75,15 @@ | ||
75 | return Promise.all([ | 75 | return Promise.all([ |
76 | getModelTsl({ | 76 | getModelTsl({ |
77 | deviceProfileId, | 77 | deviceProfileId, |
78 | - functionType: FunctionType.EVENTS, | 78 | + functionType: FunctionTypeEnum.EVENTS, |
79 | }), | 79 | }), |
80 | getModelTsl({ | 80 | getModelTsl({ |
81 | deviceProfileId, | 81 | deviceProfileId, |
82 | - functionType: FunctionType.PROPERTIES, | 82 | + functionType: FunctionTypeEnum.PROPERTIES, |
83 | }), | 83 | }), |
84 | getModelTsl({ | 84 | getModelTsl({ |
85 | deviceProfileId, | 85 | deviceProfileId, |
86 | - functionType: FunctionType.SERVICE, | 86 | + functionType: FunctionTypeEnum.SERVICE, |
87 | }), | 87 | }), |
88 | ]); | 88 | ]); |
89 | }; | 89 | }; |
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | transfromToStructJSON, | 6 | transfromToStructJSON, |
7 | excludeIdInStructJSON, | 7 | excludeIdInStructJSON, |
8 | } from '/@/components/Form/src/components/StructForm/util'; | 8 | } from '/@/components/Form/src/components/StructForm/util'; |
9 | - import { FunctionType } from './config'; | 9 | + import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; |
10 | import { isArray } from 'lodash'; | 10 | import { isArray } from 'lodash'; |
11 | import { OpenModelMode } from '../types'; | 11 | import { OpenModelMode } from '../types'; |
12 | import { formSchemas } from '/@/components/Form/src/components/StructForm/config'; | 12 | import { formSchemas } from '/@/components/Form/src/components/StructForm/config'; |
@@ -46,7 +46,7 @@ | @@ -46,7 +46,7 @@ | ||
46 | 46 | ||
47 | const value = { | 47 | const value = { |
48 | functionName, | 48 | functionName, |
49 | - functionType: FunctionType.PROPERTIES, | 49 | + functionType: FunctionTypeEnum.PROPERTIES, |
50 | remark, | 50 | remark, |
51 | identifier, | 51 | identifier, |
52 | accessMode, | 52 | accessMode, |
@@ -3,7 +3,8 @@ | @@ -3,7 +3,8 @@ | ||
3 | </template> | 3 | </template> |
4 | <script lang="ts" setup> | 4 | <script lang="ts" setup> |
5 | import { BasicForm, useForm } from '/@/components/Form'; | 5 | import { BasicForm, useForm } from '/@/components/Form'; |
6 | - import { eventSchemas, FunctionType } from './config'; | 6 | + import { eventSchemas } from './config'; |
7 | + import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; | ||
7 | import { ModelOfMatterParams, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | 8 | import { ModelOfMatterParams, StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
8 | import { StructFormValue } from '/@/components/Form/src/components/StructForm/type'; | 9 | import { StructFormValue } from '/@/components/Form/src/components/StructForm/type'; |
9 | import { excludeIdInStructJSON } from '/@/components/Form/src/components/StructForm/util'; | 10 | import { excludeIdInStructJSON } from '/@/components/Form/src/components/StructForm/util'; |
@@ -57,7 +58,7 @@ | @@ -57,7 +58,7 @@ | ||
57 | functionName, | 58 | functionName, |
58 | identifier, | 59 | identifier, |
59 | remark, | 60 | remark, |
60 | - functionType: FunctionType.EVENTS, | 61 | + functionType: FunctionTypeEnum.EVENTS, |
61 | eventType, | 62 | eventType, |
62 | functionJson: { | 63 | functionJson: { |
63 | outputData, | 64 | outputData, |
@@ -4,7 +4,7 @@ | @@ -4,7 +4,7 @@ | ||
4 | <script lang="ts" setup> | 4 | <script lang="ts" setup> |
5 | import { BasicForm, useForm } from '/@/components/Form'; | 5 | import { BasicForm, useForm } from '/@/components/Form'; |
6 | import { FormField, serviceSchemas } from './config'; | 6 | import { FormField, serviceSchemas } from './config'; |
7 | - import { FunctionType } from './config'; | 7 | + import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; |
8 | import { StructFormValue } from '/@/components/Form/src/components/StructForm/type'; | 8 | import { StructFormValue } from '/@/components/Form/src/components/StructForm/type'; |
9 | import { ModelOfMatterParams, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | 9 | import { ModelOfMatterParams, StructJSON } from '/@/api/device/model/modelOfMatterModel'; |
10 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; | 10 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
@@ -94,7 +94,7 @@ | @@ -94,7 +94,7 @@ | ||
94 | functionName, | 94 | functionName, |
95 | identifier, | 95 | identifier, |
96 | remark, | 96 | remark, |
97 | - functionType: FunctionType.SERVICE, | 97 | + functionType: FunctionTypeEnum.SERVICE, |
98 | callType, | 98 | callType, |
99 | functionJson: { | 99 | functionJson: { |
100 | inputData, | 100 | inputData, |
@@ -9,9 +9,9 @@ | @@ -9,9 +9,9 @@ | ||
9 | </div> | 9 | </div> |
10 | <div> | 10 | <div> |
11 | <Tabs type="card" v-model:active-key="activeKey" @change="handleSwitchTsl"> | 11 | <Tabs type="card" v-model:active-key="activeKey" @change="handleSwitchTsl"> |
12 | - <Tabs.TabPane :key="FunctionType.PROPERTIES" tab="属性" /> | ||
13 | - <Tabs.TabPane :key="FunctionType.SERVICE" tab="服务" /> | ||
14 | - <Tabs.TabPane :key="FunctionType.EVENTS" tab="事件" /> | 12 | + <Tabs.TabPane :key="FunctionTypeEnum.PROPERTIES" tab="属性" /> |
13 | + <Tabs.TabPane :key="FunctionTypeEnum.SERVICE" tab="服务" /> | ||
14 | + <Tabs.TabPane :key="FunctionTypeEnum.EVENTS" tab="事件" /> | ||
15 | <template #tabBarExtraContent> | 15 | <template #tabBarExtraContent> |
16 | <Button class="ml-2" @click="handleCopy"> | 16 | <Button class="ml-2" @click="handleCopy"> |
17 | <template #icon> | 17 | <template #icon> |
@@ -38,7 +38,7 @@ | @@ -38,7 +38,7 @@ | ||
38 | import { CopyOutlined } from '@ant-design/icons-vue'; | 38 | import { CopyOutlined } from '@ant-design/icons-vue'; |
39 | import { useMessage } from '/@/hooks/web/useMessage'; | 39 | import { useMessage } from '/@/hooks/web/useMessage'; |
40 | import { Button, Typography, TypographyParagraph, Tabs, Spin, Input } from 'ant-design-vue'; | 40 | import { Button, Typography, TypographyParagraph, Tabs, Spin, Input } from 'ant-design-vue'; |
41 | - import { FunctionType } from './config'; | 41 | + import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; |
42 | import useCommon from '../hook/useCommon'; | 42 | import useCommon from '../hook/useCommon'; |
43 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; | 43 | import { DeviceRecord } from '/@/api/device/model/deviceModel'; |
44 | import { getModelTsl } from '/@/api/device/modelOfMatter'; | 44 | import { getModelTsl } from '/@/api/device/modelOfMatter'; |
@@ -56,7 +56,7 @@ | @@ -56,7 +56,7 @@ | ||
56 | 56 | ||
57 | const jsonValue = ref(); | 57 | const jsonValue = ref(); |
58 | 58 | ||
59 | - const activeKey = ref(FunctionType.PROPERTIES); | 59 | + const activeKey = ref(FunctionTypeEnum.PROPERTIES); |
60 | 60 | ||
61 | const { copied, copy } = useClipboard({ legacy: true }); | 61 | const { copied, copy } = useClipboard({ legacy: true }); |
62 | const handleCopy = async () => { | 62 | const handleCopy = async () => { |
@@ -81,7 +81,7 @@ | @@ -81,7 +81,7 @@ | ||
81 | jsonValue.value = null; | 81 | jsonValue.value = null; |
82 | }; | 82 | }; |
83 | 83 | ||
84 | - const handleSwitchTsl = async (functionType: FunctionType) => { | 84 | + const handleSwitchTsl = async (functionType: FunctionTypeEnum) => { |
85 | try { | 85 | try { |
86 | loading.value = true; | 86 | loading.value = true; |
87 | const record = await getModelTsl({ | 87 | const record = await getModelTsl({ |
@@ -102,8 +102,8 @@ | @@ -102,8 +102,8 @@ | ||
102 | }; | 102 | }; |
103 | 103 | ||
104 | onMounted(() => { | 104 | onMounted(() => { |
105 | - activeKey.value = FunctionType.PROPERTIES; | ||
106 | - handleSwitchTsl(FunctionType.PROPERTIES); | 105 | + activeKey.value = FunctionTypeEnum.PROPERTIES; |
106 | + handleSwitchTsl(FunctionTypeEnum.PROPERTIES); | ||
107 | }); | 107 | }); |
108 | 108 | ||
109 | defineExpose({ | 109 | defineExpose({ |
@@ -33,17 +33,6 @@ export enum FormField { | @@ -33,17 +33,6 @@ export enum FormField { | ||
33 | HAS_STRUCT_FROM = 'hasStructForm', | 33 | HAS_STRUCT_FROM = 'hasStructForm', |
34 | } | 34 | } |
35 | 35 | ||
36 | -export enum FunctionType { | ||
37 | - PROPERTIES = 'properties', | ||
38 | - EVENTS = 'events', | ||
39 | - SERVICE = 'services', | ||
40 | -} | ||
41 | - | ||
42 | -export enum AssessMode { | ||
43 | - READ = 'r', | ||
44 | - WRITE = 'w', | ||
45 | -} | ||
46 | - | ||
47 | const isNumber = (type: string) => { | 36 | const isNumber = (type: string) => { |
48 | return type === DataTypeEnum.NUMBER_INT || type === DataTypeEnum.NUMBER_DOUBLE; | 37 | return type === DataTypeEnum.NUMBER_INT || type === DataTypeEnum.NUMBER_DOUBLE; |
49 | }; | 38 | }; |
@@ -27,7 +27,7 @@ import { DeviceModelOfMatterAttrs, DeviceProfileModel } from '/@/api/device/mode | @@ -27,7 +27,7 @@ import { DeviceModelOfMatterAttrs, DeviceProfileModel } from '/@/api/device/mode | ||
27 | import TriggerDurationInput from './TriggerDurationInput.vue'; | 27 | import TriggerDurationInput from './TriggerDurationInput.vue'; |
28 | import { DataTypeEnum } from '/@/enums/objectModelEnum'; | 28 | import { DataTypeEnum } from '/@/enums/objectModelEnum'; |
29 | import { getModelTsl } from '/@/api/device/modelOfMatter'; | 29 | import { getModelTsl } from '/@/api/device/modelOfMatter'; |
30 | -import { FunctionType } from '/@/views/device/profiles/step/cpns/physical/cpns/config'; | 30 | +import { FunctionTypeEnum } from '/@/enums/objectModelEnum'; |
31 | import { GetModelTslParams } from '/@/api/device/model/modelOfMatterModel'; | 31 | import { GetModelTslParams } from '/@/api/device/model/modelOfMatterModel'; |
32 | import { FlipFlopComponentTypeEnum } from './types'; | 32 | import { FlipFlopComponentTypeEnum } from './types'; |
33 | import { OptionsType } from 'ant-design-vue/es/vc-select/interface'; | 33 | import { OptionsType } from 'ant-design-vue/es/vc-select/interface'; |
@@ -405,7 +405,7 @@ export const getFormSchemas = ( | @@ -405,7 +405,7 @@ export const getFormSchemas = ( | ||
405 | labelField: 'functionName', | 405 | labelField: 'functionName', |
406 | valueField: 'identifier', | 406 | valueField: 'identifier', |
407 | params: { | 407 | params: { |
408 | - functionType: FunctionType.EVENTS, | 408 | + functionType: FunctionTypeEnum.EVENTS, |
409 | deviceProfileId: formModel[FormFieldEnum.DEVICE_PROFILE_ID], | 409 | deviceProfileId: formModel[FormFieldEnum.DEVICE_PROFILE_ID], |
410 | }, | 410 | }, |
411 | placeholder: `请选择${FormFieldNameEnum.DEVICE_EVENT_TRIGGER_KEY}`, | 411 | placeholder: `请选择${FormFieldNameEnum.DEVICE_EVENT_TRIGGER_KEY}`, |
@@ -37,5 +37,15 @@ | @@ -37,5 +37,15 @@ | ||
37 | </script> | 37 | </script> |
38 | 38 | ||
39 | <template> | 39 | <template> |
40 | - <BasicForm @register="register" /> | 40 | + <BasicForm @register="register" class="data-board-source-form" /> |
41 | </template> | 41 | </template> |
42 | + | ||
43 | +<style lang="less" scoped> | ||
44 | + .data-board-source-form { | ||
45 | + :deep(.ant-form-item-control-input-content) { | ||
46 | + > div > div { | ||
47 | + width: 100%; | ||
48 | + } | ||
49 | + } | ||
50 | + } | ||
51 | +</style> |
@@ -197,8 +197,7 @@ | @@ -197,8 +197,7 @@ | ||
197 | <label class="w-24 text-right pr-2">数据源{{ index + 1 }}</label> | 197 | <label class="w-24 text-right pr-2">数据源{{ index + 1 }}</label> |
198 | <component | 198 | <component |
199 | :ref="(event) => setDataSourceFormsEl(item.uuid, event, index)" | 199 | :ref="(event) => setDataSourceFormsEl(item.uuid, event, index)" |
200 | - class="flex-1 bg-light-50 dark:bg-dark-400" | ||
201 | - style="max-width: calc(100% - 216px)" | 200 | + class="flex-1 bg-light-50 dark:bg-dark-400 data-board-source-form" |
202 | :is="getComponent" | 201 | :is="getComponent" |
203 | :component-config="componentConfig" | 202 | :component-config="componentConfig" |
204 | :values="item" | 203 | :values="item" |
@@ -238,9 +237,11 @@ | @@ -238,9 +237,11 @@ | ||
238 | </template> | 237 | </template> |
239 | 238 | ||
240 | <style scoped lang="less"> | 239 | <style scoped lang="less"> |
241 | - :deep(#deviceId) { | ||
242 | - div { | ||
243 | - width: 100%; | 240 | + .data-board-source-form { |
241 | + :deep(.ant-form-item-control-input-content) { | ||
242 | + > div > div { | ||
243 | + width: 100%; | ||
244 | + } | ||
244 | } | 245 | } |
245 | } | 246 | } |
246 | </style> | 247 | </style> |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | import { computed } from 'vue'; | 2 | import { computed } from 'vue'; |
3 | - import { PackagesCategoryEnum } from '../../../packages/index.type'; | ||
4 | import { SelectedWidgetKeys } from '../../index.type'; | 3 | import { SelectedWidgetKeys } from '../../index.type'; |
5 | import { Alert } from 'ant-design-vue'; | 4 | import { Alert } from 'ant-design-vue'; |
6 | 5 | ||
@@ -9,10 +8,10 @@ | @@ -9,10 +8,10 @@ | ||
9 | }>(); | 8 | }>(); |
10 | 9 | ||
11 | const alert = { | 10 | const alert = { |
12 | - [PackagesCategoryEnum.MAP]: [ | ||
13 | - '1、绑定数据源为结构体时,可以自行选择结构体里的属性作为经纬度', | ||
14 | - '2、绑定数据源为非结构体时,第一数据源为经度,第二数据源为纬度,且数据源为同一设备,并同时上报。否则地图组件不能正常显示。', | ||
15 | - ], | 11 | + // [PackagesCategoryEnum.MAP]: [ |
12 | + // '1、绑定数据源为结构体时,可以自行选择结构体里的属性作为经纬度', | ||
13 | + // '2、绑定数据源为非结构体时,第一数据源为经度,第二数据源为纬度,且数据源为同一设备,并同时上报。否则地图组件不能正常显示。', | ||
14 | + // ], | ||
16 | }; | 15 | }; |
17 | 16 | ||
18 | const getMessage = computed(() => { | 17 | const getMessage = computed(() => { |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | - import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | 2 | + import { ComponentMode, ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; |
3 | import { option } from './config'; | 3 | import { option } from './config'; |
4 | import { Spin } from 'ant-design-vue'; | 4 | import { Spin } from 'ant-design-vue'; |
5 | import { computed, ref, unref } from 'vue'; | 5 | import { computed, ref, unref } from 'vue'; |
6 | import { useComponentScale } from '../../../hook/useComponentScale'; | 6 | import { useComponentScale } from '../../../hook/useComponentScale'; |
7 | - import { useSendCommand } from '../../../hook/useSendCommand'; | ||
8 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; | 7 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; |
9 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 8 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
10 | import { useDataFetch } from '../../../hook/socket/useSocket'; | 9 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
11 | - import { getSendValues } from '../config'; | ||
12 | import { useModal } from '/@/components/Modal'; | 10 | import { useModal } from '/@/components/Modal'; |
13 | import PasswordModal from '../component/PasswordModal.vue'; | 11 | import PasswordModal from '../component/PasswordModal.vue'; |
12 | + import { useCommandDelivery } from '../../../hook/useCommandDelivery'; | ||
13 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
14 | 14 | ||
15 | const props = defineProps<{ | 15 | const props = defineProps<{ |
16 | config: ComponentPropsConfigType<typeof option>; | 16 | config: ComponentPropsConfigType<typeof option>; |
@@ -20,48 +20,31 @@ | @@ -20,48 +20,31 @@ | ||
20 | 20 | ||
21 | const currentValue = ref(false); | 21 | const currentValue = ref(false); |
22 | 22 | ||
23 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
24 | + | ||
23 | const getDesign = computed(() => { | 25 | const getDesign = computed(() => { |
24 | const { option, persetOption } = props.config; | 26 | const { option, persetOption } = props.config; |
25 | - const { | ||
26 | - attribute, | ||
27 | - attributeRename, | ||
28 | - attributeName, | ||
29 | - componentInfo, | ||
30 | - commandType, | ||
31 | - extensionDesc, | ||
32 | - codeType, | ||
33 | - deviceCode, | ||
34 | - customCommand, | ||
35 | - } = option; | 27 | + const { attribute, attributeRename, componentInfo, commandType, deviceProfileId } = option; |
36 | 28 | ||
37 | const { fontSize: persetFontSize, password: persetPassword } = persetOption || {}; | 29 | const { fontSize: persetFontSize, password: persetPassword } = persetOption || {}; |
38 | const { fontSize, password } = componentInfo || {}; | 30 | const { fontSize, password } = componentInfo || {}; |
31 | + | ||
32 | + const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
39 | return { | 33 | return { |
40 | - attribute: attributeRename || attributeName || attribute, | 34 | + attribute: attributeRename || tsl?.functionName || attribute, |
41 | fontSize: fontSize || persetFontSize || 14, | 35 | fontSize: fontSize || persetFontSize || 14, |
42 | password: password || persetPassword, | 36 | password: password || persetPassword, |
43 | - extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, | ||
44 | commandType, | 37 | commandType, |
45 | - codeType, | ||
46 | - deviceCode, | ||
47 | - customCommand, | ||
48 | }; | 38 | }; |
49 | }); | 39 | }); |
50 | 40 | ||
51 | - const { sendCommand, loading } = useSendCommand(); | 41 | + const { doCommandDeliver, loading } = useCommandDelivery(); |
52 | 42 | ||
53 | - const handleSendCommand = async (data) => { | ||
54 | - const { control: event } = data || {}; | ||
55 | - const target = event.target as HTMLInputElement; | ||
56 | - const value = !target.checked; | 43 | + const handleSendCommand = async () => { |
44 | + if (props.config.option.mode === ComponentMode.SELECT_PREVIEW) return; | ||
57 | const { option } = props.config || {}; | 45 | const { option } = props.config || {}; |
58 | - | ||
59 | - const { values, isModbusCommand, sendValue } = | ||
60 | - (await getSendValues(option, unref(getDesign), value)) || {}; | ||
61 | - | ||
62 | - const flag = await sendCommand(values, isModbusCommand ? sendValue : value, isModbusCommand); | ||
63 | - if (flag) currentValue.value = value; | ||
64 | - flag ? (currentValue.value = value) : (target.checked = !value); | 46 | + const result = await doCommandDeliver(option, Number(!unref(currentValue))); |
47 | + currentValue.value = result ? !unref(currentValue) : unref(currentValue); | ||
65 | }; | 48 | }; |
66 | 49 | ||
67 | const handleChange = async (event: Event) => { | 50 | const handleChange = async (event: Event) => { |
@@ -74,16 +57,7 @@ | @@ -74,16 +57,7 @@ | ||
74 | return; | 57 | return; |
75 | } | 58 | } |
76 | 59 | ||
77 | - const target = event.target as HTMLInputElement; | ||
78 | - const value = target.checked; | ||
79 | - const { option } = props.config || {}; | ||
80 | - | ||
81 | - const { values, isModbusCommand, sendValue } = | ||
82 | - (await getSendValues(option, unref(getDesign), value)) || {}; | ||
83 | - | ||
84 | - const flag = await sendCommand(values, isModbusCommand ? sendValue : value, isModbusCommand); | ||
85 | - if (flag) currentValue.value = value; | ||
86 | - flag ? (currentValue.value = value) : (target.checked = !value); | 60 | + handleSendCommand(); |
87 | }; | 61 | }; |
88 | 62 | ||
89 | const updateFn: DataFetchUpdateFn = (message, attribute) => { | 63 | const updateFn: DataFetchUpdateFn = (message, attribute) => { |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | - import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | 2 | + import { ComponentMode, ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; |
3 | import { option } from './config'; | 3 | import { option } from './config'; |
4 | import { SvgIcon } from '/@/components/Icon'; | 4 | import { SvgIcon } from '/@/components/Icon'; |
5 | import { Switch } from 'ant-design-vue'; | 5 | import { Switch } from 'ant-design-vue'; |
6 | import { computed, ref } from 'vue'; | 6 | import { computed, ref } from 'vue'; |
7 | import { useComponentScale } from '../../../hook/useComponentScale'; | 7 | import { useComponentScale } from '../../../hook/useComponentScale'; |
8 | - import { useSendCommand } from '../../../hook/useSendCommand'; | ||
9 | import { unref } from 'vue'; | 8 | import { unref } from 'vue'; |
10 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; | 9 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; |
11 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 10 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
12 | import { useDataFetch } from '../../../hook/socket/useSocket'; | 11 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
13 | - import { getSendValues } from '../config'; | ||
14 | import { useModal } from '/@/components/Modal'; | 12 | import { useModal } from '/@/components/Modal'; |
15 | import PasswordModal from '../component/PasswordModal.vue'; | 13 | import PasswordModal from '../component/PasswordModal.vue'; |
14 | + import { useCommandDelivery } from '../../../hook/useCommandDelivery'; | ||
15 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
16 | 16 | ||
17 | const props = defineProps<{ | 17 | const props = defineProps<{ |
18 | config: ComponentPropsConfigType<typeof option>; | 18 | config: ComponentPropsConfigType<typeof option>; |
@@ -20,19 +20,11 @@ | @@ -20,19 +20,11 @@ | ||
20 | 20 | ||
21 | const checked = ref(false); | 21 | const checked = ref(false); |
22 | 22 | ||
23 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
24 | + | ||
23 | const getDesign = computed(() => { | 25 | const getDesign = computed(() => { |
24 | const { option, persetOption } = props.config; | 26 | const { option, persetOption } = props.config; |
25 | - const { | ||
26 | - componentInfo, | ||
27 | - attribute, | ||
28 | - attributeRename, | ||
29 | - attributeName, | ||
30 | - commandType, | ||
31 | - extensionDesc, | ||
32 | - codeType, | ||
33 | - deviceCode, | ||
34 | - customCommand, | ||
35 | - } = option; | 27 | + const { componentInfo, attribute, deviceProfileId, attributeRename, commandType } = option; |
36 | const { | 28 | const { |
37 | icon: presetIcon, | 29 | icon: presetIcon, |
38 | iconColor: presetIconColor, | 30 | iconColor: presetIconColor, |
@@ -41,21 +33,18 @@ | @@ -41,21 +33,18 @@ | ||
41 | } = persetOption || {}; | 33 | } = persetOption || {}; |
42 | const { icon, iconColor, fontSize, password } = componentInfo || {}; | 34 | const { icon, iconColor, fontSize, password } = componentInfo || {}; |
43 | 35 | ||
36 | + const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
44 | return { | 37 | return { |
45 | icon: icon ?? presetIcon, | 38 | icon: icon ?? presetIcon, |
46 | iconColor: iconColor || presetIconColor, | 39 | iconColor: iconColor || presetIconColor, |
47 | - attribute: attributeRename || attributeName || attribute, | ||
48 | - extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, | 40 | + attribute: attributeRename || tsl?.functionName || attribute, |
49 | fontSize: fontSize || persetFontSize || 14, | 41 | fontSize: fontSize || persetFontSize || 14, |
50 | password: password || persetPassword, | 42 | password: password || persetPassword, |
51 | commandType, | 43 | commandType, |
52 | - codeType, | ||
53 | - deviceCode, | ||
54 | - customCommand, | ||
55 | }; | 44 | }; |
56 | }); | 45 | }); |
57 | 46 | ||
58 | - const { sendCommand, loading } = useSendCommand(); | 47 | + const { loading, doCommandDeliver } = useCommandDelivery(); |
59 | 48 | ||
60 | const handleChange = async () => { | 49 | const handleChange = async () => { |
61 | if (unref(getDesign).password) { | 50 | if (unref(getDesign).password) { |
@@ -63,32 +52,14 @@ | @@ -63,32 +52,14 @@ | ||
63 | checked.value = !unref(checked); | 52 | checked.value = !unref(checked); |
64 | return; | 53 | return; |
65 | } | 54 | } |
66 | - const { option } = props.config || {}; | ||
67 | - | ||
68 | - const { values, isModbusCommand, sendValue } = | ||
69 | - (await getSendValues(option, unref(getDesign), unref(checked))) || {}; | ||
70 | - | ||
71 | - const flag = await sendCommand( | ||
72 | - values, | ||
73 | - isModbusCommand ? sendValue : unref(checked), | ||
74 | - isModbusCommand | ||
75 | - ); | ||
76 | - if (!flag) checked.value = !unref(checked); | 55 | + handleSendCommand(); |
77 | }; | 56 | }; |
78 | 57 | ||
79 | const handleSendCommand = async () => { | 58 | const handleSendCommand = async () => { |
59 | + if (props.config.option.mode === ComponentMode.SELECT_PREVIEW) return; | ||
80 | const { option } = props.config || {}; | 60 | const { option } = props.config || {}; |
81 | - checked.value = !unref(checked); | ||
82 | - | ||
83 | - const { values, isModbusCommand, sendValue } = | ||
84 | - (await getSendValues(option, unref(getDesign), unref(checked))) || {}; | ||
85 | - | ||
86 | - const flag = await sendCommand( | ||
87 | - values, | ||
88 | - isModbusCommand ? sendValue : unref(checked), | ||
89 | - isModbusCommand | ||
90 | - ); | ||
91 | - if (!flag) checked.value = !unref(checked); | 61 | + const result = await doCommandDeliver(option, Number(unref(checked))); |
62 | + if (!result) checked.value = !unref(checked); | ||
92 | }; | 63 | }; |
93 | 64 | ||
94 | const updateFn: DataFetchUpdateFn = (message, attribute) => { | 65 | const updateFn: DataFetchUpdateFn = (message, attribute) => { |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | - import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | 2 | + import { ComponentMode, ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; |
3 | import { option } from './config'; | 3 | import { option } from './config'; |
4 | import { Spin } from 'ant-design-vue'; | 4 | import { Spin } from 'ant-design-vue'; |
5 | import { computed, ref, unref } from 'vue'; | 5 | import { computed, ref, unref } from 'vue'; |
6 | import { useComponentScale } from '../../../hook/useComponentScale'; | 6 | import { useComponentScale } from '../../../hook/useComponentScale'; |
7 | - import { useSendCommand } from '../../../hook/useSendCommand'; | ||
8 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; | 7 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; |
9 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 8 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
10 | import { useDataFetch } from '../../../hook/socket/useSocket'; | 9 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
11 | - import { getSendValues } from '../config'; | ||
12 | import PasswordModal from '../component/PasswordModal.vue'; | 10 | import PasswordModal from '../component/PasswordModal.vue'; |
13 | import { useModal } from '/@/components/Modal'; | 11 | import { useModal } from '/@/components/Modal'; |
12 | + import { useCommandDelivery } from '../../../hook/useCommandDelivery'; | ||
13 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
14 | 14 | ||
15 | const props = defineProps<{ | 15 | const props = defineProps<{ |
16 | config: ComponentPropsConfigType<typeof option>; | 16 | config: ComponentPropsConfigType<typeof option>; |
@@ -20,34 +20,31 @@ | @@ -20,34 +20,31 @@ | ||
20 | 20 | ||
21 | const currentValue = ref(false); | 21 | const currentValue = ref(false); |
22 | 22 | ||
23 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
24 | + | ||
23 | const getDesign = computed(() => { | 25 | const getDesign = computed(() => { |
24 | const { option, persetOption } = props.config; | 26 | const { option, persetOption } = props.config; |
25 | - const { | ||
26 | - attribute, | ||
27 | - attributeRename, | ||
28 | - attributeName, | ||
29 | - commandType, | ||
30 | - extensionDesc, | ||
31 | - codeType, | ||
32 | - deviceCode, | ||
33 | - customCommand, | ||
34 | - componentInfo, | ||
35 | - } = option; | 27 | + const { attribute, deviceProfileId, attributeRename, commandType, componentInfo } = option; |
36 | const { fontSize: persetFontSize, password: persetPassword } = persetOption || {}; | 28 | const { fontSize: persetFontSize, password: persetPassword } = persetOption || {}; |
37 | const { fontSize, password } = componentInfo || {}; | 29 | const { fontSize, password } = componentInfo || {}; |
30 | + | ||
31 | + const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
32 | + | ||
38 | return { | 33 | return { |
39 | - attribute: attributeRename || attributeName || attribute, | ||
40 | - extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, | 34 | + attribute: attributeRename || tsl?.functionName || attribute, |
41 | password: password || persetPassword, | 35 | password: password || persetPassword, |
42 | commandType, | 36 | commandType, |
43 | - codeType, | ||
44 | - deviceCode, | ||
45 | - customCommand, | ||
46 | fontSize: fontSize || persetFontSize || 14, | 37 | fontSize: fontSize || persetFontSize || 14, |
47 | }; | 38 | }; |
48 | }); | 39 | }); |
40 | + const { doCommandDeliver, loading } = useCommandDelivery(); | ||
49 | 41 | ||
50 | - const { loading, sendCommand } = useSendCommand(); | 42 | + const handleSendCommand = async () => { |
43 | + if (props.config.option.mode === ComponentMode.SELECT_PREVIEW) return; | ||
44 | + const { option } = props.config || {}; | ||
45 | + const result = await doCommandDeliver(option, Number(!unref(currentValue))); | ||
46 | + currentValue.value = result ? !unref(currentValue) : unref(currentValue); | ||
47 | + }; | ||
51 | const handleChange = async (event: Event) => { | 48 | const handleChange = async (event: Event) => { |
52 | if (unref(getDesign).password) { | 49 | if (unref(getDesign).password) { |
53 | const target = event.target as HTMLInputElement; | 50 | const target = event.target as HTMLInputElement; |
@@ -57,29 +54,7 @@ | @@ -57,29 +54,7 @@ | ||
57 | openModal(true, { password: unref(getDesign).password, control: event }); | 54 | openModal(true, { password: unref(getDesign).password, control: event }); |
58 | return; | 55 | return; |
59 | } | 56 | } |
60 | - | ||
61 | - const target = event.target as HTMLInputElement; | ||
62 | - const value = target.checked; | ||
63 | - const { option } = props.config || {}; | ||
64 | - | ||
65 | - const { values, isModbusCommand, sendValue } = | ||
66 | - (await getSendValues(option, unref(getDesign), value)) || {}; | ||
67 | - | ||
68 | - const flag = await sendCommand(values, isModbusCommand ? sendValue : value, isModbusCommand); | ||
69 | - flag ? (currentValue.value = value) : (target.checked = !value); | ||
70 | - }; | ||
71 | - | ||
72 | - const handleSendCommand = async (data) => { | ||
73 | - const { control: event } = data || {}; | ||
74 | - const target = event.target as HTMLInputElement; | ||
75 | - const value = !target.checked; | ||
76 | - const { option } = props.config || {}; | ||
77 | - | ||
78 | - const { values, isModbusCommand, sendValue } = | ||
79 | - (await getSendValues(option, unref(getDesign), value)) || {}; | ||
80 | - | ||
81 | - const flag = await sendCommand(values, isModbusCommand ? sendValue : value, isModbusCommand); | ||
82 | - flag ? (currentValue.value = value) : (target.checked = !value); | 57 | + handleSendCommand(); |
83 | }; | 58 | }; |
84 | 59 | ||
85 | const updateFn: DataFetchUpdateFn = (message, attribute) => { | 60 | const updateFn: DataFetchUpdateFn = (message, attribute) => { |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | - import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | 2 | + import { ComponentMode, ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; |
3 | import { option } from './config'; | 3 | import { option } from './config'; |
4 | import { Slider, Spin } from 'ant-design-vue'; | 4 | import { Slider, Spin } from 'ant-design-vue'; |
5 | import { computed, ref, unref } from 'vue'; | 5 | import { computed, ref, unref } from 'vue'; |
6 | import { useComponentScale } from '../../../hook/useComponentScale'; | 6 | import { useComponentScale } from '../../../hook/useComponentScale'; |
7 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; | 7 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; |
8 | - import { useSendCommand } from '../../../hook/useSendCommand'; | ||
9 | import { useReceiveValue } from '../../../hook/useReceiveValue'; | 8 | import { useReceiveValue } from '../../../hook/useReceiveValue'; |
10 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 9 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
11 | import { useDataFetch } from '../../../hook/socket/useSocket'; | 10 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
12 | - import { TaskTypeEnum } from '/@/views/task/center/config'; | ||
13 | - import { useMessage } from '/@/hooks/web/useMessage'; | ||
14 | - import { SingleToHex } from '/@/views/device/list/cpns/tabs/ObjectModelCommandDeliveryModal/config'; | ||
15 | - import { genModbusCommand } from '/@/api/task'; | ||
16 | import PasswordModal from '../component/PasswordModal.vue'; | 11 | import PasswordModal from '../component/PasswordModal.vue'; |
17 | import { useModal } from '/@/components/Modal'; | 12 | import { useModal } from '/@/components/Modal'; |
13 | + import { useCommandDelivery } from '../../../hook/useCommandDelivery'; | ||
14 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
18 | 15 | ||
19 | const props = defineProps<{ | 16 | const props = defineProps<{ |
20 | config: ComponentPropsConfigType<typeof option>; | 17 | config: ComponentPropsConfigType<typeof option>; |
21 | }>(); | 18 | }>(); |
22 | 19 | ||
23 | const sliderValue = ref<number>(33); | 20 | const sliderValue = ref<number>(33); |
24 | - const oldSliderValue = ref<number>(33); | ||
25 | - const noSendValue = ref<number>(0); | ||
26 | - const sliderEl = ref<Nullable<InstanceType<typeof Slider>>>(null); | 21 | + const sliderElRef = ref<InstanceType<typeof Slider>>(); |
27 | 22 | ||
28 | - const { loading, sendCommand } = useSendCommand(); | 23 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); |
29 | 24 | ||
30 | const getDesign = computed(() => { | 25 | const getDesign = computed(() => { |
31 | const { option, persetOption } = props.config; | 26 | const { option, persetOption } = props.config; |
32 | - const { | ||
33 | - componentInfo, | ||
34 | - attribute, | ||
35 | - attributeRename, | ||
36 | - attributeName, | ||
37 | - commandType, | ||
38 | - extensionDesc, | ||
39 | - codeType, | ||
40 | - deviceCode, | ||
41 | - customCommand, | ||
42 | - } = option; | 27 | + const { componentInfo, attribute, deviceProfileId, attributeRename, commandType } = option; |
28 | + | ||
43 | const { | 29 | const { |
44 | controlBarColor: persetControlBarColor, | 30 | controlBarColor: persetControlBarColor, |
45 | fonColor: persetFontColor, | 31 | fonColor: persetFontColor, |
@@ -50,6 +36,8 @@ | @@ -50,6 +36,8 @@ | ||
50 | fontSize: persetFontSize, | 36 | fontSize: persetFontSize, |
51 | password: persetPassword, | 37 | password: persetPassword, |
52 | } = persetOption || {}; | 38 | } = persetOption || {}; |
39 | + | ||
40 | + const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
53 | const { | 41 | const { |
54 | controlBarColor, | 42 | controlBarColor, |
55 | password, | 43 | password, |
@@ -61,16 +49,12 @@ | @@ -61,16 +49,12 @@ | ||
61 | fontSize, | 49 | fontSize, |
62 | } = componentInfo || {}; | 50 | } = componentInfo || {}; |
63 | return { | 51 | return { |
64 | - attribute: attributeRename || attributeName || attribute, | 52 | + attribute: attributeRename || tsl?.functionName || attribute, |
65 | controlBarColor: controlBarColor ?? persetControlBarColor, | 53 | controlBarColor: controlBarColor ?? persetControlBarColor, |
66 | fontColor: fontColor ?? persetFontColor, | 54 | fontColor: fontColor ?? persetFontColor, |
67 | minNumber: minNumber ?? persetMinNumber, | 55 | minNumber: minNumber ?? persetMinNumber, |
68 | maxNumber: maxNumber ?? persetMaxNumber, | 56 | maxNumber: maxNumber ?? persetMaxNumber, |
69 | - extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, | ||
70 | commandType, | 57 | commandType, |
71 | - codeType, | ||
72 | - deviceCode, | ||
73 | - customCommand, | ||
74 | textColor: textColor || persetTextColor, | 58 | textColor: textColor || persetTextColor, |
75 | valueSize: valueSize || persetValueSize || 20, | 59 | valueSize: valueSize || persetValueSize || 20, |
76 | fontSize: fontSize || persetFontSize || 14, | 60 | fontSize: fontSize || persetFontSize || 14, |
@@ -78,153 +62,28 @@ | @@ -78,153 +62,28 @@ | ||
78 | }; | 62 | }; |
79 | }); | 63 | }); |
80 | 64 | ||
81 | - const index = ref<number>(0); | ||
82 | - const afterValue = ref<number>(0); //点击Slider获取的值 | ||
83 | - | ||
84 | - const handleChange = async (e) => { | ||
85 | - index.value++; | ||
86 | - afterValue.value = e; | ||
87 | - if (index.value == 1) { | ||
88 | - oldSliderValue.value = unref(sliderValue); | ||
89 | - return; //这个是因为设置了最大值时,当sliderValue的值大于最大值时只会显示设置的最大值,会执行一次change | ||
90 | - } | ||
91 | - sliderValue.value = e; | ||
92 | - }; | ||
93 | - | ||
94 | - const handleAfterChange = async () => { | ||
95 | - unref(sliderEl)?.blur(); | ||
96 | - if (unref(sliderValue) == unref(afterValue)) return; | ||
97 | - if (unref(getDesign).password) return; | ||
98 | - sliderValue.value = afterValue.value; //这一步是因为当我们是点击不是拖动时候,会让值更新不了,所以需要赋值一次 | ||
99 | - }; | ||
100 | - | ||
101 | - const { createMessage } = useMessage(); | ||
102 | - | ||
103 | - // 获取小数 | ||
104 | - const getFloatPart = (number: string | number) => { | ||
105 | - const isLessZero = Number(number) < 0; | ||
106 | - number = number.toString(); | ||
107 | - const floatPartStartIndex = number.indexOf('.'); | ||
108 | - const value = ~floatPartStartIndex | ||
109 | - ? `${isLessZero ? '-' : ''}0.${number.substring(floatPartStartIndex + 1)}` | ||
110 | - : '0'; | ||
111 | - return Number(value); | 65 | + const sendValue = ref(0); |
66 | + const handleChange = async (value: number) => { | ||
67 | + sendValue.value = value; | ||
112 | }; | 68 | }; |
113 | 69 | ||
114 | - const getArray = (values) => { | ||
115 | - const str = values.replace(/\s+/g, ''); | ||
116 | - const array: any = []; | 70 | + const { loading, doCommandDeliver } = useCommandDelivery(); |
117 | 71 | ||
118 | - for (let i = 0; i < str.length; i += 4) { | ||
119 | - const chunk = parseInt(str.substring(i, i + 4), 16); | ||
120 | - array.push(chunk); | ||
121 | - } | ||
122 | - return array; | ||
123 | - }; | ||
124 | - | ||
125 | - const getSendValue = async (value: number) => { | ||
126 | - const { extensionDesc, codeType, deviceCode, customCommand } = unref(getDesign) || {}; | ||
127 | - const { transportType } = customCommand || {}; | ||
128 | - const { registerAddress, actionType, zoomFactor } = extensionDesc || {}; | ||
129 | - const newZoomValue = zoomFactor ? Number(zoomFactor) : 1; | ||
130 | - if (transportType == 'TCP' && codeType == TaskTypeEnum.MODBUS_RTU) { | ||
131 | - if (!deviceCode) { | ||
132 | - createMessage.warning('当前设备没有设置地址码'); | ||
133 | - return; | ||
134 | - } | ||
135 | - const modbusForm = ref({ | ||
136 | - crc: 'CRC_16_LOWER', | ||
137 | - deviceCode: deviceCode, | ||
138 | - method: actionType == '16' ? '10' : actionType, | ||
139 | - registerAddress, | ||
140 | - registerNumber: 1, | ||
141 | - registerValues: [value], | ||
142 | - }) as any; | ||
143 | - if (!actionType) { | ||
144 | - createMessage.warning('当前物模型扩展描述没有填写'); | ||
145 | - return; | ||
146 | - } | ||
147 | - if (actionType == '06') { | ||
148 | - const newValue = Math.trunc(value) * newZoomValue + getFloatPart(value) * newZoomValue; | ||
149 | - if (newValue % 1 != 0) { | ||
150 | - createMessage.warning(`值必须是整数,缩放因子为${unref(newZoomValue)}`); | ||
151 | - return; | ||
152 | - } | ||
153 | - | ||
154 | - if (newValue > 65535) { | ||
155 | - createMessage.warning(`值不能超过65535,缩放因子是${unref(newZoomValue)}`); | ||
156 | - return; | ||
157 | - } | ||
158 | - modbusForm.value.registerValues = [newValue]; | ||
159 | - } | ||
160 | - if (actionType == '05') { | ||
161 | - if (Number(value) != 0 || Number(value) != 1) { | ||
162 | - createMessage.warning(`当前物模型仅支持值为0和1`); | ||
163 | - return; | ||
164 | - } | ||
165 | - } | ||
166 | - if (actionType == '16' || actionType == '10') { | ||
167 | - const regex = /^-?\d+(\.\d{0,2})?$/; | ||
168 | - const values = | ||
169 | - Math.trunc(value) * unref(newZoomValue) + getFloatPart(value) * unref(newZoomValue); | ||
170 | - if (!regex.test(values as any)) { | ||
171 | - createMessage.warning(`值精确到两位小数,缩放因子是${unref(newZoomValue)}`); | ||
172 | - return; | ||
173 | - } | ||
174 | - const newValue = values == 0 ? [0, 0] : getArray(SingleToHex(values)); | ||
175 | - modbusForm.value.registerValues = newValue; | ||
176 | - modbusForm.value.registerNumber = 2; | ||
177 | - modbusForm.value.method = '10'; | ||
178 | - } | ||
179 | - const sendValue = await genModbusCommand(unref(modbusForm)); | ||
180 | - return sendValue; | ||
181 | - } | ||
182 | - }; | ||
183 | - | ||
184 | - const handleBlur = async () => { | 72 | + const handleAfterChange = () => { |
185 | if (unref(getDesign).password) { | 73 | if (unref(getDesign).password) { |
186 | - sliderValue.value = oldSliderValue.value; | ||
187 | - openModal(true, { password: unref(getDesign).password, value: afterValue.value }); | 74 | + openModal(true, { password: unref(getDesign).password }); |
188 | return; | 75 | return; |
189 | } | 76 | } |
190 | - | ||
191 | - if (unref(oldSliderValue) !== unref(sliderValue)) { | ||
192 | - const { codeType, customCommand } = unref(getDesign) || {}; | ||
193 | - const { transportType } = customCommand || {}; | ||
194 | - const sendValue = ref<any>(unref(sliderValue)); | ||
195 | - const isModbusCommand = ref<boolean>(false); | ||
196 | - if (transportType == 'TCP' && codeType == TaskTypeEnum.MODBUS_RTU) { | ||
197 | - sendValue.value = await getSendValue(unref(sliderValue)); | ||
198 | - isModbusCommand.value = true; | ||
199 | - } | ||
200 | - const flag = await sendCommand(props.config.option, unref(sendValue), unref(isModbusCommand)); | ||
201 | - flag | ||
202 | - ? ((sliderValue.value = unref(sliderValue)), | ||
203 | - (oldSliderValue.value = sliderValue.value), | ||
204 | - (index.value = 0)) | ||
205 | - : (sliderValue.value = unref(oldSliderValue)); | ||
206 | - } | 77 | + handleSendCommand(); |
207 | }; | 78 | }; |
208 | 79 | ||
209 | - const handleSendCommand = async (data) => { | ||
210 | - const { value } = data || {}; | ||
211 | - sliderValue.value = value; | ||
212 | - if (unref(oldSliderValue) !== unref(sliderValue)) { | ||
213 | - const { codeType, customCommand } = unref(getDesign) || {}; | ||
214 | - const { transportType } = customCommand || {}; | ||
215 | - const sendValue = ref<any>(unref(sliderValue)); | ||
216 | - const isModbusCommand = ref<boolean>(false); | ||
217 | - if (transportType == 'TCP' && codeType == TaskTypeEnum.MODBUS_RTU) { | ||
218 | - sendValue.value = await getSendValue(unref(sliderValue)); | ||
219 | - isModbusCommand.value = true; | ||
220 | - } | ||
221 | - const flag = await sendCommand(props.config.option, unref(sendValue), unref(isModbusCommand)); | ||
222 | - flag | ||
223 | - ? ((sliderValue.value = unref(sliderValue)), | ||
224 | - (oldSliderValue.value = sliderValue.value), | ||
225 | - (index.value = 0)) | ||
226 | - : (sliderValue.value = unref(oldSliderValue)); | ||
227 | - } | 80 | + const handleSendCommand = async () => { |
81 | + if (props.config.option.mode === ComponentMode.SELECT_PREVIEW) return; | ||
82 | + const value = unref(sendValue); | ||
83 | + const { option } = props.config || {}; | ||
84 | + const result = await doCommandDeliver(option, value); | ||
85 | + unref(sliderElRef)?.blur(); | ||
86 | + sliderValue.value = result ? value : unref(sliderValue); | ||
228 | }; | 87 | }; |
229 | 88 | ||
230 | const { getNumberValue } = useReceiveValue(); | 89 | const { getNumberValue } = useReceiveValue(); |
@@ -233,7 +92,6 @@ | @@ -233,7 +92,6 @@ | ||
233 | const [latest] = data[attribute] || []; | 92 | const [latest] = data[attribute] || []; |
234 | const [name, value] = latest; | 93 | const [name, value] = latest; |
235 | if (!name && !value) return; | 94 | if (!name && !value) return; |
236 | - noSendValue.value = getNumberValue(value); | ||
237 | sliderValue.value = getNumberValue(value); | 95 | sliderValue.value = getNumberValue(value); |
238 | }; | 96 | }; |
239 | 97 | ||
@@ -254,10 +112,11 @@ | @@ -254,10 +112,11 @@ | ||
254 | fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px', | 112 | fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px', |
255 | }" | 113 | }" |
256 | class="font-bold text-xl mt-3 text-center" | 114 | class="font-bold text-xl mt-3 text-center" |
257 | - >{{ sliderValue }}</span | ||
258 | > | 115 | > |
116 | + {{ sliderValue }} | ||
117 | + </span> | ||
259 | <Slider | 118 | <Slider |
260 | - ref="sliderEl" | 119 | + ref="sliderElRef" |
261 | :style="{ | 120 | :style="{ |
262 | '--slider-color': getDesign.controlBarColor, | 121 | '--slider-color': getDesign.controlBarColor, |
263 | '--slider-handle': (getRatio ? getRatio * 14 : 14) + 'px', | 122 | '--slider-handle': (getRatio ? getRatio * 14 : 14) + 'px', |
@@ -270,7 +129,6 @@ | @@ -270,7 +129,6 @@ | ||
270 | :max="getDesign.maxNumber" | 129 | :max="getDesign.maxNumber" |
271 | @change="handleChange" | 130 | @change="handleChange" |
272 | @afterChange="handleAfterChange" | 131 | @afterChange="handleAfterChange" |
273 | - @blur="handleBlur" | ||
274 | /> | 132 | /> |
275 | 133 | ||
276 | <span | 134 | <span |
@@ -8,6 +8,47 @@ import { | @@ -8,6 +8,47 @@ import { | ||
8 | } from '/@/views/visual/packages/index.type'; | 8 | } from '/@/views/visual/packages/index.type'; |
9 | import { PublicConfigClass, componentInitConfig } from '/@/views/visual/packages/publicConfig'; | 9 | import { PublicConfigClass, componentInitConfig } from '/@/views/visual/packages/publicConfig'; |
10 | import { ComponentConfigFieldEnum } from '../../../enum'; | 10 | import { ComponentConfigFieldEnum } from '../../../enum'; |
11 | +import { buildUUID } from '/@/utils/uuid'; | ||
12 | + | ||
13 | +export interface SwitchItemType extends Recordable { | ||
14 | + id: string; | ||
15 | + checked: boolean; | ||
16 | + deviceId?: string; | ||
17 | + deviceProfileId?: string; | ||
18 | + attribute?: string; | ||
19 | + deviceName?: string; | ||
20 | + attributeName?: string; | ||
21 | + openCommand?: string; | ||
22 | + closeCommand?: string; | ||
23 | + openService?: string; | ||
24 | + closeService?: string; | ||
25 | +} | ||
26 | + | ||
27 | +export const DEFAULT_VALUE: SwitchItemType[] = [ | ||
28 | + { | ||
29 | + deviceName: '光照设备', | ||
30 | + attributeName: '光照', | ||
31 | + icon: 'zongfushe', | ||
32 | + unit: 'kw', | ||
33 | + iconColor: '#367BFF', | ||
34 | + fontColor: '#357CFB', | ||
35 | + checked: false, | ||
36 | + fontSize: 16, | ||
37 | + id: buildUUID(), | ||
38 | + }, | ||
39 | + { | ||
40 | + value: 53.7, | ||
41 | + deviceName: '风机设备', | ||
42 | + attributeName: '风机', | ||
43 | + icon: 'guangzhaoqiangdu', | ||
44 | + unit: '℃', | ||
45 | + iconColor: '#FFA000', | ||
46 | + fontColor: '#FFA000', | ||
47 | + checked: true, | ||
48 | + fontSize: 16, | ||
49 | + id: buildUUID(), | ||
50 | + }, | ||
51 | +]; | ||
11 | 52 | ||
12 | export const option: PublicPresetOptions = { | 53 | export const option: PublicPresetOptions = { |
13 | multipleDataSourceComponent: true, | 54 | multipleDataSourceComponent: true, |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | - import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | ||
3 | - import { option } from './config'; | 2 | + import { ComponentMode, ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; |
3 | + import { DEFAULT_VALUE, option, SwitchItemType } from './config'; | ||
4 | import { SvgIcon } from '/@/components/Icon'; | 4 | import { SvgIcon } from '/@/components/Icon'; |
5 | import { Switch } from 'ant-design-vue'; | 5 | import { Switch } from 'ant-design-vue'; |
6 | - import { computed, ref } from 'vue'; | 6 | + import { computed, ref, toRaw } from 'vue'; |
7 | import { useComponentScale } from '../../../hook/useComponentScale'; | 7 | import { useComponentScale } from '../../../hook/useComponentScale'; |
8 | - import { useSendCommand } from '../../../hook/useSendCommand'; | ||
9 | import { unref } from 'vue'; | 8 | import { unref } from 'vue'; |
10 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; | 9 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; |
11 | import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 10 | import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
12 | import { useMultipleDataFetch } from '../../../hook/socket/useSocket'; | 11 | import { useMultipleDataFetch } from '../../../hook/socket/useSocket'; |
13 | import { useReceiveMessage } from '../../../hook/useReceiveMessage'; | 12 | import { useReceiveMessage } from '../../../hook/useReceiveMessage'; |
14 | import { useReceiveValue } from '../../../hook/useReceiveValue'; | 13 | import { useReceiveValue } from '../../../hook/useReceiveValue'; |
15 | - import { DataSource } from '/@/views/visual/palette/types'; | ||
16 | - import { getSendValues, CommandTypeEnumLIst } from '../config'; | ||
17 | import { useModal } from '/@/components/Modal'; | 14 | import { useModal } from '/@/components/Modal'; |
18 | import PasswordModal from '../component/PasswordModal.vue'; | 15 | import PasswordModal from '../component/PasswordModal.vue'; |
16 | + import { | ||
17 | + DoCommandDeliverDataSourceType, | ||
18 | + useCommandDelivery, | ||
19 | + } from '../../../hook/useCommandDelivery'; | ||
20 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
19 | 21 | ||
20 | const props = defineProps<{ | 22 | const props = defineProps<{ |
21 | config: ComponentPropsConfigType<typeof option>; | 23 | config: ComponentPropsConfigType<typeof option>; |
22 | }>(); | 24 | }>(); |
23 | 25 | ||
24 | - const svgList = ref<any>([ | ||
25 | - { | ||
26 | - value: 26.2, | ||
27 | - deviceName: '光照设备', | ||
28 | - attributeName: '光照', | ||
29 | - icon: 'zongfushe', | ||
30 | - unit: 'kw', | ||
31 | - iconColor: '#367BFF', | ||
32 | - fontColor: '#357CFB', | ||
33 | - checked: false, | ||
34 | - id: 0, | ||
35 | - }, | ||
36 | - { | ||
37 | - value: 53.7, | ||
38 | - deviceName: '风机设备', | ||
39 | - attributeName: '风机', | ||
40 | - icon: 'guangzhaoqiangdu', | ||
41 | - unit: '℃', | ||
42 | - iconColor: '#FFA000', | ||
43 | - fontColor: '#FFA000', | ||
44 | - checked: true, | ||
45 | - id: 1, | ||
46 | - }, | ||
47 | - ]); | 26 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); |
48 | 27 | ||
49 | const getDesign = computed(() => { | 28 | const getDesign = computed(() => { |
50 | const { persetOption = {}, option } = props.config; | 29 | const { persetOption = {}, option } = props.config; |
@@ -64,90 +43,66 @@ | @@ -64,90 +43,66 @@ | ||
64 | const { | 43 | const { |
65 | attribute, | 44 | attribute, |
66 | attributeRename, | 45 | attributeRename, |
67 | - attributeName, | ||
68 | deviceId, | 46 | deviceId, |
69 | deviceName, | 47 | deviceName, |
70 | deviceRename, | 48 | deviceRename, |
71 | commandType, | 49 | commandType, |
72 | - extensionDesc, | ||
73 | - codeType, | ||
74 | - deviceCode, | ||
75 | - customCommand, | 50 | + deviceProfileId, |
51 | + openCommand, | ||
52 | + closeCommand, | ||
53 | + openService, | ||
54 | + closeService, | ||
76 | } = item; | 55 | } = item; |
56 | + | ||
57 | + const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
58 | + | ||
77 | return { | 59 | return { |
78 | unit: unit ?? persetUnit, | 60 | unit: unit ?? persetUnit, |
61 | + deviceProfileId, | ||
62 | + deviceId, | ||
79 | fontColor: fontColor ?? persetFontColor, | 63 | fontColor: fontColor ?? persetFontColor, |
80 | icon: icon ?? persetIcon, | 64 | icon: icon ?? persetIcon, |
81 | iconColor: iconColor ?? persetIconColor, | 65 | iconColor: iconColor ?? persetIconColor, |
82 | attribute: attribute, | 66 | attribute: attribute, |
83 | - attributeName: attributeRename || attributeName, | 67 | + attributeName: attributeRename || tsl?.functionName || attribute, |
84 | showDeviceName, | 68 | showDeviceName, |
85 | deviceName: deviceRename || deviceName, | 69 | deviceName: deviceRename || deviceName, |
86 | id: deviceId, | 70 | id: deviceId, |
87 | - extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, | ||
88 | commandType, | 71 | commandType, |
89 | - codeType, | ||
90 | - deviceCode, | ||
91 | - customCommand, | ||
92 | fontSize: fontSize || persetFontSize || 14, | 72 | fontSize: fontSize || persetFontSize || 14, |
93 | password: password || persetPassword, | 73 | password: password || persetPassword, |
94 | - }; | 74 | + checked: false, |
75 | + openCommand, | ||
76 | + closeCommand, | ||
77 | + openService, | ||
78 | + closeService, | ||
79 | + } as SwitchItemType; | ||
95 | }), | 80 | }), |
96 | }; | 81 | }; |
97 | }); | 82 | }); |
98 | 83 | ||
99 | - const { loading, sendCommand } = useSendCommand(); | ||
100 | - const handleChange = async (index: number, checked: Boolean, item: any) => { | 84 | + const handleChange = async (item) => { |
101 | if (item.password) { | 85 | if (item.password) { |
102 | - openModal(true, { password: item.password, index, checked }); | ||
103 | - controlList.value[index].checked = !checked; | 86 | + openModal(true, { password: item.password }); |
104 | return; | 87 | return; |
105 | } | 88 | } |
106 | - const { heightPx, itemHeightRatio, itemWidthRatio, mode, widthPx, dataSource } = | ||
107 | - props.config.option; | ||
108 | - const data = { | ||
109 | - ...dataSource?.[index], | ||
110 | - heightPx, | ||
111 | - itemHeightRatio, | ||
112 | - itemWidthRatio, | ||
113 | - mode, | ||
114 | - widthPx, | ||
115 | - } as DataSource; | ||
116 | - const { values, isModbusCommand, sendValue } = | ||
117 | - (await getSendValues(data, unref(getDesign).dataSource[index], checked)) || {}; | ||
118 | - | ||
119 | - const flag = await sendCommand(values, isModbusCommand ? sendValue : checked, isModbusCommand); | ||
120 | - if (!flag) controlList.value[index].checked = !checked; | 89 | + handleSendCommand(item); |
121 | }; | 90 | }; |
122 | 91 | ||
123 | const { forEachGroupMessage } = useReceiveMessage(); | 92 | const { forEachGroupMessage } = useReceiveMessage(); |
124 | const { getNumberValue } = useReceiveValue(); | 93 | const { getNumberValue } = useReceiveValue(); |
125 | 94 | ||
126 | const controlList = ref( | 95 | const controlList = ref( |
127 | - props.config.option.dataSource | ||
128 | - ? unref(getDesign).dataSource.map((item) => { | ||
129 | - return { ...item, checked: false }; | ||
130 | - }) | ||
131 | - : svgList | 96 | + props.config.option.dataSource ? unref(getDesign).dataSource : DEFAULT_VALUE |
132 | ); | 97 | ); |
133 | - const handleSendCommand = async (modalData) => { | ||
134 | - const { index, checked } = modalData || {}; | ||
135 | - const { heightPx, itemHeightRatio, itemWidthRatio, mode, widthPx, dataSource } = | ||
136 | - props.config.option; | ||
137 | - const data = { | ||
138 | - ...dataSource?.[index], | ||
139 | - heightPx, | ||
140 | - itemHeightRatio, | ||
141 | - itemWidthRatio, | ||
142 | - mode, | ||
143 | - widthPx, | ||
144 | - } as DataSource; | ||
145 | - controlList.value[index].checked = checked; | ||
146 | - const { values, isModbusCommand, sendValue } = | ||
147 | - (await getSendValues(data, unref(getDesign).dataSource[index], checked)) || {}; | ||
148 | 98 | ||
149 | - const flag = await sendCommand(values, isModbusCommand ? sendValue : checked, isModbusCommand); | ||
150 | - if (!flag) controlList.value[index].checked = !checked; | 99 | + const { loading, doCommandDeliver } = useCommandDelivery(); |
100 | + const handleSendCommand = async (modalData: SwitchItemType) => { | ||
101 | + if (props.config.option.mode === ComponentMode.SELECT_PREVIEW) return; | ||
102 | + await doCommandDeliver( | ||
103 | + toRaw(unref(modalData)) as DoCommandDeliverDataSourceType, | ||
104 | + Number(unref(modalData).checked) | ||
105 | + ); | ||
151 | }; | 106 | }; |
152 | 107 | ||
153 | const updateFn: MultipleDataFetchUpdateFn = async (message, deviceId, attribute) => { | 108 | const updateFn: MultipleDataFetchUpdateFn = async (message, deviceId, attribute) => { |
@@ -169,34 +124,26 @@ | @@ -169,34 +124,26 @@ | ||
169 | <main class="w-full h-full flex flex-col justify-evenly items-center"> | 124 | <main class="w-full h-full flex flex-col justify-evenly items-center"> |
170 | <DeviceName :config="config" /> | 125 | <DeviceName :config="config" /> |
171 | <div | 126 | <div |
172 | - style="width: 86%" | ||
173 | - v-for="(item, index) in controlList" | 127 | + v-for="item in controlList" |
174 | :key="item.id" | 128 | :key="item.id" |
175 | - class="flex justify-between items-center" | 129 | + class="flex justify-between items-center w-full px-4" |
176 | > | 130 | > |
177 | - <div class="flex items-center"> | ||
178 | - <SvgIcon | ||
179 | - :name="item.icon!" | ||
180 | - prefix="iconfont" | ||
181 | - :size="getRatio ? 30 * getRatio : 30" | ||
182 | - :style="{ color: item.iconColor }" | ||
183 | - /> | ||
184 | - | ||
185 | - <div | ||
186 | - class="text-gray-500 truncate ml-6" | ||
187 | - :style="{ fontSize: (getRatio ? getRatio * item.fontSize : item.fontSize) + 'px' }" | ||
188 | - >{{ | ||
189 | - `${item.deviceName} - ${ | ||
190 | - item.commandType ? CommandTypeEnumLIst[item.commandType].name : item.attributeName | ||
191 | - }` | ||
192 | - }}</div | ||
193 | - > | 131 | + <SvgIcon |
132 | + :name="item.icon!" | ||
133 | + prefix="iconfont" | ||
134 | + :size="getRatio ? 30 * getRatio : 30" | ||
135 | + :style="{ color: item.iconColor }" | ||
136 | + /> | ||
137 | + <div | ||
138 | + class="text-gray-500 truncate mx-2" | ||
139 | + :style="{ fontSize: (getRatio ? getRatio * item.fontSize : item.fontSize) + 'px' }" | ||
140 | + > | ||
141 | + {{ `${item.deviceName} - ${item.attributeName}` }} | ||
194 | </div> | 142 | </div> |
195 | - | ||
196 | <Switch | 143 | <Switch |
197 | v-model:checked="item.checked" | 144 | v-model:checked="item.checked" |
198 | :loading="loading" | 145 | :loading="loading" |
199 | - @change="handleChange(index, item.checked, item)" | 146 | + @change="handleChange(item)" |
200 | :style="{ transform: `scale(${getRatio || 1})` }" | 147 | :style="{ transform: `scale(${getRatio || 1})` }" |
201 | /> | 148 | /> |
202 | </div> | 149 | </div> |
src/views/visual/packages/components/Control/config.ts
deleted
100644 → 0
1 | -import { ref, unref } from 'vue'; | ||
2 | -import { TaskTypeEnum } from '/@/views/task/center/config'; | ||
3 | -import { genModbusCommand } from '/@/api/task'; | ||
4 | -import { useMessage } from '/@/hooks/web/useMessage'; | ||
5 | -import { SingleToHex } from '/@/views/device/list/cpns/tabs/ObjectModelCommandDeliveryModal/config'; | ||
6 | -import { CommandTypeEnum } from '/@/enums/deviceEnum'; | ||
7 | -import { TransportTypeEnum } from '/@/enums/deviceEnum'; | ||
8 | - | ||
9 | -const getArray = (values) => { | ||
10 | - const str = values.replace(/\s+/g, ''); | ||
11 | - const array: any = []; | ||
12 | - | ||
13 | - for (let i = 0; i < str.length; i += 4) { | ||
14 | - const chunk = parseInt(str.substring(i, i + 4), 16); | ||
15 | - array.push(chunk); | ||
16 | - } | ||
17 | - return array; | ||
18 | -}; | ||
19 | - | ||
20 | -export const getSendValues = async (option, getDesign, checked) => { | ||
21 | - const values: any = option; | ||
22 | - const isModbusCommand = ref<boolean>(false); //判断是否是TCP设备-> 且设备标识符是modeBUs,切选择是下发命令类型是属性 | ||
23 | - const { extensionDesc, commandType, codeType, deviceCode, customCommand } = getDesign || {}; | ||
24 | - const { registerAddress, actionType } = extensionDesc || {}; | ||
25 | - const { openCommand, closeCommand, transportType } = customCommand || {}; | ||
26 | - const modBUS = ref<any>({}); | ||
27 | - const sendValue = ref(); | ||
28 | - | ||
29 | - const { createMessage } = useMessage(); | ||
30 | - //判断是不是TCP类型设备 | ||
31 | - if (transportType === TransportTypeEnum.TCP) { | ||
32 | - if ( | ||
33 | - //判断TCP下发类型是否是自定义还是服务 | ||
34 | - commandType === CommandTypeEnum.CUSTOM.toString() || | ||
35 | - commandType == CommandTypeEnum.SERVICE.toString() | ||
36 | - ) { | ||
37 | - values.customCommand.command = checked ? openCommand : closeCommand; | ||
38 | - values.customCommand.command = values.customCommand.command | ||
39 | - .replaceAll(/\s/g, '') | ||
40 | - .toUpperCase(); | ||
41 | - } | ||
42 | - if ( | ||
43 | - //判断命令下发类型是不是属性 且是modbus | ||
44 | - commandType === CommandTypeEnum.ATTRIBUTE.toString() && | ||
45 | - codeType === TaskTypeEnum.MODBUS_RTU | ||
46 | - ) { | ||
47 | - if (!deviceCode) { | ||
48 | - createMessage.warning('当前设备没有设置地址码'); | ||
49 | - return; | ||
50 | - } | ||
51 | - if (!actionType) { | ||
52 | - createMessage.warning('当前物模型扩展描述没有填写'); | ||
53 | - return; | ||
54 | - } | ||
55 | - isModbusCommand.value = true; | ||
56 | - modBUS.value = { | ||
57 | - crc: 'CRC_16_LOWER', | ||
58 | - deviceCode: deviceCode, | ||
59 | - method: actionType == '16' ? '10' : actionType, | ||
60 | - registerAddress, | ||
61 | - registerNumber: 1, | ||
62 | - registerValues: [Number(checked)], | ||
63 | - }; | ||
64 | - | ||
65 | - if (actionType == '16' || actionType == '10') { | ||
66 | - const newValue = Number(checked) == 0 ? [0, 0] : getArray(SingleToHex(Number(checked))); | ||
67 | - modBUS.value.registerValues = newValue; | ||
68 | - modBUS.value.registerNumber = 2; | ||
69 | - modBUS.value.method = '10'; | ||
70 | - } | ||
71 | - | ||
72 | - sendValue.value = await genModbusCommand(unref(modBUS)); | ||
73 | - } | ||
74 | - } | ||
75 | - | ||
76 | - return { values, sendValue: unref(sendValue), isModbusCommand: unref(isModbusCommand) }; | ||
77 | -}; | ||
78 | - | ||
79 | -export const CommandTypeEnumLIst = { | ||
80 | - '0': { CUSTOM: 0, name: '自定义' }, | ||
81 | - '1': { CUSTOM: 1, name: '服务' }, | ||
82 | - '2': { CUSTOM: 2, name: '属性' }, | ||
83 | -}; |
@@ -11,3 +11,7 @@ export const ControlList = [ | @@ -11,3 +11,7 @@ export const ControlList = [ | ||
11 | LateralNumericalControlConfig, | 11 | LateralNumericalControlConfig, |
12 | SwitchListConfig, | 12 | SwitchListConfig, |
13 | ]; | 13 | ]; |
14 | + | ||
15 | +export enum ControlComponentEnum { | ||
16 | + LATERAL_NUMERICAL_CONTROL = 'LateralNumericalControl', | ||
17 | +} |
@@ -3,11 +3,15 @@ | @@ -3,11 +3,15 @@ | ||
3 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 3 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
4 | import { formSchema, getHistorySearchParams, SchemaFiled } from './history.config'; | 4 | import { formSchema, getHistorySearchParams, SchemaFiled } from './history.config'; |
5 | import { HistoryModalOkEmitParams } from './type'; | 5 | import { HistoryModalOkEmitParams } from './type'; |
6 | - import { ref, unref } from 'vue'; | 6 | + import { computed, ref, unref } from 'vue'; |
7 | import { getAllDeviceByOrg } from '/@/api/dataBoard'; | 7 | import { getAllDeviceByOrg } from '/@/api/dataBoard'; |
8 | import { getDeviceHistoryInfo } from '/@/api/alarm/position'; | 8 | import { getDeviceHistoryInfo } from '/@/api/alarm/position'; |
9 | import { DataSource } from '/@/views/visual/palette/types'; | 9 | import { DataSource } from '/@/views/visual/palette/types'; |
10 | - import { cloneDeep } from 'lodash-es'; | 10 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; |
11 | + import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
12 | + import { StructJSON } from '/@/api/device/model/modelOfMatterModel'; | ||
13 | + import { HistoryData } from '/@/api/alarm/position/model'; | ||
14 | + import { useJsonParse } from '/@/hooks/business/useJsonParse'; | ||
11 | 15 | ||
12 | const emit = defineEmits(['register', 'ok']); | 16 | const emit = defineEmits(['register', 'ok']); |
13 | 17 | ||
@@ -20,47 +24,44 @@ | @@ -20,47 +24,44 @@ | ||
20 | }); | 24 | }); |
21 | 25 | ||
22 | const loading = ref(false); | 26 | const loading = ref(false); |
23 | - const getDesign = ref(); | 27 | + const dataSourceRef = ref<DataSource[]>([]); |
24 | 28 | ||
25 | - const getTwoMap = async (dataSource) => { | ||
26 | - if (dataSource.length < 2) return; | ||
27 | - dataSource = dataSource.splice(0, 2); | ||
28 | - const deviceRecord = dataSource?.at(0) || ({} as DataSource); | 29 | + const getPositionRecord = computed<DataSource>(() => unref(dataSourceRef).at(0) as DataSource); |
30 | + | ||
31 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
32 | + | ||
33 | + const handleSetForm = async () => { | ||
34 | + const deviceRecord = unref(getPositionRecord) || {}; | ||
29 | 35 | ||
30 | if (!deviceRecord.organizationId) return; | 36 | if (!deviceRecord.organizationId) return; |
31 | const deviceList = await getAllDeviceByOrg( | 37 | const deviceList = await getAllDeviceByOrg( |
32 | deviceRecord.organizationId, | 38 | deviceRecord.organizationId, |
33 | deviceRecord.deviceProfileId | 39 | deviceRecord.deviceProfileId |
34 | ); | 40 | ); |
41 | + | ||
35 | const options = deviceList | 42 | const options = deviceList |
36 | .filter((item) => item.tbDeviceId === deviceRecord.deviceId) | 43 | .filter((item) => item.tbDeviceId === deviceRecord.deviceId) |
37 | .map((item) => ({ ...item, label: item.alias || item.name, value: item.tbDeviceId })); | 44 | .map((item) => ({ ...item, label: item.alias || item.name, value: item.tbDeviceId })); |
38 | 45 | ||
39 | - const attKey = dataSource.map((item) => ({ | ||
40 | - ...item, | ||
41 | - label: item.attribute, | ||
42 | - value: item.attribute, | ||
43 | - })); | 46 | + const { latitudeIdentifier, longitudeIdentifier, deviceProfileId } = deviceRecord; |
44 | 47 | ||
45 | - updateSchemaMap(options, attKey, deviceRecord); | ||
46 | - }; | 48 | + const attKey = [latitudeIdentifier, longitudeIdentifier].map((item) => { |
49 | + const [identifier, structIdentifier] = item || []; | ||
50 | + const detail = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, identifier); | ||
47 | 51 | ||
48 | - const getOneMap = async (dataSource) => { | ||
49 | - const deviceRecord = dataSource?.[0]; | ||
50 | - if (!deviceRecord.organizationId) return; | ||
51 | - const deviceList = await getAllDeviceByOrg( | ||
52 | - deviceRecord.organizationId, | ||
53 | - deviceRecord.deviceProfileId | ||
54 | - ); | ||
55 | - const options = deviceList | ||
56 | - .filter((item) => item.tbDeviceId === deviceRecord.deviceId) | ||
57 | - .map((item) => ({ ...item, label: item.alias || item.name, value: item.tbDeviceId })); | 52 | + if (detail?.specs?.dataType.type === DataTypeEnum.STRUCT) { |
53 | + const structIdentifierDetail = (detail.specs.dataType.specs as StructJSON[])?.find( | ||
54 | + (temp) => temp.identifier === structIdentifier | ||
55 | + ); | ||
56 | + return { | ||
57 | + label: `${detail.functionName} / ${structIdentifierDetail?.functionName}`, | ||
58 | + value: identifier, | ||
59 | + }; | ||
60 | + } | ||
61 | + | ||
62 | + return { label: detail?.functionName, value: identifier }; | ||
63 | + }); | ||
58 | 64 | ||
59 | - const attKey = dataSource?.map((item) => ({ | ||
60 | - ...item, | ||
61 | - label: item.attributeName, | ||
62 | - value: item.attribute, | ||
63 | - })); | ||
64 | updateSchemaMap(options, attKey, deviceRecord); | 65 | updateSchemaMap(options, attKey, deviceRecord); |
65 | }; | 66 | }; |
66 | 67 | ||
@@ -92,81 +93,73 @@ | @@ -92,81 +93,73 @@ | ||
92 | 93 | ||
93 | const [registerModal, { closeModal }] = useModalInner(async (dataSource: DataSource[]) => { | 94 | const [registerModal, { closeModal }] = useModalInner(async (dataSource: DataSource[]) => { |
94 | try { | 95 | try { |
95 | - getDesign.value = dataSource; | ||
96 | - dataSource = cloneDeep(dataSource); | ||
97 | - //判断选择是不是结构体 | ||
98 | - if (dataSource.length == 1 && dataSource?.[0]?.lal) { | ||
99 | - getOneMap(dataSource); | ||
100 | - return; | ||
101 | - } | ||
102 | - getTwoMap(dataSource); | 96 | + dataSourceRef.value = dataSource; |
97 | + handleSetForm(); | ||
103 | } catch (error) { | 98 | } catch (error) { |
104 | throw error; | 99 | throw error; |
105 | } | 100 | } |
106 | }); | 101 | }); |
107 | 102 | ||
108 | - const getMultipleDataSource = async (res) => { | 103 | + const getPositionDataSource = async (res: HistoryData) => { |
104 | + const keys = Object.keys(res); | ||
105 | + const track: Record<'lng' | 'lat', number>[] = []; | ||
106 | + | ||
107 | + const { | ||
108 | + latitudeIdentifier = [], | ||
109 | + longitudeIdentifier = [], | ||
110 | + deviceProfileId, | ||
111 | + } = unref(getPositionRecord); | ||
112 | + | ||
113 | + const [latIdentifier] = latitudeIdentifier || []; | ||
114 | + const [lngIdentifier] = longitudeIdentifier || []; | ||
115 | + | ||
116 | + if (!latIdentifier || !lngIdentifier) return track; | ||
117 | + | ||
118 | + const latDetail = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, latIdentifier); | ||
119 | + const lngDetail = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, lngIdentifier); | ||
120 | + | ||
121 | + if (!latDetail || !lngDetail) return track; | ||
122 | + | ||
109 | let timespanList = Object.keys(res).reduce((prev, next) => { | 123 | let timespanList = Object.keys(res).reduce((prev, next) => { |
110 | const ts = res[next].map((item) => item.ts); | 124 | const ts = res[next].map((item) => item.ts); |
111 | return [...prev, ...ts]; | 125 | return [...prev, ...ts]; |
112 | }, [] as number[]); | 126 | }, [] as number[]); |
113 | timespanList = [...new Set(timespanList)]; | 127 | timespanList = [...new Set(timespanList)]; |
114 | 128 | ||
115 | - const track: Record<'lng' | 'lat', number>[] = []; | ||
116 | - const keys = Object.keys(res); | 129 | + for (const position of [longitudeIdentifier, latitudeIdentifier]) { |
130 | + const [attribute] = position; | ||
131 | + const detail = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
132 | + if (!detail) continue; | ||
133 | + const { identifier } = detail || {}; | ||
134 | + | ||
135 | + if (detail?.specs?.dataType.type === DataTypeEnum.STRUCT) { | ||
136 | + const [, structIdentifier] = position; | ||
137 | + res[identifier].forEach((temp) => { | ||
138 | + const structJSON = useJsonParse(temp.value).value; | ||
139 | + temp.value = structJSON?.[structIdentifier]; | ||
140 | + }); | ||
141 | + } | ||
142 | + } | ||
117 | 143 | ||
118 | for (const ts of timespanList) { | 144 | for (const ts of timespanList) { |
119 | const list: { ts: number; value: number }[] = []; | 145 | const list: { ts: number; value: number }[] = []; |
120 | for (const key of keys) { | 146 | for (const key of keys) { |
121 | const record = res[key].find((item) => ts === item.ts); | 147 | const record = res[key].find((item) => ts === item.ts); |
122 | - if (!validEffective(record?.value)) { | ||
123 | - continue; | ||
124 | - } | ||
125 | list.push(record as any); | 148 | list.push(record as any); |
126 | } | 149 | } |
127 | 150 | ||
128 | if (list.length === 2 && list.every(Boolean)) { | 151 | if (list.length === 2 && list.every(Boolean)) { |
129 | - const lng = list.at(0)?.value; | ||
130 | - const lat = list.at(1)?.value; | ||
131 | - if (lng && lat) track.push({ lng, lat }); | 152 | + let lng = list.at(0)?.value; |
153 | + let lat = list.at(1)?.value; | ||
154 | + if (lng && lat) { | ||
155 | + track.push({ lng: Number(lng), lat: Number(lat) }); | ||
156 | + } | ||
132 | } | 157 | } |
133 | } | 158 | } |
134 | - return track; | ||
135 | - }; | ||
136 | - | ||
137 | - // 单数据源选择结构体 | ||
138 | - const getSingleDataSource = async (res) => { | ||
139 | - const [keys] = Object.keys(res); | ||
140 | - const track: Record<'lng' | 'lat', number>[] = []; | ||
141 | - const dataSource = res[keys]?.map((item) => { | ||
142 | - return { | ||
143 | - value: item.value ? JSON.parse(item.value) : {}, | ||
144 | - }; | ||
145 | - }); | ||
146 | - const list: { value: number }[] = []; | ||
147 | - dataSource?.forEach((item) => { | ||
148 | - if ( | ||
149 | - //判断结构体得值是不是数字 | ||
150 | - Object.values(item.value).every((item1) => { | ||
151 | - return validEffective(item1 as any); | ||
152 | - }) | ||
153 | - ) { | ||
154 | - list.push(item.value); | ||
155 | - } | ||
156 | - }); | ||
157 | - const { latitude, longitude } = unref(getDesign)?.[0]; //获取选择的经纬度选项 | ||
158 | 159 | ||
159 | - list.forEach((item) => { | ||
160 | - const lng = item[longitude]; | ||
161 | - const lat = item[latitude]; | ||
162 | - if (lng && lat) track.push({ lng, lat }); | ||
163 | - }); | ||
164 | return track; | 160 | return track; |
165 | }; | 161 | }; |
166 | 162 | ||
167 | - const validEffective = (value = '') => { | ||
168 | - return !!(value && !isNaN(value as unknown as number)); | ||
169 | - }; | ||
170 | const handleOk = async () => { | 163 | const handleOk = async () => { |
171 | try { | 164 | try { |
172 | await validate(); | 165 | await validate(); |
@@ -180,9 +173,8 @@ | @@ -180,9 +173,8 @@ | ||
180 | ...value, | 173 | ...value, |
181 | [SchemaFiled.KEYS]: value[SchemaFiled.KEYS].join(','), | 174 | [SchemaFiled.KEYS]: value[SchemaFiled.KEYS].join(','), |
182 | }); | 175 | }); |
183 | - const ifSingle = unref(getDesign)?.length === 1 && unref(getDesign)?.[0]?.lal; | ||
184 | 176 | ||
185 | - const track = ifSingle ? await getSingleDataSource(res) : await getMultipleDataSource(res); | 177 | + const track = await getPositionDataSource(res); |
186 | emit('ok', { track, value } as HistoryModalOkEmitParams); | 178 | emit('ok', { track, value } as HistoryModalOkEmitParams); |
187 | closeModal(); | 179 | closeModal(); |
188 | } catch (error) { | 180 | } catch (error) { |
1 | +import { CategoryEnum } from '../..'; | ||
1 | import { useComponentKeys } from '/@/views/visual/packages/hook/useComponentKeys'; | 2 | import { useComponentKeys } from '/@/views/visual/packages/hook/useComponentKeys'; |
2 | import { ConfigType, PackagesCategoryEnum } from '/@/views/visual/packages/index.type'; | 3 | import { ConfigType, PackagesCategoryEnum } from '/@/views/visual/packages/index.type'; |
3 | 4 | ||
@@ -6,5 +7,6 @@ const componentKeys = useComponentKeys('MapComponentTrackHistory'); | @@ -6,5 +7,6 @@ const componentKeys = useComponentKeys('MapComponentTrackHistory'); | ||
6 | export const MapComponentTrackHistoryConfig: ConfigType = { | 7 | export const MapComponentTrackHistoryConfig: ConfigType = { |
7 | ...componentKeys, | 8 | ...componentKeys, |
8 | title: '历史轨迹', | 9 | title: '历史轨迹', |
10 | + category: CategoryEnum.MAP, | ||
9 | package: PackagesCategoryEnum.MAP, | 11 | package: PackagesCategoryEnum.MAP, |
10 | }; | 12 | }; |
1 | +import { CategoryEnum } from '../..'; | ||
1 | import { useComponentKeys } from '/@/views/visual/packages/hook/useComponentKeys'; | 2 | import { useComponentKeys } from '/@/views/visual/packages/hook/useComponentKeys'; |
2 | import { ConfigType, PackagesCategoryEnum } from '/@/views/visual/packages/index.type'; | 3 | import { ConfigType, PackagesCategoryEnum } from '/@/views/visual/packages/index.type'; |
3 | 4 | ||
@@ -6,5 +7,6 @@ const componentKeys = useComponentKeys('MapComponentTrackReal'); | @@ -6,5 +7,6 @@ const componentKeys = useComponentKeys('MapComponentTrackReal'); | ||
6 | export const MapComponentTrackRealConfig: ConfigType = { | 7 | export const MapComponentTrackRealConfig: ConfigType = { |
7 | ...componentKeys, | 8 | ...componentKeys, |
8 | title: '实时轨迹', | 9 | title: '实时轨迹', |
10 | + category: CategoryEnum.MAP, | ||
9 | package: PackagesCategoryEnum.MAP, | 11 | package: PackagesCategoryEnum.MAP, |
10 | }; | 12 | }; |
@@ -9,6 +9,7 @@ | @@ -9,6 +9,7 @@ | ||
9 | import { useMapTrackPlayBack } from './useMapTrackPlayback'; | 9 | import { useMapTrackPlayBack } from './useMapTrackPlayback'; |
10 | import { useMultipleDataFetch } from '../../../hook/socket/useSocket'; | 10 | import { useMultipleDataFetch } from '../../../hook/socket/useSocket'; |
11 | import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 11 | import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
12 | + import get from 'lodash-es/get'; | ||
12 | 13 | ||
13 | const props = defineProps<{ | 14 | const props = defineProps<{ |
14 | config: ComponentPropsConfigType<typeof option>; | 15 | config: ComponentPropsConfigType<typeof option>; |
@@ -24,44 +25,36 @@ | @@ -24,44 +25,36 @@ | ||
24 | return props.config.option.dataSource?.at(0)?.deviceId; | 25 | return props.config.option.dataSource?.at(0)?.deviceId; |
25 | }); | 26 | }); |
26 | 27 | ||
27 | - const getDesign = computed(() => { | ||
28 | - const { option } = props.config; | ||
29 | - const { dataSource } = option || {}; | ||
30 | - return { | ||
31 | - dataSource: dataSource, | ||
32 | - }; | ||
33 | - }); | ||
34 | - | ||
35 | /** | 28 | /** |
36 | * @description 经度key | 29 | * @description 经度key |
37 | */ | 30 | */ |
38 | const getLngKey = computed(() => { | 31 | const getLngKey = computed(() => { |
39 | - return props.config.option.dataSource?.at(0)?.attribute || ''; | 32 | + return props.config.option.dataSource?.at(0)?.longitudeIdentifier || []; |
40 | }); | 33 | }); |
41 | 34 | ||
42 | /** | 35 | /** |
43 | * @description 纬度key | 36 | * @description 纬度key |
44 | */ | 37 | */ |
45 | const getLatKey = computed(() => { | 38 | const getLatKey = computed(() => { |
46 | - return props.config.option.dataSource?.at(1)?.attribute || ''; | 39 | + return props.config.option.dataSource?.at(0)?.latitudeIdentifier || []; |
47 | }); | 40 | }); |
48 | 41 | ||
49 | const validEffective = (value = '') => { | 42 | const validEffective = (value = '') => { |
50 | return !!(value && !isNaN(value as unknown as number)); | 43 | return !!(value && !isNaN(value as unknown as number)); |
51 | }; | 44 | }; |
52 | 45 | ||
53 | - const getTwoMap = (message, deviceId) => { | 46 | + const handleMessage = (message, deviceId) => { |
54 | if (unref(getDeviceId) !== deviceId) return; | 47 | if (unref(getDeviceId) !== deviceId) return; |
55 | 48 | ||
56 | const { data = {} } = message; | 49 | const { data = {} } = message; |
57 | 50 | ||
58 | const bindMessage = data[deviceId]; | 51 | const bindMessage = data[deviceId]; |
59 | 52 | ||
60 | - const lngData = bindMessage[unref(getLngKey)] || []; | 53 | + const lngData = get(bindMessage, unref(getLngKey)) || []; |
61 | const [lngLatest] = lngData; | 54 | const [lngLatest] = lngData; |
62 | const [, lng] = lngLatest || []; | 55 | const [, lng] = lngLatest || []; |
63 | 56 | ||
64 | - const latData = bindMessage[unref(getLatKey)] || []; | 57 | + const latData = get(bindMessage, unref(getLatKey)) || []; |
65 | const [latLatest] = latData; | 58 | const [latLatest] = latData; |
66 | const [, lat] = latLatest || []; | 59 | const [, lat] = latLatest || []; |
67 | 60 | ||
@@ -70,32 +63,8 @@ | @@ -70,32 +63,8 @@ | ||
70 | } | 63 | } |
71 | }; | 64 | }; |
72 | 65 | ||
73 | - const getOneMap = (message, deviceId) => { | ||
74 | - if (unref(getDeviceId) !== deviceId) return; | ||
75 | - | ||
76 | - const { longitude, latitude, attribute } = unref(getDesign)?.dataSource?.[0] || {}; | ||
77 | - const { data } = message || {}; | ||
78 | - const bindMessage = data[deviceId]; | ||
79 | - const [, values] = attribute && bindMessage?.[attribute][0]; | ||
80 | - | ||
81 | - const mapValues = values ? JSON.parse(values) : {}; | ||
82 | - const lng = longitude && mapValues[longitude]; | ||
83 | - const lat = latitude && mapValues[latitude]; | ||
84 | - | ||
85 | - if (validEffective(lng) && validEffective(lat)) { | ||
86 | - drawLine({ lng: Number(lng), lat: Number(lat) }); | ||
87 | - } | ||
88 | - }; | ||
89 | - | ||
90 | const updateFn: MultipleDataFetchUpdateFn = (message, deviceId) => { | 66 | const updateFn: MultipleDataFetchUpdateFn = (message, deviceId) => { |
91 | - const { lal } = unref(getDesign)?.dataSource?.[0] || {}; | ||
92 | - // 属性选择结构体类型时 | ||
93 | - if (lal && unref(getDesign)?.dataSource?.length == 1) { | ||
94 | - getOneMap(message, deviceId); | ||
95 | - return; | ||
96 | - } | ||
97 | - // 选择两个属性时 | ||
98 | - getTwoMap(message, deviceId); | 67 | + handleMessage(message, deviceId); |
99 | }; | 68 | }; |
100 | 69 | ||
101 | useMultipleDataFetch(props, updateFn); | 70 | useMultipleDataFetch(props, updateFn); |
src/views/visual/packages/components/Text/SwitchSignalLight/config.ts
deleted
100644 → 0
1 | -import cloneDeep from 'lodash-es/cloneDeep'; | ||
2 | -import { SwitchSignalLightConfig } from '.'; | ||
3 | -import { | ||
4 | - ConfigType, | ||
5 | - CreateComponentType, | ||
6 | - PublicComponentOptions, | ||
7 | - PublicPresetOptions, | ||
8 | -} from '/@/views/visual/packages/index.type'; | ||
9 | -import { PublicConfigClass, componentInitConfig } from '/@/views/visual/packages/publicConfig'; | ||
10 | -import { ComponentConfigFieldEnum } from '/@/views/visual/packages/enum'; | ||
11 | - | ||
12 | -export const option: PublicPresetOptions = { | ||
13 | - [ComponentConfigFieldEnum.OPEN_COLOR]: '#30f230', | ||
14 | - [ComponentConfigFieldEnum.CLOSE_COLOR]: '#eeeeee', | ||
15 | - [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: true, | ||
16 | -}; | ||
17 | - | ||
18 | -export default class Config extends PublicConfigClass implements CreateComponentType { | ||
19 | - public key: string = SwitchSignalLightConfig.key; | ||
20 | - | ||
21 | - public attr = { ...componentInitConfig }; | ||
22 | - | ||
23 | - public componentConfig: ConfigType = cloneDeep(SwitchSignalLightConfig); | ||
24 | - | ||
25 | - public persetOption = cloneDeep(option); | ||
26 | - | ||
27 | - public option: PublicComponentOptions; | ||
28 | - | ||
29 | - constructor(option: PublicComponentOptions) { | ||
30 | - super(); | ||
31 | - this.option = { ...option }; | ||
32 | - } | ||
33 | -} |
src/views/visual/packages/components/Text/SwitchSignalLight/config.vue
deleted
100644 → 0
1 | -<script lang="ts" setup> | ||
2 | - import { ComponentConfigFieldEnum } from '/@/views/visual/packages/enum'; | ||
3 | - import { useForm, BasicForm } from '/@/components/Form'; | ||
4 | - import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; | ||
5 | - import { option } from './config'; | ||
6 | - | ||
7 | - const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ | ||
8 | - schemas: [ | ||
9 | - { | ||
10 | - field: ComponentConfigFieldEnum.OPEN_COLOR, | ||
11 | - label: 'ON颜色', | ||
12 | - component: 'ColorPicker', | ||
13 | - changeEvent: 'update:value', | ||
14 | - componentProps: { | ||
15 | - defaultValue: option.openColor, | ||
16 | - }, | ||
17 | - }, | ||
18 | - { | ||
19 | - field: ComponentConfigFieldEnum.CLOSE_COLOR, | ||
20 | - label: 'OFF颜色', | ||
21 | - component: 'ColorPicker', | ||
22 | - changeEvent: 'update:value', | ||
23 | - componentProps: { | ||
24 | - defaultValue: option.closeColor, | ||
25 | - }, | ||
26 | - }, | ||
27 | - { | ||
28 | - field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
29 | - label: '显示设备名称', | ||
30 | - component: 'Checkbox', | ||
31 | - defaultValue: option.showDeviceName, | ||
32 | - }, | ||
33 | - ], | ||
34 | - showActionButtonGroup: false, | ||
35 | - labelWidth: 120, | ||
36 | - baseColProps: { | ||
37 | - span: 12, | ||
38 | - }, | ||
39 | - }); | ||
40 | - | ||
41 | - const getFormValues = () => { | ||
42 | - return getFieldsValue(); | ||
43 | - }; | ||
44 | - | ||
45 | - const setFormValues = (data: Recordable) => { | ||
46 | - return setFieldsValue(data); | ||
47 | - }; | ||
48 | - | ||
49 | - defineExpose({ | ||
50 | - getFormValues, | ||
51 | - setFormValues, | ||
52 | - resetFormValues: resetFields, | ||
53 | - } as PublicFormInstaceType); | ||
54 | -</script> | ||
55 | - | ||
56 | -<template> | ||
57 | - <BasicForm @register="register" /> | ||
58 | -</template> |
src/views/visual/packages/components/Text/SwitchSignalLight/datasource.vue
deleted
100644 → 0
1 | -<script lang="ts" setup> | ||
2 | - import { commonDataSourceSchemas } from '../../../config/common.config'; | ||
3 | - import { BasicForm, useForm } from '/@/components/Form'; | ||
4 | - import { PublicFormInstaceType } from '/@/views/visual/dataSourceBindPanel/index.type'; | ||
5 | - | ||
6 | - const [register, { getFieldsValue, setFieldsValue, validate, resetFields }] = useForm({ | ||
7 | - labelWidth: 0, | ||
8 | - showActionButtonGroup: false, | ||
9 | - layout: 'horizontal', | ||
10 | - labelCol: { span: 0 }, | ||
11 | - schemas: commonDataSourceSchemas(), | ||
12 | - }); | ||
13 | - | ||
14 | - const getFormValues = () => { | ||
15 | - return getFieldsValue(); | ||
16 | - }; | ||
17 | - | ||
18 | - const setFormValues = (record: Recordable) => { | ||
19 | - return setFieldsValue(record); | ||
20 | - }; | ||
21 | - | ||
22 | - defineExpose({ | ||
23 | - getFormValues, | ||
24 | - setFormValues, | ||
25 | - validate, | ||
26 | - resetFormValues: resetFields, | ||
27 | - } as PublicFormInstaceType); | ||
28 | -</script> | ||
29 | - | ||
30 | -<template> | ||
31 | - <BasicForm @register="register" /> | ||
32 | -</template> |
src/views/visual/packages/components/Text/SwitchSignalLight/index.ts
deleted
100644 → 0
1 | -// import { ComponentEnum, ComponentNameEnum } from '../index.type'; | ||
2 | -import { useComponentKeys } from '/@/views/visual/packages/hook/useComponentKeys'; | ||
3 | -import { ConfigType, PackagesCategoryEnum } from '/@/views/visual/packages/index.type'; | ||
4 | - | ||
5 | -const componentKeys = useComponentKeys('SwitchSignalLight'); | ||
6 | -export const SwitchSignalLightConfig: ConfigType = { | ||
7 | - ...componentKeys, | ||
8 | - // title: ComponentNameEnum.TEXT_COMPONENT_1, | ||
9 | - title: '开关量信号灯', | ||
10 | - package: PackagesCategoryEnum.TEXT, | ||
11 | -}; |
src/views/visual/packages/components/Text/SwitchSignalLight/index.vue
deleted
100644 → 0
1 | -<script lang="ts" setup> | ||
2 | - import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | ||
3 | - import { option } from './config'; | ||
4 | - import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale'; | ||
5 | - import { ref, onMounted, unref } from 'vue'; | ||
6 | - import { useIntervalFn } from '@vueuse/core'; | ||
7 | - import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; | ||
8 | - import { useReceiveValue } from '../../../hook/useReceiveValue'; | ||
9 | - import { useDataFetch } from '../../../hook/socket/useSocket'; | ||
10 | - import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | ||
11 | - | ||
12 | - const props = defineProps<{ | ||
13 | - config: ComponentPropsConfigType<typeof option>; | ||
14 | - }>(); | ||
15 | - | ||
16 | - const isOpenClose = ref<boolean>(true); | ||
17 | - | ||
18 | - const randomFn = () => { | ||
19 | - useIntervalFn(() => { | ||
20 | - isOpenClose.value = !unref(isOpenClose); | ||
21 | - }, 2000); | ||
22 | - }; | ||
23 | - const { getNumberValue } = useReceiveValue(); | ||
24 | - const updateFn: DataFetchUpdateFn = (message, attribute) => { | ||
25 | - const { data = {} } = message; | ||
26 | - const [latest] = data[attribute] || []; | ||
27 | - const [_, value] = latest; | ||
28 | - isOpenClose.value = Boolean(getNumberValue(value)); | ||
29 | - }; | ||
30 | - | ||
31 | - onMounted(() => { | ||
32 | - !props.config.option.uuid && randomFn(); | ||
33 | - }); | ||
34 | - | ||
35 | - useDataFetch(props, updateFn); | ||
36 | - | ||
37 | - const { getScale } = useComponentScale(props); | ||
38 | -</script> | ||
39 | - | ||
40 | -<template> | ||
41 | - <main :style="getScale" class="w-full h-full flex flex-col justify-center items-center"> | ||
42 | - <DeviceName :config="config" class="text-center" /> | ||
43 | - <div | ||
44 | - style="--open-color: `${getDesign.openColor}`; --close-color: `${getDesign.closeColor}`" | ||
45 | - :class="isOpenClose ? 'switch_open' : 'switch_close'" | ||
46 | - > | ||
47 | - </div> | ||
48 | - </main> | ||
49 | -</template> | ||
50 | -<style lang="less" scoped> | ||
51 | - .switch_open { | ||
52 | - background: var(--open-color); | ||
53 | - box-shadow: var(--open-color) 0 0 10px 3px; | ||
54 | - width: 60px; | ||
55 | - height: 60px; | ||
56 | - border-radius: 50%; | ||
57 | - margin: 10px 0; | ||
58 | - } | ||
59 | - | ||
60 | - .switch_close { | ||
61 | - background-color: var(--close-color); | ||
62 | - box-shadow: none; | ||
63 | - width: 42.023px; | ||
64 | - height: 42.023px; | ||
65 | - border-radius: 50%; | ||
66 | - margin: 10px 0; | ||
67 | - } | ||
68 | -</style> |
@@ -2,11 +2,13 @@ | @@ -2,11 +2,13 @@ | ||
2 | import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | 2 | import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; |
3 | import { option } from './config'; | 3 | import { option } from './config'; |
4 | import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale'; | 4 | import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale'; |
5 | - import { computed } from 'vue'; | 5 | + import { computed, unref } from 'vue'; |
6 | import { ref } from 'vue'; | 6 | import { ref } from 'vue'; |
7 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; | 7 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; |
8 | import { useDataFetch } from '../../../hook/socket/useSocket'; | 8 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
9 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 9 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
10 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
11 | + import { useThingsModelValueTransform } from '/@/views/visual/palette/hooks/useThingsModelValueTransform'; | ||
10 | 12 | ||
11 | const props = defineProps<{ | 13 | const props = defineProps<{ |
12 | config: ComponentPropsConfigType<typeof option>; | 14 | config: ComponentPropsConfigType<typeof option>; |
@@ -14,6 +16,15 @@ | @@ -14,6 +16,15 @@ | ||
14 | 16 | ||
15 | const currentValue = ref<string | number>(123); | 17 | const currentValue = ref<string | number>(123); |
16 | 18 | ||
19 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
20 | + | ||
21 | + const getThingModelTsl = computed(() => { | ||
22 | + const { option } = props.config; | ||
23 | + | ||
24 | + const { deviceProfileId, attribute } = option; | ||
25 | + return getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
26 | + }); | ||
27 | + | ||
17 | const getDesign = computed(() => { | 28 | const getDesign = computed(() => { |
18 | const { persetOption = {}, option } = props.config; | 29 | const { persetOption = {}, option } = props.config; |
19 | 30 | ||
@@ -23,14 +34,14 @@ | @@ -23,14 +34,14 @@ | ||
23 | valueSize: persetValueSize, | 34 | valueSize: persetValueSize, |
24 | } = persetOption; | 35 | } = persetOption; |
25 | 36 | ||
26 | - const { componentInfo, attribute, attributeRename, attributeName } = option; | 37 | + const { componentInfo, attribute, attributeRename } = option; |
27 | 38 | ||
28 | const { fontColor, fontSize, valueSize } = componentInfo || {}; | 39 | const { fontColor, fontSize, valueSize } = componentInfo || {}; |
29 | return { | 40 | return { |
30 | fontColor: fontColor || persetFontColor, | 41 | fontColor: fontColor || persetFontColor, |
31 | fontSize: fontSize || persetFontSize || 14, | 42 | fontSize: fontSize || persetFontSize || 14, |
32 | valueSize: valueSize || persetValueSize || 20, | 43 | valueSize: valueSize || persetValueSize || 20, |
33 | - attribute: attributeRename || attributeName || attribute, | 44 | + attribute: attributeRename || unref(getThingModelTsl)?.functionName || attribute, |
34 | }; | 45 | }; |
35 | }); | 46 | }); |
36 | 47 | ||
@@ -39,7 +50,10 @@ | @@ -39,7 +50,10 @@ | ||
39 | const [latest] = data[attribute] || []; | 50 | const [latest] = data[attribute] || []; |
40 | if (!latest.length) return; | 51 | if (!latest.length) return; |
41 | const [_, value] = latest; | 52 | const [_, value] = latest; |
42 | - currentValue.value = value; | 53 | + currentValue.value = useThingsModelValueTransform( |
54 | + value, | ||
55 | + unref(getThingModelTsl)?.specs?.dataType | ||
56 | + ); | ||
43 | }; | 57 | }; |
44 | 58 | ||
45 | useDataFetch(props, updateFn); | 59 | useDataFetch(props, updateFn); |
@@ -52,7 +66,7 @@ | @@ -52,7 +66,7 @@ | ||
52 | <DeviceName :config="config" /> | 66 | <DeviceName :config="config" /> |
53 | 67 | ||
54 | <h1 | 68 | <h1 |
55 | - class="my-4 font-bold !my-2 truncate" | 69 | + class="my-4 font-bold !my-2 truncate w-full text-center" |
56 | :style="{ | 70 | :style="{ |
57 | color: getDesign.fontColor, | 71 | color: getDesign.fontColor, |
58 | fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px', | 72 | fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px', |
@@ -63,10 +77,8 @@ | @@ -63,10 +77,8 @@ | ||
63 | <div | 77 | <div |
64 | class="text-gray-500 truncate" | 78 | class="text-gray-500 truncate" |
65 | :style="{ fontSize: (getRatio ? getRatio * getDesign.fontSize : getDesign.fontSize) + 'px' }" | 79 | :style="{ fontSize: (getRatio ? getRatio * getDesign.fontSize : getDesign.fontSize) + 'px' }" |
66 | - >{{ getDesign.attribute || '温度' }}</div | ||
67 | > | 80 | > |
68 | - <!-- <div v-if="config.option.componentInfo.showDeviceName"> | ||
69 | - {{ config.option.deviceRename || config.option.deviceName }} | ||
70 | - </div> --> | 81 | + {{ getDesign.attribute || '温度' }} |
82 | + </div> | ||
71 | </main> | 83 | </main> |
72 | </template> | 84 | </template> |
@@ -2,12 +2,14 @@ | @@ -2,12 +2,14 @@ | ||
2 | import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | 2 | import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; |
3 | import { option } from './config'; | 3 | import { option } from './config'; |
4 | import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale'; | 4 | import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale'; |
5 | - import { computed } from 'vue'; | 5 | + import { computed, unref } from 'vue'; |
6 | import { ref } from 'vue'; | 6 | import { ref } from 'vue'; |
7 | import { UpdateTime } from '/@/views/visual/commonComponents/UpdateTime'; | 7 | import { UpdateTime } from '/@/views/visual/commonComponents/UpdateTime'; |
8 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; | 8 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; |
9 | import { useDataFetch } from '../../../hook/socket/useSocket'; | 9 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
10 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 10 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
11 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
12 | + import { useThingsModelValueTransform } from '/@/views/visual/palette/hooks/useThingsModelValueTransform'; | ||
11 | 13 | ||
12 | const props = defineProps<{ | 14 | const props = defineProps<{ |
13 | config: ComponentPropsConfigType<typeof option>; | 15 | config: ComponentPropsConfigType<typeof option>; |
@@ -16,6 +18,15 @@ | @@ -16,6 +18,15 @@ | ||
16 | const currentValue = ref<string | number>(123); | 18 | const currentValue = ref<string | number>(123); |
17 | const time = ref<Nullable<number>>(null); | 19 | const time = ref<Nullable<number>>(null); |
18 | 20 | ||
21 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
22 | + | ||
23 | + const getThingModelTsl = computed(() => { | ||
24 | + const { option } = props.config; | ||
25 | + | ||
26 | + const { deviceProfileId, attribute } = option; | ||
27 | + return getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
28 | + }); | ||
29 | + | ||
19 | const getDesign = computed(() => { | 30 | const getDesign = computed(() => { |
20 | const { persetOption = {}, option } = props.config; | 31 | const { persetOption = {}, option } = props.config; |
21 | 32 | ||
@@ -25,7 +36,7 @@ | @@ -25,7 +36,7 @@ | ||
25 | fontSize: persetFontSize, | 36 | fontSize: persetFontSize, |
26 | } = persetOption; | 37 | } = persetOption; |
27 | 38 | ||
28 | - const { componentInfo, attribute, attributeName, attributeRename } = option; | 39 | + const { componentInfo, attribute, attributeRename } = option; |
29 | 40 | ||
30 | const { fontColor, valueSize, fontSize } = componentInfo || {}; | 41 | const { fontColor, valueSize, fontSize } = componentInfo || {}; |
31 | 42 | ||
@@ -33,7 +44,7 @@ | @@ -33,7 +44,7 @@ | ||
33 | fontColor: fontColor || persetFontColor, | 44 | fontColor: fontColor || persetFontColor, |
34 | valueSize: valueSize || persetValueSize || 20, | 45 | valueSize: valueSize || persetValueSize || 20, |
35 | fontSize: fontSize || persetFontSize || 14, | 46 | fontSize: fontSize || persetFontSize || 14, |
36 | - attribute: attributeRename || attributeName || attribute, | 47 | + attribute: attributeRename || unref(getThingModelTsl)?.functionName || attribute, |
37 | }; | 48 | }; |
38 | }); | 49 | }); |
39 | 50 | ||
@@ -42,7 +53,10 @@ | @@ -42,7 +53,10 @@ | ||
42 | const [info] = data[attribute] || []; | 53 | const [info] = data[attribute] || []; |
43 | if (!info.length) return; | 54 | if (!info.length) return; |
44 | const [timespan, value] = info; | 55 | const [timespan, value] = info; |
45 | - currentValue.value = value; | 56 | + currentValue.value = useThingsModelValueTransform( |
57 | + value, | ||
58 | + unref(getThingModelTsl)?.specs?.dataType | ||
59 | + ); | ||
46 | time.value = timespan; | 60 | time.value = timespan; |
47 | }; | 61 | }; |
48 | 62 | ||
@@ -54,9 +68,9 @@ | @@ -54,9 +68,9 @@ | ||
54 | <template> | 68 | <template> |
55 | <main class="w-full h-full flex flex-col justify-center items-center"> | 69 | <main class="w-full h-full flex flex-col justify-center items-center"> |
56 | <DeviceName :config="config" /> | 70 | <DeviceName :config="config" /> |
57 | - <div class="flex-1 flex justify-center items-center flex-col" :style="getScale"> | 71 | + <div class="flex-1 flex justify-center items-center flex-col w-full" :style="getScale"> |
58 | <h1 | 72 | <h1 |
59 | - class="my-4 font-bold !my-2 truncate" | 73 | + class="my-4 font-bold !my-2 truncate w-full text-center" |
60 | :style="{ | 74 | :style="{ |
61 | color: getDesign.fontColor, | 75 | color: getDesign.fontColor, |
62 | fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px', | 76 | fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px', |
@@ -2,13 +2,15 @@ | @@ -2,13 +2,15 @@ | ||
2 | import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | 2 | import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; |
3 | import { option } from './config'; | 3 | import { option } from './config'; |
4 | import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale'; | 4 | import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale'; |
5 | - import { ref } from 'vue'; | 5 | + import { ref, unref } from 'vue'; |
6 | import { UpdateTime } from '/@/views/visual/commonComponents/UpdateTime'; | 6 | import { UpdateTime } from '/@/views/visual/commonComponents/UpdateTime'; |
7 | import { SvgIcon } from '/@/components/Icon'; | 7 | import { SvgIcon } from '/@/components/Icon'; |
8 | import { computed } from 'vue'; | 8 | import { computed } from 'vue'; |
9 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; | 9 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; |
10 | import { useDataFetch } from '../../../hook/socket/useSocket'; | 10 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
11 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 11 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
12 | + import { useThingsModelValueTransform } from '/@/views/visual/palette/hooks/useThingsModelValueTransform'; | ||
13 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
12 | 14 | ||
13 | const props = defineProps<{ | 15 | const props = defineProps<{ |
14 | config: ComponentPropsConfigType<typeof option>; | 16 | config: ComponentPropsConfigType<typeof option>; |
@@ -18,6 +20,15 @@ | @@ -18,6 +20,15 @@ | ||
18 | 20 | ||
19 | const time = ref<Nullable<number>>(null); | 21 | const time = ref<Nullable<number>>(null); |
20 | 22 | ||
23 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
24 | + | ||
25 | + const getThingModelTsl = computed(() => { | ||
26 | + const { option } = props.config; | ||
27 | + | ||
28 | + const { deviceProfileId, attribute } = option; | ||
29 | + return getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
30 | + }); | ||
31 | + | ||
21 | const getDesign = computed(() => { | 32 | const getDesign = computed(() => { |
22 | const { persetOption = {}, option } = props.config; | 33 | const { persetOption = {}, option } = props.config; |
23 | 34 | ||
@@ -49,7 +60,10 @@ | @@ -49,7 +60,10 @@ | ||
49 | const [latest] = data[attribute] || []; | 60 | const [latest] = data[attribute] || []; |
50 | if (!latest.length) return; | 61 | if (!latest.length) return; |
51 | const [timespan, value] = latest; | 62 | const [timespan, value] = latest; |
52 | - currentValue.value = value; | 63 | + currentValue.value = useThingsModelValueTransform( |
64 | + value, | ||
65 | + unref(getThingModelTsl)?.specs?.dataType | ||
66 | + ); | ||
53 | time.value = timespan; | 67 | time.value = timespan; |
54 | }; | 68 | }; |
55 | 69 | ||
@@ -61,7 +75,7 @@ | @@ -61,7 +75,7 @@ | ||
61 | <template> | 75 | <template> |
62 | <main :style="getScale" class="w-full h-full flex flex-col justify-center items-center"> | 76 | <main :style="getScale" class="w-full h-full flex flex-col justify-center items-center"> |
63 | <DeviceName :config="config" /> | 77 | <DeviceName :config="config" /> |
64 | - <div class="flex-1 flex justify-center items-center flex-col"> | 78 | + <div class="flex-1 flex justify-center items-center flex-col w-full"> |
65 | <SvgIcon | 79 | <SvgIcon |
66 | :name="getDesign.icon!" | 80 | :name="getDesign.icon!" |
67 | prefix="iconfont" | 81 | prefix="iconfont" |
@@ -69,7 +83,7 @@ | @@ -69,7 +83,7 @@ | ||
69 | :style="{ color: getDesign.iconColor }" | 83 | :style="{ color: getDesign.iconColor }" |
70 | /> | 84 | /> |
71 | <h1 | 85 | <h1 |
72 | - class="font-bold m-2 truncate" | 86 | + class="font-bold m-2 truncate w-full text-center" |
73 | :style="{ | 87 | :style="{ |
74 | color: getDesign.fontColor, | 88 | color: getDesign.fontColor, |
75 | fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px', | 89 | fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px', |
@@ -2,12 +2,14 @@ | @@ -2,12 +2,14 @@ | ||
2 | import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; | 2 | import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; |
3 | import { option } from './config'; | 3 | import { option } from './config'; |
4 | import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale'; | 4 | import { useComponentScale } from '/@/views/visual/packages/hook/useComponentScale'; |
5 | - import { computed } from 'vue'; | 5 | + import { computed, unref } from 'vue'; |
6 | import { ref } from 'vue'; | 6 | import { ref } from 'vue'; |
7 | import { SvgIcon } from '/@/components/Icon'; | 7 | import { SvgIcon } from '/@/components/Icon'; |
8 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; | 8 | import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; |
9 | import { useDataFetch } from '../../../hook/socket/useSocket'; | 9 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
10 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 10 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
11 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
12 | + import { useThingsModelValueTransform } from '/@/views/visual/palette/hooks/useThingsModelValueTransform'; | ||
11 | 13 | ||
12 | const props = defineProps<{ | 14 | const props = defineProps<{ |
13 | config: ComponentPropsConfigType<typeof option>; | 15 | config: ComponentPropsConfigType<typeof option>; |
@@ -15,6 +17,15 @@ | @@ -15,6 +17,15 @@ | ||
15 | 17 | ||
16 | const currentValue = ref<string | number>(123); | 18 | const currentValue = ref<string | number>(123); |
17 | 19 | ||
20 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
21 | + | ||
22 | + const getThingModelTsl = computed(() => { | ||
23 | + const { option } = props.config; | ||
24 | + | ||
25 | + const { deviceProfileId, attribute } = option; | ||
26 | + return getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
27 | + }); | ||
28 | + | ||
18 | const getDesign = computed(() => { | 29 | const getDesign = computed(() => { |
19 | const { persetOption = {}, option } = props.config; | 30 | const { persetOption = {}, option } = props.config; |
20 | 31 | ||
@@ -27,7 +38,7 @@ | @@ -27,7 +38,7 @@ | ||
27 | fontSize: persetFontSize, | 38 | fontSize: persetFontSize, |
28 | } = persetOption; | 39 | } = persetOption; |
29 | 40 | ||
30 | - const { componentInfo, attribute, attributeRename, attributeName } = option; | 41 | + const { componentInfo, attribute, attributeRename } = option; |
31 | 42 | ||
32 | const { icon, iconColor, fontColor, unit, valueSize, fontSize } = componentInfo || {}; | 43 | const { icon, iconColor, fontColor, unit, valueSize, fontSize } = componentInfo || {}; |
33 | return { | 44 | return { |
@@ -35,7 +46,7 @@ | @@ -35,7 +46,7 @@ | ||
35 | unit: unit ?? perseUnit, | 46 | unit: unit ?? perseUnit, |
36 | icon: icon || persetIcon, | 47 | icon: icon || persetIcon, |
37 | fontColor: fontColor || persetFontColor, | 48 | fontColor: fontColor || persetFontColor, |
38 | - attribute: attributeRename || attributeName || attribute, | 49 | + attribute: attributeRename || unref(getThingModelTsl)?.functionName || attribute, |
39 | valueSize: valueSize || persetValueSize || 20, | 50 | valueSize: valueSize || persetValueSize || 20, |
40 | fontSize: fontSize || persetFontSize || 14, | 51 | fontSize: fontSize || persetFontSize || 14, |
41 | }; | 52 | }; |
@@ -46,7 +57,10 @@ | @@ -46,7 +57,10 @@ | ||
46 | const [info] = data[attribute] || []; | 57 | const [info] = data[attribute] || []; |
47 | if (!info.length) return; | 58 | if (!info.length) return; |
48 | const [_, value] = info; | 59 | const [_, value] = info; |
49 | - currentValue.value = value; | 60 | + currentValue.value = useThingsModelValueTransform( |
61 | + value, | ||
62 | + unref(getThingModelTsl)?.specs?.dataType | ||
63 | + ); | ||
50 | }; | 64 | }; |
51 | 65 | ||
52 | useDataFetch(props, updateFn); | 66 | useDataFetch(props, updateFn); |
@@ -57,7 +71,7 @@ | @@ -57,7 +71,7 @@ | ||
57 | <template> | 71 | <template> |
58 | <main class="w-full h-full flex flex-col justify-center items-center"> | 72 | <main class="w-full h-full flex flex-col justify-center items-center"> |
59 | <DeviceName :config="config" /> | 73 | <DeviceName :config="config" /> |
60 | - <div :style="getScale" class="flex-1 flex justify-center items-center flex-col"> | 74 | + <div :style="getScale" class="flex-1 flex justify-center items-center flex-col w-full"> |
61 | <SvgIcon | 75 | <SvgIcon |
62 | :name="getDesign.icon!" | 76 | :name="getDesign.icon!" |
63 | prefix="iconfont" | 77 | prefix="iconfont" |
@@ -65,7 +79,7 @@ | @@ -65,7 +79,7 @@ | ||
65 | :style="{ color: getDesign.iconColor }" | 79 | :style="{ color: getDesign.iconColor }" |
66 | /> | 80 | /> |
67 | <h1 | 81 | <h1 |
68 | - class="my-4 font-bold !my-2 truncate" | 82 | + class="my-4 font-bold !my-2 truncate w-full text-center" |
69 | :style="{ | 83 | :style="{ |
70 | color: getDesign.fontColor, | 84 | color: getDesign.fontColor, |
71 | fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px', | 85 | fontSize: (getRatio ? getRatio * getDesign.valueSize : getDesign.valueSize) + 'px', |
@@ -10,6 +10,7 @@ | @@ -10,6 +10,7 @@ | ||
10 | import { useMultipleDataFetch } from '../../../hook/socket/useSocket'; | 10 | import { useMultipleDataFetch } from '../../../hook/socket/useSocket'; |
11 | import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 11 | import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
12 | import { useComponentScale } from '../../../hook/useComponentScale'; | 12 | import { useComponentScale } from '../../../hook/useComponentScale'; |
13 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
13 | 14 | ||
14 | const props = defineProps<{ | 15 | const props = defineProps<{ |
15 | config: ComponentPropsConfigType<typeof option>; | 16 | config: ComponentPropsConfigType<typeof option>; |
@@ -56,6 +57,8 @@ | @@ -56,6 +57,8 @@ | ||
56 | }, | 57 | }, |
57 | ]; | 58 | ]; |
58 | 59 | ||
60 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
61 | + | ||
59 | const getDesign = computed(() => { | 62 | const getDesign = computed(() => { |
60 | const { persetOption = {}, option } = props.config; | 63 | const { persetOption = {}, option } = props.config; |
61 | const { dataSource = [] } = option || {}; | 64 | const { dataSource = [] } = option || {}; |
@@ -71,15 +74,17 @@ | @@ -71,15 +74,17 @@ | ||
71 | dataSource: dataSource.map((item) => { | 74 | dataSource: dataSource.map((item) => { |
72 | const { unit, fontColor, backgroundColor, maxNumber, valueSize, fontSize } = | 75 | const { unit, fontColor, backgroundColor, maxNumber, valueSize, fontSize } = |
73 | item.componentInfo || {}; | 76 | item.componentInfo || {}; |
74 | - const { attribute, attributeRename, deviceName, deviceRename, deviceId, attributeName } = | 77 | + const { attribute, attributeRename, deviceProfileId, deviceName, deviceRename, deviceId } = |
75 | item; | 78 | item; |
79 | + | ||
80 | + const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
76 | return { | 81 | return { |
77 | unit: unit ?? presetUnit, | 82 | unit: unit ?? presetUnit, |
78 | fontColor: fontColor ?? presetFontColor, | 83 | fontColor: fontColor ?? presetFontColor, |
79 | backgroundColor: backgroundColor ?? persetBackgroundColor, | 84 | backgroundColor: backgroundColor ?? persetBackgroundColor, |
80 | deviceName: deviceRename || deviceName, | 85 | deviceName: deviceRename || deviceName, |
81 | attribute, | 86 | attribute, |
82 | - attributeName: attributeRename || attributeName, | 87 | + attributeName: attributeRename || tsl?.functionName, |
83 | maxNumber: maxNumber || persetMaxNumber, | 88 | maxNumber: maxNumber || persetMaxNumber, |
84 | id: deviceId, | 89 | id: deviceId, |
85 | valueSize: valueSize || persetValueSize || 20, | 90 | valueSize: valueSize || persetValueSize || 20, |
@@ -10,6 +10,8 @@ | @@ -10,6 +10,8 @@ | ||
10 | import { useMultipleDataFetch } from '../../../hook/socket/useSocket'; | 10 | import { useMultipleDataFetch } from '../../../hook/socket/useSocket'; |
11 | import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 11 | import { MultipleDataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
12 | import { useComponentScale } from '../../../hook/useComponentScale'; | 12 | import { useComponentScale } from '../../../hook/useComponentScale'; |
13 | + import { useDeviceProfileQueryContext } from '/@/views/visual/palette/hooks/useDeviceProfileQueryContext'; | ||
14 | + import { buildUUID } from '/@/utils/uuid'; | ||
13 | 15 | ||
14 | const props = defineProps<{ | 16 | const props = defineProps<{ |
15 | config: ComponentPropsConfigType<typeof option>; | 17 | config: ComponentPropsConfigType<typeof option>; |
@@ -17,6 +19,8 @@ | @@ -17,6 +19,8 @@ | ||
17 | 19 | ||
18 | const time = ref<Nullable<number>>(null); | 20 | const time = ref<Nullable<number>>(null); |
19 | 21 | ||
22 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
23 | + | ||
20 | const getDesign = computed(() => { | 24 | const getDesign = computed(() => { |
21 | const { persetOption = {}, option } = props.config; | 25 | const { persetOption = {}, option } = props.config; |
22 | const { dataSource = [] } = option || {}; | 26 | const { dataSource = [] } = option || {}; |
@@ -28,12 +32,13 @@ | @@ -28,12 +32,13 @@ | ||
28 | valueSize: persetValueSize, | 32 | valueSize: persetValueSize, |
29 | fontSize: persetFontSize, | 33 | fontSize: persetFontSize, |
30 | } = persetOption || {}; | 34 | } = persetOption || {}; |
35 | + | ||
31 | return { | 36 | return { |
32 | dataSource: dataSource.map((item) => { | 37 | dataSource: dataSource.map((item) => { |
33 | const { fontColor, icon, iconColor, unit, valueSize, fontSize } = item.componentInfo; | 38 | const { fontColor, icon, iconColor, unit, valueSize, fontSize } = item.componentInfo; |
34 | - const { attribute, attributeRename, deviceName, deviceRename, deviceId, attributeName } = | 39 | + const { attribute, attributeRename, deviceName, deviceRename, deviceId, deviceProfileId } = |
35 | item; | 40 | item; |
36 | - | 41 | + const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); |
37 | return { | 42 | return { |
38 | unit: unit ?? persetUnit, | 43 | unit: unit ?? persetUnit, |
39 | fontColor: fontColor ?? persetFontColor, | 44 | fontColor: fontColor ?? persetFontColor, |
@@ -41,7 +46,7 @@ | @@ -41,7 +46,7 @@ | ||
41 | iconColor: iconColor ?? persetIconColor, | 46 | iconColor: iconColor ?? persetIconColor, |
42 | attribute, | 47 | attribute, |
43 | deviceName: deviceRename || deviceName, | 48 | deviceName: deviceRename || deviceName, |
44 | - attributeName: attributeRename || attributeName, | 49 | + attributeName: attributeRename || tsl?.functionName, |
45 | id: deviceId, | 50 | id: deviceId, |
46 | valueSize: valueSize || persetValueSize || 20, | 51 | valueSize: valueSize || persetValueSize || 20, |
47 | fontSize: fontSize || persetFontSize || 14, | 52 | fontSize: fontSize || persetFontSize || 14, |
@@ -49,8 +54,10 @@ | @@ -49,8 +54,10 @@ | ||
49 | }), | 54 | }), |
50 | }; | 55 | }; |
51 | }); | 56 | }); |
52 | - const defaultSvgList = ref<any>([ | 57 | + |
58 | + const defaultSvgList = ref([ | ||
53 | { | 59 | { |
60 | + id: buildUUID(), | ||
54 | value: 26.2, | 61 | value: 26.2, |
55 | deviceName: '温湿度', | 62 | deviceName: '温湿度', |
56 | attributeName: '温度', | 63 | attributeName: '温度', |
@@ -58,8 +65,11 @@ | @@ -58,8 +65,11 @@ | ||
58 | unit: '℃', | 65 | unit: '℃', |
59 | iconColor: '#367BFF', | 66 | iconColor: '#367BFF', |
60 | fontColor: '#357CFB', | 67 | fontColor: '#357CFB', |
68 | + fontSize: 16, | ||
69 | + valueSize: 16, | ||
61 | }, | 70 | }, |
62 | { | 71 | { |
72 | + id: buildUUID(), | ||
63 | value: 53.7, | 73 | value: 53.7, |
64 | deviceName: '温湿度', | 74 | deviceName: '温湿度', |
65 | attributeName: '湿度', | 75 | attributeName: '湿度', |
@@ -67,6 +77,8 @@ | @@ -67,6 +77,8 @@ | ||
67 | unit: '℃', | 77 | unit: '℃', |
68 | iconColor: '#FFA000', | 78 | iconColor: '#FFA000', |
69 | fontColor: '#FFA000', | 79 | fontColor: '#FFA000', |
80 | + fontSize: 16, | ||
81 | + valueSize: 16, | ||
70 | }, | 82 | }, |
71 | ]); | 83 | ]); |
72 | 84 | ||
@@ -108,7 +120,6 @@ | @@ -108,7 +120,6 @@ | ||
108 | :size="getRatio ? 30 * getRatio : 30" | 120 | :size="getRatio ? 30 * getRatio : 30" |
109 | :style="{ color: item.iconColor }" | 121 | :style="{ color: item.iconColor }" |
110 | /> | 122 | /> |
111 | - | ||
112 | <div | 123 | <div |
113 | class="text-gray-500 ml-6" | 124 | class="text-gray-500 ml-6" |
114 | :style="{ fontSize: (getRatio ? getRatio * item.fontSize : item.fontSize) + 'px' }" | 125 | :style="{ fontSize: (getRatio ? getRatio * item.fontSize : item.fontSize) + 'px' }" |
@@ -122,10 +133,9 @@ | @@ -122,10 +133,9 @@ | ||
122 | fontSize: (getRatio ? getRatio * item.valueSize : item.valueSize) + 'px', | 133 | fontSize: (getRatio ? getRatio * item.valueSize : item.valueSize) + 'px', |
123 | }" | 134 | }" |
124 | > | 135 | > |
125 | - <span> {{ item.value || 0 }}</span> | 136 | + <span> {{ (item as any).value || 0 }}</span> |
126 | <span>{{ item.unit }} </span> | 137 | <span>{{ item.unit }} </span> |
127 | </span> | 138 | </span> |
128 | </div> | 139 | </div> |
129 | - <!-- <UpdateTime :time="time" /> --> | ||
130 | </main> | 140 | </main> |
131 | </template> | 141 | </template> |
@@ -3,21 +3,25 @@ import { useSelectWidgetKeys, useSelectWidgetMode } from '../../dataSourceBindPa | @@ -3,21 +3,25 @@ import { useSelectWidgetKeys, useSelectWidgetMode } from '../../dataSourceBindPa | ||
3 | import { PackagesCategoryEnum } from '../index.type'; | 3 | import { PackagesCategoryEnum } from '../index.type'; |
4 | import { getDeviceProfile } from '/@/api/alarm/position'; | 4 | import { getDeviceProfile } from '/@/api/alarm/position'; |
5 | import { getDeviceAttributes, getMeetTheConditionsDevice } from '/@/api/dataBoard'; | 5 | import { getDeviceAttributes, getMeetTheConditionsDevice } from '/@/api/dataBoard'; |
6 | -import { DeviceAttributeParams, MasterDeviceList } from '/@/api/dataBoard/model'; | ||
7 | -import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | ||
8 | -import { ModelOfMatterParams } from '/@/api/device/model/modelOfMatterModel'; | 6 | +import { DeviceAttributeParams } from '/@/api/dataBoard/model'; |
9 | import { getModelServices } from '/@/api/device/modelOfMatter'; | 7 | import { getModelServices } from '/@/api/device/modelOfMatter'; |
10 | import { findDictItemByCode } from '/@/api/system/dict'; | 8 | import { findDictItemByCode } from '/@/api/system/dict'; |
11 | -import { FormSchema, useComponentRegister } from '/@/components/Form'; | 9 | +import { ApiCascader, FormSchema, useComponentRegister } from '/@/components/Form'; |
12 | import { OrgTreeSelect } from '/@/views/common/OrgTreeSelect'; | 10 | import { OrgTreeSelect } from '/@/views/common/OrgTreeSelect'; |
13 | import { DataActionModeEnum } from '/@/enums/toolEnum'; | 11 | import { DataActionModeEnum } from '/@/enums/toolEnum'; |
14 | import { TaskTypeEnum } from '/@/views/task/center/config'; | 12 | import { TaskTypeEnum } from '/@/views/task/center/config'; |
15 | import { createPickerSearch } from '/@/utils/pickerSearch'; | 13 | import { createPickerSearch } from '/@/utils/pickerSearch'; |
16 | import { DataTypeEnum } from '/@/enums/objectModelEnum'; | 14 | import { DataTypeEnum } from '/@/enums/objectModelEnum'; |
17 | -import { CommandTypeEnum } from '/@/enums/deviceEnum'; | 15 | +import { CommandTypeEnum, CommandTypeNameEnum } from '/@/enums/deviceEnum'; |
18 | import { TransportTypeEnum } from '/@/enums/deviceEnum'; | 16 | import { TransportTypeEnum } from '/@/enums/deviceEnum'; |
17 | +import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | ||
18 | +import { ControlComponentEnum } from '../components/Control'; | ||
19 | +import { isNullOrUnDef } from '/@/utils/is'; | ||
20 | +import { validateTCPCustomCommand } from '/@/components/Form/src/components/ThingsModelForm'; | ||
21 | +import { CategoryEnum } from '../components'; | ||
19 | 22 | ||
20 | useComponentRegister('OrgTreeSelect', OrgTreeSelect); | 23 | useComponentRegister('OrgTreeSelect', OrgTreeSelect); |
24 | +useComponentRegister('ApiCascader', ApiCascader); | ||
21 | 25 | ||
22 | export interface CommonDataSourceBindValueType extends Record<DataSourceField, string> { | 26 | export interface CommonDataSourceBindValueType extends Record<DataSourceField, string> { |
23 | customCommand?: { | 27 | customCommand?: { |
@@ -31,30 +35,51 @@ export interface CommonDataSourceBindValueType extends Record<DataSourceField, s | @@ -31,30 +35,51 @@ export interface CommonDataSourceBindValueType extends Record<DataSourceField, s | ||
31 | } | 35 | } |
32 | 36 | ||
33 | export enum DataSourceField { | 37 | export enum DataSourceField { |
34 | - IS_GATEWAY_DEVICE = 'gatewayDevice', | 38 | + // IS_GATEWAY_DEVICE = 'gatewayDevice', |
35 | DEVICE_TYPE = 'deviceType', | 39 | DEVICE_TYPE = 'deviceType', |
36 | TRANSPORT_TYPE = 'transportType', | 40 | TRANSPORT_TYPE = 'transportType', |
37 | ORIGINATION_ID = 'organizationId', | 41 | ORIGINATION_ID = 'organizationId', |
38 | DEVICE_ID = 'deviceId', | 42 | DEVICE_ID = 'deviceId', |
39 | - DEVICE_CODE = 'deviceCode', //设备地址码 | 43 | + // DEVICE_CODE = 'deviceCode', //设备地址码 |
40 | DEVICE_PROFILE_ID = 'deviceProfileId', | 44 | DEVICE_PROFILE_ID = 'deviceProfileId', |
41 | ATTRIBUTE = 'attribute', | 45 | ATTRIBUTE = 'attribute', |
42 | - ATTRIBUTE_NAME = 'attributeName', | 46 | + // ATTRIBUTE_NAME = 'attributeName', |
43 | ATTRIBUTE_RENAME = 'attributeRename', | 47 | ATTRIBUTE_RENAME = 'attributeRename', |
44 | DEVICE_NAME = 'deviceName', | 48 | DEVICE_NAME = 'deviceName', |
45 | DEVICE_RENAME = 'deviceRename', | 49 | DEVICE_RENAME = 'deviceRename', |
46 | - LONGITUDE_ATTRIBUTE = 'longitudeAttribute', | ||
47 | - LATITUDE_ATTRIBUTE = 'latitudeAttribute', | 50 | + |
48 | CODE_TYPE = 'codeType', | 51 | CODE_TYPE = 'codeType', |
49 | - COMMAND = 'command', | 52 | + // COMMAND = 'command', |
53 | + | ||
50 | OPEN_COMMAND = 'openCommand', | 54 | OPEN_COMMAND = 'openCommand', |
51 | CLOSE_COMMAND = 'closeCommand', | 55 | CLOSE_COMMAND = 'closeCommand', |
56 | + | ||
52 | COMMAND_TYPE = 'commandType', | 57 | COMMAND_TYPE = 'commandType', |
53 | - SERVICE = 'service', | 58 | + |
59 | + // SERVICE = 'service', | ||
60 | + | ||
61 | + /** | ||
62 | + * @description 关服务标识符 | ||
63 | + */ | ||
54 | OPEN_SERVICE = 'openService', | 64 | OPEN_SERVICE = 'openService', |
65 | + | ||
66 | + /** | ||
67 | + * @description 开服务标识符 | ||
68 | + */ | ||
55 | CLOSE_SERVICE = 'closeService', | 69 | CLOSE_SERVICE = 'closeService', |
56 | - EXTENSION_DESC = 'extensionDesc', | ||
57 | - CALL_TYPE = 'callType', | 70 | + |
71 | + /** | ||
72 | + * @description 经度标识符 | ||
73 | + */ | ||
74 | + LONGITUDE_IDENTIFIER = 'longitudeIdentifier', | ||
75 | + | ||
76 | + /** | ||
77 | + * @description 纬度标识符号 | ||
78 | + */ | ||
79 | + LATITUDE_IDENTIFIER = 'latitudeIdentifier', | ||
80 | + | ||
81 | + // EXTENSION_DESC = 'extensionDesc', | ||
82 | + // CALL_TYPE = 'callType', | ||
58 | } | 83 | } |
59 | 84 | ||
60 | const isTcpProfile = (transportType: string) => transportType === TransportTypeEnum.TCP; | 85 | const isTcpProfile = (transportType: string) => transportType === TransportTypeEnum.TCP; |
@@ -69,15 +94,6 @@ const isBooleanComponent = (componentKeys: { categoryKey?: string; componentKey? | @@ -69,15 +94,6 @@ const isBooleanComponent = (componentKeys: { categoryKey?: string; componentKey? | ||
69 | ); | 94 | ); |
70 | }; | 95 | }; |
71 | 96 | ||
72 | -const getDeviceService = async (deviceProfileId: string) => { | ||
73 | - try { | ||
74 | - const data = await getModelServices({ deviceProfileId }); | ||
75 | - if (data) | ||
76 | - return data.map((item) => ({ ...item, label: item.functionName, value: item.identifier })); | ||
77 | - } catch (error) {} | ||
78 | - return []; | ||
79 | -}; | ||
80 | - | ||
81 | const getDeviceAttribute = async (params: DeviceAttributeParams) => { | 97 | const getDeviceAttribute = async (params: DeviceAttributeParams) => { |
82 | try { | 98 | try { |
83 | const data = await getDeviceAttributes(params); | 99 | const data = await getDeviceAttributes(params); |
@@ -94,24 +110,6 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -94,24 +110,6 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
94 | 110 | ||
95 | return [ | 111 | return [ |
96 | { | 112 | { |
97 | - field: DataSourceField.IS_GATEWAY_DEVICE, | ||
98 | - component: 'Switch', | ||
99 | - label: '是否是网关设备', | ||
100 | - show: false, | ||
101 | - }, | ||
102 | - { | ||
103 | - field: DataSourceField.DEVICE_NAME, | ||
104 | - component: 'Input', | ||
105 | - label: '设备名', | ||
106 | - show: false, | ||
107 | - }, | ||
108 | - { | ||
109 | - field: DataSourceField.TRANSPORT_TYPE, | ||
110 | - component: 'Input', | ||
111 | - label: '设备配置类型', | ||
112 | - show: false, | ||
113 | - }, | ||
114 | - { | ||
115 | field: DataSourceField.DEVICE_TYPE, | 113 | field: DataSourceField.DEVICE_TYPE, |
116 | component: 'ApiSelect', | 114 | component: 'ApiSelect', |
117 | label: '设备类型', | 115 | label: '设备类型', |
@@ -127,13 +125,11 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -127,13 +125,11 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
127 | valueField: 'itemValue', | 125 | valueField: 'itemValue', |
128 | labelField: 'itemText', | 126 | labelField: 'itemText', |
129 | placeholder: '请选择设备类型', | 127 | placeholder: '请选择设备类型', |
130 | - onChange: (value: DeviceTypeEnum) => { | 128 | + onChange: () => { |
131 | setFieldsValue({ | 129 | setFieldsValue({ |
132 | - [DataSourceField.IS_GATEWAY_DEVICE]: value === DeviceTypeEnum.GATEWAY, | ||
133 | [DataSourceField.DEVICE_PROFILE_ID]: null, | 130 | [DataSourceField.DEVICE_PROFILE_ID]: null, |
134 | [DataSourceField.DEVICE_ID]: null, | 131 | [DataSourceField.DEVICE_ID]: null, |
135 | [DataSourceField.ATTRIBUTE]: null, | 132 | [DataSourceField.ATTRIBUTE]: null, |
136 | - [DataSourceField.ATTRIBUTE_NAME]: null, | ||
137 | [DataSourceField.TRANSPORT_TYPE]: null, | 133 | [DataSourceField.TRANSPORT_TYPE]: null, |
138 | }); | 134 | }); |
139 | }, | 135 | }, |
@@ -142,6 +138,12 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -142,6 +138,12 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
142 | }, | 138 | }, |
143 | }, | 139 | }, |
144 | { | 140 | { |
141 | + field: DataSourceField.TRANSPORT_TYPE, | ||
142 | + label: '传输协议', | ||
143 | + component: 'Input', | ||
144 | + ifShow: false, | ||
145 | + }, | ||
146 | + { | ||
145 | field: DataSourceField.DEVICE_PROFILE_ID, | 147 | field: DataSourceField.DEVICE_PROFILE_ID, |
146 | component: 'ApiSelect', | 148 | component: 'ApiSelect', |
147 | label: '产品', | 149 | label: '产品', |
@@ -164,12 +166,11 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -164,12 +166,11 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
164 | labelField: 'name', | 166 | labelField: 'name', |
165 | valueField: 'id', | 167 | valueField: 'id', |
166 | placeholder: '请选择产品', | 168 | placeholder: '请选择产品', |
167 | - onChange: (_, option = {} as Record<'transportType', string>) => { | 169 | + onChange: (_, option: Record<'transportType', string>) => { |
168 | setFieldsValue({ | 170 | setFieldsValue({ |
169 | [DataSourceField.DEVICE_ID]: null, | 171 | [DataSourceField.DEVICE_ID]: null, |
170 | [DataSourceField.ATTRIBUTE]: null, | 172 | [DataSourceField.ATTRIBUTE]: null, |
171 | - [DataSourceField.ATTRIBUTE_NAME]: null, | ||
172 | - [DataSourceField.TRANSPORT_TYPE]: option[DataSourceField.TRANSPORT_TYPE], | 173 | + [DataSourceField.TRANSPORT_TYPE]: option?.[DataSourceField.TRANSPORT_TYPE], |
173 | [DataSourceField.COMMAND_TYPE]: null, | 174 | [DataSourceField.COMMAND_TYPE]: null, |
174 | }); | 175 | }); |
175 | }, | 176 | }, |
@@ -201,10 +202,10 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -201,10 +202,10 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
201 | }, | 202 | }, |
202 | }, | 203 | }, |
203 | { | 204 | { |
204 | - field: DataSourceField.DEVICE_PROFILE_ID, | 205 | + field: DataSourceField.DEVICE_NAME, |
205 | component: 'Input', | 206 | component: 'Input', |
206 | - label: '', | ||
207 | - show: false, | 207 | + label: '设备名称', |
208 | + ifShow: false, | ||
208 | }, | 209 | }, |
209 | { | 210 | { |
210 | field: DataSourceField.DEVICE_ID, | 211 | field: DataSourceField.DEVICE_ID, |
@@ -238,12 +239,11 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -238,12 +239,11 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
238 | } | 239 | } |
239 | return []; | 240 | return []; |
240 | }, | 241 | }, |
241 | - onChange(_value, record: MasterDeviceList) { | 242 | + onChange(_value, options: Record<'label' | 'codeType', string>) { |
242 | setFieldsValue({ | 243 | setFieldsValue({ |
243 | - [DataSourceField.DEVICE_NAME]: record?.label, | ||
244 | - [DataSourceField.CODE_TYPE]: record?.codeType, | ||
245 | - [DataSourceField.DEVICE_CODE]: record?.code, | ||
246 | [DataSourceField.COMMAND_TYPE]: null, | 244 | [DataSourceField.COMMAND_TYPE]: null, |
245 | + [DataSourceField.DEVICE_NAME]: options?.label, | ||
246 | + [DataSourceField.CODE_TYPE]: options?.codeType, | ||
247 | }); | 247 | }); |
248 | }, | 248 | }, |
249 | placeholder: '请选择设备', | 249 | placeholder: '请选择设备', |
@@ -253,91 +253,9 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -253,91 +253,9 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
253 | }, | 253 | }, |
254 | { | 254 | { |
255 | field: DataSourceField.CODE_TYPE, | 255 | field: DataSourceField.CODE_TYPE, |
256 | + label: '设备标识符类型', | ||
256 | component: 'Input', | 257 | component: 'Input', |
257 | - label: '设备标识符', | ||
258 | - show: false, | ||
259 | - }, | ||
260 | - | ||
261 | - { | ||
262 | - field: DataSourceField.DEVICE_CODE, | ||
263 | - component: 'Input', | ||
264 | - show: false, | ||
265 | - label: '设备地址码', | ||
266 | - }, | ||
267 | - | ||
268 | - { | ||
269 | - field: DataSourceField.ATTRIBUTE_NAME, | ||
270 | - component: 'Input', | ||
271 | - label: '属性名', | ||
272 | - show: false, | ||
273 | - }, | ||
274 | - { | ||
275 | - field: DataSourceField.COMMAND_TYPE, | ||
276 | - component: 'ApiSelect', | ||
277 | - label: '命令类型', | ||
278 | - defaultValue: CommandTypeEnum.CUSTOM.toString(), | ||
279 | - rules: [{ required: true, message: '请选择命令类型' }], | ||
280 | - colProps: { span: 8 }, | ||
281 | - ifShow: ({ model }) => { | ||
282 | - return isControlComponent(category!) && isTcpProfile(model[DataSourceField.TRANSPORT_TYPE]); | ||
283 | - }, | ||
284 | - componentProps: ({ formActionType, formModel }) => { | ||
285 | - const { setFieldsValue } = formActionType; | ||
286 | - const { codeType, deviceType, transportType } = formModel || {}; | ||
287 | - return { | ||
288 | - // api: findDictItemByCode, | ||
289 | - api: async (params: Recordable) => { | ||
290 | - try { | ||
291 | - const record = await findDictItemByCode(params); | ||
292 | - if (unref(selectWidgetKeys).componentKey == 'LateralNumericalControl') { | ||
293 | - return record.filter( | ||
294 | - (item) => item.itemValue == CommandTypeEnum.ATTRIBUTE.toString() | ||
295 | - ); | ||
296 | - } | ||
297 | - // TCP网关子 --> 不能要服务命令类型 | ||
298 | - if (deviceType == 'SENSOR' && transportType == 'TCP') { | ||
299 | - return codeType == 'MODBUS_RTU' | ||
300 | - ? record.filter((item) => item.itemValue == CommandTypeEnum.ATTRIBUTE.toString()) | ||
301 | - : codeType == 'CUSTOM' | ||
302 | - ? record.filter((item) => item.itemValue == CommandTypeEnum.CUSTOM.toString()) | ||
303 | - : []; | ||
304 | - } | ||
305 | - | ||
306 | - if (codeType == TaskTypeEnum.MODBUS_RTU) { | ||
307 | - // setFieldsValue({ [DataSourceField.COMMAND_TYPE]: undefined }); | ||
308 | - return record.filter( | ||
309 | - (item) => item.itemValue !== CommandTypeEnum.CUSTOM.toString() | ||
310 | - ); | ||
311 | - } else { | ||
312 | - return record.filter( | ||
313 | - (item) => item.itemValue !== CommandTypeEnum.ATTRIBUTE.toString() | ||
314 | - ); | ||
315 | - } | ||
316 | - } catch (error) { | ||
317 | - return []; | ||
318 | - } | ||
319 | - }, | ||
320 | - params: { | ||
321 | - dictCode: 'custom_define', | ||
322 | - }, | ||
323 | - labelField: 'itemText', | ||
324 | - valueField: 'itemValue', | ||
325 | - placeholder: '请选择命令类型', | ||
326 | - getPopupContainer: () => document.body, | ||
327 | - onChange() { | ||
328 | - setFieldsValue({ | ||
329 | - [DataSourceField.COMMAND]: null, | ||
330 | - [DataSourceField.SERVICE]: null, | ||
331 | - [DataSourceField.OPEN_COMMAND]: null, | ||
332 | - [DataSourceField.CLOSE_COMMAND]: null, | ||
333 | - [DataSourceField.OPEN_SERVICE]: null, | ||
334 | - [DataSourceField.CLOSE_SERVICE]: null, | ||
335 | - [DataSourceField.CALL_TYPE]: null, | ||
336 | - [DataSourceField.ATTRIBUTE]: null, | ||
337 | - }); | ||
338 | - }, | ||
339 | - }; | ||
340 | - }, | 258 | + ifShow: false, |
341 | }, | 259 | }, |
342 | { | 260 | { |
343 | field: DataSourceField.ATTRIBUTE, | 261 | field: DataSourceField.ATTRIBUTE, |
@@ -345,9 +263,7 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -345,9 +263,7 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
345 | label: '属性', | 263 | label: '属性', |
346 | colProps: { span: 8 }, | 264 | colProps: { span: 8 }, |
347 | rules: [{ required: true, message: '请选择属性' }], | 265 | rules: [{ required: true, message: '请选择属性' }], |
348 | - ifShow: ({ model }) => | ||
349 | - !(isTcpProfile(model[DataSourceField.TRANSPORT_TYPE]) && isControlComponent(category!)) || | ||
350 | - model[DataSourceField.COMMAND_TYPE] == 2, | 266 | + ifShow: () => category !== CategoryEnum.MAP, |
351 | componentProps({ formModel, formActionType }) { | 267 | componentProps({ formModel, formActionType }) { |
352 | const { setFieldsValue } = formActionType; | 268 | const { setFieldsValue } = formActionType; |
353 | const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; | 269 | const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; |
@@ -359,20 +275,25 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -359,20 +275,25 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
359 | deviceProfileId, | 275 | deviceProfileId, |
360 | dataType: | 276 | dataType: |
361 | (isControlComponent(category!) && | 277 | (isControlComponent(category!) && |
362 | - unref(selectWidgetKeys).componentKey !== 'LateralNumericalControl') || | 278 | + unref(selectWidgetKeys).componentKey !== |
279 | + ControlComponentEnum.LATERAL_NUMERICAL_CONTROL) || | ||
363 | isBooleanComponent(unref(selectWidgetKeys)) | 280 | isBooleanComponent(unref(selectWidgetKeys)) |
364 | ? DataTypeEnum.BOOL | 281 | ? DataTypeEnum.BOOL |
365 | : undefined, | 282 | : undefined, |
366 | }); | 283 | }); |
367 | 284 | ||
368 | // 选择控制组件4的时候只能选择属性且是(int double类型) | 285 | // 选择控制组件4的时候只能选择属性且是(int double类型) |
369 | - if (unref(selectWidgetKeys).componentKey == 'LateralNumericalControl') { | 286 | + if ( |
287 | + unref(selectWidgetKeys).componentKey === | ||
288 | + ControlComponentEnum.LATERAL_NUMERICAL_CONTROL | ||
289 | + ) { | ||
370 | setFieldsValue({ | 290 | setFieldsValue({ |
371 | [DataSourceField.COMMAND_TYPE]: CommandTypeEnum.ATTRIBUTE.toString(), | 291 | [DataSourceField.COMMAND_TYPE]: CommandTypeEnum.ATTRIBUTE.toString(), |
372 | }); | 292 | }); |
373 | return option.filter( | 293 | return option.filter( |
374 | (item) => | 294 | (item) => |
375 | - item.detail.dataType.type == 'INT' || item.detail.dataType.type == 'DOUBLE' | 295 | + item.detail.dataType.type === DataTypeEnum.NUMBER_INT || |
296 | + item.detail.dataType.type == DataTypeEnum.NUMBER_DOUBLE | ||
376 | ); | 297 | ); |
377 | } | 298 | } |
378 | return option; | 299 | return option; |
@@ -381,76 +302,133 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -381,76 +302,133 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
381 | return []; | 302 | return []; |
382 | }, | 303 | }, |
383 | placeholder: '请选择属性', | 304 | placeholder: '请选择属性', |
384 | - onChange(value: string, option: Record<'label' | 'value' | any, string>) { | ||
385 | - const { detail }: any = option || {}; | ||
386 | - setFieldsValue({ | ||
387 | - [DataSourceField.ATTRIBUTE_NAME]: value ? option.label : null, | ||
388 | - [DataSourceField.EXTENSION_DESC]: value ? JSON.stringify(option.extensionDesc) : '', | ||
389 | - // 地图组件结构体 | ||
390 | - lal: | ||
391 | - category === 'MAP' && value && detail?.dataType.type === 'STRUCT' | ||
392 | - ? JSON.stringify(detail?.dataType.specs) | ||
393 | - : null, | ||
394 | - latitude: null, | ||
395 | - longitude: null, | ||
396 | - }); | ||
397 | - }, | ||
398 | ...createPickerSearch(), | 305 | ...createPickerSearch(), |
399 | }; | 306 | }; |
400 | }, | 307 | }, |
401 | }, | 308 | }, |
402 | { | 309 | { |
403 | - field: 'lal', | ||
404 | - label: '经纬度存储的值', | ||
405 | - component: 'Input', | ||
406 | - show: false, | ||
407 | - }, | ||
408 | - { | ||
409 | - field: 'longitude', | 310 | + field: DataSourceField.LONGITUDE_IDENTIFIER, |
410 | label: '经度', | 311 | label: '经度', |
312 | + component: 'ApiCascader', | ||
313 | + ifShow: ({}) => category === CategoryEnum.MAP, | ||
411 | colProps: { span: 8 }, | 314 | colProps: { span: 8 }, |
412 | - component: 'Select', | ||
413 | - required: true, | ||
414 | - ifShow: ({ model }) => category === 'MAP' && model.lal, | ||
415 | - componentProps({ formModel }) { | ||
416 | - const { lal } = formModel || {}; | 315 | + changeEvent: 'update:value', |
316 | + valueField: 'value', | ||
317 | + componentProps: ({ formModel }) => { | ||
318 | + const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; | ||
417 | return { | 319 | return { |
320 | + api: async () => { | ||
321 | + try { | ||
322 | + if (deviceProfileId) { | ||
323 | + const options = await getDeviceAttributes({ | ||
324 | + deviceProfileId, | ||
325 | + }); | ||
326 | + | ||
327 | + const _options = options.map((item) => { | ||
328 | + item = Object.assign(item, { functionName: item.name }); | ||
329 | + if (item.detail.dataType.type === DataTypeEnum.STRUCT) { | ||
330 | + return Object.assign(item, { specs: item.detail.dataType.specs }); | ||
331 | + } | ||
332 | + return item; | ||
333 | + }); | ||
334 | + return _options; | ||
335 | + } | ||
336 | + } catch (error) {} | ||
337 | + return []; | ||
338 | + }, | ||
418 | placeholder: '请选择经度', | 339 | placeholder: '请选择经度', |
419 | - options: lal | ||
420 | - ? JSON.parse(lal)?.map((item) => ({ label: item.functionName, value: item.identifier })) | ||
421 | - : [], | 340 | + getPopupContainer: () => document.body, |
341 | + fieldNames: { label: 'functionName', value: 'identifier', children: 'specs' }, | ||
422 | }; | 342 | }; |
423 | }, | 343 | }, |
424 | }, | 344 | }, |
425 | { | 345 | { |
426 | - field: 'latitude', | 346 | + field: DataSourceField.LATITUDE_IDENTIFIER, |
427 | label: '纬度', | 347 | label: '纬度', |
348 | + component: 'ApiCascader', | ||
349 | + ifShow: ({}) => category === CategoryEnum.MAP, | ||
428 | colProps: { span: 8 }, | 350 | colProps: { span: 8 }, |
429 | - required: true, | ||
430 | - component: 'Select', | ||
431 | - ifShow: ({ model }) => category === 'MAP' && model.lal, | ||
432 | - componentProps({ formModel }) { | ||
433 | - const { lal } = formModel || {}; | 351 | + changeEvent: 'update:value', |
352 | + valueField: 'value', | ||
353 | + componentProps: ({ formModel }) => { | ||
354 | + const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; | ||
355 | + | ||
434 | return { | 356 | return { |
357 | + api: async () => { | ||
358 | + try { | ||
359 | + if (deviceProfileId) { | ||
360 | + const options = await getDeviceAttributes({ | ||
361 | + deviceProfileId, | ||
362 | + }); | ||
363 | + | ||
364 | + const _options = options.map((item) => { | ||
365 | + item = Object.assign(item, { functionName: item.name }); | ||
366 | + | ||
367 | + if (item.detail.dataType.type === DataTypeEnum.STRUCT) { | ||
368 | + return Object.assign(item, { specs: item.detail.dataType.specs }); | ||
369 | + } | ||
370 | + return item; | ||
371 | + }); | ||
372 | + | ||
373 | + return _options; | ||
374 | + } | ||
375 | + } catch (error) {} | ||
376 | + return []; | ||
377 | + }, | ||
435 | placeholder: '请选择纬度', | 378 | placeholder: '请选择纬度', |
436 | - options: lal | ||
437 | - ? JSON.parse(lal)?.map((item) => ({ label: item.functionName, value: item.identifier })) | ||
438 | - : [], | 379 | + getPopupContainer: () => document.body, |
380 | + fieldNames: { label: 'functionName', value: 'identifier', children: 'specs' }, | ||
439 | }; | 381 | }; |
440 | }, | 382 | }, |
441 | }, | 383 | }, |
442 | { | 384 | { |
443 | - field: DataSourceField.EXTENSION_DESC, | ||
444 | - component: 'Input', | ||
445 | - show: false, | ||
446 | - label: '扩展描述符', | ||
447 | - }, | 385 | + field: DataSourceField.COMMAND_TYPE, |
386 | + component: 'Select', | ||
387 | + label: '命令类型', | ||
388 | + defaultValue: CommandTypeEnum.CUSTOM, | ||
389 | + rules: [ | ||
390 | + { | ||
391 | + required: true, | ||
392 | + validator(_, value: number | string) { | ||
393 | + if (isNullOrUnDef(value)) return Promise.reject('请选择命令类型'); | ||
394 | + return Promise.resolve(); | ||
395 | + }, | ||
396 | + }, | ||
397 | + ], | ||
398 | + colProps: { span: 8 }, | ||
399 | + ifShow: ({ model }) => { | ||
400 | + return ( | ||
401 | + isControlComponent(category!) && | ||
402 | + unref(selectWidgetKeys).componentKey !== ControlComponentEnum.LATERAL_NUMERICAL_CONTROL && | ||
403 | + isTcpProfile(model[DataSourceField.TRANSPORT_TYPE]) && | ||
404 | + model[DataSourceField.CODE_TYPE] === TaskTypeEnum.CUSTOM | ||
405 | + ); | ||
406 | + }, | ||
407 | + componentProps: ({ formActionType, formModel }) => { | ||
408 | + const { setFieldsValue } = formActionType; | ||
409 | + const deviceType = formModel[DataSourceField.DEVICE_TYPE]; | ||
410 | + const options: Record<'label' | 'value', string | number>[] = [ | ||
411 | + { label: CommandTypeNameEnum.CUSTOM, value: CommandTypeEnum.CUSTOM }, | ||
412 | + ]; | ||
448 | 413 | ||
449 | - { | ||
450 | - field: DataSourceField.CALL_TYPE, | ||
451 | - component: 'Input', | ||
452 | - ifShow: false, | ||
453 | - label: 'callType', | 414 | + // 网关子设备无服务 |
415 | + if (deviceType !== DeviceTypeEnum.SENSOR) | ||
416 | + options.push({ label: CommandTypeNameEnum.SERVICE, value: CommandTypeEnum.SERVICE }); | ||
417 | + | ||
418 | + return { | ||
419 | + options, | ||
420 | + placeholder: '请选择命令类型', | ||
421 | + getPopupContainer: () => document.body, | ||
422 | + onChange() { | ||
423 | + setFieldsValue({ | ||
424 | + [DataSourceField.OPEN_COMMAND]: null, | ||
425 | + [DataSourceField.CLOSE_COMMAND]: null, | ||
426 | + [DataSourceField.OPEN_SERVICE]: null, | ||
427 | + [DataSourceField.CLOSE_SERVICE]: null, | ||
428 | + }); | ||
429 | + }, | ||
430 | + }; | ||
431 | + }, | ||
454 | }, | 432 | }, |
455 | { | 433 | { |
456 | field: DataSourceField.OPEN_SERVICE, | 434 | field: DataSourceField.OPEN_SERVICE, |
@@ -460,40 +438,19 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -460,40 +438,19 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
460 | rules: [{ required: true, message: '请选择开服务' }], | 438 | rules: [{ required: true, message: '请选择开服务' }], |
461 | ifShow: ({ model }) => | 439 | ifShow: ({ model }) => |
462 | isControlComponent(category!) && | 440 | isControlComponent(category!) && |
463 | - model[DataSourceField.COMMAND_TYPE] === CommandTypeEnum.SERVICE.toString() && | 441 | + model[DataSourceField.COMMAND_TYPE] === CommandTypeEnum.SERVICE && |
464 | isTcpProfile(model[DataSourceField.TRANSPORT_TYPE]), | 442 | isTcpProfile(model[DataSourceField.TRANSPORT_TYPE]), |
465 | - componentProps({ formModel, formActionType }) { | ||
466 | - const { setFieldsValue } = formActionType; | 443 | + componentProps({ formModel }) { |
467 | const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; | 444 | const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; |
468 | - const transportType = formModel[DataSourceField.TRANSPORT_TYPE]; | ||
469 | - if (isUpdate && ![deviceProfileId, transportType].every(Boolean)) | ||
470 | - return { placeholder: '请选择开服务', getPopupContainer: () => document.body }; | ||
471 | return { | 445 | return { |
472 | - api: async () => { | ||
473 | - try { | ||
474 | - if (deviceProfileId) { | ||
475 | - const services = await getDeviceService(deviceProfileId); | ||
476 | - const value = formModel[DataSourceField.SERVICE]; | ||
477 | - if (value) { | ||
478 | - const selected = services.find((item) => item.value === value); | ||
479 | - selected && setFieldsValue({ [DataSourceField.CALL_TYPE]: selected.callType }); | ||
480 | - } | ||
481 | - return services; | ||
482 | - } | ||
483 | - } catch (error) {} | ||
484 | - return []; | 446 | + api: getModelServices, |
447 | + params: { | ||
448 | + deviceProfileId, | ||
485 | }, | 449 | }, |
486 | placeholder: '请选择开服务', | 450 | placeholder: '请选择开服务', |
451 | + labelField: 'functionName', | ||
452 | + valueField: 'identifier', | ||
487 | getPopupContainer: () => document.body, | 453 | getPopupContainer: () => document.body, |
488 | - onChange(value: string, options: ModelOfMatterParams) { | ||
489 | - const command = value | ||
490 | - ? (options.functionJson.inputData || [])[0]?.serviceCommand | ||
491 | - : null; | ||
492 | - setFieldsValue({ | ||
493 | - [DataSourceField.OPEN_COMMAND]: command, | ||
494 | - [DataSourceField.CALL_TYPE]: value ? options.callType : null, | ||
495 | - }); | ||
496 | - }, | ||
497 | }; | 454 | }; |
498 | }, | 455 | }, |
499 | }, | 456 | }, |
@@ -505,40 +462,19 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -505,40 +462,19 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
505 | rules: [{ required: true, message: '请选择关服务' }], | 462 | rules: [{ required: true, message: '请选择关服务' }], |
506 | ifShow: ({ model }) => | 463 | ifShow: ({ model }) => |
507 | isControlComponent(category!) && | 464 | isControlComponent(category!) && |
508 | - model[DataSourceField.COMMAND_TYPE] === CommandTypeEnum.SERVICE.toString() && | 465 | + model[DataSourceField.COMMAND_TYPE] === CommandTypeEnum.SERVICE && |
509 | isTcpProfile(model[DataSourceField.TRANSPORT_TYPE]), | 466 | isTcpProfile(model[DataSourceField.TRANSPORT_TYPE]), |
510 | - componentProps({ formModel, formActionType }) { | ||
511 | - const { setFieldsValue } = formActionType; | 467 | + componentProps({ formModel }) { |
512 | const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; | 468 | const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; |
513 | - const transportType = formModel[DataSourceField.TRANSPORT_TYPE]; | ||
514 | - if (isUpdate && ![deviceProfileId, transportType].every(Boolean)) | ||
515 | - return { placeholder: '请选择关服务', getPopupContainer: () => document.body }; | ||
516 | return { | 469 | return { |
517 | - api: async () => { | ||
518 | - try { | ||
519 | - if (deviceProfileId) { | ||
520 | - const services = await getDeviceService(deviceProfileId); | ||
521 | - const value = formModel[DataSourceField.SERVICE]; | ||
522 | - if (value) { | ||
523 | - const selected = services.find((item) => item.value === value); | ||
524 | - selected && setFieldsValue({ [DataSourceField.CALL_TYPE]: selected.callType }); | ||
525 | - } | ||
526 | - return services; | ||
527 | - } | ||
528 | - } catch (error) {} | ||
529 | - return []; | 470 | + api: getModelServices, |
471 | + params: { | ||
472 | + deviceProfileId, | ||
530 | }, | 473 | }, |
531 | placeholder: '请选择关服务', | 474 | placeholder: '请选择关服务', |
475 | + labelField: 'functionName', | ||
476 | + valueField: 'identifier', | ||
532 | getPopupContainer: () => document.body, | 477 | getPopupContainer: () => document.body, |
533 | - onChange(value: string, options: ModelOfMatterParams) { | ||
534 | - const command = value | ||
535 | - ? (options.functionJson.inputData || [])[0]?.serviceCommand | ||
536 | - : null; | ||
537 | - setFieldsValue({ | ||
538 | - [DataSourceField.CLOSE_COMMAND]: command, | ||
539 | - [DataSourceField.CALL_TYPE]: value ? options.callType : null, | ||
540 | - }); | ||
541 | - }, | ||
542 | }; | 478 | }; |
543 | }, | 479 | }, |
544 | }, | 480 | }, |
@@ -547,11 +483,11 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -547,11 +483,11 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
547 | component: 'Input', | 483 | component: 'Input', |
548 | label: '命令', | 484 | label: '命令', |
549 | colProps: { span: 8 }, | 485 | colProps: { span: 8 }, |
550 | - rules: [{ required: true, message: '请输入开下发命令' }], | 486 | + rules: [{ validator: validateTCPCustomCommand }], |
551 | // 是控制组件 && 自定义命令 && 传输协议为TCP | 487 | // 是控制组件 && 自定义命令 && 传输协议为TCP |
552 | ifShow: ({ model }) => | 488 | ifShow: ({ model }) => |
553 | isControlComponent(category!) && | 489 | isControlComponent(category!) && |
554 | - model[DataSourceField.COMMAND_TYPE] === CommandTypeEnum.CUSTOM.toString() && | 490 | + model[DataSourceField.COMMAND_TYPE] === CommandTypeEnum.CUSTOM && |
555 | model[DataSourceField.TRANSPORT_TYPE] && | 491 | model[DataSourceField.TRANSPORT_TYPE] && |
556 | isTcpProfile(model[DataSourceField.TRANSPORT_TYPE]), | 492 | isTcpProfile(model[DataSourceField.TRANSPORT_TYPE]), |
557 | componentProps: { | 493 | componentProps: { |
@@ -563,11 +499,11 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -563,11 +499,11 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
563 | component: 'Input', | 499 | component: 'Input', |
564 | label: '命令', | 500 | label: '命令', |
565 | colProps: { span: 8 }, | 501 | colProps: { span: 8 }, |
566 | - rules: [{ required: true, message: '请输入关下发命令' }], | 502 | + rules: [{ validator: validateTCPCustomCommand }], |
567 | // 是控制组件 && 自定义命令 && 传输协议为TCP | 503 | // 是控制组件 && 自定义命令 && 传输协议为TCP |
568 | ifShow: ({ model }) => | 504 | ifShow: ({ model }) => |
569 | isControlComponent(category!) && | 505 | isControlComponent(category!) && |
570 | - model[DataSourceField.COMMAND_TYPE] === CommandTypeEnum.CUSTOM.toString() && | 506 | + model[DataSourceField.COMMAND_TYPE] === CommandTypeEnum.CUSTOM && |
571 | model[DataSourceField.TRANSPORT_TYPE] && | 507 | model[DataSourceField.TRANSPORT_TYPE] && |
572 | isTcpProfile(model[DataSourceField.TRANSPORT_TYPE]), | 508 | isTcpProfile(model[DataSourceField.TRANSPORT_TYPE]), |
573 | componentProps: { | 509 | componentProps: { |
@@ -24,6 +24,7 @@ import { | @@ -24,6 +24,7 @@ import { | ||
24 | } from './useSocket.type'; | 24 | } from './useSocket.type'; |
25 | import { ComponentPropsConfigType } from '../../index.type'; | 25 | import { ComponentPropsConfigType } from '../../index.type'; |
26 | import { isNullOrUnDef } from '/@/utils/is'; | 26 | import { isNullOrUnDef } from '/@/utils/is'; |
27 | +import { CategoryEnum } from '../../components'; | ||
27 | 28 | ||
28 | interface DeviceGroupMapType { | 29 | interface DeviceGroupMapType { |
29 | subscriptionId: number; | 30 | subscriptionId: number; |
@@ -410,8 +411,20 @@ export const useMultipleDataFetch = ( | @@ -410,8 +411,20 @@ export const useMultipleDataFetch = ( | ||
410 | Object.keys(unref(getDataSourceGroup)).forEach((key) => { | 411 | Object.keys(unref(getDataSourceGroup)).forEach((key) => { |
411 | const item = unref(getDataSourceGroup)[key]; | 412 | const item = unref(getDataSourceGroup)[key]; |
412 | const attributes = [...new Set(item.map((item) => item.attribute))]; | 413 | const attributes = [...new Set(item.map((item) => item.attribute))]; |
414 | + | ||
415 | + if (props.config.componentConfig.category === CategoryEnum.MAP) { | ||
416 | + const positionIdentifier = item.reduce((prev, next) => { | ||
417 | + const [lat] = next.latitudeIdentifier || []; | ||
418 | + const [lng] = next.longitudeIdentifier || []; | ||
419 | + | ||
420 | + return [...prev, lat, lng]; | ||
421 | + }, []); | ||
422 | + | ||
423 | + attributes.push(...new Set(positionIdentifier)); | ||
424 | + } | ||
425 | + | ||
413 | subscriber.trackUpdateGroup(key, { | 426 | subscriber.trackUpdateGroup(key, { |
414 | - attributes, | 427 | + attributes: attributes.filter(Boolean), |
415 | fn: updateFn, | 428 | fn: updateFn, |
416 | }); | 429 | }); |
417 | }); | 430 | }); |
1 | +import { ref } from 'vue'; | ||
2 | +import { getDeviceDetail } from '/@/api/device/deviceManager'; | ||
3 | +import { useDeviceProfileQueryContext } from '../../palette/hooks/useDeviceProfileQueryContext'; | ||
4 | +import { | ||
5 | + CommandTypeEnum, | ||
6 | + RPCCommandMethodEnum, | ||
7 | + ServiceCallTypeEnum, | ||
8 | + TransportTypeEnum, | ||
9 | +} from '/@/enums/deviceEnum'; | ||
10 | +import { RpcCommandType } from '/@/api/device/model/deviceConfigModel'; | ||
11 | +import { useMessage } from '/@/hooks/web/useMessage'; | ||
12 | +import { useGetModbusCommand } from './useGetModbusCommand'; | ||
13 | +import { TaskTypeEnum } from '/@/views/task/center/config'; | ||
14 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
15 | +import { sendCommandOneway, sendCommandTwoway } from '/@/api/dataBoard'; | ||
16 | +import { isNullOrUnDef } from '/@/utils/is'; | ||
17 | + | ||
18 | +export interface DoCommandDeliverDataSourceType { | ||
19 | + deviceId: string; | ||
20 | + deviceProfileId: string; | ||
21 | + attribute: string; | ||
22 | + commandType?: CommandTypeEnum; | ||
23 | + openCommand?: string; | ||
24 | + closeCommand?: string; | ||
25 | + openService?: string; | ||
26 | + closeService?: string; | ||
27 | +} | ||
28 | + | ||
29 | +export function useCommandDelivery() { | ||
30 | + const loading = ref(false); | ||
31 | + | ||
32 | + const { createMessage } = useMessage(); | ||
33 | + | ||
34 | + const { getDeviceProfileTslByIdWithIdentifier } = useDeviceProfileQueryContext(); | ||
35 | + | ||
36 | + const doGetDeviceId = async (deviceId: string) => { | ||
37 | + return await getDeviceDetail(deviceId); | ||
38 | + }; | ||
39 | + | ||
40 | + const { validateCanGetCommand, getModbusCommand } = useGetModbusCommand(); | ||
41 | + | ||
42 | + const doCommandDeliver = async ( | ||
43 | + dataSource: DoCommandDeliverDataSourceType, | ||
44 | + value: any | ||
45 | + ): Promise<boolean> => { | ||
46 | + try { | ||
47 | + const { deviceId, deviceProfileId, attribute, commandType } = dataSource; | ||
48 | + | ||
49 | + loading.value = true; | ||
50 | + const tsl = getDeviceProfileTslByIdWithIdentifier?.(deviceProfileId, attribute); | ||
51 | + const deviceDetail = await doGetDeviceId(deviceId); | ||
52 | + | ||
53 | + let sendCommandFn = sendCommandOneway; | ||
54 | + | ||
55 | + let params: string | Recordable | undefined = { | ||
56 | + [attribute]: value, | ||
57 | + }; | ||
58 | + | ||
59 | + if (deviceDetail.transportType === TransportTypeEnum.TCP) { | ||
60 | + if (deviceDetail.codeType === TaskTypeEnum.MODBUS_RTU) { | ||
61 | + if (!validateCanGetCommand(tsl?.extensionDesc, deviceDetail.code)) return false; | ||
62 | + params = await getModbusCommand(value, tsl!.extensionDesc, deviceDetail.code!); | ||
63 | + } else if (deviceDetail.codeType === TaskTypeEnum.CUSTOM) { | ||
64 | + params = value; | ||
65 | + if (commandType === CommandTypeEnum.CUSTOM) { | ||
66 | + if (tsl?.specs?.dataType.type === DataTypeEnum.BOOL) { | ||
67 | + const { openCommand, closeCommand } = dataSource; | ||
68 | + params = !!Number(value) ? openCommand : closeCommand; | ||
69 | + } | ||
70 | + } else if (commandType === CommandTypeEnum.SERVICE) { | ||
71 | + if (tsl?.specs?.dataType.type === DataTypeEnum.BOOL) { | ||
72 | + const { openService, closeService } = dataSource; | ||
73 | + const serviceIdentifier = !!Number(value) ? openService : closeService; | ||
74 | + const serviceTsl = getDeviceProfileTslByIdWithIdentifier?.( | ||
75 | + deviceProfileId, | ||
76 | + serviceIdentifier! | ||
77 | + ); | ||
78 | + params = serviceTsl?.inputData?.[0].serviceCommand; | ||
79 | + sendCommandFn = | ||
80 | + serviceTsl?.callType === ServiceCallTypeEnum.SYNC | ||
81 | + ? sendCommandTwoway | ||
82 | + : sendCommandOneway; | ||
83 | + } | ||
84 | + } | ||
85 | + } | ||
86 | + } | ||
87 | + | ||
88 | + if (isNullOrUnDef(params)) return false; | ||
89 | + | ||
90 | + const rpcCommand: RpcCommandType = { | ||
91 | + additionalInfo: { | ||
92 | + cmdType: CommandTypeEnum.API, | ||
93 | + }, | ||
94 | + params, | ||
95 | + method: RPCCommandMethodEnum.THINGSKIT, | ||
96 | + persistent: true, | ||
97 | + }; | ||
98 | + | ||
99 | + await sendCommandFn({ deviceId: deviceId, value: rpcCommand }); | ||
100 | + | ||
101 | + createMessage.success('命令下发成功'); | ||
102 | + | ||
103 | + return true; | ||
104 | + } catch (e) { | ||
105 | + return false; | ||
106 | + } finally { | ||
107 | + loading.value = false; | ||
108 | + } | ||
109 | + }; | ||
110 | + | ||
111 | + return { | ||
112 | + loading, | ||
113 | + doCommandDeliver, | ||
114 | + }; | ||
115 | +} |
1 | +import { ExtensionDesc } from '/@/api/device/model/modelOfMatterModel'; | ||
2 | +import { genModbusCommand } from '/@/api/task'; | ||
3 | +import { GenModbusCommandType } from '/@/api/task/model'; | ||
4 | +import { ModbusCRCEnum, RegisterActionTypeEnum } from '/@/enums/objectModelEnum'; | ||
5 | +import { useMessage } from '/@/hooks/web/useMessage'; | ||
6 | + | ||
7 | +export const InsertString = (t: any, c: any, n: any) => { | ||
8 | + const r: string | number[] = []; | ||
9 | + | ||
10 | + for (let i = 0; i * 2 < t.length; i++) r.push(t.substr(i * 2, n)); | ||
11 | + | ||
12 | + return r.join(c); | ||
13 | +}; | ||
14 | + | ||
15 | +export const FillString = (t: any, c: any, n: any, b: any) => { | ||
16 | + if (t === '' || c.length !== 1 || n <= t.length) return t; | ||
17 | + | ||
18 | + const l = t.length; | ||
19 | + | ||
20 | + for (let i = 0; i < n - l; i++) { | ||
21 | + if (b === true) t = c + t; | ||
22 | + else t += c; | ||
23 | + } | ||
24 | + return t; | ||
25 | +}; | ||
26 | + | ||
27 | +export const SingleToHex = (t: any) => { | ||
28 | + if (t === '') return ''; | ||
29 | + | ||
30 | + t = parseFloat(t); | ||
31 | + | ||
32 | + if (isNaN(t) === true) return 'Error'; | ||
33 | + | ||
34 | + if (t === 0) return '00000000'; | ||
35 | + | ||
36 | + let s, e, m; | ||
37 | + | ||
38 | + if (t > 0) { | ||
39 | + s = 0; | ||
40 | + } else { | ||
41 | + s = 1; | ||
42 | + | ||
43 | + t = 0 - t; | ||
44 | + } | ||
45 | + m = t.toString(2); | ||
46 | + | ||
47 | + if (m >= 1) { | ||
48 | + if (m.indexOf('.') === -1) m = `${m}.0`; | ||
49 | + | ||
50 | + e = m.indexOf('.') - 1; | ||
51 | + } else { | ||
52 | + e = 1 - m.indexOf('1'); | ||
53 | + } | ||
54 | + if (e >= 0) m = m.replace('.', ''); | ||
55 | + else m = m.substring(m.indexOf('1')); | ||
56 | + | ||
57 | + if (m.length > 24) m = m.substr(0, 24); | ||
58 | + else m = FillString(m, '0', 24, false); | ||
59 | + | ||
60 | + m = m.substring(1); | ||
61 | + | ||
62 | + e = (e + 127).toString(2); | ||
63 | + | ||
64 | + e = FillString(e, '0', 8, true); | ||
65 | + | ||
66 | + let r = parseInt(s + e + m, 2).toString(16); | ||
67 | + | ||
68 | + r = FillString(r, '0', 8, true); | ||
69 | + | ||
70 | + return InsertString(r, ' ', 2).toUpperCase(); | ||
71 | +}; | ||
72 | + | ||
73 | +export const FormatHex = (t: any, n: any, ie: any) => { | ||
74 | + const r: string[] = []; | ||
75 | + | ||
76 | + let s = ''; | ||
77 | + | ||
78 | + let c = 0; | ||
79 | + | ||
80 | + for (let i = 0; i < t.length; i++) { | ||
81 | + if (t.charAt(i) !== ' ') { | ||
82 | + s += t.charAt(i); | ||
83 | + | ||
84 | + c += 1; | ||
85 | + | ||
86 | + if (c === n) { | ||
87 | + r.push(s); | ||
88 | + | ||
89 | + s = ''; | ||
90 | + | ||
91 | + c = 0; | ||
92 | + } | ||
93 | + } | ||
94 | + if (ie === false) { | ||
95 | + if (i === t.length - 1 && s !== '') r.push(s); | ||
96 | + } | ||
97 | + } | ||
98 | + return r.join('\n'); | ||
99 | +}; | ||
100 | + | ||
101 | +export const FormatHexBatch = (t: any, n: any, ie: any) => { | ||
102 | + const a = t.split('\n'); | ||
103 | + | ||
104 | + const r: string[] = []; | ||
105 | + | ||
106 | + for (let i = 0; i < a.length; i++) r[i] = FormatHex(a[i], n, ie); | ||
107 | + | ||
108 | + return r.join('\n'); | ||
109 | +}; | ||
110 | + | ||
111 | +export const SingleToHexBatch = (t: any) => { | ||
112 | + const a = t.split('\n'); | ||
113 | + | ||
114 | + const r: string[] = []; | ||
115 | + | ||
116 | + for (let i = 0; i < a.length; i++) r[i] = SingleToHex(a[i]); | ||
117 | + | ||
118 | + return r.join('\r\n'); | ||
119 | +}; | ||
120 | + | ||
121 | +const getArray = (values: any) => { | ||
122 | + const str = values.replace(/\s+/g, ''); | ||
123 | + const array: any = []; | ||
124 | + | ||
125 | + for (let i = 0; i < str.length; i += 4) { | ||
126 | + const chunk = parseInt(str.substring(i, i + 4), 16); | ||
127 | + array.push(chunk); | ||
128 | + } | ||
129 | + return array; | ||
130 | +}; | ||
131 | + | ||
132 | +const getFloatPart = (number: string | number) => { | ||
133 | + const isLessZero = Number(number) < 0; | ||
134 | + number = number.toString(); | ||
135 | + const floatPartStartIndex = number.indexOf('.'); | ||
136 | + const value = ~floatPartStartIndex | ||
137 | + ? `${isLessZero ? '-' : ''}0.${number.substring(floatPartStartIndex + 1)}` | ||
138 | + : '0'; | ||
139 | + return Number(value); | ||
140 | +}; | ||
141 | + | ||
142 | +const REGISTER_MAX_VALUE = Number(0xffff); | ||
143 | + | ||
144 | +export function useGetModbusCommand() { | ||
145 | + const { createMessage } = useMessage(); | ||
146 | + | ||
147 | + const getModbusCommand = async ( | ||
148 | + value: number, | ||
149 | + extensionDesc: ExtensionDesc, | ||
150 | + deviceAddressCode: string | ||
151 | + ) => { | ||
152 | + const { registerAddress, actionType, zoomFactor } = extensionDesc as Required<ExtensionDesc>; | ||
153 | + | ||
154 | + const params: GenModbusCommandType = { | ||
155 | + crc: ModbusCRCEnum.CRC_16_LOWER, | ||
156 | + registerNumber: 1, | ||
157 | + deviceCode: deviceAddressCode, | ||
158 | + registerAddress, | ||
159 | + method: actionType, | ||
160 | + registerValues: [value], | ||
161 | + }; | ||
162 | + | ||
163 | + if (actionType === RegisterActionTypeEnum.INT) { | ||
164 | + const newValue = Math.trunc(value) * zoomFactor + getFloatPart(value) * zoomFactor; | ||
165 | + | ||
166 | + if (newValue % 1 !== 0) { | ||
167 | + createMessage.warning(`属性下发类型必须是整数,缩放因子为${zoomFactor}`); | ||
168 | + return; | ||
169 | + } | ||
170 | + | ||
171 | + if (value * zoomFactor > REGISTER_MAX_VALUE) { | ||
172 | + createMessage.warning(`属性下发值不能超过${REGISTER_MAX_VALUE},缩放因子为${zoomFactor}`); | ||
173 | + return; | ||
174 | + } | ||
175 | + | ||
176 | + params.registerValues = [newValue]; | ||
177 | + } else if (actionType === RegisterActionTypeEnum.DOUBLE) { | ||
178 | + const regex = /^-?\d+(\.\d{0,2})?$/; | ||
179 | + const values = Math.trunc(value) * zoomFactor + getFloatPart(value) * zoomFactor; | ||
180 | + | ||
181 | + if (!regex.test(values.toString())) { | ||
182 | + createMessage.warning(`属性下发值精确到两位小数,缩放因子为${zoomFactor}`); | ||
183 | + return; | ||
184 | + } | ||
185 | + | ||
186 | + const newValue = values === 0 ? [0, 0] : getArray(SingleToHex(values)); | ||
187 | + params.registerValues = newValue; | ||
188 | + params.registerNumber = 2; | ||
189 | + params.method = '10'; | ||
190 | + } | ||
191 | + | ||
192 | + return await genModbusCommand(params); | ||
193 | + }; | ||
194 | + | ||
195 | + /** | ||
196 | + * | ||
197 | + * @param extensionDesc 物模型拓展描述符 | ||
198 | + * @param deviceAddressCode 设备地址码 | ||
199 | + */ | ||
200 | + const validateCanGetCommand = ( | ||
201 | + extensionDesc?: ExtensionDesc, | ||
202 | + deviceAddressCode?: string, | ||
203 | + createValidateMessage = true | ||
204 | + ) => { | ||
205 | + const result = { flag: true, message: '' }; | ||
206 | + if (!extensionDesc) { | ||
207 | + result.flag = false; | ||
208 | + result.message = '当前物模型扩展描述没有填写'; | ||
209 | + } | ||
210 | + | ||
211 | + if (!deviceAddressCode) { | ||
212 | + result.flag = false; | ||
213 | + result.message = '当前设备未绑定设备地址码'; | ||
214 | + } | ||
215 | + | ||
216 | + if (result.message && createValidateMessage) createMessage.warning(result.message); | ||
217 | + | ||
218 | + return result; | ||
219 | + }; | ||
220 | + | ||
221 | + return { | ||
222 | + getModbusCommand, | ||
223 | + validateCanGetCommand, | ||
224 | + }; | ||
225 | +} |
src/views/visual/packages/hook/useSendCommand.ts
deleted
100644 → 0
1 | -import { ref } from 'vue'; | ||
2 | -import { DataSource } from '../../palette/types'; | ||
3 | -import { sendCommandOneway, sendCommandTwoway } from '/@/api/dataBoard'; | ||
4 | -import { useMessage } from '/@/hooks/web/useMessage'; | ||
5 | -import { TransportTypeEnum, ServiceCallTypeEnum } from '/@/enums/deviceEnum'; | ||
6 | - | ||
7 | -const { createMessage } = useMessage(); | ||
8 | -export function useSendCommand() { | ||
9 | - const loading = ref(false); | ||
10 | - | ||
11 | - const error = () => { | ||
12 | - // createMessage.error('下发指令失败'); | ||
13 | - return false; | ||
14 | - }; | ||
15 | - | ||
16 | - const sendCommand = async (record: DataSource, value: any, isModbusCommand = false) => { | ||
17 | - if (!record) return false; | ||
18 | - const { customCommand, attribute } = record || {}; | ||
19 | - const { deviceId } = record; | ||
20 | - if (!deviceId) return false; | ||
21 | - | ||
22 | - try { | ||
23 | - loading.value = true; | ||
24 | - let params: string | Recordable = { | ||
25 | - [attribute!]: Number(value), | ||
26 | - }; | ||
27 | - if (isModbusCommand) { | ||
28 | - params = value; | ||
29 | - } | ||
30 | - | ||
31 | - let sendCommandFn = sendCommandOneway; | ||
32 | - // 如果是TCP设备从物模型中获取下发命令(TCP网关子设备无物模型服务与事件) | ||
33 | - if (customCommand?.transportType === TransportTypeEnum.TCP && !isModbusCommand) { | ||
34 | - params = customCommand.command!; | ||
35 | - if (customCommand.callType === ServiceCallTypeEnum.SYNC) { | ||
36 | - sendCommandFn = sendCommandTwoway; | ||
37 | - } | ||
38 | - } | ||
39 | - // 控制按钮下发命令为0 或 1 | ||
40 | - await sendCommandFn({ | ||
41 | - deviceId, | ||
42 | - value: { | ||
43 | - params: params || null, | ||
44 | - persistent: true, | ||
45 | - additionalInfo: { | ||
46 | - cmdType: customCommand.commandType || 'API', | ||
47 | - }, | ||
48 | - method: 'methodThingskit', | ||
49 | - }, | ||
50 | - }); | ||
51 | - createMessage.success('命令下发成功'); | ||
52 | - return true; | ||
53 | - } catch (msg) { | ||
54 | - console.error(msg); | ||
55 | - return error(); | ||
56 | - } finally { | ||
57 | - loading.value = false; | ||
58 | - } | ||
59 | - }; | ||
60 | - return { | ||
61 | - loading, | ||
62 | - sendCommand, | ||
63 | - }; | ||
64 | -} |
@@ -9,7 +9,7 @@ export const useApp = () => { | @@ -9,7 +9,7 @@ export const useApp = () => { | ||
9 | 9 | ||
10 | const isPhone = () => { | 10 | const isPhone = () => { |
11 | const values = location?.pathname.split('/') || []; | 11 | const values = location?.pathname.split('/') || []; |
12 | - return values[values?.length - 2] === 'phone' ? true : false; | 12 | + return values[values?.length - 2] === 'phone'; |
13 | }; | 13 | }; |
14 | 14 | ||
15 | return { getIsAppPage, isPhone }; | 15 | return { getIsAppPage, isPhone }; |
@@ -11,6 +11,8 @@ import { | @@ -11,6 +11,8 @@ import { | ||
11 | } from '../types'; | 11 | } from '../types'; |
12 | import { buildUUID } from '/@/utils/uuid'; | 12 | import { buildUUID } from '/@/utils/uuid'; |
13 | import { PublicComponentOptions } from '../../packages/index.type'; | 13 | import { PublicComponentOptions } from '../../packages/index.type'; |
14 | +import { batchGetObjectModel } from '/@/api/device/modelOfMatter'; | ||
15 | +import { BatchGetObjectModelItemType } from '/@/api/device/model/modelOfMatterModel'; | ||
14 | 16 | ||
15 | export interface WidgetDataType extends Layout, ComponentDataType, PublicComponentOptions {} | 17 | export interface WidgetDataType extends Layout, ComponentDataType, PublicComponentOptions {} |
16 | 18 | ||
@@ -23,6 +25,17 @@ export const useDataSource = (propsRef: ComputedRef<Recordable>) => { | @@ -23,6 +25,17 @@ export const useDataSource = (propsRef: ComputedRef<Recordable>) => { | ||
23 | 25 | ||
24 | const dataSource = ref<WidgetDataType[]>([]); | 26 | const dataSource = ref<WidgetDataType[]>([]); |
25 | 27 | ||
28 | + const deviceProfilesMapRef = ref<Map<string, BatchGetObjectModelItemType>>(); | ||
29 | + | ||
30 | + const getAllDeviceProfileIdsByDataSource = computed(() => { | ||
31 | + const result = unref(rawDataSource)?.componentData?.reduce((prev, next) => { | ||
32 | + const ids = next.dataSource.map((temp) => temp.deviceProfileId); | ||
33 | + return [...prev, ...ids]; | ||
34 | + }, []); | ||
35 | + | ||
36 | + return [...new Set(result)]; | ||
37 | + }); | ||
38 | + | ||
26 | const getSharePageData = computed(() => { | 39 | const getSharePageData = computed(() => { |
27 | return unref(propsRef).value!; | 40 | return unref(propsRef).value!; |
28 | }); | 41 | }); |
@@ -64,19 +77,8 @@ export const useDataSource = (propsRef: ComputedRef<Recordable>) => { | @@ -64,19 +77,8 @@ export const useDataSource = (propsRef: ComputedRef<Recordable>) => { | ||
64 | loading.value = true; | 77 | loading.value = true; |
65 | const { data } = await getDataBoradDetail(); | 78 | const { data } = await getDataBoradDetail(); |
66 | rawDataSource.value = data; | 79 | rawDataSource.value = data; |
67 | - // const result: WidgetDataType[] = (data.componentData || []).map((item) => { | ||
68 | - // const { id } = item; | ||
69 | - | ||
70 | - // const layout = | ||
71 | - // (data.componentLayout || []).find((item) => item.id === id) || | ||
72 | - // ({} as ComponentLayoutType); | ||
73 | - | ||
74 | - // return { | ||
75 | - // i: buildUUID(), | ||
76 | - // ...layout, | ||
77 | - // ...item, | ||
78 | - // } as WidgetDataType; | ||
79 | - // }); | 80 | + await getAllDeviceProfiles(); |
81 | + | ||
80 | const result: WidgetDataType[] = data.componentLayout.map((item) => { | 82 | const result: WidgetDataType[] = data.componentLayout.map((item) => { |
81 | const { id } = item; | 83 | const { id } = item; |
82 | const dataSource = | 84 | const dataSource = |
@@ -129,8 +131,35 @@ export const useDataSource = (propsRef: ComputedRef<Recordable>) => { | @@ -129,8 +131,35 @@ export const useDataSource = (propsRef: ComputedRef<Recordable>) => { | ||
129 | } catch (error) {} | 131 | } catch (error) {} |
130 | }; | 132 | }; |
131 | 133 | ||
132 | - onMounted(() => { | ||
133 | - getDataSource(); | 134 | + const getAllDeviceProfiles = async () => { |
135 | + if (!unref(getAllDeviceProfileIdsByDataSource).length) return; | ||
136 | + const result = await batchGetObjectModel({ | ||
137 | + deviceProfileIds: unref(getAllDeviceProfileIdsByDataSource), | ||
138 | + }); | ||
139 | + | ||
140 | + const map = new Map(); | ||
141 | + | ||
142 | + result.forEach((item) => { | ||
143 | + map.set(item.id, item); | ||
144 | + }); | ||
145 | + | ||
146 | + deviceProfilesMapRef.value = map; | ||
147 | + }; | ||
148 | + | ||
149 | + function getDeviceProfileDetailById(id: string) { | ||
150 | + return unref(deviceProfilesMapRef)?.get(id); | ||
151 | + } | ||
152 | + | ||
153 | + function getDeviceProfileTslByIdWithIdentifier(id: string, identifier: string) { | ||
154 | + const detail = getDeviceProfileDetailById(id); | ||
155 | + if (!detail) return; | ||
156 | + for (const item of detail.tsl) { | ||
157 | + if (item.identifier === identifier) return item; | ||
158 | + } | ||
159 | + } | ||
160 | + | ||
161 | + onMounted(async () => { | ||
162 | + await getDataSource(); | ||
134 | }); | 163 | }); |
135 | 164 | ||
136 | return { | 165 | return { |
@@ -138,8 +167,11 @@ export const useDataSource = (propsRef: ComputedRef<Recordable>) => { | @@ -138,8 +167,11 @@ export const useDataSource = (propsRef: ComputedRef<Recordable>) => { | ||
138 | draggable: !unref(getIsSharePage) && !unref(getIsAppPage), | 167 | draggable: !unref(getIsSharePage) && !unref(getIsAppPage), |
139 | resizable: !unref(getIsSharePage) && !unref(getIsAppPage), | 168 | resizable: !unref(getIsSharePage) && !unref(getIsAppPage), |
140 | dataSource, | 169 | dataSource, |
170 | + deviceProfilesMapRef, | ||
141 | rawDataSource, | 171 | rawDataSource, |
142 | getDataSource, | 172 | getDataSource, |
143 | setLayoutInfo, | 173 | setLayoutInfo, |
174 | + getDeviceProfileDetailById, | ||
175 | + getDeviceProfileTslByIdWithIdentifier, | ||
144 | }; | 176 | }; |
145 | }; | 177 | }; |
1 | +import { inject, provide } from 'vue'; | ||
2 | +import { BatchGetObjectModelItemType, Tsl } from '/@/api/device/model/modelOfMatterModel'; | ||
3 | + | ||
4 | +const SymbolKey = Symbol('data-board'); | ||
5 | + | ||
6 | +export interface ContextOptionsType { | ||
7 | + getDeviceProfileDetailById: (id: string) => BatchGetObjectModelItemType | undefined; | ||
8 | + getDeviceProfileTslByIdWithIdentifier: (id: string, identifier?: string) => Tsl | undefined; | ||
9 | +} | ||
10 | + | ||
11 | +export const createDeviceProfileQueryContext = (options: ContextOptionsType) => { | ||
12 | + provide(SymbolKey, options); | ||
13 | +}; | ||
14 | + | ||
15 | +export const useDeviceProfileQueryContext = () => { | ||
16 | + return inject<ContextOptionsType>(SymbolKey) || ({} as Partial<ContextOptionsType>); | ||
17 | +}; |
1 | +import { DataType, Specs, StructJSON } from '/@/api/device/model/modelOfMatterModel'; | ||
2 | +import { DataTypeEnum } from '/@/enums/objectModelEnum'; | ||
3 | +import { useJsonParse } from '/@/hooks/business/useJsonParse'; | ||
4 | +function getBoolTypeValue(value: number, Specs: Specs) { | ||
5 | + const { boolOpen, boolClose } = Specs; | ||
6 | + | ||
7 | + return Number(value) ? boolOpen : boolClose; | ||
8 | +} | ||
9 | + | ||
10 | +function getEnumTypeValue(value: number, specsList: Specs[]) { | ||
11 | + const res = specsList.find((item) => item.value === Number(value)); | ||
12 | + | ||
13 | + return res?.name; | ||
14 | +} | ||
15 | + | ||
16 | +function getStructTypeValue(value: string, specs: StructJSON[]): string { | ||
17 | + const res = useJsonParse(value).value; | ||
18 | + | ||
19 | + function generateStruct(specs: StructJSON[], value: Recordable) { | ||
20 | + if (!value) return {}; | ||
21 | + | ||
22 | + return specs.reduce((prev, next) => { | ||
23 | + return { | ||
24 | + ...prev, | ||
25 | + [next.functionName!]: getValueByType( | ||
26 | + next.dataType!.type, | ||
27 | + value[next.identifier], | ||
28 | + next.dataType! | ||
29 | + ), | ||
30 | + }; | ||
31 | + }, {}); | ||
32 | + } | ||
33 | + | ||
34 | + return JSON.stringify(generateStruct(specs, res)); | ||
35 | +} | ||
36 | + | ||
37 | +function getValueByType(type: string, value: any, dataType: DataType) { | ||
38 | + switch (type) { | ||
39 | + case DataTypeEnum.BOOL: | ||
40 | + return getBoolTypeValue(value, dataType.specs as Specs); | ||
41 | + case DataTypeEnum.STRUCT: | ||
42 | + return getStructTypeValue(value, dataType.specs as StructJSON[]); | ||
43 | + case DataTypeEnum.ENUM: | ||
44 | + return getEnumTypeValue(value, dataType.specsList as Specs[]); | ||
45 | + default: | ||
46 | + return value; | ||
47 | + } | ||
48 | +} | ||
49 | +export function useThingsModelValueTransform(value: any, thingsModelDataType?: DataType) { | ||
50 | + if (!thingsModelDataType) return value; | ||
51 | + | ||
52 | + const { type } = thingsModelDataType; | ||
53 | + return getValueByType(type, value, thingsModelDataType); | ||
54 | +} |
@@ -40,6 +40,7 @@ | @@ -40,6 +40,7 @@ | ||
40 | import SIGNALSVG from '/@/assets/svg/signal.svg'; | 40 | import SIGNALSVG from '/@/assets/svg/signal.svg'; |
41 | import BATTERYSVG from '/@/assets/svg/battery.svg'; | 41 | import BATTERYSVG from '/@/assets/svg/battery.svg'; |
42 | import { useRoute } from 'vue-router'; | 42 | import { useRoute } from 'vue-router'; |
43 | + import { createDeviceProfileQueryContext } from './hooks/useDeviceProfileQueryContext'; | ||
43 | 44 | ||
44 | const props = defineProps<{ | 45 | const props = defineProps<{ |
45 | value?: Recordable; | 46 | value?: Recordable; |
@@ -53,8 +54,17 @@ | @@ -53,8 +54,17 @@ | ||
53 | 54 | ||
54 | const ROUTE = useRoute(); | 55 | const ROUTE = useRoute(); |
55 | 56 | ||
56 | - const { loading, draggable, resizable, dataSource, rawDataSource, setLayoutInfo, getDataSource } = | ||
57 | - useDataSource(getProps); | 57 | + const { |
58 | + loading, | ||
59 | + draggable, | ||
60 | + resizable, | ||
61 | + dataSource, | ||
62 | + rawDataSource, | ||
63 | + setLayoutInfo, | ||
64 | + getDataSource, | ||
65 | + getDeviceProfileDetailById, | ||
66 | + getDeviceProfileTslByIdWithIdentifier, | ||
67 | + } = useDataSource(getProps); | ||
58 | 68 | ||
59 | const { resize, resized, moved, containerResized } = useDragGridLayout(dataSource, setLayoutInfo); | 69 | const { resize, resized, moved, containerResized } = useDragGridLayout(dataSource, setLayoutInfo); |
60 | 70 | ||
@@ -157,6 +167,11 @@ | @@ -157,6 +167,11 @@ | ||
157 | 167 | ||
158 | createDataBoardContext({ send, close }); | 168 | createDataBoardContext({ send, close }); |
159 | 169 | ||
170 | + createDeviceProfileQueryContext({ | ||
171 | + getDeviceProfileDetailById, | ||
172 | + getDeviceProfileTslByIdWithIdentifier, | ||
173 | + }); | ||
174 | + | ||
160 | const { getDarkMode } = useRootSetting(); | 175 | const { getDarkMode } = useRootSetting(); |
161 | watch( | 176 | watch( |
162 | getIsSharePage, | 177 | getIsSharePage, |
1 | import { PublicComponentOptions } from '../../packages/index.type'; | 1 | import { PublicComponentOptions } from '../../packages/index.type'; |
2 | +import { CommandTypeEnum } from '/@/enums/deviceEnum'; | ||
2 | 3 | ||
3 | export interface ComponentDataType<T = ExtraDataSource> { | 4 | export interface ComponentDataType<T = ExtraDataSource> { |
4 | id: string; | 5 | id: string; |
@@ -19,19 +20,26 @@ export interface DataSource { | @@ -19,19 +20,26 @@ export interface DataSource { | ||
19 | deviceId: string; | 20 | deviceId: string; |
20 | deviceType: string; | 21 | deviceType: string; |
21 | attribute: string; | 22 | attribute: string; |
22 | - attributeName: string; | ||
23 | - deviceName: string; | ||
24 | - gatewayDevice: boolean; | ||
25 | - slaveDeviceId: string; | 23 | + commandType?: CommandTypeEnum; |
24 | + openCommand?: string; | ||
25 | + closeCommand?: string; | ||
26 | + openService?: string; | ||
27 | + closeService?: string; | ||
28 | + // attributeName: string; | ||
29 | + // deviceName: string; | ||
30 | + // gatewayDevice: boolean; | ||
31 | + // slaveDeviceId: string; | ||
26 | deviceRename: string; | 32 | deviceRename: string; |
27 | attributeRename: string; | 33 | attributeRename: string; |
28 | componentInfo: ComponentInfo; | 34 | componentInfo: ComponentInfo; |
29 | - customCommand: CustomCommand; | ||
30 | videoConfig?: VideoConfigType; | 35 | videoConfig?: VideoConfigType; |
31 | [key: string]: any; | 36 | [key: string]: any; |
32 | - lal?: string; | ||
33 | - latitude?: string | number; | ||
34 | - longitude?: string | number; | 37 | + |
38 | + latitudeIdentifier?: string[]; | ||
39 | + longitudeIdentifier?: string[]; | ||
40 | + // lal?: string; | ||
41 | + // latitude?: string | number; | ||
42 | + // longitude?: string | number; | ||
35 | } | 43 | } |
36 | 44 | ||
37 | export interface ExtraDataSource extends DataSource, PublicComponentOptions { | 45 | export interface ExtraDataSource extends DataSource, PublicComponentOptions { |