github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/views/Automation/Triggers/index.vue (about) 1 <script setup lang="ts"> 2 import {useI18n} from '@/hooks/web/useI18n' 3 import {Table} from '@/components/Table' 4 import {h, onMounted, onUnmounted, reactive, ref, watch} from 'vue' 5 import {Pagination, TableColumn} from '@/types/table' 6 import api from "@/api/api"; 7 import {ElButton, ElMessage, ElTag} from 'element-plus' 8 import {ApiTrigger} from "@/api/stub"; 9 import {useRouter} from "vue-router"; 10 import {ContentWrap} from "@/components/ContentWrap"; 11 import {parseTime} from "@/utils"; 12 import {EventStateChange, EventTriggerCompleted} from "@/api/types"; 13 import {UUID} from "uuid-generator-ts"; 14 import stream from "@/api/stream"; 15 import {useCache} from "@/hooks/web/useCache"; 16 17 const {push} = useRouter() 18 const {t} = useI18n() 19 const {wsCache} = useCache() 20 21 interface TableObject { 22 tableList: ApiTrigger[] 23 params?: any 24 loading: boolean 25 sort?: string 26 } 27 28 interface Params { 29 page?: number; 30 limit?: number; 31 sort?: string; 32 } 33 34 const cachePref = 'triggers' 35 const tableObject = reactive<TableObject>( 36 { 37 tableList: [], 38 loading: false, 39 sort: wsCache.get(cachePref + 'Sort') || '-createdAt' 40 } 41 ); 42 43 const currentID = ref('') 44 45 const onStateChanged = (event: EventStateChange) => { 46 getList() 47 } 48 49 const onEventTriggerActivated = (event: EventTriggerCompleted) => { 50 for (const i in tableObject.tableList) { 51 if (tableObject.tableList[i].id == event.id) { 52 tableObject.tableList[i].completed = true; 53 setTimeout(() => { 54 tableObject.tableList[i].completed = false 55 }, 500) 56 return 57 } 58 } 59 } 60 61 onMounted(() => { 62 const uuid = new UUID() 63 currentID.value = uuid.getDashFreeUUID() 64 65 setTimeout(() => { 66 stream.subscribe('event_trigger_loaded', currentID.value, onStateChanged); 67 stream.subscribe('event_trigger_unloaded', currentID.value, onStateChanged); 68 stream.subscribe('event_trigger_completed', currentID.value, onEventTriggerActivated); 69 }, 1000) 70 }) 71 72 onUnmounted(() => { 73 stream.unsubscribe('event_trigger_loaded', currentID.value); 74 stream.unsubscribe('event_trigger_unloaded', currentID.value); 75 stream.unsubscribe('event_trigger_completed', currentID.value); 76 }) 77 78 const columns: TableColumn[] = [ 79 { 80 field: 'id', 81 label: t('automation.triggers.id'), 82 sortable: true, 83 width: "60px" 84 }, 85 { 86 field: 'name', 87 label: t('automation.triggers.name'), 88 sortable: true, 89 width: "170px" 90 }, 91 { 92 field: 'areaId', 93 label: t('automation.area'), 94 width: "100px", 95 sortable: true, 96 formatter: (row: ApiTrigger) => { 97 return h( 98 'span', 99 row.area?.name 100 ) 101 } 102 }, 103 { 104 field: 'pluginName', 105 label: t('automation.triggers.pluginName'), 106 sortable: true, 107 }, 108 { 109 field: 'description', 110 label: t('automation.description'), 111 sortable: true, 112 formatter: (row: ApiTrigger) => { 113 return h( 114 'span', 115 row?.description || t('automation.nothing') 116 ) 117 } 118 }, 119 { 120 field: 'operations', 121 label: t('automation.triggers.operations'), 122 width: "100px", 123 }, 124 { 125 field: 'status', 126 label: t('entities.status'), 127 width: "70px", 128 }, 129 { 130 field: 'createdAt', 131 label: t('main.createdAt'), 132 type: 'time', 133 sortable: true, 134 width: "170px", 135 formatter: (row: ApiTrigger) => { 136 return h( 137 'span', 138 parseTime(row.createdAt) 139 ) 140 } 141 }, 142 { 143 field: 'updatedAt', 144 label: t('main.updatedAt'), 145 type: 'time', 146 sortable: true, 147 width: "170px", 148 formatter: (row: ApiTrigger) => { 149 return h( 150 'span', 151 parseTime(row.updatedAt) 152 ) 153 } 154 }, 155 ] 156 const paginationObj = ref<Pagination>({ 157 currentPage: wsCache.get(cachePref + 'CurrentPage') || 1, 158 pageSize: wsCache.get(cachePref + 'PageSize') || 50, 159 total: 0, 160 pageSizes: [50, 100, 150, 250], 161 }) 162 163 const getList = async () => { 164 tableObject.loading = true 165 166 wsCache.set(cachePref + 'CurrentPage', paginationObj.value.currentPage) 167 wsCache.set(cachePref + 'PageSize', paginationObj.value.pageSize) 168 wsCache.set(cachePref + 'Sort', tableObject.sort) 169 170 let params: Params = { 171 page: paginationObj.value.currentPage, 172 limit: paginationObj.value.pageSize, 173 sort: tableObject.sort, 174 } 175 176 const res = await api.v1.triggerServiceGetTriggerList(params) 177 .catch(() => { 178 }) 179 .finally(() => { 180 tableObject.loading = false 181 }) 182 if (res) { 183 const {items, meta} = res.data; 184 tableObject.tableList = items; 185 paginationObj.value.currentPage = meta.pagination.page; 186 paginationObj.value.total = meta.pagination.total; 187 } else { 188 tableObject.tableList = []; 189 } 190 } 191 192 watch( 193 () => paginationObj.value.currentPage, 194 () => { 195 getList() 196 } 197 ) 198 199 watch( 200 () => paginationObj.value.pageSize, 201 () => { 202 getList() 203 } 204 ) 205 206 const sortChange = (data) => { 207 const {column, prop, order} = data; 208 const pref: string = order === 'ascending' ? '+' : '-' 209 tableObject.sort = pref + prop 210 getList() 211 } 212 213 getList() 214 215 const addNew = () => { 216 push('/automation/triggers/new') 217 } 218 219 220 const selectRow = (row) => { 221 if (!row) { 222 return 223 } 224 const {id} = row 225 push(`/automation/triggers/edit/${id}`) 226 } 227 228 const enable = async (trigger: ApiTrigger) => { 229 if (!trigger?.id) return; 230 await api.v1.triggerServiceEnableTrigger(trigger.id); 231 ElMessage({ 232 title: t('Success'), 233 message: t('message.requestSentSuccessfully'), 234 type: 'success', 235 duration: 2000 236 }); 237 } 238 239 const disable = async (trigger: ApiTrigger) => { 240 if (!trigger?.id) return; 241 await api.v1.triggerServiceDisableTrigger(trigger.id); 242 ElMessage({ 243 title: t('Success'), 244 message: t('message.requestSentSuccessfully'), 245 type: 'success', 246 duration: 2000 247 }); 248 } 249 250 const tableRowClassName = (data) => { 251 const {row, rowIndex} = data 252 let style = '' 253 if (row.completed) { 254 style = 'completed' 255 } 256 return style 257 } 258 259 const callTrigger = async (trigger: ApiTrigger) => { 260 if (!trigger?.id) return; 261 await api.v1.developerToolsServiceCallTrigger({id: trigger.id}) 262 .catch(() => { 263 }) 264 .finally(() => { 265 ElMessage({ 266 title: t('Success'), 267 message: t('message.callSuccessful'), 268 type: 'success', 269 duration: 2000 270 }) 271 }) 272 } 273 274 </script> 275 276 <template> 277 <ContentWrap> 278 <ElButton class="flex mb-20px items-left" type="primary" @click="addNew()" plain> 279 <Icon icon="ep:plus" class="mr-5px"/> 280 {{ t('automation.triggers.addNew') }} 281 </ElButton> 282 283 <Table 284 :selection="false" 285 v-model:pageSize="paginationObj.pageSize" 286 v-model:currentPage="paginationObj.currentPage" 287 :columns="columns" 288 :data="tableObject.tableList" 289 :loading="tableObject.loading" 290 :pagination="paginationObj" 291 @sort-change="sortChange" 292 :row-class-name="tableRowClassName" 293 style="width: 100%" 294 :showUpPagination="20" 295 > 296 <template #name="{ row }"> 297 <span @click.prevent.stop="selectRow(row)" style="cursor: pointer"> 298 {{ row.name }} 299 </span> 300 </template> 301 302 <template #pluginName="{row}"> 303 <ElTag> 304 {{ row.pluginName }} 305 </ElTag> 306 </template> 307 308 <template #operations="{ row }"> 309 310 <ElButton :link="true" @click.prevent.stop="callTrigger(row)" :disabled="!row?.isLoaded"> 311 {{ $t('main.call') }} 312 </ElButton> 313 314 </template> 315 316 <template #status="{ row }"> 317 <div class="w-[100%] text-center"> 318 <ElButton :link="true" @click.prevent.stop="enable(row)" v-if="!row?.isLoaded"> 319 <Icon icon="noto:red-circle" class="mr-5px"/> 320 </ElButton> 321 <ElButton :link="true" @click.prevent.stop="disable(row)" v-if="row?.isLoaded"> 322 <Icon icon="noto:green-circle" class="mr-5px"/> 323 </ElButton> 324 </div> 325 </template> 326 327 </Table> 328 329 </ContentWrap> 330 331 </template> 332 333 <style lang="less"> 334 335 .light { 336 .el-table__row { 337 &.completed { 338 --el-table-tr-bg-color: var(--el-color-primary-light-7); 339 -webkit-transition: background-color 200ms linear; 340 -ms-transition: background-color 200ms linear; 341 transition: background-color 200ms linear; 342 } 343 } 344 } 345 346 .dark { 347 .el-table__row { 348 &.completed { 349 --el-table-tr-bg-color: var(--el-color-primary-dark-2); 350 -webkit-transition: background-color 200ms linear; 351 -ms-transition: background-color 200ms linear; 352 transition: background-color 200ms linear; 353 } 354 } 355 } 356 357 </style>