Переглянути джерело

feature 回收书单统计页面接口对接

ylong 6 місяців тому
батько
коміт
4ddf9a5a74

+ 2 - 2
src/components/CommonPage/CommonStatistics.vue

@@ -7,7 +7,7 @@
             :options="options"
             :precision="2"
         />
-        <ele-text>{{ title }}</ele-text>
+        <ele-text class="text-20">{{ title }}</ele-text>
     </div>
 </template>
 
@@ -23,7 +23,7 @@
         },
         valueStyle: {
             type: Object,
-            default: () => ({ fontSize: '28px', color: '#67C23A' })
+            default: () => ({ fontSize: '40px', color: '#67C23A' })
         },
         options: {
             type: Object,

+ 53 - 15
src/views/recycle/booklistStat/components/book-recycle-rate.vue

@@ -2,11 +2,12 @@
     <v-chart
         class="flex-1"
         ref="saleChartRef"
-        style="height: 420px"
+        style="height: 380px"
         :option="options"
     />
 </template>
 <script setup>
+    import { computed } from 'vue';
     import VChart from 'vue-echarts';
     import { use } from 'echarts/core';
     import { CanvasRenderer } from 'echarts/renderers';
@@ -28,9 +29,16 @@
         TitleComponent
     ]);
 
-    const options = reactive({
+    const props = defineProps({
+        data: {
+            type: Object,
+            default: () => ({})
+        }
+    });
+
+    const options = computed(() => ({
         title: {
-            text: '多本回收占比',
+            text: '单个订单多本回收占比',
             textStyle: {
                 color: '#363636',
                 fontSize: 14,
@@ -38,26 +46,56 @@
             }
         },
         legend: {
-            right: 'right',
-            orient: 'vertical',
-            top: 'center'
+            bottom: 'bottom',
+            orient: 'horizontal',
+            itemGap: 20,
+            textStyle: {
+                fontSize: 12
+            }
+        },
+        tooltip: {
+            trigger: 'item',
+            formatter: '{a} <br/>{b}: {c} ({d}%)'
         },
         series: [
             {
-                name: '多本回收占比',
+                name: '单个订单多本回收占比',
                 type: 'pie',
-                radius: [50, 150],
-                center: ['50%', '50%'],
-                roseType: 'area',
+                radius: [50, 100],
+                center: ['50%', '45%'],
+                avoidLabelOverlap: false,
                 itemStyle: {
-                    borderRadius: 8
+                    borderRadius: 4
+                },
+                label: {
+                    show: true,
+                    position: 'outside',
+                    formatter: function(params) {
+                        return params.name + '\n' + params.value;
+                    },
+                    fontSize: 12,
+                    lineHeight: 14
+                },
+                emphasis: {
+                    label: {
+                        show: true,
+                        fontSize: '14',
+                        fontWeight: 'bold'
+                    }
                 },
                 data: [
-                    { value: 40, name: '中等' },
-                    { value: 38, name: '良好' },
-                    { value: 32, name: '极差' }
+                    { 
+                        value: props.data.bookOrderNumMoreOne || 0, 
+                        name: '是',
+                        itemStyle: { color: '#409EFF' }
+                    },
+                    { 
+                        value: props.data.bookOrderNumEqualOne || 0, 
+                        name: '否',
+                        itemStyle: { color: '#20B2AA' }
+                    }
                 ]
             }
         ]
-    });
+    }));
 </script>

+ 61 - 14
src/views/recycle/booklistStat/components/recycle-discount-rate.vue

@@ -2,11 +2,12 @@
     <v-chart
         class="flex-1"
         ref="saleChartRef"
-        style="height: 420px"
+        style="height: 380px"
         :option="options"
     />
 </template>
 <script setup>
+    import { computed } from 'vue';
     import VChart from 'vue-echarts';
     import { use } from 'echarts/core';
     import { CanvasRenderer } from 'echarts/renderers';
@@ -28,7 +29,14 @@
         TitleComponent
     ]);
 
