github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/components/Statistics/Statistics.vue (about) 1 <script setup lang="ts"> 2 import {computed, PropType, ref, unref, watch} from 'vue' 3 import {ElCol, ElRow, ElStatistic} from 'element-plus' 4 import {ApiStatistic, ApiStatistics} from "@/api/stub"; 5 import {propTypes} from "@/utils/propTypes"; 6 import {useAppStore} from "@/store/modules/app"; 7 8 const appStore = useAppStore() 9 10 const statistic = ref<Statistic>({items: []}) 11 const rowGutter = ref(24) 12 const colSpan = ref(8) 13 14 const apiStatistics = ref<Nullable<ApiStatistics>>(null) 15 16 const isDark = computed(() => appStore.getIsDark) 17 18 interface Statistic { 19 items: ApiStatistic[][]; 20 } 21 22 const darkPalette = [ 23 'linear-gradient(rgb(61, 73, 46) 0%, rgb(38, 56, 39) 100%)', 24 'linear-gradient(rgb(40, 73, 145) 0%, rgb(18, 43, 98) 100%)', 25 'linear-gradient(rgb(49, 37, 101) 0%, rgb(32, 25, 54) 100%)', 26 'linear-gradient(#457b9d 0%, #30556d 100%)', 27 'linear-gradient(#dda15e 0%, #78562f 100%)', 28 'linear-gradient(#40916c 0%, #255640 100%)' 29 ] 30 31 const lightPalette = [ 32 'linear-gradient(rgb(78 133 9) 0%, rgb(63 115 66) 100%)', 33 'linear-gradient(rgb(40, 73, 145) 0%, rgb(18, 43, 98) 100%)', 34 'linear-gradient(rgb(49, 37, 101) 0%, rgb(32, 25, 54) 100%)', 35 'linear-gradient(#457b9d 0%, #30556d 100%)', 36 'linear-gradient(#dda15e 0%, #78562f 100%)', 37 'linear-gradient(#40916c 0%, #255640 100%)' 38 ] 39 40 const props = defineProps({ 41 modelValue: { 42 type: Object as PropType<Nullable<ApiStatistics>>, 43 default: () => null 44 }, 45 cols: propTypes.number.def(3), 46 }) 47 48 watch( 49 () => props.cols, 50 (val?: number) => { 51 colSpan.value = rowGutter.value / val 52 } 53 ) 54 55 watch( 56 () => props.modelValue, 57 (val?: ApiStatistics) => { 58 if (val === unref(apiStatistics)) return; 59 apiStatistics.value = val || null; 60 const items = val?.items || []; 61 let row = 0; 62 statistic.value.items = [] 63 for (const index in val?.items) { 64 row = Math.floor(index / props.cols) 65 if (!statistic.value.items[row]) { 66 statistic.value.items[row] = [] 67 } 68 statistic.value.items[row].push(items[index]) 69 } 70 }, 71 ) 72 73 const getStyle = (index, index2) => { 74 return {'background': isDark.value ? darkPalette[index2] : lightPalette[index2]} 75 } 76 77 </script> 78 79 <template> 80 <div class="ml-20px mr-20px" v-if="statistic"> 81 <ElRow :gutter="rowGutter" v-for="(cols, $index) in statistic.items" :key="$index"> 82 <ElCol :span="colSpan" v-for="(col, $index2) in cols" :key="$index2" class="mt-20px"> 83 <div class="statistic-card" :style="getStyle($index, $index2)"> 84 <ElStatistic :value="col.value"> 85 <template #title> 86 <div style="display: inline-flex; align-items: center"> 87 {{ $t(col.name) }} 88 </div> 89 </template> 90 </ElStatistic> 91 </div> 92 </ElCol> 93 </ElRow> 94 </div> 95 </template> 96 97 <style lang="less"> 98 99 .el-statistic { 100 --el-statistic-content-font-size: 28px; 101 } 102 103 .statistic-card { 104 height: 100%; 105 padding: 20px; 106 border-radius: 4px; 107 background-color: var(--el-bg-color-overlay); 108 } 109 110 .statistic-footer { 111 display: flex; 112 justify-content: space-between; 113 align-items: center; 114 flex-wrap: wrap; 115 font-size: 12px; 116 color: var(--el-text-color-regular); 117 margin-top: 16px; 118 } 119 120 .statistic-footer .footer-item { 121 display: flex; 122 justify-content: space-between; 123 align-items: center; 124 } 125 126 .statistic-footer .footer-item span:last-child { 127 display: inline-flex; 128 align-items: center; 129 margin-left: 4px; 130 } 131 132 .green { 133 color: var(--el-color-success); 134 } 135 136 .red { 137 color: var(--el-color-error); 138 } 139 140 .el-statistic__head { 141 color: #bbb; 142 } 143 144 .el-statistic__content { 145 color: #fff; 146 } 147 </style>