Commit 416f565c23311ac6284d359be5e41a8a02fe2b14
Merge branch 'main_dev' of http://git.yunteng.com/yunteng/thingskit-front into f…
…eat/device-new-protocol
Showing
27 changed files
with
322 additions
and
28 deletions
| @@ -187,6 +187,7 @@ export interface AlarmLogItem { | @@ -187,6 +187,7 @@ export interface AlarmLogItem { | ||
| 187 | originatorType: number; | 187 | originatorType: number; |
| 188 | deviceId: string; | 188 | deviceId: string; |
| 189 | deviceName: string; | 189 | deviceName: string; |
| 190 | + deviceAlias: string; | ||
| 190 | type: string; | 191 | type: string; |
| 191 | severity: string; | 192 | severity: string; |
| 192 | status: string; | 193 | status: string; |
| @@ -67,7 +67,7 @@ export function useAlarmNotify(params: UseAlarmNotifyParams = {}) { | @@ -67,7 +67,7 @@ export function useAlarmNotify(params: UseAlarmNotifyParams = {}) { | ||
| 67 | 67 | ||
| 68 | if (items.length) { | 68 | if (items.length) { |
| 69 | const first = items.at(0)!; | 69 | const first = items.at(0)!; |
| 70 | - const { deviceName, id, severity, type } = first; | 70 | + const { deviceAlias, deviceName, id, severity, type } = first; |
| 71 | 71 | ||
| 72 | let key: Nullable<string> = `open-notify-${id}`; | 72 | let key: Nullable<string> = `open-notify-${id}`; |
| 73 | 73 | ||
| @@ -80,7 +80,7 @@ export function useAlarmNotify(params: UseAlarmNotifyParams = {}) { | @@ -80,7 +80,7 @@ export function useAlarmNotify(params: UseAlarmNotifyParams = {}) { | ||
| 80 | description: h('div', {}, [ | 80 | description: h('div', {}, [ |
| 81 | h('div', { style: { marginRight: '5px' } }, [ | 81 | h('div', { style: { marginRight: '5px' } }, [ |
| 82 | h('span', { style: { marginRight: '5px' } }, '设备:'), | 82 | h('span', { style: { marginRight: '5px' } }, '设备:'), |
| 83 | - h('span', {}, `[${deviceName}]`), | 83 | + h('span', {}, `[${deviceAlias ?? deviceName}]`), |
| 84 | ]), | 84 | ]), |
| 85 | h('div', { style: { marginRight: '5px' } }, [ | 85 | h('div', { style: { marginRight: '5px' } }, [ |
| 86 | h('span', { style: { marginRight: '5px' } }, '告警场景:'), | 86 | h('span', { style: { marginRight: '5px' } }, '告警场景:'), |
| @@ -41,6 +41,7 @@ | @@ -41,6 +41,7 @@ | ||
| 41 | " | 41 | " |
| 42 | v-else-if="item.key === TableDefaultTypeEnum.ENTITYID" | 42 | v-else-if="item.key === TableDefaultTypeEnum.ENTITYID" |
| 43 | v-model:value="item.value" | 43 | v-model:value="item.value" |
| 44 | + v-bind="createPickerSearch()" | ||
| 44 | placeholder="请选择" | 45 | placeholder="请选择" |
| 45 | :options="entityOptions" | 46 | :options="entityOptions" |
| 46 | allowClear | 47 | allowClear |
| @@ -53,6 +54,7 @@ | @@ -53,6 +54,7 @@ | ||
| 53 | " | 54 | " |
| 54 | v-else-if="item.key === TableDefaultTypeEnum.KEYS" | 55 | v-else-if="item.key === TableDefaultTypeEnum.KEYS" |
| 55 | v-model:value="item.value" | 56 | v-model:value="item.value" |
| 57 | + v-bind="createPickerSearch()" | ||
| 56 | placeholder="请选择" | 58 | placeholder="请选择" |
| 57 | :options="attributeOptions" | 59 | :options="attributeOptions" |
| 58 | mode="multiple" | 60 | mode="multiple" |
| @@ -102,6 +104,7 @@ | @@ -102,6 +104,7 @@ | ||
| 102 | " | 104 | " |
| 103 | v-else | 105 | v-else |
| 104 | v-model:value="item.value" | 106 | v-model:value="item.value" |
| 107 | + v-bind="createPickerSearch()" | ||
| 105 | placeholder="请选择" | 108 | placeholder="请选择" |
| 106 | :options="valueOptions" | 109 | :options="valueOptions" |
| 107 | allowClear | 110 | allowClear |
| @@ -157,6 +160,7 @@ | @@ -157,6 +160,7 @@ | ||
| 157 | import { getPacketIntervalByRange } from '/@/views/device/localtion/cpns/TimePeriodForm/helper'; | 160 | import { getPacketIntervalByRange } from '/@/views/device/localtion/cpns/TimePeriodForm/helper'; |
| 158 | import { uniqBy } from 'lodash'; | 161 | import { uniqBy } from 'lodash'; |
| 159 | import { TableDefaultTypeEnum } from '../../../config/enum'; | 162 | import { TableDefaultTypeEnum } from '../../../config/enum'; |
| 163 | + import { createPickerSearch } from '/@/utils/pickerSearch'; | ||
| 160 | 164 | ||
| 161 | const props = defineProps({ | 165 | const props = defineProps({ |
| 162 | method: { | 166 | method: { |
| @@ -212,6 +212,10 @@ export const basicInfoForm: FormSchema[] = [ | @@ -212,6 +212,10 @@ export const basicInfoForm: FormSchema[] = [ | ||
| 212 | labelField: 'name', | 212 | labelField: 'name', |
| 213 | valueField: 'tbDeviceId', | 213 | valueField: 'tbDeviceId', |
| 214 | getPopupContainer: () => document.body, | 214 | getPopupContainer: () => document.body, |
| 215 | + showSearch: true, | ||
| 216 | + filterOption: (inputValue: string, options: Record<'label', string>) => { | ||
| 217 | + return options.label.includes(inputValue); | ||
| 218 | + }, | ||
| 215 | }; | 219 | }; |
| 216 | }, | 220 | }, |
| 217 | }, | 221 | }, |
| @@ -2,7 +2,8 @@ import type { BasicColumn } from '/@/components/Table'; | @@ -2,7 +2,8 @@ import type { BasicColumn } from '/@/components/Table'; | ||
| 2 | import type { FormSchema } from '/@/components/Table'; | 2 | import type { FormSchema } from '/@/components/Table'; |
| 3 | import { getOrganizationList } from '/@/api/system/system'; | 3 | import { getOrganizationList } from '/@/api/system/system'; |
| 4 | import { copyTransFun } from '/@/utils/fnUtils'; | 4 | import { copyTransFun } from '/@/utils/fnUtils'; |
| 5 | -import { getDeviceDataKeys, getDeviceProfile } from '/@/api/alarm/position'; | 5 | +import { getDeviceDataKeys } from '/@/api/alarm/position'; |
| 6 | +import { deviceProfile } from '/@/api/device/deviceManager'; | ||
| 6 | import { EChartsOption } from 'echarts'; | 7 | import { EChartsOption } from 'echarts'; |
| 7 | 8 | ||
| 8 | export enum AggregateDataEnum { | 9 | export enum AggregateDataEnum { |
| @@ -31,11 +32,17 @@ export const formSchema: FormSchema[] = [ | @@ -31,11 +32,17 @@ export const formSchema: FormSchema[] = [ | ||
| 31 | field: 'deviceProfileId', | 32 | field: 'deviceProfileId', |
| 32 | label: '', | 33 | label: '', |
| 33 | component: 'ApiSelect', | 34 | component: 'ApiSelect', |
| 34 | - componentProps: { | ||
| 35 | - api: getDeviceProfile, | ||
| 36 | - placeholder: '请选择产品', | ||
| 37 | - labelField: 'name', | ||
| 38 | - valueField: 'tbProfileId', | 35 | + componentProps: () => { |
| 36 | + return { | ||
| 37 | + showSearch: true, | ||
| 38 | + labelField: 'name', | ||
| 39 | + valueField: 'tbProfileId', | ||
| 40 | + resultField: 'data', | ||
| 41 | + placeholder: '请选择产品', | ||
| 42 | + api: deviceProfile, | ||
| 43 | + filterOption: (inputValue: string, option: Record<'label' | 'value', string>) => | ||
| 44 | + option.label.includes(inputValue), | ||
| 45 | + }; | ||
| 39 | }, | 46 | }, |
| 40 | }, | 47 | }, |
| 41 | { | 48 | { |
| @@ -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 | } |