-    const options = reactive({
+    const props = defineProps({
+        data: {
+            type: Object,
+            default: () => ({})
+        }
+    });
+
+    const options = computed(() => ({
         title: {
             text: '回收折扣占比',
             textStyle: {
@@ -38,27 +46,66 @@
             }
         },
         legend: {
-            right: 'right',
-            orient: 'vertical',
-            top: 'center'
+            bottom: 'bottom',
+            orient: 'horizontal',
+            itemGap: 20,
+            textStyle: {
+                fontSize: 12
+            }
+        },
+        tooltip: {
+            trigger: 'item',
+            formatter: '{a} <br/>{b}: {c} ({d}%)'
         },
         series: [
             {
                 name: '回收折扣占比',
                 type: 'pie',
-                radius: [50, 150],
-                center: ['50%', '50%'],
-                roseType: 'area',
+                radius: [50, 100],
+                center: ['50%', '45%'],
+                avoidLabelOverlap: false,
                 itemStyle: {
-                    borderRadius: 8
+                    borderRadius: 4
+                },
+                label: {
+                    show: true,
+                    position: 'outside',
+                    formatter: function(params) {
+                        return params.name + '\n' + params.value;
+                    },
+                    fontSize: 12,
+                    lineHeight: 14
+                },
+                emphasis: {
+                    label: {
+                        show: true,
+                        fontSize: '14',
+                        fontWeight: 'bold'
+                    }
                 },
                 data: [
-                    { value: 40, name: '≥2折' },
-                    { value: 38, name: '2<至≥1' },
-                    { value: 32, name: '1<至≥0.5' },
-                    { value: 30, name: '≤0.5' }
+                    { 
+                        value: props.data.recycleDiscount4 || 0, 
+                        name: '≥2折',
+                        itemStyle: { color: '#409EFF' }
+                    },
+                    { 
+                        value: props.data.recycleDiscount3 || 0, 
+                        name: '2<至≥1',
+                        itemStyle: { color: '#20B2AA' }
+                    },
+                    { 
+                        value: props.data.recycleDiscount2 || 0, 
+                        name: '1<至≥0.5',
+                        itemStyle: { color: '#67C23A' }
+                    },
+                    { 
+                        value: props.data.recycleDiscount1 || 0, 
+                        name: '≤0.5',
+                        itemStyle: { color: '#E6A23C' }
+                    }
                 ]
             }
         ]
-    });
+    }));
 </script>

+ 116 - 0
src/views/recycle/booklistStat/components/recycle-proportion.vue

@@ -0,0 +1,116 @@
+<template>
+    <v-chart
+        class="flex-1"
+        ref="saleChartRef"
+        style="height: 380px"
+        :option="options"
+    />
+</template>
+<script setup>
+    import { computed } from 'vue';
+    import VChart from 'vue-echarts';
+    import { use } from 'echarts/core';
+    import { CanvasRenderer } from 'echarts/renderers';
+    import { PieChart } from 'echarts/charts';
+    import {
+        GridComponent,
+        TooltipComponent,
+        LegendComponent,
+        TitleComponent
+    } from 'echarts/components';
+
+    // 按需加载echarts
+    use([
+        CanvasRenderer,
+        PieChart,
+        GridComponent,
+        TooltipComponent,
+        LegendComponent,
+        TitleComponent
+    ]);
+
+    const props = defineProps({
+        data: {
+            type: Object,
+            default: () => ({})
+        }
+    });
+
+    const options = computed(() => ({
+        title: {
+            text: '回收占比',
+            textStyle: {
+                color: '#363636',
+                fontSize: 14,
+                fontWeight: 'normal'
+            }
+        },
+        legend: {
+            bottom: 'bottom',
+            orient: 'horizontal',
+            itemGap: 20,
+            textStyle: {
+                fontSize: 12
+            }
+        },
+        tooltip: {
+            trigger: 'item',
+            formatter: '{a} <br/>{b}: {c} ({d}%)'
+        },
+        series: [
+            {
+                name: '回收占比',
+                type: 'pie',
+                radius: [50, 100],
+                center: ['50%', '45%'],
+                avoidLabelOverlap: false,
+                itemStyle: {
+                    borderRadius: 4
+                },
+                label: {
+                    show: true,
+                    position: 'outside',
+                    formatter: function(params) {
+                        return params.name + '\n' + params.value;
+                    },
+                    fontSize: 12,
+                    lineHeight: 14
+                },
+                emphasis: {
+                    label: {
+                        show: true,
+                        fontSize: '14',
+                        fontWeight: 'bold'
+                    }
+                },
+                data: [
+                    { 
+                        value: props.data.recycleingNum || 0, 
+                        name: '已加入回收书单 (正在回收)',
+                        itemStyle: { color: '#409EFF' }
+                    },
+                    { 
+                        value: props.data.notInListNum || 0, 
+                        name: '未加入回收书单',
+                        itemStyle: { color: '#20B2AA' }
+                    },
+                    { 
+                        value: props.data.blackNum || 0, 
+                        name: '黑名单',
+                        itemStyle: { color: '#67C23A' }
+                    },
+                    { 
+                        value: props.data.fullPauseNum || 0, 
+                        name: '已加入回收书单 (收满暂停)',
+                        itemStyle: { color: '#E6A23C' }
+                    },
+                    { 
+                        value: props.data.pauseNum || 0, 
+                        name: '已加入回收书单 (手动暂停)',
+                        itemStyle: { color: '#F56C6C' }
+                    }
+                ]
+            }
+        ]
+    }));
+</script> 

