Commit 7061943df5fe149fd6861992dfcba950f936ff7b

Authored by xp.Huang
2 parents 34e5b4ef 0eddcf3d

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 }