Commit 310138b3cc4c3e6710657bc0216af7934dad5e28
1 parent
74c11a97
feat(front): 新增设备及设备配置页面【待完善新增、修改】
Showing
8 changed files
with
879 additions
and
0 deletions
src/api/device/deviceManager.ts
0 → 100644
| 1 | +import {defHttp} from "/@/utils/http/axios"; | |
| 2 | +import { | |
| 3 | + DeviceModel, | |
| 4 | + DeviceProfileModel, | |
| 5 | + DeviceProfileQueryParam, | |
| 6 | + DeviceQueryParam | |
| 7 | +} from "/@/api/device/model/deviceModel"; | |
| 8 | + | |
| 9 | +enum DeviceManagerApi { | |
| 10 | + /** | |
| 11 | + * 设备URL | |
| 12 | + */ | |
| 13 | + DEVICE_URL = "/device", | |
| 14 | + /** | |
| 15 | + * 设备配置URL | |
| 16 | + */ | |
| 17 | + DEVICE_PROFILE_URL = "/deviceProfile" | |
| 18 | +} | |
| 19 | + | |
| 20 | +export const devicePage = (params: DeviceQueryParam) =>{ | |
| 21 | + return defHttp.get<DeviceModel>({ | |
| 22 | + url: DeviceManagerApi.DEVICE_URL, | |
| 23 | + params | |
| 24 | + }); | |
| 25 | +} | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * 分页查询设备配置页面 | |
| 29 | + * @param params pageSize page name | |
| 30 | + */ | |
| 31 | +export const deviceProfilePage = (params: DeviceProfileQueryParam) => { | |
| 32 | + return defHttp.get<DeviceProfileModel>({ | |
| 33 | + url: DeviceManagerApi.DEVICE_PROFILE_URL, | |
| 34 | + params | |
| 35 | + }); | |
| 36 | +} | |
| 37 | +/** | |
| 38 | + * 删除设备配置 | |
| 39 | + * @param ids 删除的ids | |
| 40 | + */ | |
| 41 | +export const deleteDeviceProfile = (ids: string[]) => { | |
| 42 | + return defHttp.delete({ | |
| 43 | + url: DeviceManagerApi.DEVICE_PROFILE_URL, | |
| 44 | + data:{ | |
| 45 | + ids:ids | |
| 46 | + } | |
| 47 | + }) | |
| 48 | +} | |
| 49 | + | |
| 50 | +/** | |
| 51 | + * 删除设备 | |
| 52 | + * @param ids 删除的ids | |
| 53 | + */ | |
| 54 | +export const deleteDevice = (ids: string[]) => { | |
| 55 | + return defHttp.delete({ | |
| 56 | + url: DeviceManagerApi.DEVICE_URL, | |
| 57 | + data:{ | |
| 58 | + ids:ids | |
| 59 | + } | |
| 60 | + }) | |
| 61 | +} | ... | ... |
src/api/device/model/deviceModel.ts
0 → 100644
| 1 | +import {BasicPageParams} from "/@/api/model/baseModel"; | |
| 2 | +export enum DeviceState { | |
| 3 | + INACTIVE='INACTIVE', | |
| 4 | + ONLINE='ONLINE', | |
| 5 | + OFFLINE='OFFLINE' | |
| 6 | +} | |
| 7 | +export enum DeviceTypeEnum{ | |
| 8 | + GATEWAY='GATEWAY', | |
| 9 | + DIRECT_CONNECTION='DIRECT_CONNECTION', | |
| 10 | + SENSOR='SENSOR' | |
| 11 | +} | |
| 12 | +export type DeviceProfileQueryParam = BasicPageParams & DeviceProfileParam | |
| 13 | +export type DeviceQueryParam = BasicPageParams & DeviceParam | |
| 14 | +export type DeviceParam = { | |
| 15 | + name?:string, | |
| 16 | + deviceProfileId?:string | |
| 17 | +} | |
| 18 | +export type DeviceProfileParam = { | |
| 19 | + name?: string | |
| 20 | +} | |
| 21 | + | |
| 22 | +export interface DeviceModel{ | |
| 23 | + id:string, | |
| 24 | + name:string, | |
| 25 | + deviceInfo:any, | |
| 26 | + activeTime:string, | |
| 27 | + deviceState:DeviceState, | |
| 28 | + profileId:string, | |
| 29 | + label:string, | |
| 30 | + lastConnectTime:string, | |
| 31 | + deviceType:DeviceTypeEnum | |
| 32 | +} | |
| 33 | + | |
| 34 | +export interface DeviceProfileModel{ | |
| 35 | + id:string, | |
| 36 | + name:string, | |
| 37 | + transportType:string, | |
| 38 | + createTime:string, | |
| 39 | + description:string | |
| 40 | +} | ... | ... |
src/views/device/DeviceDrawer.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <BasicDrawer | |
| 3 | + v-bind="$attrs" | |
| 4 | + @register="registerDrawer" | |
| 5 | + showFooter | |
| 6 | + :title="getTitle" | |
| 7 | + width="500px" | |
| 8 | + @ok="handleSubmit" | |
| 9 | + > | |
| 10 | + <BasicForm @register="registerForm"/> | |
| 11 | + </BasicDrawer> | |
| 12 | +</template> | |
| 13 | +<script lang="ts"> | |
| 14 | + import { defineComponent, ref, computed, unref } from 'vue'; | |
| 15 | + import { BasicForm, useForm } from '/@/components/Form'; | |
| 16 | + import { formSchema } from './config.data'; | |
| 17 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | |
| 18 | + import {saveOrEditMessageConfig} from "/@/api/message/config"; | |
| 19 | + import {useMessage} from "/@/hooks/web/useMessage"; | |
| 20 | + | |
| 21 | + export default defineComponent({ | |
| 22 | + name: 'ConfigDrawer', | |
| 23 | + components: { BasicDrawer, BasicForm }, | |
| 24 | + emits: ['success', 'register'], | |
| 25 | + setup(_, { emit }) { | |
| 26 | + const isUpdate = ref(true); | |
| 27 | + | |
| 28 | + const [registerForm, { validate,setFieldsValue,resetFields }] = useForm({ | |
| 29 | + labelWidth: 120, | |
| 30 | + schemas: formSchema, | |
| 31 | + showActionButtonGroup: false, | |
| 32 | + }); | |
| 33 | + | |
| 34 | + const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { | |
| 35 | + await resetFields(); | |
| 36 | + setDrawerProps({ confirmLoading: false }); | |
| 37 | + isUpdate.value = !!data?.isUpdate; | |
| 38 | + if (unref(isUpdate)) { | |
| 39 | + const config = data.record.config; | |
| 40 | + for (const key in config){ | |
| 41 | + Reflect.set(data.record, key+'', config[key]); | |
| 42 | + } | |
| 43 | + await setFieldsValue({ | |
| 44 | + ...data.record, | |
| 45 | + }); | |
| 46 | + } | |
| 47 | + }); | |
| 48 | + | |
| 49 | + const getTitle = computed(() => (!unref(isUpdate) ? '新增消息配置' : '编辑消息配置')); | |
| 50 | + | |
| 51 | + async function handleSubmit() { | |
| 52 | + try { | |
| 53 | + const values = await validate(); | |
| 54 | + const { createMessage } = useMessage(); | |
| 55 | + setDrawerProps({ confirmLoading: true }); | |
| 56 | + let config={}; | |
| 57 | + if(values.messageType === 'PHONE_MESSAGE'){ | |
| 58 | + config ={ | |
| 59 | + "accessKeyId":values.accessKeyId, | |
| 60 | + "accessKeySecret":values.accessKeySecret, | |
| 61 | + } | |
| 62 | + }else if(values.messageType === 'EMAIL_MESSAGE'){ | |
| 63 | + config ={ | |
| 64 | + "host":values.host, | |
| 65 | + "port":values.port, | |
| 66 | + "username":values.username, | |
| 67 | + "password":values.password, | |
| 68 | + } | |
| 69 | + } | |
| 70 | + Reflect.set(values, 'config', config); | |
| 71 | + let saveMessage = "添加成功"; | |
| 72 | + let updateMessage = "修改成功"; | |
| 73 | + await saveOrEditMessageConfig(values, unref(isUpdate)); | |
| 74 | + closeDrawer(); | |
| 75 | + emit('success'); | |
| 76 | + createMessage.success(unref(isUpdate)?updateMessage:saveMessage); | |
| 77 | + } finally { | |
| 78 | + setDrawerProps({ confirmLoading: false }); | |
| 79 | + } | |
| 80 | + } | |
| 81 | + | |
| 82 | + return { | |
| 83 | + registerDrawer, | |
| 84 | + registerForm, | |
| 85 | + getTitle, | |
| 86 | + handleSubmit, | |
| 87 | + }; | |
| 88 | + }, | |
| 89 | + }); | |
| 90 | +</script> | ... | ... |
src/views/device/config.data.ts
0 → 100644
| 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 | +export const columns: BasicColumn[] = [ | |
| 7 | + { | |
| 8 | + title: '设备名称', | |
| 9 | + dataIndex: 'name', | |
| 10 | + width: 200, | |
| 11 | + }, | |
| 12 | + { | |
| 13 | + title: '设备类型', | |
| 14 | + dataIndex: 'deviceType', | |
| 15 | + width: 200, | |
| 16 | + slots:{customRender:'deviceType'}, | |
| 17 | + }, | |
| 18 | + { | |
| 19 | + title: '设备配置', | |
| 20 | + dataIndex: 'deviceProfile.name', | |
| 21 | + width: 180, | |
| 22 | + slots: { customRender: 'deviceProfile' }, | |
| 23 | + }, | |
| 24 | + { | |
| 25 | + title: '标签', | |
| 26 | + dataIndex: 'label', | |
| 27 | + width: 180 | |
| 28 | + }, | |
| 29 | + { | |
| 30 | + title: '配置信息', | |
| 31 | + dataIndex: 'deviceInfo', | |
| 32 | + width: 180, | |
| 33 | + slots: { customRender: 'config' }, | |
| 34 | + }, | |
| 35 | + { | |
| 36 | + title: '状态', | |
| 37 | + dataIndex: 'deviceState', | |
| 38 | + width: 120, | |
| 39 | + slots: { customRender: 'deviceState' }, | |
| 40 | + }, | |
| 41 | + | |
| 42 | + { | |
| 43 | + title: '最后连接时间', | |
| 44 | + dataIndex: 'lastConnectTime', | |
| 45 | + width: 180, | |
| 46 | + }, | |
| 47 | + { | |
| 48 | + title: '创建时间', | |
| 49 | + dataIndex: 'createTime', | |
| 50 | + width: 180, | |
| 51 | + }, | |
| 52 | +]; | |
| 53 | + | |
| 54 | +export const searchFormSchema: FormSchema[] = [ | |
| 55 | + { | |
| 56 | + field: 'deviceType', | |
| 57 | + label: '设备类型', | |
| 58 | + component: 'Select', | |
| 59 | + componentProps: { | |
| 60 | + options: [ | |
| 61 | + { label: '网关设备', value: DeviceTypeEnum.GATEWAY }, | |
| 62 | + { label: '直连设备', value: DeviceTypeEnum.DIRECT_CONNECTION }, | |
| 63 | + { label: '网关子设备', value: DeviceTypeEnum.SENSOR }, | |
| 64 | + ], | |
| 65 | + }, | |
| 66 | + colProps: { span: 4 }, | |
| 67 | + }, | |
| 68 | + { | |
| 69 | + field: 'deviceState', | |
| 70 | + label: '设备状态', | |
| 71 | + component: 'Select', | |
| 72 | + componentProps: { | |
| 73 | + options: [ | |
| 74 | + { label: '待激活', value: DeviceState.INACTIVE }, | |
| 75 | + { label: '在线', value: DeviceState.ONLINE }, | |
| 76 | + { label: '离线', value: DeviceState.OFFLINE }, | |
| 77 | + ], | |
| 78 | + }, | |
| 79 | + colProps: { span: 4 }, | |
| 80 | + }, | |
| 81 | + { | |
| 82 | + field: 'name', | |
| 83 | + label: '设备名称', | |
| 84 | + component: 'Input', | |
| 85 | + colProps: { span: 8 }, | |
| 86 | + }, | |
| 87 | +]; | |
| 88 | + | |
| 89 | + | |
| 90 | +export const isMessage = (type:string)=>{ | |
| 91 | + return type===MessageEnum.IS_SMS; | |
| 92 | +} | |
| 93 | +export const isEmail = (type:string)=>{ | |
| 94 | + return type===MessageEnum.IS_EMAIL; | |
| 95 | +} | |
| 96 | + | |
| 97 | +export const formSchema: FormSchema[] = [ | |
| 98 | + { | |
| 99 | + field: 'configName', | |
| 100 | + label: '配置名称', | |
| 101 | + required: true, | |
| 102 | + component:'Input' | |
| 103 | + }, | |
| 104 | + { | |
| 105 | + field: 'messageType', | |
| 106 | + label: '消息类型', | |
| 107 | + required: true, | |
| 108 | + component: 'ApiSelect', | |
| 109 | + componentProps: { | |
| 110 | + api:findDictItemByCode, | |
| 111 | + params:{ | |
| 112 | + dictCode:"message_type" | |
| 113 | + }, | |
| 114 | + labelField:'itemText', | |
| 115 | + valueField:'itemValue', | |
| 116 | + }, | |
| 117 | + }, | |
| 118 | + { | |
| 119 | + field: 'platformType', | |
| 120 | + label: '平台类型', | |
| 121 | + required: true, | |
| 122 | + component: 'ApiSelect', | |
| 123 | + componentProps: { | |
| 124 | + api:findDictItemByCode, | |
| 125 | + params:{ | |
| 126 | + dictCode:"platform_type" | |
| 127 | + }, | |
| 128 | + labelField:'itemText', | |
| 129 | + valueField:'itemValue', | |
| 130 | + }, | |
| 131 | + ifShow:({values}) => isMessage(Reflect.get(values,'messageType')), | |
| 132 | + }, | |
| 133 | + { | |
| 134 | + field: 'accessKeyId', | |
| 135 | + label: 'accessKeyId', | |
| 136 | + required: true, | |
| 137 | + component:'Input', | |
| 138 | + ifShow:({values}) => isMessage(Reflect.get(values,'messageType')), | |
| 139 | + }, | |
| 140 | + { | |
| 141 | + field: 'accessKeySecret', | |
| 142 | + label: 'accessKeySecret', | |
| 143 | + required: true, | |
| 144 | + component:'Input', | |
| 145 | + ifShow:({values}) => isMessage(Reflect.get(values,'messageType')), | |
| 146 | + }, | |
| 147 | + { | |
| 148 | + field: 'host', | |
| 149 | + label: '服务器地址', | |
| 150 | + defaultValue:'smtp.163.com', | |
| 151 | + required: true, | |
| 152 | + component:'Input', | |
| 153 | + ifShow:({values}) => isEmail(Reflect.get(values,'messageType')), | |
| 154 | + }, | |
| 155 | + { | |
| 156 | + field: 'port', | |
| 157 | + label: '端口', | |
| 158 | + defaultValue: 25, | |
| 159 | + required: true, | |
| 160 | + component:'InputNumber', | |
| 161 | + ifShow:({values}) => isEmail(Reflect.get(values,'messageType')), | |
| 162 | + }, | |
| 163 | + { | |
| 164 | + field: 'username', | |
| 165 | + label: '用户名', | |
| 166 | + required: true, | |
| 167 | + component:'Input', | |
| 168 | + ifShow:({values}) => isEmail(Reflect.get(values,'messageType')), | |
| 169 | + }, | |
| 170 | + { | |
| 171 | + field: 'password', | |
| 172 | + label: '密码', | |
| 173 | + required: true, | |
| 174 | + component:'InputPassword', | |
| 175 | + ifShow:({values}) => isEmail(Reflect.get(values,'messageType')), | |
| 176 | + }, | |
| 177 | + { | |
| 178 | + field: 'config', | |
| 179 | + label: '消息配置', | |
| 180 | + component:'Input', | |
| 181 | + show:false, | |
| 182 | + }, | |
| 183 | + { | |
| 184 | + field: 'id', | |
| 185 | + label: '主键', | |
| 186 | + component:'Input', | |
| 187 | + show:false, | |
| 188 | + }, | |
| 189 | + { | |
| 190 | + field: 'status', | |
| 191 | + label: '状态', | |
| 192 | + component: 'RadioButtonGroup', | |
| 193 | + defaultValue: 0, | |
| 194 | + componentProps: { | |
| 195 | + options: [ | |
| 196 | + { label: '启用', value: 1 }, | |
| 197 | + { label: '停用', value: 0 }, | |
| 198 | + ], | |
| 199 | + }, | |
| 200 | + }, | |
| 201 | + { | |
| 202 | + label: '备注', | |
| 203 | + field: 'remark', | |
| 204 | + component: 'InputTextArea', | |
| 205 | + } | |
| 206 | +]; | ... | ... |
src/views/device/index.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div> | |
| 3 | + <BasicTable @register="registerTable"> | |
| 4 | + <template #toolbar> | |
| 5 | + <a-button type="primary" @click="handleCreate"> 新增设备 </a-button> | |
| 6 | + </template> | |
| 7 | + <template #config="{record}"> | |
| 8 | + <a-button type="link" class="ml-2" @click="showData(record)"> 查看配置 </a-button> | |
| 9 | + </template> | |
| 10 | + <template #deviceProfile="{record}"> | |
| 11 | + <a-button type="link" class="ml-2" @click="goDeviceProfile"> {{record.deviceProfile.name}} </a-button> | |
| 12 | + </template> | |
| 13 | + <template #deviceType = "{record}"> | |
| 14 | + <Tag color="success" class="ml-2"> | |
| 15 | + {{record.deviceType==DeviceTypeEnum.GATEWAY ?'网关设备': | |
| 16 | + record.deviceType==DeviceTypeEnum.DIRECT_CONNECTION ?'直连设备':'网关子设备'}} | |
| 17 | + </Tag> | |
| 18 | + </template> | |
| 19 | + <template #deviceState = "{record}"> | |
| 20 | + <Tag :color="record.deviceState==DeviceState.INACTIVE?'warning':record.deviceState==DeviceState.ONLINE?'success':'error'" class="ml-2"> | |
| 21 | + {{record.deviceState==DeviceState.INACTIVE ?'待激活': | |
| 22 | + record.deviceState==DeviceState.ONLINE ?'在线':'离线'}} | |
| 23 | + </Tag> | |
| 24 | + </template> | |
| 25 | + <template #action="{ record }"> | |
| 26 | + <TableAction | |
| 27 | + :actions="[ | |
| 28 | + { | |
| 29 | + label:'编辑', | |
| 30 | + icon: 'clarity:note-edit-line', | |
| 31 | + onClick: handleEdit.bind(null, record), | |
| 32 | + }, | |
| 33 | + { | |
| 34 | + label:'删除', | |
| 35 | + icon: 'ant-design:delete-outlined', | |
| 36 | + color: 'error', | |
| 37 | + popConfirm: { | |
| 38 | + title: '是否确认删除', | |
| 39 | + confirm: handleDelete.bind(null, record), | |
| 40 | + } | |
| 41 | + }, | |
| 42 | + ]" | |
| 43 | + /> | |
| 44 | + </template> | |
| 45 | + </BasicTable> | |
| 46 | + <ConfigDrawer @register="registerDrawer" @success="handleSuccess" /> | |
| 47 | + </div> | |
| 48 | +</template> | |
| 49 | +<script lang="ts"> | |
| 50 | +import { defineComponent,h} from 'vue'; | |
| 51 | +import {DeviceState, DeviceTypeEnum} from "/@/api/device/model/deviceModel"; | |
| 52 | +import { BasicTable, useTable, TableAction } from '/@/components/Table'; | |
| 53 | +import { useDrawer } from '/@/components/Drawer'; | |
| 54 | +import ConfigDrawer from './DeviceDrawer.vue'; | |
| 55 | +import { columns, searchFormSchema } from './config.data'; | |
| 56 | +import {Modal, Tag} from 'ant-design-vue'; | |
| 57 | +import { CodeEditor,JsonPreview } from '/@/components/CodeEditor'; | |
| 58 | +import {useMessage} from "/@/hooks/web/useMessage"; | |
| 59 | +import {deleteDevice, devicePage} from "/@/api/device/deviceManager"; | |
| 60 | +import {PageEnum} from "/@/enums/pageEnum"; | |
| 61 | +import {useGo} from "/@/hooks/web/usePage"; | |
| 62 | + | |
| 63 | +export default defineComponent({ | |
| 64 | + name: 'DeviceManagement', | |
| 65 | + components: { BasicTable, ConfigDrawer, TableAction ,CodeEditor,Tag}, | |
| 66 | + setup() { | |
| 67 | + const [registerDrawer, { openDrawer }] = useDrawer(); | |
| 68 | + const {createMessage} = useMessage(); | |
| 69 | + const go = useGo(); | |
| 70 | + const [registerTable, { reload }] = useTable({ | |
| 71 | + title: '设备列表', | |
| 72 | + api: devicePage, | |
| 73 | + columns, | |
| 74 | + formConfig: { | |
| 75 | + labelWidth: 120, | |
| 76 | + schemas: searchFormSchema, | |
| 77 | + }, | |
| 78 | + useSearchForm: true, | |
| 79 | + showTableSetting: true, | |
| 80 | + bordered: true, | |
| 81 | + showIndexColumn: false, | |
| 82 | + actionColumn: { | |
| 83 | + width: 180, | |
| 84 | + title: '操作', | |
| 85 | + dataIndex: 'action', | |
| 86 | + slots: { customRender: 'action' }, | |
| 87 | + fixed: undefined, | |
| 88 | + }, | |
| 89 | + }); | |
| 90 | + | |
| 91 | + function handleCreate() { | |
| 92 | + openDrawer(true, { | |
| 93 | + isUpdate: false, | |
| 94 | + }); | |
| 95 | + } | |
| 96 | + | |
| 97 | + function handleEdit(record: Recordable) { | |
| 98 | + openDrawer(true, { | |
| 99 | + record, | |
| 100 | + isUpdate: true, | |
| 101 | + }); | |
| 102 | + } | |
| 103 | + | |
| 104 | + function handleDelete(record: Recordable) { | |
| 105 | + let ids = [record.id]; | |
| 106 | + deleteDevice(ids).then(()=>{ | |
| 107 | + createMessage.success("删除设备成功") | |
| 108 | + handleSuccess() | |
| 109 | + }); | |
| 110 | + } | |
| 111 | + | |
| 112 | + function handleSuccess() { | |
| 113 | + reload(); | |
| 114 | + } | |
| 115 | + function showData(record: Recordable){ | |
| 116 | + Modal.info({ | |
| 117 | + title: '当前配置', | |
| 118 | + width:480, | |
| 119 | + content: h(JsonPreview, { data: JSON.parse(JSON.stringify(record.deviceInfo)) }), | |
| 120 | + }); | |
| 121 | + } | |
| 122 | + function goDeviceProfile(){ | |
| 123 | + go(PageEnum.DEVICE_PROFILE) | |
| 124 | + } | |
| 125 | + return { | |
| 126 | + registerTable, | |
| 127 | + registerDrawer, | |
| 128 | + showData, | |
| 129 | + handleCreate, | |
| 130 | + handleEdit, | |
| 131 | + handleDelete, | |
| 132 | + handleSuccess, | |
| 133 | + goDeviceProfile, | |
| 134 | + DeviceTypeEnum, | |
| 135 | + DeviceState | |
| 136 | + }; | |
| 137 | + }, | |
| 138 | +}); | |
| 139 | +</script> | ... | ... |
src/views/device/profile/DeviceProfile.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <BasicDrawer | |
| 3 | + v-bind="$attrs" | |
| 4 | + @register="registerDrawer" | |
| 5 | + showFooter | |
| 6 | + :title="getTitle" | |
| 7 | + width="500px" | |
| 8 | + @ok="handleSubmit" | |
| 9 | + > | |
| 10 | + <BasicForm @register="registerForm"/> | |
| 11 | + </BasicDrawer> | |
| 12 | +</template> | |
| 13 | +<script lang="ts"> | |
| 14 | + import { defineComponent, ref, computed, unref } from 'vue'; | |
| 15 | + import { BasicForm, useForm } from '/@/components/Form'; | |
| 16 | + import { formSchema } from './device.profile.data'; | |
| 17 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | |
| 18 | + import {saveOrEditMessageConfig} from "/@/api/message/config"; | |
| 19 | + import {useMessage} from "/@/hooks/web/useMessage"; | |
| 20 | + | |
| 21 | + export default defineComponent({ | |
| 22 | + name: 'DeviceProfileDrawer', | |
| 23 | + components: { BasicDrawer, BasicForm }, | |
| 24 | + emits: ['success', 'register'], | |
| 25 | + setup(_, { emit }) { | |
| 26 | + const isUpdate = ref(true); | |
| 27 | + | |
| 28 | + const [registerForm, { validate,setFieldsValue,resetFields }] = useForm({ | |
| 29 | + labelWidth: 120, | |
| 30 | + schemas: formSchema, | |
| 31 | + showActionButtonGroup: false, | |
| 32 | + }); | |
| 33 | + | |
| 34 | + const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { | |
| 35 | + await resetFields(); | |
| 36 | + setDrawerProps({ confirmLoading: false }); | |
| 37 | + isUpdate.value = !!data?.isUpdate; | |
| 38 | + if (unref(isUpdate)) { | |
| 39 | + const config = data.record.config; | |
| 40 | + for (const key in config){ | |
| 41 | + Reflect.set(data.record, key+'', config[key]); | |
| 42 | + } | |
| 43 | + await setFieldsValue({ | |
| 44 | + ...data.record, | |
| 45 | + }); | |
| 46 | + } | |
| 47 | + }); | |
| 48 | + | |
| 49 | + const getTitle = computed(() => (!unref(isUpdate) ? '新增消息配置' : '编辑消息配置')); | |
| 50 | + | |
| 51 | + async function handleSubmit() { | |
| 52 | + try { | |
| 53 | + const values = await validate(); | |
| 54 | + const { createMessage } = useMessage(); | |
| 55 | + setDrawerProps({ confirmLoading: true }); | |
| 56 | + let config={}; | |
| 57 | + if(values.messageType === 'PHONE_MESSAGE'){ | |
| 58 | + config ={ | |
| 59 | + "accessKeyId":values.accessKeyId, | |
| 60 | + "accessKeySecret":values.accessKeySecret, | |
| 61 | + } | |
| 62 | + }else if(values.messageType === 'EMAIL_MESSAGE'){ | |
| 63 | + config ={ | |
| 64 | + "host":values.host, | |
| 65 | + "port":values.port, | |
| 66 | + "username":values.username, | |
| 67 | + "password":values.password, | |
| 68 | + } | |
| 69 | + } | |
| 70 | + Reflect.set(values, 'config', config); | |
| 71 | + let saveMessage = "添加成功"; | |
| 72 | + let updateMessage = "修改成功"; | |
| 73 | + await saveOrEditMessageConfig(values, unref(isUpdate)); | |
| 74 | + closeDrawer(); | |
| 75 | + emit('success'); | |
| 76 | + createMessage.success(unref(isUpdate)?updateMessage:saveMessage); | |
| 77 | + } finally { | |
| 78 | + setDrawerProps({ confirmLoading: false }); | |
| 79 | + } | |
| 80 | + } | |
| 81 | + | |
| 82 | + return { | |
| 83 | + registerDrawer, | |
| 84 | + registerForm, | |
| 85 | + getTitle, | |
| 86 | + handleSubmit, | |
| 87 | + }; | |
| 88 | + }, | |
| 89 | + }); | |
| 90 | +</script> | ... | ... |
| 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 | +export const columns: BasicColumn[] = [ | |
| 6 | + { | |
| 7 | + title: '配置名称', | |
| 8 | + dataIndex: 'name', | |
| 9 | + width: 200, | |
| 10 | + }, | |
| 11 | + { | |
| 12 | + title: '传输协议', | |
| 13 | + dataIndex: 'transportType', | |
| 14 | + width: 200, | |
| 15 | + }, | |
| 16 | + { | |
| 17 | + title: '创建时间', | |
| 18 | + dataIndex: 'createTime', | |
| 19 | + width: 180, | |
| 20 | + }, | |
| 21 | + { | |
| 22 | + title: '描述', | |
| 23 | + dataIndex: 'description', | |
| 24 | + width: 180, | |
| 25 | + }, | |
| 26 | +]; | |
| 27 | + | |
| 28 | +export const searchFormSchema: FormSchema[] = [ | |
| 29 | + { | |
| 30 | + field: 'name', | |
| 31 | + label: '配置名称', | |
| 32 | + component: 'Input', | |
| 33 | + colProps: { span: 8 }, | |
| 34 | + }, | |
| 35 | +]; | |
| 36 | + | |
| 37 | + | |
| 38 | +export const isMessage = (type:string)=>{ | |
| 39 | + return type===MessageEnum.IS_SMS; | |
| 40 | +} | |
| 41 | +export const isEmail = (type:string)=>{ | |
| 42 | + return type===MessageEnum.IS_EMAIL; | |
| 43 | +} | |
| 44 | + | |
| 45 | +export const formSchema: FormSchema[] = [ | |
| 46 | + { | |
| 47 | + field: 'configName', | |
| 48 | + label: '配置名称', | |
| 49 | + required: true, | |
| 50 | + component:'Input' | |
| 51 | + }, | |
| 52 | + { | |
| 53 | + field: 'messageType', | |
| 54 | + label: '消息类型', | |
| 55 | + required: true, | |
| 56 | + component: 'ApiSelect', | |
| 57 | + componentProps: { | |
| 58 | + api:findDictItemByCode, | |
| 59 | + params:{ | |
| 60 | + dictCode:"message_type" | |
| 61 | + }, | |
| 62 | + labelField:'itemText', | |
| 63 | + valueField:'itemValue', | |
| 64 | + }, | |
| 65 | + }, | |
| 66 | + { | |
| 67 | + field: 'platformType', | |
| 68 | + label: '平台类型', | |
| 69 | + required: true, | |
| 70 | + component: 'ApiSelect', | |
| 71 | + componentProps: { | |
| 72 | + api:findDictItemByCode, | |
| 73 | + params:{ | |
| 74 | + dictCode:"platform_type" | |
| 75 | + }, | |
| 76 | + labelField:'itemText', | |
| 77 | + valueField:'itemValue', | |
| 78 | + }, | |
| 79 | + ifShow:({values}) => isMessage(Reflect.get(values,'messageType')), | |
| 80 | + }, | |
| 81 | + { | |
| 82 | + field: 'accessKeyId', | |
| 83 | + label: 'accessKeyId', | |
| 84 | + required: true, | |
| 85 | + component:'Input', | |
| 86 | + ifShow:({values}) => isMessage(Reflect.get(values,'messageType')), | |
| 87 | + }, | |
| 88 | + { | |
| 89 | + field: 'accessKeySecret', | |
| 90 | + label: 'accessKeySecret', | |
| 91 | + required: true, | |
| 92 | + component:'Input', | |
| 93 | + ifShow:({values}) => isMessage(Reflect.get(values,'messageType')), | |
| 94 | + }, | |
| 95 | + { | |
| 96 | + field: 'host', | |
| 97 | + label: '服务器地址', | |
| 98 | + defaultValue:'smtp.163.com', | |
| 99 | + required: true, | |
| 100 | + component:'Input', | |
| 101 | + ifShow:({values}) => isEmail(Reflect.get(values,'messageType')), | |
| 102 | + }, | |
| 103 | + { | |
| 104 | + field: 'port', | |
| 105 | + label: '端口', | |
| 106 | + defaultValue: 25, | |
| 107 | + required: true, | |
| 108 | + component:'InputNumber', | |
| 109 | + ifShow:({values}) => isEmail(Reflect.get(values,'messageType')), | |
| 110 | + }, | |
| 111 | + { | |
| 112 | + field: 'username', | |
| 113 | + label: '用户名', | |
| 114 | + required: true, | |
| 115 | + component:'Input', | |
| 116 | + ifShow:({values}) => isEmail(Reflect.get(values,'messageType')), | |
| 117 | + }, | |
| 118 | + { | |
| 119 | + field: 'password', | |
| 120 | + label: '密码', | |
| 121 | + required: true, | |
| 122 | + component:'InputPassword', | |
| 123 | + ifShow:({values}) => isEmail(Reflect.get(values,'messageType')), | |
| 124 | + }, | |
| 125 | + { | |
| 126 | + field: 'config', | |
| 127 | + label: '消息配置', | |
| 128 | + component:'Input', | |
| 129 | + show:false, | |
| 130 | + }, | |
| 131 | + { | |
| 132 | + field: 'id', | |
| 133 | + label: '主键', | |
| 134 | + component:'Input', | |
| 135 | + show:false, | |
| 136 | + }, | |
| 137 | + { | |
| 138 | + field: 'status', | |
| 139 | + label: '状态', | |
| 140 | + component: 'RadioButtonGroup', | |
| 141 | + defaultValue: 0, | |
| 142 | + componentProps: { | |
| 143 | + options: [ | |
| 144 | + { label: '启用', value: 1 }, | |
| 145 | + { label: '停用', value: 0 }, | |
| 146 | + ], | |
| 147 | + }, | |
| 148 | + }, | |
| 149 | + { | |
| 150 | + label: '备注', | |
| 151 | + field: 'remark', | |
| 152 | + component: 'InputTextArea', | |
| 153 | + } | |
| 154 | +]; | ... | ... |
src/views/device/profile/index.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div> | |
| 3 | + <BasicTable @register="registerTable"> | |
| 4 | + <template #toolbar> | |
| 5 | + <a-button type="primary" @click="handleCreate"> 新增设备配置 </a-button> | |
| 6 | + </template> | |
| 7 | + <template #action="{ record }"> | |
| 8 | + <TableAction | |
| 9 | + :actions="[ | |
| 10 | + { | |
| 11 | + label:'编辑', | |
| 12 | + icon: 'clarity:note-edit-line', | |
| 13 | + onClick: handleEdit.bind(null, record), | |
| 14 | + }, | |
| 15 | + { | |
| 16 | + label:'删除', | |
| 17 | + icon: 'ant-design:delete-outlined', | |
| 18 | + color: 'error', | |
| 19 | + popConfirm: { | |
| 20 | + title: '是否确认删除', | |
| 21 | + confirm: handleDelete.bind(null, record), | |
| 22 | + } | |
| 23 | + }, | |
| 24 | + ]" | |
| 25 | + /> | |
| 26 | + </template> | |
| 27 | + </BasicTable> | |
| 28 | + <DeviceProfileDrawer @register="registerDrawer" @success="handleSuccess" /> | |
| 29 | + </div> | |
| 30 | +</template> | |
| 31 | +<script lang="ts"> | |
| 32 | +import { defineComponent} from 'vue'; | |
| 33 | +import { BasicTable, useTable, TableAction } from '/@/components/Table'; | |
| 34 | +import { useDrawer } from '/@/components/Drawer'; | |
| 35 | +import DeviceProfileDrawer from './DeviceProfile.vue'; | |
| 36 | +import { columns, searchFormSchema } from './device.profile.data'; | |
| 37 | +import {useMessage} from "/@/hooks/web/useMessage"; | |
| 38 | +import {deviceProfilePage,deleteDeviceProfile} from "/@/api/device/deviceManager"; | |
| 39 | +export default defineComponent({ | |
| 40 | + name: 'DeviceProfileManagement', | |
| 41 | + components: { BasicTable, DeviceProfileDrawer, TableAction}, | |
| 42 | + setup() { | |
| 43 | + const [registerDrawer, { openDrawer }] = useDrawer(); | |
| 44 | + const {createMessage} = useMessage(); | |
| 45 | + const [registerTable, { reload }] = useTable({ | |
| 46 | + title: '设备配置列表', | |
| 47 | + api: deviceProfilePage, | |
| 48 | + columns, | |
| 49 | + formConfig: { | |
| 50 | + labelWidth: 120, | |
| 51 | + schemas: searchFormSchema, | |
| 52 | + }, | |
| 53 | + useSearchForm: true, | |
| 54 | + showTableSetting: true, | |
| 55 | + bordered: true, | |
| 56 | + showIndexColumn: false, | |
| 57 | + actionColumn: { | |
| 58 | + width: 180, | |
| 59 | + title: '操作', | |
| 60 | + dataIndex: 'action', | |
| 61 | + slots: { customRender: 'action' }, | |
| 62 | + }, | |
| 63 | + }); | |
| 64 | + | |
| 65 | + function handleCreate() { | |
| 66 | + openDrawer(true, { | |
| 67 | + isUpdate: false, | |
| 68 | + }); | |
| 69 | + } | |
| 70 | + | |
| 71 | + function handleEdit(record: Recordable) { | |
| 72 | + openDrawer(true, { | |
| 73 | + record, | |
| 74 | + isUpdate: true, | |
| 75 | + }); | |
| 76 | + } | |
| 77 | + | |
| 78 | + function handleDelete(record: Recordable) { | |
| 79 | + let ids = [record.id]; | |
| 80 | + deleteDeviceProfile(ids).then(()=>{ | |
| 81 | + createMessage.success("删除设备配置成功") | |
| 82 | + handleSuccess() | |
| 83 | + }); | |
| 84 | + } | |
| 85 | + | |
| 86 | + function handleSuccess() { | |
| 87 | + reload(); | |
| 88 | + } | |
| 89 | + return { | |
| 90 | + registerTable, | |
| 91 | + registerDrawer, | |
| 92 | + handleCreate, | |
| 93 | + handleEdit, | |
| 94 | + handleDelete, | |
| 95 | + handleSuccess, | |
| 96 | + }; | |
| 97 | + }, | |
| 98 | +}); | |
| 99 | +</script> | ... | ... |