Commit 7061943df5fe149fd6861992dfcba950f936ff7b
Merge branch 'feat/board-control-add-password' into 'main_dev'
feat: 看板控制组件添加操作密码等逻辑 和修改teambition上的问题 See merge request yunteng/thingskit-front!948
Showing
22 changed files
with
298 additions
and
20 deletions
@@ -6,6 +6,7 @@ | @@ -6,6 +6,7 @@ | ||
6 | v-model:value="param.attributes" | 6 | v-model:value="param.attributes" |
7 | class="!w-1/2" | 7 | class="!w-1/2" |
8 | :options="selectOptions" | 8 | :options="selectOptions" |
9 | + v-bind="createPickerSearch()" | ||
9 | :disabled="disabled" | 10 | :disabled="disabled" |
10 | @change="emitChange" | 11 | @change="emitChange" |
11 | mode="multiple" | 12 | mode="multiple" |
@@ -24,6 +25,7 @@ | @@ -24,6 +25,7 @@ | ||
24 | import { Select } from 'ant-design-vue'; | 25 | import { Select } from 'ant-design-vue'; |
25 | import { Params } from '../type/'; | 26 | import { Params } from '../type/'; |
26 | import { useHooks } from '../hooks/index.hooks'; | 27 | import { useHooks } from '../hooks/index.hooks'; |
28 | + import { createPickerSearch } from '/@/utils/pickerSearch'; | ||
27 | 29 | ||
28 | const props = defineProps({ | 30 | const props = defineProps({ |
29 | value: propTypes.object.def({}), | 31 | value: propTypes.object.def({}), |
@@ -32,12 +32,10 @@ | @@ -32,12 +32,10 @@ | ||
32 | class="min-w-25" | 32 | class="min-w-25" |
33 | v-model:value="item.active" | 33 | v-model:value="item.active" |
34 | @change="(value) => handleChangeChars(value, item.device, item)" | 34 | @change="(value) => handleChangeChars(value, item.device, item)" |
35 | + v-bind="createPickerSearch()" | ||
35 | placeholder="请选择设备属性" | 36 | placeholder="请选择设备属性" |
36 | - > | ||
37 | - <Select.Option v-for="attr in item.attributes" :key="attr" :value="attr"> | ||
38 | - {{ attr }} | ||
39 | - </Select.Option> | ||
40 | - </Select> | 37 | + :options="item?.attributes?.map((item1) => ({ label: item1, value: item1 }))" |
38 | + /> | ||
41 | </div> | 39 | </div> |
42 | <div class="w-full h-full flex justify-center items-center"> | 40 | <div class="w-full h-full flex justify-center items-center"> |
43 | <Empty v-show="item.notFoundData" description="暂无数据" class="text-dark-50" /> | 41 | <Empty v-show="item.notFoundData" description="暂无数据" class="text-dark-50" /> |
@@ -65,6 +63,7 @@ | @@ -65,6 +63,7 @@ | ||
65 | import moment from 'moment'; | 63 | import moment from 'moment'; |
66 | import { ExecuteReportRecord } from '/@/api/export/model/exportModel'; | 64 | import { ExecuteReportRecord } from '/@/api/export/model/exportModel'; |
67 | import { Select, Spin, Empty } from 'ant-design-vue'; | 65 | import { Select, Spin, Empty } from 'ant-design-vue'; |
66 | + import { createPickerSearch } from '/@/utils/pickerSearch'; | ||
68 | 67 | ||
69 | interface ResponsData { | 68 | interface ResponsData { |
70 | attr: string; | 69 | attr: string; |
@@ -8,6 +8,7 @@ import { findDictItemByCode } from '/@/api/system/dict'; | @@ -8,6 +8,7 @@ import { findDictItemByCode } from '/@/api/system/dict'; | ||
8 | // import { unref } from 'vue'; | 8 | // import { unref } from 'vue'; |
9 | import { getMeetTheConditionsDevice } from '/@/api/dataBoard'; | 9 | import { getMeetTheConditionsDevice } from '/@/api/dataBoard'; |
10 | import { MasterDeviceList } from '/@/api/dataBoard/model'; | 10 | import { MasterDeviceList } from '/@/api/dataBoard/model'; |
11 | +import { createPickerSearch } from '/@/utils/pickerSearch'; | ||
11 | 12 | ||
12 | export const formSchemas = (): FormSchema[] => { | 13 | export const formSchemas = (): FormSchema[] => { |
13 | // const mode = useSelectWidgetMode(); | 14 | // const mode = useSelectWidgetMode(); |
@@ -150,7 +151,6 @@ export const formSchemas = (): FormSchema[] => { | @@ -150,7 +151,6 @@ export const formSchemas = (): FormSchema[] => { | ||
150 | return []; | 151 | return []; |
151 | }, | 152 | }, |
152 | onChange(_value, record: MasterDeviceList) { | 153 | onChange(_value, record: MasterDeviceList) { |
153 | - console.log(record, 'record'); | ||
154 | setFieldsValue({ | 154 | setFieldsValue({ |
155 | [DataSourceField.DEVICE_NAME]: record?.label, | 155 | [DataSourceField.DEVICE_NAME]: record?.label, |
156 | deviceIds: record?.id, | 156 | deviceIds: record?.id, |
@@ -158,6 +158,7 @@ export const formSchemas = (): FormSchema[] => { | @@ -158,6 +158,7 @@ export const formSchemas = (): FormSchema[] => { | ||
158 | }, | 158 | }, |
159 | placeholder: '请选择设备', | 159 | placeholder: '请选择设备', |
160 | getPopupContainer: () => document.body, | 160 | getPopupContainer: () => document.body, |
161 | + ...createPickerSearch(), | ||
161 | }; | 162 | }; |
162 | }, | 163 | }, |
163 | }, | 164 | }, |
@@ -12,6 +12,7 @@ import { ComponentConfigFieldEnum } from '../../../enum'; | @@ -12,6 +12,7 @@ import { ComponentConfigFieldEnum } from '../../../enum'; | ||
12 | export const option: PublicPresetOptions = { | 12 | export const option: PublicPresetOptions = { |
13 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, | 13 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, |
14 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, | 14 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, |
15 | + [ComponentConfigFieldEnum.PASS_WORD]: '', | ||
15 | // [ComponentConfigFieldEnum.FONT_COLOR]: '#000', | 16 | // [ComponentConfigFieldEnum.FONT_COLOR]: '#000', |
16 | }; | 17 | }; |
17 | 18 |
@@ -14,10 +14,10 @@ | @@ -14,10 +14,10 @@ | ||
14 | // defaultValue: option.fontColor, | 14 | // defaultValue: option.fontColor, |
15 | // }, | 15 | // }, |
16 | { | 16 | { |
17 | - field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
18 | - label: '显示设备名称', | ||
19 | - component: 'Checkbox', | ||
20 | - defaultValue: option.showDeviceName, | 17 | + field: ComponentConfigFieldEnum.PASS_WORD, |
18 | + label: '操作密码', | ||
19 | + component: 'InputPassword', | ||
20 | + defaultValue: '', | ||
21 | }, | 21 | }, |
22 | { | 22 | { |
23 | field: ComponentConfigFieldEnum.FONT_SIZE, | 23 | field: ComponentConfigFieldEnum.FONT_SIZE, |
@@ -25,6 +25,12 @@ | @@ -25,6 +25,12 @@ | ||
25 | component: 'InputNumber', | 25 | component: 'InputNumber', |
26 | defaultValue: 14, | 26 | defaultValue: 14, |
27 | }, | 27 | }, |
28 | + { | ||
29 | + field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, | ||
30 | + label: '显示设备名称', | ||
31 | + component: 'Checkbox', | ||
32 | + defaultValue: option.showDeviceName, | ||
33 | + }, | ||
28 | ], | 34 | ], |
29 | showActionButtonGroup: false, | 35 | showActionButtonGroup: false, |
30 | labelWidth: 120, | 36 | labelWidth: 120, |
@@ -9,6 +9,8 @@ | @@ -9,6 +9,8 @@ | ||
9 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 9 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
10 | import { useDataFetch } from '../../../hook/socket/useSocket'; | 10 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
11 | import { getSendValues } from '../config'; | 11 | import { getSendValues } from '../config'; |
12 | + import { useModal } from '/@/components/Modal'; | ||
13 | + import PasswordModal from '../component/PasswordModal.vue'; | ||
12 | 14 | ||
13 | const props = defineProps<{ | 15 | const props = defineProps<{ |
14 | config: ComponentPropsConfigType<typeof option>; | 16 | config: ComponentPropsConfigType<typeof option>; |
@@ -31,11 +33,13 @@ | @@ -31,11 +33,13 @@ | ||
31 | deviceCode, | 33 | deviceCode, |
32 | customCommand, | 34 | customCommand, |
33 | } = option; | 35 | } = option; |
34 | - const { fontSize: persetFontSize } = persetOption || {}; | ||
35 | - const { fontSize } = componentInfo || {}; | 36 | + |
37 | + const { fontSize: persetFontSize, password: persetPassword } = persetOption || {}; | ||
38 | + const { fontSize, password } = componentInfo || {}; | ||
36 | return { | 39 | return { |
37 | attribute: attributeRename || attributeName || attribute, | 40 | attribute: attributeRename || attributeName || attribute, |
38 | fontSize: fontSize || persetFontSize || 14, | 41 | fontSize: fontSize || persetFontSize || 14, |
42 | + password: password || persetPassword, | ||
39 | extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, | 43 | extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, |
40 | commandType, | 44 | commandType, |
41 | codeType, | 45 | codeType, |
@@ -45,7 +49,31 @@ | @@ -45,7 +49,31 @@ | ||
45 | }); | 49 | }); |
46 | 50 | ||
47 | const { sendCommand, loading } = useSendCommand(); | 51 | const { sendCommand, loading } = useSendCommand(); |
52 | + | ||
53 | + const handleSendCommand = async (data) => { | ||
54 | + const { control: event } = data || {}; | ||
55 | + const target = event.target as HTMLInputElement; | ||
56 | + const value = !target.checked; | ||
57 | + 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); | ||
65 | + }; | ||
66 | + | ||
48 | const handleChange = async (event: Event) => { | 67 | const handleChange = async (event: Event) => { |
68 | + if (unref(getDesign).password) { | ||
69 | + const target = event.target as HTMLInputElement; | ||
70 | + const value = target.checked; | ||
71 | + target.checked = !value; | ||
72 | + currentValue.value = !value; | ||
73 | + openModal(true, { password: unref(getDesign).password, control: event }); | ||
74 | + return; | ||
75 | + } | ||
76 | + | ||
49 | const target = event.target as HTMLInputElement; | 77 | const target = event.target as HTMLInputElement; |
50 | const value = target.checked; | 78 | const value = target.checked; |
51 | const { option } = props.config || {}; | 79 | const { option } = props.config || {}; |
@@ -66,6 +94,8 @@ | @@ -66,6 +94,8 @@ | ||
66 | }; | 94 | }; |
67 | 95 | ||
68 | useDataFetch(props, updateFn); | 96 | useDataFetch(props, updateFn); |
97 | + | ||
98 | + const [registerModal, { openModal }] = useModal(); | ||
69 | </script> | 99 | </script> |
70 | 100 | ||
71 | <template> | 101 | <template> |
@@ -95,6 +125,8 @@ | @@ -95,6 +125,8 @@ | ||
95 | </div> | 125 | </div> |
96 | </Spin> | 126 | </Spin> |
97 | </main> | 127 | </main> |
128 | + | ||
129 | + <PasswordModal @register="registerModal" @success="handleSendCommand" /> | ||
98 | </main> | 130 | </main> |
99 | </template> | 131 | </template> |
100 | 132 |
@@ -14,6 +14,7 @@ export const option: PublicPresetOptions = { | @@ -14,6 +14,7 @@ export const option: PublicPresetOptions = { | ||
14 | [ComponentConfigFieldEnum.ICON_COLOR]: '#377DFF', | 14 | [ComponentConfigFieldEnum.ICON_COLOR]: '#377DFF', |
15 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, | 15 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, |
16 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, | 16 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, |
17 | + [ComponentConfigFieldEnum.PASS_WORD]: '', | ||
17 | }; | 18 | }; |
18 | 19 | ||
19 | export default class Config extends PublicConfigClass implements CreateComponentType { | 20 | export default class Config extends PublicConfigClass implements CreateComponentType { |
@@ -38,6 +38,12 @@ | @@ -38,6 +38,12 @@ | ||
38 | component: 'InputNumber', | 38 | component: 'InputNumber', |
39 | defaultValue: option.fontSize, | 39 | defaultValue: option.fontSize, |
40 | }, | 40 | }, |
41 | + { | ||
42 | + field: ComponentConfigFieldEnum.PASS_WORD, | ||
43 | + label: '操作密码', | ||
44 | + component: 'InputPassword', | ||
45 | + defaultValue: '', | ||
46 | + }, | ||
41 | ], | 47 | ], |
42 | showActionButtonGroup: false, | 48 | showActionButtonGroup: false, |
43 | labelWidth: 120, | 49 | labelWidth: 120, |
@@ -11,6 +11,8 @@ | @@ -11,6 +11,8 @@ | ||
11 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 11 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
12 | import { useDataFetch } from '../../../hook/socket/useSocket'; | 12 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
13 | import { getSendValues } from '../config'; | 13 | import { getSendValues } from '../config'; |
14 | + import { useModal } from '/@/components/Modal'; | ||
15 | + import PasswordModal from '../component/PasswordModal.vue'; | ||
14 | 16 | ||
15 | const props = defineProps<{ | 17 | const props = defineProps<{ |
16 | config: ComponentPropsConfigType<typeof option>; | 18 | config: ComponentPropsConfigType<typeof option>; |
@@ -35,8 +37,9 @@ | @@ -35,8 +37,9 @@ | ||
35 | icon: presetIcon, | 37 | icon: presetIcon, |
36 | iconColor: presetIconColor, | 38 | iconColor: presetIconColor, |
37 | fontSize: persetFontSize, | 39 | fontSize: persetFontSize, |
40 | + password: persetPassword, | ||
38 | } = persetOption || {}; | 41 | } = persetOption || {}; |
39 | - const { icon, iconColor, fontSize } = componentInfo || {}; | 42 | + const { icon, iconColor, fontSize, password } = componentInfo || {}; |
40 | 43 | ||
41 | return { | 44 | return { |
42 | icon: icon ?? presetIcon, | 45 | icon: icon ?? presetIcon, |
@@ -44,6 +47,7 @@ | @@ -44,6 +47,7 @@ | ||
44 | attribute: attributeRename || attributeName || attribute, | 47 | attribute: attributeRename || attributeName || attribute, |
45 | extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, | 48 | extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, |
46 | fontSize: fontSize || persetFontSize || 14, | 49 | fontSize: fontSize || persetFontSize || 14, |
50 | + password: password || persetPassword, | ||
47 | commandType, | 51 | commandType, |
48 | codeType, | 52 | codeType, |
49 | deviceCode, | 53 | deviceCode, |
@@ -54,6 +58,11 @@ | @@ -54,6 +58,11 @@ | ||
54 | const { sendCommand, loading } = useSendCommand(); | 58 | const { sendCommand, loading } = useSendCommand(); |
55 | 59 | ||
56 | const handleChange = async () => { | 60 | const handleChange = async () => { |
61 | + if (unref(getDesign).password) { | ||
62 | + openModal(true, { password: unref(getDesign).password }); | ||
63 | + checked.value = !unref(checked); | ||
64 | + return; | ||
65 | + } | ||
57 | const { option } = props.config || {}; | 66 | const { option } = props.config || {}; |
58 | 67 | ||
59 | const { values, isModbusCommand, sendValue } = | 68 | const { values, isModbusCommand, sendValue } = |
@@ -67,6 +76,21 @@ | @@ -67,6 +76,21 @@ | ||
67 | if (!flag) checked.value = !unref(checked); | 76 | if (!flag) checked.value = !unref(checked); |
68 | }; | 77 | }; |
69 | 78 | ||
79 | + const handleSendCommand = async () => { | ||
80 | + 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); | ||
92 | + }; | ||
93 | + | ||
70 | const updateFn: DataFetchUpdateFn = (message, attribute) => { | 94 | const updateFn: DataFetchUpdateFn = (message, attribute) => { |
71 | const { data = {} } = message; | 95 | const { data = {} } = message; |
72 | const [latest] = data[attribute] || []; | 96 | const [latest] = data[attribute] || []; |
@@ -76,6 +100,8 @@ | @@ -76,6 +100,8 @@ | ||
76 | 100 | ||
77 | useDataFetch(props, updateFn); | 101 | useDataFetch(props, updateFn); |
78 | const { getScale, getRatio } = useComponentScale(props); | 102 | const { getScale, getRatio } = useComponentScale(props); |
103 | + | ||
104 | + const [registerModal, { openModal }] = useModal(); | ||
79 | </script> | 105 | </script> |
80 | 106 | ||
81 | <template> | 107 | <template> |
@@ -105,5 +131,6 @@ | @@ -105,5 +131,6 @@ | ||
105 | @change="handleChange" | 131 | @change="handleChange" |
106 | /> | 132 | /> |
107 | </main> | 133 | </main> |
134 | + <PasswordModal @register="registerModal" @success="handleSendCommand" /> | ||
108 | </main> | 135 | </main> |
109 | </template> | 136 | </template> |
@@ -12,6 +12,7 @@ import { ComponentConfigFieldEnum } from '../../../enum'; | @@ -12,6 +12,7 @@ import { ComponentConfigFieldEnum } from '../../../enum'; | ||
12 | export const option: PublicPresetOptions = { | 12 | export const option: PublicPresetOptions = { |
13 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, | 13 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, |
14 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, | 14 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, |
15 | + [ComponentConfigFieldEnum.PASS_WORD]: '', | ||
15 | // [ComponentConfigFieldEnum.FONT_COLOR]: '#000', | 16 | // [ComponentConfigFieldEnum.FONT_COLOR]: '#000', |
16 | }; | 17 | }; |
17 | 18 |
@@ -24,6 +24,12 @@ | @@ -24,6 +24,12 @@ | ||
24 | component: 'InputNumber', | 24 | component: 'InputNumber', |
25 | defaultValue: option.fontSize, | 25 | defaultValue: option.fontSize, |
26 | }, | 26 | }, |
27 | + { | ||
28 | + field: ComponentConfigFieldEnum.PASS_WORD, | ||
29 | + label: '操作密码', | ||
30 | + component: 'InputPassword', | ||
31 | + defaultValue: '', | ||
32 | + }, | ||
27 | ], | 33 | ], |
28 | showActionButtonGroup: false, | 34 | showActionButtonGroup: false, |
29 | labelWidth: 120, | 35 | labelWidth: 120, |
@@ -9,6 +9,8 @@ | @@ -9,6 +9,8 @@ | ||
9 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; | 9 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
10 | import { useDataFetch } from '../../../hook/socket/useSocket'; | 10 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
11 | import { getSendValues } from '../config'; | 11 | import { getSendValues } from '../config'; |
12 | + import PasswordModal from '../component/PasswordModal.vue'; | ||
13 | + import { useModal } from '/@/components/Modal'; | ||
12 | 14 | ||
13 | const props = defineProps<{ | 15 | const props = defineProps<{ |
14 | config: ComponentPropsConfigType<typeof option>; | 16 | config: ComponentPropsConfigType<typeof option>; |
@@ -31,11 +33,12 @@ | @@ -31,11 +33,12 @@ | ||
31 | customCommand, | 33 | customCommand, |
32 | componentInfo, | 34 | componentInfo, |
33 | } = option; | 35 | } = option; |
34 | - const { fontSize: persetFontSize } = persetOption || {}; | ||
35 | - const { fontSize } = componentInfo || {}; | 36 | + const { fontSize: persetFontSize, password: persetPassword } = persetOption || {}; |
37 | + const { fontSize, password } = componentInfo || {}; | ||
36 | return { | 38 | return { |
37 | attribute: attributeRename || attributeName || attribute, | 39 | attribute: attributeRename || attributeName || attribute, |
38 | extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, | 40 | extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, |
41 | + password: password || persetPassword, | ||
39 | commandType, | 42 | commandType, |
40 | codeType, | 43 | codeType, |
41 | deviceCode, | 44 | deviceCode, |
@@ -46,6 +49,15 @@ | @@ -46,6 +49,15 @@ | ||
46 | 49 | ||
47 | const { loading, sendCommand } = useSendCommand(); | 50 | const { loading, sendCommand } = useSendCommand(); |
48 | const handleChange = async (event: Event) => { | 51 | const handleChange = async (event: Event) => { |
52 | + if (unref(getDesign).password) { | ||
53 | + const target = event.target as HTMLInputElement; | ||
54 | + const value = target.checked; | ||
55 | + target.checked = !value; | ||
56 | + currentValue.value = !value; | ||
57 | + openModal(true, { password: unref(getDesign).password, control: event }); | ||
58 | + return; | ||
59 | + } | ||
60 | + | ||
49 | const target = event.target as HTMLInputElement; | 61 | const target = event.target as HTMLInputElement; |
50 | const value = target.checked; | 62 | const value = target.checked; |
51 | const { option } = props.config || {}; | 63 | const { option } = props.config || {}; |
@@ -57,6 +69,19 @@ | @@ -57,6 +69,19 @@ | ||
57 | flag ? (currentValue.value = value) : (target.checked = !value); | 69 | flag ? (currentValue.value = value) : (target.checked = !value); |
58 | }; | 70 | }; |
59 | 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); | ||
83 | + }; | ||
84 | + | ||
60 | const updateFn: DataFetchUpdateFn = (message, attribute) => { | 85 | const updateFn: DataFetchUpdateFn = (message, attribute) => { |
61 | const { data = {} } = message; | 86 | const { data = {} } = message; |
62 | const [latest] = data[attribute] || []; | 87 | const [latest] = data[attribute] || []; |
@@ -65,6 +90,7 @@ | @@ -65,6 +90,7 @@ | ||
65 | }; | 90 | }; |
66 | 91 | ||
67 | useDataFetch(props, updateFn); | 92 | useDataFetch(props, updateFn); |
93 | + const [registerModal, { openModal }] = useModal(); | ||
68 | </script> | 94 | </script> |
69 | 95 | ||
70 | <template> | 96 | <template> |
@@ -94,6 +120,8 @@ | @@ -94,6 +120,8 @@ | ||
94 | > | 120 | > |
95 | </Spin> | 121 | </Spin> |
96 | </main> | 122 | </main> |
123 | + | ||
124 | + <PasswordModal @register="registerModal" @success="handleSendCommand" /> | ||
97 | </main> | 125 | </main> |
98 | </template> | 126 | </template> |
99 | 127 |
@@ -18,6 +18,7 @@ export const option: PublicPresetOptions = { | @@ -18,6 +18,7 @@ export const option: PublicPresetOptions = { | ||
18 | [ComponentConfigFieldEnum.MAX_NUMBER]: 100, | 18 | [ComponentConfigFieldEnum.MAX_NUMBER]: 100, |
19 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, | 19 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, |
20 | [ComponentConfigFieldEnum.VALUE_SIZE]: 20, | 20 | [ComponentConfigFieldEnum.VALUE_SIZE]: 20, |
21 | + [ComponentConfigFieldEnum.PASS_WORD]: '', | ||
21 | }; | 22 | }; |
22 | 23 | ||
23 | export default class Config extends PublicConfigClass implements CreateComponentType { | 24 | export default class Config extends PublicConfigClass implements CreateComponentType { |
@@ -87,6 +87,13 @@ | @@ -87,6 +87,13 @@ | ||
87 | component: 'Checkbox', | 87 | component: 'Checkbox', |
88 | defaultValue: option.showDeviceName, | 88 | defaultValue: option.showDeviceName, |
89 | }, | 89 | }, |
90 | + | ||
91 | + { | ||
92 | + field: ComponentConfigFieldEnum.PASS_WORD, | ||
93 | + label: '操作密码', | ||
94 | + component: 'InputPassword', | ||
95 | + defaultValue: '', | ||
96 | + }, | ||
90 | ], | 97 | ], |
91 | showActionButtonGroup: false, | 98 | showActionButtonGroup: false, |
92 | labelWidth: 120, | 99 | labelWidth: 120, |
@@ -13,6 +13,8 @@ | @@ -13,6 +13,8 @@ | ||
13 | import { useMessage } from '/@/hooks/web/useMessage'; | 13 | import { useMessage } from '/@/hooks/web/useMessage'; |
14 | import { SingleToHex } from '/@/views/device/list/cpns/tabs/ObjectModelCommandDeliveryModal/config'; | 14 | import { SingleToHex } from '/@/views/device/list/cpns/tabs/ObjectModelCommandDeliveryModal/config'; |
15 | import { genModbusCommand } from '/@/api/task'; | 15 | import { genModbusCommand } from '/@/api/task'; |
16 | + import PasswordModal from '../component/PasswordModal.vue'; | ||
17 | + import { useModal } from '/@/components/Modal'; | ||
16 | 18 | ||
17 | const props = defineProps<{ | 19 | const props = defineProps<{ |
18 | config: ComponentPropsConfigType<typeof option>; | 20 | config: ComponentPropsConfigType<typeof option>; |
@@ -46,9 +48,18 @@ | @@ -46,9 +48,18 @@ | ||
46 | textColor: persetTextColor, | 48 | textColor: persetTextColor, |
47 | valueSize: persetValueSize, | 49 | valueSize: persetValueSize, |
48 | fontSize: persetFontSize, | 50 | fontSize: persetFontSize, |
51 | + password: persetPassword, | ||
49 | } = persetOption || {}; | 52 | } = persetOption || {}; |
50 | - const { controlBarColor, fontColor, minNumber, maxNumber, textColor, valueSize, fontSize } = | ||
51 | - componentInfo || {}; | 53 | + const { |
54 | + controlBarColor, | ||
55 | + password, | ||
56 | + fontColor, | ||
57 | + minNumber, | ||
58 | + maxNumber, | ||
59 | + textColor, | ||
60 | + valueSize, | ||
61 | + fontSize, | ||
62 | + } = componentInfo || {}; | ||
52 | return { | 63 | return { |
53 | attribute: attributeRename || attributeName || attribute, | 64 | attribute: attributeRename || attributeName || attribute, |
54 | controlBarColor: controlBarColor ?? persetControlBarColor, | 65 | controlBarColor: controlBarColor ?? persetControlBarColor, |
@@ -63,6 +74,7 @@ | @@ -63,6 +74,7 @@ | ||
63 | textColor: textColor || persetTextColor, | 74 | textColor: textColor || persetTextColor, |
64 | valueSize: valueSize || persetValueSize || 20, | 75 | valueSize: valueSize || persetValueSize || 20, |
65 | fontSize: fontSize || persetFontSize || 14, | 76 | fontSize: fontSize || persetFontSize || 14, |
77 | + password: password || persetPassword, | ||
66 | }; | 78 | }; |
67 | }); | 79 | }); |
68 | 80 | ||
@@ -82,6 +94,7 @@ | @@ -82,6 +94,7 @@ | ||
82 | const handleAfterChange = async () => { | 94 | const handleAfterChange = async () => { |
83 | unref(sliderEl)?.blur(); | 95 | unref(sliderEl)?.blur(); |
84 | if (unref(sliderValue) == unref(afterValue)) return; | 96 | if (unref(sliderValue) == unref(afterValue)) return; |
97 | + if (unref(getDesign).password) return; | ||
85 | sliderValue.value = afterValue.value; //这一步是因为当我们是点击不是拖动时候,会让值更新不了,所以需要赋值一次 | 98 | sliderValue.value = afterValue.value; //这一步是因为当我们是点击不是拖动时候,会让值更新不了,所以需要赋值一次 |
86 | }; | 99 | }; |
87 | 100 | ||
@@ -169,6 +182,33 @@ | @@ -169,6 +182,33 @@ | ||
169 | }; | 182 | }; |
170 | 183 | ||
171 | const handleBlur = async () => { | 184 | const handleBlur = async () => { |
185 | + if (unref(getDesign).password) { | ||
186 | + sliderValue.value = oldSliderValue.value; | ||
187 | + openModal(true, { password: unref(getDesign).password, value: afterValue.value }); | ||
188 | + return; | ||
189 | + } | ||
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 | + } | ||
207 | + }; | ||
208 | + | ||
209 | + const handleSendCommand = async (data) => { | ||
210 | + const { value } = data || {}; | ||
211 | + sliderValue.value = value; | ||
172 | if (unref(oldSliderValue) !== unref(sliderValue)) { | 212 | if (unref(oldSliderValue) !== unref(sliderValue)) { |
173 | const { codeType, customCommand } = unref(getDesign) || {}; | 213 | const { codeType, customCommand } = unref(getDesign) || {}; |
174 | const { transportType } = customCommand || {}; | 214 | const { transportType } = customCommand || {}; |
@@ -199,6 +239,7 @@ | @@ -199,6 +239,7 @@ | ||
199 | 239 | ||
200 | useDataFetch(props, updateFn); | 240 | useDataFetch(props, updateFn); |
201 | const { getScale, getRatio } = useComponentScale(props); | 241 | const { getScale, getRatio } = useComponentScale(props); |
242 | + const [registerModal, { openModal }] = useModal(); | ||
202 | </script> | 243 | </script> |
203 | 244 | ||
204 | <template> | 245 | <template> |
@@ -244,6 +285,7 @@ | @@ -244,6 +285,7 @@ | ||
244 | </div> | 285 | </div> |
245 | </Spin> | 286 | </Spin> |
246 | </main> | 287 | </main> |
288 | + <PasswordModal @register="registerModal" @success="handleSendCommand" /> | ||
247 | </main> | 289 | </main> |
248 | </template> | 290 | </template> |
249 | <style lang="less" scoped> | 291 | <style lang="less" scoped> |
@@ -15,6 +15,7 @@ export const option: PublicPresetOptions = { | @@ -15,6 +15,7 @@ export const option: PublicPresetOptions = { | ||
15 | [ComponentConfigFieldEnum.ICON_COLOR]: '#377DFF', | 15 | [ComponentConfigFieldEnum.ICON_COLOR]: '#377DFF', |
16 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, | 16 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, |
17 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, | 17 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, |
18 | + [ComponentConfigFieldEnum.PASS_WORD]: '', | ||
18 | }; | 19 | }; |
19 | 20 | ||
20 | export default class Config extends PublicConfigClass implements CreateComponentType { | 21 | export default class Config extends PublicConfigClass implements CreateComponentType { |
@@ -38,6 +38,12 @@ | @@ -38,6 +38,12 @@ | ||
38 | component: 'Checkbox', | 38 | component: 'Checkbox', |
39 | defaultValue: option.showDeviceName, | 39 | defaultValue: option.showDeviceName, |
40 | }, | 40 | }, |
41 | + { | ||
42 | + field: ComponentConfigFieldEnum.PASS_WORD, | ||
43 | + label: '操作密码', | ||
44 | + component: 'InputPassword', | ||
45 | + defaultValue: '', | ||
46 | + }, | ||
41 | ], | 47 | ], |
42 | showActionButtonGroup: false, | 48 | showActionButtonGroup: false, |
43 | labelWidth: 120, | 49 | labelWidth: 120, |
@@ -14,6 +14,8 @@ | @@ -14,6 +14,8 @@ | ||
14 | import { useReceiveValue } from '../../../hook/useReceiveValue'; | 14 | import { useReceiveValue } from '../../../hook/useReceiveValue'; |
15 | import { DataSource } from '/@/views/visual/palette/types'; | 15 | import { DataSource } from '/@/views/visual/palette/types'; |
16 | import { getSendValues, CommandTypeEnumLIst } from '../config'; | 16 | import { getSendValues, CommandTypeEnumLIst } from '../config'; |
17 | + import { useModal } from '/@/components/Modal'; | ||
18 | + import PasswordModal from '../component/PasswordModal.vue'; | ||
17 | 19 | ||
18 | const props = defineProps<{ | 20 | const props = defineProps<{ |
19 | config: ComponentPropsConfigType<typeof option>; | 21 | config: ComponentPropsConfigType<typeof option>; |
@@ -53,10 +55,12 @@ | @@ -53,10 +55,12 @@ | ||
53 | icon: persetIcon, | 55 | icon: persetIcon, |
54 | iconColor: persetIconColor, | 56 | iconColor: persetIconColor, |
55 | fontSize: persetFontSize, | 57 | fontSize: persetFontSize, |
58 | + password: persetPassword, | ||
56 | } = persetOption || {}; | 59 | } = persetOption || {}; |
57 | return { | 60 | return { |
58 | dataSource: dataSource.map((item) => { | 61 | dataSource: dataSource.map((item) => { |
59 | - const { fontColor, icon, iconColor, unit, showDeviceName, fontSize } = item.componentInfo; | 62 | + const { fontColor, icon, iconColor, unit, showDeviceName, password, fontSize } = |
63 | + item.componentInfo; | ||
60 | const { | 64 | const { |
61 | attribute, | 65 | attribute, |
62 | attributeRename, | 66 | attributeRename, |
@@ -86,13 +90,19 @@ | @@ -86,13 +90,19 @@ | ||
86 | deviceCode, | 90 | deviceCode, |
87 | customCommand, | 91 | customCommand, |
88 | fontSize: fontSize || persetFontSize || 14, | 92 | fontSize: fontSize || persetFontSize || 14, |
93 | + password: password || persetPassword, | ||
89 | }; | 94 | }; |
90 | }), | 95 | }), |
91 | }; | 96 | }; |
92 | }); | 97 | }); |
93 | 98 | ||
94 | const { loading, sendCommand } = useSendCommand(); | 99 | const { loading, sendCommand } = useSendCommand(); |
95 | - const handleChange = async (index: number, checked: Boolean) => { | 100 | + const handleChange = async (index: number, checked: Boolean, item: any) => { |
101 | + if (item.password) { | ||
102 | + openModal(true, { password: item.password, index, checked }); | ||
103 | + controlList.value[index].checked = !checked; | ||
104 | + return; | ||
105 | + } | ||
96 | const { heightPx, itemHeightRatio, itemWidthRatio, mode, widthPx, dataSource } = | 106 | const { heightPx, itemHeightRatio, itemWidthRatio, mode, widthPx, dataSource } = |
97 | props.config.option; | 107 | props.config.option; |
98 | const data = { | 108 | const data = { |
@@ -120,6 +130,25 @@ | @@ -120,6 +130,25 @@ | ||
120 | }) | 130 | }) |
121 | : svgList | 131 | : svgList |
122 | ); | 132 | ); |
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 | + | ||
149 | + const flag = await sendCommand(values, isModbusCommand ? sendValue : checked, isModbusCommand); | ||
150 | + if (!flag) controlList.value[index].checked = !checked; | ||
151 | + }; | ||
123 | 152 | ||
124 | const updateFn: MultipleDataFetchUpdateFn = async (message, deviceId, attribute) => { | 153 | const updateFn: MultipleDataFetchUpdateFn = async (message, deviceId, attribute) => { |
125 | forEachGroupMessage(message, deviceId, attribute, (attribute, value) => { | 154 | forEachGroupMessage(message, deviceId, attribute, (attribute, value) => { |
@@ -133,6 +162,7 @@ | @@ -133,6 +162,7 @@ | ||
133 | 162 | ||
134 | useMultipleDataFetch(props, updateFn); | 163 | useMultipleDataFetch(props, updateFn); |
135 | const { getRatio } = useComponentScale(props); | 164 | const { getRatio } = useComponentScale(props); |
165 | + const [registerModal, { openModal }] = useModal(); | ||
136 | </script> | 166 | </script> |
137 | 167 | ||
138 | <template> | 168 | <template> |
@@ -166,9 +196,10 @@ | @@ -166,9 +196,10 @@ | ||
166 | <Switch | 196 | <Switch |
167 | v-model:checked="item.checked" | 197 | v-model:checked="item.checked" |
168 | :loading="loading" | 198 | :loading="loading" |
169 | - @change="handleChange(index, item.checked)" | 199 | + @change="handleChange(index, item.checked, item)" |
170 | :style="{ transform: `scale(${getRatio || 1})` }" | 200 | :style="{ transform: `scale(${getRatio || 1})` }" |
171 | /> | 201 | /> |
172 | </div> | 202 | </div> |
203 | + <PasswordModal @register="registerModal" @success="handleSendCommand" /> | ||
173 | </main> | 204 | </main> |
174 | </template> | 205 | </template> |
1 | +<template> | ||
2 | + <div> | ||
3 | + <BasicModal | ||
4 | + destroyOnClose | ||
5 | + v-bind="$attrs" | ||
6 | + width="30rem" | ||
7 | + :height="50" | ||
8 | + :minHeight="50" | ||
9 | + @register="register" | ||
10 | + title="操作密码" | ||
11 | + @ok="handleSuccess" | ||
12 | + @cancel="handleClose" | ||
13 | + > | ||
14 | + <div> | ||
15 | + <BasicForm @register="registerForm" /> | ||
16 | + </div> | ||
17 | + </BasicModal> | ||
18 | + </div> | ||
19 | +</template> | ||
20 | +<script setup lang="ts"> | ||
21 | + import { BasicModal, useModalInner } from '/@/components/Modal'; | ||
22 | + import { useForm, BasicForm } from '/@/components/Form'; | ||
23 | + import { formSchema } from './config'; | ||
24 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
25 | + import { ref, unref } from 'vue'; | ||
26 | + | ||
27 | + const emit = defineEmits(['register', 'success', 'cancel']); | ||
28 | + | ||
29 | + const persetData = ref<{ [key: string]: string | number }>({}); | ||
30 | + | ||
31 | + const { createMessage } = useMessage(); | ||
32 | + | ||
33 | + const [registerForm, { getFieldsValue, validate }] = useForm({ | ||
34 | + labelWidth: 70, | ||
35 | + schemas: formSchema, | ||
36 | + showActionButtonGroup: false, | ||
37 | + }); | ||
38 | + | ||
39 | + const [register, { setModalProps, closeModal }] = useModalInner(async (data) => { | ||
40 | + setModalProps({ loading: true }); | ||
41 | + persetData.value = data; | ||
42 | + setModalProps({ loading: false }); | ||
43 | + }); | ||
44 | + | ||
45 | + const handleClose = () => { | ||
46 | + emit('cancel'); | ||
47 | + closeModal(); | ||
48 | + }; | ||
49 | + | ||
50 | + const handleSuccess = async () => { | ||
51 | + await validate(); | ||
52 | + const { password: passwordField } = getFieldsValue(); | ||
53 | + if (unref(persetData).password != passwordField) { | ||
54 | + createMessage.warning('操作密码不正确'); | ||
55 | + return; | ||
56 | + } | ||
57 | + emit('success', unref(persetData)); | ||
58 | + closeModal(); | ||
59 | + }; | ||
60 | +</script> | ||
61 | +<style lang="less" scoped></style> |
1 | +import { FormSchema } from '/@/components/Form'; | ||
2 | + | ||
3 | +export const formSchema: FormSchema[] = [ | ||
4 | + { | ||
5 | + field: 'password', | ||
6 | + label: '操作密码', | ||
7 | + colProps: { span: 16 }, | ||
8 | + component: 'InputPassword', | ||
9 | + required: true, | ||
10 | + componentProps: { | ||
11 | + placeholder: '请输入操作密码', | ||
12 | + max: 120, | ||
13 | + }, | ||
14 | + }, | ||
15 | +]; |
@@ -15,6 +15,7 @@ import { TransportTypeEnum } from '/@/views/device/profiles/components/Transport | @@ -15,6 +15,7 @@ import { TransportTypeEnum } from '/@/views/device/profiles/components/Transport | ||
15 | import { CommandTypeEnum } from '/@/views/rule/linkedge/config/config.data'; | 15 | import { CommandTypeEnum } from '/@/views/rule/linkedge/config/config.data'; |
16 | import { DataActionModeEnum } from '/@/enums/toolEnum'; | 16 | import { DataActionModeEnum } from '/@/enums/toolEnum'; |
17 | import { TaskTypeEnum } from '/@/views/task/center/config'; | 17 | import { TaskTypeEnum } from '/@/views/task/center/config'; |
18 | +import { createPickerSearch } from '/@/utils/pickerSearch'; | ||
18 | 19 | ||
19 | useComponentRegister('OrgTreeSelect', OrgTreeSelect); | 20 | useComponentRegister('OrgTreeSelect', OrgTreeSelect); |
20 | 21 | ||
@@ -247,6 +248,7 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -247,6 +248,7 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
247 | }, | 248 | }, |
248 | placeholder: '请选择设备', | 249 | placeholder: '请选择设备', |
249 | getPopupContainer: () => document.body, | 250 | getPopupContainer: () => document.body, |
251 | + ...createPickerSearch(), | ||
250 | }; | 252 | }; |
251 | }, | 253 | }, |
252 | }, | 254 | }, |
@@ -387,6 +389,7 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | @@ -387,6 +389,7 @@ export const commonDataSourceSchemas = (): FormSchema[] => { | ||
387 | [DataSourceField.EXTENSION_DESC]: value ? JSON.stringify(option.extensionDesc) : '', | 389 | [DataSourceField.EXTENSION_DESC]: value ? JSON.stringify(option.extensionDesc) : '', |
388 | }); | 390 | }); |
389 | }, | 391 | }, |
392 | + ...createPickerSearch(), | ||
390 | }; | 393 | }; |
391 | }, | 394 | }, |
392 | }, | 395 | }, |
@@ -35,4 +35,5 @@ export enum ComponentConfigFieldEnum { | @@ -35,4 +35,5 @@ export enum ComponentConfigFieldEnum { | ||
35 | CLOSE_COLOR = 'closeColor', | 35 | CLOSE_COLOR = 'closeColor', |
36 | MIN_NUMBER = 'minNumber', | 36 | MIN_NUMBER = 'minNumber', |
37 | MAX_NUMBER = 'maxNumber', | 37 | MAX_NUMBER = 'maxNumber', |
38 | + PASS_WORD = 'password', //操作密码 | ||
38 | } | 39 | } |