Showing
10 changed files
with
225 additions
and
395 deletions
... | ... | @@ -15,6 +15,8 @@ enum DeviceManagerApi { |
15 | 15 | * 设备配置URL |
16 | 16 | */ |
17 | 17 | DEVICE_PROFILE_URL = '/deviceProfile', |
18 | + | |
19 | + DEVICE_PROFILE_URL_ME = '/deviceProfile/me', | |
18 | 20 | } |
19 | 21 | |
20 | 22 | export const devicePage = (params: DeviceQueryParam) => { |
... | ... | @@ -59,3 +61,20 @@ export const deleteDevice = (ids: string[]) => { |
59 | 61 | }, |
60 | 62 | }); |
61 | 63 | }; |
64 | + | |
65 | +/** | |
66 | + * 查询设备配置 | |
67 | + * @param params pageSize page name | |
68 | + */ | |
69 | +export const deviceProfile = () => { | |
70 | + return defHttp.get({ | |
71 | + url: DeviceManagerApi.DEVICE_PROFILE_URL_ME, | |
72 | + }); | |
73 | +}; | |
74 | + | |
75 | +export const createOrEditDevice = (data) => { | |
76 | + return defHttp.post({ | |
77 | + url: DeviceManagerApi.DEVICE_URL, | |
78 | + data, | |
79 | + }); | |
80 | +}; | ... | ... |
... | ... | @@ -6,6 +6,7 @@ |
6 | 6 | :title="getTitle" |
7 | 7 | @cancel="handleCancel" |
8 | 8 | @ok="handleOk" |
9 | + centered | |
9 | 10 | > |
10 | 11 | <div class="step-form-form"> |
11 | 12 | <a-steps :current="current"> |
... | ... | @@ -28,9 +29,11 @@ |
28 | 29 | <script lang="ts"> |
29 | 30 | import { defineComponent, ref, computed, unref, reactive, toRefs } from 'vue'; |
30 | 31 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
32 | + import { createOrEditDevice } from '/@/api/device/deviceManager'; | |
31 | 33 | import DeviceStep1 from '/@/views/device/step/DeviceStep1.vue'; |
32 | 34 | import DeviceStep2 from '/@/views/device/step/DeviceStep2.vue'; |
33 | 35 | import { Steps } from 'ant-design-vue'; |
36 | + import { useMessage } from '/@/hooks/web/useMessage'; | |
34 | 37 | export default defineComponent({ |
35 | 38 | name: 'DeviceModal', |
36 | 39 | components: { |
... | ... | @@ -43,31 +46,42 @@ |
43 | 46 | props: { |
44 | 47 | userData: { type: Object }, |
45 | 48 | }, |
46 | - setup(_) { | |
47 | - // const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); | |
49 | + setup(_, { emit }) { | |
48 | 50 | const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); |
49 | 51 | const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); |
52 | + const { createMessage } = useMessage(); | |
50 | 53 | const state = reactive({ |
51 | 54 | initStep2: false, |
52 | 55 | }); |
53 | 56 | const current = ref(0); |
54 | 57 | const isUpdate = ref(true); |
55 | - const modelRef = ref({}); | |
56 | 58 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备')); |
57 | 59 | // 所有参数 |
58 | - let stepState = reactive({}); | |
59 | - const [register] = useModalInner((data) => { | |
60 | + let stepState = ref(); | |
61 | + // 编辑回显 | |
62 | + const [register, { closeModal }] = useModalInner((data) => { | |
63 | + if (data.isUpdate) { | |
64 | + DeviceStep1Ref.value?.parentSetFieldsValue(data.record); | |
65 | + DeviceStep1Ref.value?.parentSetFieldsValue({ | |
66 | + profile: data.record.deviceProfile.name, | |
67 | + remark: data.record.deviceInfo.description, | |
68 | + profileId: data.record.profileId, | |
69 | + }); | |
70 | + } | |
60 | 71 | isUpdate.value = !!data?.isUpdate; |
61 | 72 | }); |
62 | 73 | |
74 | + // 上一步 | |
63 | 75 | function handleStepPrev() { |
64 | 76 | current.value--; |
65 | 77 | } |
78 | + // 下一步 | |
66 | 79 | function handleStep1Next(step1Values: any) { |
67 | 80 | current.value++; |
68 | 81 | state.initStep2 = true; |
69 | 82 | stepState = { ...step1Values }; |
70 | 83 | } |
84 | + // | |
71 | 85 | function handleStep2Next(step2Values: any) { |
72 | 86 | stepState = { ...stepState, ...step2Values }; |
73 | 87 | } |
... | ... | @@ -75,17 +89,34 @@ |
75 | 89 | current.value = 0; |
76 | 90 | DeviceStep1Ref?.value?.resetFields(); |
77 | 91 | DeviceStep2Ref?.value?.resetFields(); |
78 | - console.log('关闭弹框'); | |
79 | - stepState = {}; | |
80 | 92 | } |
81 | - function handleOk() { | |
82 | - // 所有参数 | |
83 | - console.log(stepState); | |
84 | - console.log('确定了'); | |
93 | + // 提交 | |
94 | + async function handleOk() { | |
95 | + if (current.value === 0) { | |
96 | + // 验证 | |
97 | + const valid = await DeviceStep1Ref.value?.parentValidate(); | |
98 | + if (!valid) return; | |
99 | + | |
100 | + stepState.value = DeviceStep1Ref?.value?.parentGetFieldsValue(); | |
101 | + handleCancel(); | |
102 | + closeModal(); | |
103 | + } else { | |
104 | + if (!DeviceStep2Ref?.value?.creaentialsPassword.isCreaentials) { | |
105 | + const valid = await DeviceStep2Ref?.value?.validate(); | |
106 | + if (!valid) return; | |
107 | + // 第二页验证通过情况 | |
108 | + handleCancel(); | |
109 | + closeModal(); | |
110 | + } | |
111 | + } | |
112 | + // 验证成功 --掉新增或者编辑接口 | |
113 | + const msg = computed(() => (stepState.value.id ? '更新设备成功' : '新增设备成功')); | |
114 | + await createOrEditDevice(stepState.value); | |
115 | + createMessage.success(msg.value); | |
116 | + emit('reload'); | |
85 | 117 | } |
86 | 118 | return { |
87 | 119 | register, |
88 | - model: modelRef, | |
89 | 120 | getTitle, |
90 | 121 | current, |
91 | 122 | DeviceStep1Ref, | ... | ... |
src/views/device/config.data.ts
deleted
100644 → 0
1 | -import { BasicColumn } from '/@/components/Table'; | |
2 | -import { FormSchema } from '/@/components/Table'; | |
3 | -import { findDictItemByCode } from '/@/api/system/dict'; | |
4 | -import { MessageEnum } from '/@/enums/messageEnum'; | |
5 | -import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel'; | |
6 | -// 表格列数据 | |
7 | -export const columns: BasicColumn[] = [ | |
8 | - { | |
9 | - title: '设备名称', | |
10 | - dataIndex: 'name', | |
11 | - width: 200, | |
12 | - }, | |
13 | - { | |
14 | - title: '设备类型', | |
15 | - dataIndex: 'deviceType', | |
16 | - width: 200, | |
17 | - slots: { customRender: 'deviceType' }, | |
18 | - }, | |
19 | - { | |
20 | - title: '设备配置', | |
21 | - dataIndex: 'deviceProfile.name', | |
22 | - width: 180, | |
23 | - slots: { customRender: 'deviceProfile' }, | |
24 | - }, | |
25 | - { | |
26 | - title: '标签', | |
27 | - dataIndex: 'label', | |
28 | - width: 180, | |
29 | - }, | |
30 | - { | |
31 | - title: '配置信息', | |
32 | - dataIndex: 'deviceInfo', | |
33 | - width: 180, | |
34 | - slots: { customRender: 'config' }, | |
35 | - }, | |
36 | - { | |
37 | - title: '状态', | |
38 | - dataIndex: 'deviceState', | |
39 | - width: 120, | |
40 | - slots: { customRender: 'deviceState' }, | |
41 | - }, | |
42 | - { | |
43 | - title: '最后连接时间', | |
44 | - dataIndex: 'lastConnectTime', | |
45 | - width: 180, | |
46 | - }, | |
47 | - { | |
48 | - title: '创建时间', | |
49 | - dataIndex: 'createTime', | |
50 | - width: 180, | |
51 | - }, | |
52 | -]; | |
53 | - | |
54 | -// 查询字段 | |
55 | -export const searchFormSchema: FormSchema[] = [ | |
56 | - { | |
57 | - field: 'deviceType', | |
58 | - label: '设备类型', | |
59 | - component: 'Select', | |
60 | - componentProps: { | |
61 | - options: [ | |
62 | - { label: '网关设备', value: DeviceTypeEnum.GATEWAY }, | |
63 | - { label: '直连设备', value: DeviceTypeEnum.DIRECT_CONNECTION }, | |
64 | - { label: '网关子设备', value: DeviceTypeEnum.SENSOR }, | |
65 | - ], | |
66 | - }, | |
67 | - colProps: { span: 4 }, | |
68 | - }, | |
69 | - { | |
70 | - field: 'deviceState', | |
71 | - label: '设备状态', | |
72 | - component: 'Select', | |
73 | - componentProps: { | |
74 | - options: [ | |
75 | - { label: '待激活', value: DeviceState.INACTIVE }, | |
76 | - { label: '在线', value: DeviceState.ONLINE }, | |
77 | - { label: '离线', value: DeviceState.OFFLINE }, | |
78 | - ], | |
79 | - }, | |
80 | - colProps: { span: 4 }, | |
81 | - }, | |
82 | - { | |
83 | - field: 'name', | |
84 | - label: '设备名称', | |
85 | - component: 'Input', | |
86 | - colProps: { span: 8 }, | |
87 | - }, | |
88 | -]; | |
89 | - | |
90 | -// 弹框配置项 | |
91 | -export const formSchema: FormSchema[] = [ | |
92 | - { | |
93 | - field: 'configName', | |
94 | - label: '配置名称', | |
95 | - required: true, | |
96 | - component: 'Input', | |
97 | - }, | |
98 | - { | |
99 | - field: 'messageType', | |
100 | - label: '消息类型', | |
101 | - required: true, | |
102 | - component: 'ApiSelect', | |
103 | - componentProps: { | |
104 | - api: findDictItemByCode, | |
105 | - params: { | |
106 | - dictCode: 'message_type', | |
107 | - }, | |
108 | - labelField: 'itemText', | |
109 | - valueField: 'itemValue', | |
110 | - }, | |
111 | - }, | |
112 | - { | |
113 | - field: 'platformType', | |
114 | - label: '平台类型', | |
115 | - required: true, | |
116 | - component: 'ApiSelect', | |
117 | - componentProps: { | |
118 | - api: findDictItemByCode, | |
119 | - params: { | |
120 | - dictCode: 'platform_type', | |
121 | - }, | |
122 | - labelField: 'itemText', | |
123 | - valueField: 'itemValue', | |
124 | - }, | |
125 | - ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')), | |
126 | - }, | |
127 | - { | |
128 | - field: 'accessKeyId', | |
129 | - label: 'accessKeyId', | |
130 | - required: true, | |
131 | - component: 'Input', | |
132 | - ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')), | |
133 | - }, | |
134 | - { | |
135 | - field: 'accessKeySecret', | |
136 | - label: 'accessKeySecret', | |
137 | - required: true, | |
138 | - component: 'Input', | |
139 | - ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')), | |
140 | - }, | |
141 | - { | |
142 | - field: 'host', | |
143 | - label: '服务器地址', | |
144 | - defaultValue: 'smtp.163.com', | |
145 | - required: true, | |
146 | - component: 'Input', | |
147 | - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), | |
148 | - }, | |
149 | - { | |
150 | - field: 'port', | |
151 | - label: '端口', | |
152 | - defaultValue: 25, | |
153 | - required: true, | |
154 | - component: 'InputNumber', | |
155 | - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), | |
156 | - }, | |
157 | - { | |
158 | - field: 'username', | |
159 | - label: '用户名', | |
160 | - required: true, | |
161 | - component: 'Input', | |
162 | - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), | |
163 | - }, | |
164 | - { | |
165 | - field: 'password', | |
166 | - label: '密码', | |
167 | - required: true, | |
168 | - component: 'InputPassword', | |
169 | - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), | |
170 | - }, | |
171 | - { | |
172 | - field: 'config', | |
173 | - label: '消息配置', | |
174 | - component: 'Input', | |
175 | - show: false, | |
176 | - }, | |
177 | - { | |
178 | - field: 'id', | |
179 | - label: '主键', | |
180 | - component: 'Input', | |
181 | - show: false, | |
182 | - }, | |
183 | - { | |
184 | - field: 'status', | |
185 | - label: '状态', | |
186 | - component: 'RadioButtonGroup', | |
187 | - defaultValue: 0, | |
188 | - componentProps: { | |
189 | - options: [ | |
190 | - { label: '启用', value: 1 }, | |
191 | - { label: '停用', value: 0 }, | |
192 | - ], | |
193 | - }, | |
194 | - }, | |
195 | - { | |
196 | - label: '备注', | |
197 | - field: 'remark', | |
198 | - component: 'InputTextArea', | |
199 | - }, | |
200 | -]; | |
201 | - | |
202 | -export const isMessage = (type: string) => { | |
203 | - return type === MessageEnum.IS_SMS; | |
204 | -}; | |
205 | -export const isEmail = (type: string) => { | |
206 | - return type === MessageEnum.IS_EMAIL; | |
207 | -}; |
1 | 1 | import { BasicColumn } from '/@/components/Table'; |
2 | 2 | import { FormSchema } from '/@/components/Table'; |
3 | -import { findDictItemByCode } from '/@/api/system/dict'; | |
4 | 3 | import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel'; |
4 | +// 表格列数据 | |
5 | 5 | export const columns: BasicColumn[] = [ |
6 | 6 | { |
7 | 7 | title: '设备名称', |
... | ... | @@ -45,6 +45,7 @@ export const columns: BasicColumn[] = [ |
45 | 45 | }, |
46 | 46 | ]; |
47 | 47 | |
48 | +// 查询字段 | |
48 | 49 | export const searchFormSchema: FormSchema[] = [ |
49 | 50 | { |
50 | 51 | field: 'deviceType', |
... | ... | @@ -79,48 +80,3 @@ export const searchFormSchema: FormSchema[] = [ |
79 | 80 | colProps: { span: 8 }, |
80 | 81 | }, |
81 | 82 | ]; |
82 | - | |
83 | -export const formSchema: FormSchema[] = [ | |
84 | - { | |
85 | - field: 'icon', | |
86 | - label: '设备图片: ', | |
87 | - slot: 'iconSelect', | |
88 | - component: 'Input', | |
89 | - }, | |
90 | - { | |
91 | - field: 'name', | |
92 | - label: '设备名称', | |
93 | - required: true, | |
94 | - component: 'Input', | |
95 | - componentProps: { | |
96 | - maxLength: 30, | |
97 | - }, | |
98 | - }, | |
99 | - { | |
100 | - field: 'deviceType', | |
101 | - label: '设备类型', | |
102 | - required: true, | |
103 | - component: 'ApiSelect', | |
104 | - componentProps: { | |
105 | - api: findDictItemByCode, | |
106 | - params: { | |
107 | - dictCode: 'device_type', | |
108 | - }, | |
109 | - labelField: 'itemText', | |
110 | - valueField: 'itemValue', | |
111 | - }, | |
112 | - }, | |
113 | - { | |
114 | - field: 'label', | |
115 | - label: '设备标签', | |
116 | - component: 'Input', | |
117 | - componentProps: { | |
118 | - maxLength: 255, | |
119 | - }, | |
120 | - }, | |
121 | - { | |
122 | - label: '备注', | |
123 | - field: 'remark', | |
124 | - component: 'InputTextArea', | |
125 | - }, | |
126 | -]; | ... | ... |
... | ... | @@ -65,16 +65,13 @@ |
65 | 65 | /> |
66 | 66 | </template> |
67 | 67 | </BasicTable> |
68 | - <!-- <ConfigDrawer @register="registerDrawer" @success="handleSuccess" /> --> | |
69 | - <DeviceModal @register="registerModal" @success="handleSuccess" /> | |
68 | + <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleReload" /> | |
70 | 69 | </PageWrapper> |
71 | 70 | </template> |
72 | 71 | <script lang="ts"> |
73 | 72 | import { defineComponent, reactive } from 'vue'; |
74 | 73 | import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
75 | 74 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
76 | - // import { useDrawer } from '/@/components/Drawer'; | |
77 | - // import ConfigDrawer from './DeviceDrawer.vue'; | |
78 | 75 | import { columns, searchFormSchema } from './device.data'; |
79 | 76 | import { Tag } from 'ant-design-vue'; |
80 | 77 | import { useMessage } from '/@/hooks/web/useMessage'; |
... | ... | @@ -90,17 +87,16 @@ |
90 | 87 | name: 'DeviceManagement', |
91 | 88 | components: { |
92 | 89 | BasicTable, |
93 | - // ConfigDrawer, | |
94 | 90 | PageWrapper, |
95 | 91 | TableAction, |
96 | 92 | OrganizationIdTree, |
97 | 93 | Tag, |
98 | 94 | DeviceModal, |
99 | 95 | }, |
100 | - setup() { | |
101 | - // const [registerDrawer, { openDrawer }] = useDrawer(); | |
96 | + setup(_) { | |
102 | 97 | const { createMessage } = useMessage(); |
103 | 98 | const go = useGo(); |
99 | + | |
104 | 100 | const searchInfo = reactive<Recordable>({}); |
105 | 101 | const [registerModal, { openModal }] = useModal(); |
106 | 102 | const [registerTable, { reload }] = useTable({ |
... | ... | @@ -124,6 +120,9 @@ |
124 | 120 | fixed: undefined, |
125 | 121 | }, |
126 | 122 | }); |
123 | + const handleReload = () => { | |
124 | + handleSuccess(); | |
125 | + }; | |
127 | 126 | |
128 | 127 | function handleCreate() { |
129 | 128 | openModal(true, { |
... | ... | @@ -158,7 +157,6 @@ |
158 | 157 | } |
159 | 158 | return { |
160 | 159 | registerTable, |
161 | - // registerDrawer, | |
162 | 160 | handleCreate, |
163 | 161 | handleEdit, |
164 | 162 | handleDelete, |
... | ... | @@ -169,6 +167,7 @@ |
169 | 167 | handleSelect, |
170 | 168 | searchInfo, |
171 | 169 | registerModal, |
170 | + handleReload, | |
172 | 171 | }; |
173 | 172 | }, |
174 | 173 | }); | ... | ... |
... | ... | @@ -19,7 +19,7 @@ |
19 | 19 | </div> |
20 | 20 | </Upload> |
21 | 21 | </template> |
22 | - <template #devicePosition> | |
22 | + <template #deviceAddress> | |
23 | 23 | <Input disabled v-model:value="positionState.address"> |
24 | 24 | <template #addonAfter> |
25 | 25 | <EnvironmentTwoTone @click="selectPosition" /> |
... | ... | @@ -28,10 +28,17 @@ |
28 | 28 | </template> |
29 | 29 | </BasicForm> |
30 | 30 | </div> |
31 | - <Modal v-model:visible="visible" title="设备位置" @ok="handleOk" width="800px"> | |
31 | + <Modal | |
32 | + v-model:visible="visible" | |
33 | + title="设备位置" | |
34 | + @ok="handleOk" | |
35 | + width="800px" | |
36 | + @cancel="handleCancel" | |
37 | + centered | |
38 | + > | |
32 | 39 | <div> |
33 | 40 | <a-form :label-col="labelCol"> |
34 | - <a-row :gutter="20"> | |
41 | + <a-row :gutter="20" class="pt-4 pl-6"> | |
35 | 42 | <a-col :span="8"> |
36 | 43 | <a-form-item label="经度"> |
37 | 44 | <Input type="input" v-model:value="positionState.lng" disabled /> |
... | ... | @@ -59,7 +66,6 @@ |
59 | 66 | import { EnvironmentTwoTone, PlusOutlined } from '@ant-design/icons-vue'; |
60 | 67 | import { upload } from '/@/api/oss/ossFileUploader'; |
61 | 68 | import { FileItem } from '/@/components/Upload/src/typing'; |
62 | - | |
63 | 69 | export default defineComponent({ |
64 | 70 | components: { |
65 | 71 | BasicForm, |
... | ... | @@ -79,34 +85,35 @@ |
79 | 85 | emits: ['next'], |
80 | 86 | setup(_, { emit }) { |
81 | 87 | const devicePic = ref(''); |
82 | - const positionState = reactive({ | |
88 | + let positionState = reactive({ | |
83 | 89 | lng: '', |
84 | 90 | lat: '', |
85 | 91 | address: '', |
86 | 92 | }); |
87 | - const [register, { validate, resetFields }] = useForm({ | |
93 | + const [register, { validate, resetFields, setFieldsValue, getFieldsValue }] = useForm({ | |
88 | 94 | labelWidth: 100, |
89 | 95 | schemas: step1Schemas, |
90 | 96 | actionColOptions: { |
91 | 97 | span: 14, |
92 | 98 | }, |
99 | + labelAlign: 'left', | |
93 | 100 | showResetButton: false, |
94 | 101 | submitButtonOptions: { |
95 | 102 | text: '下一步', |
96 | 103 | }, |
97 | 104 | submitFunc: customSubmitFunc, |
98 | 105 | }); |
99 | - | |
100 | 106 | async function customSubmitFunc() { |
101 | 107 | try { |
102 | 108 | let values = await validate(); |
103 | 109 | values = { devicePic: devicePic.value, ...positionState, ...values }; |
104 | 110 | delete values.icon; |
105 | - delete values.devicePosition; | |
111 | + delete values.deviceAddress; | |
106 | 112 | emit('next', values); |
107 | 113 | // 获取输入的数据 |
108 | - } catch (error) {} | |
114 | + } catch (e) {} | |
109 | 115 | } |
116 | + | |
110 | 117 | // 图片上传 |
111 | 118 | async function customUpload({ file }) { |
112 | 119 | if (beforeUpload(file)) { |
... | ... | @@ -150,12 +157,30 @@ |
150 | 157 | const BMap = (window as any).BMap; |
151 | 158 | if (!wrapEl) return; |
152 | 159 | const map = new BMap.Map(wrapEl); |
153 | - map.addEventListener('click', () => { | |
160 | + const point = new BMap.Point(104.04813399999999, 30.54348986021446); | |
161 | + map.centerAndZoom(point, 15); | |
162 | + map.enableScrollWheelZoom(true); | |
163 | + let preMarker = null; | |
164 | + map.addEventListener('click', (e) => { | |
154 | 165 | const { lat, lng } = map.he; |
155 | 166 | positionState.lat = lat + ''; |
156 | 167 | positionState.lng = lng + ''; |
157 | 168 | let gc = new BMap.Geocoder(); |
158 | 169 | let newPoint = new BMap.Point(lng, lat); |
170 | + if (!e.overlay) { | |
171 | + let myIcon = new BMap.Icon( | |
172 | + 'http://api.map.baidu.com/img/markers.png', | |
173 | + new BMap.Size(40, 25), | |
174 | + { | |
175 | + offset: new BMap.Size(0, 0), // 指定定位位置 | |
176 | + imageOffset: new BMap.Size(20, -260), // 设置图片偏移 | |
177 | + } | |
178 | + ); | |
179 | + let marker = new BMap.Marker(e.point, { icon: myIcon }); | |
180 | + map.removeOverlay(preMarker); | |
181 | + map.addOverlay(marker); | |
182 | + preMarker = marker; | |
183 | + } | |
159 | 184 | gc.getLocation(newPoint, (rs) => { |
160 | 185 | let addComp = rs.addressComponents; |
161 | 186 | //获取详细的地址,精确到街道的名称 |
... | ... | @@ -163,14 +188,31 @@ |
163 | 188 | positionState.address = addrname; |
164 | 189 | }); |
165 | 190 | }); |
166 | - const point = new BMap.Point(104.04813399999999, 30.54348986021446); | |
167 | - map.centerAndZoom(point, 15); | |
168 | - map.enableScrollWheelZoom(true); | |
169 | 191 | } |
170 | 192 | // 确定选择的位置 |
171 | 193 | const handleOk = () => { |
172 | 194 | visible.value = false; |
173 | 195 | }; |
196 | + // 取消选择位置 | |
197 | + const handleCancel = () => { | |
198 | + for (let key in positionState) { | |
199 | + positionState[key] = ''; | |
200 | + } | |
201 | + }; | |
202 | + // 父组件调用更新字段值的方法 | |
203 | + function parentSetFieldsValue(data) { | |
204 | + setFieldsValue(data); | |
205 | + } | |
206 | + | |
207 | + function parentGetFieldsValue() { | |
208 | + return getFieldsValue(); | |
209 | + } | |
210 | + | |
211 | + async function parentValidate() { | |
212 | + const valid = await validate(); | |
213 | + return valid; | |
214 | + } | |
215 | + | |
174 | 216 | return { |
175 | 217 | resetFields, |
176 | 218 | positionState, |
... | ... | @@ -182,8 +224,12 @@ |
182 | 224 | visible, |
183 | 225 | scrollRef, |
184 | 226 | handleOk, |
227 | + handleCancel, | |
185 | 228 | wrapRef, |
186 | 229 | labelCol: { style: { width: '40px' } }, |
230 | + parentSetFieldsValue, | |
231 | + parentGetFieldsValue, | |
232 | + parentValidate, | |
187 | 233 | }; |
188 | 234 | }, |
189 | 235 | }); | ... | ... |
... | ... | @@ -4,15 +4,16 @@ |
4 | 4 | ><input type="checkbox" v-model="creaentialsPassword.isCreaentials" @click="checked" /> |
5 | 5 | 添加凭证 |
6 | 6 | </div> |
7 | - | |
8 | 7 | <a-form |
9 | 8 | ref="formRef" |
9 | + :rules="rules" | |
10 | 10 | :label-col="labelCol" |
11 | 11 | :wrapper-col="wrapperCol" |
12 | - v-if="creaentialsPassword.isCreaentials" | |
12 | + v-show="creaentialsPassword.isCreaentials" | |
13 | 13 | :model="creaentialsPassword" |
14 | + labelAlign="left" | |
14 | 15 | > |
15 | - <a-form-item label="凭据类型" name="creantialsType"> | |
16 | + <a-form-item label="凭据类型" name="creaentialsType"> | |
16 | 17 | <a-select |
17 | 18 | v-model:value="creaentialsPassword.creaentialsType" |
18 | 19 | style="width: 200px" |
... | ... | @@ -23,13 +24,13 @@ |
23 | 24 | </a-form-item> |
24 | 25 | <div v-if="creaentialsPassword.creaentialsType === 'Access token'"> |
25 | 26 | <a-form-item label="访问令牌" name="token"> |
26 | - <a-input type="input" style="width: 200px" v-model:value="creaentialsPassword.token" /> | |
27 | + <a-input type="password" style="width: 200px" v-model:value="creaentialsPassword.token" /> | |
27 | 28 | </a-form-item> |
28 | 29 | </div> |
29 | 30 | <div v-else-if="creaentialsPassword.creaentialsType === 'X.509'"> |
30 | 31 | <a-form-item label="RSA公钥" name="publicKey"> |
31 | 32 | <a-input |
32 | - type="input" | |
33 | + type="password" | |
33 | 34 | style="width: 200px" |
34 | 35 | v-model:value="creaentialsPassword.publicKey" |
35 | 36 | /> |
... | ... | @@ -51,7 +52,6 @@ |
51 | 52 | </a-form-item> |
52 | 53 | </div> |
53 | 54 | </a-form> |
54 | - | |
55 | 55 | <div class="flex justify-start"> |
56 | 56 | <a-button class="mr-5" @click="prevStep">上一步</a-button> |
57 | 57 | </div> |
... | ... | @@ -69,6 +69,7 @@ |
69 | 69 | [Select.name]: Select, |
70 | 70 | [Button.name]: Button, |
71 | 71 | }, |
72 | + | |
72 | 73 | emits: ['prev', 'next'], |
73 | 74 | setup(_, { emit }) { |
74 | 75 | const formRef = ref(); |
... | ... | @@ -81,6 +82,12 @@ |
81 | 82 | username: '', |
82 | 83 | password: '', |
83 | 84 | }); |
85 | + const rules = { | |
86 | + token: [{ required: true, message: '请输入访问令牌', trigger: 'blur' }], | |
87 | + publicKey: [{ required: true, message: '请输入RSA公钥', trigger: 'blur' }], | |
88 | + clientId: [{ required: true, message: '请输入客户端ID', trigger: 'blur' }], | |
89 | + username: [{ required: true, message: '请输入用户名', trigger: 'blur' }], | |
90 | + }; | |
84 | 91 | const options = ref([ |
85 | 92 | { |
86 | 93 | value: 'Access token', |
... | ... | @@ -96,8 +103,11 @@ |
96 | 103 | label: 'MQTT Basic', |
97 | 104 | }, |
98 | 105 | ]); |
106 | + // 切换是否添加凭证 | |
99 | 107 | const checked = () => { |
100 | 108 | creaentialsPassword.isCreaentials = !creaentialsPassword.isCreaentials; |
109 | + formRef.value.resetFields(); | |
110 | + creaentialsPassword.creaentialsType = 'Access token'; | |
101 | 111 | }; |
102 | 112 | const prevStep = () => { |
103 | 113 | emit('prev'); |
... | ... | @@ -109,21 +119,40 @@ |
109 | 119 | // 切换凭证类型时,重置字段 |
110 | 120 | const handleChange = (value) => { |
111 | 121 | if (value === 'Access token') { |
112 | - creaentialsPassword.token = ''; | |
122 | + resetCreantialsType(); | |
113 | 123 | } else if (value === 'X.509') { |
114 | - creaentialsPassword.publicKey = ''; | |
124 | + resetCreantialsType(); | |
115 | 125 | } else { |
116 | - creaentialsPassword.clientId = ''; | |
117 | - creaentialsPassword.username = ''; | |
118 | - creaentialsPassword.password = ''; | |
126 | + resetCreantialsType(); | |
119 | 127 | } |
120 | 128 | }; |
129 | + // 切换凭证类型时,重置字段 | |
130 | + function resetCreantialsType() { | |
131 | + creaentialsPassword.token = ''; | |
132 | + creaentialsPassword.publicKey = ''; | |
133 | + creaentialsPassword.clientId = ''; | |
134 | + creaentialsPassword.username = ''; | |
135 | + creaentialsPassword.password = ''; | |
136 | + } | |
121 | 137 | |
122 | 138 | // 重置所有字段 |
123 | 139 | function resetFields() { |
124 | - console.log(formRef); | |
140 | + creaentialsPassword.isCreaentials = false; | |
141 | + creaentialsPassword.creaentialsType = 'Access token'; | |
142 | + creaentialsPassword.token = ''; | |
143 | + creaentialsPassword.publicKey = ''; | |
144 | + creaentialsPassword.clientId = ''; | |
145 | + creaentialsPassword.username = ''; | |
146 | + creaentialsPassword.password = ''; | |
125 | 147 | formRef.value.resetFields(); |
126 | - console.log('----'); | |
148 | + } | |
149 | + | |
150 | + // 表单验证 | |
151 | + function validate() { | |
152 | + if (creaentialsPassword.isCreaentials) { | |
153 | + return formRef.value.validate(); | |
154 | + } | |
155 | + return true; | |
127 | 156 | } |
128 | 157 | return { |
129 | 158 | options, |
... | ... | @@ -135,13 +164,15 @@ |
135 | 164 | labelCol: { style: { width: '150px' } }, |
136 | 165 | wrapperCol: { span: 18 }, |
137 | 166 | resetFields, |
167 | + validate, | |
168 | + rules, | |
138 | 169 | }; |
139 | 170 | }, |
140 | 171 | }); |
141 | 172 | </script> |
142 | 173 | <style lang="less" scoped> |
143 | 174 | .step2 { |
144 | - width: 500px; | |
175 | + width: 700px; | |
145 | 176 | margin: 0 auto; |
146 | 177 | } |
147 | 178 | </style> | ... | ... |
src/views/device/step/StepIndexDemo.vue
deleted
100644 → 0
1 | -<template> | |
2 | - <PageWrapper | |
3 | - title="分步表单" | |
4 | - contentBackground | |
5 | - content=" 将一个冗长或用户不熟悉的表单任务分成多个步骤,指导用户完成。" | |
6 | - contentClass="p-4" | |
7 | - > | |
8 | - <div class="step-form-form"> | |
9 | - <a-steps :current="current"> | |
10 | - <a-step title="填写转账信息" /> | |
11 | - <a-step title="确认转账信息" /> | |
12 | - <a-step title="完成" /> | |
13 | - </a-steps> | |
14 | - </div> | |
15 | - <div class="mt-5"> | |
16 | - <Step1 @next="handleStep1Next" v-show="current === 0" /> | |
17 | - <Step2 | |
18 | - @prev="handleStepPrev" | |
19 | - @next="handleStep2Next" | |
20 | - v-show="current === 1" | |
21 | - v-if="initSetp2" | |
22 | - /> | |
23 | - </div> | |
24 | - </PageWrapper> | |
25 | -</template> | |
26 | -<script lang="ts"> | |
27 | - import { defineComponent, ref, reactive, toRefs } from 'vue'; | |
28 | - import Step1 from './DeviceStep1.vue'; | |
29 | - import Step2 from './DeviceStep2.vue'; | |
30 | - import { PageWrapper } from '/@/components/Page'; | |
31 | - import { Steps } from 'ant-design-vue'; | |
32 | - | |
33 | - export default defineComponent({ | |
34 | - name: 'FormStepPage', | |
35 | - components: { | |
36 | - Step1, | |
37 | - Step2, | |
38 | - | |
39 | - PageWrapper, | |
40 | - [Steps.name]: Steps, | |
41 | - [Steps.Step.name]: Steps.Step, | |
42 | - }, | |
43 | - setup() { | |
44 | - const current = ref(1); | |
45 | - | |
46 | - const state = reactive({ | |
47 | - initSetp2: false, | |
48 | - }); | |
49 | - | |
50 | - function handleStep1Next(step1Values: any) { | |
51 | - current.value++; | |
52 | - state.initSetp2 = true; | |
53 | - console.log(step1Values); | |
54 | - } | |
55 | - | |
56 | - function handleStepPrev() { | |
57 | - current.value--; | |
58 | - } | |
59 | - | |
60 | - function handleStep2Next(step2Values: any) { | |
61 | - current.value++; | |
62 | - console.log(step2Values); | |
63 | - } | |
64 | - | |
65 | - function handleRedo() { | |
66 | - current.value = 0; | |
67 | - state.initSetp2 = false; | |
68 | - } | |
69 | - | |
70 | - return { | |
71 | - current, | |
72 | - handleStep1Next, | |
73 | - handleStep2Next, | |
74 | - handleRedo, | |
75 | - handleStepPrev, | |
76 | - ...toRefs(state), | |
77 | - }; | |
78 | - }, | |
79 | - }); | |
80 | -</script> | |
81 | -<style lang="less" scoped> | |
82 | - .step-form-content { | |
83 | - padding: 24px; | |
84 | - background-color: @component-background; | |
85 | - } | |
86 | - | |
87 | - .step-form-form { | |
88 | - width: 750px; | |
89 | - margin: 0 auto; | |
90 | - } | |
91 | -</style> |
1 | 1 | import { FormSchema } from '/@/components/Form'; |
2 | 2 | import { findDictItemByCode } from '/@/api/system/dict'; |
3 | - | |
3 | +import { deviceProfile } from '/@/api/device/deviceManager'; | |
4 | +import { getOrganizationList } from '/@/api/system/system'; | |
5 | +import { copyTransFun } from '/@/utils/fnUtils'; | |
6 | +// 第一步的表单 | |
4 | 7 | export const step1Schemas: FormSchema[] = [ |
5 | 8 | { |
6 | 9 | field: 'icon', |
... | ... | @@ -32,6 +35,30 @@ export const step1Schemas: FormSchema[] = [ |
32 | 35 | }, |
33 | 36 | }, |
34 | 37 | { |
38 | + field: 'profileId', | |
39 | + label: '设备配置', | |
40 | + required: true, | |
41 | + component: 'ApiSelect', | |
42 | + componentProps: { | |
43 | + api: deviceProfile, | |
44 | + labelField: 'name', | |
45 | + valueField: 'id', | |
46 | + }, | |
47 | + }, | |
48 | + { | |
49 | + field: 'organizationId', | |
50 | + required: true, | |
51 | + label: '所属组织', | |
52 | + component: 'ApiTreeSelect', | |
53 | + componentProps: { | |
54 | + api: async () => { | |
55 | + const data = await getOrganizationList(); | |
56 | + copyTransFun(data as any as any[]); | |
57 | + return data; | |
58 | + }, | |
59 | + }, | |
60 | + }, | |
61 | + { | |
35 | 62 | field: 'label', |
36 | 63 | label: '设备标签', |
37 | 64 | component: 'Input', |
... | ... | @@ -40,14 +67,32 @@ export const step1Schemas: FormSchema[] = [ |
40 | 67 | }, |
41 | 68 | }, |
42 | 69 | { |
43 | - field: 'devicePosition', | |
70 | + field: 'deviceAddress', | |
44 | 71 | label: '设备位置', |
45 | 72 | component: 'Input', |
46 | - slot: 'devicePosition', | |
73 | + slot: 'deviceAddress', | |
47 | 74 | }, |
48 | 75 | { |
49 | - label: '备注', | |
50 | 76 | field: 'remark', |
77 | + label: '备注', | |
51 | 78 | component: 'InputTextArea', |
52 | 79 | }, |
80 | + { | |
81 | + field: 'id', | |
82 | + label: 'id', | |
83 | + component: 'Input', | |
84 | + show: false, | |
85 | + }, | |
86 | + { | |
87 | + field: 'profileId', | |
88 | + label: '设备配置id', | |
89 | + component: 'Input', | |
90 | + show: false, | |
91 | + }, | |
92 | + { | |
93 | + field: 'deviceToken', | |
94 | + label: '设备唯一token', | |
95 | + component: 'Input', | |
96 | + show: false, | |
97 | + }, | |
53 | 98 | ]; | ... | ... |