Showing
15 changed files
with
568 additions
and
107 deletions
... | ... | @@ -82,13 +82,6 @@ export const createOrEditDevice = (data) => { |
82 | 82 | }); |
83 | 83 | }; |
84 | 84 | |
85 | -// 获取设备唯一token | |
86 | -export const getDeviceToken = () => { | |
87 | - return defHttp.get({ | |
88 | - url: '/common', | |
89 | - }); | |
90 | -}; | |
91 | - | |
92 | 85 | // 查询设备详情 |
93 | 86 | export const getDeviceDetail = (id: string) => { |
94 | 87 | return defHttp.get({ | ... | ... |
1 | +import { alarmLevel, statusType } from '/@/views/device/manage/config/detail.config'; | |
2 | +import { FormSchema } from '/@/components/Form'; | |
3 | +import { BasicColumn } from '/@/components/Table'; | |
4 | +export const alarmSearchSchemas: FormSchema[] = [ | |
5 | + { | |
6 | + field: 'status', | |
7 | + label: '告警状态', | |
8 | + component: 'Select', | |
9 | + colProps: { span: 6 }, | |
10 | + componentProps: { | |
11 | + options: [ | |
12 | + { | |
13 | + label: '清除未确认', | |
14 | + value: 'CLEARED_UNACK', | |
15 | + }, | |
16 | + { | |
17 | + label: '激活未确认', | |
18 | + value: 'ACTIVE_UNACK', | |
19 | + }, | |
20 | + { | |
21 | + label: '清除已确认', | |
22 | + value: 'CLEARED_ACK', | |
23 | + }, | |
24 | + { | |
25 | + label: '激活已确认', | |
26 | + value: 'ACTIVE_ACK', | |
27 | + }, | |
28 | + ], | |
29 | + }, | |
30 | + }, | |
31 | + { | |
32 | + field: 'alarmType', | |
33 | + label: '告警类型', | |
34 | + component: 'Input', | |
35 | + colProps: { span: 6 }, | |
36 | + }, | |
37 | + { | |
38 | + field: 'time', | |
39 | + label: '告警时间范围', | |
40 | + component: 'RangePicker', | |
41 | + componentProps: {}, | |
42 | + colProps: { span: 6 }, | |
43 | + }, | |
44 | +]; | |
45 | +export const alarmColumns: BasicColumn[] = [ | |
46 | + { | |
47 | + title: '告警时间', | |
48 | + dataIndex: 'createdTime', | |
49 | + width: 120, | |
50 | + }, | |
51 | + { | |
52 | + title: '告警设备', | |
53 | + dataIndex: 'deviceName', | |
54 | + width: 100, | |
55 | + }, | |
56 | + { | |
57 | + title: '类型', | |
58 | + dataIndex: 'type', | |
59 | + width: 160, | |
60 | + }, | |
61 | + { | |
62 | + title: '告警级别', | |
63 | + dataIndex: 'severity', | |
64 | + width: 160, | |
65 | + format: (text) => alarmLevel(text), | |
66 | + }, | |
67 | + { | |
68 | + title: '状态', | |
69 | + dataIndex: 'status', | |
70 | + format: (text) => statusType(text), | |
71 | + width: 160, | |
72 | + }, | |
73 | +]; | |
74 | + | |
75 | +export const alarmSchemasForm: FormSchema[] = [ | |
76 | + { | |
77 | + field: 'deviceName', | |
78 | + label: '告警设备', | |
79 | + component: 'Input', | |
80 | + componentProps: { | |
81 | + disabled: true, | |
82 | + }, | |
83 | + }, | |
84 | + | |
85 | + { | |
86 | + field: 'startTs', | |
87 | + label: '开始时间', | |
88 | + component: 'Input', | |
89 | + componentProps: { | |
90 | + disabled: true, | |
91 | + }, | |
92 | + }, | |
93 | + { | |
94 | + field: 'endTs', | |
95 | + label: '结束时间', | |
96 | + component: 'Input', | |
97 | + componentProps: { | |
98 | + disabled: true, | |
99 | + }, | |
100 | + }, | |
101 | + { | |
102 | + field: 'ackTs', | |
103 | + label: '处理时间', | |
104 | + component: 'Input', | |
105 | + componentProps: { | |
106 | + disabled: true, | |
107 | + }, | |
108 | + ifShow: ({ values }) => values.status === '激活已确认' || values.status === '清除已确认', | |
109 | + }, | |
110 | + { | |
111 | + field: 'clearTs', | |
112 | + label: '清除时间', | |
113 | + component: 'Input', | |
114 | + componentProps: { | |
115 | + disabled: true, | |
116 | + }, | |
117 | + ifShow: ({ values }) => values.status === '清除已确认' || values.status === '清除未确认', | |
118 | + }, | |
119 | + { | |
120 | + field: 'type', | |
121 | + label: '告警类型', | |
122 | + component: 'Input', | |
123 | + componentProps: { | |
124 | + disabled: true, | |
125 | + }, | |
126 | + }, | |
127 | + { | |
128 | + field: 'severity', | |
129 | + label: '严重程度', | |
130 | + component: 'Input', | |
131 | + componentProps: { | |
132 | + disabled: true, | |
133 | + }, | |
134 | + }, | |
135 | + { | |
136 | + field: 'status', | |
137 | + label: '状态', | |
138 | + component: 'Input', | |
139 | + componentProps: { | |
140 | + disabled: true, | |
141 | + }, | |
142 | + }, | |
143 | + { | |
144 | + field: 'details', | |
145 | + label: '详情', | |
146 | + component: 'InputTextArea', | |
147 | + }, | |
148 | +]; | ... | ... |
1 | +<template> | |
2 | + <BasicDrawer v-bind="$attrs" title="告警详情" @register="registerDrawer" width="30%"> | |
3 | + <BasicForm @register="registerForm" /> | |
4 | + <div class="flex justify-end"> | |
5 | + <a-button | |
6 | + type="primary" | |
7 | + class="mr-4" | |
8 | + @click="handleAlarm" | |
9 | + v-if="alarmStatus !== 'ACTIVE_ACK' && alarmStatus !== 'CLEARED_ACK'" | |
10 | + >处理</a-button | |
11 | + > | |
12 | + <a-button | |
13 | + danger | |
14 | + type="primary" | |
15 | + @click="clearAlarm" | |
16 | + v-if="alarmStatus !== 'CLEARED_UNACK' && alarmStatus !== 'CLEARED_ACK'" | |
17 | + >清除</a-button | |
18 | + > | |
19 | + </div> | |
20 | + </BasicDrawer> | |
21 | +</template> | |
22 | + | |
23 | +<script lang="ts"> | |
24 | + import { defineComponent, ref, unref } from 'vue'; | |
25 | + import { BasicForm, useForm } from '/@/components/Form'; | |
26 | + import { alarmSchemasForm } from '../config/detail.config'; | |
27 | + import { clearOrAckAlarm } from '/@/api/device/deviceManager'; | |
28 | + import { alarmLevel, statusType } from '/@/views/device/manage/config/detail.config'; | |
29 | + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | |
30 | + export default defineComponent({ | |
31 | + name: 'AlarmDetailDrawer', | |
32 | + components: { | |
33 | + BasicForm, | |
34 | + BasicDrawer, | |
35 | + }, | |
36 | + emits: ['success', 'register'], | |
37 | + setup(_, { emit }) { | |
38 | + const [registerForm, { setFieldsValue, resetFields }] = useForm({ | |
39 | + showActionButtonGroup: false, | |
40 | + schemas: alarmSchemasForm, | |
41 | + labelCol: { | |
42 | + span: 5, | |
43 | + }, | |
44 | + }); | |
45 | + const alarmId = ref(''); | |
46 | + const alarmStatus = ref(''); | |
47 | + const [registerDrawer, { closeDrawer }] = useDrawerInner(async (data) => { | |
48 | + await resetFields(); | |
49 | + await setFieldsValue({ | |
50 | + ...data, | |
51 | + severity: alarmLevel(data.severity), | |
52 | + status: statusType(data.status), | |
53 | + }); | |
54 | + console.log(data.status); | |
55 | + alarmStatus.value = data.status; | |
56 | + alarmId.value = data.id; | |
57 | + }); | |
58 | + // 处理报警 | |
59 | + const handleAlarm = async () => { | |
60 | + await clearOrAckAlarm(unref(alarmId), false); | |
61 | + emit('success'); | |
62 | + closeDrawer(); | |
63 | + }; | |
64 | + // 清除报警 | |
65 | + const clearAlarm = async () => { | |
66 | + await clearOrAckAlarm(unref(alarmId), true); | |
67 | + emit('success'); | |
68 | + closeDrawer(); | |
69 | + }; | |
70 | + return { | |
71 | + registerDrawer, | |
72 | + registerForm, | |
73 | + clearAlarm, | |
74 | + handleAlarm, | |
75 | + alarmStatus, | |
76 | + }; | |
77 | + }, | |
78 | + }); | |
79 | +</script> | |
80 | + | |
81 | +<style lang="less" scoped></style> | ... | ... |
1 | 1 | <template> |
2 | - <div></div> | |
2 | + <div> | |
3 | + <BasicTable @register="registerTable"> | |
4 | + <template #action="{ record }"> | |
5 | + <TableAction | |
6 | + :actions="[ | |
7 | + { | |
8 | + label: '详情', | |
9 | + icon: 'ant-design:eye-outlined', | |
10 | + onClick: handleDetail.bind(null, record), | |
11 | + }, | |
12 | + ]" | |
13 | + /> | |
14 | + </template> | |
15 | + </BasicTable> | |
16 | + <AlarmDetailDrawer @register="registerDetailDrawer" @success="handleSuccess" /> | |
17 | + </div> | |
3 | 18 | </template> |
4 | - | |
5 | 19 | <script lang="ts"> |
6 | 20 | import { defineComponent } from 'vue'; |
21 | + import { BasicTable, useTable, TableAction } from '/@/components/Table'; | |
22 | + import { alarmColumns, alarmSearchSchemas } from './config/detail.config'; | |
23 | + import { getDeviceAlarm } from '/@/api/device/deviceManager'; | |
24 | + import AlarmDetailDrawer from './cpns/AlarmDetailDrawer.vue'; | |
25 | + import { useDrawer } from '/@/components/Drawer'; | |
7 | 26 | export default defineComponent({ |
8 | - setup() {}, | |
27 | + name: 'DeviceManagement', | |
28 | + components: { | |
29 | + BasicTable, | |
30 | + TableAction, | |
31 | + AlarmDetailDrawer, | |
32 | + }, | |
33 | + | |
34 | + setup() { | |
35 | + const [registerTable, { reload }] = useTable({ | |
36 | + api: getDeviceAlarm, | |
37 | + columns: alarmColumns, | |
38 | + formConfig: { | |
39 | + labelWidth: 120, | |
40 | + schemas: alarmSearchSchemas, | |
41 | + fieldMapToTime: [['time', ['startTime', 'endTime'], 'x']], | |
42 | + }, | |
43 | + useSearchForm: true, | |
44 | + bordered: true, | |
45 | + showIndexColumn: false, | |
46 | + actionColumn: { | |
47 | + width: 200, | |
48 | + title: '操作', | |
49 | + slots: { customRender: 'action' }, | |
50 | + fixed: 'right', | |
51 | + }, | |
52 | + beforeFetch: (data) => { | |
53 | + Reflect.set(data, 'startTime', null); | |
54 | + }, | |
55 | + }); | |
56 | + const [registerDetailDrawer, { openDrawer }] = useDrawer(); | |
57 | + const handleDetail = (record: Recordable) => { | |
58 | + openDrawer(true, record); | |
59 | + }; | |
60 | + const handleSuccess = () => { | |
61 | + reload(); | |
62 | + }; | |
63 | + return { | |
64 | + registerTable, | |
65 | + registerDetailDrawer, | |
66 | + handleDetail, | |
67 | + handleSuccess, | |
68 | + }; | |
69 | + }, | |
9 | 70 | }); |
10 | 71 | </script> |
11 | - | |
12 | -<style lang="less" scoped></style> | ... | ... |
... | ... | @@ -84,12 +84,6 @@ export const step1Schemas: FormSchema[] = [ |
84 | 84 | show: false, |
85 | 85 | }, |
86 | 86 | { |
87 | - field: 'deviceToken', | |
88 | - label: '设备唯一token', | |
89 | - component: 'Input', | |
90 | - show: false, | |
91 | - }, | |
92 | - { | |
93 | 87 | field: 'tenantId', |
94 | 88 | label: '租户Code', |
95 | 89 | component: 'Input', |
... | ... | @@ -103,6 +97,11 @@ export const step1Schemas: FormSchema[] = [ |
103 | 97 | }, |
104 | 98 | ]; |
105 | 99 | |
100 | +export enum credentialTypeEnum { | |
101 | + ACCESS_TOKEN = 'ACCESS_TOKEN', | |
102 | + X_509 = 'X509_CERTIFICATE', | |
103 | + MQTT_BASIC = 'MQTT_BASIC', | |
104 | +} | |
106 | 105 | // 第二步的表单 |
107 | 106 | export const step2Schemas: FormSchema[] = [ |
108 | 107 | { |
... | ... | @@ -114,37 +113,37 @@ export const step2Schemas: FormSchema[] = [ |
114 | 113 | { |
115 | 114 | label: '凭据类型', |
116 | 115 | component: 'Select', |
117 | - field: 'creaentialsType', | |
116 | + field: 'credentialType', | |
117 | + required: true, | |
118 | 118 | componentProps({ formActionType }) { |
119 | 119 | const { updateSchema, setFieldsValue } = formActionType; |
120 | 120 | return { |
121 | 121 | options: [ |
122 | 122 | { |
123 | - value: 'Access token', | |
124 | - label: 'Access token', | |
123 | + value: credentialTypeEnum.ACCESS_TOKEN, | |
124 | + label: 'Access Token', | |
125 | 125 | }, |
126 | - | |
127 | 126 | { |
128 | - value: 'X.509', | |
127 | + value: credentialTypeEnum.X_509, | |
129 | 128 | label: 'X.509', |
130 | 129 | }, |
131 | 130 | { |
132 | - value: 'MQTT Basic', | |
131 | + value: credentialTypeEnum.MQTT_BASIC, | |
133 | 132 | label: 'MQTT Basic', |
134 | 133 | }, |
135 | 134 | ], |
136 | 135 | onChange(value) { |
137 | 136 | setFieldsValue({ |
138 | 137 | publicKey: '', |
139 | - token: '', | |
138 | + credentialsId: '', | |
140 | 139 | clientId: '', |
141 | 140 | username: '', |
142 | 141 | password: '', |
143 | 142 | }); |
144 | - if (value === 'Access token') { | |
143 | + if (value === credentialTypeEnum.ACCESS_TOKEN) { | |
145 | 144 | updateSchema([ |
146 | 145 | { |
147 | - field: 'token', | |
146 | + field: 'credentialsId', | |
148 | 147 | ifShow: true, |
149 | 148 | }, |
150 | 149 | { |
... | ... | @@ -164,14 +163,14 @@ export const step2Schemas: FormSchema[] = [ |
164 | 163 | ifShow: false, |
165 | 164 | }, |
166 | 165 | ]); |
167 | - } else if (value === 'X.509') { | |
166 | + } else if (value === credentialTypeEnum.X_509) { | |
168 | 167 | updateSchema([ |
169 | 168 | { |
170 | 169 | field: 'publicKey', |
171 | 170 | ifShow: true, |
172 | 171 | }, |
173 | 172 | { |
174 | - field: 'token', | |
173 | + field: 'credentialsId', | |
175 | 174 | ifShow: false, |
176 | 175 | }, |
177 | 176 | { |
... | ... | @@ -187,7 +186,7 @@ export const step2Schemas: FormSchema[] = [ |
187 | 186 | ifShow: false, |
188 | 187 | }, |
189 | 188 | ]); |
190 | - } else { | |
189 | + } else if (value === credentialTypeEnum.MQTT_BASIC) { | |
191 | 190 | updateSchema([ |
192 | 191 | { |
193 | 192 | field: 'clientId', |
... | ... | @@ -206,7 +205,30 @@ export const step2Schemas: FormSchema[] = [ |
206 | 205 | ifShow: false, |
207 | 206 | }, |
208 | 207 | { |
209 | - field: 'token', | |
208 | + field: 'credentialsId', | |
209 | + ifShow: false, | |
210 | + }, | |
211 | + ]); | |
212 | + } else { | |
213 | + updateSchema([ | |
214 | + { | |
215 | + field: 'clientId', | |
216 | + ifShow: false, | |
217 | + }, | |
218 | + { | |
219 | + field: 'username', | |
220 | + ifShow: false, | |
221 | + }, | |
222 | + { | |
223 | + field: 'password', | |
224 | + ifShow: false, | |
225 | + }, | |
226 | + { | |
227 | + field: 'publicKey', | |
228 | + ifShow: false, | |
229 | + }, | |
230 | + { | |
231 | + field: 'credentialsId', | |
210 | 232 | ifShow: false, |
211 | 233 | }, |
212 | 234 | ]); |
... | ... | @@ -219,7 +241,7 @@ export const step2Schemas: FormSchema[] = [ |
219 | 241 | { |
220 | 242 | label: '访问令牌', |
221 | 243 | component: 'Input', |
222 | - field: 'token', | |
244 | + field: 'credentialsId', | |
223 | 245 | required: true, |
224 | 246 | ifShow: false, |
225 | 247 | }, | ... | ... |
... | ... | @@ -42,16 +42,7 @@ export const columns: BasicColumn[] = [ |
42 | 42 | key: 'description', |
43 | 43 | }, |
44 | 44 | ]; |
45 | - | |
46 | -// 实时数据 | |
47 | -export const realTimeDataSearchSchemas: FormSchema[] = [ | |
48 | - { | |
49 | - field: 'key', | |
50 | - label: '键 / 值', | |
51 | - component: 'Input', | |
52 | - colProps: { span: 8 }, | |
53 | - }, | |
54 | -]; | |
45 | +// 实时数据表格 | |
55 | 46 | export const realTimeDataColumns: BasicColumn[] = [ |
56 | 47 | { |
57 | 48 | title: '键', |
... | ... | @@ -100,15 +91,15 @@ export const alarmSearchSchemas: FormSchema[] = [ |
100 | 91 | }, |
101 | 92 | }, |
102 | 93 | { |
103 | - field: 'type', | |
94 | + field: 'alarmType', | |
104 | 95 | label: '告警类型', |
105 | 96 | component: 'Input', |
106 | 97 | colProps: { span: 6 }, |
107 | 98 | }, |
108 | 99 | { |
109 | - field: 'startTime', | |
110 | - label: ' ', | |
111 | - component: 'DatePicker', | |
100 | + field: 'time', | |
101 | + label: '告警时间范围', | |
102 | + component: 'RangePicker', | |
112 | 103 | componentProps: {}, |
113 | 104 | colProps: { span: 6 }, |
114 | 105 | }, |
... | ... | @@ -170,6 +161,24 @@ export const alarmSchemasForm: FormSchema[] = [ |
170 | 161 | }, |
171 | 162 | }, |
172 | 163 | { |
164 | + field: 'ackTs', | |
165 | + label: '处理时间', | |
166 | + component: 'Input', | |
167 | + componentProps: { | |
168 | + disabled: true, | |
169 | + }, | |
170 | + ifShow: ({ values }) => values.status === '激活已确认' || values.status === '清除已确认', | |
171 | + }, | |
172 | + { | |
173 | + field: 'clearTs', | |
174 | + label: '清除时间', | |
175 | + component: 'Input', | |
176 | + componentProps: { | |
177 | + disabled: true, | |
178 | + }, | |
179 | + ifShow: ({ values }) => values.status === '清除已确认' || values.status === '清除未确认', | |
180 | + }, | |
181 | + { | |
173 | 182 | field: 'type', |
174 | 183 | label: '告警类型', |
175 | 184 | component: 'Input', |
... | ... | @@ -197,9 +206,6 @@ export const alarmSchemasForm: FormSchema[] = [ |
197 | 206 | field: 'details', |
198 | 207 | label: '详情', |
199 | 208 | component: 'InputTextArea', |
200 | - componentProps: { | |
201 | - disabled: true, | |
202 | - }, | |
203 | 209 | }, |
204 | 210 | ]; |
205 | 211 | ... | ... |
... | ... | @@ -8,8 +8,20 @@ |
8 | 8 | > |
9 | 9 | <BasicForm @register="registerForm" /> |
10 | 10 | <div class="flex justify-end"> |
11 | - <a-button type="primary" class="mr-4" @click="handleAlarm">处理</a-button> | |
12 | - <a-button danger type="primary" @click="clearAlarm">清除</a-button> | |
11 | + <a-button | |
12 | + type="primary" | |
13 | + class="mr-4" | |
14 | + @click="handleAlarm" | |
15 | + v-if="alarmStatus !== 'ACTIVE_ACK' && alarmStatus !== 'CLEARED_ACK'" | |
16 | + >处理</a-button | |
17 | + > | |
18 | + <a-button | |
19 | + danger | |
20 | + type="primary" | |
21 | + @click="clearAlarm" | |
22 | + v-if="alarmStatus !== 'CLEARED_UNACK' && alarmStatus !== 'CLEARED_ACK'" | |
23 | + >清除</a-button | |
24 | + > | |
13 | 25 | </div> |
14 | 26 | </BasicModal> |
15 | 27 | </template> |
... | ... | @@ -22,17 +34,22 @@ |
22 | 34 | import { clearOrAckAlarm } from '/@/api/device/deviceManager'; |
23 | 35 | import { alarmLevel, statusType } from '../../config/detail.config'; |
24 | 36 | export default defineComponent({ |
25 | - name: 'AlarmDetailDrawer', | |
37 | + name: 'AlarmDetailModal', | |
26 | 38 | components: { |
27 | 39 | BasicModal, |
28 | 40 | BasicForm, |
29 | 41 | }, |
30 | - setup() { | |
42 | + emits: ['success', 'register'], | |
43 | + setup(_, { emit }) { | |
31 | 44 | const [registerForm, { setFieldsValue, resetFields }] = useForm({ |
32 | 45 | showActionButtonGroup: false, |
33 | 46 | schemas: alarmSchemasForm, |
47 | + labelCol: { | |
48 | + span: 5, | |
49 | + }, | |
34 | 50 | }); |
35 | 51 | const alarmId = ref(''); |
52 | + const alarmStatus = ref(''); | |
36 | 53 | const [registerModal, { closeModal }] = useModalInner(async (data) => { |
37 | 54 | await resetFields(); |
38 | 55 | await setFieldsValue({ |
... | ... | @@ -41,16 +58,18 @@ |
41 | 58 | status: statusType(data.status), |
42 | 59 | }); |
43 | 60 | alarmId.value = data.id; |
44 | - console.log(data); | |
61 | + alarmStatus.value = data.status; | |
45 | 62 | }); |
46 | 63 | // 处理报警 |
47 | 64 | const handleAlarm = async () => { |
48 | 65 | await clearOrAckAlarm(unref(alarmId), false); |
66 | + emit('success'); | |
49 | 67 | closeModal(); |
50 | 68 | }; |
51 | 69 | // 清除报警 |
52 | 70 | const clearAlarm = async () => { |
53 | 71 | await clearOrAckAlarm(unref(alarmId), true); |
72 | + emit('success'); | |
54 | 73 | closeModal(); |
55 | 74 | }; |
56 | 75 | return { |
... | ... | @@ -58,6 +77,7 @@ |
58 | 77 | registerForm, |
59 | 78 | clearAlarm, |
60 | 79 | handleAlarm, |
80 | + alarmStatus, | |
61 | 81 | }; |
62 | 82 | }, |
63 | 83 | }); | ... | ... |
... | ... | @@ -6,12 +6,13 @@ |
6 | 6 | @register="register" |
7 | 7 | @cancel="handleCancel" |
8 | 8 | @ok="handleOk" |
9 | + destroyOnClose | |
9 | 10 | centered |
10 | 11 | > |
11 | 12 | <div class="step-form-form"> |
12 | 13 | <Steps :current="current"> |
13 | - <Step title="填写设备信息" /> | |
14 | - <Step title="添加设备凭证" /> | |
14 | + <Step title="填写设备信息" v-if="!isUpdate" /> | |
15 | + <Step title="添加设备凭证" v-if="!isUpdate" /> | |
15 | 16 | </Steps> |
16 | 17 | </div> |
17 | 18 | <div class="mt-5"> |
... | ... | @@ -20,12 +21,14 @@ |
20 | 21 | ref="DeviceStep1Ref" |
21 | 22 | :deviceInfo="deviceInfo" |
22 | 23 | v-show="current === 0" |
24 | + :isUpdate="!isUpdate" | |
23 | 25 | /> |
24 | 26 | <DeviceStep2 |
25 | 27 | ref="DeviceStep2Ref" |
26 | 28 | @prev="handleStepPrev" |
27 | 29 | @next="handleStep2Next" |
28 | 30 | v-show="current === 1" |
31 | + v-if="!isUpdate" | |
29 | 32 | /> |
30 | 33 | </div> |
31 | 34 | </BasicModal> |
... | ... | @@ -33,12 +36,12 @@ |
33 | 36 | <script lang="ts"> |
34 | 37 | import { defineComponent, ref, computed, unref } from 'vue'; |
35 | 38 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
36 | - import { createOrEditDevice, getDeviceToken } from '/@/api/device/deviceManager'; | |
39 | + import { createOrEditDevice } from '/@/api/device/deviceManager'; | |
37 | 40 | import DeviceStep1 from '../step/DeviceStep1.vue'; |
38 | 41 | import DeviceStep2 from '../step/DeviceStep2.vue'; |
39 | 42 | import { Steps, Step } from 'ant-design-vue'; |
40 | 43 | import { useMessage } from '/@/hooks/web/useMessage'; |
41 | - | |
44 | + import { credentialTypeEnum } from '../../config/data'; | |
42 | 45 | export default defineComponent({ |
43 | 46 | name: 'DeviceModal', |
44 | 47 | components: { |
... | ... | @@ -57,26 +60,26 @@ |
57 | 60 | const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); |
58 | 61 | const { createMessage } = useMessage(); |
59 | 62 | const current = ref(0); |
60 | - const isUpdate = ref<Boolean>(); | |
63 | + const isUpdate = ref<Boolean>(false); | |
61 | 64 | const deviceInfo = ref({}); |
62 | 65 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备' : '编辑设备')); |
63 | 66 | // 所有参数 |
64 | 67 | let stepState = ref(); |
65 | 68 | // 编辑回显 |
66 | 69 | const [register, { closeModal }] = useModalInner((data) => { |
67 | - if (data.isUpdate) { | |
68 | - DeviceStep1Ref?.value?.parentSetFieldsValue(data.record); | |
69 | - DeviceStep1Ref?.value?.parentSetFieldsValue({ | |
70 | + isUpdate.value = data?.isUpdate; | |
71 | + if (unref(isUpdate)) { | |
72 | + unref(DeviceStep1Ref)?.parentSetFieldsValue(data.record); | |
73 | + unref(DeviceStep1Ref)?.parentSetFieldsValue({ | |
70 | 74 | profile: data.record.deviceProfile.name, |
71 | 75 | profileId: data.record.profileId, |
72 | 76 | deviceType: data.record.deviceType, |
73 | 77 | }); |
74 | 78 | deviceInfo.value = data.record.deviceInfo; |
75 | 79 | } else { |
76 | - DeviceStep1Ref?.value?.parentResetPositionState(); | |
80 | + unref(DeviceStep1Ref)?.parentResetPositionState(); | |
77 | 81 | deviceInfo.value = {}; |
78 | 82 | } |
79 | - isUpdate.value = data?.isUpdate; | |
80 | 83 | }); |
81 | 84 | |
82 | 85 | // 上一步 |
... | ... | @@ -94,31 +97,37 @@ |
94 | 97 | } |
95 | 98 | function handleCancel() { |
96 | 99 | if (unref(isUpdate)) { |
97 | - DeviceStep1Ref?.value?.parentResetDevicePic(deviceInfo.value); | |
100 | + unref(DeviceStep1Ref)?.parentResetDevicePic(deviceInfo.value); | |
98 | 101 | } |
99 | 102 | current.value = 0; |
100 | - DeviceStep1Ref?.value?.resetFields(); | |
101 | - DeviceStep2Ref?.value?.resetFieldsValueAndStatus(); | |
103 | + unref(DeviceStep1Ref)?.resetFields(); | |
104 | + unref(DeviceStep2Ref)?.resetFieldsValueAndStatus(); | |
102 | 105 | } |
103 | 106 | // 提交 |
104 | 107 | async function handleOk() { |
105 | 108 | if (current.value === 0) { |
106 | 109 | // 验证 |
107 | - const valid = await DeviceStep1Ref.value?.parentValidate(); | |
110 | + const valid = await unref(DeviceStep1Ref)?.parentValidate(); | |
111 | + console.log('123'); | |
108 | 112 | if (!valid) return; |
109 | - stepState.value = DeviceStep1Ref?.value?.parentGetFieldsValue(); | |
113 | + stepState.value = unref(DeviceStep1Ref)?.parentGetFieldsValue(); | |
110 | 114 | } else { |
111 | - if (DeviceStep2Ref?.value?.getFieldsValue().creaentialsType) { | |
112 | - const valid = await DeviceStep2Ref?.value?.validate(); | |
113 | - // 第二页验证通过情况 | |
115 | + if (unref(DeviceStep2Ref)?.getFieldsValue().addAgree) { | |
116 | + const valid = await unref(DeviceStep2Ref)?.validate(); | |
114 | 117 | if (!valid) return; |
118 | + | |
119 | + // 第二页验证通过情况 | |
120 | + stepState.value = { | |
121 | + ...unref(stepState), | |
122 | + ...unref(DeviceStep2Ref)?.getFieldsValue(), | |
123 | + }; | |
115 | 124 | } |
116 | 125 | } |
117 | 126 | // 验证成功 --调-- 新增或者编辑接口 |
118 | 127 | const msg = computed(() => (unref(stepState).id ? '更新设备成功' : '新增设备成功')); |
119 | 128 | if (unref(stepState).id) { |
120 | 129 | const editData = { |
121 | - ...stepState.value, | |
130 | + ...unref(stepState), | |
122 | 131 | deviceInfo: { |
123 | 132 | avatar: DeviceStep1Ref.value?.devicePic, |
124 | 133 | ...DeviceStep1Ref.value?.positionState, |
... | ... | @@ -126,19 +135,33 @@ |
126 | 135 | }; |
127 | 136 | await createOrEditDevice(editData); |
128 | 137 | } else { |
129 | - let deviceToken = await getDeviceToken(); | |
130 | - // 创建需要携带唯一的设备token | |
131 | 138 | const createData = { |
132 | - ...stepState.value, | |
133 | - deviceToken, | |
139 | + ...unref(stepState), | |
134 | 140 | deviceInfo: { |
135 | 141 | avatar: DeviceStep1Ref.value?.devicePic, |
136 | 142 | ...DeviceStep1Ref.value?.positionState, |
137 | 143 | }, |
144 | + deviceToken: | |
145 | + unref(current) === 0 || !unref(stepState).addAgree | |
146 | + ? null | |
147 | + : { | |
148 | + credentialsType: unref(stepState).credentialType, | |
149 | + credentialsId: unref(stepState).credentialsId, | |
150 | + credentialsValue: | |
151 | + unref(stepState).credentialType === credentialTypeEnum.MQTT_BASIC | |
152 | + ? JSON.stringify({ | |
153 | + userName: unref(stepState).username, | |
154 | + password: unref(stepState).password, | |
155 | + clientId: unref(stepState).clientId, | |
156 | + }) | |
157 | + : unref(stepState).credentialType === credentialTypeEnum.X_509 | |
158 | + ? unref(stepState).publicKey | |
159 | + : null, | |
160 | + }, | |
138 | 161 | }; |
139 | 162 | await createOrEditDevice(createData); |
140 | 163 | } |
141 | - createMessage.success(msg.value); | |
164 | + createMessage.success(unref(msg)); | |
142 | 165 | handleCancel(); |
143 | 166 | closeModal(); |
144 | 167 | emit('reload'); |
... | ... | @@ -149,6 +172,7 @@ |
149 | 172 | DeviceStep1Ref, |
150 | 173 | DeviceStep2Ref, |
151 | 174 | deviceInfo, |
175 | + isUpdate, | |
152 | 176 | register, |
153 | 177 | handleStepPrev, |
154 | 178 | handleStep1Next, | ... | ... |
1 | +<template> | |
2 | + <BasicModal @register="registerModal" v-bind="$attrs" title="管理设备凭证"> | |
3 | + <BasicForm @register="registerForm" @cancel="handleCancel" @ok="handleOk"> | |
4 | + <template #addAgree="{ model, field }"> | |
5 | + <Checkbox v-model:checked="model[field]" @change="checkedChange" /> | |
6 | + <span class="ml-2">添加协议</span> | |
7 | + </template> | |
8 | + </BasicForm> | |
9 | + </BasicModal> | |
10 | +</template> | |
11 | + | |
12 | +<script lang="ts"> | |
13 | + import { defineComponent } from 'vue'; | |
14 | + import { useModalInner, BasicModal } from '/@/components/Modal'; | |
15 | + import { Checkbox } from 'ant-design-vue'; | |
16 | + import { BasicForm, useForm } from '/@/components/Form'; | |
17 | + import { step2Schemas } from '../../config/data'; | |
18 | + | |
19 | + export default defineComponent({ | |
20 | + components: { | |
21 | + BasicModal, | |
22 | + BasicForm, | |
23 | + Checkbox, | |
24 | + }, | |
25 | + emits: ['register'], | |
26 | + setup() { | |
27 | + const [registerModal, { closeModal }] = useModalInner(async (data) => { | |
28 | + console.log(data); | |
29 | + }); | |
30 | + const [ | |
31 | + registerForm, | |
32 | + { getFieldsValue, updateSchema, validate, resetFields, setFieldsValue }, | |
33 | + ] = useForm({ | |
34 | + labelWidth: 100, | |
35 | + schemas: step2Schemas, | |
36 | + actionColOptions: { | |
37 | + span: 14, | |
38 | + }, | |
39 | + labelAlign: 'left', | |
40 | + showSubmitButton: false, | |
41 | + showResetButton: false, | |
42 | + wrapperCol: { | |
43 | + span: 12, | |
44 | + }, | |
45 | + }); | |
46 | + const checkedChange = async (e) => { | |
47 | + if (!e.target.checked) { | |
48 | + await updateSchema([ | |
49 | + { | |
50 | + field: 'credentialsId', | |
51 | + ifShow: false, | |
52 | + }, | |
53 | + { | |
54 | + field: 'clientId', | |
55 | + ifShow: false, | |
56 | + }, | |
57 | + { | |
58 | + field: 'username', | |
59 | + ifShow: false, | |
60 | + }, | |
61 | + { | |
62 | + field: 'password', | |
63 | + ifShow: false, | |
64 | + }, | |
65 | + { | |
66 | + field: 'publicKey', | |
67 | + ifShow: false, | |
68 | + }, | |
69 | + ]); | |
70 | + setFieldsValue({ | |
71 | + credentialType: '', | |
72 | + }); | |
73 | + } | |
74 | + }; | |
75 | + const handleCancel = () => { | |
76 | + console.log('取消'); | |
77 | + }; | |
78 | + const handleOk = () => { | |
79 | + console.log('确定'); | |
80 | + }; | |
81 | + return { | |
82 | + registerModal, | |
83 | + registerForm, | |
84 | + checkedChange, | |
85 | + handleCancel, | |
86 | + handleOk, | |
87 | + }; | |
88 | + }, | |
89 | + }); | |
90 | +</script> | ... | ... |
... | ... | @@ -26,6 +26,9 @@ |
26 | 26 | </Input> |
27 | 27 | </template> |
28 | 28 | </BasicForm> |
29 | + <div class="flex justify-center" v-if="isUpdate"> | |
30 | + <a-button type="primary" @click="nextStep">下一步</a-button> | |
31 | + </div> | |
29 | 32 | </div> |
30 | 33 | <Modal |
31 | 34 | v-model:visible="visible" |
... | ... | @@ -86,6 +89,9 @@ |
86 | 89 | type: Object, |
87 | 90 | default: () => ({}), |
88 | 91 | }, |
92 | + isUpdate: { | |
93 | + type: Boolean, | |
94 | + }, | |
89 | 95 | }, |
90 | 96 | emits: ['next'], |
91 | 97 | setup(props, { emit }) { |
... | ... | @@ -106,14 +112,11 @@ |
106 | 112 | actionColOptions: { |
107 | 113 | span: 14, |
108 | 114 | }, |
109 | - labelAlign: 'left', | |
115 | + labelAlign: 'right', | |
110 | 116 | showResetButton: false, |
111 | - submitButtonOptions: { | |
112 | - text: '下一步', | |
113 | - }, | |
114 | - submitFunc: customSubmitFunc, | |
117 | + showSubmitButton: false, | |
115 | 118 | }); |
116 | - async function customSubmitFunc() { | |
119 | + async function nextStep() { | |
117 | 120 | try { |
118 | 121 | let values = await validate(); |
119 | 122 | values = { devicePic: devicePic.value, ...positionState, ...values }; |
... | ... | @@ -268,6 +271,7 @@ |
268 | 271 | parentValidate, |
269 | 272 | parentResetDevicePic, |
270 | 273 | parentResetPositionState, |
274 | + nextStep, | |
271 | 275 | }; |
272 | 276 | }, |
273 | 277 | }); | ... | ... |
... | ... | @@ -2,7 +2,8 @@ |
2 | 2 | <div class="step2"> |
3 | 3 | <BasicForm @register="registerForm"> |
4 | 4 | <template #addAgree="{ model, field }"> |
5 | - <Checkbox v-model:checked="model[field]" @change="checkedChange" />添加协议 | |
5 | + <Checkbox v-model:checked="model[field]" @change="checkedChange" /> | |
6 | + <span class="ml-2">添加协议</span> | |
6 | 7 | </template> |
7 | 8 | </BasicForm> |
8 | 9 | <div> |
... | ... | @@ -47,7 +48,7 @@ |
47 | 48 | if (!e.target.checked) { |
48 | 49 | await updateSchema([ |
49 | 50 | { |
50 | - field: 'token', | |
51 | + field: 'credentialsId', | |
51 | 52 | ifShow: false, |
52 | 53 | }, |
53 | 54 | { |
... | ... | @@ -67,6 +68,9 @@ |
67 | 68 | ifShow: false, |
68 | 69 | }, |
69 | 70 | ]); |
71 | + setFieldsValue({ | |
72 | + credentialType: '', | |
73 | + }); | |
70 | 74 | } |
71 | 75 | }; |
72 | 76 | function resetFieldsValueAndStatus() { |
... | ... | @@ -80,7 +84,7 @@ |
80 | 84 | ifShow: false, |
81 | 85 | }, |
82 | 86 | { |
83 | - field: 'token', | |
87 | + field: 'credentialsId', | |
84 | 88 | ifShow: false, |
85 | 89 | }, |
86 | 90 | { |
... | ... | @@ -97,6 +101,10 @@ |
97 | 101 | }, |
98 | 102 | ]); |
99 | 103 | } |
104 | + // 验证 | |
105 | + function validateStep2Method() { | |
106 | + validate(); | |
107 | + } | |
100 | 108 | |
101 | 109 | return { |
102 | 110 | prevStep, |
... | ... | @@ -105,6 +113,7 @@ |
105 | 113 | getFieldsValue, |
106 | 114 | validate, |
107 | 115 | resetFieldsValueAndStatus, |
116 | + validateStep2Method, | |
108 | 117 | }; |
109 | 118 | }, |
110 | 119 | }); | ... | ... |
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | /> |
14 | 14 | </template> |
15 | 15 | </BasicTable> |
16 | - <AlarmDetailModal @register="registerDetailModal" /> | |
16 | + <AlarmDetailModal @register="registerDetailModal" @success="handleSuccess" /> | |
17 | 17 | </div> |
18 | 18 | </template> |
19 | 19 | <script lang="ts"> |
... | ... | @@ -37,18 +37,20 @@ |
37 | 37 | }, |
38 | 38 | }, |
39 | 39 | setup(props) { |
40 | - const [registerTable] = useTable({ | |
40 | + const [registerTable, { reload }] = useTable({ | |
41 | 41 | api: getDeviceAlarm, |
42 | 42 | columns: alarmColumns, |
43 | 43 | formConfig: { |
44 | 44 | labelWidth: 120, |
45 | 45 | schemas: alarmSearchSchemas, |
46 | + fieldMapToTime: [['time', ['startTime', 'endTime'], 'x']], | |
46 | 47 | }, |
47 | 48 | useSearchForm: true, |
48 | 49 | bordered: true, |
49 | 50 | showIndexColumn: false, |
50 | 51 | beforeFetch: (data) => { |
51 | 52 | Reflect.set(data, 'deviceId', props.id); |
53 | + Reflect.set(data, 'startTime', null); | |
52 | 54 | }, |
53 | 55 | actionColumn: { |
54 | 56 | width: 200, |
... | ... | @@ -61,17 +63,15 @@ |
61 | 63 | const handleDetail = (record: Recordable) => { |
62 | 64 | openModal(true, record); |
63 | 65 | }; |
66 | + const handleSuccess = () => { | |
67 | + reload(); | |
68 | + }; | |
64 | 69 | return { |
65 | 70 | registerTable, |
66 | 71 | registerDetailModal, |
67 | 72 | handleDetail, |
73 | + handleSuccess, | |
68 | 74 | }; |
69 | 75 | }, |
70 | 76 | }); |
71 | 77 | </script> |
72 | - | |
73 | -<style> | |
74 | - .aaa { | |
75 | - position: absolute; | |
76 | - } | |
77 | -</style> | ... | ... |
... | ... | @@ -15,14 +15,16 @@ |
15 | 15 | style="width: 800px" |
16 | 16 | /> |
17 | 17 | </div> |
18 | + <div class="mt-4"> | |
19 | + <a-button type="primary" class="mr-4" @click="copyTbDeviceId">复制设备ID</a-button> | |
20 | + <a-button type="primary" class="mr-4" @click="copyDeviceToken">复制访问令牌</a-button> | |
21 | + <a-button type="primary" @click="manageDeviceToken">管理设备凭证</a-button> | |
22 | + <ManageDeviceTokenModal @register="registerModal" /> | |
23 | + </div> | |
18 | 24 | <div v-if="deviceDetail?.deviceInfo?.address" class="mt-4"> |
19 | 25 | <p>设备位置</p> |
20 | 26 | <div ref="wrapRef" style="height: 400px; width: 90%"></div> |
21 | 27 | </div> |
22 | - <div class="mt-4"> | |
23 | - <a-button type="primary" class="mr-4" @click="copyTbDeviceId">复制设备ID</a-button> | |
24 | - <a-button type="primary" @click="copyDeviceToken">复制访问令牌</a-button> | |
25 | - </div> | |
26 | 28 | </div> |
27 | 29 | </template> |
28 | 30 | <script lang="ts"> |
... | ... | @@ -33,10 +35,13 @@ |
33 | 35 | import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; |
34 | 36 | import { useMessage } from '/@/hooks/web/useMessage'; |
35 | 37 | import { BAI_DU_MAP_URL } from '/@/utils/fnUtils'; |
38 | + import { useModal } from '/@/components/Modal'; | |
39 | + import ManageDeviceTokenModal from '../modal/ManageDeviceTokenModal.vue'; | |
36 | 40 | export default defineComponent({ |
37 | 41 | components: { |
38 | 42 | Image, |
39 | 43 | Table, |
44 | + ManageDeviceTokenModal, | |
40 | 45 | }, |
41 | 46 | props: { |
42 | 47 | deviceDetail: { |
... | ... | @@ -92,6 +97,10 @@ |
92 | 97 | createMessage.success('复制成功~'); |
93 | 98 | } |
94 | 99 | }; |
100 | + const [registerModal, { openModal }] = useModal(); | |
101 | + const manageDeviceToken = () => { | |
102 | + openModal(true); | |
103 | + }; | |
95 | 104 | |
96 | 105 | return { |
97 | 106 | columns, |
... | ... | @@ -99,6 +108,8 @@ |
99 | 108 | copyTbDeviceId, |
100 | 109 | copyDeviceToken, |
101 | 110 | initMap, |
111 | + manageDeviceToken, | |
112 | + registerModal, | |
102 | 113 | }; |
103 | 114 | }, |
104 | 115 | }); | ... | ... |
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | <script lang="ts"> |
5 | 5 | import { defineComponent, reactive } from 'vue'; |
6 | 6 | import { BasicTable, useTable } from '/@/components/Table'; |
7 | - import { realTimeDataColumns, realTimeDataSearchSchemas } from '../../config/detail.config'; | |
7 | + import { realTimeDataColumns } from '../../config/detail.config'; | |
8 | 8 | import { useWebSocket } from '@vueuse/core'; |
9 | 9 | import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; |
10 | 10 | import { getAuthCache } from '/@/utils/auth'; |
... | ... | @@ -40,11 +40,6 @@ |
40 | 40 | const { createMessage } = useMessage(); |
41 | 41 | const [registerTable] = useTable({ |
42 | 42 | columns: realTimeDataColumns, |
43 | - formConfig: { | |
44 | - labelWidth: 120, | |
45 | - schemas: realTimeDataSearchSchemas, | |
46 | - }, | |
47 | - useSearchForm: true, | |
48 | 43 | showTableSetting: false, |
49 | 44 | bordered: true, |
50 | 45 | showIndexColumn: false, |
... | ... | @@ -78,7 +73,6 @@ |
78 | 73 | if (item.key === item1.key) { |
79 | 74 | item1.time = item.time; |
80 | 75 | item1.value = item.value; |
81 | - console.log('哈哈哈', item, item1, state.recordList); | |
82 | 76 | flag = true; |
83 | 77 | } |
84 | 78 | }); | ... | ... |
... | ... | @@ -34,7 +34,7 @@ |
34 | 34 | import { useDrawerInner } from '/@/components/Drawer'; |
35 | 35 | import { columns, searchFormSchema } from './email.data'; |
36 | 36 | import { useMessage } from '/@/hooks/web/useMessage'; |
37 | - import { deleteSmsLog, mailLogPage, deleteMailLog } from '/@/api/message/records'; | |
37 | + import { mailLogPage, deleteMailLog } from '/@/api/message/records'; | |
38 | 38 | import { useModal } from '/@/components/Modal'; |
39 | 39 | import EmailDetail from '/@/views/message/records/item/EmailDetail.vue'; |
40 | 40 | export default defineComponent({ | ... | ... |