Commit 288e65088ff750a5817a4089edda280270a924f8

Authored by xp.Huang
2 parents 2536255f 8ed5db00

Merge branch 'sqy_dev' into 'main'

feat:告警页面及逻辑编写,告警中心页面开发,设备凭证调试...

See merge request huang/yun-teng-iot-front!57
... ... @@ -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({
... ...
... ... @@ -49,6 +49,7 @@ export default {
49 49 alarmManagement: 'alarm management',
50 50 geographicPosition: 'geographic position',
51 51 alarmContact: 'alarm contact',
  52 + alarmCenter: 'alarm center',
52 53 },
53 54
54 55 dept: {
... ...
... ... @@ -62,6 +62,7 @@ export default {
62 62 alarmManagement: '告警管理',
63 63 geographicPosition: '地理位置',
64 64 alarmContact: '告警联系人',
  65 + alarmCenter: '告警中心',
65 66 },
66 67 system: {
67 68 system: '系统管理',
... ...
  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 +<template>
  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>
  18 +</template>
  19 +<script lang="ts">
  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';
  26 + export default defineComponent({
  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 + },
  70 + });
  71 +</script>
... ...
... ... @@ -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 },
... ...
... ... @@ -2,7 +2,6 @@ import { formatToDateTime } from '/@/utils/dateUtil';
2 2 import { FormSchema } from '/@/components/Form';
3 3 import { BasicColumn } from '/@/components/Table';
4 4 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel';
5   -import {} from '';
6 5
7 6 export const columns: BasicColumn[] = [
8 7 {
... ... @@ -43,16 +42,7 @@ export const columns: BasicColumn[] = [
43 42 key: 'description',
44 43 },
45 44 ];
46   -
47   -// 实时数据
48   -export const realTimeDataSearchSchemas: FormSchema[] = [
49   - {
50   - field: 'key',
51   - label: '键 / 值',
52   - component: 'Input',
53   - colProps: { span: 8 },
54   - },
55   -];
  45 +// 实时数据表格
56 46 export const realTimeDataColumns: BasicColumn[] = [
57 47 {
58 48 title: '键',
... ... @@ -101,18 +91,16 @@ export const alarmSearchSchemas: FormSchema[] = [
101 91 },
102 92 },
103 93 {
104   - field: 'type',
  94 + field: 'alarmType',
105 95 label: '告警类型',
106 96 component: 'Input',
107 97 colProps: { span: 6 },
108 98 },
109 99 {
110   - field: 'startTime',
111   - label: ' ',
112   - component: 'DatePicker',
113   - componentProps: {
114   - format: (value) => dayjs(value).valueOf(),
115   - },
  100 + field: 'time',
  101 + label: '告警时间范围',
  102 + component: 'RangePicker',
  103 + componentProps: {},
116 104 colProps: { span: 6 },
117 105 },
118 106 ];
... ... @@ -145,30 +133,6 @@ export const alarmColumns: BasicColumn[] = [
145 133 width: 160,
146 134 },
147 135 ];
148   -const alarmLevel = (type: string): string => {
149   - if (type === 'CRITICAL') {
150   - return '危险';
151   - } else if (type === 'MAJOR') {
152   - return '重要';
153   - } else if (type === 'MINOR') {
154   - return '次要';
155   - } else if (type === 'WARNING') {
156   - return '警告';
157   - } else {
158   - return '不确定';
159   - }
160   -};
161   -const statusType = (type: string): string => {
162   - if (type === 'CLEARED_UNACK') {
163   - return '清除未确认';
164   - } else if (type === 'CLEARED_ACK') {
165   - return '清除已确认';
166   - } else if (type === 'ACTIVE_ACK') {
167   - return '激活已确认';
168   - } else {
169   - return '激活未确认';
170   - }
171   -};
172 136
173 137 export const alarmSchemasForm: FormSchema[] = [
174 138 {
... ... @@ -197,6 +161,24 @@ export const alarmSchemasForm: FormSchema[] = [
197 161 },
198 162 },
199 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 + {
200 182 field: 'type',
201 183 label: '告警类型',
202 184 component: 'Input',
... ... @@ -224,9 +206,6 @@ export const alarmSchemasForm: FormSchema[] = [
224 206 field: 'details',
225 207 label: '详情',
226 208 component: 'InputTextArea',
227   - componentProps: {
228   - disabled: true,
229   - },
230 209 },
231 210 ];
232 211
... ... @@ -277,3 +256,28 @@ export const childDeviceColumns: BasicColumn[] = [
277 256 width: 160,
278 257 },
279 258 ];
  259 +
  260 +export const alarmLevel = (type: string): string => {
  261 + if (type === 'CRITICAL') {
  262 + return '危险';
  263 + } else if (type === 'MAJOR') {
  264 + return '重要';
  265 + } else if (type === 'MINOR') {
  266 + return '次要';
  267 + } else if (type === 'WARNING') {
  268 + return '警告';
  269 + } else {
  270 + return '不确定';
  271 + }
  272 +};
  273 +export const statusType = (type: string): string => {
  274 + if (type === 'CLEARED_UNACK') {
  275 + return '清除未确认';
  276 + } else if (type === 'CLEARED_ACK') {
  277 + return '清除已确认';
  278 + } else if (type === 'ACTIVE_ACK') {
  279 + return '激活已确认';
  280 + } else {
  281 + return '激活未确认';
  282 + }
  283 +};
... ...
... ... @@ -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 type="danger" @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>
... ... @@ -20,32 +32,44 @@
20 32 import { BasicForm, useForm } from '/@/components/Form';
21 33 import { alarmSchemasForm } from '../../config/detail.config';
22 34 import { clearOrAckAlarm } from '/@/api/device/deviceManager';
  35 + import { alarmLevel, statusType } from '../../config/detail.config';
23 36 export default defineComponent({
24   - name: 'AlarmDetailDrawer',
  37 + name: 'AlarmDetailModal',
25 38 components: {
26 39 BasicModal,
27 40 BasicForm,
28 41 },
29   - setup() {
  42 + emits: ['success', 'register'],
  43 + setup(_, { emit }) {
30 44 const [registerForm, { setFieldsValue, resetFields }] = useForm({
31 45 showActionButtonGroup: false,
32 46 schemas: alarmSchemasForm,
  47 + labelCol: {
  48 + span: 5,
  49 + },
33 50 });
34 51 const alarmId = ref('');
  52 + const alarmStatus = ref('');
35 53 const [registerModal, { closeModal }] = useModalInner(async (data) => {
36 54 await resetFields();
37   - await setFieldsValue(data);
  55 + await setFieldsValue({
  56 + ...data,
  57 + severity: alarmLevel(data.severity),
  58 + status: statusType(data.status),
  59 + });
38 60 alarmId.value = data.id;
39   - console.log(data);
  61 + alarmStatus.value = data.status;
40 62 });
41 63 // 处理报警
42 64 const handleAlarm = async () => {
43 65 await clearOrAckAlarm(unref(alarmId), false);
  66 + emit('success');
44 67 closeModal();
45 68 };
46 69 // 清除报警
47 70 const clearAlarm = async () => {
48 71 await clearOrAckAlarm(unref(alarmId), true);
  72 + emit('success');
49 73 closeModal();
50 74 };
51 75 return {
... ... @@ -53,6 +77,7 @@
53 77 registerForm,
54 78 clearAlarm,
55 79 handleAlarm,
  80 + alarmStatus,
56 81 };
57 82 },
58 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({
... ...