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