|
@@ -1,164 +0,0 @@
|
|
|
-<template>
|
|
|
|
|
- <div class="scroll-wrapper">
|
|
|
|
|
- <div class="statistics-container">
|
|
|
|
|
- <!-- 固定首列 -->
|
|
|
|
|
- <div class="fixed-first">
|
|
|
|
|
- <div class="stat-card">
|
|
|
|
|
- <slot name="first-item" :item="dataList[0]">
|
|
|
|
|
- <div class="card-icon">
|
|
|
|
|
- <component :is="dataList[0].icon" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="card-content">
|
|
|
|
|
- <div>
|
|
|
|
|
- <span class="card-title">{{ dataList[0].title }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div
|
|
|
|
|
- class="card-body"
|
|
|
|
|
- :style="
|
|
|
|
|
- dataList[0].showNoPercent
|
|
|
|
|
- ? 'justify-content: flex-start;'
|
|
|
|
|
- : 'justify-content: space-around;'
|
|
|
|
|
- "
|
|
|
|
|
- >
|
|
|
|
|
- <div>
|
|
|
|
|
- <span class="card-count">{{ formatNumber(dataList[0].value) }}</span>
|
|
|
|
|
- <span class="card-unit">件</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-if="!dataList[0].showNoPercent">
|
|
|
|
|
- <span class="card-count">{{ calculatePercentage(dataList[0].value) }}%</span>
|
|
|
|
|
- <span class="card-unit">占比</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </slot>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <!-- 可滚动内容 -->
|
|
|
|
|
- <div class="scroll-content-wrapper">
|
|
|
|
|
- <div class="scroll-content">
|
|
|
|
|
- <div v-for="(item, index) in dataList.slice(1)" :key="index" class="stat-card">
|
|
|
|
|
- <div class="card-icon">
|
|
|
|
|
- <component :is="item.icon" />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="card-content">
|
|
|
|
|
- <div>
|
|
|
|
|
- <span class="card-title">{{ item.title }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="card-body">
|
|
|
|
|
- <div>
|
|
|
|
|
- <span class="card-count">{{ formatNumber(item.value) }}</span>
|
|
|
|
|
- <span class="card-unit">件</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div>
|
|
|
|
|
- <span class="card-count">{{ calculatePercentage(item.value) }}%</span>
|
|
|
|
|
- <span class="card-unit">占比</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
-</template>
|
|
|
|
|
-
|
|
|
|
|
-<script setup lang="ts">
|
|
|
|
|
-interface DataList {
|
|
|
|
|
- title: string;
|
|
|
|
|
- value: number;
|
|
|
|
|
- icon: string;
|
|
|
|
|
- showNoPercent?: boolean;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-interface IProps {
|
|
|
|
|
- dataList: Array<DataList>;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const props = defineProps<IProps>();
|
|
|
|
|
-
|
|
|
|
|
-const formatNumber = num => {
|
|
|
|
|
- return num.toLocaleString();
|
|
|
|
|
-};
|
|
|
|
|
-const calculatePercentage = value => {
|
|
|
|
|
- const total = props.dataList.reduce((sum, item) => sum + item.value, 0);
|
|
|
|
|
- return total > 0 ? ((value / total) * 100).toFixed(1) : 0;
|
|
|
|
|
-};
|
|
|
|
|
-</script>
|
|
|
|
|
-
|
|
|
|
|
-<style scoped lang="scss">
|
|
|
|
|
-/* 外层容器 */
|
|
|
|
|
-.scroll-wrapper {
|
|
|
|
|
- margin: 15px 0;
|
|
|
|
|
- // padding-bottom: 8px;
|
|
|
|
|
-}
|
|
|
|
|
-/* 主容器 */
|
|
|
|
|
-.statistics-container {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- position: relative;
|
|
|
|
|
-}
|
|
|
|
|
-/* 固定首列 */
|
|
|
|
|
-.fixed-first {
|
|
|
|
|
- position: sticky;
|
|
|
|
|
- left: 0;
|
|
|
|
|
- z-index: 2;
|
|
|
|
|
- margin-left: 0;
|
|
|
|
|
- .stat-card {
|
|
|
|
|
- margin-left: 0;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-/* 可滚动内容的外层容器 */
|
|
|
|
|
-.scroll-content-wrapper {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- overflow-x: auto;
|
|
|
|
|
- -webkit-overflow-scrolling: touch;
|
|
|
|
|
-}
|
|
|
|
|
-/* 可滚动内容 */
|
|
|
|
|
-.scroll-content {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- width: max-content;
|
|
|
|
|
-}
|
|
|
|
|
-/* 卡片通用样式 */
|
|
|
|
|
-.stat-card {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: row;
|
|
|
|
|
- flex-shrink: 0;
|
|
|
|
|
- width: 320px;
|
|
|
|
|
- padding: 16px;
|
|
|
|
|
- margin-left: 12px;
|
|
|
|
|
- background: white;
|
|
|
|
|
- border-radius: 4px;
|
|
|
|
|
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
|
|
|
-}
|
|
|
|
|
-.card-icon {
|
|
|
|
|
- width: 60px;
|
|
|
|
|
- height: 60px;
|
|
|
|
|
- border-radius: 50%;
|
|
|
|
|
- background-color: #f5f7fa;
|
|
|
|
|
- margin-right: 20px;
|
|
|
|
|
-}
|
|
|
|
|
-.card-content {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: column;
|
|
|
|
|
- justify-content: center;
|
|
|
|
|
-}
|
|
|
|
|
-.card-title {
|
|
|
|
|
- font-size: 14px;
|
|
|
|
|
- color: rgb(115, 118, 122);
|
|
|
|
|
-}
|
|
|
|
|
-.card-body {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: row;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: space-around;
|
|
|
|
|
- font-size: 14px;
|
|
|
|
|
- & > div:last-child {
|
|
|
|
|
- margin-left: 10px;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-.card-count {
|
|
|
|
|
- font-size: 20px;
|
|
|
|
|
- margin-right: 10px;
|
|
|
|
|
-}
|
|
|
|
|
-</style>
|
|
|