Showing
10 changed files
with
225 additions
and
395 deletions
@@ -15,6 +15,8 @@ enum DeviceManagerApi { | @@ -15,6 +15,8 @@ enum DeviceManagerApi { | ||
15 | * 设备配置URL | 15 | * 设备配置URL |
16 | */ | 16 | */ |
17 | DEVICE_PROFILE_URL = '/deviceProfile', | 17 | DEVICE_PROFILE_URL = '/deviceProfile', |
18 | + | ||
19 | + DEVICE_PROFILE_URL_ME = '/deviceProfile/me', | ||
18 | } | 20 | } |
19 | 21 | ||
20 | export const devicePage = (params: DeviceQueryParam) => { | 22 | export const devicePage = (params: DeviceQueryParam) => { |
@@ -59,3 +61,20 @@ export const deleteDevice = (ids: string[]) => { | @@ -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 +6,7 @@ | ||
6 | :title="getTitle" | 6 | :title="getTitle" |
7 | @cancel="handleCancel" | 7 | @cancel="handleCancel" |
8 | @ok="handleOk" | 8 | @ok="handleOk" |
9 | + centered | ||
9 | > | 10 | > |
10 | <div class="step-form-form"> | 11 | <div class="step-form-form"> |
11 | <a-steps :current="current"> | 12 | <a-steps :current="current"> |
@@ -28,9 +29,11 @@ | @@ -28,9 +29,11 @@ | ||
28 | <script lang="ts"> | 29 | <script lang="ts"> |
29 | import { defineComponent, ref, computed, unref, reactive, toRefs } from 'vue'; | 30 | import { defineComponent, ref, computed, unref, reactive, toRefs } from 'vue'; |
30 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 31 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
32 | + import { createOrEditDevice } from '/@/api/device/deviceManager'; | ||
31 | import DeviceStep1 from '/@/views/device/step/DeviceStep1.vue'; | 33 | import DeviceStep1 from '/@/views/device/step/DeviceStep1.vue'; |
32 | import DeviceStep2 from '/@/views/device/step/DeviceStep2.vue'; | 34 | import DeviceStep2 from '/@/views/device/step/DeviceStep2.vue'; |
33 | import { Steps } from 'ant-design-vue'; | 35 | import { Steps } from 'ant-design-vue'; |
36 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
34 | export default defineComponent({ | 37 | export default defineComponent({ |
35 | name: 'DeviceModal', | 38 | name: 'DeviceModal', |
36 | components: { | 39 | components: { |
@@ -43,31 +46,42 @@ | @@ -43,31 +46,42 @@ | ||
43 | props: { | 46 | props: { |
44 | userData: { type: Object }, | 47 | userData: { type: Object }, |
45 | }, | 48 | }, |
46 | - setup(_) { | ||
47 | - // const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); | 49 | + setup(_, { emit }) { |
48 | const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); | 50 | const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); |
49 | const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); | 51 | const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); |
52 | + const { createMessage } = useMessage(); | ||
50 | const state = reactive({ | 53 | const state = reactive({ |
51 | initStep2: false, | 54 | initStep2: false, |
52 | }); | 55 | }); |
53 | const current = ref(0); | 56 | const current = ref(0); |
54 | const isUpdate = ref(true); | 57 | const isUpdate = ref(true); |
55 | - const modelRef = ref({}); | ||
56 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备')); | 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 | isUpdate.value = !!data?.isUpdate; | 71 | isUpdate.value = !!data?.isUpdate; |
61 | }); | 72 | }); |
62 | 73 | ||
74 | + // 上一步 | ||
63 | function handleStepPrev() { | 75 | function handleStepPrev() { |
64 | current.value--; | 76 | current.value--; |
65 | } | 77 | } |
78 | + // 下一步 | ||
66 | function handleStep1Next(step1Values: any) { | 79 | function handleStep1Next(step1Values: any) { |
67 | current.value++; | 80 | current.value++; |
68 | state.initStep2 = true; | 81 | state.initStep2 = true; |
69 | stepState = { ...step1Values }; | 82 | stepState = { ...step1Values }; |
70 | } | 83 | } |
84 | + // | ||
71 | function handleStep2Next(step2Values: any) { | 85 | function handleStep2Next(step2Values: any) { |
72 | stepState = { ...stepState, ...step2Values }; | 86 | stepState = { ...stepState, ...step2Values }; |
73 | } | 87 | } |
@@ -75,17 +89,34 @@ | @@ -75,17 +89,34 @@ | ||
75 | current.value = 0; | 89 | current.value = 0; |
76 | DeviceStep1Ref?.value?.resetFields(); | 90 | DeviceStep1Ref?.value?.resetFields(); |
77 | DeviceStep2Ref?.value?.resetFields(); | 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 | return { | 118 | return { |
87 | register, | 119 | register, |
88 | - model: modelRef, | ||
89 | getTitle, | 120 | getTitle, |
90 | current, | 121 | current, |
91 | DeviceStep1Ref, | 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 | import { BasicColumn } from '/@/components/Table'; | 1 | import { BasicColumn } from '/@/components/Table'; |
2 | import { FormSchema } from '/@/components/Table'; | 2 | import { FormSchema } from '/@/components/Table'; |
3 | -import { findDictItemByCode } from '/@/api/system/dict'; | ||
4 | import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel'; | 3 | import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel'; |
4 | +// 表格列数据 | ||
5 | export const columns: BasicColumn[] = [ | 5 | export const columns: BasicColumn[] = [ |
6 | { | 6 | { |
7 | title: '设备名称', | 7 | title: '设备名称', |
@@ -45,6 +45,7 @@ export const columns: BasicColumn[] = [ | @@ -45,6 +45,7 @@ export const columns: BasicColumn[] = [ | ||
45 | }, | 45 | }, |
46 | ]; | 46 | ]; |
47 | 47 | ||
48 | +// 查询字段 | ||
48 | export const searchFormSchema: FormSchema[] = [ | 49 | export const searchFormSchema: FormSchema[] = [ |
49 | { | 50 | { |
50 | field: 'deviceType', | 51 | field: 'deviceType', |
@@ -79,48 +80,3 @@ export const searchFormSchema: FormSchema[] = [ | @@ -79,48 +80,3 @@ export const searchFormSchema: FormSchema[] = [ | ||
79 | colProps: { span: 8 }, | 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,16 +65,13 @@ | ||
65 | /> | 65 | /> |
66 | </template> | 66 | </template> |
67 | </BasicTable> | 67 | </BasicTable> |
68 | - <!-- <ConfigDrawer @register="registerDrawer" @success="handleSuccess" /> --> | ||
69 | - <DeviceModal @register="registerModal" @success="handleSuccess" /> | 68 | + <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleReload" /> |
70 | </PageWrapper> | 69 | </PageWrapper> |
71 | </template> | 70 | </template> |
72 | <script lang="ts"> | 71 | <script lang="ts"> |
73 | import { defineComponent, reactive } from 'vue'; | 72 | import { defineComponent, reactive } from 'vue'; |
74 | import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | 73 | import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
75 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 74 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
76 | - // import { useDrawer } from '/@/components/Drawer'; | ||
77 | - // import ConfigDrawer from './DeviceDrawer.vue'; | ||
78 | import { columns, searchFormSchema } from './device.data'; | 75 | import { columns, searchFormSchema } from './device.data'; |
79 | import { Tag } from 'ant-design-vue'; | 76 | import { Tag } from 'ant-design-vue'; |
80 | import { useMessage } from '/@/hooks/web/useMessage'; | 77 | import { useMessage } from '/@/hooks/web/useMessage'; |
@@ -90,17 +87,16 @@ | @@ -90,17 +87,16 @@ | ||
90 | name: 'DeviceManagement', | 87 | name: 'DeviceManagement', |
91 | components: { | 88 | components: { |
92 | BasicTable, | 89 | BasicTable, |
93 | - // ConfigDrawer, | ||
94 | PageWrapper, | 90 | PageWrapper, |
95 | TableAction, | 91 | TableAction, |
96 | OrganizationIdTree, | 92 | OrganizationIdTree, |
97 | Tag, | 93 | Tag, |
98 | DeviceModal, | 94 | DeviceModal, |
99 | }, | 95 | }, |
100 | - setup() { | ||
101 | - // const [registerDrawer, { openDrawer }] = useDrawer(); | 96 | + setup(_) { |
102 | const { createMessage } = useMessage(); | 97 | const { createMessage } = useMessage(); |
103 | const go = useGo(); | 98 | const go = useGo(); |
99 | + | ||
104 | const searchInfo = reactive<Recordable>({}); | 100 | const searchInfo = reactive<Recordable>({}); |
105 | const [registerModal, { openModal }] = useModal(); | 101 | const [registerModal, { openModal }] = useModal(); |
106 | const [registerTable, { reload }] = useTable({ | 102 | const [registerTable, { reload }] = useTable({ |
@@ -124,6 +120,9 @@ | @@ -124,6 +120,9 @@ | ||
124 | fixed: undefined, | 120 | fixed: undefined, |
125 | }, | 121 | }, |
126 | }); | 122 | }); |
123 | + const handleReload = () => { | ||
124 | + handleSuccess(); | ||
125 | + }; | ||
127 | 126 | ||
128 | function handleCreate() { | 127 | function handleCreate() { |
129 | openModal(true, { | 128 | openModal(true, { |
@@ -158,7 +157,6 @@ | @@ -158,7 +157,6 @@ | ||
158 | } | 157 | } |
159 | return { | 158 | return { |
160 | registerTable, | 159 | registerTable, |
161 | - // registerDrawer, | ||
162 | handleCreate, | 160 | handleCreate, |
163 | handleEdit, | 161 | handleEdit, |
164 | handleDelete, | 162 | handleDelete, |
@@ -169,6 +167,7 @@ | @@ -169,6 +167,7 @@ | ||
169 | handleSelect, | 167 | handleSelect, |
170 | searchInfo, | 168 | searchInfo, |
171 | registerModal, | 169 | registerModal, |
170 | + handleReload, | ||
172 | }; | 171 | }; |
173 | }, | 172 | }, |
174 | }); | 173 | }); |
@@ -19,7 +19,7 @@ | @@ -19,7 +19,7 @@ | ||
19 | </div> | 19 | </div> |
20 | </Upload> | 20 | </Upload> |
21 | </template> | 21 | </template> |
22 | - <template #devicePosition> | 22 | + <template #deviceAddress> |
23 | <Input disabled v-model:value="positionState.address"> | 23 | <Input disabled v-model:value="positionState.address"> |
24 | <template #addonAfter> | 24 | <template #addonAfter> |
25 | <EnvironmentTwoTone @click="selectPosition" /> | 25 | <EnvironmentTwoTone @click="selectPosition" /> |
@@ -28,10 +28,17 @@ | @@ -28,10 +28,17 @@ | ||
28 | </template> | 28 | </template> |
29 | </BasicForm> | 29 | </BasicForm> |
30 | </div> | 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 | <div> | 39 | <div> |
33 | <a-form :label-col="labelCol"> | 40 | <a-form :label-col="labelCol"> |
34 | - <a-row :gutter="20"> | 41 | + <a-row :gutter="20" class="pt-4 pl-6"> |
35 | <a-col :span="8"> | 42 | <a-col :span="8"> |
36 | <a-form-item label="经度"> | 43 | <a-form-item label="经度"> |
37 | <Input type="input" v-model:value="positionState.lng" disabled /> | 44 | <Input type="input" v-model:value="positionState.lng" disabled /> |
@@ -59,7 +66,6 @@ | @@ -59,7 +66,6 @@ | ||
59 | import { EnvironmentTwoTone, PlusOutlined } from '@ant-design/icons-vue'; | 66 | import { EnvironmentTwoTone, PlusOutlined } from '@ant-design/icons-vue'; |
60 | import { upload } from '/@/api/oss/ossFileUploader'; | 67 | import { upload } from '/@/api/oss/ossFileUploader'; |
61 | import { FileItem } from '/@/components/Upload/src/typing'; | 68 | import { FileItem } from '/@/components/Upload/src/typing'; |
62 | - | ||
63 | export default defineComponent({ | 69 | export default defineComponent({ |
64 | components: { | 70 | components: { |
65 | BasicForm, | 71 | BasicForm, |
@@ -79,34 +85,35 @@ | @@ -79,34 +85,35 @@ | ||
79 | emits: ['next'], | 85 | emits: ['next'], |
80 | setup(_, { emit }) { | 86 | setup(_, { emit }) { |
81 | const devicePic = ref(''); | 87 | const devicePic = ref(''); |
82 | - const positionState = reactive({ | 88 | + let positionState = reactive({ |
83 | lng: '', | 89 | lng: '', |
84 | lat: '', | 90 | lat: '', |
85 | address: '', | 91 | address: '', |
86 | }); | 92 | }); |
87 | - const [register, { validate, resetFields }] = useForm({ | 93 | + const [register, { validate, resetFields, setFieldsValue, getFieldsValue }] = useForm({ |
88 | labelWidth: 100, | 94 | labelWidth: 100, |
89 | schemas: step1Schemas, | 95 | schemas: step1Schemas, |
90 | actionColOptions: { | 96 | actionColOptions: { |
91 | span: 14, | 97 | span: 14, |
92 | }, | 98 | }, |
99 | + labelAlign: 'left', | ||
93 | showResetButton: false, | 100 | showResetButton: false, |
94 | submitButtonOptions: { | 101 | submitButtonOptions: { |
95 | text: '下一步', | 102 | text: '下一步', |
96 | }, | 103 | }, |
97 | submitFunc: customSubmitFunc, | 104 | submitFunc: customSubmitFunc, |
98 | }); | 105 | }); |
99 | - | ||
100 | async function customSubmitFunc() { | 106 | async function customSubmitFunc() { |
101 | try { | 107 | try { |
102 | let values = await validate(); | 108 | let values = await validate(); |
103 | values = { devicePic: devicePic.value, ...positionState, ...values }; | 109 | values = { devicePic: devicePic.value, ...positionState, ...values }; |
104 | delete values.icon; | 110 | delete values.icon; |
105 | - delete values.devicePosition; | 111 | + delete values.deviceAddress; |
106 | emit('next', values); | 112 | emit('next', values); |
107 | // 获取输入的数据 | 113 | // 获取输入的数据 |
108 | - } catch (error) {} | 114 | + } catch (e) {} |
109 | } | 115 | } |
116 | + | ||
110 | // 图片上传 | 117 | // 图片上传 |
111 | async function customUpload({ file }) { | 118 | async function customUpload({ file }) { |
112 | if (beforeUpload(file)) { | 119 | if (beforeUpload(file)) { |
@@ -150,12 +157,30 @@ | @@ -150,12 +157,30 @@ | ||
150 | const BMap = (window as any).BMap; | 157 | const BMap = (window as any).BMap; |
151 | if (!wrapEl) return; | 158 | if (!wrapEl) return; |
152 | const map = new BMap.Map(wrapEl); | 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 | const { lat, lng } = map.he; | 165 | const { lat, lng } = map.he; |
155 | positionState.lat = lat + ''; | 166 | positionState.lat = lat + ''; |
156 | positionState.lng = lng + ''; | 167 | positionState.lng = lng + ''; |
157 | let gc = new BMap.Geocoder(); | 168 | let gc = new BMap.Geocoder(); |
158 | let newPoint = new BMap.Point(lng, lat); | 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 | gc.getLocation(newPoint, (rs) => { | 184 | gc.getLocation(newPoint, (rs) => { |
160 | let addComp = rs.addressComponents; | 185 | let addComp = rs.addressComponents; |
161 | //获取详细的地址,精确到街道的名称 | 186 | //获取详细的地址,精确到街道的名称 |
@@ -163,14 +188,31 @@ | @@ -163,14 +188,31 @@ | ||
163 | positionState.address = addrname; | 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 | const handleOk = () => { | 193 | const handleOk = () => { |
172 | visible.value = false; | 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 | return { | 216 | return { |
175 | resetFields, | 217 | resetFields, |
176 | positionState, | 218 | positionState, |
@@ -182,8 +224,12 @@ | @@ -182,8 +224,12 @@ | ||
182 | visible, | 224 | visible, |
183 | scrollRef, | 225 | scrollRef, |
184 | handleOk, | 226 | handleOk, |
227 | + handleCancel, | ||
185 | wrapRef, | 228 | wrapRef, |
186 | labelCol: { style: { width: '40px' } }, | 229 | labelCol: { style: { width: '40px' } }, |
230 | + parentSetFieldsValue, | ||
231 | + parentGetFieldsValue, | ||
232 | + parentValidate, | ||
187 | }; | 233 | }; |
188 | }, | 234 | }, |
189 | }); | 235 | }); |
@@ -4,15 +4,16 @@ | @@ -4,15 +4,16 @@ | ||
4 | ><input type="checkbox" v-model="creaentialsPassword.isCreaentials" @click="checked" /> | 4 | ><input type="checkbox" v-model="creaentialsPassword.isCreaentials" @click="checked" /> |
5 | 添加凭证 | 5 | 添加凭证 |
6 | </div> | 6 | </div> |
7 | - | ||
8 | <a-form | 7 | <a-form |
9 | ref="formRef" | 8 | ref="formRef" |
9 | + :rules="rules" | ||
10 | :label-col="labelCol" | 10 | :label-col="labelCol" |
11 | :wrapper-col="wrapperCol" | 11 | :wrapper-col="wrapperCol" |
12 | - v-if="creaentialsPassword.isCreaentials" | 12 | + v-show="creaentialsPassword.isCreaentials" |
13 | :model="creaentialsPassword" | 13 | :model="creaentialsPassword" |
14 | + labelAlign="left" | ||
14 | > | 15 | > |
15 | - <a-form-item label="凭据类型" name="creantialsType"> | 16 | + <a-form-item label="凭据类型" name="creaentialsType"> |
16 | <a-select | 17 | <a-select |
17 | v-model:value="creaentialsPassword.creaentialsType" | 18 | v-model:value="creaentialsPassword.creaentialsType" |
18 | style="width: 200px" | 19 | style="width: 200px" |
@@ -23,13 +24,13 @@ | @@ -23,13 +24,13 @@ | ||
23 | </a-form-item> | 24 | </a-form-item> |
24 | <div v-if="creaentialsPassword.creaentialsType === 'Access token'"> | 25 | <div v-if="creaentialsPassword.creaentialsType === 'Access token'"> |
25 | <a-form-item label="访问令牌" name="token"> | 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 | </a-form-item> | 28 | </a-form-item> |
28 | </div> | 29 | </div> |
29 | <div v-else-if="creaentialsPassword.creaentialsType === 'X.509'"> | 30 | <div v-else-if="creaentialsPassword.creaentialsType === 'X.509'"> |
30 | <a-form-item label="RSA公钥" name="publicKey"> | 31 | <a-form-item label="RSA公钥" name="publicKey"> |
31 | <a-input | 32 | <a-input |
32 | - type="input" | 33 | + type="password" |
33 | style="width: 200px" | 34 | style="width: 200px" |
34 | v-model:value="creaentialsPassword.publicKey" | 35 | v-model:value="creaentialsPassword.publicKey" |
35 | /> | 36 | /> |
@@ -51,7 +52,6 @@ | @@ -51,7 +52,6 @@ | ||
51 | </a-form-item> | 52 | </a-form-item> |
52 | </div> | 53 | </div> |
53 | </a-form> | 54 | </a-form> |
54 | - | ||
55 | <div class="flex justify-start"> | 55 | <div class="flex justify-start"> |
56 | <a-button class="mr-5" @click="prevStep">上一步</a-button> | 56 | <a-button class="mr-5" @click="prevStep">上一步</a-button> |
57 | </div> | 57 | </div> |
@@ -69,6 +69,7 @@ | @@ -69,6 +69,7 @@ | ||
69 | [Select.name]: Select, | 69 | [Select.name]: Select, |
70 | [Button.name]: Button, | 70 | [Button.name]: Button, |
71 | }, | 71 | }, |
72 | + | ||
72 | emits: ['prev', 'next'], | 73 | emits: ['prev', 'next'], |
73 | setup(_, { emit }) { | 74 | setup(_, { emit }) { |
74 | const formRef = ref(); | 75 | const formRef = ref(); |
@@ -81,6 +82,12 @@ | @@ -81,6 +82,12 @@ | ||
81 | username: '', | 82 | username: '', |
82 | password: '', | 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 | const options = ref([ | 91 | const options = ref([ |
85 | { | 92 | { |
86 | value: 'Access token', | 93 | value: 'Access token', |
@@ -96,8 +103,11 @@ | @@ -96,8 +103,11 @@ | ||
96 | label: 'MQTT Basic', | 103 | label: 'MQTT Basic', |
97 | }, | 104 | }, |
98 | ]); | 105 | ]); |
106 | + // 切换是否添加凭证 | ||
99 | const checked = () => { | 107 | const checked = () => { |
100 | creaentialsPassword.isCreaentials = !creaentialsPassword.isCreaentials; | 108 | creaentialsPassword.isCreaentials = !creaentialsPassword.isCreaentials; |
109 | + formRef.value.resetFields(); | ||
110 | + creaentialsPassword.creaentialsType = 'Access token'; | ||
101 | }; | 111 | }; |
102 | const prevStep = () => { | 112 | const prevStep = () => { |
103 | emit('prev'); | 113 | emit('prev'); |
@@ -109,21 +119,40 @@ | @@ -109,21 +119,40 @@ | ||
109 | // 切换凭证类型时,重置字段 | 119 | // 切换凭证类型时,重置字段 |
110 | const handleChange = (value) => { | 120 | const handleChange = (value) => { |
111 | if (value === 'Access token') { | 121 | if (value === 'Access token') { |
112 | - creaentialsPassword.token = ''; | 122 | + resetCreantialsType(); |
113 | } else if (value === 'X.509') { | 123 | } else if (value === 'X.509') { |
114 | - creaentialsPassword.publicKey = ''; | 124 | + resetCreantialsType(); |
115 | } else { | 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 | function resetFields() { | 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 | formRef.value.resetFields(); | 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 | return { | 157 | return { |
129 | options, | 158 | options, |
@@ -135,13 +164,15 @@ | @@ -135,13 +164,15 @@ | ||
135 | labelCol: { style: { width: '150px' } }, | 164 | labelCol: { style: { width: '150px' } }, |
136 | wrapperCol: { span: 18 }, | 165 | wrapperCol: { span: 18 }, |
137 | resetFields, | 166 | resetFields, |
167 | + validate, | ||
168 | + rules, | ||
138 | }; | 169 | }; |
139 | }, | 170 | }, |
140 | }); | 171 | }); |
141 | </script> | 172 | </script> |
142 | <style lang="less" scoped> | 173 | <style lang="less" scoped> |
143 | .step2 { | 174 | .step2 { |
144 | - width: 500px; | 175 | + width: 700px; |
145 | margin: 0 auto; | 176 | margin: 0 auto; |
146 | } | 177 | } |
147 | </style> | 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 | import { FormSchema } from '/@/components/Form'; | 1 | import { FormSchema } from '/@/components/Form'; |
2 | import { findDictItemByCode } from '/@/api/system/dict'; | 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 | export const step1Schemas: FormSchema[] = [ | 7 | export const step1Schemas: FormSchema[] = [ |
5 | { | 8 | { |
6 | field: 'icon', | 9 | field: 'icon', |
@@ -32,6 +35,30 @@ export const step1Schemas: FormSchema[] = [ | @@ -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 | field: 'label', | 62 | field: 'label', |
36 | label: '设备标签', | 63 | label: '设备标签', |
37 | component: 'Input', | 64 | component: 'Input', |
@@ -40,14 +67,32 @@ export const step1Schemas: FormSchema[] = [ | @@ -40,14 +67,32 @@ export const step1Schemas: FormSchema[] = [ | ||
40 | }, | 67 | }, |
41 | }, | 68 | }, |
42 | { | 69 | { |
43 | - field: 'devicePosition', | 70 | + field: 'deviceAddress', |
44 | label: '设备位置', | 71 | label: '设备位置', |
45 | component: 'Input', | 72 | component: 'Input', |
46 | - slot: 'devicePosition', | 73 | + slot: 'deviceAddress', |
47 | }, | 74 | }, |
48 | { | 75 | { |
49 | - label: '备注', | ||
50 | field: 'remark', | 76 | field: 'remark', |
77 | + label: '备注', | ||
51 | component: 'InputTextArea', | 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 | ]; |