From 2bf5b87e82dd2c4abea65454cd0b66cb0f254356 Mon Sep 17 00:00:00 2001 From: zxl <763096477@qq.com> Date: 星期一, 22 九月 2025 15:31:23 +0800 Subject: [PATCH] 订单问题,以及订单统计页面折线图 --- manager/src/api/order.js | 3 manager/src/views/order/order/orderList.vue | 28 +++ manager/src/views/statistics/order.vue | 411 +++++++++++++++++++++++++++++++++++++++++++++++++++ manager/src/api/orderStatistics.jsx | 9 + 4 files changed, 451 insertions(+), 0 deletions(-) diff --git a/manager/src/api/order.js b/manager/src/api/order.js index 6d523ed..8f77fee 100644 --- a/manager/src/api/order.js +++ b/manager/src/api/order.js @@ -84,6 +84,9 @@ export const getOrderList = (params) => { return getRequest(`/order/order`, params) } +export const getStoreSelect = ()=>{ + return getRequest('/order/order/storeSelect') +} // 瀵煎嚭璁㈠崟鍒楄〃 export const exportOrder = (params) => { diff --git a/manager/src/api/orderStatistics.jsx b/manager/src/api/orderStatistics.jsx new file mode 100644 index 0000000..533d95f --- /dev/null +++ b/manager/src/api/orderStatistics.jsx @@ -0,0 +1,9 @@ +import service from "../libs/axios"; + +export const pvUvData = (param) =>{ + return service({ + url:"/lmk/statistics/pvUv", + method: "GET", + params: param + }) +} diff --git a/manager/src/views/order/order/orderList.vue b/manager/src/views/order/order/orderList.vue index fad9ab0..031a10a 100644 --- a/manager/src/views/order/order/orderList.vue +++ b/manager/src/views/order/order/orderList.vue @@ -51,6 +51,23 @@ <Option value="KANJIA">鐮嶄环璁㈠崟</Option> </Select> </Form-item> + <Form-item label="搴楅摵" prop="store"> + <Select + v-model="searchForm.storeSelectId" + placeholder="璇烽�夋嫨" + clearable + style="width: 160px" + > + <Option + v-for="store in storeSelectList" + :key="store.id" + :label="store.label" + :value="store.id" + > + {{ store.label }} + </Option> + </Select> + </Form-item> <Form-item label="涓嬪崟鏃堕棿"> <DatePicker v-model="selectDate" @@ -231,6 +248,7 @@ import * as API_Member from "@/api/member.js"; import { getTags } from "@/api/tag.js"; import vueQr from "vue-qr"; +import {getStoreSelect} from "../../../api/order"; export default { name: "orderList", components: { @@ -241,6 +259,8 @@ }, data() { return { + //涓嬫媺妗嗘暟鎹� + storeSelectList:[], // 琛ㄦ牸鐨勮〃澶翠互鍙婂唴瀹� fields: { 璁㈠崟缂栧彿: "sn", @@ -523,6 +543,13 @@ }; }, methods: { + getStoreSelect(){ + API_Order.getStoreSelect().then(res =>{ + if (res.result){ + this.storeSelectList = res.result; + } + }) + }, closeGeneralQrCode(){ this.showGeneralQrCode = false; }, @@ -765,6 +792,7 @@ }, mounted() { this.init(); + this.getStoreSelect(); }, }; </script> diff --git a/manager/src/views/statistics/order.vue b/manager/src/views/statistics/order.vue index c8a24df..08a7ff6 100644 --- a/manager/src/views/statistics/order.vue +++ b/manager/src/views/statistics/order.vue @@ -5,7 +5,66 @@ <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>–>--> +<!--<!– <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>–>--> + +<!--<!– <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>–>--> + +<!-- <!– 鍥捐〃鍖哄煙 –>--> +<!-- <div class="chart-wrapper">--> +<!-- <div class="chart-header">--> +<!-- <h2>PV/UV 瓒嬪娍鍥�</h2>--> +<!-- </div>--> +<!-- <div ref="chartDom" class="chart-container"></div>--> +<!-- </div>--> + +<!-- <!– 鏁版嵁鏇存柊鏃堕棿 –>--> +<!--<!– <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> @@ -203,12 +262,20 @@ import orderRow from "./order/orderDetail"; import refundRow from "./order/refundOrder"; import affixTime from "@/components/affix-time"; +import * as echarts from 'echarts'; +import {pvUvData} from "../../api/orderStatistics"; export default { components: { orderRow, refundRow, affixTime }, data() { return { + // 鍥捐〃瀹炰緥 + chart: null, //pvuv + orderCountChart:null, //璁㈠崟鏃ヨ秼鍔� + + // 缁熻鏁版嵁 + orderOrRefund: 1, // 璁㈠崟杩樻槸閫�鍗� total: 0, // 鎬绘暟 // 璁㈠崟鐘舵�� @@ -525,6 +592,219 @@ }, }, methods: { + //------------- puvu + handleResize() { + if (this.chart) { + this.chart.resize() + } + }, + initChart(){ + this.chart = echarts.init(this.$refs.chartDom) + this.updateChartData(this.orderParams) + }, + // 鏇存柊鍥捐〃鏁版嵁 + async updateChartData(param) { + // 鐢熸垚鏃ユ湡鍜孭V鏁版嵁 + const { dates, pvData ,uvData} = await this.generateChartData(param) + console.log(dates, pvData ,uvData) + // 鏇存柊缁熻鏁版嵁 + + + // 璁剧疆鍥捐〃閰嶇疆 + this.chart.setOption(this.getChartOption(dates, 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鍑芥暟 + 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')); + } + + // 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 { dates, pvData, uvData }; + }, + //------------- + //-------------璁㈠崟鏃ヨ秼鍔� + + + + //------------- + + + + + + 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 +860,9 @@ this.refundParams = callback; this.refundParams.pageNumber = 1 this.refundParams.pageSize = 10 + + //鏇存柊琛ㄦ牸 + this.updateChartData(this.orderParams) }, // 瀹炰緥鍖栬鍗曟瑙� @@ -637,7 +920,10 @@ }, mounted() { + console.log('ECharts 鏄惁瀛樺湪锛�', typeof echarts !== 'undefined'); // 搴旇緭鍑� true + this.initChart(); this.initBaseParams(); + window.addEventListener('resize', this.handleResize) }, }; </script> @@ -859,4 +1145,129 @@ .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; +//} + +.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