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">-->
+<!--        &lt;!&ndash; 鏁版嵁姒傝鍗$墖 &ndash;&gt;-->
+<!--&lt;!&ndash;        <div class="stats-cards">&ndash;&gt;-->
+<!--&lt;!&ndash;          <div class="stat-card">&ndash;&gt;-->
+<!--&lt;!&ndash;            <div class="stat-header">&ndash;&gt;-->
+<!--&lt;!&ndash;              <span class="stat-title">鎬绘祻瑙堥噺</span>&ndash;&gt;-->
+<!--&lt;!&ndash;              <i class="fa fa-eye stat-icon"></i>&ndash;&gt;-->
+<!--&lt;!&ndash;            </div>&ndash;&gt;-->
+<!--&lt;!&ndash;            <div class="stat-value">{{ totalPv }}</div>&ndash;&gt;-->
+<!--&lt;!&ndash;            <div class="stat-trend positive">&ndash;&gt;-->
+<!--&lt;!&ndash;              <i class="fa fa-arrow-up"></i> 12.5% 杈冧笂鏈�&ndash;&gt;-->
+<!--&lt;!&ndash;            </div>&ndash;&gt;-->
+<!--&lt;!&ndash;          </div>&ndash;&gt;-->
 
+<!--&lt;!&ndash;          <div class="stat-card">&ndash;&gt;-->
+<!--&lt;!&ndash;            <div class="stat-header">&ndash;&gt;-->
+<!--&lt;!&ndash;              <span class="stat-title">骞冲潎鏃ユ祻瑙堥噺</span>&ndash;&gt;-->
+<!--&lt;!&ndash;              <i class="fa fa-calendar stat-icon"></i>&ndash;&gt;-->
+<!--&lt;!&ndash;            </div>&ndash;&gt;-->
+<!--&lt;!&ndash;            <div class="stat-value">{{ avgDailyPv }}</div>&ndash;&gt;-->
+<!--&lt;!&ndash;            <div class="stat-trend positive">&ndash;&gt;-->
+<!--&lt;!&ndash;              <i class="fa fa-arrow-up"></i> 8.3% 杈冧笂鏈�&ndash;&gt;-->
+<!--&lt;!&ndash;            </div>&ndash;&gt;-->
+<!--&lt;!&ndash;          </div>&ndash;&gt;-->
+
+<!--&lt;!&ndash;          <div class="stat-card">&ndash;&gt;-->
+<!--&lt;!&ndash;            <div class="stat-header">&ndash;&gt;-->
+<!--&lt;!&ndash;              <span class="stat-title">鏈�楂樺崟鏃ユ祻瑙堥噺</span>&ndash;&gt;-->
+<!--&lt;!&ndash;              <i class="fa fa-trophy stat-icon"></i>&ndash;&gt;-->
+<!--&lt;!&ndash;            </div>&ndash;&gt;-->
+<!--&lt;!&ndash;            <div class="stat-value">{{ maxDailyPv }}</div>&ndash;&gt;-->
+<!--&lt;!&ndash;            <div class="stat-trend">{{ maxPvDate }}</div>&ndash;&gt;-->
+<!--&lt;!&ndash;          </div>&ndash;&gt;-->
+<!--&lt;!&ndash;        </div>&ndash;&gt;-->
+
+<!--        &lt;!&ndash; 鍥捐〃鍖哄煙 &ndash;&gt;-->
+<!--        <div class="chart-wrapper">-->
+<!--          <div class="chart-header">-->
+<!--            <h2>PV/UV 瓒嬪娍鍥�</h2>-->
+<!--          </div>-->
+<!--          <div ref="chartDom" class="chart-container"></div>-->
+<!--        </div>-->
+
+<!--        &lt;!&ndash; 鏁版嵁鏇存柊鏃堕棿 &ndash;&gt;-->
+<!--&lt;!&ndash;        <div class="update-time">&ndash;&gt;-->
+<!--&lt;!&ndash;          鏁版嵁鏇存柊鏃堕棿: {{ updateTime }}&ndash;&gt;-->
+<!--&lt;!&ndash;        </div>&ndash;&gt;-->
+<!--      </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