github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/views/Mqtt/client.vue (about) 1 <script setup lang="tsx"> 2 import { Descriptions } from '@/components/Descriptions' 3 import { useI18n } from '@/hooks/web/useI18n' 4 import {computed, h, reactive, ref, watch} from 'vue' 5 import { Form } from '@/components/Form' 6 import { ElFormItem, ElInput, ElButton } from 'element-plus' 7 import {ContentWrap} from "@/components/ContentWrap"; 8 import { useValidator } from '@/hooks/web/useValidator' 9 import { useForm } from '@/hooks/web/useForm' 10 import { DescriptionsSchema } from '@/components/Descriptions' 11 import {ApiClient, ApiSubscription} from "@/api/stub"; 12 import api from "@/api/api"; 13 import {useRoute} from "vue-router"; 14 import {parseTime} from "@/utils"; 15 import {Table} from '@/components/Table' 16 import {Pagination, TableColumn} from '@/types/table' 17 18 const route = useRoute(); 19 20 const { required } = useValidator() 21 22 const { t } = useI18n() 23 24 const loading = ref(true) 25 const clientId = computed(() => route.params.id as string); 26 const client = ref<Nullable<ApiClient>>(null) 27 28 const clientSchema = reactive<DescriptionsSchema[]>([ 29 { 30 field: 'clientId', 31 label: t('mqtt.client.clientId') 32 }, 33 { 34 field: 'username', 35 label: t('mqtt.client.username') 36 }, 37 { 38 field: 'keepAlive', 39 label: t('mqtt.client.keepAlive') 40 }, 41 { 42 field: 'version', 43 label: t('mqtt.client.version') 44 }, 45 { 46 field: 'willRetain', 47 label: t('mqtt.client.willRetain') 48 }, 49 { 50 field: 'willQos', 51 label: t('mqtt.client.willQos') 52 }, 53 { 54 field: 'willTopic', 55 label: t('mqtt.client.willTopic') 56 }, 57 { 58 field: 'willPayload', 59 label: t('mqtt.client.willPayload') 60 }, 61 { 62 field: 'remoteAddr', 63 label: t('mqtt.client.remoteAddr') 64 }, 65 { 66 field: 'localAddr', 67 label: t('mqtt.client.localAddr') 68 }, 69 { 70 field: 'subscriptionsCurrent', 71 label: t('mqtt.client.subscriptionsCurrent') 72 }, 73 { 74 field: 'subscriptionsTotal', 75 label: t('mqtt.client.subscriptionsTotal') 76 }, 77 { 78 field: 'packetsReceivedBytes', 79 label: t('mqtt.client.packetsReceivedBytes') 80 }, 81 { 82 field: 'packetsReceivedNums', 83 label: t('mqtt.client.packetsReceivedNums') 84 }, 85 { 86 field: 'packetsSendBytes', 87 label: t('mqtt.client.packetsSendBytes') 88 }, 89 { 90 field: 'packetsSendNums', 91 label: t('mqtt.client.packetsSendNums') 92 }, 93 { 94 field: 'messageDropped', 95 label: t('mqtt.client.messageDropped') 96 }, 97 { 98 field: 'inflightLen', 99 label: t('mqtt.client.inflightLen') 100 }, 101 { 102 field: 'queueLen', 103 label: t('mqtt.client.queueLen') 104 }, 105 { 106 field: 'connectedAt', 107 label: t('mqtt.client.connectedAt') 108 }, 109 { 110 field: 'disconnectedAt', 111 label: t('mqtt.client.disconnectedAt') 112 } 113 ]) 114 115 const fetch = async () => { 116 loading.value = true 117 const res = await api.v1.mqttServiceGetClientById(clientId.value) 118 .catch(() => { 119 }) 120 .finally(() => { 121 loading.value = false 122 }) 123 if (res) { 124 client.value = res.data 125 } else { 126 client.value = null 127 } 128 } 129 130 // ------------------------------------------------ 131 // subscriptions 132 // ------------------------------------------------ 133 134 interface TableObject { 135 tableList: ApiSubscription[] 136 params?: any 137 loading: boolean 138 sort?: string 139 } 140 141 interface Params { 142 page?: number; 143 limit?: number; 144 sort?: string; 145 } 146 147 const tableObject = reactive<TableObject>( 148 { 149 tableList: [], 150 loading: false, 151 } 152 ); 153 154 const columns: TableColumn[] = [ 155 { 156 field: 'id', 157 label: t('mqtt.subscription.id'), 158 width: "100px" 159 }, 160 { 161 field: 'topicName', 162 label: t('mqtt.subscription.topicName'), 163 }, 164 { 165 field: 'name', 166 label: t('mqtt.subscription.name'), 167 }, 168 { 169 field: 'qos', 170 label: t('mqtt.subscription.qos'), 171 }, 172 { 173 field: 'noLocal', 174 label: t('mqtt.subscription.noLocal'), 175 }, 176 { 177 field: 'retainAsPublished', 178 label: t('mqtt.subscription.retainAsPublished'), 179 }, 180 { 181 field: 'retainHandling', 182 label: t('mqtt.subscription.retainHandling'), 183 }, 184 ] 185 186 const paginationObj = ref<Pagination>({ 187 currentPage: 1, 188 pageSize: 50, 189 total: 0, 190 pageSizes: [50, 100, 150, 250], 191 }) 192 193 const getSubscriptionList = async () => { 194 tableObject.loading = true 195 196 let params: Params = { 197 page: paginationObj.value.currentPage, 198 limit: paginationObj.value.pageSize, 199 sort: tableObject.sort, 200 clientId: clientId.value, 201 } 202 203 const res = await api.v1.mqttServiceGetSubscriptionList(params) 204 .catch(() => { 205 }) 206 .finally(() => { 207 tableObject.loading = false 208 }) 209 if (res) { 210 const {items, meta} = res.data; 211 tableObject.tableList = items; 212 paginationObj.value.currentPage = meta.pagination.page; 213 paginationObj.value.total = meta.pagination.total; 214 } else { 215 tableObject.tableList = []; 216 } 217 } 218 219 watch( 220 () => paginationObj.value.currentPage, 221 () => { 222 getSubscriptionList() 223 } 224 ) 225 226 watch( 227 () => paginationObj.value.pageSize, 228 () => { 229 getSubscriptionList() 230 } 231 ) 232 233 const sortChange = (data) => { 234 const {column, prop, order} = data; 235 const pref: string = order === 'ascending' ? '+' : '-' 236 tableObject.sort = pref + prop 237 getSubscriptionList() 238 } 239 240 241 fetch() 242 243 getSubscriptionList() 244 245 </script> 246 247 <template> 248 249 <ContentWrap v-if="client"> 250 <Descriptions 251 :title="t('mqtt.client.client')" 252 :data="client" 253 :schema="clientSchema" 254 /> 255 256 <h2 class="mt-20px"><strong>{{ t('mqtt.client.subscriptions') }}</strong></h2> 257 258 <Table 259 class="mt-20px" 260 :selection="false" 261 v-model:pageSize="paginationObj.pageSize" 262 v-model:currentPage="paginationObj.currentPage" 263 :columns="columns" 264 :data="tableObject.tableList" 265 :loading="tableObject.loading" 266 :pagination="paginationObj" 267 style="width: 100%" 268 :showUpPagination="20" 269 /> 270 271 </ContentWrap> 272 </template> 273 274 <style lang="less" scoped> 275 :deep(.is-required--item) { 276 position: relative; 277 278 &::before { 279 margin-right: 4px; 280 color: var(--el-color-danger); 281 content: '*'; 282 } 283 } 284 </style>