Commit fabfa424903a2f2dff9a7a4f2811d770bf603e8f
1 parent
aa0a85c1
feat: implement data component control component
Showing
15 changed files
with
408 additions
and
505 deletions
@@ -8,6 +8,7 @@ import { | @@ -8,6 +8,7 @@ import { | ||
8 | DeviceAttributeRecord, | 8 | DeviceAttributeRecord, |
9 | GetDataBoardParams, | 9 | GetDataBoardParams, |
10 | MasterDeviceList, | 10 | MasterDeviceList, |
11 | + SendCommandParams, | ||
11 | UpdateDataBoardLayoutParams, | 12 | UpdateDataBoardLayoutParams, |
12 | UpdateDataBoardParams, | 13 | UpdateDataBoardParams, |
13 | UpdateDataComponentParams, | 14 | UpdateDataComponentParams, |
@@ -33,6 +34,10 @@ enum DataBoardShareUrl { | @@ -33,6 +34,10 @@ enum DataBoardShareUrl { | ||
33 | GET_DATA_COMPONENT = '/noauth/share/data_board', | 34 | GET_DATA_COMPONENT = '/noauth/share/data_board', |
34 | } | 35 | } |
35 | 36 | ||
37 | +enum SendCommand { | ||
38 | + ONEWAY = '/plugins/rpc/oneway', | ||
39 | +} | ||
40 | + | ||
36 | enum DeviceUrl { | 41 | enum DeviceUrl { |
37 | GET_DEVICE = '/device/list/master', | 42 | GET_DEVICE = '/device/list/master', |
38 | GET_SLAVE_DEVICE = '/device/list/slave', | 43 | GET_SLAVE_DEVICE = '/device/list/slave', |
@@ -194,3 +199,13 @@ export const getDeviceAttributes = (params: DeviceAttributeParams) => { | @@ -194,3 +199,13 @@ export const getDeviceAttributes = (params: DeviceAttributeParams) => { | ||
194 | }, | 199 | }, |
195 | }); | 200 | }); |
196 | }; | 201 | }; |
202 | + | ||
203 | +export const sendCommandOneway = (params: SendCommandParams) => { | ||
204 | + return defHttp.post( | ||
205 | + { | ||
206 | + url: `${SendCommand.ONEWAY}/${params.deviceId}`, | ||
207 | + params: params.value, | ||
208 | + }, | ||
209 | + { joinPrefix: false } | ||
210 | + ); | ||
211 | +}; |
@@ -156,3 +156,8 @@ export interface DeviceAttributeRecord { | @@ -156,3 +156,8 @@ export interface DeviceAttributeRecord { | ||
156 | identifier: string; | 156 | identifier: string; |
157 | detail: DataType; | 157 | detail: DataType; |
158 | } | 158 | } |
159 | + | ||
160 | +export interface SendCommandParams { | ||
161 | + deviceId: string; | ||
162 | + value: any; | ||
163 | +} |
@@ -5,8 +5,10 @@ | @@ -5,8 +5,10 @@ | ||
5 | </script> | 5 | </script> |
6 | <script lang="ts" setup> | 6 | <script lang="ts" setup> |
7 | import { RadioRecord } from '../../detail/config/util'; | 7 | import { RadioRecord } from '../../detail/config/util'; |
8 | + import { ControlComponentDefaultConfig, ControlComponentValue } from './control.config'; | ||
9 | + import { useSendCommand } from './useSendCommand'; | ||
8 | 10 | ||
9 | - interface VisualComponentProps<Layout = Recordable, Value = Recordable> { | 11 | + interface VisualComponentProps<Layout = Recordable, Value = ControlComponentValue> { |
10 | value?: Value; | 12 | value?: Value; |
11 | layout?: Layout; | 13 | layout?: Layout; |
12 | radio?: RadioRecord; | 14 | radio?: RadioRecord; |
@@ -15,29 +17,40 @@ | @@ -15,29 +17,40 @@ | ||
15 | update?: () => void; | 17 | update?: () => void; |
16 | remove?: (key: string) => void; | 18 | remove?: (key: string) => void; |
17 | } | 19 | } |
20 | + | ||
18 | const props = defineProps<VisualComponentProps>(); | 21 | const props = defineProps<VisualComponentProps>(); |
19 | 22 | ||
20 | const emit = defineEmits(['update:value', 'change']); | 23 | const emit = defineEmits(['update:value', 'change']); |
21 | 24 | ||
25 | + const { sendCommand } = useSendCommand(); | ||
22 | const handleChange = (event: Event) => { | 26 | const handleChange = (event: Event) => { |
23 | const _value = (event.target as HTMLInputElement).checked; | 27 | const _value = (event.target as HTMLInputElement).checked; |
24 | emit('update:value', _value); | 28 | emit('update:value', _value); |
25 | emit('change', _value); | 29 | emit('change', _value); |
30 | + sendCommand(props.value?.slaveDeviceId || props.value?.deviceId, _value); | ||
26 | }; | 31 | }; |
27 | </script> | 32 | </script> |
28 | 33 | ||
29 | <template> | 34 | <template> |
30 | - <label class="sliding-switch"> | ||
31 | - <input | ||
32 | - :value="props.value?.value" | ||
33 | - type="checkbox" | ||
34 | - :checked="props.value?.value" | ||
35 | - @change="handleChange" | ||
36 | - /> | ||
37 | - <span class="slider"></span> | ||
38 | - <span class="on">ON</span> | ||
39 | - <span class="off">OFF</span> | ||
40 | - </label> | 35 | + <div class="flex flex-col justify-center"> |
36 | + <label class="sliding-switch"> | ||
37 | + <input | ||
38 | + :value="props.value?.value" | ||
39 | + type="checkbox" | ||
40 | + :checked="props.value?.value" | ||
41 | + @change="handleChange" | ||
42 | + /> | ||
43 | + <span class="slider"></span> | ||
44 | + <span class="on">ON</span> | ||
45 | + <span class="off">OFF</span> | ||
46 | + </label> | ||
47 | + <div | ||
48 | + class="text-center mt-2 text-gray-700" | ||
49 | + :style="{ color: props?.value?.fontColor || ControlComponentDefaultConfig.fontColor }" | ||
50 | + > | ||
51 | + {{ props.value?.attributeRename || props.value?.attribute }}</div | ||
52 | + > | ||
53 | + </div> | ||
41 | </template> | 54 | </template> |
42 | 55 | ||
43 | <style scoped lang="less"> | 56 | <style scoped lang="less"> |
@@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
5 | </script> | 5 | </script> |
6 | <script lang="ts" setup> | 6 | <script lang="ts" setup> |
7 | import { Switch } from 'ant-design-vue'; | 7 | import { Switch } from 'ant-design-vue'; |
8 | - import { computed } from 'vue'; | 8 | + import { computed, ref, watchEffect } from 'vue'; |
9 | import { DEFAULT_RADIO_RECORD, fontSize, RadioRecord } from '../../detail/config/util'; | 9 | import { DEFAULT_RADIO_RECORD, fontSize, RadioRecord } from '../../detail/config/util'; |
10 | import SvgIcon from '/@/components/Icon/src/SvgIcon.vue'; | 10 | import SvgIcon from '/@/components/Icon/src/SvgIcon.vue'; |
11 | import { | 11 | import { |
@@ -13,6 +13,7 @@ | @@ -13,6 +13,7 @@ | ||
13 | ControlComponentValue, | 13 | ControlComponentValue, |
14 | ControlComponentLayout, | 14 | ControlComponentLayout, |
15 | } from './control.config'; | 15 | } from './control.config'; |
16 | + import { useSendCommand } from './useSendCommand'; | ||
16 | const props = withDefaults( | 17 | const props = withDefaults( |
17 | defineProps<{ | 18 | defineProps<{ |
18 | layout?: ControlComponentLayout; | 19 | layout?: ControlComponentLayout; |
@@ -26,6 +27,18 @@ | @@ -26,6 +27,18 @@ | ||
26 | const getRadio = computed(() => { | 27 | const getRadio = computed(() => { |
27 | return props.radio || DEFAULT_RADIO_RECORD; | 28 | return props.radio || DEFAULT_RADIO_RECORD; |
28 | }); | 29 | }); |
30 | + | ||
31 | + const checked = ref(!!Number(props.value.value)); | ||
32 | + | ||
33 | + const { sendCommand } = useSendCommand(); | ||
34 | + const handleChange = (value: boolean) => { | ||
35 | + console.log(props.value); | ||
36 | + sendCommand(props.value.slaveDeviceId! || props.value.deviceId!, value); | ||
37 | + }; | ||
38 | + | ||
39 | + watchEffect(() => { | ||
40 | + checked.value = !!Number(props.value.value); | ||
41 | + }); | ||
29 | </script> | 42 | </script> |
30 | 43 | ||
31 | <template> | 44 | <template> |
@@ -40,8 +53,13 @@ | @@ -40,8 +53,13 @@ | ||
40 | height: fontSize({ radioRecord: getRadio, basic: 30, min: 16 }), | 53 | height: fontSize({ radioRecord: getRadio, basic: 30, min: 16 }), |
41 | }" | 54 | }" |
42 | /> | 55 | /> |
43 | - <span class="flex-auto mx-4 flex items-center truncate inline-block">属性名</span> | 56 | + <span |
57 | + class="flex-auto mx-4 flex items-center truncate inline-block text-gray-700" | ||
58 | + :style="{ color: props.value.fontColor || ControlComponentDefaultConfig.fontColor }" | ||
59 | + > | ||
60 | + {{ props.value.attributeRename || props.value.attribute }} | ||
61 | + </span> | ||
44 | </div> | 62 | </div> |
45 | - <Switch /> | 63 | + <Switch v-model:checked="checked" @change="handleChange" /> |
46 | </div> | 64 | </div> |
47 | </template> | 65 | </template> |
@@ -6,7 +6,8 @@ | @@ -6,7 +6,8 @@ | ||
6 | <script lang="ts" setup> | 6 | <script lang="ts" setup> |
7 | import { computed } from '@vue/reactivity'; | 7 | import { computed } from '@vue/reactivity'; |
8 | import { DEFAULT_RADIO_RECORD, fontSize, RadioRecord } from '../../detail/config/util'; | 8 | import { DEFAULT_RADIO_RECORD, fontSize, RadioRecord } from '../../detail/config/util'; |
9 | - import { ControlComponentValue } from './control.config'; | 9 | + import { ControlComponentDefaultConfig, ControlComponentValue } from './control.config'; |
10 | + import { useSendCommand } from './useSendCommand'; | ||
10 | 11 | ||
11 | const props = defineProps<{ | 12 | const props = defineProps<{ |
12 | value?: ControlComponentValue; | 13 | value?: ControlComponentValue; |
@@ -16,10 +17,12 @@ | @@ -16,10 +17,12 @@ | ||
16 | 17 | ||
17 | const emit = defineEmits(['update:value', 'change']); | 18 | const emit = defineEmits(['update:value', 'change']); |
18 | 19 | ||
20 | + const { sendCommand } = useSendCommand(); | ||
19 | const handleChange = (event: Event) => { | 21 | const handleChange = (event: Event) => { |
20 | const _value = (event.target as HTMLInputElement).checked; | 22 | const _value = (event.target as HTMLInputElement).checked; |
21 | emit('update:value', _value); | 23 | emit('update:value', _value); |
22 | emit('change', _value); | 24 | emit('change', _value); |
25 | + sendCommand(props.value?.slaveDeviceId || props.value?.deviceId, _value); | ||
23 | }; | 26 | }; |
24 | 27 | ||
25 | const getRadio = computed(() => { | 28 | const getRadio = computed(() => { |
@@ -28,28 +31,36 @@ | @@ -28,28 +31,36 @@ | ||
28 | </script> | 31 | </script> |
29 | 32 | ||
30 | <template> | 33 | <template> |
31 | - <div | ||
32 | - class="toggle-switch" | ||
33 | - :style="{ | ||
34 | - width: fontSize({ radioRecord: getRadio, basic: 75, max: 75, min: 60 }), | ||
35 | - height: fontSize({ radioRecord: getRadio, basic: 97.5, max: 97.5, min: 80 }), | ||
36 | - }" | ||
37 | - > | ||
38 | - <label class="switch"> | ||
39 | - <input | ||
40 | - :value="props.value?.value" | ||
41 | - type="checkbox" | ||
42 | - :checked="props.value?.value" | ||
43 | - @change="handleChange" | ||
44 | - /> | ||
45 | - <div class="button"> | ||
46 | - <div class="light"></div> | ||
47 | - <div class="dots"></div> | ||
48 | - <div class="characters"></div> | ||
49 | - <div class="shine"></div> | ||
50 | - <div class="shadow"></div> | ||
51 | - </div> | ||
52 | - </label> | 34 | + <div class="flex flex-col"> |
35 | + <div | ||
36 | + class="toggle-switch" | ||
37 | + :style="{ | ||
38 | + width: fontSize({ radioRecord: getRadio, basic: 75, max: 75, min: 60 }), | ||
39 | + height: fontSize({ radioRecord: getRadio, basic: 97.5, max: 97.5, min: 80 }), | ||
40 | + }" | ||
41 | + > | ||
42 | + <label class="switch"> | ||
43 | + <input | ||
44 | + :value="props.value?.value" | ||
45 | + type="checkbox" | ||
46 | + :checked="props.value?.value" | ||
47 | + @change="handleChange" | ||
48 | + /> | ||
49 | + <div class="button"> | ||
50 | + <div class="light"></div> | ||
51 | + <div class="dots"></div> | ||
52 | + <div class="characters"></div> | ||
53 | + <div class="shine"></div> | ||
54 | + <div class="shadow"></div> | ||
55 | + </div> | ||
56 | + </label> | ||
57 | + </div> | ||
58 | + <div | ||
59 | + class="text-center mt-2 text-gray-700" | ||
60 | + :style="{ color: props?.value?.fontColor || ControlComponentDefaultConfig.fontColor }" | ||
61 | + > | ||
62 | + {{ props.value?.attributeRename || props.value?.attribute }}</div | ||
63 | + > | ||
53 | </div> | 64 | </div> |
54 | </template> | 65 | </template> |
55 | 66 |
@@ -6,14 +6,19 @@ export interface ControlComponentLayout { | @@ -6,14 +6,19 @@ export interface ControlComponentLayout { | ||
6 | 6 | ||
7 | export interface ControlComponentValue { | 7 | export interface ControlComponentValue { |
8 | value?: boolean; | 8 | value?: boolean; |
9 | - name?: string; | 9 | + attribute?: string; |
10 | + attributeRename?: string; | ||
10 | icon?: string; | 11 | icon?: string; |
11 | iconColor?: string; | 12 | iconColor?: string; |
13 | + deviceId?: string; | ||
14 | + fontColor?: string; | ||
15 | + slaveDeviceId?: string; | ||
12 | } | 16 | } |
13 | 17 | ||
14 | export const ControlComponentDefaultConfig: ControlComponentValue = { | 18 | export const ControlComponentDefaultConfig: ControlComponentValue = { |
15 | icon: 'shuiwen', | 19 | icon: 'shuiwen', |
16 | iconColor: '#367BFF', | 20 | iconColor: '#367BFF', |
21 | + fontColor: '#000', | ||
17 | }; | 22 | }; |
18 | 23 | ||
19 | export const transformControlConfig = ( | 24 | export const transformControlConfig = ( |
@@ -23,8 +28,11 @@ export const transformControlConfig = ( | @@ -23,8 +28,11 @@ export const transformControlConfig = ( | ||
23 | ) => { | 28 | ) => { |
24 | return { | 29 | return { |
25 | value: { | 30 | value: { |
26 | - value: dataSourceRecord.componentInfo.value, | ||
27 | - icon: dataSourceRecord.componentInfo.icon, | 31 | + ...dataSourceRecord.componentInfo, |
32 | + attribute: dataSourceRecord.attribute, | ||
33 | + attributeRename: dataSourceRecord.attributeRename, | ||
34 | + deviceId: dataSourceRecord.deviceId, | ||
35 | + slaveDeviceId: dataSourceRecord.slaveDeviceId, | ||
28 | } as ControlComponentValue, | 36 | } as ControlComponentValue, |
29 | }; | 37 | }; |
30 | }; | 38 | }; |
1 | -export function useSendCommand() {} | 1 | +import { sendCommandOneway } from '/@/api/dataBoard'; |
2 | +import { useMessage } from '/@/hooks/web/useMessage'; | ||
3 | + | ||
4 | +const { createMessage } = useMessage(); | ||
5 | +export function useSendCommand() { | ||
6 | + const sendCommand = async (deviceId: string, value: any) => { | ||
7 | + if (!deviceId) return; | ||
8 | + try { | ||
9 | + await sendCommandOneway({ | ||
10 | + deviceId, | ||
11 | + value: { | ||
12 | + params: Number(value), | ||
13 | + persistent: true, | ||
14 | + additionalInfo: { | ||
15 | + cmdType: 'API', | ||
16 | + }, | ||
17 | + method: 'methodThingskit', | ||
18 | + }, | ||
19 | + }); | ||
20 | + createMessage.success('命令下发成功'); | ||
21 | + } catch (error) {} | ||
22 | + }; | ||
23 | + return { | ||
24 | + sendCommand, | ||
25 | + }; | ||
26 | +} |
@@ -146,7 +146,7 @@ frontComponentMap.set(FrontComponent.CONTROL_COMPONENT_SWITCH_WITH_ICON, { | @@ -146,7 +146,7 @@ frontComponentMap.set(FrontComponent.CONTROL_COMPONENT_SWITCH_WITH_ICON, { | ||
146 | ComponentCategory: FrontComponentCategory.CONTROL, | 146 | ComponentCategory: FrontComponentCategory.CONTROL, |
147 | isMultipleDataSource: false, | 147 | isMultipleDataSource: false, |
148 | hasHistoryTrend: true, | 148 | hasHistoryTrend: true, |
149 | - hasSetting: false, | 149 | + hasSetting: true, |
150 | transformConfig: transformControlConfig, | 150 | transformConfig: transformControlConfig, |
151 | }); | 151 | }); |
152 | 152 |
@@ -274,7 +274,11 @@ | @@ -274,7 +274,11 @@ | ||
274 | 选择设备 | 274 | 选择设备 |
275 | </div> | 275 | </div> |
276 | <div class="pl-2 flex-auto"> | 276 | <div class="pl-2 flex-auto"> |
277 | - <component :is="dataSourceComponent" :ref="(el) => setFormEl(el, item.id)" /> | 277 | + <component |
278 | + :frontId="$props.frontId" | ||
279 | + :is="dataSourceComponent" | ||
280 | + :ref="(el) => setFormEl(el, item.id)" | ||
281 | + /> | ||
278 | </div> | 282 | </div> |
279 | <div class="flex justify-center gap-3 w-28"> | 283 | <div class="flex justify-center gap-3 w-28"> |
280 | <Tooltip title="复制"> | 284 | <Tooltip title="复制"> |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | import { ref } from 'vue'; | 2 | import { ref } from 'vue'; |
3 | + import { FrontComponent } from '../../../const/const'; | ||
3 | import { dataSourceSchema } from '../../config/basicConfiguration'; | 4 | import { dataSourceSchema } from '../../config/basicConfiguration'; |
4 | import { FormActionType } from '/@/components/Form'; | 5 | import { FormActionType } from '/@/components/Form'; |
5 | import BasicForm from '/@/components/Form/src/BasicForm.vue'; | 6 | import BasicForm from '/@/components/Form/src/BasicForm.vue'; |
6 | const formEl = ref<Nullable<FormActionType>>(null); | 7 | const formEl = ref<Nullable<FormActionType>>(null); |
7 | 8 | ||
9 | + defineProps<{ | ||
10 | + frontId?: FrontComponent; | ||
11 | + }>(); | ||
12 | + | ||
8 | defineExpose({ formActionType: formEl }); | 13 | defineExpose({ formActionType: formEl }); |
9 | </script> | 14 | </script> |
10 | 15 | ||
11 | <template> | 16 | <template> |
12 | <BasicForm | 17 | <BasicForm |
13 | ref="formEl" | 18 | ref="formEl" |
14 | - :schemas="dataSourceSchema" | 19 | + :schemas="dataSourceSchema($props.frontId)" |
15 | class="w-full flex-1 data-source-form" | 20 | class="w-full flex-1 data-source-form" |
16 | :show-action-button-group="false" | 21 | :show-action-button-group="false" |
17 | :row-props="{ | 22 | :row-props="{ |
1 | <script lang="ts" setup> | 1 | <script lang="ts" setup> |
2 | import { ref, unref } from 'vue'; | 2 | import { ref, unref } from 'vue'; |
3 | import { BasicForm, FormActionType } from '/@/components/Form'; | 3 | import { BasicForm, FormActionType } from '/@/components/Form'; |
4 | - import { controlFormSchema } from '../../config/basicConfiguration'; | 4 | + import { dataSourceSchema } from '../../config/basicConfiguration'; |
5 | + import { FrontComponent } from '../../../const/const'; | ||
6 | + | ||
7 | + defineProps<{ | ||
8 | + frontId?: FrontComponent; | ||
9 | + }>(); | ||
5 | 10 | ||
6 | const formEl = ref<Nullable<FormActionType>>(); | 11 | const formEl = ref<Nullable<FormActionType>>(); |
7 | 12 | ||
@@ -33,7 +38,7 @@ | @@ -33,7 +38,7 @@ | ||
33 | <div class="w-full flex-1"> | 38 | <div class="w-full flex-1"> |
34 | <BasicForm | 39 | <BasicForm |
35 | :ref="(el) => setFormEl(el)" | 40 | :ref="(el) => setFormEl(el)" |
36 | - :schemas="controlFormSchema" | 41 | + :schemas="dataSourceSchema($props.frontId)" |
37 | class="w-full flex-1 data-source-form" | 42 | class="w-full flex-1 data-source-form" |
38 | :show-action-button-group="false" | 43 | :show-action-button-group="false" |
39 | :row-props="{ | 44 | :row-props="{ |
1 | -<script lang="ts" setup> | ||
2 | - import { ref, unref } from 'vue'; | ||
3 | - import { BasicForm, FormActionType } from '/@/components/Form'; | ||
4 | - import { mapFormSchema } from '../../config/basicConfiguration'; | ||
5 | - | ||
6 | - const formEl = ref<Nullable<FormActionType>>(); | ||
7 | - | ||
8 | - const setFormEl = (el: any) => { | ||
9 | - formEl.value = el; | ||
10 | - }; | ||
11 | - | ||
12 | - const getFieldsValue = () => { | ||
13 | - return unref(formEl)!.getFieldsValue(); | ||
14 | - }; | ||
15 | - | ||
16 | - const validate = async () => { | ||
17 | - await unref(formEl)!.validate(); | ||
18 | - }; | ||
19 | - | ||
20 | - const setFieldsValue = async (record: Recordable) => { | ||
21 | - await unref(formEl)!.setFieldsValue(record); | ||
22 | - }; | ||
23 | - | ||
24 | - const clearValidate = async (name?: string | string[]) => { | ||
25 | - await unref(formEl)!.clearValidate(name); | ||
26 | - }; | ||
27 | - defineExpose({ | ||
28 | - formActionType: { getFieldsValue, validate, setFieldsValue, clearValidate }, | ||
29 | - }); | ||
30 | -</script> | ||
31 | - | ||
32 | -<template> | ||
33 | - <div class="w-full flex-1"> | ||
34 | - <BasicForm | ||
35 | - :ref="(el) => setFormEl(el)" | ||
36 | - :schemas="mapFormSchema" | ||
37 | - class="w-full flex-1 data-source-form" | ||
38 | - :show-action-button-group="false" | ||
39 | - :row-props="{ | ||
40 | - gutter: 10, | ||
41 | - }" | ||
42 | - layout="horizontal" | ||
43 | - :label-col="{ span: 0 }" | ||
44 | - /> | ||
45 | - </div> | ||
46 | -</template> |
1 | import { Component } from 'vue'; | 1 | import { Component } from 'vue'; |
2 | import { FrontComponent } from '../../../const/const'; | 2 | import { FrontComponent } from '../../../const/const'; |
3 | import BasicDataSourceForm from './BasicDataSourceForm.vue'; | 3 | import BasicDataSourceForm from './BasicDataSourceForm.vue'; |
4 | -import ControlDataSourceForm from './ControlDataSourceForm.vue'; | 4 | +// import ControlDataSourceForm from './ControlDataSourceForm.vue'; |
5 | 5 | ||
6 | const dataSourceComponentMap = new Map<FrontComponent, Component>(); | 6 | const dataSourceComponentMap = new Map<FrontComponent, Component>(); |
7 | 7 | ||
8 | -dataSourceComponentMap.set(FrontComponent.CONTROL_COMPONENT_TOGGLE_SWITCH, ControlDataSourceForm); | ||
9 | export const getDataSourceComponent = (frontId: FrontComponent) => { | 8 | export const getDataSourceComponent = (frontId: FrontComponent) => { |
10 | if (dataSourceComponentMap.has(frontId)) return dataSourceComponentMap.get(frontId)!; | 9 | if (dataSourceComponentMap.has(frontId)) return dataSourceComponentMap.get(frontId)!; |
11 | return BasicDataSourceForm; | 10 | return BasicDataSourceForm; |
@@ -2,18 +2,17 @@ import { getAllDeviceByOrg, getDeviceAttributes, getGatewaySlaveDevice } from '/ | @@ -2,18 +2,17 @@ import { getAllDeviceByOrg, getDeviceAttributes, getGatewaySlaveDevice } from '/ | ||
2 | import { getOrganizationList } from '/@/api/system/system'; | 2 | import { getOrganizationList } from '/@/api/system/system'; |
3 | import { FormSchema } from '/@/components/Form'; | 3 | import { FormSchema } from '/@/components/Form'; |
4 | import { copyTransFun } from '/@/utils/fnUtils'; | 4 | import { copyTransFun } from '/@/utils/fnUtils'; |
5 | -import { OnChangeHookParams } from '/@/components/Form/src/components/ApiSearchSelect.vue'; | ||
6 | -import { unref } from 'vue'; | ||
7 | -import { MasterDeviceList } from '/@/api/dataBoard/model'; | 5 | +import { DeviceAttributeParams, MasterDeviceList } from '/@/api/dataBoard/model'; |
6 | +import { FrontComponent } from '../../const/const'; | ||
8 | 7 | ||
9 | export enum BasicConfigField { | 8 | export enum BasicConfigField { |
10 | NAME = 'name', | 9 | NAME = 'name', |
11 | REMARK = 'remark', | 10 | REMARK = 'remark', |
12 | } | 11 | } |
13 | 12 | ||
14 | -const getDeviceAttribute = async (deviceProfileId: string) => { | 13 | +const getDeviceAttribute = async (params: DeviceAttributeParams) => { |
15 | try { | 14 | try { |
16 | - const data = await getDeviceAttributes({ deviceProfileId }); | 15 | + const data = await getDeviceAttributes(params); |
17 | if (data) return data.map((item) => ({ label: item.name, value: item.identifier })); | 16 | if (data) return data.map((item) => ({ label: item.name, value: item.identifier })); |
18 | } catch (error) {} | 17 | } catch (error) {} |
19 | return []; | 18 | return []; |
@@ -34,6 +33,18 @@ export enum DataSourceField { | @@ -34,6 +33,18 @@ export enum DataSourceField { | ||
34 | LATITUDE_ATTRIBUTE = 'latitudeAttribute', | 33 | LATITUDE_ATTRIBUTE = 'latitudeAttribute', |
35 | } | 34 | } |
36 | 35 | ||
36 | +const isControlComponent = (frontId: FrontComponent) => { | ||
37 | + const list = [ | ||
38 | + FrontComponent.CONTROL_COMPONENT_SLIDING_SWITCH, | ||
39 | + FrontComponent.CONTROL_COMPONENT_SWITCH_WITH_ICON, | ||
40 | + FrontComponent.CONTROL_COMPONENT_TOGGLE_SWITCH, | ||
41 | + ]; | ||
42 | + if (list.includes(frontId)) { | ||
43 | + return true; | ||
44 | + } | ||
45 | + return false; | ||
46 | +}; | ||
47 | + | ||
37 | export const basicSchema: FormSchema[] = [ | 48 | export const basicSchema: FormSchema[] = [ |
38 | { | 49 | { |
39 | field: BasicConfigField.NAME, | 50 | field: BasicConfigField.NAME, |
@@ -55,420 +66,214 @@ export const basicSchema: FormSchema[] = [ | @@ -55,420 +66,214 @@ export const basicSchema: FormSchema[] = [ | ||
55 | }, | 66 | }, |
56 | ]; | 67 | ]; |
57 | 68 | ||
58 | -export const dataSourceSchema: FormSchema[] = [ | ||
59 | - { | ||
60 | - field: DataSourceField.IS_GATEWAY_DEVICE, | ||
61 | - component: 'Switch', | ||
62 | - label: '是否是网关设备', | ||
63 | - show: false, | ||
64 | - }, | ||
65 | - { | ||
66 | - field: DataSourceField.DEVICE_NAME, | ||
67 | - component: 'Input', | ||
68 | - label: '设备名', | ||
69 | - show: false, | ||
70 | - }, | ||
71 | - { | ||
72 | - field: DataSourceField.ORIGINATION_ID, | ||
73 | - component: 'ApiTreeSelect', | ||
74 | - label: '组织', | ||
75 | - colProps: { span: 8 }, | ||
76 | - rules: [{ required: true, message: '组织为必填项' }], | ||
77 | - componentProps({ formActionType }) { | ||
78 | - const { setFieldsValue } = formActionType; | ||
79 | - return { | ||
80 | - placeholder: '请选择组织', | ||
81 | - api: async () => { | ||
82 | - const data = await getOrganizationList(); | ||
83 | - copyTransFun(data as any as any[]); | ||
84 | - return data; | ||
85 | - }, | ||
86 | - onChange() { | ||
87 | - setFieldsValue({ | ||
88 | - [DataSourceField.DEVICE_ID]: null, | ||
89 | - [DataSourceField.ATTRIBUTE]: null, | ||
90 | - [DataSourceField.SLAVE_DEVICE_ID]: null, | ||
91 | - [DataSourceField.IS_GATEWAY_DEVICE]: false, | ||
92 | - [DataSourceField.DEVICE_PROFILE_ID]: null, | ||
93 | - [DataSourceField.SLAVE_DEVICE_PROFILE_ID]: null, | ||
94 | - }); | ||
95 | - }, | ||
96 | - getPopupContainer: () => document.body, | ||
97 | - }; | 69 | +export const dataSourceSchema = (frontId?: FrontComponent): FormSchema[] => { |
70 | + return [ | ||
71 | + { | ||
72 | + field: DataSourceField.IS_GATEWAY_DEVICE, | ||
73 | + component: 'Switch', | ||
74 | + label: '是否是网关设备', | ||
75 | + show: false, | ||
98 | }, | 76 | }, |
99 | - }, | ||
100 | - { | ||
101 | - field: DataSourceField.DEVICE_PROFILE_ID, | ||
102 | - component: 'Input', | ||
103 | - label: '', | ||
104 | - show: false, | ||
105 | - }, | ||
106 | - { | ||
107 | - field: DataSourceField.DEVICE_ID, | ||
108 | - component: 'ApiSelect', | ||
109 | - label: '设备', | ||
110 | - colProps: { span: 8 }, | ||
111 | - rules: [{ required: true, message: '设备名称为必填项' }], | ||
112 | - componentProps({ formModel, formActionType }) { | ||
113 | - const { setFieldsValue } = formActionType; | ||
114 | - const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
115 | - const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
116 | - return { | ||
117 | - api: async () => { | ||
118 | - if (organizationId) { | ||
119 | - try { | ||
120 | - const data = await getAllDeviceByOrg(organizationId); | ||
121 | - if (deviceId) { | ||
122 | - const record = data.find((item) => item.id === deviceId); | ||
123 | - setFieldsValue({ [DataSourceField.DEVICE_PROFILE_ID]: record?.deviceProfileId }); | ||
124 | - } | ||
125 | - if (data) | ||
126 | - return data.map((item) => ({ | ||
127 | - ...item, | ||
128 | - label: item.name, | ||
129 | - value: item.id, | ||
130 | - deviceType: item.deviceType, | ||
131 | - })); | ||
132 | - } catch (error) {} | ||
133 | - } | ||
134 | - return []; | ||
135 | - }, | ||
136 | - | ||
137 | - onChange(_value, record: MasterDeviceList) { | ||
138 | - setFieldsValue({ | ||
139 | - [DataSourceField.ATTRIBUTE]: null, | ||
140 | - [DataSourceField.IS_GATEWAY_DEVICE]: record?.deviceType === 'GATEWAY', | ||
141 | - [DataSourceField.DEVICE_PROFILE_ID]: record?.deviceProfileId, | ||
142 | - [DataSourceField.SLAVE_DEVICE_ID]: null, | ||
143 | - [DataSourceField.SLAVE_DEVICE_PROFILE_ID]: null, | ||
144 | - [DataSourceField.DEVICE_NAME]: record?.label, | ||
145 | - }); | ||
146 | - }, | ||
147 | - placeholder: '请选择设备', | ||
148 | - getPopupContainer: () => document.body, | ||
149 | - }; | 77 | + { |
78 | + field: DataSourceField.DEVICE_NAME, | ||
79 | + component: 'Input', | ||
80 | + label: '设备名', | ||
81 | + show: false, | ||
150 | }, | 82 | }, |
151 | - }, | ||
152 | - { | ||
153 | - field: DataSourceField.SLAVE_DEVICE_PROFILE_ID, | ||
154 | - component: 'Input', | ||
155 | - label: '', | ||
156 | - show: false, | ||
157 | - }, | ||
158 | - { | ||
159 | - field: DataSourceField.SLAVE_DEVICE_ID, | ||
160 | - label: '网关子设备', | ||
161 | - component: 'ApiSelect', | ||
162 | - colProps: { span: 8 }, | ||
163 | - rules: [{ required: true, message: '网关子设备为必填项' }], | ||
164 | - ifShow({ model }) { | ||
165 | - return model[DataSourceField.IS_GATEWAY_DEVICE]; | 83 | + { |
84 | + field: DataSourceField.ORIGINATION_ID, | ||
85 | + component: 'ApiTreeSelect', | ||
86 | + label: '组织', | ||
87 | + colProps: { span: 8 }, | ||
88 | + rules: [{ required: true, message: '组织为必填项' }], | ||
89 | + componentProps({ formActionType }) { | ||
90 | + const { setFieldsValue } = formActionType; | ||
91 | + return { | ||
92 | + placeholder: '请选择组织', | ||
93 | + api: async () => { | ||
94 | + const data = await getOrganizationList(); | ||
95 | + copyTransFun(data as any as any[]); | ||
96 | + return data; | ||
97 | + }, | ||
98 | + onChange() { | ||
99 | + setFieldsValue({ | ||
100 | + [DataSourceField.DEVICE_ID]: null, | ||
101 | + [DataSourceField.ATTRIBUTE]: null, | ||
102 | + [DataSourceField.SLAVE_DEVICE_ID]: null, | ||
103 | + [DataSourceField.IS_GATEWAY_DEVICE]: false, | ||
104 | + [DataSourceField.DEVICE_PROFILE_ID]: null, | ||
105 | + [DataSourceField.SLAVE_DEVICE_PROFILE_ID]: null, | ||
106 | + }); | ||
107 | + }, | ||
108 | + getPopupContainer: () => document.body, | ||
109 | + }; | ||
110 | + }, | ||
166 | }, | 111 | }, |
167 | - dynamicRules({ model }) { | ||
168 | - return [{ required: model[DataSourceField.IS_GATEWAY_DEVICE], message: '请选择网关子设备' }]; | 112 | + { |
113 | + field: DataSourceField.DEVICE_PROFILE_ID, | ||
114 | + component: 'Input', | ||
115 | + label: '', | ||
116 | + show: false, | ||
169 | }, | 117 | }, |
170 | - componentProps({ formModel, formActionType }) { | ||
171 | - const { setFieldsValue } = formActionType; | ||
172 | - const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
173 | - const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; | ||
174 | - const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
175 | - const slaveDeviceId = formModel[DataSourceField.SLAVE_DEVICE_ID]; | ||
176 | - return { | ||
177 | - api: async () => { | ||
178 | - if (organizationId && isGatewayDevice) { | ||
179 | - try { | ||
180 | - const data = await getGatewaySlaveDevice({ organizationId, masterId: deviceId }); | ||
181 | - if (slaveDeviceId) { | ||
182 | - const record = data.find((item) => item.id === slaveDeviceId); | ||
183 | - setFieldsValue({ [DataSourceField.DEVICE_PROFILE_ID]: record?.deviceProfileId }); | ||
184 | - } | ||
185 | - if (data) | ||
186 | - return data.map((item) => ({ | ||
187 | - ...item, | ||
188 | - label: item.name, | ||
189 | - value: item.id, | ||
190 | - deviceType: item.deviceType, | ||
191 | - })); | ||
192 | - } catch (error) {} | ||
193 | - } | ||
194 | - return []; | ||
195 | - }, | ||
196 | - onChange(_value, record: MasterDeviceList) { | ||
197 | - setFieldsValue({ | ||
198 | - [DataSourceField.ATTRIBUTE]: null, | ||
199 | - [DataSourceField.SLAVE_DEVICE_PROFILE_ID]: record.deviceProfileId, | ||
200 | - [DataSourceField.DEVICE_NAME]: record?.label, | ||
201 | - }); | ||
202 | - }, | ||
203 | - placeholder: '请选择网关子设备', | ||
204 | - getPopupContainer: () => document.body, | ||
205 | - }; | ||
206 | - }, | ||
207 | - }, | ||
208 | - { | ||
209 | - field: DataSourceField.ATTRIBUTE, | ||
210 | - component: 'ApiSelect', | ||
211 | - label: '属性', | ||
212 | - colProps: { span: 8 }, | ||
213 | - rules: [{ required: true, message: '属性为必填项' }], | ||
214 | - componentProps({ formModel }) { | ||
215 | - const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; | ||
216 | - const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
217 | - const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; | ||
218 | - const slaveDeviceId = formModel[DataSourceField.SLAVE_DEVICE_ID]; | ||
219 | - const slaveDeviceProfileId = formModel[DataSourceField.SLAVE_DEVICE_PROFILE_ID]; | 118 | + { |
119 | + field: DataSourceField.DEVICE_ID, | ||
120 | + component: 'ApiSelect', | ||
121 | + label: '设备', | ||
122 | + colProps: { span: 8 }, | ||
123 | + rules: [{ required: true, message: '设备名称为必填项' }], | ||
124 | + componentProps({ formModel, formActionType }) { | ||
125 | + const { setFieldsValue } = formActionType; | ||
126 | + const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
127 | + const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
128 | + return { | ||
129 | + api: async () => { | ||
130 | + if (organizationId) { | ||
131 | + try { | ||
132 | + const data = await getAllDeviceByOrg(organizationId); | ||
133 | + if (deviceId) { | ||
134 | + const record = data.find((item) => item.id === deviceId); | ||
135 | + setFieldsValue({ [DataSourceField.DEVICE_PROFILE_ID]: record?.deviceProfileId }); | ||
136 | + } | ||
137 | + if (data) | ||
138 | + return data.map((item) => ({ | ||
139 | + ...item, | ||
140 | + label: item.name, | ||
141 | + value: item.id, | ||
142 | + deviceType: item.deviceType, | ||
143 | + })); | ||
144 | + } catch (error) {} | ||
145 | + } | ||
146 | + return []; | ||
147 | + }, | ||
220 | 148 | ||
221 | - return { | ||
222 | - api: async () => { | ||
223 | - if (deviceId) { | ||
224 | - try { | ||
225 | - if (isGatewayDevice && slaveDeviceId && slaveDeviceProfileId) { | ||
226 | - return await getDeviceAttribute(slaveDeviceProfileId); | ||
227 | - } | ||
228 | - if (!isGatewayDevice && deviceProfileId) { | ||
229 | - return await getDeviceAttribute(deviceProfileId); | ||
230 | - } | ||
231 | - } catch (error) {} | ||
232 | - } | ||
233 | - return []; | ||
234 | - }, | ||
235 | - placeholder: '请选择属性', | ||
236 | - getPopupContainer: () => document.body, | ||
237 | - }; | 149 | + onChange(_value, record: MasterDeviceList) { |
150 | + setFieldsValue({ | ||
151 | + [DataSourceField.ATTRIBUTE]: null, | ||
152 | + [DataSourceField.IS_GATEWAY_DEVICE]: record?.deviceType === 'GATEWAY', | ||
153 | + [DataSourceField.DEVICE_PROFILE_ID]: record?.deviceProfileId, | ||
154 | + [DataSourceField.SLAVE_DEVICE_ID]: null, | ||
155 | + [DataSourceField.SLAVE_DEVICE_PROFILE_ID]: null, | ||
156 | + [DataSourceField.DEVICE_NAME]: record?.label, | ||
157 | + }); | ||
158 | + }, | ||
159 | + placeholder: '请选择设备', | ||
160 | + getPopupContainer: () => document.body, | ||
161 | + }; | ||
162 | + }, | ||
238 | }, | 163 | }, |
239 | - }, | ||
240 | - { | ||
241 | - field: DataSourceField.DEVICE_RENAME, | ||
242 | - component: 'Input', | ||
243 | - label: '设备', | ||
244 | - colProps: { span: 8 }, | ||
245 | - componentProps: { | ||
246 | - placeholder: '设备重命名', | 164 | + { |
165 | + field: DataSourceField.SLAVE_DEVICE_PROFILE_ID, | ||
166 | + component: 'Input', | ||
167 | + label: '', | ||
168 | + show: false, | ||
247 | }, | 169 | }, |
248 | - }, | ||
249 | - { | ||
250 | - field: DataSourceField.ATTRIBUTE_RENAME, | ||
251 | - component: 'Input', | ||
252 | - label: '属性', | ||
253 | - colProps: { span: 8 }, | ||
254 | - componentProps: { | ||
255 | - placeholder: '属性重命名', | 170 | + { |
171 | + field: DataSourceField.SLAVE_DEVICE_ID, | ||
172 | + label: '网关子设备', | ||
173 | + component: 'ApiSelect', | ||
174 | + colProps: { span: 8 }, | ||
175 | + rules: [{ required: true, message: '网关子设备为必填项' }], | ||
176 | + ifShow({ model }) { | ||
177 | + return model[DataSourceField.IS_GATEWAY_DEVICE]; | ||
178 | + }, | ||
179 | + dynamicRules({ model }) { | ||
180 | + return [ | ||
181 | + { required: model[DataSourceField.IS_GATEWAY_DEVICE], message: '请选择网关子设备' }, | ||
182 | + ]; | ||
183 | + }, | ||
184 | + componentProps({ formModel, formActionType }) { | ||
185 | + const { setFieldsValue } = formActionType; | ||
186 | + const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
187 | + const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; | ||
188 | + const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
189 | + const slaveDeviceId = formModel[DataSourceField.SLAVE_DEVICE_ID]; | ||
190 | + return { | ||
191 | + api: async () => { | ||
192 | + if (organizationId && isGatewayDevice) { | ||
193 | + try { | ||
194 | + const data = await getGatewaySlaveDevice({ organizationId, masterId: deviceId }); | ||
195 | + if (slaveDeviceId) { | ||
196 | + const record = data.find((item) => item.id === slaveDeviceId); | ||
197 | + setFieldsValue({ [DataSourceField.DEVICE_PROFILE_ID]: record?.deviceProfileId }); | ||
198 | + } | ||
199 | + if (data) | ||
200 | + return data.map((item) => ({ | ||
201 | + ...item, | ||
202 | + label: item.name, | ||
203 | + value: item.id, | ||
204 | + deviceType: item.deviceType, | ||
205 | + })); | ||
206 | + } catch (error) {} | ||
207 | + } | ||
208 | + return []; | ||
209 | + }, | ||
210 | + onChange(_value, record: MasterDeviceList) { | ||
211 | + setFieldsValue({ | ||
212 | + [DataSourceField.ATTRIBUTE]: null, | ||
213 | + [DataSourceField.SLAVE_DEVICE_PROFILE_ID]: record.deviceProfileId, | ||
214 | + [DataSourceField.DEVICE_NAME]: record?.label, | ||
215 | + }); | ||
216 | + }, | ||
217 | + placeholder: '请选择网关子设备', | ||
218 | + getPopupContainer: () => document.body, | ||
219 | + }; | ||
220 | + }, | ||
256 | }, | 221 | }, |
257 | - }, | ||
258 | -]; | 222 | + { |
223 | + field: DataSourceField.ATTRIBUTE, | ||
224 | + component: 'ApiSelect', | ||
225 | + label: '属性', | ||
226 | + colProps: { span: 8 }, | ||
227 | + rules: [{ required: true, message: '属性为必填项' }], | ||
228 | + componentProps({ formModel }) { | ||
229 | + const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; | ||
230 | + const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
231 | + const deviceProfileId = formModel[DataSourceField.DEVICE_PROFILE_ID]; | ||
232 | + const slaveDeviceId = formModel[DataSourceField.SLAVE_DEVICE_ID]; | ||
233 | + const slaveDeviceProfileId = formModel[DataSourceField.SLAVE_DEVICE_PROFILE_ID]; | ||
259 | 234 | ||
260 | -export const controlFormSchema: FormSchema[] = [ | ||
261 | - { | ||
262 | - field: DataSourceField.DEVICE_RENAME, | ||
263 | - component: 'Input', | ||
264 | - label: '设备', | ||
265 | - colProps: { span: 8 }, | ||
266 | - componentProps: { | ||
267 | - placeholder: '设备重命名', | ||
268 | - }, | ||
269 | - }, | ||
270 | - { | ||
271 | - field: DataSourceField.ATTRIBUTE_RENAME, | ||
272 | - component: 'Input', | ||
273 | - label: '属性', | ||
274 | - colProps: { span: 8 }, | ||
275 | - componentProps: { | ||
276 | - placeholder: '属性重命名', | ||
277 | - }, | ||
278 | - }, | ||
279 | -]; | ||
280 | - | ||
281 | -export const mapFormSchema: FormSchema[] = [ | ||
282 | - { | ||
283 | - field: DataSourceField.IS_GATEWAY_DEVICE, | ||
284 | - component: 'Switch', | ||
285 | - label: '是否是网关设备', | ||
286 | - show: false, | ||
287 | - }, | ||
288 | - { | ||
289 | - field: DataSourceField.DEVICE_NAME, | ||
290 | - component: 'Input', | ||
291 | - label: '设备名', | ||
292 | - show: false, | ||
293 | - }, | ||
294 | - { | ||
295 | - field: DataSourceField.ORIGINATION_ID, | ||
296 | - component: 'ApiTreeSelect', | ||
297 | - label: '组织', | ||
298 | - colProps: { span: 8 }, | ||
299 | - rules: [{ required: true, message: '组织为必填项' }], | ||
300 | - componentProps({ formActionType }) { | ||
301 | - const { setFieldsValue } = formActionType; | ||
302 | - return { | ||
303 | - placeholder: '请选择组织', | ||
304 | - api: async () => { | ||
305 | - const data = await getOrganizationList(); | ||
306 | - copyTransFun(data as any as any[]); | ||
307 | - return data; | ||
308 | - }, | ||
309 | - onChange() { | ||
310 | - setFieldsValue({ | ||
311 | - [DataSourceField.DEVICE_ID]: null, | ||
312 | - [DataSourceField.LATITUDE_ATTRIBUTE]: null, | ||
313 | - [DataSourceField.LONGITUDE_ATTRIBUTE]: null, | ||
314 | - [DataSourceField.SLAVE_DEVICE_ID]: null, | ||
315 | - [DataSourceField.IS_GATEWAY_DEVICE]: false, | ||
316 | - }); | ||
317 | - }, | ||
318 | - getPopupContainer: () => document.body, | ||
319 | - }; | ||
320 | - }, | ||
321 | - }, | ||
322 | - { | ||
323 | - field: DataSourceField.DEVICE_ID, | ||
324 | - component: 'ApiSelect', | ||
325 | - label: '设备', | ||
326 | - colProps: { span: 8 }, | ||
327 | - rules: [{ required: true, message: '设备名称为必填项' }], | ||
328 | - componentProps({ formModel, formActionType }) { | ||
329 | - const { setFieldsValue } = formActionType; | ||
330 | - const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
331 | - return { | ||
332 | - api: async () => { | ||
333 | - if (organizationId) { | ||
334 | - try { | ||
335 | - const data = await getAllDeviceByOrg(organizationId); | ||
336 | - if (data) | ||
337 | - return data.map((item) => ({ | ||
338 | - label: item.name, | ||
339 | - value: item.id, | ||
340 | - deviceType: item.deviceType, | ||
341 | - })); | ||
342 | - } catch (error) {} | ||
343 | - } | ||
344 | - return []; | ||
345 | - }, | ||
346 | - onChange(_value, record: Record<'value' | 'label' | 'deviceType', string>) { | ||
347 | - setFieldsValue({ | ||
348 | - [DataSourceField.LONGITUDE_ATTRIBUTE]: null, | ||
349 | - [DataSourceField.LATITUDE_ATTRIBUTE]: null, | ||
350 | - [DataSourceField.IS_GATEWAY_DEVICE]: record?.deviceType === 'GATEWAY', | ||
351 | - [DataSourceField.SLAVE_DEVICE_ID]: null, | ||
352 | - [DataSourceField.DEVICE_NAME]: record?.label, | ||
353 | - }); | ||
354 | - }, | ||
355 | - placeholder: '请选择设备', | ||
356 | - getPopupContainer: () => document.body, | ||
357 | - }; | ||
358 | - }, | ||
359 | - }, | ||
360 | - { | ||
361 | - field: DataSourceField.SLAVE_DEVICE_ID, | ||
362 | - label: '网关子设备', | ||
363 | - component: 'ApiSelect', | ||
364 | - colProps: { span: 8 }, | ||
365 | - rules: [{ required: true, message: '网关子设备为必填项' }], | ||
366 | - ifShow({ model }) { | ||
367 | - return model[DataSourceField.IS_GATEWAY_DEVICE]; | ||
368 | - }, | ||
369 | - dynamicRules({ model }) { | ||
370 | - return [{ required: model[DataSourceField.IS_GATEWAY_DEVICE], message: '请选择网关子设备' }]; | 235 | + return { |
236 | + api: async () => { | ||
237 | + if (deviceId) { | ||
238 | + try { | ||
239 | + if (isGatewayDevice && slaveDeviceId && slaveDeviceProfileId) { | ||
240 | + return await getDeviceAttribute({ | ||
241 | + deviceProfileId: slaveDeviceProfileId, | ||
242 | + dataType: isControlComponent(frontId!) ? 'BOOL' : undefined, | ||
243 | + }); | ||
244 | + } | ||
245 | + if (!isGatewayDevice && deviceProfileId) { | ||
246 | + return await getDeviceAttribute({ | ||
247 | + deviceProfileId, | ||
248 | + dataType: isControlComponent(frontId!) ? 'BOOL' : undefined, | ||
249 | + }); | ||
250 | + } | ||
251 | + } catch (error) {} | ||
252 | + } | ||
253 | + return []; | ||
254 | + }, | ||
255 | + placeholder: '请选择属性', | ||
256 | + getPopupContainer: () => document.body, | ||
257 | + }; | ||
258 | + }, | ||
371 | }, | 259 | }, |
372 | - componentProps({ formModel, formActionType }) { | ||
373 | - const { setFieldsValue } = formActionType; | ||
374 | - const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
375 | - const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; | ||
376 | - const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
377 | - return { | ||
378 | - api: async () => { | ||
379 | - if (organizationId && isGatewayDevice) { | ||
380 | - try { | ||
381 | - const data = await getGatewaySlaveDevice({ organizationId, masterId: deviceId }); | ||
382 | - if (data) | ||
383 | - return data.map((item) => ({ | ||
384 | - label: item.name, | ||
385 | - value: item.id, | ||
386 | - deviceType: item.deviceType, | ||
387 | - })); | ||
388 | - } catch (error) {} | ||
389 | - } | ||
390 | - return []; | ||
391 | - }, | ||
392 | - onChange(_value, record: Record<'value' | 'label' | 'deviceType', string>) { | ||
393 | - setFieldsValue({ | ||
394 | - [DataSourceField.LATITUDE_ATTRIBUTE]: null, | ||
395 | - [DataSourceField.LONGITUDE_ATTRIBUTE]: null, | ||
396 | - [DataSourceField.DEVICE_NAME]: record?.label, | ||
397 | - }); | ||
398 | - }, | ||
399 | - placeholder: '请选择网关子设备', | ||
400 | - getPopupContainer: () => document.body, | ||
401 | - }; | 260 | + { |
261 | + field: DataSourceField.DEVICE_RENAME, | ||
262 | + component: 'Input', | ||
263 | + label: '设备', | ||
264 | + colProps: { span: 8 }, | ||
265 | + componentProps: { | ||
266 | + placeholder: '设备重命名', | ||
267 | + }, | ||
402 | }, | 268 | }, |
403 | - }, | ||
404 | - { | ||
405 | - field: DataSourceField.LONGITUDE_ATTRIBUTE, | ||
406 | - component: 'ApiSearchSelect', | ||
407 | - label: '经度属性', | ||
408 | - colProps: { span: 8 }, | ||
409 | - rules: [{ required: true, message: '属性为必填项' }], | ||
410 | - componentProps({ formModel }) { | ||
411 | - const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
412 | - const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; | ||
413 | - const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
414 | - const slaveDeviceId = formModel[DataSourceField.SLAVE_DEVICE_ID]; | ||
415 | - return { | ||
416 | - api: async () => { | ||
417 | - if (organizationId && deviceId) { | ||
418 | - try { | ||
419 | - if (isGatewayDevice && slaveDeviceId) { | ||
420 | - return await getDeviceAttribute(slaveDeviceId); | ||
421 | - } | ||
422 | - if (!isGatewayDevice) { | ||
423 | - return await getDeviceAttribute(deviceId); | ||
424 | - } | ||
425 | - } catch (error) {} | ||
426 | - } | ||
427 | - return []; | ||
428 | - }, | ||
429 | - placeholder: '请选择经度属性', | ||
430 | - dropdownVisibleChangeHook: ({ options }: OnChangeHookParams) => { | ||
431 | - options.value = unref(options).filter( | ||
432 | - (item) => item.value !== formModel[DataSourceField.LATITUDE_ATTRIBUTE] | ||
433 | - ); | ||
434 | - }, | ||
435 | - getPopupContainer: () => document.body, | ||
436 | - }; | ||
437 | - }, | ||
438 | - }, | ||
439 | - { | ||
440 | - field: DataSourceField.LATITUDE_ATTRIBUTE, | ||
441 | - component: 'ApiSearchSelect', | ||
442 | - label: '纬度属性', | ||
443 | - colProps: { span: 8 }, | ||
444 | - rules: [{ required: true, message: '属性为必填项' }], | ||
445 | - componentProps({ formModel }) { | ||
446 | - const organizationId = formModel[DataSourceField.ORIGINATION_ID]; | ||
447 | - const isGatewayDevice = formModel[DataSourceField.IS_GATEWAY_DEVICE]; | ||
448 | - const deviceId = formModel[DataSourceField.DEVICE_ID]; | ||
449 | - const slaveDeviceId = formModel[DataSourceField.SLAVE_DEVICE_ID]; | ||
450 | - return { | ||
451 | - api: async () => { | ||
452 | - if (organizationId && deviceId) { | ||
453 | - try { | ||
454 | - if (isGatewayDevice && slaveDeviceId) { | ||
455 | - return getDeviceAttribute(slaveDeviceId); | ||
456 | - } | ||
457 | - if (!isGatewayDevice) { | ||
458 | - return await getDeviceAttribute(deviceId); | ||
459 | - } | ||
460 | - } catch (error) {} | ||
461 | - } | ||
462 | - return []; | ||
463 | - }, | ||
464 | - dropdownVisibleChangeHook: ({ options }: OnChangeHookParams) => { | ||
465 | - options.value = unref(options).filter( | ||
466 | - (item) => item.value !== formModel[DataSourceField.LONGITUDE_ATTRIBUTE] | ||
467 | - ); | ||
468 | - }, | ||
469 | - placeholder: '请选择纬度属性', | ||
470 | - getPopupContainer: () => document.body, | ||
471 | - }; | 269 | + { |
270 | + field: DataSourceField.ATTRIBUTE_RENAME, | ||
271 | + component: 'Input', | ||
272 | + label: '属性', | ||
273 | + colProps: { span: 8 }, | ||
274 | + componentProps: { | ||
275 | + placeholder: '属性重命名', | ||
276 | + }, | ||
472 | }, | 277 | }, |
473 | - }, | ||
474 | -]; | 278 | + ]; |
279 | +}; |
@@ -178,6 +178,39 @@ export const modeFour: FormSchema[] = [ | @@ -178,6 +178,39 @@ export const modeFour: FormSchema[] = [ | ||
178 | }, | 178 | }, |
179 | ]; | 179 | ]; |
180 | 180 | ||
181 | +export const modeFive: FormSchema[] = [ | ||
182 | + { | ||
183 | + field: visualOptionField.FONT_COLOR, | ||
184 | + label: '数值字体颜色', | ||
185 | + component: 'ColorPicker', | ||
186 | + changeEvent: 'update:value', | ||
187 | + componentProps: { | ||
188 | + defaultValue: '#000', | ||
189 | + }, | ||
190 | + }, | ||
191 | + { | ||
192 | + field: visualOptionField.ICON_COLOR, | ||
193 | + label: '图标颜色', | ||
194 | + component: 'ColorPicker', | ||
195 | + changeEvent: 'update:value', | ||
196 | + componentProps: { | ||
197 | + defaultValue: '#367BFF', | ||
198 | + }, | ||
199 | + }, | ||
200 | + { | ||
201 | + field: visualOptionField.ICON, | ||
202 | + label: '图标', | ||
203 | + component: 'IconDrawer', | ||
204 | + changeEvent: 'update:value', | ||
205 | + componentProps({ formModel }) { | ||
206 | + const color = formModel[visualOptionField.ICON_COLOR]; | ||
207 | + return { | ||
208 | + color, | ||
209 | + }; | ||
210 | + }, | ||
211 | + }, | ||
212 | +]; | ||
213 | + | ||
181 | export const schemasMap = new Map<FrontComponent, FormSchema[]>(); | 214 | export const schemasMap = new Map<FrontComponent, FormSchema[]>(); |
182 | 215 | ||
183 | schemasMap.set(FrontComponent.TEXT_COMPONENT_1, modeOne); | 216 | schemasMap.set(FrontComponent.TEXT_COMPONENT_1, modeOne); |
@@ -188,3 +221,6 @@ schemasMap.set(FrontComponent.TEXT_COMPONENT_5, modeTwo); | @@ -188,3 +221,6 @@ schemasMap.set(FrontComponent.TEXT_COMPONENT_5, modeTwo); | ||
188 | schemasMap.set(FrontComponent.INSTRUMENT_COMPONENT_1, modeOne); | 221 | schemasMap.set(FrontComponent.INSTRUMENT_COMPONENT_1, modeOne); |
189 | schemasMap.set(FrontComponent.INSTRUMENT_COMPONENT_2, modeThree); | 222 | schemasMap.set(FrontComponent.INSTRUMENT_COMPONENT_2, modeThree); |
190 | schemasMap.set(FrontComponent.DIGITAL_DASHBOARD_COMPONENT, modeFour); | 223 | schemasMap.set(FrontComponent.DIGITAL_DASHBOARD_COMPONENT, modeFour); |
224 | +schemasMap.set(FrontComponent.CONTROL_COMPONENT_SWITCH_WITH_ICON, modeFive); | ||
225 | +schemasMap.set(FrontComponent.CONTROL_COMPONENT_SLIDING_SWITCH, modeOne); | ||
226 | +schemasMap.set(FrontComponent.CONTROL_COMPONENT_TOGGLE_SWITCH, modeOne); |