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 | ]; | ... | ... |