| | |
| | | <affixTime @selected="clickBreadcrumb" /> |
| | | </Card> |
| | | </Affix> |
| | | |
| | | <Card class="card"> |
| | | <div class="chart-wrapper"> |
| | | <div class="chart-header"> |
| | |
| | | <div class="my-chart-container"> |
| | | <div class="chart-wrapper" style="height: 800px"> |
| | | <div class="chart-header"> |
| | | <h2>商品/视频浏览量完播率 趋势图</h2> |
| | | <h2>商品/视频浏览量完播率 排名图</h2> |
| | | </div> |
| | | <div class="button-group-wrapper"> |
| | | <!-- 第一组:商品/视频(靠左) --> |
| | |
| | | </div> |
| | | </div> |
| | | </Card> |
| | | |
| | | <Card class="card"> |
| | | <div class="my-chart-container"> |
| | | <div class="chart-wrapper"> |
| | |
| | | <div ref="orderTimePeriodChartDom" class="chart-container"></div> |
| | | </div> |
| | | </div> |
| | | |
| | | </Card> |
| | | <Card class="card"> |
| | | <div class="my-chart-container"> |
| | | <div class="chart-wrapper" style="height: 800px"> |
| | | <div class="chart-header"> |
| | | <h2>商品复购率 排名图</h2> |
| | | </div> |
| | | <div class="button-group-wrapper"> |
| | | <!-- 页面样式需要 --> |
| | | <div></div> |
| | | <ButtonGroup> |
| | | <Button |
| | | :type="repurchaseCurrentLimit === 10 ? 'success' : 'default'" |
| | | @click="handleRepurchaseLimitChange(10)" |
| | | > |
| | | 前10 |
| | | </Button> |
| | | <Button |
| | | :type="repurchaseCurrentLimit === 20 ? 'success' : 'default'" |
| | | @click="handleRepurchaseLimitChange(20)" |
| | | > |
| | | 前20 |
| | | </Button> |
| | | <Button |
| | | :type="repurchaseCurrentLimit === 30 ? 'success' : 'default'" |
| | | @click="handleRepurchaseLimitChange(30)" |
| | | > |
| | | 前30 |
| | | </Button> |
| | | </ButtonGroup> |
| | | </div> |
| | | <div ref="productRepurchaseRateChartDom" class="repurchase-chart-container"></div> |
| | | </div> |
| | | </div> |
| | | </Card> |
| | | |
| | | |
| | |
| | | import refundRow from "./order/refundOrder"; |
| | | import affixTime from "@/components/affix-time"; |
| | | import * as echarts from 'echarts'; |
| | | import {pvUvData,getOrderCount,getViewAndCompletionRateCount,getOrderTimePeriod} from "../../api/orderStatistics"; |
| | | import {pvUvData,getOrderCount,getViewAndCompletionRateCount,getOrderTimePeriod,gerProductRepurchase} from "../../api/orderStatistics"; |
| | | |
| | | export default { |
| | | components: { orderRow, refundRow, affixTime }, |
| | |
| | | // 图表实例 |
| | | chart: null, //pvuv |
| | | orderCountChart:null, //订单日趋势 |
| | | viewPrintChart:null, |
| | | orderTimePeriodChart:null, |
| | | viewPrintChart:null, //完播率 |
| | | orderTimePeriodChart:null, //订单/浏览时间 |
| | | productRepurchaseRateChart:null,//商品复购率 |
| | | |
| | | currentType:"goods", |
| | | currentLimit:10, |
| | | |
| | | repurchaseCurrentLimit:10, |
| | | |
| | | |
| | | // 统计数据 |
| | | |
| | | orderOrRefund: 1, // 订单还是退单 |
| | |
| | | const dates = []; |
| | | const today = new Date(); |
| | | let days = 1; |
| | | console.log(param.year) |
| | | console.log(param.month) |
| | | if(param.year !== null && param.year !== undefined && param.month !== null && param.month !== undefined && param.month !=='' ){ |
| | | // 当传入年份和月份时,生成该月份的所有日期 |
| | | const year = parseInt(param.year); |
| | |
| | | if (this.orderTimePeriodChart){ |
| | | this.orderTimePeriodChart.resize(); |
| | | } |
| | | if (this.productRepurchaseRateChart){ |
| | | this.productRepurchaseRateChart.resize(); |
| | | } |
| | | }, |
| | | initChart(){ |
| | | this.chart = echarts.init(this.$refs.chartDom) |
| | | this.viewPrintChart = echarts.init(this.$refs.viewPrintChartDom) |
| | | this.orderCountChart = echarts.init(this.$refs.orderCountChartDom) |
| | | this.orderTimePeriodChart = echarts.init(this.$refs.orderTimePeriodChartDom) |
| | | this.productRepurchaseRateChart = echarts.init(this.$refs.productRepurchaseRateChartDom) |
| | | |
| | | this.updateChartData(this.orderParams) |
| | | |
| | | this.updateOrderCountChartDate(this.orderParams) |
| | | this.updateChartData(this.orderParams)//更新 pvuv |
| | | |
| | | let form = {...this.orderParams}; |
| | | console.log(this.currentType) |
| | | console.log(this.currentLimit) |
| | | form.currentType = this.currentType; |
| | | form.currentLimit = this.currentLimit; |
| | | console.log(form) |
| | | this.updateViewAndCompletionRateData(form) |
| | | this.updateOrderCountChartDate(this.orderParams)//更新日订单 |
| | | |
| | | this.updateOrderTimePeriodData(this.orderParams) |
| | | let viewForm = {...this.orderParams}; |
| | | viewForm.currentType = this.currentType; |
| | | viewForm.currentLimit = this.currentLimit; |
| | | this.updateViewAndCompletionRateData(viewForm)//更新完播率 |
| | | |
| | | this.updateOrderTimePeriodData(this.orderParams)//更新浏览数据,下订单日期时间段分析 |
| | | |
| | | let productRepurchaseDataForm ={...this.orderParams}; |
| | | productRepurchaseDataForm.currentLimit = this.repurchaseCurrentLimit |
| | | this.updateProductRepurchaseData(productRepurchaseDataForm)// |
| | | }, |
| | | // 更新图表数据 |
| | | //------------更新图表数据pvuv start |
| | | async updateChartData(param) { |
| | | // 生成日期和PV数据 |
| | | const { pvData ,uvData} = await this.generateChartData(param) |
| | |
| | | // 3. 此时pvData和uvData已被接口数据填充,再返回 |
| | | return { pvData, uvData }; |
| | | }, |
| | | //------------- |
| | | //-------------订单日趋势 |
| | | //-------------end |
| | | //-------------订单日趋势start |
| | | async updateOrderCountChartDate(param){ |
| | | const { orderCountData } = await this.generateOrderCountChartData(param) |
| | | this.orderCountChart.setOption(this.getOrderCountChartOption(this.getDates(param),orderCountData)) |
| | |
| | | animationEasing: 'cubicOut' // 缓动效果,优化动画流畅度 |
| | | }; |
| | | }, |
| | | //------------- |
| | | //-------------end |
| | | |
| | | //-------------浏览量,完播率, |
| | | //-------------浏览量,完播率,start |
| | | handleLimitChange(limit) { |
| | | if (this.currentLimit !== limit) { |
| | | this.currentLimit = limit |
| | |
| | | formatter:tooltipFormatter |
| | | }, |
| | | grid: { |
| | | left: '5%', // 视频类型左移,给完播率标签留空间 |
| | | right: '10%', |
| | | bottom: '0', |
| | | left: '4%', // 视频类型左移,给完播率标签留空间 |
| | | right: '12%', |
| | | bottom: '2%', |
| | | top: '5%', |
| | | containLabel: true |
| | | }, |
| | |
| | | min: 0 |
| | | }, |
| | | yAxis: { |
| | | inverse: true, |
| | | type: 'category', |
| | | data: yData, |
| | | axisLine: { lineStyle: { color: '#ddd' } }, |
| | |
| | | ] |
| | | }; |
| | | }, |
| | | //------------- |
| | | //-------------浏览数据,下订单日期时间段分析 |
| | | //-------------end |
| | | //-------------浏览数据,下订单日期时间段分析start |
| | | async updateOrderTimePeriodData(param){ |
| | | const { viewData,countData,dateData} = await this.generateOrderTimePeriodChartData(param); |
| | | this.orderTimePeriodChart.setOption(this.getOrderTimePeriodChartOption(viewData,countData,dateData)); |
| | |
| | | animationEasing: 'cubicOut' |
| | | }; |
| | | }, |
| | | //--------------ebd |
| | | |
| | | //-------------复购率 start |
| | | handleRepurchaseLimitChange(limit) { |
| | | if (this.repurchaseCurrentLimit !== limit) { |
| | | this.repurchaseCurrentLimit = limit |
| | | let form = {...this.orderParams} |
| | | form.currentLimit = this.repurchaseCurrentLimit; |
| | | this.updateProductRepurchaseData(form) // 重新加载数据 |
| | | } |
| | | }, |
| | | async updateProductRepurchaseData(param){ |
| | | const { rateData,goodsData} = await this.generateProductRepurchaseChartData(param); |
| | | this.productRepurchaseRateChart.setOption(this.getProductRepurchaseChartOption(this.getDates(param),rateData,goodsData)); |
| | | }, |
| | | async generateProductRepurchaseChartData(param){ |
| | | let rateData = []; |
| | | let goodsData = []; |
| | | try{ |
| | | const res = await gerProductRepurchase(param); |
| | | if (res.code === 200){ |
| | | rateData = res.data.rateData; |
| | | goodsData = res.data.goodsData; |
| | | } |
| | | }catch (error){ |
| | | console.error("接口调用失败", error); |
| | | } |
| | | return {rateData,goodsData} |
| | | }, |
| | | getProductRepurchaseChartOption(dates, rateData, goodsData) { |
| | | // 工具函数:判断数值是否为整数(避免100.00显示为100.00%) |
| | | const isInteger = (num) => { |
| | | return Math.abs(num - Math.round(num)) < Number.EPSILON; |
| | | }; |
| | | |
| | | return { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | backgroundColor: 'rgba(255, 255, 255, 0.9)', |
| | | borderColor: '#eee', |
| | | borderWidth: 1, |
| | | textStyle: { color: '#333' }, |
| | | axisPointer: { |
| | | type: 'shadow' |
| | | }, |
| | | formatter: (params) => { |
| | | const goodsName = params[0].name; |
| | | const rate = params[0].value; |
| | | // 整数显示无小数,非整数保留两位小数 |
| | | const displayRate = isInteger(rate) ? rate : rate.toFixed(2); |
| | | return `<div class="font-medium">${goodsName}</div> |
| | | <div>复购率: <span style="color: #722ED1; font-weight: bold">${displayRate}%</span></div>`; |
| | | }, |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | top: '3%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'value', |
| | | axisLine: { show: false }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { |
| | | color: '#86909C', |
| | | // 坐标轴标签:整数显示无小数,非整数保留0位(取整) |
| | | formatter: (value) => { |
| | | return isInteger(value) ? `${value}%` : `${Math.round(value)}%`; |
| | | } |
| | | }, |
| | | splitLine: { |
| | | lineStyle: { |
| | | color: '#f2f3f5', |
| | | type: 'dashed' |
| | | } |
| | | }, |
| | | min: 0, |
| | | max: (value) => { |
| | | // 限制最大值不超过100(复购率最高100%),同时保留1.2倍的间距 |
| | | const calculatedMax = value.max * 1.2; |
| | | return Math.min(calculatedMax, 100); |
| | | } |
| | | }, |
| | | yAxis: { |
| | | type: 'category', |
| | | data: goodsData, |
| | | axisLine: { lineStyle: { color: '#eee' } }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { |
| | | color: '#86909C', |
| | | interval: 0, |
| | | formatter: (value) => { |
| | | return value.length > 10 ? value.substring(0, 10) + '...' : value; |
| | | } |
| | | }, |
| | | splitLine: { show: false }, |
| | | inverse: true |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '商品复购率', |
| | | type: 'bar', |
| | | data: rateData, |
| | | barWidth: '60%', |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ |
| | | { offset: 0, color: '#722ED1' }, |
| | | { offset: 1, color: '#EB2F96' } |
| | | ]), |
| | | borderRadius: [0, 4, 4, 0] |
| | | }, |
| | | emphasis: { |
| | | itemStyle: { |
| | | shadowBlur: 10, |
| | | shadowColor: 'rgba(114, 46, 209, 0.5)' |
| | | } |
| | | }, |
| | | label: { |
| | | show: true, |
| | | position: 'right', |
| | | // 柱状图标签:整数显示无小数,非整数保留1位 |
| | | formatter: (params) => { |
| | | const value = params.value; |
| | | return isInteger(value) ? `${value}%` : value.toFixed(1) + '%'; |
| | | }, |
| | | color: '#722ED1', |
| | | fontWeight: 'bold' |
| | | } |
| | | } |
| | | ], |
| | | }; |
| | | }, |
| | | //-------------end |
| | | formatDate(date) { |
| | | const month = date.getMonth() + 1; // 月份从0开始,需+1 |
| | | const day = date.getDate(); |
| | |
| | | this.refundParams.pageSize = 10 |
| | | |
| | | //更新表格 |
| | | |
| | | this.updateChartData(this.orderParams) |
| | | this.updateOrderCountChartDate(this.orderParams) |
| | | |
| | |
| | | this.updateViewAndCompletionRateData(form) |
| | | |
| | | this.updateOrderTimePeriodData(this.orderParams) |
| | | |
| | | let productRepurchaseDataForm ={...this.orderParams}; |
| | | productRepurchaseDataForm.currentLimit = this.repurchaseCurrentLimit |
| | | |
| | | this.updateProductRepurchaseData(productRepurchaseDataForm)// |
| | | }, |
| | | |
| | | // 实例化订单概览 |
| | |
| | | width: 100%; |
| | | height: 662px; |
| | | } |
| | | .repurchase-chart-container{ |
| | | width: 100%; |
| | | height: 662px; |
| | | } |
| | | .chart-container { |
| | | width: 100%; |
| | | height: 400px; |