Commit 20bdaf985ae0e7343d3dbfc18d30ea5b9d3bb55e
Merge branch 'sqy_dev' into 'main'
设备页面开发 See merge request huang/yun-teng-iot-front!6
Showing
10 changed files
with
291 additions
and
236 deletions
@@ -6,7 +6,7 @@ VITE_PUBLIC_PATH = / | @@ -6,7 +6,7 @@ VITE_PUBLIC_PATH = / | ||
6 | 6 | ||
7 | # Cross-domain proxy, you can configure multiple | 7 | # Cross-domain proxy, you can configure multiple |
8 | # Please note that no line breaks | 8 | # Please note that no line breaks |
9 | -VITE_PROXY = [["/api","http://192.168.10.120:8082/api"],["/upload","http://192.168.10.120:3300/upload"]] | 9 | +VITE_PROXY = [["/api","http://192.168.10.116:8082/api"],["/upload","http://192.168.10.116:3300/upload"]] |
10 | # VITE_PROXY=[["/api","https://vvbin.cn/test"]] | 10 | # VITE_PROXY=[["/api","https://vvbin.cn/test"]] |
11 | 11 | ||
12 | # Delete console | 12 | # Delete console |
@@ -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 | +}; |
@@ -4,8 +4,9 @@ | @@ -4,8 +4,9 @@ | ||
4 | width="55rem" | 4 | width="55rem" |
5 | @register="register" | 5 | @register="register" |
6 | :title="getTitle" | 6 | :title="getTitle" |
7 | - @visible-change="handleVisibleChange" | ||
8 | @cancel="handleCancel" | 7 | @cancel="handleCancel" |
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"> |
@@ -14,8 +15,9 @@ | @@ -14,8 +15,9 @@ | ||
14 | </a-steps> | 15 | </a-steps> |
15 | </div> | 16 | </div> |
16 | <div class="mt-5"> | 17 | <div class="mt-5"> |
17 | - <DeviceStep1 @next="handleStep1Next" v-show="current === 0" /> | 18 | + <DeviceStep1 @next="handleStep1Next" v-show="current === 0" ref="DeviceStep1Ref" /> |
18 | <DeviceStep2 | 19 | <DeviceStep2 |
20 | + ref="DeviceStep2Ref" | ||
19 | @prev="handleStepPrev" | 21 | @prev="handleStepPrev" |
20 | @next="handleStep2Next" | 22 | @next="handleStep2Next" |
21 | v-show="current === 1" | 23 | v-show="current === 1" |
@@ -25,11 +27,13 @@ | @@ -25,11 +27,13 @@ | ||
25 | </BasicModal> | 27 | </BasicModal> |
26 | </template> | 28 | </template> |
27 | <script lang="ts"> | 29 | <script lang="ts"> |
28 | - import { defineComponent, ref, nextTick, computed, unref, reactive, toRefs } from 'vue'; | 30 | + import { defineComponent, ref, computed, unref, reactive, toRefs } from 'vue'; |
29 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 31 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
32 | + import { createOrEditDevice } from '/@/api/device/deviceManager'; | ||
30 | import DeviceStep1 from '/@/views/device/step/DeviceStep1.vue'; | 33 | import DeviceStep1 from '/@/views/device/step/DeviceStep1.vue'; |
31 | import DeviceStep2 from '/@/views/device/step/DeviceStep2.vue'; | 34 | import DeviceStep2 from '/@/views/device/step/DeviceStep2.vue'; |
32 | import { Steps } from 'ant-design-vue'; | 35 | import { Steps } from 'ant-design-vue'; |
36 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
33 | export default defineComponent({ | 37 | export default defineComponent({ |
34 | name: 'DeviceModal', | 38 | name: 'DeviceModal', |
35 | components: { | 39 | components: { |
@@ -42,72 +46,87 @@ | @@ -42,72 +46,87 @@ | ||
42 | props: { | 46 | props: { |
43 | userData: { type: Object }, | 47 | userData: { type: Object }, |
44 | }, | 48 | }, |
45 | - setup(props) { | 49 | + setup(_, { emit }) { |
50 | + const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); | ||
51 | + const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); | ||
52 | + const { createMessage } = useMessage(); | ||
46 | const state = reactive({ | 53 | const state = reactive({ |
47 | initStep2: false, | 54 | initStep2: false, |
48 | }); | 55 | }); |
49 | const current = ref(0); | 56 | const current = ref(0); |
50 | const isUpdate = ref(true); | 57 | const isUpdate = ref(true); |
51 | - const modelRef = ref({}); | ||
52 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备')); | 58 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备')); |
53 | - | ||
54 | - const [register] = useModalInner((data) => { | 59 | + // 所有参数 |
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 | + } | ||
55 | isUpdate.value = !!data?.isUpdate; | 71 | isUpdate.value = !!data?.isUpdate; |
56 | - data && onDataReceive(data); | ||
57 | }); | 72 | }); |
58 | 73 | ||
74 | + // 上一步 | ||
59 | function handleStepPrev() { | 75 | function handleStepPrev() { |
60 | current.value--; | 76 | current.value--; |
61 | } | 77 | } |
78 | + // 下一步 | ||
62 | function handleStep1Next(step1Values: any) { | 79 | function handleStep1Next(step1Values: any) { |
63 | current.value++; | 80 | current.value++; |
64 | state.initStep2 = true; | 81 | state.initStep2 = true; |
65 | - console.log(step1Values); | 82 | + stepState = { ...step1Values }; |
66 | } | 83 | } |
84 | + // | ||
67 | function handleStep2Next(step2Values: any) { | 85 | function handleStep2Next(step2Values: any) { |
68 | - current.value++; | ||
69 | - console.log(step2Values); | ||
70 | - } | ||
71 | - function handleRedo() { | ||
72 | - current.value = 0; | ||
73 | - state.initStep2 = false; | 86 | + stepState = { ...stepState, ...step2Values }; |
74 | } | 87 | } |
75 | function handleCancel() { | 88 | function handleCancel() { |
76 | - console.log('关闭了弹框'); | ||
77 | - } | ||
78 | - | ||
79 | - function onDataReceive(data) { | ||
80 | - console.log('Data Received', data); | ||
81 | - // 方式1; | ||
82 | - // setFieldsValue({ | ||
83 | - // field2: data.data, | ||
84 | - // field1: data.info, | ||
85 | - // }); | ||
86 | - | ||
87 | - // // 方式2 | ||
88 | - modelRef.value = { field2: data.data, field1: data.info }; | ||
89 | - | ||
90 | - // setProps({ | ||
91 | - // model:{ field2: data.data, field1: data.info } | ||
92 | - // }) | 89 | + current.value = 0; |
90 | + DeviceStep1Ref?.value?.resetFields(); | ||
91 | + DeviceStep2Ref?.value?.resetFields(); | ||
93 | } | 92 | } |
93 | + // 提交 | ||
94 | + async function handleOk() { | ||
95 | + if (current.value === 0) { | ||
96 | + // 验证 | ||
97 | + const valid = await DeviceStep1Ref.value?.parentValidate(); | ||
98 | + if (!valid) return; | ||
94 | 99 | ||
95 | - function handleVisibleChange(v) { | ||
96 | - v && props.userData && nextTick(() => onDataReceive(props.userData)); | 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'); | ||
97 | } | 117 | } |
98 | - | ||
99 | return { | 118 | return { |
100 | register, | 119 | register, |
101 | - model: modelRef, | ||
102 | getTitle, | 120 | getTitle, |
103 | - handleVisibleChange, | ||
104 | current, | 121 | current, |
122 | + DeviceStep1Ref, | ||
123 | + DeviceStep2Ref, | ||
105 | ...toRefs(state), | 124 | ...toRefs(state), |
106 | handleStepPrev, | 125 | handleStepPrev, |
107 | handleStep1Next, | 126 | handleStep1Next, |
108 | handleStep2Next, | 127 | handleStep2Next, |
109 | handleCancel, | 128 | handleCancel, |
110 | - handleRedo, | 129 | + handleOk, |
111 | }; | 130 | }; |
112 | }, | 131 | }, |
113 | }); | 132 | }); |
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 /> |
@@ -56,10 +63,9 @@ | @@ -56,10 +63,9 @@ | ||
56 | import { useScript } from '/@/hooks/web/useScript'; | 63 | import { useScript } from '/@/hooks/web/useScript'; |
57 | import { ScrollActionType } from '/@/components/Container/index'; | 64 | import { ScrollActionType } from '/@/components/Container/index'; |
58 | import { Input, Divider, Upload, message, Modal, Form, Row, Col } from 'ant-design-vue'; | 65 | import { Input, Divider, Upload, message, Modal, Form, Row, Col } from 'ant-design-vue'; |
59 | - import { EnvironmentTwoTone, LoadingOutlined, 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 }] = 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,15 +188,33 @@ | @@ -163,15 +188,33 @@ | ||
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 { |
217 | + resetFields, | ||
175 | positionState, | 218 | positionState, |
176 | register, | 219 | register, |
177 | beforeUpload, | 220 | beforeUpload, |
@@ -181,8 +224,12 @@ | @@ -181,8 +224,12 @@ | ||
181 | visible, | 224 | visible, |
182 | scrollRef, | 225 | scrollRef, |
183 | handleOk, | 226 | handleOk, |
227 | + handleCancel, | ||
184 | wrapRef, | 228 | wrapRef, |
185 | labelCol: { style: { width: '40px' } }, | 229 | labelCol: { style: { width: '40px' } }, |
230 | + parentSetFieldsValue, | ||
231 | + parentGetFieldsValue, | ||
232 | + parentValidate, | ||
186 | }; | 233 | }; |
187 | }, | 234 | }, |
188 | }); | 235 | }); |
1 | <template> | 1 | <template> |
2 | <div class="step2"> | 2 | <div class="step2"> |
3 | - <div><input type="checkbox" v-model="isCreaentials" @click="checked" /> 添加凭证 </div> | ||
4 | - | ||
5 | - <a-form :label-col="labelCol" :wrapper-col="wrapperCol" v-if="isCreaentials"> | ||
6 | - <a-form-item label="凭据类型"> | 3 | + <div |
4 | + ><input type="checkbox" v-model="creaentialsPassword.isCreaentials" @click="checked" /> | ||
5 | + 添加凭证 | ||
6 | + </div> | ||
7 | + <a-form | ||
8 | + ref="formRef" | ||
9 | + :rules="rules" | ||
10 | + :label-col="labelCol" | ||
11 | + :wrapper-col="wrapperCol" | ||
12 | + v-show="creaentialsPassword.isCreaentials" | ||
13 | + :model="creaentialsPassword" | ||
14 | + labelAlign="left" | ||
15 | + > | ||
16 | + <a-form-item label="凭据类型" name="creaentialsType"> | ||
7 | <a-select | 17 | <a-select |
8 | - v-model:value="creaentialsType" | 18 | + v-model:value="creaentialsPassword.creaentialsType" |
9 | style="width: 200px" | 19 | style="width: 200px" |
10 | @change="handleChange" | 20 | @change="handleChange" |
11 | placeholder="请选择凭据类型" | 21 | placeholder="请选择凭据类型" |
12 | :options="options" | 22 | :options="options" |
13 | /> | 23 | /> |
14 | </a-form-item> | 24 | </a-form-item> |
15 | - <div v-if="creaentialsType === 'Access token'"> | ||
16 | - <a-form-item label="访问令牌"> | ||
17 | - <a-input type="input" style="width: 200px" v-model:value="token" /> | 25 | + <div v-if="creaentialsPassword.creaentialsType === 'Access token'"> |
26 | + <a-form-item label="访问令牌" name="token"> | ||
27 | + <a-input type="password" style="width: 200px" v-model:value="creaentialsPassword.token" /> | ||
18 | </a-form-item> | 28 | </a-form-item> |
19 | </div> | 29 | </div> |
20 | - <div v-else-if="creaentialsType === 'X.509'"> | ||
21 | - <a-form-item label="RSA公钥"> | ||
22 | - <a-input type="input" style="width: 200px" v-model:value="publicKey" /> | 30 | + <div v-else-if="creaentialsPassword.creaentialsType === 'X.509'"> |
31 | + <a-form-item label="RSA公钥" name="publicKey"> | ||
32 | + <a-input | ||
33 | + type="password" | ||
34 | + style="width: 200px" | ||
35 | + v-model:value="creaentialsPassword.publicKey" | ||
36 | + /> | ||
23 | </a-form-item> | 37 | </a-form-item> |
24 | </div> | 38 | </div> |
25 | <div v-else> | 39 | <div v-else> |
26 | - <a-form-item label="客户端ID"> | ||
27 | - <a-input type="input" style="width: 200px" v-model:value="clientId" /> | 40 | + <a-form-item label="客户端ID" name="clientId"> |
41 | + <a-input type="input" style="width: 200px" v-model:value="creaentialsPassword.clientId" /> | ||
28 | </a-form-item> | 42 | </a-form-item> |
29 | - <a-form-item label="用户名"> | ||
30 | - <a-input type="input" style="width: 200px" v-model:value="username" /> | 43 | + <a-form-item label="用户名" name="username"> |
44 | + <a-input type="input" style="width: 200px" v-model:value="creaentialsPassword.username" /> | ||
31 | </a-form-item> | 45 | </a-form-item> |
32 | - <a-form-item label="密码"> | ||
33 | - <a-input type="password" style="width: 200px" v-model:value="password" /> | 46 | + <a-form-item label="密码" name="password"> |
47 | + <a-input | ||
48 | + type="password" | ||
49 | + style="width: 200px" | ||
50 | + v-model:value="creaentialsPassword.password" | ||
51 | + /> | ||
34 | </a-form-item> | 52 | </a-form-item> |
35 | </div> | 53 | </div> |
36 | </a-form> | 54 | </a-form> |
37 | - | ||
38 | <div class="flex justify-start"> | 55 | <div class="flex justify-start"> |
39 | <a-button class="mr-5" @click="prevStep">上一步</a-button> | 56 | <a-button class="mr-5" @click="prevStep">上一步</a-button> |
40 | </div> | 57 | </div> |
41 | </div> | 58 | </div> |
42 | </template> | 59 | </template> |
43 | <script lang="ts"> | 60 | <script lang="ts"> |
44 | - import { defineComponent, reactive, ref, toRefs } from 'vue'; | 61 | + import { defineComponent, reactive, ref, watch } from 'vue'; |
45 | 62 | ||
46 | - import { Input, Form, Select, Button, SelectProps } from 'ant-design-vue'; | 63 | + import { Input, Form, Select, Button } from 'ant-design-vue'; |
47 | export default defineComponent({ | 64 | export default defineComponent({ |
48 | components: { | 65 | components: { |
49 | [Form.name]: Form, | 66 | [Form.name]: Form, |
@@ -52,18 +69,26 @@ | @@ -52,18 +69,26 @@ | ||
52 | [Select.name]: Select, | 69 | [Select.name]: Select, |
53 | [Button.name]: Button, | 70 | [Button.name]: Button, |
54 | }, | 71 | }, |
55 | - emits: ['prev'], | 72 | + |
73 | + emits: ['prev', 'next'], | ||
56 | setup(_, { emit }) { | 74 | setup(_, { emit }) { |
57 | - const isCreaentials = ref(false); | ||
58 | - const creaentialsType = ref('Access token'); | 75 | + const formRef = ref(); |
59 | const creaentialsPassword = reactive({ | 76 | const creaentialsPassword = reactive({ |
77 | + isCreaentials: false, | ||
78 | + creaentialsType: 'Access token', | ||
60 | token: '', | 79 | token: '', |
61 | publicKey: '', | 80 | publicKey: '', |
62 | clientId: '', | 81 | clientId: '', |
63 | username: '', | 82 | username: '', |
64 | password: '', | 83 | password: '', |
65 | }); | 84 | }); |
66 | - const options = ref<SelectProps['options']>([ | 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 | + }; | ||
91 | + const options = ref([ | ||
67 | { | 92 | { |
68 | value: 'Access token', | 93 | value: 'Access token', |
69 | label: 'Access token', | 94 | label: 'Access token', |
@@ -78,41 +103,76 @@ | @@ -78,41 +103,76 @@ | ||
78 | label: 'MQTT Basic', | 103 | label: 'MQTT Basic', |
79 | }, | 104 | }, |
80 | ]); | 105 | ]); |
106 | + // 切换是否添加凭证 | ||
81 | const checked = () => { | 107 | const checked = () => { |
82 | - isCreaentials.value = !isCreaentials.value; | 108 | + creaentialsPassword.isCreaentials = !creaentialsPassword.isCreaentials; |
109 | + formRef.value.resetFields(); | ||
110 | + creaentialsPassword.creaentialsType = 'Access token'; | ||
83 | }; | 111 | }; |
84 | const prevStep = () => { | 112 | const prevStep = () => { |
85 | emit('prev'); | 113 | emit('prev'); |
86 | }; | 114 | }; |
115 | + watch(creaentialsPassword, (newValue) => { | ||
116 | + emit('next', newValue); | ||
117 | + }); | ||
118 | + | ||
87 | // 切换凭证类型时,重置字段 | 119 | // 切换凭证类型时,重置字段 |
88 | const handleChange = (value) => { | 120 | const handleChange = (value) => { |
89 | if (value === 'Access token') { | 121 | if (value === 'Access token') { |
90 | - creaentialsPassword.token = ''; | 122 | + resetCreantialsType(); |
91 | } else if (value === 'X.509') { | 123 | } else if (value === 'X.509') { |
92 | - creaentialsPassword.publicKey = ''; | 124 | + resetCreantialsType(); |
93 | } else { | 125 | } else { |
94 | - creaentialsPassword.clientId = ''; | ||
95 | - creaentialsPassword.username = ''; | ||
96 | - creaentialsPassword.password = ''; | 126 | + resetCreantialsType(); |
97 | } | 127 | } |
98 | }; | 128 | }; |
129 | + // 切换凭证类型时,重置字段 | ||
130 | + function resetCreantialsType() { | ||
131 | + creaentialsPassword.token = ''; | ||
132 | + creaentialsPassword.publicKey = ''; | ||
133 | + creaentialsPassword.clientId = ''; | ||
134 | + creaentialsPassword.username = ''; | ||
135 | + creaentialsPassword.password = ''; | ||
136 | + } | ||
137 | + | ||
138 | + // 重置所有字段 | ||
139 | + function resetFields() { | ||
140 | + creaentialsPassword.isCreaentials = false; | ||
141 | + creaentialsPassword.creaentialsType = 'Access token'; | ||
142 | + creaentialsPassword.token = ''; | ||
143 | + creaentialsPassword.publicKey = ''; | ||
144 | + creaentialsPassword.clientId = ''; | ||
145 | + creaentialsPassword.username = ''; | ||
146 | + creaentialsPassword.password = ''; | ||
147 | + formRef.value.resetFields(); | ||
148 | + } | ||
149 | + | ||
150 | + // 表单验证 | ||
151 | + function validate() { | ||
152 | + if (creaentialsPassword.isCreaentials) { | ||
153 | + return formRef.value.validate(); | ||
154 | + } | ||
155 | + return true; | ||
156 | + } | ||
99 | return { | 157 | return { |
100 | - ...toRefs(creaentialsPassword), | ||
101 | - creaentialsType, | ||
102 | - isCreaentials, | ||
103 | options, | 158 | options, |
159 | + formRef, | ||
160 | + creaentialsPassword, | ||
104 | handleChange, | 161 | handleChange, |
105 | prevStep, | 162 | prevStep, |
106 | checked, | 163 | checked, |
107 | labelCol: { style: { width: '150px' } }, | 164 | labelCol: { style: { width: '150px' } }, |
108 | wrapperCol: { span: 18 }, | 165 | wrapperCol: { span: 18 }, |
166 | + resetFields, | ||
167 | + validate, | ||
168 | + rules, | ||
109 | }; | 169 | }; |
110 | }, | 170 | }, |
111 | }); | 171 | }); |
112 | </script> | 172 | </script> |
113 | <style lang="less" scoped> | 173 | <style lang="less" scoped> |
114 | .step2 { | 174 | .step2 { |
115 | - width: 500px; | 175 | + width: 700px; |
116 | margin: 0 auto; | 176 | margin: 0 auto; |
117 | } | 177 | } |
118 | </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 | ]; |