wangzhibo
6 天以前 7bd866831780abcf5a59c4cbb7d1be456eea7c99
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<template>
    <div class="category-ratio">
        <div class="card">
            <div class="card__header">
                <span class="label">销售类别占比</span>
 
                <el-icon class="more" @click="router.push('/goods/category')">
                    <arrow-right-bold />
                </el-icon>
            </div>
 
            <div class="card__container">
                <v-chart :option="chartOption" autoresize />
            </div>
        </div>
    </div>
</template>
 
<script lang="ts" setup>
import { onMounted, reactive, ref } from "vue";
import { useCool } from "/@/cool";
import { ArrowRightBold } from "@element-plus/icons-vue";
import { orderBy } from "lodash-es";
 
const { service, router } = useCool();
 
const list = ref<{ typeName: string; total: number }[]>([]);
 
const chartOption = reactive({
    legend: {
        top: 50,
        left: 15,
        orient: "vertical",
        icon: "circle",
        data: [] as string[],
        formatter(name: string) {
            const d = list.value.find((e) => e.typeName === name);
 
            return `${d?.typeName}(${d?.total})`;
        }
    },
 
    series: [
        {
            type: "pie",
            padAngle: 5,
            radius: ["45%", "60%"],
            center: ["75%", "55%"],
            avoidLabelOverlap: false,
            label: {
                show: false,
                position: "center"
            },
            emphasis: {
                label: {
                    show: true,
                    fontSize: "15",
                    fontWeight: "bold"
                }
            },
            labelLine: {
                show: false
            },
            data: [] as any[],
            itemStyle: {
                borderColor: "#fff",
                borderWidth: 2,
                borderRadius: 4
            }
        }
    ]
});
 
onMounted(() => {
    service.count.home
        .goodsCategory({
            type: "count"
        })
        .then((res: any[]) => {
            // 倒序
            const arr = orderBy(res, "total", "desc").map((e) => {
                return {
                    ...e,
                    total: Number(e.total)
                };
            });
 
            // 前5个先
            const rank = arr.filter((_, i) => i < 5);
 
            // 合并其他
            const other = {
                typeName: "其他",
                total: arr.splice(5).reduce((a, b) => a + b.total, 0)
            };
 
            list.value = [...rank, other];
 
            // 设置图例
            chartOption.legend.data = list.value.map((e) => e.typeName);
 
            // 设置数据
            chartOption.series[0].data = list.value.map((e) => {
                return {
                    value: e.total,
                    name: e.typeName
                };
            });
        });
});
</script>
 
<style lang="scss" scoped>
.category-ratio {
    position: relative;
 
    .echarts {
        height: 150px;
        position: absolute;
        right: 0;
        top: 0;
    }
 
    .card__container {
        height: 100px;
    }
}
</style>