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 | v-model:value="param.attributes" |
7 | 7 | class="!w-1/2" |
8 | 8 | :options="selectOptions" |
9 | + v-bind="createPickerSearch()" | |
9 | 10 | :disabled="disabled" |
10 | 11 | @change="emitChange" |
11 | 12 | mode="multiple" |
... | ... | @@ -24,6 +25,7 @@ |
24 | 25 | import { Select } from 'ant-design-vue'; |
25 | 26 | import { Params } from '../type/'; |
26 | 27 | import { useHooks } from '../hooks/index.hooks'; |
28 | + import { createPickerSearch } from '/@/utils/pickerSearch'; | |
27 | 29 | |
28 | 30 | const props = defineProps({ |
29 | 31 | value: propTypes.object.def({}), | ... | ... |
... | ... | @@ -32,12 +32,10 @@ |
32 | 32 | class="min-w-25" |
33 | 33 | v-model:value="item.active" |
34 | 34 | @change="(value) => handleChangeChars(value, item.device, item)" |
35 | + v-bind="createPickerSearch()" | |
35 | 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 | 39 | </div> |
42 | 40 | <div class="w-full h-full flex justify-center items-center"> |
43 | 41 | <Empty v-show="item.notFoundData" description="暂无数据" class="text-dark-50" /> |
... | ... | @@ -65,6 +63,7 @@ |
65 | 63 | import moment from 'moment'; |
66 | 64 | import { ExecuteReportRecord } from '/@/api/export/model/exportModel'; |
67 | 65 | import { Select, Spin, Empty } from 'ant-design-vue'; |
66 | + import { createPickerSearch } from '/@/utils/pickerSearch'; | |
68 | 67 | |
69 | 68 | interface ResponsData { |
70 | 69 | attr: string; | ... | ... |
... | ... | @@ -8,6 +8,7 @@ import { findDictItemByCode } from '/@/api/system/dict'; |
8 | 8 | // import { unref } from 'vue'; |
9 | 9 | import { getMeetTheConditionsDevice } from '/@/api/dataBoard'; |
10 | 10 | import { MasterDeviceList } from '/@/api/dataBoard/model'; |
11 | +import { createPickerSearch } from '/@/utils/pickerSearch'; | |
11 | 12 | |
12 | 13 | export const formSchemas = (): FormSchema[] => { |
13 | 14 | // const mode = useSelectWidgetMode(); |
... | ... | @@ -150,7 +151,6 @@ export const formSchemas = (): FormSchema[] => { |
150 | 151 | return []; |
151 | 152 | }, |
152 | 153 | onChange(_value, record: MasterDeviceList) { |
153 | - console.log(record, 'record'); | |
154 | 154 | setFieldsValue({ |
155 | 155 | [DataSourceField.DEVICE_NAME]: record?.label, |
156 | 156 | deviceIds: record?.id, |
... | ... | @@ -158,6 +158,7 @@ export const formSchemas = (): FormSchema[] => { |
158 | 158 | }, |
159 | 159 | placeholder: '请选择设备', |
160 | 160 | getPopupContainer: () => document.body, |
161 | + ...createPickerSearch(), | |
161 | 162 | }; |
162 | 163 | }, |
163 | 164 | }, | ... | ... |
... | ... | @@ -12,6 +12,7 @@ import { ComponentConfigFieldEnum } from '../../../enum'; |
12 | 12 | export const option: PublicPresetOptions = { |
13 | 13 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, |
14 | 14 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, |
15 | + [ComponentConfigFieldEnum.PASS_WORD]: '', | |
15 | 16 | // [ComponentConfigFieldEnum.FONT_COLOR]: '#000', |
16 | 17 | }; |
17 | 18 | ... | ... |
... | ... | @@ -14,10 +14,10 @@ |
14 | 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 | 23 | field: ComponentConfigFieldEnum.FONT_SIZE, |
... | ... | @@ -25,6 +25,12 @@ |
25 | 25 | component: 'InputNumber', |
26 | 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 | 35 | showActionButtonGroup: false, |
30 | 36 | labelWidth: 120, | ... | ... |
... | ... | @@ -9,6 +9,8 @@ |
9 | 9 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
10 | 10 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
11 | 11 | import { getSendValues } from '../config'; |
12 | + import { useModal } from '/@/components/Modal'; | |
13 | + import PasswordModal from '../component/PasswordModal.vue'; | |
12 | 14 | |
13 | 15 | const props = defineProps<{ |
14 | 16 | config: ComponentPropsConfigType<typeof option>; |
... | ... | @@ -31,11 +33,13 @@ |
31 | 33 | deviceCode, |
32 | 34 | customCommand, |
33 | 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 | 39 | return { |
37 | 40 | attribute: attributeRename || attributeName || attribute, |
38 | 41 | fontSize: fontSize || persetFontSize || 14, |
42 | + password: password || persetPassword, | |
39 | 43 | extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, |
40 | 44 | commandType, |
41 | 45 | codeType, |
... | ... | @@ -45,7 +49,31 @@ |
45 | 49 | }); |
46 | 50 | |
47 | 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 | 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 | 77 | const target = event.target as HTMLInputElement; |
50 | 78 | const value = target.checked; |
51 | 79 | const { option } = props.config || {}; |
... | ... | @@ -66,6 +94,8 @@ |
66 | 94 | }; |
67 | 95 | |
68 | 96 | useDataFetch(props, updateFn); |
97 | + | |
98 | + const [registerModal, { openModal }] = useModal(); | |
69 | 99 | </script> |
70 | 100 | |
71 | 101 | <template> |
... | ... | @@ -95,6 +125,8 @@ |
95 | 125 | </div> |
96 | 126 | </Spin> |
97 | 127 | </main> |
128 | + | |
129 | + <PasswordModal @register="registerModal" @success="handleSendCommand" /> | |
98 | 130 | </main> |
99 | 131 | </template> |
100 | 132 | ... | ... |
... | ... | @@ -14,6 +14,7 @@ export const option: PublicPresetOptions = { |
14 | 14 | [ComponentConfigFieldEnum.ICON_COLOR]: '#377DFF', |
15 | 15 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, |
16 | 16 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, |
17 | + [ComponentConfigFieldEnum.PASS_WORD]: '', | |
17 | 18 | }; |
18 | 19 | |
19 | 20 | export default class Config extends PublicConfigClass implements CreateComponentType { | ... | ... |
... | ... | @@ -38,6 +38,12 @@ |
38 | 38 | component: 'InputNumber', |
39 | 39 | defaultValue: option.fontSize, |
40 | 40 | }, |
41 | + { | |
42 | + field: ComponentConfigFieldEnum.PASS_WORD, | |
43 | + label: '操作密码', | |
44 | + component: 'InputPassword', | |
45 | + defaultValue: '', | |
46 | + }, | |
41 | 47 | ], |
42 | 48 | showActionButtonGroup: false, |
43 | 49 | labelWidth: 120, | ... | ... |
... | ... | @@ -11,6 +11,8 @@ |
11 | 11 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
12 | 12 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
13 | 13 | import { getSendValues } from '../config'; |
14 | + import { useModal } from '/@/components/Modal'; | |
15 | + import PasswordModal from '../component/PasswordModal.vue'; | |
14 | 16 | |
15 | 17 | const props = defineProps<{ |
16 | 18 | config: ComponentPropsConfigType<typeof option>; |
... | ... | @@ -35,8 +37,9 @@ |
35 | 37 | icon: presetIcon, |
36 | 38 | iconColor: presetIconColor, |
37 | 39 | fontSize: persetFontSize, |
40 | + password: persetPassword, | |
38 | 41 | } = persetOption || {}; |
39 | - const { icon, iconColor, fontSize } = componentInfo || {}; | |
42 | + const { icon, iconColor, fontSize, password } = componentInfo || {}; | |
40 | 43 | |
41 | 44 | return { |
42 | 45 | icon: icon ?? presetIcon, |
... | ... | @@ -44,6 +47,7 @@ |
44 | 47 | attribute: attributeRename || attributeName || attribute, |
45 | 48 | extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, |
46 | 49 | fontSize: fontSize || persetFontSize || 14, |
50 | + password: password || persetPassword, | |
47 | 51 | commandType, |
48 | 52 | codeType, |
49 | 53 | deviceCode, |
... | ... | @@ -54,6 +58,11 @@ |
54 | 58 | const { sendCommand, loading } = useSendCommand(); |
55 | 59 | |
56 | 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 | 66 | const { option } = props.config || {}; |
58 | 67 | |
59 | 68 | const { values, isModbusCommand, sendValue } = |
... | ... | @@ -67,6 +76,21 @@ |
67 | 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 | 94 | const updateFn: DataFetchUpdateFn = (message, attribute) => { |
71 | 95 | const { data = {} } = message; |
72 | 96 | const [latest] = data[attribute] || []; |
... | ... | @@ -76,6 +100,8 @@ |
76 | 100 | |
77 | 101 | useDataFetch(props, updateFn); |
78 | 102 | const { getScale, getRatio } = useComponentScale(props); |
103 | + | |
104 | + const [registerModal, { openModal }] = useModal(); | |
79 | 105 | </script> |
80 | 106 | |
81 | 107 | <template> |
... | ... | @@ -105,5 +131,6 @@ |
105 | 131 | @change="handleChange" |
106 | 132 | /> |
107 | 133 | </main> |
134 | + <PasswordModal @register="registerModal" @success="handleSendCommand" /> | |
108 | 135 | </main> |
109 | 136 | </template> | ... | ... |
... | ... | @@ -12,6 +12,7 @@ import { ComponentConfigFieldEnum } from '../../../enum'; |
12 | 12 | export const option: PublicPresetOptions = { |
13 | 13 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, |
14 | 14 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, |
15 | + [ComponentConfigFieldEnum.PASS_WORD]: '', | |
15 | 16 | // [ComponentConfigFieldEnum.FONT_COLOR]: '#000', |
16 | 17 | }; |
17 | 18 | ... | ... |
... | ... | @@ -24,6 +24,12 @@ |
24 | 24 | component: 'InputNumber', |
25 | 25 | defaultValue: option.fontSize, |
26 | 26 | }, |
27 | + { | |
28 | + field: ComponentConfigFieldEnum.PASS_WORD, | |
29 | + label: '操作密码', | |
30 | + component: 'InputPassword', | |
31 | + defaultValue: '', | |
32 | + }, | |
27 | 33 | ], |
28 | 34 | showActionButtonGroup: false, |
29 | 35 | labelWidth: 120, | ... | ... |
... | ... | @@ -9,6 +9,8 @@ |
9 | 9 | import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; |
10 | 10 | import { useDataFetch } from '../../../hook/socket/useSocket'; |
11 | 11 | import { getSendValues } from '../config'; |
12 | + import PasswordModal from '../component/PasswordModal.vue'; | |
13 | + import { useModal } from '/@/components/Modal'; | |
12 | 14 | |
13 | 15 | const props = defineProps<{ |
14 | 16 | config: ComponentPropsConfigType<typeof option>; |
... | ... | @@ -31,11 +33,12 @@ |
31 | 33 | customCommand, |
32 | 34 | componentInfo, |
33 | 35 | } = option; |
34 | - const { fontSize: persetFontSize } = persetOption || {}; | |
35 | - const { fontSize } = componentInfo || {}; | |
36 | + const { fontSize: persetFontSize, password: persetPassword } = persetOption || {}; | |
37 | + const { fontSize, password } = componentInfo || {}; | |
36 | 38 | return { |
37 | 39 | attribute: attributeRename || attributeName || attribute, |
38 | 40 | extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {}, |
41 | + password: password || persetPassword, | |
39 | 42 | commandType, |
40 | 43 | codeType, |
41 | 44 | deviceCode, |
... | ... | @@ -46,6 +49,15 @@ |
46 | 49 | |
47 | 50 | const { loading, sendCommand } = useSendCommand(); |
48 | 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 | 61 | const target = event.target as HTMLInputElement; |
50 | 62 | const value = target.checked; |
51 | 63 | const { option } = props.config || {}; |
... | ... | @@ -57,6 +69,19 @@ |
57 | 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 | 85 | const updateFn: DataFetchUpdateFn = (message, attribute) => { |
61 | 86 | const { data = {} } = message; |
62 | 87 | const [latest] = data[attribute] || []; |
... | ... | @@ -65,6 +90,7 @@ |
65 | 90 | }; |
66 | 91 | |
67 | 92 | useDataFetch(props, updateFn); |
93 | + const [registerModal, { openModal }] = useModal(); | |
68 | 94 | </script> |
69 | 95 | |
70 | 96 | <template> |
... | ... | @@ -94,6 +120,8 @@ |
94 | 120 | > |
95 | 121 | </Spin> |
96 | 122 | </main> |
123 | + | |
124 | + <PasswordModal @register="registerModal" @success="handleSendCommand" /> | |
97 | 125 | </main> |
98 | 126 | </template> |
99 | 127 | ... | ... |
... | ... | @@ -18,6 +18,7 @@ export const option: PublicPresetOptions = { |
18 | 18 | [ComponentConfigFieldEnum.MAX_NUMBER]: 100, |
19 | 19 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, |
20 | 20 | [ComponentConfigFieldEnum.VALUE_SIZE]: 20, |
21 | + [ComponentConfigFieldEnum.PASS_WORD]: '', | |
21 | 22 | }; |
22 | 23 | |
23 | 24 | export default class Config extends PublicConfigClass implements CreateComponentType { | ... | ... |
... | ... | @@ -87,6 +87,13 @@ |
87 | 87 | component: 'Checkbox', |
88 | 88 | defaultValue: option.showDeviceName, |
89 | 89 | }, |
90 | + | |
91 | + { | |
92 | + field: ComponentConfigFieldEnum.PASS_WORD, | |
93 | + label: '操作密码', | |
94 | + component: 'InputPassword', | |
95 | + defaultValue: '', | |
96 | + }, | |
90 | 97 | ], |
91 | 98 | showActionButtonGroup: false, |
92 | 99 | labelWidth: 120, | ... | ... |
... | ... | @@ -13,6 +13,8 @@ |
13 | 13 | import { useMessage } from '/@/hooks/web/useMessage'; |
14 | 14 | import { SingleToHex } from '/@/views/device/list/cpns/tabs/ObjectModelCommandDeliveryModal/config'; |
15 | 15 | import { genModbusCommand } from '/@/api/task'; |
16 | + import PasswordModal from '../component/PasswordModal.vue'; | |
17 | + import { useModal } from '/@/components/Modal'; | |
16 | 18 | |
17 | 19 | const props = defineProps<{ |
18 | 20 | config: ComponentPropsConfigType<typeof option>; |
... | ... | @@ -46,9 +48,18 @@ |
46 | 48 | textColor: persetTextColor, |
47 | 49 | valueSize: persetValueSize, |
48 | 50 | fontSize: persetFontSize, |
51 | + password: persetPassword, | |
49 | 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 | 63 | return { |
53 | 64 | attribute: attributeRename || attributeName || attribute, |
54 | 65 | controlBarColor: controlBarColor ?? persetControlBarColor, |
... | ... | @@ -63,6 +74,7 @@ |
63 | 74 | textColor: textColor || persetTextColor, |
64 | 75 | valueSize: valueSize || persetValueSize || 20, |
65 | 76 | fontSize: fontSize || persetFontSize || 14, |
77 | + password: password || persetPassword, | |
66 | 78 | }; |
67 | 79 | }); |
68 | 80 | |
... | ... | @@ -82,6 +94,7 @@ |
82 | 94 | const handleAfterChange = async () => { |
83 | 95 | unref(sliderEl)?.blur(); |
84 | 96 | if (unref(sliderValue) == unref(afterValue)) return; |
97 | + if (unref(getDesign).password) return; | |
85 | 98 | sliderValue.value = afterValue.value; //这一步是因为当我们是点击不是拖动时候,会让值更新不了,所以需要赋值一次 |
86 | 99 | }; |
87 | 100 | |
... | ... | @@ -169,6 +182,33 @@ |
169 | 182 | }; |
170 | 183 | |
171 | 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 | 212 | if (unref(oldSliderValue) !== unref(sliderValue)) { |
173 | 213 | const { codeType, customCommand } = unref(getDesign) || {}; |
174 | 214 | const { transportType } = customCommand || {}; |
... | ... | @@ -199,6 +239,7 @@ |
199 | 239 | |
200 | 240 | useDataFetch(props, updateFn); |
201 | 241 | const { getScale, getRatio } = useComponentScale(props); |
242 | + const [registerModal, { openModal }] = useModal(); | |
202 | 243 | </script> |
203 | 244 | |
204 | 245 | <template> |
... | ... | @@ -244,6 +285,7 @@ |
244 | 285 | </div> |
245 | 286 | </Spin> |
246 | 287 | </main> |
288 | + <PasswordModal @register="registerModal" @success="handleSendCommand" /> | |
247 | 289 | </main> |
248 | 290 | </template> |
249 | 291 | <style lang="less" scoped> | ... | ... |
... | ... | @@ -15,6 +15,7 @@ export const option: PublicPresetOptions = { |
15 | 15 | [ComponentConfigFieldEnum.ICON_COLOR]: '#377DFF', |
16 | 16 | [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, |
17 | 17 | [ComponentConfigFieldEnum.FONT_SIZE]: 14, |
18 | + [ComponentConfigFieldEnum.PASS_WORD]: '', | |
18 | 19 | }; |
19 | 20 | |
20 | 21 | export default class Config extends PublicConfigClass implements CreateComponentType { | ... | ... |
... | ... | @@ -38,6 +38,12 @@ |
38 | 38 | component: 'Checkbox', |
39 | 39 | defaultValue: option.showDeviceName, |
40 | 40 | }, |
41 | + { | |
42 | + field: ComponentConfigFieldEnum.PASS_WORD, | |
43 | + label: '操作密码', | |
44 | + component: 'InputPassword', | |
45 | + defaultValue: '', | |
46 | + }, | |
41 | 47 | ], |
42 | 48 | showActionButtonGroup: false, |
43 | 49 | labelWidth: 120, | ... | ... |
... | ... | @@ -14,6 +14,8 @@ |
14 | 14 | import { useReceiveValue } from '../../../hook/useReceiveValue'; |
15 | 15 | import { DataSource } from '/@/views/visual/palette/types'; |
16 | 16 | import { getSendValues, CommandTypeEnumLIst } from '../config'; |
17 | + import { useModal } from '/@/components/Modal'; | |
18 | + import PasswordModal from '../component/PasswordModal.vue'; | |
17 | 19 | |
18 | 20 | const props = defineProps<{ |
19 | 21 | config: ComponentPropsConfigType<typeof option>; |
... | ... | @@ -53,10 +55,12 @@ |
53 | 55 | icon: persetIcon, |
54 | 56 | iconColor: persetIconColor, |
55 | 57 | fontSize: persetFontSize, |
58 | + password: persetPassword, | |
56 | 59 | } = persetOption || {}; |
57 | 60 | return { |
58 | 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 | 64 | const { |
61 | 65 | attribute, |
62 | 66 | attributeRename, |
... | ... | @@ -86,13 +90,19 @@ |
86 | 90 | deviceCode, |
87 | 91 | customCommand, |
88 | 92 | fontSize: fontSize || persetFontSize || 14, |
93 | + password: password || persetPassword, | |
89 | 94 | }; |
90 | 95 | }), |
91 | 96 | }; |
92 | 97 | }); |
93 | 98 | |
94 | 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 | 106 | const { heightPx, itemHeightRatio, itemWidthRatio, mode, widthPx, dataSource } = |
97 | 107 | props.config.option; |
98 | 108 | const data = { |
... | ... | @@ -120,6 +130,25 @@ |
120 | 130 | }) |
121 | 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 | 153 | const updateFn: MultipleDataFetchUpdateFn = async (message, deviceId, attribute) => { |
125 | 154 | forEachGroupMessage(message, deviceId, attribute, (attribute, value) => { |
... | ... | @@ -133,6 +162,7 @@ |
133 | 162 | |
134 | 163 | useMultipleDataFetch(props, updateFn); |
135 | 164 | const { getRatio } = useComponentScale(props); |
165 | + const [registerModal, { openModal }] = useModal(); | |
136 | 166 | </script> |
137 | 167 | |
138 | 168 | <template> |
... | ... | @@ -166,9 +196,10 @@ |
166 | 196 | <Switch |
167 | 197 | v-model:checked="item.checked" |
168 | 198 | :loading="loading" |
169 | - @change="handleChange(index, item.checked)" | |
199 | + @change="handleChange(index, item.checked, item)" | |
170 | 200 | :style="{ transform: `scale(${getRatio || 1})` }" |
171 | 201 | /> |
172 | 202 | </div> |
203 | + <PasswordModal @register="registerModal" @success="handleSendCommand" /> | |
173 | 204 | </main> |
174 | 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 | 15 | import { CommandTypeEnum } from '/@/views/rule/linkedge/config/config.data'; |
16 | 16 | import { DataActionModeEnum } from '/@/enums/toolEnum'; |
17 | 17 | import { TaskTypeEnum } from '/@/views/task/center/config'; |
18 | +import { createPickerSearch } from '/@/utils/pickerSearch'; | |
18 | 19 | |
19 | 20 | useComponentRegister('OrgTreeSelect', OrgTreeSelect); |
20 | 21 | |
... | ... | @@ -247,6 +248,7 @@ export const commonDataSourceSchemas = (): FormSchema[] => { |
247 | 248 | }, |
248 | 249 | placeholder: '请选择设备', |
249 | 250 | getPopupContainer: () => document.body, |
251 | + ...createPickerSearch(), | |
250 | 252 | }; |
251 | 253 | }, |
252 | 254 | }, |
... | ... | @@ -387,6 +389,7 @@ export const commonDataSourceSchemas = (): FormSchema[] => { |
387 | 389 | [DataSourceField.EXTENSION_DESC]: value ? JSON.stringify(option.extensionDesc) : '', |
388 | 390 | }); |
389 | 391 | }, |
392 | + ...createPickerSearch(), | |
390 | 393 | }; |
391 | 394 | }, |
392 | 395 | }, | ... | ... |