Commit 9904d26ff0909c3278cda9865fc0e7c504fad4e1
Merge branch 'sqy_dev' into 'main'
'feat:设备详情页面' See merge request huang/yun-teng-iot-front!24
Showing
16 changed files
with
464 additions
and
218 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.117:8082/api"],["/upload","http://192.168.10.116:3300/upload"]] | 9 | +VITE_PROXY = [["/api","http://192.168.10.123: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,7 @@ | @@ -15,6 +15,7 @@ | ||
| 15 | :title="getMergeProps.title" | 15 | :title="getMergeProps.title" |
| 16 | @dblclick="handleTitleDbClick" | 16 | @dblclick="handleTitleDbClick" |
| 17 | /> | 17 | /> |
| 18 | + <slot name="titleSlot" v-if="!getMergeProps.title"></slot> | ||
| 18 | </template> | 19 | </template> |
| 19 | 20 | ||
| 20 | <template #footer v-if="!$slots.footer"> | 21 | <template #footer v-if="!$slots.footer"> |
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 | - }, | ||
| 11 | - { | ||
| 12 | - title: '设备名称', | ||
| 13 | - dataIndex: 'name', | ||
| 14 | - width: 200, | ||
| 15 | - }, | ||
| 16 | - { | ||
| 17 | - title: '设备类型', | ||
| 18 | - dataIndex: 'deviceType', | ||
| 19 | - width: 200, | ||
| 20 | - slots: { customRender: 'deviceType' }, | ||
| 21 | - }, | ||
| 22 | - { | ||
| 23 | - title: '设备配置', | ||
| 24 | - dataIndex: 'deviceProfile.name', | ||
| 25 | - width: 180, | ||
| 26 | - slots: { customRender: 'deviceProfile' }, | ||
| 27 | - }, | ||
| 28 | - { | ||
| 29 | - title: '标签', | ||
| 30 | - dataIndex: 'label', | ||
| 31 | - width: 180, | ||
| 32 | - }, | ||
| 33 | - { | ||
| 34 | - title: '配置信息', | ||
| 35 | - dataIndex: 'deviceInfo', | ||
| 36 | - width: 180, | ||
| 37 | - slots: { customRender: 'config' }, | ||
| 38 | - }, | ||
| 39 | - { | ||
| 40 | - title: '状态', | ||
| 41 | - dataIndex: 'deviceState', | ||
| 42 | - width: 120, | ||
| 43 | - slots: { customRender: 'deviceState' }, | ||
| 44 | - }, | ||
| 45 | - { | ||
| 46 | - title: '最后连接时间', | ||
| 47 | - dataIndex: 'lastConnectTime', | ||
| 48 | - width: 180, | ||
| 49 | - }, | ||
| 50 | - { | ||
| 51 | - title: '创建时间', | ||
| 52 | - dataIndex: 'createTime', | ||
| 53 | - width: 180, | ||
| 54 | - }, | ||
| 55 | -]; | ||
| 56 | - | ||
| 57 | -// 查询字段 | ||
| 58 | -export const searchFormSchema: FormSchema[] = [ | ||
| 59 | - { | ||
| 60 | - field: 'deviceType', | ||
| 61 | - label: '设备类型', | ||
| 62 | - component: 'Select', | ||
| 63 | - componentProps: { | ||
| 64 | - options: [ | ||
| 65 | - { label: '网关设备', value: DeviceTypeEnum.GATEWAY }, | ||
| 66 | - { label: '直连设备', value: DeviceTypeEnum.DIRECT_CONNECTION }, | ||
| 67 | - { label: '网关子设备', value: DeviceTypeEnum.SENSOR }, | ||
| 68 | - ], | ||
| 69 | - }, | ||
| 70 | - colProps: { span: 4 }, | ||
| 71 | - }, | ||
| 72 | - { | ||
| 73 | - field: 'deviceState', | ||
| 74 | - label: '设备状态', | ||
| 75 | - component: 'Select', | ||
| 76 | - componentProps: { | ||
| 77 | - options: [ | ||
| 78 | - { label: '待激活', value: DeviceState.INACTIVE }, | ||
| 79 | - { label: '在线', value: DeviceState.ONLINE }, | ||
| 80 | - { label: '离线', value: DeviceState.OFFLINE }, | ||
| 81 | - ], | ||
| 82 | - }, | ||
| 83 | - colProps: { span: 4 }, | ||
| 84 | - }, | ||
| 85 | - { | ||
| 86 | - field: 'name', | ||
| 87 | - label: '设备名称', | ||
| 88 | - component: 'Input', | ||
| 89 | - colProps: { span: 8 }, | ||
| 90 | - }, | ||
| 91 | -]; | ||
| 92 | - | ||
| 93 | -// 弹框配置项 | ||
| 94 | -export const formSchema: FormSchema[] = [ | ||
| 95 | - { | ||
| 96 | - field: 'configName', | ||
| 97 | - label: '配置名称', | ||
| 98 | - required: true, | ||
| 99 | - component: 'Input', | ||
| 100 | - }, | ||
| 101 | - { | ||
| 102 | - field: 'messageType', | ||
| 103 | - label: '消息类型', | ||
| 104 | - required: true, | ||
| 105 | - component: 'ApiSelect', | ||
| 106 | - componentProps: { | ||
| 107 | - api: findDictItemByCode, | ||
| 108 | - params: { | ||
| 109 | - dictCode: 'message_type', | ||
| 110 | - }, | ||
| 111 | - labelField: 'itemText', | ||
| 112 | - valueField: 'itemValue', | ||
| 113 | - }, | ||
| 114 | - }, | ||
| 115 | - { | ||
| 116 | - field: 'platformType', | ||
| 117 | - label: '平台类型', | ||
| 118 | - required: true, | ||
| 119 | - component: 'ApiSelect', | ||
| 120 | - componentProps: { | ||
| 121 | - api: findDictItemByCode, | ||
| 122 | - params: { | ||
| 123 | - dictCode: 'platform_type', | ||
| 124 | - }, | ||
| 125 | - labelField: 'itemText', | ||
| 126 | - valueField: 'itemValue', | ||
| 127 | - }, | ||
| 128 | - ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')), | ||
| 129 | - }, | ||
| 130 | - { | ||
| 131 | - field: 'accessKeyId', | ||
| 132 | - label: 'accessKeyId', | ||
| 133 | - required: true, | ||
| 134 | - component: 'Input', | ||
| 135 | - ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')), | ||
| 136 | - }, | ||
| 137 | - { | ||
| 138 | - field: 'accessKeySecret', | ||
| 139 | - label: 'accessKeySecret', | ||
| 140 | - required: true, | ||
| 141 | - component: 'Input', | ||
| 142 | - ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')), | ||
| 143 | - }, | ||
| 144 | - { | ||
| 145 | - field: 'host', | ||
| 146 | - label: '服务器地址', | ||
| 147 | - defaultValue: 'smtp.163.com', | ||
| 148 | - required: true, | ||
| 149 | - component: 'Input', | ||
| 150 | - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), | ||
| 151 | - }, | ||
| 152 | - { | ||
| 153 | - field: 'port', | ||
| 154 | - label: '端口', | ||
| 155 | - defaultValue: 25, | ||
| 156 | - required: true, | ||
| 157 | - component: 'InputNumber', | ||
| 158 | - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), | ||
| 159 | - }, | ||
| 160 | - { | ||
| 161 | - field: 'username', | ||
| 162 | - label: '用户名', | ||
| 163 | - required: true, | ||
| 164 | - component: 'Input', | ||
| 165 | - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), | ||
| 166 | - }, | ||
| 167 | - { | ||
| 168 | - field: 'password', | ||
| 169 | - label: '密码', | ||
| 170 | - required: true, | ||
| 171 | - component: 'InputPassword', | ||
| 172 | - ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), | ||
| 173 | - }, | ||
| 174 | - { | ||
| 175 | - field: 'config', | ||
| 176 | - label: '消息配置', | ||
| 177 | - component: 'Input', | ||
| 178 | - show: false, | ||
| 179 | - }, | ||
| 180 | - { | ||
| 181 | - field: 'id', | ||
| 182 | - label: '主键', | ||
| 183 | - component: 'Input', | ||
| 184 | - show: false, | ||
| 185 | - }, | ||
| 186 | - { | ||
| 187 | - field: 'status', | ||
| 188 | - label: '状态', | ||
| 189 | - component: 'RadioButtonGroup', | ||
| 190 | - defaultValue: 0, | ||
| 191 | - componentProps: { | ||
| 192 | - options: [ | ||
| 193 | - { label: '启用', value: 1 }, | ||
| 194 | - { label: '停用', value: 0 }, | ||
| 195 | - ], | ||
| 196 | - }, | ||
| 197 | - }, | ||
| 198 | - { | ||
| 199 | - label: '备注', | ||
| 200 | - field: 'remark', | ||
| 201 | - component: 'InputTextArea', | ||
| 202 | - }, | ||
| 203 | -]; | ||
| 204 | - | ||
| 205 | -export const isMessage = (type: string) => { | ||
| 206 | - return type === MessageEnum.IS_SMS; | ||
| 207 | -}; | ||
| 208 | -export const isEmail = (type: string) => { | ||
| 209 | - return type === MessageEnum.IS_EMAIL; | ||
| 210 | -}; |
src/views/device/manage/config/data.ts
renamed from
src/views/device/step/data.ts
| 1 | +import { FormSchema } from '/@/components/Form'; | ||
| 2 | +import { BasicColumn } from '/@/components/Table'; | ||
| 3 | +export const columns: BasicColumn[] = [ | ||
| 4 | + { | ||
| 5 | + title: '设备名称', | ||
| 6 | + dataIndex: 'name', | ||
| 7 | + width: 120, | ||
| 8 | + key: 'name', | ||
| 9 | + }, | ||
| 10 | + { | ||
| 11 | + title: '设备标签', | ||
| 12 | + dataIndex: 'label', | ||
| 13 | + width: 100, | ||
| 14 | + key: 'label', | ||
| 15 | + }, | ||
| 16 | + { | ||
| 17 | + title: '设备配置', | ||
| 18 | + dataIndex: 'deviceProfile.name', | ||
| 19 | + width: 160, | ||
| 20 | + key: 'deviceProfile.name', | ||
| 21 | + }, | ||
| 22 | + | ||
| 23 | + { | ||
| 24 | + title: '设备类型', | ||
| 25 | + dataIndex: 'deviceType', | ||
| 26 | + key: 'deviceType', | ||
| 27 | + }, | ||
| 28 | + { | ||
| 29 | + title: '描述', | ||
| 30 | + dataIndex: 'label', | ||
| 31 | + width: 180, | ||
| 32 | + key: 'label', | ||
| 33 | + }, | ||
| 34 | +]; | ||
| 35 | + | ||
| 36 | +// 实时数据 | ||
| 37 | +export const realTimeDataSearchSchemas: FormSchema[] = [ | ||
| 38 | + { | ||
| 39 | + field: 'key', | ||
| 40 | + label: '键 / 值', | ||
| 41 | + component: 'Input', | ||
| 42 | + colProps: { span: 12 }, | ||
| 43 | + }, | ||
| 44 | +]; | ||
| 45 | +export const realTimeDataColumns: BasicColumn[] = [ | ||
| 46 | + { | ||
| 47 | + title: '最后更新时间', | ||
| 48 | + dataIndex: 'update', | ||
| 49 | + width: 120, | ||
| 50 | + }, | ||
| 51 | + { | ||
| 52 | + title: '键', | ||
| 53 | + dataIndex: 'label', | ||
| 54 | + width: 100, | ||
| 55 | + }, | ||
| 56 | + { | ||
| 57 | + title: '值', | ||
| 58 | + dataIndex: 'name', | ||
| 59 | + width: 160, | ||
| 60 | + }, | ||
| 61 | +]; | ||
| 62 | + | ||
| 63 | +// 告警 | ||
| 64 | +export const alarmSearchSchemas: FormSchema[] = [ | ||
| 65 | + { | ||
| 66 | + field: 'icon', | ||
| 67 | + label: '告警状态', | ||
| 68 | + component: 'Select', | ||
| 69 | + colProps: { span: 8 }, | ||
| 70 | + }, | ||
| 71 | + { | ||
| 72 | + field: 'icon', | ||
| 73 | + label: ' ', | ||
| 74 | + component: 'DatePicker', | ||
| 75 | + colProps: { span: 8 }, | ||
| 76 | + }, | ||
| 77 | + { | ||
| 78 | + field: 'icon', | ||
| 79 | + label: '告警类型', | ||
| 80 | + component: 'Input', | ||
| 81 | + colProps: { span: 8 }, | ||
| 82 | + }, | ||
| 83 | +]; | ||
| 84 | +export const alarmColumns: BasicColumn[] = [ | ||
| 85 | + { | ||
| 86 | + title: '告警时间', | ||
| 87 | + dataIndex: 'aaa', | ||
| 88 | + width: 120, | ||
| 89 | + }, | ||
| 90 | + { | ||
| 91 | + title: '告警设备', | ||
| 92 | + dataIndex: 'label', | ||
| 93 | + width: 100, | ||
| 94 | + }, | ||
| 95 | + { | ||
| 96 | + title: '类型', | ||
| 97 | + dataIndex: 'ccc', | ||
| 98 | + width: 160, | ||
| 99 | + }, | ||
| 100 | + { | ||
| 101 | + title: '告警级别', | ||
| 102 | + dataIndex: 'ddd', | ||
| 103 | + width: 160, | ||
| 104 | + }, | ||
| 105 | + { | ||
| 106 | + title: '状态', | ||
| 107 | + dataIndex: 'eee', | ||
| 108 | + width: 160, | ||
| 109 | + }, | ||
| 110 | + { | ||
| 111 | + title: '操作', | ||
| 112 | + dataIndex: 'name', | ||
| 113 | + width: 160, | ||
| 114 | + }, | ||
| 115 | +]; | ||
| 116 | + | ||
| 117 | +// 子设备 | ||
| 118 | +export const childDeviceSchemas: FormSchema[] = [ | ||
| 119 | + { | ||
| 120 | + field: 'icon', | ||
| 121 | + label: '设备配置', | ||
| 122 | + component: 'Select', | ||
| 123 | + colProps: { span: 12 }, | ||
| 124 | + }, | ||
| 125 | + { | ||
| 126 | + field: 'icon', | ||
| 127 | + label: '设备名称', | ||
| 128 | + component: 'Input', | ||
| 129 | + colProps: { span: 12 }, | ||
| 130 | + }, | ||
| 131 | +]; | ||
| 132 | +export const childDeviceColumns: BasicColumn[] = [ | ||
| 133 | + { | ||
| 134 | + title: '名称', | ||
| 135 | + dataIndex: 'name', | ||
| 136 | + width: 120, | ||
| 137 | + }, | ||
| 138 | + { | ||
| 139 | + title: '设备配置', | ||
| 140 | + dataIndex: 'label', | ||
| 141 | + width: 100, | ||
| 142 | + }, | ||
| 143 | + { | ||
| 144 | + title: '标签', | ||
| 145 | + dataIndex: 'aaa', | ||
| 146 | + width: 160, | ||
| 147 | + }, | ||
| 148 | + { | ||
| 149 | + title: '状态', | ||
| 150 | + dataIndex: 'bbb', | ||
| 151 | + width: 160, | ||
| 152 | + }, | ||
| 153 | + { | ||
| 154 | + title: '最后连接时间', | ||
| 155 | + dataIndex: 'ccc', | ||
| 156 | + width: 160, | ||
| 157 | + }, | ||
| 158 | + { | ||
| 159 | + title: '创建时间', | ||
| 160 | + dataIndex: 'ddd', | ||
| 161 | + width: 160, | ||
| 162 | + }, | ||
| 163 | +]; |
src/views/device/manage/config/device.data.ts
renamed from
src/views/device/device.data.ts
| 1 | +<template> | ||
| 2 | + <!-- <BasicModal v-bind="$attrs" width="55rem" @register="register" centered /> --> | ||
| 3 | + <BasicDrawer | ||
| 4 | + v-bind="$attrs" | ||
| 5 | + isDetail | ||
| 6 | + :title="deviceInfo?.name" | ||
| 7 | + @register="register" | ||
| 8 | + :destroyOnClose="true" | ||
| 9 | + @close="closeDrawer" | ||
| 10 | + > | ||
| 11 | + <Tabs v-model:activeKey="activeKey" :size="size" type="card"> | ||
| 12 | + <TabPane key="1" tab="详情" | ||
| 13 | + ><Detail :deviceDetail="deviceInfo" ref="deviceDetailRef" | ||
| 14 | + /></TabPane> | ||
| 15 | + <TabPane key="2" tab="实时数据"><RealTimeData /></TabPane> | ||
| 16 | + <TabPane key="3" tab="告警"><Alarm /></TabPane> | ||
| 17 | + <TabPane key="4" tab="子设备"><ChildDevice /></TabPane> | ||
| 18 | + </Tabs> | ||
| 19 | + </BasicDrawer> | ||
| 20 | +</template> | ||
| 21 | +<script lang="ts"> | ||
| 22 | + import { defineComponent, ref } from 'vue'; | ||
| 23 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | ||
| 24 | + | ||
| 25 | + import { Tabs, TabPane } from 'ant-design-vue'; | ||
| 26 | + import Detail from '../tabs/Detail.vue'; | ||
| 27 | + import RealTimeData from '../tabs/RealTimeData.vue'; | ||
| 28 | + import Alarm from '../tabs/Alarm.vue'; | ||
| 29 | + import ChildDevice from '../tabs/ChildDevice.vue'; | ||
| 30 | + export default defineComponent({ | ||
| 31 | + name: 'DeviceModal', | ||
| 32 | + components: { | ||
| 33 | + BasicDrawer, | ||
| 34 | + Tabs, | ||
| 35 | + TabPane, | ||
| 36 | + Detail, | ||
| 37 | + RealTimeData, | ||
| 38 | + Alarm, | ||
| 39 | + ChildDevice, | ||
| 40 | + }, | ||
| 41 | + emits: ['reload', 'register'], | ||
| 42 | + setup() { | ||
| 43 | + const activeKey = ref('1'); | ||
| 44 | + const size = ref('small'); | ||
| 45 | + const deviceInfo = ref({}); | ||
| 46 | + const deviceDetailRef = ref(); | ||
| 47 | + // 详情回显 | ||
| 48 | + const [register] = useDrawerInner((data) => { | ||
| 49 | + deviceInfo.value = data.record; | ||
| 50 | + const { latitude, longitude, address } = data.record.deviceInfo; | ||
| 51 | + deviceDetailRef.value.initMap(longitude, latitude, address); | ||
| 52 | + }); | ||
| 53 | + | ||
| 54 | + const closeDrawer = () => { | ||
| 55 | + activeKey.value = '1'; | ||
| 56 | + }; | ||
| 57 | + | ||
| 58 | + return { | ||
| 59 | + size, | ||
| 60 | + activeKey, | ||
| 61 | + deviceInfo, | ||
| 62 | + register, | ||
| 63 | + closeDrawer, | ||
| 64 | + deviceDetailRef, | ||
| 65 | + }; | ||
| 66 | + }, | ||
| 67 | + }); | ||
| 68 | +</script> |
src/views/device/manage/cpns/modal/DeviceModal.vue
renamed from
src/views/device/DeviceModal.vue
| @@ -34,8 +34,8 @@ | @@ -34,8 +34,8 @@ | ||
| 34 | import { defineComponent, ref, computed, unref } from 'vue'; | 34 | import { defineComponent, ref, computed, unref } from 'vue'; |
| 35 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 35 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
| 36 | import { createOrEditDevice, getDeviceToken } from '/@/api/device/deviceManager'; | 36 | import { createOrEditDevice, getDeviceToken } from '/@/api/device/deviceManager'; |
| 37 | - import DeviceStep1 from '/@/views/device/step/DeviceStep1.vue'; | ||
| 38 | - import DeviceStep2 from '/@/views/device/step/DeviceStep2.vue'; | 37 | + import DeviceStep1 from '../step/DeviceStep1.vue'; |
| 38 | + import DeviceStep2 from '../step/DeviceStep2.vue'; | ||
| 39 | import { Steps } from 'ant-design-vue'; | 39 | import { Steps } from 'ant-design-vue'; |
| 40 | import { useMessage } from '/@/hooks/web/useMessage'; | 40 | import { useMessage } from '/@/hooks/web/useMessage'; |
| 41 | 41 |
src/views/device/manage/cpns/step/DeviceStep1.vue
renamed from
src/views/device/step/DeviceStep1.vue
| @@ -59,7 +59,7 @@ | @@ -59,7 +59,7 @@ | ||
| 59 | <script lang="ts"> | 59 | <script lang="ts"> |
| 60 | import { defineComponent, ref, nextTick, unref, reactive, watch } from 'vue'; | 60 | import { defineComponent, ref, nextTick, unref, reactive, watch } from 'vue'; |
| 61 | import { BasicForm, useForm } from '/@/components/Form'; | 61 | import { BasicForm, useForm } from '/@/components/Form'; |
| 62 | - import { step1Schemas } from './data'; | 62 | + import { step1Schemas } from '../../config/data'; |
| 63 | import { useScript } from '/@/hooks/web/useScript'; | 63 | import { useScript } from '/@/hooks/web/useScript'; |
| 64 | import { Input, Divider, Upload, message, Modal, Form, Row, Col } from 'ant-design-vue'; | 64 | import { Input, Divider, Upload, message, Modal, Form, Row, Col } from 'ant-design-vue'; |
| 65 | import { EnvironmentTwoTone, PlusOutlined } from '@ant-design/icons-vue'; | 65 | import { EnvironmentTwoTone, PlusOutlined } from '@ant-design/icons-vue'; |
src/views/device/manage/cpns/step/DeviceStep2.vue
renamed from
src/views/device/step/DeviceStep2.vue
src/views/device/manage/cpns/tabs/Alarm.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <BasicTable @register="registerTable" /> | ||
| 3 | +</template> | ||
| 4 | +<script lang="ts"> | ||
| 5 | + import { defineComponent } from 'vue'; | ||
| 6 | + import { BasicTable, useTable } from '/@/components/Table'; | ||
| 7 | + import { alarmColumns, alarmSearchSchemas } from '../../config/detail.config'; | ||
| 8 | + export default defineComponent({ | ||
| 9 | + name: 'DeviceManagement', | ||
| 10 | + components: { | ||
| 11 | + BasicTable, | ||
| 12 | + }, | ||
| 13 | + setup(_) { | ||
| 14 | + const [registerTable] = useTable({ | ||
| 15 | + columns: alarmColumns, | ||
| 16 | + formConfig: { | ||
| 17 | + labelWidth: 120, | ||
| 18 | + schemas: alarmSearchSchemas, | ||
| 19 | + }, | ||
| 20 | + useSearchForm: true, | ||
| 21 | + showTableSetting: true, | ||
| 22 | + bordered: true, | ||
| 23 | + showIndexColumn: false, | ||
| 24 | + }); | ||
| 25 | + | ||
| 26 | + return { | ||
| 27 | + registerTable, | ||
| 28 | + }; | ||
| 29 | + }, | ||
| 30 | + }); | ||
| 31 | +</script> |
| 1 | +<template> | ||
| 2 | + <BasicTable @register="registerTable" /> | ||
| 3 | +</template> | ||
| 4 | +<script lang="ts"> | ||
| 5 | + import { defineComponent } from 'vue'; | ||
| 6 | + import { BasicTable, useTable } from '/@/components/Table'; | ||
| 7 | + import { childDeviceColumns, childDeviceSchemas } from '../../config/detail.config'; | ||
| 8 | + | ||
| 9 | + export default defineComponent({ | ||
| 10 | + name: 'DeviceManagement', | ||
| 11 | + components: { | ||
| 12 | + BasicTable, | ||
| 13 | + }, | ||
| 14 | + setup(_) { | ||
| 15 | + const [registerTable] = useTable({ | ||
| 16 | + columns: childDeviceColumns, | ||
| 17 | + formConfig: { | ||
| 18 | + labelWidth: 120, | ||
| 19 | + schemas: childDeviceSchemas, | ||
| 20 | + }, | ||
| 21 | + useSearchForm: true, | ||
| 22 | + showTableSetting: true, | ||
| 23 | + bordered: true, | ||
| 24 | + showIndexColumn: false, | ||
| 25 | + }); | ||
| 26 | + | ||
| 27 | + return { | ||
| 28 | + registerTable, | ||
| 29 | + }; | ||
| 30 | + }, | ||
| 31 | + }); | ||
| 32 | +</script> |
src/views/device/manage/cpns/tabs/Detail.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="tabs-detail"> | ||
| 3 | + <div v-if="deviceDetail?.deviceInfo?.avatar"> | ||
| 4 | + <p>设备图片</p> | ||
| 5 | + <Image :src="deviceDetail.deviceInfo.avatar" :width="100" /> | ||
| 6 | + </div> | ||
| 7 | + <div> | ||
| 8 | + <p>设备信息</p> | ||
| 9 | + <Table | ||
| 10 | + bordered | ||
| 11 | + :columns="columns" | ||
| 12 | + :data-source="[{ ...deviceDetail, key: 'name' }]" | ||
| 13 | + :pagination="false" | ||
| 14 | + /> | ||
| 15 | + </div> | ||
| 16 | + <div v-if="deviceDetail?.deviceInfo?.address"> | ||
| 17 | + <p>设备位置</p> | ||
| 18 | + <div ref="wrapRef" style="height: 400px; width: 90%" class="ml-6"></div> | ||
| 19 | + </div> | ||
| 20 | + <div class="mt-4"> | ||
| 21 | + <a-button type="primary" class="mr-4">复制设备ID</a-button> | ||
| 22 | + <a-button type="primary">复制访问令牌</a-button> | ||
| 23 | + </div> | ||
| 24 | + </div> | ||
| 25 | +</template> | ||
| 26 | +<script lang="ts"> | ||
| 27 | + import { defineComponent, ref, unref, nextTick } from 'vue'; | ||
| 28 | + import { Image, Table } from 'ant-design-vue'; | ||
| 29 | + import { columns } from '../../config/detail.config'; | ||
| 30 | + import { useScript } from '/@/hooks/web/useScript'; | ||
| 31 | + export default defineComponent({ | ||
| 32 | + components: { | ||
| 33 | + Image, | ||
| 34 | + Table, | ||
| 35 | + }, | ||
| 36 | + props: { | ||
| 37 | + deviceDetail: { | ||
| 38 | + type: Object, | ||
| 39 | + required: true, | ||
| 40 | + }, | ||
| 41 | + }, | ||
| 42 | + setup() { | ||
| 43 | + const BAI_DU_MAP_URL = | ||
| 44 | + 'https://api.map.baidu.com/getscript?v=3.0&ak=7uOPPyAHn2Y2ZryeQqHtcRqtIY374vKa'; | ||
| 45 | + const wrapRef = ref<HTMLDivElement | null>(null); | ||
| 46 | + const { toPromise } = useScript({ src: BAI_DU_MAP_URL }); | ||
| 47 | + | ||
| 48 | + async function initMap(longitude, latitude, address) { | ||
| 49 | + await toPromise(); | ||
| 50 | + await nextTick(); | ||
| 51 | + const wrapEl = unref(wrapRef); | ||
| 52 | + const BMap = (window as any).BMap; | ||
| 53 | + if (!wrapEl) return; | ||
| 54 | + const map = new BMap.Map(wrapEl); | ||
| 55 | + let myIcon = new BMap.Icon( | ||
| 56 | + 'http://api.map.baidu.com/img/markers.png', | ||
| 57 | + new BMap.Size(40, 25), | ||
| 58 | + { | ||
| 59 | + offset: new BMap.Size(0, 0), // 指定定位位置 | ||
| 60 | + imageOffset: new BMap.Size(20, -260), // 设置图片偏移 | ||
| 61 | + } | ||
| 62 | + ); | ||
| 63 | + const point = new BMap.Point(Number(longitude), Number(latitude)); | ||
| 64 | + var content = `我在 ${address}`; | ||
| 65 | + var label = new BMap.Label(content, { | ||
| 66 | + // 创建文本标注 | ||
| 67 | + position: point, | ||
| 68 | + offset: new BMap.Size(15, -35), | ||
| 69 | + }); | ||
| 70 | + map.addOverlay(label); // 将标注添加到地图中 | ||
| 71 | + label.setStyle({ | ||
| 72 | + // 设置label的样式 | ||
| 73 | + color: '#000', | ||
| 74 | + fontSize: '10px', | ||
| 75 | + border: '1px solid #1E90FF', | ||
| 76 | + }); | ||
| 77 | + let marker = new BMap.Marker(point, { icon: myIcon }); | ||
| 78 | + map.centerAndZoom(point, 15); | ||
| 79 | + map.enableScrollWheelZoom(true); | ||
| 80 | + map.addOverlay(marker); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + return { | ||
| 84 | + columns, | ||
| 85 | + wrapRef, | ||
| 86 | + initMap, | ||
| 87 | + }; | ||
| 88 | + }, | ||
| 89 | + }); | ||
| 90 | +</script> | ||
| 91 | +<style lang="less" scoped></style> |
| 1 | +<template> | ||
| 2 | + <BasicTable @register="registerTable" /> | ||
| 3 | +</template> | ||
| 4 | +<script lang="ts"> | ||
| 5 | + import { defineComponent } from 'vue'; | ||
| 6 | + import { BasicTable, useTable } from '/@/components/Table'; | ||
| 7 | + import { realTimeDataColumns, realTimeDataSearchSchemas } from '../../config/detail.config'; | ||
| 8 | + export default defineComponent({ | ||
| 9 | + name: 'DeviceManagement', | ||
| 10 | + components: { | ||
| 11 | + BasicTable, | ||
| 12 | + }, | ||
| 13 | + setup(_) { | ||
| 14 | + const [registerTable] = useTable({ | ||
| 15 | + columns: realTimeDataColumns, | ||
| 16 | + formConfig: { | ||
| 17 | + labelWidth: 120, | ||
| 18 | + schemas: realTimeDataSearchSchemas, | ||
| 19 | + }, | ||
| 20 | + useSearchForm: true, | ||
| 21 | + showTableSetting: true, | ||
| 22 | + bordered: true, | ||
| 23 | + showIndexColumn: false, | ||
| 24 | + }); | ||
| 25 | + | ||
| 26 | + return { | ||
| 27 | + registerTable, | ||
| 28 | + }; | ||
| 29 | + }, | ||
| 30 | + }); | ||
| 31 | +</script> |
src/views/device/manage/index.vue
renamed from
src/views/device/index.vue
| @@ -48,6 +48,11 @@ | @@ -48,6 +48,11 @@ | ||
| 48 | <TableAction | 48 | <TableAction |
| 49 | :actions="[ | 49 | :actions="[ |
| 50 | { | 50 | { |
| 51 | + label: '详情', | ||
| 52 | + icon: 'ant-design:eye-outlined', | ||
| 53 | + onClick: handleDetail.bind(null, record), | ||
| 54 | + }, | ||
| 55 | + { | ||
| 51 | label: '编辑', | 56 | label: '编辑', |
| 52 | icon: 'clarity:note-edit-line', | 57 | icon: 'clarity:note-edit-line', |
| 53 | onClick: handleEdit.bind(null, record), | 58 | onClick: handleEdit.bind(null, record), |
| @@ -65,6 +70,7 @@ | @@ -65,6 +70,7 @@ | ||
| 65 | /> | 70 | /> |
| 66 | </template> | 71 | </template> |
| 67 | </BasicTable> | 72 | </BasicTable> |
| 73 | + <DeviceDetailDrawer @register="registerDetailDrawer" /> | ||
| 68 | <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleReload" /> | 74 | <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleReload" /> |
| 69 | </PageWrapper> | 75 | </PageWrapper> |
| 70 | </template> | 76 | </template> |
| @@ -72,16 +78,18 @@ | @@ -72,16 +78,18 @@ | ||
| 72 | import { defineComponent, reactive } from 'vue'; | 78 | import { defineComponent, reactive } from 'vue'; |
| 73 | import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | 79 | import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
| 74 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 80 | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
| 75 | - import { columns, searchFormSchema } from './device.data'; | 81 | + import { columns, searchFormSchema } from './config/device.data'; |
| 76 | import { Tag } from 'ant-design-vue'; | 82 | import { Tag } from 'ant-design-vue'; |
| 77 | import { useMessage } from '/@/hooks/web/useMessage'; | 83 | import { useMessage } from '/@/hooks/web/useMessage'; |
| 78 | import { deleteDevice, devicePage } from '/@/api/device/deviceManager'; | 84 | import { deleteDevice, devicePage } from '/@/api/device/deviceManager'; |
| 79 | import { PageEnum } from '/@/enums/pageEnum'; | 85 | import { PageEnum } from '/@/enums/pageEnum'; |
| 80 | import { useGo } from '/@/hooks/web/usePage'; | 86 | import { useGo } from '/@/hooks/web/usePage'; |
| 81 | import { PageWrapper } from '/@/components/Page'; | 87 | import { PageWrapper } from '/@/components/Page'; |
| 82 | - import OrganizationIdTree from '/@/views/common/OrganizationIdTree.vue'; | ||
| 83 | import { useModal } from '/@/components/Modal'; | 88 | import { useModal } from '/@/components/Modal'; |
| 84 | - import DeviceModal from '/@/views/device/DeviceModal.vue'; | 89 | + import OrganizationIdTree from '/@/views/common/OrganizationIdTree.vue'; |
| 90 | + import DeviceModal from './cpns/modal/DeviceModal.vue'; | ||
| 91 | + import { useDrawer } from '/@/components/Drawer'; | ||
| 92 | + import DeviceDetailDrawer from './cpns/modal/DeviceDetailDrawer.vue'; | ||
| 85 | 93 | ||
| 86 | export default defineComponent({ | 94 | export default defineComponent({ |
| 87 | name: 'DeviceManagement', | 95 | name: 'DeviceManagement', |
| @@ -92,6 +100,7 @@ | @@ -92,6 +100,7 @@ | ||
| 92 | OrganizationIdTree, | 100 | OrganizationIdTree, |
| 93 | Tag, | 101 | Tag, |
| 94 | DeviceModal, | 102 | DeviceModal, |
| 103 | + DeviceDetailDrawer, | ||
| 95 | }, | 104 | }, |
| 96 | setup(_) { | 105 | setup(_) { |
| 97 | const { createMessage } = useMessage(); | 106 | const { createMessage } = useMessage(); |
| @@ -99,6 +108,7 @@ | @@ -99,6 +108,7 @@ | ||
| 99 | 108 | ||
| 100 | const searchInfo = reactive<Recordable>({}); | 109 | const searchInfo = reactive<Recordable>({}); |
| 101 | const [registerModal, { openModal }] = useModal(); | 110 | const [registerModal, { openModal }] = useModal(); |
| 111 | + const [registerDetailDrawer, { openDrawer }] = useDrawer(); | ||
| 102 | const [registerTable, { reload }] = useTable({ | 112 | const [registerTable, { reload }] = useTable({ |
| 103 | title: '设备列表', | 113 | title: '设备列表', |
| 104 | api: devicePage, | 114 | api: devicePage, |
| @@ -113,7 +123,7 @@ | @@ -113,7 +123,7 @@ | ||
| 113 | showIndexColumn: false, | 123 | showIndexColumn: false, |
| 114 | searchInfo: searchInfo, | 124 | searchInfo: searchInfo, |
| 115 | actionColumn: { | 125 | actionColumn: { |
| 116 | - width: 180, | 126 | + width: 200, |
| 117 | title: '操作', | 127 | title: '操作', |
| 118 | dataIndex: 'action', | 128 | dataIndex: 'action', |
| 119 | slots: { customRender: 'action' }, | 129 | slots: { customRender: 'action' }, |
| @@ -130,6 +140,12 @@ | @@ -130,6 +140,12 @@ | ||
| 130 | }); | 140 | }); |
| 131 | } | 141 | } |
| 132 | 142 | ||
| 143 | + function handleDetail(record: Recordable) { | ||
| 144 | + openDrawer(true, { | ||
| 145 | + record, | ||
| 146 | + }); | ||
| 147 | + } | ||
| 148 | + | ||
| 133 | function handleEdit(record: Recordable) { | 149 | function handleEdit(record: Recordable) { |
| 134 | openModal(true, { | 150 | openModal(true, { |
| 135 | isUpdate: true, | 151 | isUpdate: true, |
| @@ -155,9 +171,11 @@ | @@ -155,9 +171,11 @@ | ||
| 155 | function goDeviceProfile() { | 171 | function goDeviceProfile() { |
| 156 | go(PageEnum.DEVICE_PROFILE); | 172 | go(PageEnum.DEVICE_PROFILE); |
| 157 | } | 173 | } |
| 174 | + | ||
| 158 | return { | 175 | return { |
| 159 | registerTable, | 176 | registerTable, |
| 160 | handleCreate, | 177 | handleCreate, |
| 178 | + handleDetail, | ||
| 161 | handleEdit, | 179 | handleEdit, |
| 162 | handleDelete, | 180 | handleDelete, |
| 163 | handleSuccess, | 181 | handleSuccess, |
| @@ -165,6 +183,7 @@ | @@ -165,6 +183,7 @@ | ||
| 165 | handleSelect, | 183 | handleSelect, |
| 166 | registerModal, | 184 | registerModal, |
| 167 | handleReload, | 185 | handleReload, |
| 186 | + registerDetailDrawer, | ||
| 168 | DeviceTypeEnum, | 187 | DeviceTypeEnum, |
| 169 | DeviceState, | 188 | DeviceState, |
| 170 | searchInfo, | 189 | searchInfo, |
src/views/device/manage/types/index.ts
0 → 100644
| 1 | +export interface DeviceType { | ||
| 2 | + alarmStatus: number; | ||
| 3 | + createTime: string; | ||
| 4 | + creator: string; | ||
| 5 | + deviceInfo: Object; | ||
| 6 | + deviceProfile: Object; | ||
| 7 | + deviceState: string; | ||
| 8 | + deviceToken: string; | ||
| 9 | + deviceType: string; | ||
| 10 | + enabled: boolean; | ||
| 11 | + id: string; | ||
| 12 | + key: string; | ||
| 13 | + label: string; | ||
| 14 | + name: string; | ||
| 15 | + organizationDTO: Object; | ||
| 16 | + organizationId: string; | ||
| 17 | + profileId: string; | ||
| 18 | + tenantCode: string; | ||
| 19 | + updateTime: string; | ||
| 20 | +} |