From 52c46fb923bf6fb6c15932a7f51c8fef2fd7266f Mon Sep 17 00:00:00 2001
From: peng <peng.com>
Date: 星期一, 27 十月 2025 15:56:51 +0800
Subject: [PATCH] 页面调整图片预览
---
manager/src/views/statistics/order.vue | 1073 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1,073 insertions(+), 0 deletions(-)
diff --git a/manager/src/views/statistics/order.vue b/manager/src/views/statistics/order.vue
index c8a24df..842b373 100644
--- a/manager/src/views/statistics/order.vue
+++ b/manager/src/views/statistics/order.vue
@@ -7,6 +7,119 @@
</Affix>
<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>
+
+ <!-- 绗簩缁勶細鍓�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>
+ <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>
+ </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>
+
+
+ <Card class="card">
<div>
<h4>浜ゆ槗姒傚喌</h4>
<div class="flex">
@@ -203,12 +316,29 @@
import orderRow from "./order/orderDetail";
import refundRow from "./order/refundOrder";
import affixTime from "@/components/affix-time";
+import * as echarts from 'echarts';
+import {pvUvData,getOrderCount,getViewAndCompletionRateCount,getOrderTimePeriod,gerProductRepurchase} from "../../api/orderStatistics";
export default {
components: { orderRow, refundRow, affixTime },
data() {
return {
+ // 鍥捐〃瀹炰緥
+ chart: null, //pvuv
+ orderCountChart:null, //璁㈠崟鏃ヨ秼鍔�
+ viewPrintChart:null, //瀹屾挱鐜�
+ orderTimePeriodChart:null, //璁㈠崟/娴忚鏃堕棿
+ productRepurchaseRateChart:null,//鍟嗗搧澶嶈喘鐜�
+
+ currentType:"goods",
+ currentLimit:10,
+
+ repurchaseCurrentLimit:10,
+
+
+ // 缁熻鏁版嵁
+
orderOrRefund: 1, // 璁㈠崟杩樻槸閫�鍗�
total: 0, // 鎬绘暟
// 璁㈠崟鐘舵��
@@ -525,6 +655,781 @@
},
},
methods: {
+ getDates(param){
+ const dates = [];
+ const today = new Date();
+ let days = 1;
+ 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();
+ }
+ 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)//鏇存柊 pvuv
+
+ this.updateOrderCountChartDate(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) {
+ // 鐢熸垚鏃ユ湡鍜孭V鏁版嵁
+ const { pvData ,uvData} = await this.generateChartData(param)
+ // 璁剧疆鍥捐〃閰嶇疆
+ this.chart.setOption(this.getChartOption(this.getDates(param), pvData, uvData))
+ },
+ // 鑾峰彇鍥捐〃閰嶇疆椤�
+ // 鍥捐〃閰嶇疆椤癸紙鎭㈠鍘熷棰滆壊锛�
+ getChartOption(dates, pvData, uvData) {
+ 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 pv = params.find(item => item.seriesName === '娴忚閲�(PV)')?.value || 0;
+ const uv = params.find(item => item.seriesName === '鐙珛璁垮(UV)')?.value || 0;
+ // 浼樺寲锛氭坊鍔犳崲琛岀杞箟锛岄伩鍏嶆綔鍦ㄦ牸寮忛棶棰橈紙鍙�夛紝涓嶅奖鍝嶅姛鑳斤級
+ return `<div class="font-medium">${date}</div>
+ <div>娴忚閲�(PV): <span style="color: #165DFF; font-weight: bold">${pv.toLocaleString()}</span></div>
+ <div>鐙珛璁垮(UV): <span style="color: #00b42a; font-weight: bold">${uv.toLocaleString()}</span></div>`;
+ },
+ },
+ legend: {
+ data: ['娴忚閲�(PV)', '鐙珛璁垮(UV)'],
+ top: 0,
+ textStyle: { color: '#666' }
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true,
+ top: '15%'
+ },
+ 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
+ },
+ series: [
+ // PV鎶樼嚎锛堜繚鐣欏師濮嬭摑鑹茬郴锛屼紭鍖栫偣绾胯鎺ワ級
+ {
+ name: '娴忚閲�(PV)',
+ type: 'line',
+ data: pvData,
+ 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锛氱嚎鏉$鐐硅涓哄渾瑙掞紝閬垮厤鈥滃垏鍙b�濈┖鐧�
+ 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: '鐙珛璁垮(UV)',
+ type: 'line',
+ data: uvData,
+ 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' } // 鍘熷娓愬彉杈呭姪鑹�
+ ]),
+ // 鍚孭V浼樺寲锛氱鐐瑰渾瑙�+鎷愯鍦嗚
+ cap: 'round',
+ join: 'round',
+ miterLimit: 3
+ },
+ itemStyle: {
+ color: '#00b42a', // 鍘熷鐐归鑹�
+ borderColor: '#fff', // 淇濈暀鐧借壊杈规
+ // 鍚孭V浼樺寲锛氬噺灏忚竟妗嗗搴�
+ 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'
+ };
+ },
+ // 鐢熸垚pv/uv鍥捐〃鏁版嵁
+ async generateChartData(param) {
+ // 1. 澹版槑涓篴sync鍑芥暟
+ // 2. 浣跨敤await绛夊緟鎺ュ彛杩斿洖锛岀‘淇濇暟鎹幏鍙栧悗鍐嶇户缁�
+ let pvData = [];
+ let uvData = [];
+ try {
+ const res = await pvUvData(param); // 绛夊緟鎺ュ彛鍝嶅簲
+ if (res.code === 200) {
+ pvData = res.data.pvData;
+ uvData = res.data.uvData;
+ }
+ } catch (error) {
+ console.error("鎺ュ彛璋冪敤澶辫触", error);
+ // 鍙牴鎹渶姹傛坊鍔犻敊璇鐞嗭紙濡傞粯璁ゆ暟鎹級
+ }
+
+ // 3. 姝ゆ椂pvData鍜寀vData宸茶鎺ュ彛鏁版嵁濉厖锛屽啀杩斿洖
+ return { pvData, uvData };
+ },
+ //-------------end
+ //-------------璁㈠崟鏃ヨ秼鍔縮tart
+ 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锛歍ooltip 鍐呭涓庘�滆鍗曢噺鈥濅富棰樺尮閰嶏紝绠�鍖栭�昏緫
+ 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锛氬鍔犻《閮ㄩ棿璺濓紝閬垮厤涓巐egend閲嶅彔
+ },
+ 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 // 姝g‘锛氳鍗曢噺涓嶈兘涓鸿礋锛屽浐瀹氭渶灏忓�间负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' // 缂撳姩鏁堟灉锛屼紭鍖栧姩鐢绘祦鐣呭害
+ };
+ },
+ //-------------end
+
+ //-------------娴忚閲忥紝瀹屾挱鐜囷紝start
+ 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 ? '瑙嗛' : '鍟嗗搧'}鍒嗙被锛圱op${this.currentLimit}锛塦,
+ subtextStyle: { fontSize: 12, color: '#666' }
+ },
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: { type: 'shadow' },
+ formatter:tooltipFormatter
+ },
+ grid: {
+ left: '4%', // 瑙嗛绫诲瀷宸︾Щ锛岀粰瀹屾挱鐜囨爣绛剧暀绌洪棿
+ right: '12%',
+ bottom: '2%',
+ 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: {
+ inverse: true,
+ 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' }
+ ])
+ }
+ }
+ }
+ ]
+ };
+ },
+ //-------------end
+ //-------------娴忚鏁版嵁锛屼笅璁㈠崟鏃ユ湡鏃堕棿娈靛垎鏋恠tart
+ 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锛氱嚎鏉$鐐硅涓哄渾瑙掞紝閬垮厤鈥滃垏鍙b�濈┖鐧�
+ 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' } // 鍘熷娓愬彉杈呭姪鑹�
+ ]),
+ // 鍚孭V浼樺寲锛氱鐐瑰渾瑙�+鎷愯鍦嗚
+ cap: 'round',
+ join: 'round',
+ miterLimit: 3
+ },
+ itemStyle: {
+ color: '#00b42a', // 鍘熷鐐归鑹�
+ borderColor: '#fff', // 淇濈暀鐧借壊杈规
+ // 鍚孭V浼樺寲锛氬噺灏忚竟妗嗗搴�
+ 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'
+ };
+ },
+ //--------------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();
+ // 琛ラ浂锛氬鏋滄槸涓綅鏁帮紝鍓嶉潰鍔�0
+ const formattedMonth = month < 10 ? `0${month}` : month;
+ const formattedDay = day < 10 ? `0${day}` : day;
+ return `${formattedMonth}-${formattedDay}`;
+ },
+
pageNumberChange(val){
this.refundParams.pageNumber = val
this.getOrderList();
@@ -580,6 +1485,23 @@
this.refundParams = callback;
this.refundParams.pageNumber = 1
this.refundParams.pageSize = 10
+
+ //鏇存柊琛ㄦ牸
+
+ 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)
+
+ let productRepurchaseDataForm ={...this.orderParams};
+ productRepurchaseDataForm.currentLimit = this.repurchaseCurrentLimit
+
+ this.updateProductRepurchaseData(productRepurchaseDataForm)//
},
// 瀹炰緥鍖栬鍗曟瑙�
@@ -637,11 +1559,29 @@
},
mounted() {
+ console.log('ECharts 鏄惁瀛樺湪锛�', typeof echarts !== 'undefined'); // 搴旇緭鍑� true
+ this.initChart();
this.initBaseParams();
+ window.addEventListener('resize', this.handleResize)
},
};
</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;
@@ -859,4 +1799,137 @@
.card {
margin-bottom: 10px;
}
+.my-chart-container {
+ padding: 20px;
+ background-color: #f9fafb;
+}
+
+.stats-cards {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 20px;
+ margin-bottom: 20px;
+}
+
+.stat-card {
+ flex: 1;
+ min-width: 250px;
+ background-color: #fff;
+ border-radius: 8px;
+ padding: 20px;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
+}
+
+.stat-card:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 10px 20px rgba(22, 93, 255, 0.1);
+}
+
+.stat-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 15px;
+}
+
+.stat-title {
+ color: #86909c;
+ font-size: 14px;
+}
+
+.stat-icon {
+ color: #165dff;
+ font-size: 18px;
+}
+
+.stat-value {
+ font-size: 28px;
+ font-weight: bold;
+ margin-bottom: 10px;
+ color: #1d2129;
+}
+
+.stat-trend {
+ font-size: 13px;
+ display: flex;
+ align-items: center;
+}
+
+.stat-trend.positive {
+ color: #00b42a;
+}
+
+.chart-wrapper {
+ background-color: #fff;
+ border-radius: 8px;
+ padding: 20px;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+ margin-bottom: 15px;
+}
+
+.chart-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+}
+
+.chart-header h2 {
+ font-size: 18px;
+ font-weight: 600;
+ color: #1d2129;
+}
+
+//.time-filters {
+// display: flex;
+// gap: 10px;
+//}
+
+//.time-filters button {
+// padding: 6px 12px;
+// border-radius: 4px;
+// border: none;
+// background-color: #f2f3f5;
+// color: #1d2129;
+// font-size: 14px;
+// cursor: pointer;
+// transition: all 0.2s ease;
+//}
+//
+//.time-filters button.active {
+// background-color: #ff4c16;
+// color: #fff;
+//}
+
+.view-chart-container {
+ width: 100%;
+ height: 662px;
+}
+.repurchase-chart-container{
+ width: 100%;
+ height: 662px;
+}
+.chart-container {
+ width: 100%;
+ height: 400px;
+}
+
+.update-time {
+ color: #86909c;
+ font-size: 12px;
+ text-align: right;
+}
+
+@media (max-width: 768px) {
+ .chart-header {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 10px;
+ }
+
+ .chart-container {
+ height: 300px;
+ }
+}
</style>
--
Gitblit v1.8.0