| | |
| | | <affixTime @selected="clickBreadcrumb" /> |
| | | </Card> |
| | | </Affix> |
| | | <!-- <Card class="card">--> |
| | | <!-- <div class="my-chart-container">--> |
| | | <!-- <!– 数据概览卡片 –>--> |
| | | <!--<!– <div class="stats-cards">–>--> |
| | | <!--<!– <div class="stat-card">–>--> |
| | | <!--<!– <div class="stat-header">–>--> |
| | | <!--<!– <span class="stat-title">总浏览量</span>–>--> |
| | | <!--<!– <i class="fa fa-eye stat-icon"></i>–>--> |
| | | <!--<!– </div>–>--> |
| | | <!--<!– <div class="stat-value">{{ totalPv }}</div>–>--> |
| | | <!--<!– <div class="stat-trend positive">–>--> |
| | | <!--<!– <i class="fa fa-arrow-up"></i> 12.5% 较上月–>--> |
| | | <!--<!– </div>–>--> |
| | | <!--<!– </div>–>--> |
| | | <Card class="card"> |
| | | <div class="chart-wrapper"> |
| | | <div class="chart-header"> |
| | | <h2>PV/UV 趋势图</h2> |
| | | </div> |
| | | <div ref="chartDom" class="chart-container"></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"> |
| | | <!-- 第一组:商品/视频(靠左) --> |
| | | <ButtonGroup> |
| | | <Button |
| | | :type="currentType === 'goods' ? 'primary' : 'default'" |
| | | @click="handleTypeChange('goods')" |
| | | > |
| | | 商品 |
| | | </Button> |
| | | <Button |
| | | :type="currentType === 'video' ? 'primary' : 'default'" |
| | | @click="handleTypeChange('video')" |
| | | > |
| | | 视频 |
| | | </Button> |
| | | </ButtonGroup> |
| | | |
| | | <!--<!– <div class="stat-card">–>--> |
| | | <!--<!– <div class="stat-header">–>--> |
| | | <!--<!– <span class="stat-title">平均日浏览量</span>–>--> |
| | | <!--<!– <i class="fa fa-calendar stat-icon"></i>–>--> |
| | | <!--<!– </div>–>--> |
| | | <!--<!– <div class="stat-value">{{ avgDailyPv }}</div>–>--> |
| | | <!--<!– <div class="stat-trend positive">–>--> |
| | | <!--<!– <i class="fa fa-arrow-up"></i> 8.3% 较上月–>--> |
| | | <!--<!– </div>–>--> |
| | | <!--<!– </div>–>--> |
| | | <!-- 第二组:前10/前20/前30(靠右) --> |
| | | <ButtonGroup> |
| | | <Button |
| | | :type="currentLimit === 10 ? 'success' : 'default'" |
| | | @click="handleLimitChange(10)" |
| | | > |
| | | 前10 |
| | | </Button> |
| | | <Button |
| | | :type="currentLimit === 20 ? 'success' : 'default'" |
| | | @click="handleLimitChange(20)" |
| | | > |
| | | 前20 |
| | | </Button> |
| | | <Button |
| | | :type="currentLimit === 30 ? 'success' : 'default'" |
| | | @click="handleLimitChange(30)" |
| | | > |
| | | 前30 |
| | | </Button> |
| | | </ButtonGroup> |
| | | </div> |
| | | <div ref="viewPrintChartDom" class="view-chart-container"></div> |
| | | </div> |
| | | </div> |
| | | </Card> |
| | | <Card class="card"> |
| | | <div class="my-chart-container"> |
| | | <div class="chart-wrapper"> |
| | | <div class="chart-header"> |
| | | <h2>订单增长 趋势图</h2> |
| | | </div> |
| | | <div ref="orderCountChartDom" class="chart-container"></div> |
| | | </div> |
| | | </div> |
| | | </Card> |
| | | |
| | | <!--<!– <div class="stat-card">–>--> |
| | | <!--<!– <div class="stat-header">–>--> |
| | | <!--<!– <span class="stat-title">最高单日浏览量</span>–>--> |
| | | <!--<!– <i class="fa fa-trophy stat-icon"></i>–>--> |
| | | <!--<!– </div>–>--> |
| | | <!--<!– <div class="stat-value">{{ maxDailyPv }}</div>–>--> |
| | | <!--<!– <div class="stat-trend">{{ maxPvDate }}</div>–>--> |
| | | <!--<!– </div>–>--> |
| | | <!--<!– </div>–>--> |
| | | <Card class="card"> |
| | | <div class="my-chart-container"> |
| | | <div class="chart-wrapper"> |
| | | <div class="chart-header"> |
| | | <h2>浏览数据/订单时间段 趋势图</h2> |
| | | </div> |
| | | <div ref="orderTimePeriodChartDom" class="chart-container"></div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- <!– 图表区域 –>--> |
| | | <!-- <div class="chart-wrapper">--> |
| | | <!-- <div class="chart-header">--> |
| | | <!-- <h2>PV/UV 趋势图</h2>--> |
| | | <!-- </div>--> |
| | | <!-- <div ref="chartDom" class="chart-container"></div>--> |
| | | <!-- </div>--> |
| | | </Card> |
| | | |
| | | <!-- <!– 数据更新时间 –>--> |
| | | <!--<!– <div class="update-time">–>--> |
| | | <!--<!– 数据更新时间: {{ updateTime }}–>--> |
| | | <!--<!– </div>–>--> |
| | | <!-- </div>--> |
| | | <!-- </Card>--> |
| | | <!-- <Card class="card">--> |
| | | <!-- <div class="my-chart-container">--> |
| | | <!-- <div class="chart-wrapper">--> |
| | | <!-- <div class="chart-header">--> |
| | | <!-- <h2>订单增长 趋势图</h2>--> |
| | | <!-- </div>--> |
| | | <!-- <div ref="orderCount-chartDom" class="chart-container"></div>--> |
| | | <!-- </div>--> |
| | | <!-- </div>--> |
| | | <!-- </Card>--> |
| | | |
| | | <Card class="card"> |
| | | <div> |
| | | <h4>交易概况</h4> |
| | |
| | | import refundRow from "./order/refundOrder"; |
| | | import affixTime from "@/components/affix-time"; |
| | | import * as echarts from 'echarts'; |
| | | import {pvUvData} from "../../api/orderStatistics"; |
| | | import {pvUvData,getOrderCount,getViewAndCompletionRateCount,getOrderTimePeriod} from "../../api/orderStatistics"; |
| | | |
| | | export default { |
| | | components: { orderRow, refundRow, affixTime }, |
| | |
| | | // 图表实例 |
| | | chart: null, //pvuv |
| | | orderCountChart:null, //订单日趋势 |
| | | viewPrintChart:null, |
| | | orderTimePeriodChart:null, |
| | | |
| | | currentType:"goods", |
| | | currentLimit:10, |
| | | // 统计数据 |
| | | |
| | | orderOrRefund: 1, // 订单还是退单 |
| | |
| | | }, |
| | | }, |
| | | methods: { |
| | | getDates(param){ |
| | | 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); |
| | | const month = parseInt(param.month); |
| | | // 获取该月的天数 |
| | | const daysInMonth = new Date(year, month, 0).getDate(); |
| | | |
| | | // 生成该月所有日期 |
| | | for (let day = 1; day <= daysInMonth; day++) { |
| | | const date = new Date(year, month - 1, day); // 月份从0开始,所以要减1 |
| | | dates.push(this.formatDate(date, 'MM-dd')); |
| | | } |
| | | |
| | | }else{ |
| | | // 确定天数逻辑不变 |
| | | if (param.searchType === "TODAY") { |
| | | days = 1; |
| | | } else if (param.searchType === "YESTERDAY") { |
| | | days = 1; |
| | | } else if (param.searchType === "LAST_SEVEN") { |
| | | days = 7; |
| | | } else if (param.searchType === "LAST_THIRTY") { |
| | | days = 30; |
| | | } |
| | | for (let i = days - 1; i >= 0; i--) { |
| | | const date = new Date(today); |
| | | date.setDate(today.getDate() - i); |
| | | dates.push(this.formatDate(date, 'MM-dd')); |
| | | } |
| | | } |
| | | // 生成日期数组逻辑不变 |
| | | |
| | | return dates; |
| | | }, |
| | | |
| | | //------------- puvu |
| | | handleResize() { |
| | | if (this.chart) { |
| | | this.chart.resize() |
| | | } |
| | | if(this.viewPrintChart){ |
| | | this.viewPrintChart.resize() |
| | | } |
| | | if (this.orderCountChart){ |
| | | this.orderCountChart.resize() |
| | | } |
| | | if (this.orderTimePeriodChart){ |
| | | this.orderTimePeriodChart.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.updateChartData(this.orderParams) |
| | | |
| | | this.updateOrderCountChartDate(this.orderParams) |
| | | |
| | | 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.updateOrderTimePeriodData(this.orderParams) |
| | | }, |
| | | // 更新图表数据 |
| | | async updateChartData(param) { |
| | | // 生成日期和PV数据 |
| | | const { dates, pvData ,uvData} = await this.generateChartData(param) |
| | | console.log(dates, pvData ,uvData) |
| | | // 更新统计数据 |
| | | |
| | | |
| | | const { pvData ,uvData} = await this.generateChartData(param) |
| | | // 设置图表配置 |
| | | this.chart.setOption(this.getChartOption(dates, pvData, uvData)) |
| | | this.chart.setOption(this.getChartOption(this.getDates(param), pvData, uvData)) |
| | | }, |
| | | // 获取图表配置项 |
| | | // 获取图表配置项 |
| | | // 图表配置项(恢复原始颜色) |
| | | getChartOption(dates, pvData, uvData) { |
| | | return { |
| | |
| | | animationEasing: 'cubicOut' |
| | | }; |
| | | }, |
| | | // 生成pv/uv图表数据 |
| | | async generateChartData(param) { // 1. 声明为async函数 |
| | | const dates = []; |
| | | const today = new Date(); |
| | | let days = 1; |
| | | |
| | | // 确定天数逻辑不变 |
| | | if (param.searchType === "TODAY") { |
| | | days = 1; |
| | | } else if (param.searchType === "YESTERDAY") { |
| | | days = 1; |
| | | } else if (param.searchType === "LAST_SEVEN") { |
| | | days = 7; |
| | | } else if (param.searchType === "LAST_THIRTY") { |
| | | days = 30; |
| | | } |
| | | |
| | | // 生成日期数组逻辑不变 |
| | | for (let i = days - 1; i >= 0; i--) { |
| | | const date = new Date(today); |
| | | date.setDate(today.getDate() - i); |
| | | dates.push(this.formatDate(date, 'MM-dd')); |
| | | } |
| | | |
| | | // 生成pv/uv图表数据 |
| | | async generateChartData(param) { |
| | | // 1. 声明为async函数 |
| | | // 2. 使用await等待接口返回,确保数据获取后再继续 |
| | | let pvData = []; |
| | | let uvData = []; |
| | |
| | | } |
| | | |
| | | // 3. 此时pvData和uvData已被接口数据填充,再返回 |
| | | return { dates, pvData, uvData }; |
| | | return { pvData, uvData }; |
| | | }, |
| | | //------------- |
| | | //-------------订单日趋势 |
| | | |
| | | |
| | | |
| | | async updateOrderCountChartDate(param){ |
| | | const { orderCountData } = await this.generateOrderCountChartData(param) |
| | | this.orderCountChart.setOption(this.getOrderCountChartOption(this.getDates(param),orderCountData)) |
| | | }, |
| | | async generateOrderCountChartData(param){ |
| | | let orderCountData = []; |
| | | try { |
| | | const res = await getOrderCount(param); |
| | | if (res.code === 200) { |
| | | orderCountData = res.data; |
| | | } |
| | | } catch (error) { |
| | | console.error("接口调用失败", error); |
| | | } |
| | | return { orderCountData }; |
| | | }, |
| | | getOrderCountChartOption(dates, orderCountDate) { |
| | | return { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | backgroundColor: 'rgba(255, 255, 255, 0.9)', |
| | | borderColor: '#eee', |
| | | borderWidth: 1, |
| | | textStyle: { color: '#333' }, |
| | | // 修正1:Tooltip 内容与“订单量”主题匹配,简化逻辑 |
| | | formatter: (params) => { |
| | | const date = params[0].name; |
| | | const orderCount = params[0].value || 0; // 直接取唯一系列数据 |
| | | return `<div class="font-medium">${date}</div> |
| | | <div>订单量: <span style="color: #00b42a; font-weight: bold">${orderCount.toLocaleString()}</span></div>`; |
| | | }, |
| | | }, |
| | | legend: { |
| | | data: ['订单量'], |
| | | top: 0, |
| | | textStyle: { color: '#666' } |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true, |
| | | top: '20%' // 优化1:增加顶部间距,避免与legend重叠 |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: dates, |
| | | axisLine: { lineStyle: { color: '#eee' } }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { interval: 'auto', rotate: 0, color: '#86909C' }, |
| | | splitLine: { show: false } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLine: { show: false }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: '#86909C', formatter: '{value}' }, |
| | | splitLine: { lineStyle: { color: '#f2f3f5' } }, |
| | | min: 0 // 正确:订单量不能为负,固定最小值为0 |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '订单量', |
| | | type: 'line', |
| | | data: orderCountDate, |
| | | symbol: 'circle', |
| | | symbolSize: 6, |
| | | emphasis: { |
| | | symbolSize: 8, |
| | | showSymbol: true |
| | | }, |
| | | lineStyle: { |
| | | width: 3, |
| | | color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ |
| | | { offset: 0, color: '#00b42a' }, |
| | | { offset: 1, color: '#72c140' } |
| | | ]), |
| | | cap: 'round', // 端点圆角,优化视觉 |
| | | join: 'round', // 拐角圆角,优化视觉 |
| | | miterLimit: 3 |
| | | }, |
| | | itemStyle: { |
| | | color: '#00b42a', |
| | | borderColor: '#fff', |
| | | borderWidth: 0 // 修正2:与注释一致,显示白色边框(避免点与背景融合) |
| | | }, |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: 'rgba(0, 180, 42, 0.2)' }, |
| | | { offset: 1, color: 'rgba(0, 180, 42, 0)' } |
| | | ]) |
| | | }, |
| | | smooth: true, |
| | | showSymbol: true // 显示所有数据点,便于查看具体数值 |
| | | } |
| | | ], |
| | | animation: true, |
| | | animationDuration: 1500, |
| | | animationEasing: 'cubicOut' // 缓动效果,优化动画流畅度 |
| | | }; |
| | | }, |
| | | //------------- |
| | | |
| | | //-------------浏览量,完播率, |
| | | handleLimitChange(limit) { |
| | | if (this.currentLimit !== limit) { |
| | | this.currentLimit = limit |
| | | let form = {...this.orderParams} |
| | | form.currentLimit = this.currentLimit; |
| | | form.currentType = this.currentType; |
| | | this.updateViewAndCompletionRateData(form) // 重新加载数据 |
| | | } |
| | | }, |
| | | handleTypeChange(type) { |
| | | if (this.currentType !== type){// 避免重复点击 |
| | | this.currentType = type // 更新当前类型 |
| | | let form = {...this.orderParams} |
| | | form.currentLimit = this.currentLimit; |
| | | form.currentType = this.currentType; |
| | | this.updateViewAndCompletionRateData(form) // 重新加载数据 |
| | | } |
| | | |
| | | }, |
| | | async updateViewAndCompletionRateData(param) { |
| | | // 生成日期和每日订单量数据 |
| | | const { xData,yData ,rateData} = await this.generateViewAndCompletionRateChartData(param) |
| | | // 更新统计数据 |
| | | // 设置图表配置( |
| | | this.viewPrintChart.setOption(this.getViewAndCompletionRateChartOption( xData,yData,rateData)); |
| | | }, |
| | | async generateViewAndCompletionRateChartData(param){ |
| | | let xData = []; |
| | | let yData = []; |
| | | let rateData =[]; |
| | | try { |
| | | const res = await getViewAndCompletionRateCount(param); // 等待接口响应 |
| | | if (res.code === 200) { |
| | | xData = res.data.xData; |
| | | yData = res.data.yData |
| | | rateData = res.data.rateData; |
| | | } |
| | | } catch (error) { |
| | | console.error("接口调用失败", error); |
| | | |
| | | } |
| | | return { xData,yData,rateData} |
| | | }, |
| | | getViewAndCompletionRateChartOption(xData, yData, rateData) { |
| | | // 兼容ECharts实例引用(根据项目环境选择this.$echarts或全局echarts) |
| | | let isVideoType = this.currentType === "video" |
| | | const tooltipFormatter = (params) => { |
| | | let content = `${params[0].name}<br/>浏览次数: ${params[0].value} 次`; |
| | | if (this.currentType === 'video') { |
| | | const rate = rateData?.[params[0].dataIndex] ?? 0; |
| | | content += `<br/>完播率: ${rate}%`; |
| | | } |
| | | return content; |
| | | }; |
| | | |
| | | return { |
| | | title: { |
| | | text: isVideoType ? '视频浏览量&完播率统计' : '商品浏览量统计', // 视频标题加“完播率” |
| | | left: 'center', |
| | | textStyle: { fontSize: 16, fontWeight: 'normal', color: '#333' }, |
| | | subtext: `按${isVideoType ? '视频' : '商品'}分类(Top${this.currentLimit})`, |
| | | subtextStyle: { fontSize: 12, color: '#666' } |
| | | }, |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | axisPointer: { type: 'shadow' }, |
| | | formatter:tooltipFormatter |
| | | }, |
| | | grid: { |
| | | left: '5%', // 视频类型左移,给完播率标签留空间 |
| | | right: '10%', |
| | | bottom: '0', |
| | | top: '5%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'value', |
| | | name: '浏览次数', |
| | | nameGap:100, |
| | | nameTextStyle: { color: '#666', fontSize: 12 }, |
| | | axisLine: { show: false }, |
| | | axisLabel: { formatter: '{value}', color: '#666', fontSize: 12 }, |
| | | splitLine: { lineStyle: { color: '#f5f5f5' } }, |
| | | min: 0 |
| | | }, |
| | | yAxis: { |
| | | type: 'category', |
| | | data: yData, |
| | | axisLine: { lineStyle: { color: '#ddd' } }, |
| | | axisLabel: { color: '#666', fontSize: 12, interval: 0 }, // 强制显示所有标签 |
| | | splitLine: { show: false } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: isVideoType ? '浏览量&完播率' : '浏览量', |
| | | type: 'bar', |
| | | data: xData, |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ |
| | | { offset: 0, color: '#409eff' }, |
| | | { offset: 1, color: '#69b1ff' } |
| | | ]), |
| | | borderRadius: [0, 4, 4, 0] // 横向柱子右侧圆角 |
| | | }, |
| | | barWidth: isVideoType ? '30%' : '40%', // 视频类型柱子变窄,避免标签拥挤 |
| | | label: { |
| | | show: true, |
| | | position: 'right', // 标签在柱子右侧 |
| | | color: '#333', |
| | | fontSize: 12, |
| | | // 标签内容:视频类型显示“浏览量+完播率”,商品类型只显示浏览量 |
| | | formatter: function(params) { |
| | | const viewCount = params.value; |
| | | if (isVideoType) { |
| | | const rate = rateData[params.dataIndex] || 0; // 兜底空值 |
| | | // 换行显示,避免横向拥挤 |
| | | return `${viewCount} 次\n完播率: ${rate}%`; |
| | | } |
| | | return `${viewCount} 次`; |
| | | }.bind(this) // 绑定this,确保能访问到 isVideoType 和 rateData |
| | | }, |
| | | emphasis: { |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ |
| | | { offset: 0, color: '#3a86ff' }, |
| | | { offset: 1, color: '#5a9dff' } |
| | | ]) |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | }; |
| | | }, |
| | | //------------- |
| | | //-------------浏览数据,下订单日期时间段分析 |
| | | async updateOrderTimePeriodData(param){ |
| | | const { viewData,countData,dateData} = await this.generateOrderTimePeriodChartData(param); |
| | | this.orderTimePeriodChart.setOption(this.getOrderTimePeriodChartOption(viewData,countData,dateData)); |
| | | }, |
| | | async generateOrderTimePeriodChartData(param){ |
| | | let viewData= []; |
| | | let countData =[]; |
| | | let dateData = []; |
| | | try { |
| | | const res = await getOrderTimePeriod(param); // 等待接口响应 |
| | | if (res.code === 200) { |
| | | viewData = res.data.viewData; |
| | | countData = res.data.countData |
| | | dateData = res.data.dateData; |
| | | } |
| | | } catch (error) { |
| | | console.error("接口调用失败", error); |
| | | |
| | | } |
| | | return { viewData,countData,dateData} |
| | | |
| | | }, |
| | | getOrderTimePeriodChartOption(viewData,countData,dateData){ |
| | | return { |
| | | tooltip: { |
| | | trigger: 'axis', |
| | | backgroundColor: 'rgba(255, 255, 255, 0.9)', |
| | | borderColor: '#eee', |
| | | borderWidth: 1, |
| | | textStyle: { color: '#333' }, |
| | | formatter: (params) => { |
| | | const date = params[0].name; |
| | | const view = params.find(item => item.seriesName === '浏览数据')?.value || 0; |
| | | const count= params.find(item => item.seriesName === '订单时间段')?.value || 0; |
| | | // 优化:添加换行符转义,避免潜在格式问题(可选,不影响功能) |
| | | return `<div class="font-medium">${date}</div> |
| | | <div>浏览数据: <span style="color: #165DFF; font-weight: bold">${view.toLocaleString()}</span></div> |
| | | <div>订单时间段: <span style="color: #00b42a; font-weight: bold">${count.toLocaleString()}</span></div>`; |
| | | }, |
| | | }, |
| | | legend: { |
| | | data: ['浏览数据', '订单时间段'], |
| | | top: 0, |
| | | textStyle: { color: '#666' } |
| | | }, |
| | | grid: { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true, |
| | | top: '15%' |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: dateData, |
| | | axisLine: { lineStyle: { color: '#eee' } }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { interval: 'auto', rotate: 0, color: '#86909C' }, |
| | | splitLine: { show: false } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLine: { show: false }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: '#86909C', formatter: '{value}' }, |
| | | splitLine: { lineStyle: { color: '#f2f3f5' } }, |
| | | min: 0 |
| | | }, |
| | | series: [ |
| | | // PV折线(保留原始蓝色系,优化点线衔接) |
| | | { |
| | | name: '浏览数据', |
| | | type: 'line', |
| | | data: viewData, |
| | | symbol: 'circle', |
| | | symbolSize: 6, // 保留原有点大小 |
| | | emphasis: { |
| | | symbolSize: 8, |
| | | showSymbol: true |
| | | }, |
| | | lineStyle: { |
| | | width: 3, // 保留原有线宽 |
| | | color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ |
| | | { offset: 0, color: '#165DFF' }, // 原始PV主色 |
| | | { offset: 1, color: '#36CFC9' } // 原始渐变辅助色 |
| | | ]), |
| | | // 关键优化1:线条端点设为圆角,避免“切口”空白 |
| | | cap: 'round', |
| | | // 关键优化2:线条拐角设为圆角,避免衔接间隙 |
| | | join: 'round', |
| | | // 辅助:控制拐角圆角大小(与线宽匹配,避免溢出) |
| | | miterLimit: 3 |
| | | }, |
| | | itemStyle: { |
| | | color: '#165DFF', // 原始点颜色 |
| | | borderColor: '#fff', // 保留白色边框(增强层次感) |
| | | // 关键优化3:减小边框宽度,避免遮挡线条导致断层 |
| | | borderWidth: 0 // 从2调整为1.5 |
| | | }, |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: 'rgba(22, 93, 255, 0.2)' }, // 原始填充色 |
| | | { offset: 1, color: 'rgba(22, 93, 255, 0)' } |
| | | ]) |
| | | }, |
| | | smooth: true, |
| | | showSymbol: true, // 保留你设置的“默认显示所有点” |
| | | }, |
| | | // UV折线(保留原始绿色系,同PV优化逻辑) |
| | | { |
| | | name: '订单时间段', |
| | | type: 'line', |
| | | data: countData, |
| | | symbol: 'circle', |
| | | symbolSize: 6, // 保留原有点大小 |
| | | emphasis: { |
| | | symbolSize: 8, |
| | | showSymbol: true |
| | | }, |
| | | lineStyle: { |
| | | width: 3, // 保留原有线宽 |
| | | color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ |
| | | { offset: 0, color: '#00b42a' }, // 原始UV主色 |
| | | { offset: 1, color: '#72c140' } // 原始渐变辅助色 |
| | | ]), |
| | | // 同PV优化:端点圆角+拐角圆角 |
| | | cap: 'round', |
| | | join: 'round', |
| | | miterLimit: 3 |
| | | }, |
| | | itemStyle: { |
| | | color: '#00b42a', // 原始点颜色 |
| | | borderColor: '#fff', // 保留白色边框 |
| | | // 同PV优化:减小边框宽度 |
| | | borderWidth: 0 // 从2调整为1.5 |
| | | }, |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: 'rgba(0, 180, 42, 0.2)' }, // 原始填充色 |
| | | { offset: 1, color: 'rgba(0, 180, 42, 0)' } |
| | | ]) |
| | | }, |
| | | smooth: true, |
| | | showSymbol: true, // 保留“默认显示所有点” |
| | | } |
| | | ], |
| | | animation: true, |
| | | animationDuration: 1500, |
| | | animationEasing: 'cubicOut' |
| | | }; |
| | | }, |
| | | |
| | | formatDate(date) { |
| | | const month = date.getMonth() + 1; // 月份从0开始,需+1 |
| | |
| | | |
| | | //更新表格 |
| | | this.updateChartData(this.orderParams) |
| | | this.updateOrderCountChartDate(this.orderParams) |
| | | |
| | | let form = {...this.orderParams}; |
| | | form.currentType = this.currentType; |
| | | form.currentLimit = this.currentLimit; |
| | | this.updateViewAndCompletionRateData(form) |
| | | |
| | | this.updateOrderTimePeriodData(this.orderParams) |
| | | }, |
| | | |
| | | // 实例化订单概览 |
| | |
| | | }; |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | .button-group-wrapper { |
| | | display: flex; |
| | | justify-content: space-between; /* 左右两端对齐 */ |
| | | align-items: center; /* 垂直居中(避免按钮高度不一致导致错位) */ |
| | | width: 100%; /* 必须撑满父容器,否则 justify-content: space-between 无效 */ |
| | | margin-bottom: 20px; /* 与图表保持间距 */ |
| | | flex-wrap: wrap; /* 小屏幕自动换行(避免按钮挤压) */ |
| | | gap: 12px; /* 换行时两组按钮的上下间距 */ |
| | | } |
| | | |
| | | /* 图表容器:保持固定高度 */ |
| | | .chart-wrapper { |
| | | width: 100%; |
| | | height: 500px; |
| | | } |
| | | .active { |
| | | color: $theme_color; |
| | | position: relative; |
| | |
| | | // color: #fff; |
| | | //} |
| | | |
| | | .view-chart-container { |
| | | width: 100%; |
| | | height: 662px; |
| | | } |
| | | .chart-container { |
| | | width: 100%; |
| | | height: 400px; |