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>