Commit 9904d26ff0909c3278cda9865fc0e7c504fad4e1

Authored by xp.Huang
2 parents f40541a3 ac2e57fd

Merge branch 'sqy_dev' into 'main'

'feat:设备详情页面'

See merge request huang/yun-teng-iot-front!24
... ... @@ -6,7 +6,7 @@ VITE_PUBLIC_PATH = /
6 6
7 7 # Cross-domain proxy, you can configure multiple
8 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 10 # VITE_PROXY=[["/api","https://vvbin.cn/test"]]
11 11
12 12 # Delete console
... ...
... ... @@ -15,6 +15,7 @@
15 15 :title="getMergeProps.title"
16 16 @dblclick="handleTitleDbClick"
17 17 />
  18 + <slot name="titleSlot" v-if="!getMergeProps.title"></slot>
18 19 </template>
19 20
20 21 <template #footer v-if="!$slots.footer">
... ...
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>
... ...
... ... @@ -34,8 +34,8 @@
34 34 import { defineComponent, ref, computed, unref } from 'vue';
35 35 import { BasicModal, useModalInner } from '/@/components/Modal';
36 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 39 import { Steps } from 'ant-design-vue';
40 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 59 <script lang="ts">
60 60 import { defineComponent, ref, nextTick, unref, reactive, watch } from 'vue';
61 61 import { BasicForm, useForm } from '/@/components/Form';
62   - import { step1Schemas } from './data';
  62 + import { step1Schemas } from '../../config/data';
63 63 import { useScript } from '/@/hooks/web/useScript';
64 64 import { Input, Divider, Upload, message, Modal, Form, Row, Col } from 'ant-design-vue';
65 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
  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>
... ...
  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 48 <TableAction
49 49 :actions="[
50 50 {
  51 + label: '详情',
  52 + icon: 'ant-design:eye-outlined',
  53 + onClick: handleDetail.bind(null, record),
  54 + },
  55 + {
51 56 label: '编辑',
52 57 icon: 'clarity:note-edit-line',
53 58 onClick: handleEdit.bind(null, record),
... ... @@ -65,6 +70,7 @@
65 70 />
66 71 </template>
67 72 </BasicTable>
  73 + <DeviceDetailDrawer @register="registerDetailDrawer" />
68 74 <DeviceModal @register="registerModal" @success="handleSuccess" @reload="handleReload" />
69 75 </PageWrapper>
70 76 </template>
... ... @@ -72,16 +78,18 @@
72 78 import { defineComponent, reactive } from 'vue';
73 79 import { DeviceState, DeviceTypeEnum } from '/@/api/device/model/deviceModel';
74 80 import { BasicTable, useTable, TableAction } from '/@/components/Table';
75   - import { columns, searchFormSchema } from './device.data';
  81 + import { columns, searchFormSchema } from './config/device.data';
76 82 import { Tag } from 'ant-design-vue';
77 83 import { useMessage } from '/@/hooks/web/useMessage';
78 84 import { deleteDevice, devicePage } from '/@/api/device/deviceManager';
79 85 import { PageEnum } from '/@/enums/pageEnum';
80 86 import { useGo } from '/@/hooks/web/usePage';
81 87 import { PageWrapper } from '/@/components/Page';
82   - import OrganizationIdTree from '/@/views/common/OrganizationIdTree.vue';
83 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 94 export default defineComponent({
87 95 name: 'DeviceManagement',
... ... @@ -92,6 +100,7 @@
92 100 OrganizationIdTree,
93 101 Tag,
94 102 DeviceModal,
  103 + DeviceDetailDrawer,
95 104 },
96 105 setup(_) {
97 106 const { createMessage } = useMessage();
... ... @@ -99,6 +108,7 @@
99 108
100 109 const searchInfo = reactive<Recordable>({});
101 110 const [registerModal, { openModal }] = useModal();
  111 + const [registerDetailDrawer, { openDrawer }] = useDrawer();
102 112 const [registerTable, { reload }] = useTable({
103 113 title: '设备列表',
104 114 api: devicePage,
... ... @@ -113,7 +123,7 @@
113 123 showIndexColumn: false,
114 124 searchInfo: searchInfo,
115 125 actionColumn: {
116   - width: 180,
  126 + width: 200,
117 127 title: '操作',
118 128 dataIndex: 'action',
119 129 slots: { customRender: 'action' },
... ... @@ -130,6 +140,12 @@
130 140 });
131 141 }
132 142
  143 + function handleDetail(record: Recordable) {
  144 + openDrawer(true, {
  145 + record,
  146 + });
  147 + }
  148 +
133 149 function handleEdit(record: Recordable) {
134 150 openModal(true, {
135 151 isUpdate: true,
... ... @@ -155,9 +171,11 @@
155 171 function goDeviceProfile() {
156 172 go(PageEnum.DEVICE_PROFILE);
157 173 }
  174 +
158 175 return {
159 176 registerTable,
160 177 handleCreate,
  178 + handleDetail,
161 179 handleEdit,
162 180 handleDelete,
163 181 handleSuccess,
... ... @@ -165,6 +183,7 @@
165 183 handleSelect,
166 184 registerModal,
167 185 handleReload,
  186 + registerDetailDrawer,
168 187 DeviceTypeEnum,
169 188 DeviceState,
170 189 searchInfo,
... ...
  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 +}
... ...