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