github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/views/Entities/components/Storage.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, onMounted, onUnmounted, PropType, reactive, ref, unref, watch} from 'vue' 6 import {FormSchema} from "@/types/form"; 7 import {Pagination, TableColumn} from '@/types/table' 8 import api from "@/api/api"; 9 import {UUID} from 'uuid-generator-ts' 10 import {ElButton} from 'element-plus' 11 import {ApiEntity, ApiEntityStorage} from "@/api/stub"; 12 import {useForm} from "@/hooks/web/useForm"; 13 import {parseTime} from "@/utils"; 14 import stream from "@/api/stream"; 15 import {Dialog} from '@/components/Dialog' 16 import {EventStateChange} from "@/api/types"; 17 import {AttributesViewer} from "@/components/Attributes"; 18 import debounce from "lodash.debounce"; 19 20 const {register} = useForm() 21 const {t} = useI18n() 22 const dialogVisible = ref(false) 23 const dialogSource = ref({}) 24 25 interface TableObject { 26 tableList: ApiEntityStorage[] 27 params?: any 28 loading: boolean 29 sort?: string 30 query?: string 31 startDate?: string; 32 endDate?: string; 33 } 34 35 interface Params { 36 page?: number; 37 limit?: number; 38 sort?: string; 39 query?: string; 40 startDate?: string; 41 endDate?: string; 42 entityId?: string; 43 } 44 45 const entityId = ref('') 46 const props = defineProps({ 47 modelValue: { 48 type: Object as PropType<Nullable<ApiEntity>>, 49 default: () => undefined 50 } 51 }) 52 53 watch( 54 () => props.modelValue, 55 (val?: ApiEntity) => { 56 if (val?.id === unref(entityId)) return 57 entityId.value = val?.id || ''; 58 getList() 59 }, 60 ) 61 62 const tableObject = reactive<TableObject>( 63 { 64 tableList: [], 65 loading: false, 66 } 67 ); 68 69 const schema = reactive<FormSchema[]>([ 70 { 71 field: 'dateTime', 72 component: 'DatePicker', 73 label: t('entityStorage.dateTimerange'), 74 colProps: { 75 span: 24 76 }, 77 value: [], 78 componentProps: { 79 type: 'datetimerange', 80 shortcuts: [ 81 { 82 text: t('entityStorage.today'), 83 value: () => { 84 const end = new Date() 85 const start = new Date() 86 start.setTime(start.getTime() - start.getHours() * 3600 * 1000 - start.getMinutes() * 60 * 1000 - start.getSeconds() * 1000) 87 return [start, end] 88 } 89 }, 90 { 91 text: t('entityStorage.yesterday'), 92 value: () => { 93 const end = new Date() 94 const start = new Date() 95 end.setHours(0) 96 end.setMinutes(0) 97 end.setSeconds(0) 98 start.setTime(end.getTime() - 3600 * 1000 * 24) 99 return [start, end] 100 } 101 }, 102 { 103 text: t('entityStorage.aWeekAgo'), 104 value: () => { 105 const end = new Date() 106 const start = new Date() 107 end.setHours(0) 108 end.setMinutes(0) 109 end.setSeconds(0) 110 start.setTime(end.getTime() - 3600 * 1000 * 24 * 7) 111 return [start, end] 112 } 113 } 114 ], 115 onChange: (val: Date[]) => { 116 if (val && val.length > 1) { 117 tableObject.startDate = val[0].toISOString() 118 tableObject.endDate = val[1].toISOString() 119 } else { 120 tableObject.startDate = undefined 121 tableObject.endDate = undefined 122 } 123 getList() 124 } 125 }, 126 }, 127 ]) 128 129 const columns: TableColumn[] = [ 130 { 131 field: 'createdAt', 132 label: t('main.createdAt'), 133 type: 'time', 134 sortable: true, 135 width: "170px", 136 formatter: (row: ApiEntityStorage) => { 137 return h( 138 'span', 139 parseTime(row.createdAt) 140 ) 141 } 142 }, 143 { 144 field: 'state', 145 label: t('entityStorage.state'), 146 sortable: true, 147 width: "200px", 148 }, 149 { 150 field: 'attributes', 151 label: t('entityStorage.attributes'), 152 }, 153 { 154 field: 'entityId', 155 label: t('entityStorage.entityId'), 156 width: "200px", 157 }, 158 ] 159 const paginationObj = ref<Pagination>({ 160 currentPage: 1, 161 pageSize: 100, 162 total: 0, 163 pageSizes: [50, 100, 150, 250], 164 }) 165 const currentID = ref('') 166 167 onMounted(() => { 168 const uuid = new UUID() 169 currentID.value = uuid.getDashFreeUUID() 170 171 setTimeout(() => { 172 stream.subscribe('state_changed', currentID.value, onStateChanged) 173 }, 1000) 174 }) 175 176 onUnmounted(() => { 177 stream.unsubscribe('state_changed', currentID.value) 178 }) 179 180 const getList = async () => { 181 if (!entityId.value) { 182 return 183 } 184 185 tableObject.loading = true 186 187 let params: Params = { 188 page: paginationObj.value.currentPage, 189 limit: paginationObj.value.pageSize, 190 sort: tableObject.sort, 191 startDate: tableObject.startDate, 192 endDate: tableObject.endDate, 193 entityId: [entityId.value], 194 } 195 196 const res = await api.v1.entityStorageServiceGetEntityStorageList(params) 197 .catch(() => { 198 }) 199 .finally(() => { 200 tableObject.loading = false 201 }) 202 if (res) { 203 const {items, meta} = res.data; 204 tableObject.tableList = items; 205 paginationObj.value.pageSize = meta.pagination.limit; 206 paginationObj.value.currentPage = meta.pagination.page; 207 paginationObj.value.total = meta.pagination.total; 208 } else { 209 tableObject.tableList = []; 210 } 211 } 212 213 const getList2 = debounce(() => { 214 getList() 215 }, 1000) 216 217 const onStateChanged = (event: EventStateChange) => { 218 if (event.entity_id != entityId.value) { 219 return; 220 } 221 222 getList2() 223 } 224 225 watch( 226 () => [paginationObj.value.pageSize, paginationObj.value.currentPage], 227 () => { 228 getList() 229 } 230 ) 231 232 const sortChange = (data) => { 233 const {column, prop, order} = data; 234 const pref: string = order === 'ascending' ? '+' : '-' 235 tableObject.sort = pref + prop 236 getList() 237 } 238 239 const onFormChange = async () => { 240 getList() 241 } 242 243 const selectRow = (row: ApiEntityStorage) => { 244 if (!row) return; 245 dialogSource.value = row?.attributes 246 dialogVisible.value = true 247 } 248 249 getList() 250 251 </script> 252 253 <template> 254 255 <Dialog v-model="dialogVisible" :maxHeight="400" width="80%"> 256 <div style="padding: 10px"> 257 <AttributesViewer v-model="dialogSource"/> 258 </div> 259 <template #footer> 260 <ElButton @click="dialogVisible = false">{{ t('main.closeDialog') }}</ElButton> 261 </template> 262 </Dialog> 263 264 <Form 265 :schema="schema" 266 label-position="top" 267 label-width="auto" 268 hide-required-asterisk 269 @change="onFormChange" 270 @register="register" 271 /> 272 273 <Table 274 v-model:pageSize="paginationObj.pageSize" 275 v-model:currentPage="paginationObj.currentPage" 276 :columns="columns" 277 :data="tableObject.tableList" 278 :loading="tableObject.loading" 279 :pagination="paginationObj" 280 @sort-change="sortChange" 281 style="width: 100%" 282 class="storageTable" 283 :selection="false" 284 :showUpPagination="20" 285 @current-change="selectRow" 286 > 287 <template #attributes="{row}"> 288 <span>{{ Object.keys(row.attributes).length || $t('entityStorage.nothing') }}</span> 289 </template> 290 </Table> 291 292 </template> 293 294 <style lang="less"> 295 296 </style>