+ 77 - 32
src/views/recycle/booklistStat/index.vue

@@ -1,50 +1,95 @@
 <template>
     <ele-page flex-table>
         <ele-card flex-table>
-            <div class="flex justify-center">
-                <div class="flex gap-6">
-                    <div class="common-section">
-                        <CommonStatistics
-                            title="开放回收种类(种)"
-                            :value="565621"
-                        />
+            <div v-if="loading" class="flex justify-center items-center h-64">
+                <ele-loading />
+            </div>
+            <div v-else>
+                <div class="flex justify-center mb-12">
+                    <div class="flex gap-8">
+                        <div class="common-section">
+                            <CommonStatistics
+                                title="开放回收种类(种)"
+                                :value="statData.recycleingBookNum || 0"
+                            />
+                        </div>
+                        <div class="common-section">
+                            <CommonStatistics
+                                title="单本回收均价(元)"
+                                :value="statData.averagePrice || 0"
+                                :options="{ decimalPlaces: 2 }"
+                            />
+                        </div>
+                        <div class="common-section">
+                            <CommonStatistics
+                                title="回收本数(本)"
+                                :value="statData.recycleBookNum || 0"
+                            />
+                        </div>
+                        <div class="common-section">
+                            <CommonStatistics
+                                title="无数据图书(本)"
+                                :value="statData.noDateBook || 0"
+                            />
+                        </div>
                     </div>
-                    <div class="common-section">
-                        <CommonStatistics
-                            title="单本回收均价(元)"
-                            :value="2.4"
-                            :options="{ decimalPlaces: 2 }"
-                        />
+                </div>
+
+                <div class="flex gap-6">
+                    <div class="flex-1">
+                        <el-card shadow="hover">
+                            <bookRecycleRate :data="statData" />
+                        </el-card>
                     </div>
-                    <div class="common-section">
-                        <CommonStatistics
-                            title="回收本数(本)"
-                            :value="454445"
-                        />
+                    <div class="flex-1">
+                        <el-card shadow="hover">
+                            <recycleDiscountRate :data="statData" />
+                        </el-card>
                     </div>
-                    <div class="common-section">
-                        <CommonStatistics
-                            title="无数据图书(本)"
-                            :value="5621"
-                        />
+                    <div class="flex-1">
+                        <el-card shadow="hover">
+                            <recycleProportion :data="statData" />
+                        </el-card>
                     </div>
                 </div>
             </div>
-
-            <div class="flex mt-12 gap-8">
-                <div class="flex-1">
-                    <bookRecycleRate />
-                </div>
-                <div class="flex-1">
-                    <recycleDiscountRate />
-                </div>
-            </div>
         </ele-card>
     </ele-page>
 </template>
 
 <script setup>
+    import { ref, onMounted } from 'vue';
     import CommonStatistics from '@/components/CommonPage/CommonStatistics.vue';
     import recycleDiscountRate from '@/views/recycle/booklistStat/components/recycle-discount-rate.vue';
     import bookRecycleRate from '@/views/recycle/booklistStat/components/book-recycle-rate.vue';
+    import recycleProportion from '@/views/recycle/booklistStat/components/recycle-proportion.vue';
+    import request from '@/utils/request';
+
+    const statData = ref({});
+    const loading = ref(false);
+
+    const fetchBookListStat = async () => {
+        loading.value = true;
+        try {
+            const res = await request.get('/book/bookRecycleInfo/stat/bookRecycleStat');
+            if (res.data.code === 200) {
+                statData.value = res.data.data;
+            }
+        } catch (error) {
+            console.error('获取统计数据失败:', error);
+        } finally {
+            loading.value = false;
+        }
+    };
+
+    onMounted(() => {
+        fetchBookListStat();
+    });
 </script>
+
+<style scoped>
+.common-section {
+    min-width: 160px;
+    text-align: center;
+}
+</style>