github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/views/Logs/index.vue (about) 1 <script setup lang="ts"> 2 import {useI18n} from '@/hooks/web/useI18n' 3 import {Table} from '@/components/Table' 4 import {Form} from '@/components/Form' 5 import {computed, h, onMounted, onUnmounted, reactive, ref, watch} from 'vue' 6 import {FormSchema} from "@/types/form"; 7 import {useAppStore} from "@/store/modules/app"; 8 import {Pagination, TableColumn} from '@/types/table' 9 import api from "@/api/api"; 10 import {UUID} from 'uuid-generator-ts' 11 import {ApiLog} from "@/api/stub"; 12 import {useForm} from "@/hooks/web/useForm"; 13 import {parseTime} from "@/utils"; 14 import stream from "@/api/stream"; 15 import {ContentWrap} from "@/components/ContentWrap"; 16 import {useCache} from "@/hooks/web/useCache"; 17 18 const {register, elFormRef, methods} = useForm() 19 const {t} = useI18n() 20 const {wsCache} = useCache() 21 22 interface TableObject { 23 tableList: ApiLog[] 24 params?: any 25 loading: boolean 26 sort?: string 27 query?: string 28 startDate?: string; 29 endDate?: string; 30 } 31 32 interface Params { 33 page?: number; 34 limit?: number; 35 sort?: string; 36 query?: string; 37 startDate?: string; 38 endDate?: string; 39 } 40 41 const cachePref = 'logs' 42 const tableObject = reactive<TableObject>( 43 { 44 tableList: [], 45 loading: false, 46 sort: wsCache.get(cachePref + 'Sort') || '-createdAt', 47 query: wsCache.get(cachePref + 'Query'), 48 startDate: wsCache.get(cachePref + 'StartDate'), 49 endDate: wsCache.get(cachePref + 'EndDate'), 50 } 51 ); 52 53 const schema = reactive<FormSchema[]>([ 54 { 55 field: 'dateTime', 56 component: 'DatePicker', 57 label: t('logs.dateTimerange'), 58 colProps: { 59 span: 24 60 }, 61 value: [], 62 componentProps: { 63 type: 'datetimerange', 64 shortcuts: [ 65 { 66 text: t('logs.today'), 67 value: () => { 68 const end = new Date() 69 const start = new Date() 70 start.setTime(start.getTime() - start.getHours() * 3600 * 1000 - start.getMinutes() * 60 * 1000 - start.getSeconds() * 1000) 71 return [start, end] 72 } 73 }, 74 { 75 text: t('logs.yesterday'), 76 value: () => { 77 const end = new Date() 78 const start = new Date() 79 end.setHours(0) 80 end.setMinutes(0) 81 end.setSeconds(0) 82 start.setTime(end.getTime() - 3600 * 1000 * 24) 83 return [start, end] 84 } 85 }, 86 { 87 text: t('logs.aWeekAgo'), 88 value: () => { 89 const end = new Date() 90 const start = new Date() 91 end.setHours(0) 92 end.setMinutes(0) 93 end.setSeconds(0) 94 start.setTime(end.getTime() - 3600 * 1000 * 24 * 7) 95 return [start, end] 96 } 97 } 98 ], 99 onChange: (val: Date[]) => { 100 if (val && val.length > 1) { 101 tableObject.startDate = val[0].toISOString() 102 tableObject.endDate = val[1].toISOString() 103 } else { 104 tableObject.startDate = undefined 105 tableObject.endDate = undefined 106 } 107 wsCache.set(cachePref + 'DateTime', val) 108 wsCache.set(cachePref + 'StartDate', tableObject.startDate) 109 wsCache.set(cachePref + 'EndDate', tableObject.endDate) 110 getList() 111 } 112 }, 113 }, 114 { 115 field: 'levelList', 116 label: t('logs.level'), 117 component: 'CheckboxButton', 118 value: [], 119 colProps: { 120 span: 24 121 }, 122 componentProps: { 123 options: [ 124 { 125 label: 'Emergency', 126 value: 'Emergency' 127 }, 128 { 129 label: 'Alert', 130 value: 'Alert' 131 }, 132 { 133 label: 'Critical', 134 value: 'Critical' 135 }, 136 { 137 label: 'Error', 138 value: 'Error' 139 }, 140 { 141 label: 'Warning', 142 value: 'Warning' 143 }, 144 { 145 label: 'Notice', 146 value: 'Notice' 147 }, 148 { 149 label: 'Info', 150 value: 'Info' 151 }, 152 { 153 label: 'Debug', 154 value: 'Debug' 155 } 156 ] 157 } 158 }, 159 ]) 160 161 const columns: TableColumn[] = [ 162 { 163 field: 'createdAt', 164 label: t('main.createdAt'), 165 type: 'time', 166 sortable: true, 167 width: "170px", 168 formatter: (row: ApiLog) => { 169 return h( 170 'span', 171 parseTime(row.createdAt) 172 ) 173 } 174 }, 175 { 176 field: 'level', 177 label: t('logs.level'), 178 sortable: true, 179 width: "110px" 180 }, 181 { 182 field: 'body', 183 label: t('logs.body') 184 }, 185 { 186 field: 'owner', 187 label: t('logs.owner'), 188 sortable: true, 189 width: "170px" 190 }, 191 ] 192 const paginationObj = ref<Pagination>({ 193 currentPage: wsCache.get(cachePref + 'CurrentPage') || 1, 194 pageSize: wsCache.get(cachePref + 'PageSize') || 100, 195 total: 0, 196 pageSizes: [50, 100, 150, 250], 197 }) 198 const currentID = ref('') 199 200 onMounted(() => { 201 const uuid = new UUID() 202 currentID.value = uuid.getDashFreeUUID() 203 204 setTimeout(() => { 205 stream.subscribe('log', currentID.value, onLogs) 206 }, 1000) 207 }) 208 209 onUnmounted(() => { 210 stream.unsubscribe('log', currentID.value) 211 }) 212 213 const getList = async () => { 214 tableObject.loading = true 215 216 wsCache.set(cachePref + 'CurrentPage', paginationObj.value.currentPage) 217 wsCache.set(cachePref + 'PageSize', paginationObj.value.pageSize) 218 wsCache.set(cachePref + 'Sort', tableObject.sort) 219 wsCache.set(cachePref + 'Query', tableObject.query) 220 221 let params: Params = { 222 page: paginationObj.value.currentPage, 223 limit: paginationObj.value.pageSize, 224 sort: tableObject.sort, 225 query: tableObject.query, 226 startDate: tableObject.startDate, 227 endDate: tableObject.endDate, 228 } 229 230 const res = await api.v1.logServiceGetLogList(params) 231 .catch(() => { 232 }) 233 .finally(() => { 234 tableObject.loading = false 235 }) 236 if (res) { 237 const {items, meta} = res.data; 238 tableObject.tableList = items; 239 // paginationObj.value.pageSize = meta.pagination.limit; 240 paginationObj.value.currentPage = meta.pagination.page; 241 paginationObj.value.total = meta.pagination.total; 242 } else { 243 tableObject.tableList = []; 244 } 245 } 246 247 const onLogs = (log: ApiLog) => { 248 getList() 249 } 250 251 watch( 252 () => paginationObj.value.currentPage, 253 () => { 254 getList() 255 } 256 ) 257 258 watch( 259 () => paginationObj.value.pageSize, 260 () => { 261 getList() 262 } 263 ) 264 265 const sortChange = (data) => { 266 const {column, prop, order} = data; 267 const pref: string = order === 'ascending' ? '+' : '-' 268 tableObject.sort = pref + prop 269 getList() 270 } 271 272 const onFormChange = async () => { 273 const {getFormData} = methods 274 const formData = await getFormData() 275 const {levelList} = formData 276 if (levelList && levelList.length > 0) { 277 tableObject.query = levelList.join(',') 278 } else { 279 tableObject.query = undefined 280 } 281 wsCache.set(cachePref + 'Query', tableObject.query) 282 wsCache.set(cachePref + 'LevelList', levelList) 283 getList() 284 } 285 286 const tableRowClassName = (data) => { 287 const {row, rowIndex} = data 288 let style = '' 289 switch (row.level) { 290 case 'Emergency': 291 style = 'log-emergency' 292 break 293 case 'Alert': 294 style = 'log-alert' 295 break 296 case 'Critical': 297 style = 'log-critical' 298 break 299 case 'Error': 300 style = 'log-error' 301 break 302 case 'Warning': 303 style = 'log-warning' 304 break 305 case 'Notice': 306 style = 'log-notice' 307 break 308 case 'Info': 309 style = 'log-info' 310 break 311 case 'Debug': 312 style = 'log-debug' 313 break 314 } 315 return style 316 } 317 318 const {setValues, setSchema} = methods 319 if (wsCache.get(cachePref + 'DateTime')) { 320 setValues({ 321 dateTime: wsCache.get(cachePref + 'DateTime') 322 }) 323 } 324 if (wsCache.get(cachePref + 'LevelList')) { 325 setValues({ 326 levelList: wsCache.get(cachePref + 'LevelList') 327 }) 328 } 329 330 getList() 331 332 </script> 333 334 <template> 335 <ContentWrap> 336 <Form 337 class="search-form" 338 :schema="schema" 339 label-position="top" 340 label-width="auto" 341 hide-required-asterisk 342 @change="onFormChange" 343 @register="register" 344 /> 345 346 <Table 347 v-model:pageSize="paginationObj.pageSize" 348 v-model:currentPage="paginationObj.currentPage" 349 :columns="columns" 350 :data="tableObject.tableList" 351 :loading="tableObject.loading" 352 :pagination="paginationObj" 353 @sort-change="sortChange" 354 :row-class-name="tableRowClassName" 355 style="width: 100%" 356 class="logsTable" 357 :selection="false" 358 :showUpPagination="20" 359 /> 360 </ContentWrap> 361 362 </template> 363 364 <style lang="less" scoped> 365 366 :deep(.search-form .el-col) { 367 padding-left: 0 !important; 368 padding-right: 0 !important; 369 } 370 371 :deep(.logsTable) { 372 373 .el-table__row { 374 375 td.el-table__cell { 376 padding: 0; 377 border-bottom: none !important; 378 } 379 380 &.log-emergency { 381 --el-table-tr-bg-color: var(--el-color-error-light-5); 382 } 383 384 &.log-alert { 385 --el-table-tr-bg-color: var(--el-color-error-light-5); 386 } 387 388 &.log-critical { 389 --el-table-tr-bg-color: var(--el-color-error-light-5); 390 } 391 392 &.log-error { 393 --el-table-tr-bg-color: var(--el-color-error-light-5); 394 } 395 396 &.log-warning { 397 --el-table-tr-bg-color: var(--el-color-warning-light-5); 398 } 399 400 &.log-notice { 401 --el-table-tr-bg-color: var(--el-color-success-light-5); 402 } 403 404 &.log-info { 405 background-color: inherit; 406 } 407 408 &.log-debug { 409 //background-color: #82aeff; --el-table-tr-bg-color: var(--el-color-info-light-5); 410 } 411 412 } 413 } 414 </style>