Pārlūkot izejas kodu

Merge branch 'master' of http://1.14.104.71:10880/root/ylrz_his_scrm_adminUI

lmx 3 dienas atpakaļ
vecāks
revīzija
45a4ef8065

+ 9 - 3
.env.prod-sft

@@ -17,12 +17,18 @@ VUE_APP_OBS_SECRET_ACCESS_KEY = sbyeNJLbcYmH6copxeFP9pAoksM4NIT9Zw4x0SRX
 # 存储桶配置
 VUE_APP_OBS_SERVER = https://obs.cn-north-4.myhuaweicloud.com
 # 存储桶配置
-VUE_APP_COS_BUCKET = sft-1361917636
+#VUE_APP_COS_BUCKET = sft-1361917636
+VUE_APP_COS_BUCKET = cqsft-1323137866
+# 存储桶配置
+VUE_APP_OBS_BUCKET = sft-hw079058881
 # 存储桶配置
 VUE_APP_COS_REGION = ap-chongqing
-# 线路一地址
-VUE_APP_VIDEO_LINE_1 = https://video.sft12.cn
 
+# 线路一地址
+#VUE_APP_VIDEO_LINE_1 = https://video.sft12.cn
+VUE_APP_VIDEO_LINE_1 = https://cqsfttcpv.ylrzcloud.com
+# 线路二地址
+VUE_APP_VIDEO_LINE_2 = https://sftobs.ylrztop.com
 
 # 开发环境配置
 ENV = 'development'

+ 3 - 0
.gitignore

@@ -25,3 +25,6 @@ pnpm-debug.log*
 
 package-lock.json
 yarn.lock
+
+# AGENTS.md - 项目指导文档,不上传到远程仓库
+AGENTS.md

+ 8 - 0
src/api/his/integralOrder.js

@@ -132,4 +132,12 @@ export function getIntegralTemplate(){
     url: '/his/integralOrder/importUpdateOrderTemplate',
     method: 'get'
   })
+}
+
+// 获取订单操作记录
+export function getOrderLogs(orderId) {
+  return request({
+    url: '/his/logs/order/' + orderId,
+    method: 'get'
+  })
 }

+ 86 - 0
src/api/qw/applyIpad.js

@@ -0,0 +1,86 @@
+import request from '@/utils/request'
+
+// 查询分配记录列表
+export function listRecords(query) {
+  return request({
+    url: '/qw/records/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询分配记录详细
+export function getRecords(id) {
+  return request({
+    url: '/qw/records/' + id,
+    method: 'get'
+  })
+}
+
+// 新增分配记录
+export function addRecords(data) {
+  return request({
+    url: '/qw/records',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改分配记录
+export function updateRecords(data) {
+  return request({
+    url: '/qw/records',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除分配记录
+export function delRecords(id) {
+  return request({
+    url: '/qw/records/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出分配记录
+export function exportRecords(query) {
+  return request({
+    url: '/qw/records/export',
+    method: 'get',
+    params: query
+  })
+}
+
+export function apply(applyCount) {
+  return request({
+    url: '/qw/records/apply',
+    method: 'get',
+    params: applyCount
+  })
+}
+// 新增分配记录
+//@PostMapping("/batchUpdate")
+// public AjaxResult batchUpdate(@RequestBody Long[] ids)
+//后端接收结构
+export function batchUpdate(data) {
+  return request({
+    url: '/qw/records/batchUpdate',
+    method: 'post',
+    data: data
+  })
+}
+// 获取服务器信息
+export function getServerInfo(id) {
+  return request({
+    url: '/qw/records/server/' + id,
+    method: 'get'
+  })
+}
+export function release(data) {
+  return request({
+    url: '/qw/records/release',
+    method: 'post',
+    data: data
+  })
+}

+ 9 - 0
src/api/qw/qwIpadServer.js

@@ -50,4 +50,13 @@ export function exportQwIpadServer(query) {
     method: 'get',
     params: query
   })
+}
+
+// 新增ipad服务器
+export function release(data) {
+  return request({
+    url: '/qw/records/release',
+    method: 'post',
+    data: data
+  })
 }

+ 4 - 4
src/utils/obs.js

@@ -40,10 +40,10 @@ export const uploadToOBS = async (file, progressCallback, type, cancelCallback)
         })
       }
       //四福堂专属配置
-      // resolve({
-      //   "RequestId": "",
-      //   "urlPath": ""
-      // })
+   /*   resolve({
+        "RequestId": "",
+        "urlPath": ""
+      })*/
       obsClient.putObject(
         {
           Bucket: process.env.VUE_APP_OBS_BUCKET,

+ 75 - 2
src/views/components/his/integralOrderDetails.vue

@@ -106,6 +106,27 @@
 
       </el-table>
     </div>
+    
+    <!-- 操作记录 -->
+    <div class="contentx" v-if="item != null" style="padding-bottom: 70px;">
+      <div class="desct">
+        操作记录
+      </div>
+      <el-table :data="orderLogs" border style="width: 100%; margin-top: 20px;" v-loading="logsLoading">
+        <!-- <el-table-column prop="changeType" label="操作类型" align="center" width="120">
+        </el-table-column> -->
+        <el-table-column prop="changeTime" label="操作时间" align="center" width="180">
+          <template slot-scope="scope">
+            {{ parseTime(scope.row.changeTime) }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="changeMessage" label="操作备注" align="center">
+        </el-table-column>
+        <!-- <el-table-column prop="operator" label="操作员" align="center" width="120">
+        </el-table-column> -->
+        
+      </el-table>
+    </div>
     <el-dialog width="35%" title="发货" :visible.sync="sendVisible" append-to-body @close="sendCancel">
       <el-form ref="form" :model="form" label-width="120px">
         <el-form-item label="快递名称" prop="deliveryName">
@@ -179,7 +200,10 @@
     </el-dialog>
 
     <el-dialog :title="expressDialog.title" :visible.sync="expressDialog.open" width="600px" append-to-body>
-      <el-table style="margin-top: 20px;width: 100%" ref="orderHistoryTable" :data="traces" border>
+      <div style="margin-bottom: 10px; text-align: right;">
+        <el-button type="primary" size="small" @click="syncExpressInfo" :loading="syncLoading">同步物流信息</el-button>
+      </div>
+      <el-table style="margin-top: 20px;width: 100%" ref="orderHistoryTable" :data="traces" border v-loading="tableLoading">
         <el-table-column label="操作时间" width="160" align="center">
           <template slot-scope="scope">
             {{ scope.row.AcceptTime }}
@@ -345,7 +369,7 @@
 </template>
 
 <script>
-import { getExpress,mandatoryRefunds,getCitys,finishOrder, listIntegralOrder, sendgoods, getIntegralOrder, delIntegralOrder, addIntegralOrder, updateIntegralOrder, exportIntegralOrder, getOrderUserPhone } from "@/api/his/integralOrder";
+import { getExpress,mandatoryRefunds,getCitys,finishOrder, listIntegralOrder, sendgoods, getIntegralOrder, delIntegralOrder, addIntegralOrder, updateIntegralOrder, exportIntegralOrder, getOrderUserPhone, getOrderLogs } from "@/api/his/integralOrder";
 import { getExpressList } from "@/api/his/express";
 import { listAccount } from "@/api/his/dfAccount";
 export default {
@@ -429,6 +453,11 @@ export default {
       selectedDistrict: null, // 选中的区
       detailAddress: '', // 详细地址
       deliveryTypeOptions:[],
+      // 操作记录相关数据
+      orderLogs: [], // 订单操作记录
+      logsLoading: false, // 操作记录加载状态
+      syncLoading: false, // 同步物流信息按钮加载状态
+      tableLoading: false // 物流信息表格加载状态
     }
   },
   created() {
@@ -726,13 +755,31 @@ export default {
     },
     showExpress() {
       this.expressDialog.open = true;
+      this.loadExpressInfo();
+    },
+    // 加载物流信息
+    loadExpressInfo() {
+      this.tableLoading = true;
       getExpress(this.item.orderId).then(response => {
         this.express = response.data;
         if (this.express != null && this.express.Traces != null) {
           this.traces = this.express.Traces
+        } else {
+          this.traces = [];
         }
+        this.tableLoading = false;
+      }).catch(error => {
+        this.traces = [];
+        this.tableLoading = false;
+        console.error('获取物流信息失败:', error);
       });
     },
+    // 同步物流信息
+    syncExpressInfo() {
+      this.syncLoading = true;
+      this.loadExpressInfo();
+      this.syncLoading = false;
+    },
     sendGoods() {
       // 手动验证所有必填字段
       if (!this.selectedRow) {
@@ -772,9 +819,12 @@ export default {
     },
     getDetails(orderId) {
       this.item = null;
+      this.orderLogs = []; // 清空操作记录
       getIntegralOrder(orderId).then(response => {
         this.item = response.data;
         this.prod = [JSON.parse(this.item.itemJson)][0];
+        // 获取操作记录
+        this.getOrderLogsData();
       });
     },
     // 代服账号选择变化
@@ -884,6 +934,29 @@ export default {
         console.error('完成订单失败:', error);
       });
     },
+    // 获取订单操作记录
+    getOrderLogsData() {
+      if (!this.item || !this.item.orderId) {
+        return;
+      }
+      
+      this.logsLoading = true;
+      getOrderLogs(this.item.orderId).then(response => {
+        if (response.code === 200) {
+          // 按照时间升序排列
+          this.orderLogs = response.data.sort((a, b) => {
+            return new Date(a.changeTime) - new Date(b.changeTime);
+          });
+        } else {
+          this.orderLogs = [];
+        }
+        this.logsLoading = false;
+      }).catch(error => {
+        this.orderLogs = [];
+        this.logsLoading = false;
+        console.error('获取操作记录失败:', error);
+      });
+    }
   }
 }
 </script>

+ 2313 - 0
src/views/components/index/statisticsDashboard.vue

@@ -0,0 +1,2313 @@
+<template>
+  <div class="statistics-dashboard">
+    <!-- 数据概览 (Data Overview) -->
+    <el-card class="overview-section" shadow="never">
+      <el-row :gutter="20">
+        <el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="16" class="companybox">
+          <img src="@/assets/images/topbg.png" alt="" class="topimg">
+          <img src="@/assets/images/topbg.png" alt="" class="bottomimg">
+          <div class="companyboxtitle">
+            企业数据
+          </div>
+          <div class="companyflex">
+            <div class="topbg companycard cardafter">
+              <div class="card-title1">
+                <img src="@/assets/images/tab_company.png" alt="" class="icon-img">
+                分公司数量
+              </div>
+
+              <div class="card-value highlight1">
+                <count-to :start-val="0" :end-val="dealderCount" :duration="3600"
+                          class="card-panel-num companynumber" />
+              </div>
+            </div>
+            <div class="companycard cardafter">
+              <div class="card-title1">
+                <img src="@/assets/images/salesperson.png" alt="" class="icon-img">
+                销售数量
+              </div>
+              <div class="card-value highlight1">
+                <count-to :start-val="0" :end-val="groupMgrCount" :duration="3600"
+                          class="card-panel-num companynumber" />
+              </div>
+            </div>
+            <div class="companycard cardafter">
+              <div class="card-title1">
+                <img src="@/assets/images/member.png" alt="" class="icon-img">
+                会员数量
+              </div>
+              <div class="card-value highlight1">
+                <count-to :start-val="0" :end-val="memberCount" :duration="3600" class="card-panel-num companynumber" />
+                <span class="highlight-today-add companyadd">+{{todayIncreaseUserNum}}</span>
+              </div>
+
+            </div>
+            <div class="cardafter companycard">
+              <div class="card-title1">
+                <img src="@/assets/images/tab_enterprise.png" alt="" class="icon-img">
+                企微数量
+              </div>
+              <div class="card-value highlight1">
+                <count-to :start-val="0" :end-val="qwMemberNum" :duration="3600" class="card-panel-num companynumber" />
+              </div>
+            </div>
+            <div class="botttombg companycard">
+              <div class="card-title1">
+                <svg-icon icon-class="phone" />
+                pad使用情况
+              </div>
+              <div class="card-value highlight1">
+                <count-to :start-val="0" :end-val="padUsedNum" :duration="3600" class="card-panel-num companynumber" />
+                /
+                <template v-if="typeof padTotalNum === 'number'">
+                  <count-to :start-val="0" :end-val="padTotalNum" :duration="1800" class="card-panel-num companynumber" />
+                </template>
+                <template v-else>
+                  <span class="card-panel-num companynumber">{{ padTotalNum }}</span>
+                </template>
+              </div>
+            </div>
+          </div>
+        </el-col>
+
+
+        <el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8" class="propertyboxtitle">
+          <div class="property_title">
+            资产概览
+          </div>
+          <div class="propertyboxflex">
+            <div class="property-card propertyline">
+              <div class="property-title">
+                <i class="el-icon-money"></i>
+                企业资产(元)
+              </div>
+              <div class="card-value highlight">
+                <count-to :start-val="0" :end-val="balance" :duration="3600" class="card-panel-num" />
+              </div>
+            </div>
+            <div class="property-card propertyline">
+              <div class="property-title">
+                <i class="el-icon-money"></i>
+                润天余额(元)
+              </div>
+              <div class="card-value highlight">
+                <count-to :start-val="0" :end-val="runTianBalance" :duration="3600" class="card-panel-num" />
+              </div>
+            </div>
+            <div class="property-card">
+              <div class="property-title">
+                <span>今日消耗 (元)</span>
+              </div>
+              <div class="card-value highlight" style="color: rgba(32, 33, 36, 1);margin-top: 10px;">
+                <count-to :start-val="0" :end-val="todayComsumption" :duration="3600" class="card-panel-num" />
+              </div>
+              <div class="card-compare">
+                较昨日 <span>+1</span>
+              </div>
+            </div>
+          </div>
+
+        </el-col>
+      </el-row>
+
+      <el-row :gutter="20">
+        <el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="16">
+          <div class="operatetitle">
+            经营数据
+          </div>
+          <div class="operatetitle-col">
+            <div class="operatetitle-card">
+              <div class="card-title">
+                <i class="el-icon-shopping-cart-full"></i>
+                收款总数
+              </div>
+              <div class="operate-value highlight">
+                <count-to :start-val="0" :end-val="recvTotalNum" :duration="3600" class="card-panel-num" />
+                <div class="yesterdaybox">
+                  较昨日 <span class="highlight-today-add2">+{{recvTodayNum}}</span>
+                </div>
+              </div>
+              <div class="card-badge">
+              </div>
+            </div>
+            <div class="operatetitle-card">
+              <div class="card-title">
+                <i class="el-icon-shopping-cart-full"></i>
+                订单总数
+              </div>
+              <div class="operate-value highlight">
+                <count-to :start-val="0" :end-val="orderTotalNum" :duration="3600" class="card-panel-num" />
+                <div class="yesterdaybox">
+                  较昨日 <span class="highlight-today-add2">+{{todayOrderNum}}</span>
+                </div>
+
+              </div>
+              <div class="card-badge">
+              </div>
+
+            </div>
+            <div class="operatetitle-card">
+              <div class="card-title">
+                平台今日看课人数
+              </div>
+              <div class="operate-value highlight">
+                <count-to :start-val="0" :end-val="todayWatchUserCount" :duration="3600" class="card-panel-num" />
+              </div>
+              <div class="card-sub">
+                <span>配额上限</span>
+                <span class="sub-value">
+                  <count-to :start-val="0" :end-val="todayWatchUserCount" :duration="3600" class="card-panel-num"
+                            style="color: rgba(49, 185, 154, 1);" />
+                  /
+                  <count-to :start-val="0" :end-val="versionLimit" :duration="3600" class="card-panel-num" />
+                </span>
+              </div>
+              <el-progress :percentage="versionLimitPercent" :show-text="false"
+                           color="#409EFF"></el-progress>
+            </div>
+            <div class="operatetitle-card">
+              <div class="card-title">
+                <i class="el-icon-shopping-cart-full"></i>
+                商品总数
+              </div>
+              <div class="operate-value highlight">
+                <count-to :start-val="0" :end-val="goodsTotalNum" :duration="3600" class="card-panel-num" />
+                <div class="yesterdaybox">
+                  较昨日 <span class="highlight-today-add2">+{{todayGoodsNum}}</span>
+                </div>
+
+              </div>
+              <div class="card-badge">
+              </div>
+            </div>
+          </div>
+
+        </el-col>
+
+
+        <el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8" style="padding-left: 15px;">
+
+          <div class="internetbox">
+            <div class="internet-cardtop">
+              <div class="cardinnerbox">
+                <div class="cardtopimg">
+                  <img src="@/assets/images/liuliang.png" alt=""><span>剩余流量</span>
+                </div>
+                <div class="cardtopnumber">
+                  <span>{{formatBytes(this.trafficCount)}}</span>
+                </div>
+              </div>
+              <div class="progress">
+                <el-progress :percentage="90" :show-text="false" define-back-color="#000">
+
+                </el-progress>
+              </div>
+              <div class="cardinnerbox2">
+                <div>
+                  今日消耗 <span>{{formatBytes(this.todayTraffic)}}</span>
+                </div>
+                <div>
+                  本月 <span>{{formatBytes(this.thisMonthTraffic)}}</span>
+                </div>
+              </div>
+            </div>
+
+            <div class="internetbox-messge">
+              <div class="internet-card">
+                <img src="@/assets/images/message.png" alt="">
+
+                <span class="internet-title">
+                  短信剩余条数 (条)
+                </span>
+              </div>
+              <div class="internet-number">
+                0
+              </div>
+            </div>
+          </div>
+        </el-col>
+      </el-row>
+    </el-card>
+    <!-- 分析概览 (Analysis Overview) -->
+    <div class="analysis-section" shadow="never">
+      <div slot="header" class="header">
+        <div>分析概览</div>
+        <div class="tab-group">
+          <el-radio-group v-model="queryTime" size="medium" @change="handleAnalysis">
+            <el-radio-button label="今日"></el-radio-button>
+            <el-radio-button label="昨日"></el-radio-button>
+            <el-radio-button label="本周"></el-radio-button>
+            <el-radio-button label="本月"></el-radio-button>
+            <el-radio-button label="上月"></el-radio-button>
+          </el-radio-group>
+        </div>
+        <div class="action-group">
+          <div v-if="this.$store.state.user.medicalMallConfig.statics">
+            <!-- 选择部门 -->
+            <el-select v-model="deptId" placeholder="请选择部门" size="small" @change="handleDeptChange" style="width: 150px">
+              <el-option
+                v-for="company in deptOptions"
+                :key="company.deptId"
+                :label="company.deptName"
+                :value="company.deptId"
+              />
+            </el-select>
+            <!-- 选择销售公司 -->
+            <el-select  v-model="companyId" placeholder="请选择销售公司" size="small" clearable @change="handleCompanyChange" style="width: 180px" >
+              <el-option
+                v-for="company in companyOptions"
+                :key="company.companyId"
+                :label="company.companyName"
+                :value="company.companyId"
+              />
+            </el-select>
+          </div>
+          <el-radio-group v-model="userTypeText" @change="handleUserType">
+            <el-radio-button label="会员"></el-radio-button>
+            <el-radio-button label="企微"></el-radio-button>
+          </el-radio-group>
+
+          <el-dropdown @command="handleAutoRefresh" trigger="click">
+            <el-button size="small" plain>
+              自动刷新
+              <i class="el-icon-arrow-down el-icon--right"></i>
+            </el-button>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item :command="0" :class="{ 'is-active': !autoRefreshInterval }">关闭</el-dropdown-item>
+              <el-dropdown-item :command="5" :class="{ 'is-active': autoRefreshInterval === 5 }">5分钟</el-dropdown-item>
+              <el-dropdown-item :command="10"
+                                :class="{ 'is-active': autoRefreshInterval === 10 }">10分钟</el-dropdown-item>
+              <el-dropdown-item :command="15"
+                                :class="{ 'is-active': autoRefreshInterval === 15 }">15分钟</el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+          <el-button size="small" plain icon="el-icon-refresh" type="primary" @click="manualRefresh">手动刷新</el-button>
+        </div>
+      </div>
+    </div>
+    <div>
+      <el-row :gutter="20">
+        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" style="position: relative">
+          <div class="analysis-card-check" :class="selectedDiv===0?'analysis-card-check-selected color':''"
+               @click="handleToggleDiv(0)">
+            <div class="analysis-card">
+              <img class="card-icon" src="@/assets/images/cishu_views.png"></img>
+              <div class="card-content">
+                <div class="card-row">
+                  <span>观看人数</span>
+                  <span class="highlight">
+                    <count-to :start-val="0" :end-val="watchUserCount" :duration="3600" class="card-panel-num" />
+                  </span>
+                </div>
+                <div class="card-row">
+                  <span>完播人数</span>
+                  <span class="highlight">
+                    <count-to :start-val="0" :end-val="completedUserCount" :duration="3600" class="card-panel-num" />
+                  </span>
+                </div>
+                <div class="card-row">
+                  <span>完播率</span>
+                  <span class="highlight">{{completedRate}}%</span>
+                </div>
+              </div>
+            </div>
+            <div class="analysis-card">
+              <img class="card-icon" src="@/assets/images/number_views.png"></img>
+              <div class="card-content">
+                <div class="card-row">
+                  <span>观看次数</span>
+                  <span class="highlight-red">
+                    <count-to :start-val="0" :end-val="watchCount" :duration="3600" class="card-panel-num" /></span>
+                </div>
+                <div class="card-row">
+                  <span>完播次数</span>
+                  <span class="highlight-red">
+                    <count-to :start-val="0" :end-val="completedCount" :duration="3600" class="card-panel-num" />
+                  </span>
+                </div>
+                <div class="card-row">
+                  <span>视频完播率</span>
+                  <span class="highlight-red">{{watchRate}}%</span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </el-col>
+
+        <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6" style="position: relative">
+          <div class="analysis-card-check" :class="selectedDiv===1?'analysis-card-check-selected color':''"
+               @click="handleToggleDiv(1)">
+            <div class="analysis-card">
+              <img class="card-icon" src="@/assets/images/renshu_views.png"></img>
+              <div class="card-content">
+                <div class="card-row">
+                  <span>答题人数</span>
+                  <span class="highlight-black">
+                    <count-to :start-val="0" :end-val="answerMemberCount" :duration="3600" class="card-panel-num" />
+                  </span>
+                </div>
+                <div class="card-row">
+                  <span>正确人数</span>
+                  <span class="highlight-black">
+                    <count-to :start-val="0" :end-val="correctUserCount" :duration="3600" class="card-panel-num" />
+                  </span>
+                </div>
+                <div class="card-row">
+                  <span>正确率</span>
+                  <span class="highlight-black">{{correctRate}}%</span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </el-col>
+
+        <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6"  style="position: relative">
+          <div class="analysis-card-check" :class="selectedDiv===2?'analysis-card-check-selected color':''"
+               @click="handleToggleDiv(2)">
+            <div class="analysis-card">
+              <img class="card-icon" src="@/assets/images/hongbao_views.png"></img>
+              <div class="card-content">
+                <div class="card-row">
+                  <span>答题红包个数</span>
+                  <span class="highlight-black">
+                    <count-to :start-val="0" :end-val="rewardCount" :duration="3600" class="card-panel-num" />
+                  </span>
+                </div>
+                <div class="card-row">
+                  <span>答题红包金额(元)</span>
+                  <span class="highlight-black">
+                    <count-to :start-val="0" :end-val="rewardMoney" :duration="3600" class="card-panel-num" /></span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </el-col>
+      </el-row>
+    </div>
+
+    <!-- 图表区域 (Charts Area) -->
+    <transition name="fade">
+      <el-row :gutter="20" class="charts-section" v-show="selectedDiv===0">
+        <el-col :span="12">
+          <el-card shadow="never">
+            <div slot="header" class="chart-header">
+              <span>会员观看、完播人数趋势图</span>
+              <div class="legend">
+                <div class="legend-item">
+                  <span class="dot viewer-dot"></span>
+                  <span>观看人数</span>
+                </div>
+                <div class="legend-item">
+                  <span class="dot complete-dot"></span>
+                  <span>完播人数</span>
+                </div>
+              </div>
+              <!--              <el-button size="small" plain class="view-more">平台每日统计 <i class="el-icon-arrow-right"></i></el-button>-->
+            </div>
+            <div ref="viewerChart" class="chart-container"></div>
+          </el-card>
+        </el-col>
+
+
+        <el-col :span="12">
+          <el-card shadow="never">
+            <div slot="header" class="chart-header">
+              <span>经销商看客统计</span>
+              <div class="legend">
+                <div class="legend-item">
+                  <span class="dot viewer-dot"></span>
+                  <span>观看人数</span>
+                </div>
+                <div class="legend-item">
+                  <span class="dot complete-dot"></span>
+                  <span>完播人数</span>
+                </div>
+              </div>
+            </div>
+            <div ref="dealerChartNew" class="chart-container"></div>
+          </el-card>
+        </el-col>
+
+        <!--        <el-col :span="12">-->
+        <!--          <el-card shadow="never">-->
+        <!--            <div slot="header" class="chart-header">-->
+        <!--              <span>经销商会员观看TOP10</span>-->
+        <!--              <div class="legend">-->
+        <!--                <el-radio-group v-model="viewerType" size="small" @change="handleDealerChartData">-->
+        <!--                  <el-radio-button label="0">按观看人数</el-radio-button>-->
+        <!--                  <el-radio-button label="1">按完播人数</el-radio-button>-->
+        <!--                </el-radio-group>-->
+        <!--              </div>-->
+        <!--              &lt;!&ndash;              <el-button size="small" plain class="view-more">经销商统计 <i class="el-icon-arrow-right"></i></el-button>&ndash;&gt;-->
+        <!--            </div>-->
+        <!--            <div ref="dealerChart" class="chart-container"></div>-->
+        <!--          </el-card>-->
+        <!--        </el-col>-->
+      </el-row>
+    </transition>
+    <transition name="fade">
+      <el-row :gutter="20" class="charts-section" v-show="selectedDiv===1">
+        <el-card shadow="never">
+          <div slot="header" class="chart-header">
+            <span>课程观看TOP10</span>
+            <div class="legend">
+              <el-radio-group v-model="viewerType" size="small" @change="handleCourseWatchChart">
+                <el-radio-button label="0">按观看人数</el-radio-button>
+                <el-radio-button label="1">按完播人数</el-radio-button>
+                <el-radio-button label="2">按答题人数</el-radio-button>
+                <el-radio-button label="3">按正确人数</el-radio-button>
+              </el-radio-group>
+            </div>
+            <div class="legend">
+              <el-radio-group v-model="delerSort" @change="handleCourseWatchChart">
+                <el-radio label="DESC">前10名</el-radio>
+                <el-radio label="ASC">倒数10名</el-radio>
+              </el-radio-group>
+            </div>
+            <div class="legend">
+              <div class="legend-item">
+                <span class="dot viewer-dot"></span>
+                <span>观看人数</span>
+              </div>
+              <div class="legend-item">
+                <span class="dot complete-dot"></span>
+                <span>完播人数</span>
+              </div>
+              <div class="legend-item">
+                <span class="dot" style="background-color: #E6A23C"></span>
+                <span>答题人数</span>
+              </div>
+              <div class="legend-item">
+                <span class="dot" style="background-color: #F56C6C"></span>
+                <span>正确人数</span>
+              </div>
+            </div>
+            <!--            <el-button size="small" plain class="view-more">经销商统计 <i class="el-icon-arrow-right"></i></el-button>-->
+          </div>
+          <div ref="courseWatchChart" class="chart-container"></div>
+        </el-card>
+      </el-row>
+    </transition>
+
+    <transition name="fade">
+      <el-row :gutter="20" class="charts-section" v-show="selectedDiv===2">
+        <el-col :span="12">
+          <el-card shadow="never">
+            <div slot="header" class="chart-header">
+              <span>答题红包金额TOP10</span>
+              <div class="legend">
+                <el-radio-group v-model="dataType" size="small" @change="handleAnswerRedPackViewerChart">
+                  <el-radio-button label="0">按经销商排行</el-radio-button>
+                  <el-radio-button label="1">按课程排行</el-radio-button>
+                </el-radio-group>
+              </div>
+              <!--              <el-button size="small" plain class="view-more">红包记录 <i class="el-icon-arrow-right"></i></el-button>-->
+            </div>
+            <div ref="answerRedPackViewerChart" class="chart-container"></div>
+          </el-card>
+        </el-col>
+        <el-col :span="12">
+          <el-card shadow="never">
+            <div slot="header" class="chart-header">
+              <span>答题红包金额趋势图</span>
+              <div class="legend">
+                <div class="legend-item">
+                  <span class="dot viewer-dot"></span>
+                  <span>答题红包金额</span>
+                </div>
+              </div>
+              <!--              <el-button size="small" plain class="view-more">红包记录 <i class="el-icon-arrow-right"></i></el-button>-->
+            </div>
+            <div ref="answerRedPackMoneyViewerChart" class="chart-container"></div>
+          </el-card>
+        </el-col>
+      </el-row>
+    </transition>
+    <el-row :gutter="20" class="charts-section">
+      <el-col :span="12">
+        <el-card shadow="never">
+          <div slot="header" class="chart-header">
+            <span>本月订单数</span>
+            <div class="legend">
+              <div class="legend-item">
+                <span class="dot viewer-dot"></span>
+                <span>订单数</span>
+              </div>
+              <div class="legend-item">
+                <span class="dot complete-dot"></span>
+                <span>订单金额</span>
+              </div>
+            </div>
+          </div>
+          <div ref="viewerOrderChart" class="chart-container"></div>
+        </el-card>
+      </el-col>
+      <el-col :span="12">
+        <el-card shadow="never">
+          <div slot="header" class="chart-header">
+            <span>本月收款数</span>
+            <div class="legend">
+              <div class="legend-item">
+                <span class="dot viewer-dot"></span>
+                <span>收款数</span>
+              </div>
+              <div class="legend-item">
+                <span class="dot complete-dot"></span>
+                <span>收款金额</span>
+              </div>
+            </div>
+          </div>
+          <div ref="viewerReceiveChart" class="chart-container"></div>
+        </el-card>
+      </el-col>
+    </el-row>
+    <br/>
+  </div>
+</template>
+
+<script>
+import * as echarts from 'echarts'
+import CountTo from "vue-count-to";
+import {
+  analysisPreview,
+  authorizationInfo,
+  dealerAggregated, deaMemberTopTen, rechargeComsumption, rewardMoneyTopTen, rewardMoneyTrend,
+  smsBalance, thisMonthOrderCount, thisMonthRecvCount, trafficLog,
+  watchCourseTopTen, watchEndPlayTrend,getWatchCourseStatisticsData
+} from "@/api/statistics/statistics";
+import dayjs from 'dayjs';
+import { listDept } from '@/api/system/dept'
+import { listCompany } from '@/api/his/company'
+
+
+const viewCharOption = {
+  tooltip: {
+    trigger: 'axis',
+    axisPointer: {
+      type: 'shadow'
+    }
+  },
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '3%',
+    containLabel: true
+  },
+  xAxis: {
+    type: 'category',
+    data: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23']
+  },
+  yAxis: {
+    type: 'value'
+  },
+  series: [
+    {
+      name: '观看人数',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#409EFF'
+      }
+    },
+    {
+      name: '完播人数',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#67C23A'
+      }
+    }
+  ]
+}
+
+const dealerOptionNew = {
+  tooltip: {
+    trigger: 'axis',
+    axisPointer: {
+      type: 'shadow'
+    }
+  },
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '3%',
+    containLabel: true
+  },
+  xAxis: {
+    type: 'category',
+    axisLabel: {
+      rotate: 30, // 设置标签倾斜45度
+      // fontSize: 12, // 减小字体大小
+      interval: 0, // 显示所有标签
+      // 可选:限制标签宽度并截断
+      width: 80,
+      overflow: 'truncate',
+      // 可选:设置标签的对齐方式
+      margin: 20,
+      fontWeight: 'bold' // 设置字体加粗
+    }
+  },
+  yAxis: {
+    type: 'value'
+  },
+  series: [
+    {
+      name: '观看人数',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#409EFF'
+      }
+    },
+    {
+      name: '完播人数',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#67C23A'
+      }
+    }
+  ]
+}
+
+const thisMonthOrderCountOption = {
+  tooltip: {
+    trigger: 'axis',
+    axisPointer: {
+      type: 'shadow'
+    }
+  },
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '3%',
+    containLabel: true
+  },
+  xAxis: {
+    type: 'category',
+    data: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23']
+  },
+  yAxis: {
+    type: 'value'
+  },
+  series: [
+    {
+      name: '订单数',
+      type: 'line',
+      data: [],
+      itemStyle: {
+        color: '#409EFF'
+      }
+    },
+    {
+      name: '订单金额',
+      type: 'line',
+      data: [],
+      itemStyle: {
+        color: '#67C23A'
+      }
+    }
+  ]
+}
+
+const thisMonthRecvCountOption = {
+  tooltip: {
+    trigger: 'axis',
+    axisPointer: {
+      type: 'shadow'
+    }
+  },
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '3%',
+    containLabel: true
+  },
+  xAxis: {
+    type: 'category',
+    data: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23']
+  },
+  yAxis: {
+    type: 'value'
+  },
+  series: [
+    {
+      name: '收款数',
+      type: 'line',
+      data: [],
+      itemStyle: {
+        color: '#409EFF'
+      }
+    },
+    {
+      name: '收款金额',
+      type: 'line',
+      data: [],
+      itemStyle: {
+        color: '#67C23A'
+      }
+    }
+  ]
+}
+const dealerOption = {
+  tooltip: {
+    trigger: 'axis',
+    axisPointer: {
+      type: 'shadow'
+    }
+  },
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '3%',
+    containLabel: true
+  },
+  xAxis: {
+    type: 'value'
+  },
+  yAxis: {
+    type: 'category',
+    data: []
+  },
+  series: [
+    {
+      name: '观看人数',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#409EFF'
+      }
+    }
+  ]
+}
+
+const courseWatchOption = {
+  tooltip: {
+    trigger: 'axis',
+    axisPointer: {
+      type: 'shadow'
+    }
+  },
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '8%',
+    top: '3%',
+    containLabel: true
+  },
+  xAxis: {
+    type: 'category',
+    data: [],
+    axisLabel: {
+      interval: 0,
+      rotate: 30,
+      fontSize: 10,
+      width: 100,
+      overflow: 'truncate'
+    }
+  },
+  yAxis: {
+    type: 'value',
+    splitLine: {
+      lineStyle: {
+        type: 'dashed'
+      }
+    }
+  },
+  series: [
+    {
+      name: '观看人数',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#409EFF'
+      }
+    },
+    {
+      name: '完播人数',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#67C23A'
+      }
+    },
+    {
+      name: '答题人数',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#E6A23C'
+      }
+    },
+    {
+      name: '正确人数',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#F56C6C'
+      }
+    }
+  ]
+}
+
+const lineChartOption = {
+  tooltip: {
+    trigger: 'axis',
+    axisPointer: {
+      type: 'cross' // 改为 'cross' 更适合折线图
+    }
+  },
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '8%', // 如果x轴标签旋转,可能需要更大的 bottom
+    top: '5%',    // 增加一点顶部空间给可能的 Y 轴名称
+    containLabel: true
+  },
+  xAxis: {
+    type: 'time', // X轴类型改为 'time'
+    // data: [], // 时间轴不需要单独设置 data,数据在 series 中提供
+    axisLabel: {
+      // interval: 0, // 时间轴通常自动处理间隔,可以先移除或注释掉
+      rotate: 30,   // 保留旋转,如果标签可能重叠
+      fontSize: 10,
+      // width: 100, // width 和 overflow 对于时间轴可能行为不同,按需调整
+      // overflow: 'truncate',
+      formatter: null // ECharts 会自动格式化时间,如需特定格式可用 function 或字符串模板
+    }
+  },
+  yAxis: {
+    type: 'value',
+    name: '金额 (元)', // 添加 Y 轴名称
+    nameLocation: 'end', // 名称位置
+    nameTextStyle: {
+      align: 'right',
+      padding: [0, 10, 0, 0] // 调整名称与轴线的距离
+    },
+    splitLine: {
+      lineStyle: {
+        type: 'dashed'
+      }
+    },
+    axisLabel: {
+      formatter: '{value} 元' // 可选:给 Y 轴刻度添加单位
+    }
+  },
+  series: [
+    {
+      name: '答题红包金额',
+      type: 'line', // 系列类型改为 'line'
+      data: [
+      ],
+      itemStyle: { // 控制数据点(标记)的样式
+        color: '#409EFF'
+      },
+      lineStyle: { // 控制线的样式
+        color: '#409EFF'
+      },
+      smooth: false, // 是否平滑曲线,可设为 true
+      symbol: 'circle', // 数据点标记形状,'emptyCircle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'
+      symbolSize: 4   // 数据点标记大小
+    }
+  ]
+};
+
+
+const redPackageOption = {
+  tooltip: {
+    trigger: 'axis',
+    axisPointer: {
+      type: 'shadow'
+    }
+  },
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '8%',
+    top: '3%',
+    containLabel: true
+  },
+  xAxis: {
+    type: 'category',
+    data: [],
+    axisLabel: {
+      interval: 0,
+      rotate: 30,
+      fontSize: 10,
+      width: 100,
+      overflow: 'truncate'
+    }
+  },
+  yAxis: {
+    type: 'value',
+    splitLine: {
+      lineStyle: {
+        type: 'dashed'
+      }
+    }
+  },
+  series: [
+    {
+      name: '答题红包金额',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#409EFF'
+      }
+    }
+  ]
+}
+export default {
+  name: 'StatisticsDashboard',
+  components: {CountTo},
+  data() {
+    return {
+      deptInitOptions:[],
+      deptOptions:[],
+      intiDeptId:this.$store.state.user.user.deptId,
+      deptId:this.$store.state.user.user.deptId,
+      staticParam : {companyId:null,deptId:this.$store.state.user.user.deptId},
+      companyIntiOptions:[],
+      companyOptions:[],
+      companyId:null,
+      percentage: 0,
+      // 预测message
+      remainMessage: '',
+      // 当天使用流量
+      todayTraffic: 0,
+      trafficCount: 0,
+      // 当月使用流量
+      thisMonthTraffic: 0,
+      dataType: '0',
+      delerSort: 'DESC',
+      smsRemainCount: 0,
+      viewerType: '0',
+      viewerChart: null,
+      dealerChartNew: null,
+      userTypeText: process.env.VUE_APP_COURSE_DEFAULT==1?"会员":"企微",
+      userType: process.env.VUE_APP_COURSE_DEFAULT,
+      dealerChart: null,
+      // 分公司数量
+      dealderCount: 0,
+      // 销售数量
+      groupMgrCount: 0,
+      // 会员总数量
+      memberCount: 0,
+      // 企微数量
+      qwMemberNum: 0,
+      // pad使用情况
+      padTotalNum: 0,
+      // pad使用情况
+      padUsedNum: 0,
+      // 正常会员数量
+      normalNum: 0,
+      // 黑名单会员数量
+      blackNum: 0,
+      // 观看人数
+      watchUserCount: 0,
+      // 完播人数
+      completedUserCount: 0,
+      // 完播率
+      completedRate: 0,
+      // 观看次数
+      watchCount:0,
+      // 完播次数
+      completedCount: 0,
+      // 视频完播率
+      watchRate: 0,
+      // 答题人数
+      answerMemberCount: 0,
+      // 正确人数
+      correctUserCount: 0,
+      correctRate: 0.0,
+      // 答题红包个数
+      rewardCount: 0,
+      // 答题红包金额
+      rewardMoney: 0.0,
+      queryTime: '今日',
+      todayWatchUserCount: 0,
+      versionLimit: 0,
+      versionLimitPercent : 0.0,
+      /// 选中的分析概览
+      selectedDiv: 0,
+      filterType: 0,
+      answerRedPackViewerChart: null,
+      answerRedPackMoneyViewerChart: null,
+      todayComsumption: 0,
+      yesterdayComsumption: 0,
+      balance: 0,
+      runTianBalance: 0,
+      autoRefreshInterval: null,
+      // 今日新增用户数
+      todayIncreaseUserNum: 0,
+      // 订单总数
+      orderTotalNum: 0,
+      // 今日新增订单数
+      todayOrderNum: 0,
+      // 收款总数
+      recvTotalNum: 0,
+      // 今日收款总数
+      recvTodayNum: 0,
+      // 商品总数
+      goodsTotalNum: 0,
+      // 今日商品总数
+      todayGoodsNum: 0
+    }
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.initViewerChart();
+      this.initDealerChartNew();
+      this.initDealerChart();
+      this.initCourseWatchChart();
+      this.initAnswerRedPackViewerChart();
+      this.initAnswerRedPackMoneyViewerChart();
+      this.initThisMonthOrderChart();
+      this.initThisMonthRecvChart();
+
+
+      // 监听窗口大小变化,重新渲染图表
+      window.addEventListener('resize', () => {
+        this.viewerChart && this.viewerChart.resize()
+        this.dealerChart && this.dealerChart.resize()
+        this.dealerChartNew && this.dealerChartNew.resize()
+      })
+    })
+  },
+  created() {
+    this.refresh();
+    listDept().then(res => {
+      this.deptInitOptions = res.data;
+      listCompany().then(res => {
+        this.companyIntiOptions = res.rows;
+        this.getDeptOptions(this.intiDeptId);
+        this.getCompanyOptions(this.intiDeptId);
+      });
+    });
+  },
+  methods: {
+    getDeptOptions(deptId) {
+      const deptInitOptions = this.deptInitOptions;
+      // 部门本身节点
+      let deptNode = deptInitOptions.filter(item => item.deptId === deptId);
+
+      // 递归查找所有子节点
+      function findChildren(parentId) {
+        //部门的子部门
+        let deptChildren = deptInitOptions.filter(item => item.parentId === parentId);
+        //添加子部门
+        deptChildren.forEach(child => {
+          deptNode.push(child);
+          findChildren(child.deptId); // 递归查找子节点的子节点
+        });
+      }
+
+      // 从目标节点开始查找子节点
+      findChildren(deptId);
+      this.deptOptions = deptNode;
+    },
+    getCompanyOptions(deptId) {
+      this.companyId = null;
+      //修改选择后清空查询参数
+      this.staticParam.companyId = null;
+      this.staticParam.deptId = deptId;
+      const deptInitOptions = this.deptInitOptions;
+      const companyInitOptions = this.companyIntiOptions;
+      // 部门下的公司
+      let companyNode = companyInitOptions.filter(item => item.deptId === deptId);
+
+      // 递归查找所有子节点
+      function findChildren(parentId) {
+        //部门的子部门
+        let deptChildren = deptInitOptions.filter(item => item.parentId === parentId);
+        //添加子部门
+        deptChildren.forEach(child => {
+          //子部门下的销售公司
+          let companyChildren = companyInitOptions.filter(item => item.deptId === child.deptId);
+          companyChildren.forEach(companyChild => {
+            companyNode.push(companyChild);
+          })
+          findChildren(child.deptId); // 递归查找子节点的子节点
+        });
+      }
+
+      // 从目标节点开始查找子节点
+      findChildren(deptId);
+      this.companyOptions = companyNode;
+    },
+    //首页统计选择部门、销售公司
+    handleDeptChange() {
+      this.getCompanyOptions(this.deptId);
+      this.refresh();
+    },
+    handleCompanyChange() {
+      this.staticParam.companyId = this.companyId;
+      this.refresh();
+    },
+    handleUserType() {
+      if (this.userTypeText === '会员') {
+        this.userType = 1
+      } else {
+        this.userType = 2
+      }
+
+      this.refresh()
+    },
+    /**
+     * 计算余额预计可持续的天数
+     * @param {number} balance - 当前账户余额
+     * @param {number} runTianBalance - 润天账户余额
+     * @param {number} todayConsumption - 今日消耗金额
+     * @param {number} yesterdayConsumption - 昨日消耗金额
+     * @return {Object} 包含天数和进度百分比的对象
+     */
+    calculateRemainingDays(balance, todayConsumption, yesterdayConsumption) {
+      // 如果今日和昨日消耗都为0,则无法预测(避免除以0)
+      if (todayConsumption === 0 && yesterdayConsumption === 0) {
+        return {
+          days: Infinity,
+          percentage: 0,
+          message: '暂无消耗数据'
+        };
+      }
+
+      // 计算每日平均消耗量
+      const avgDailyConsumption = (todayConsumption + yesterdayConsumption) / 2;
+
+      // 如果平均消耗为0,则无法预测
+      if (avgDailyConsumption === 0) {
+        return {
+          days: Infinity,
+          percentage: 0,
+          message: '暂无消耗数据'
+        };
+      }
+
+      // 计算剩余天数(向下取整)
+      const remainingDays = Math.floor(balance / avgDailyConsumption);
+
+      // 计算进度条百分比,最大为100
+      // 这里假设100天是满值,可以根据需要调整
+      const maxDays = 100;
+      const percentage = Math.min(100, Math.max(0, Math.round((remainingDays / maxDays) * 100)));
+
+      let message = '';
+      if (remainingDays > 365) {
+        message = '预测余额充足';
+      } else {
+        message = `预测不足${remainingDays}天`;
+      }
+
+      return {
+        days: remainingDays,
+        percentage: 100 - percentage,
+        message: message
+      };
+    },
+    /**
+     * 将字节数转换为合适的单位表示(Byte、KB、MB、GB、TB)
+     * @param {number} bytes - 字节数
+     * @param {number} [decimals=2] - 小数点后保留的位数
+     * @returns {string} 格式化后的字符串,包含数值和单位
+     */
+    formatBytes(bytes, decimals = 2) {
+      const isNegative = bytes < 0;  // 判断是否为负数
+      bytes = Math.abs(bytes);  // 获取绝对值
+
+      if (bytes === 0) return '0 Byte';
+
+      const k = 1024;
+      const sizes = ['Byte', 'KB', 'MB', 'GB', 'TB'];
+
+      // 计算合适的单位级别
+      let i = Math.floor(Math.log(bytes) / Math.log(k));
+
+      // 转换为对应单位的值
+      const value = bytes / Math.pow(k, i);
+
+
+      if(this.deptId !== 1 ||  this.companyId !== null){
+        i += 1;
+      }
+      // 格式化为指定小数位的字符串
+      const result = parseFloat(value.toFixed(decimals)) + ' ' + sizes[Math.min(i, sizes.length - 1)];
+
+      // 如果是负数,返回带负号的值
+      return isNegative ? `-${result}` : result;
+    },
+    // 手动刷新
+    manualRefresh() {
+      this.refresh();
+    },
+    // 处理自动刷新选项
+    handleAutoRefresh(command) {
+      // 清除之前的定时器
+      if (this.timer) {
+        clearInterval(this.timer);
+        this.timer = null;
+      }
+
+      // 设置新的刷新间隔
+      this.autoRefreshInterval = parseInt(command);
+
+      // 如果间隔大于0,设置新的定时器
+      if (this.autoRefreshInterval > 0) {
+        this.timer = setInterval(() => {
+          this.refresh();
+        }, this.autoRefreshInterval * 60 * 1000); // 转换为毫秒
+
+        this.$message.success(`已设置${this.autoRefreshInterval}分钟自动刷新`);
+      } else {
+        this.$message.info('已关闭自动刷新');
+      }
+    },
+    refresh() {
+      rechargeComsumption(this.staticParam).then(res => {
+        console.log(res);
+        if (res.code === 200) {
+          this.balance = res.data.balance;
+          this.runTianBalance = res.data.runTianBalance;
+          this.todayComsumption = res.data.todayComsumption;
+          this.yesterdayComsumption = res.data.yesterdayComsumption;
+          let calculateRemainingDays1 = this.calculateRemainingDays(this.balance, this.todayComsumption, this.yesterdayComsumption);
+          this.percentage = calculateRemainingDays1.percentage;
+          this.remainMessage = calculateRemainingDays1.message;
+        }
+      });
+
+      trafficLog(this.staticParam).then(res => {
+        if (res.code === 200) {
+          this.todayTraffic = res.data.today;
+          this.thisMonthTraffic = res.data.thisMonth;
+          this.trafficCount = res.data.traffic;
+        }
+      })
+
+      dealerAggregated(this.staticParam).then(res => {
+        if (res.code === 200) {
+          this.dealderCount = res.data.dealderCount ?? 0;
+          this.groupMgrCount = res.data.groupMgrCount ?? 0;
+          this.memberCount = res.data.memberCount ?? 0;
+          this.qwMemberNum = res.data.qwMemberNum ?? 0;
+          const totalNum = res.data.padTotalNum;
+          //-1 不限 null 未设置
+          if(totalNum != null && totalNum !== -1 && totalNum > 0){
+            this.padTotalNum = totalNum;
+          }else{
+            this.padTotalNum = '不限';
+          }
+          this.padUsedNum = res.data.padUsedNum ?? 0;
+          this.padInfo = res.data.padInfo;
+          this.normalNum = res.data.normalNum ?? 0;
+          this.blackNum = res.data.blackNum ?? 0;
+          this.todayIncreaseUserNum = res.data.todayIncreaseUserNum ?? 0;
+          this.orderTotalNum = res.data.orderTotalNum ?? 0;
+          this.todayOrderNum = res.data.todayOrderNum ?? 0;
+          this.recvTotalNum = res.data.recvTotalNum ?? 0;
+          this.recvTodayNum = res.data.recvTodayNum ?? 0;
+          this.goodsTotalNum = res.data.goodsTotalNum ?? 0;
+          this.todayGoodsNum = res.data.todayGoodsNum ?? 0;
+        }
+      })
+      let param = this.getParam();
+
+      // 获取当前日期时间
+      const today = dayjs();
+      param.startTime = this.formatDate(today);
+      param.endTime = this.formatDate(today);
+      analysisPreview(param).then(res => {
+        if (res.code === 200) {
+          this.watchUserCount = res.data.watchUserCount;
+          this.completedUserCount = res.data.completedUserCount;
+          this.completedRate = res.data.completedRate;
+          this.watchCount = res.data.watchCount;
+          this.completedCount = res.data.completedCount;
+          this.answerMemberCount = res.data.answerMemberCount;
+          this.correctUserCount = res.data.correctUserCount;
+          this.correctRate = res.data.correctRate;
+          this.rewardCount = res.data.rewardCount;
+          this.rewardMoney = res.data.rewardMoney;
+          this.watchRate = res.data.watchRate;
+        }
+      })
+      smsBalance(this.staticParam).then(res => {
+        if (res.code === 200) {
+          if (res.data == null) {
+            this.smsRemainCount = 0;
+          } else {
+            this.smsRemainCount = res.data;
+          }
+        }
+      })
+      authorizationInfo(this.staticParam).then(res => {
+        if (res.code === 200 && res.data != null) {
+          this.todayWatchUserCount = res.data.todayWatchUserCount;
+          this.versionLimit = res.data.versionLimit;
+          if(this.versionLimit){
+            this.versionLimitPercent = this.todayWatchUserCount/this.versionLimit;
+          }
+        }
+      })
+
+      this.handleCourseWatchChart()
+      this.handleViewChartData()
+      this.handleDealerChartDataNew()
+
+      // 经销商会员观看TOP10
+      this.handleDealerChartData()
+
+      this.handleAnswerRedPackViewerChart()
+
+      this.handleAnswerRedPackMoneyViewerChart()
+
+      this.handleThisMonthRecvCount();
+      this.handleThisMonthOrderCount();
+
+    },
+    /**
+     * 将数字添加千位分隔符
+     * @param {number|string} num - 需要格式化的数字
+     * @return {string} 添加千位分隔符后的字符串
+     */
+    formatNumberWithCommas(num) {
+      if (num === null || num === undefined || isNaN(Number(num))) {
+        return '0';
+      }
+
+      const numStr = String(num);
+
+      // 处理负数
+      const isNegative = numStr.startsWith('-');
+      const absNumStr = isNegative ? numStr.slice(1) : numStr;
+
+      // 分离整数部分和小数部分
+      const parts = absNumStr.split('.');
+      const integerPart = parts[0];
+      const decimalPart = parts.length > 1 ? '.' + parts[1] : '';
+
+      const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+
+      return (isNegative ? '-' : '') + formattedInteger + decimalPart;
+    },
+    handleToggleDiv(selected) {
+      this.selectedDiv = selected;
+
+      if (selected === 1) {
+        this.$nextTick(() => {
+          if (this.courseWatchChart) {
+            this.courseWatchChart.resize();
+          } else {
+          }
+        });
+      } else if (selected === 0) {
+        this.$nextTick(() => {
+          if (this.viewerChart) this.viewerChart.resize();
+          if (this.dealerChart) this.dealerChart.resize();
+        });
+      } else if (selected === 2) {
+        this.$nextTick(() => {
+          if (this.answerRedPackViewerChart) this.answerRedPackViewerChart.resize();
+          if (this.answerRedPackMoneyViewerChart) this.answerRedPackMoneyViewerChart.resize();
+        });
+      }
+      if (this.selectedDiv === 0) {
+        this.handleViewChartData()
+        this.handleDealerChartData()
+        this.handleDealerChartDataNew()
+      } else if (this.selectedDiv === 1) {
+        this.handleCourseWatchChart()
+      } else if (this.selectedDiv === 2) {
+        this.handleAnswerRedPackViewerChart()
+        this.handleAnswerRedPackMoneyViewerChart()
+      }
+    },
+    formatDate(date) {
+      return dayjs(date).format('YYYY-MM-DD');
+    },
+
+    getParam() {
+      let param = {
+        startTime: '',
+        endTime: '',
+        userType: this.userType,
+        companyId: this.companyId,
+        deptId: this.deptId
+      };
+      // 获取当前日期时间
+      const today = dayjs();
+
+      let type = 0;
+      if (this.queryTime === '今日') {
+        param.startTime = this.formatDate(today);
+        param.endTime = this.formatDate(today);
+        type = 0;
+      } else if (this.queryTime === '昨日') {
+        const yesterday = today.subtract(1, 'day');
+        param.startTime = this.formatDate(yesterday);
+        param.endTime = this.formatDate(yesterday);
+        type = 1;
+      } else if (this.queryTime === '本周') {
+        param.startTime = this.formatDate(today.startOf('week'));
+        param.endTime = this.formatDate(today.endOf('week'));
+        type = 2;
+      } else if (this.queryTime === '本月') {
+        param.startTime = this.formatDate(today.startOf('month'));
+        param.endTime = this.formatDate(today.endOf('month'));
+        type = 3;
+      } else if (this.queryTime === '上月') {
+        const lastMonth = today.subtract(1, 'month');
+        param.startTime = this.formatDate(lastMonth.startOf('month'));
+        param.endTime = this.formatDate(lastMonth.endOf('month'));
+        type = 4;
+      } else {
+        console.warn(`未知的 queryTime: ${this.queryTime}, 默认使用今日`);
+        param.startTime = this.formatDate(today);
+        param.endTime = this.formatDate(today);
+      }
+      param.type = type;
+      param.sort = this.delerSort;
+      return param;
+    },
+    // 分析概览
+    handleAnalysis(e) {
+
+      let param = this.getParam();
+      analysisPreview(param).then(res => {
+        if (res.code === 200) {
+          this.watchUserCount = res.data.watchUserCount;
+          this.completedUserCount = res.data.completedUserCount;
+          this.completedRate = res.data.completedRate;
+          this.watchCount = res.data.watchCount;
+          this.completedCount = res.data.completedCount;
+          this.answerMemberCount = res.data.answerMemberCount;
+          this.correctUserCount = res.data.correctUserCount;
+          this.correctRate = res.data.correctRate;
+          this.rewardCount = res.data.rewardCount;
+          this.rewardMoney = res.data.rewardMoney;
+          this.watchRate = res.data.watchRate;
+        }
+      })
+
+      if (this.selectedDiv === 0) {
+        this.handleViewChartData()
+        this.handleDealerChartData()
+        this.handleDealerChartDataNew()
+      } else if (this.selectedDiv === 1) {
+        this.handleCourseWatchChart()
+      } else if (this.selectedDiv === 2) {
+        this.handleAnswerRedPackViewerChart()
+        this.handleAnswerRedPackMoneyViewerChart()
+      }
+    },
+    handleAnswerRedPackViewerChart() {
+      let param = this.getParam();
+      param = { ...param, statisticalType: this.viewerType, dataType: this.dataType };
+      rewardMoneyTopTen(param).then(res => {
+        if (res.code === 200) {
+          let data = res.data;
+          let companyNameList = data.map(e => e.companyName)
+          let courseNameList = data.map(e => e.courseName)
+          let rewardMoneyList = data.map(e => e.rewardMoney)
+          if (this.dataType === '0') {
+            redPackageOption.xAxis.data = companyNameList;
+          } else {
+            redPackageOption.xAxis.data = courseNameList;
+          }
+          redPackageOption.series[0].data = rewardMoneyList;
+
+          this.answerRedPackViewerChart.setOption(redPackageOption)
+        }
+      })
+    },
+    handleAnswerRedPackMoneyViewerChart() {
+      let param = this.getParam();
+      param = { ...param, statisticalType: this.viewerType, dataType: this.dataType };
+      rewardMoneyTrend(param).then(res => {
+        if (res.code === 200) {
+          let data = res.data;
+          let option = data.map(e => [e.x, e.rewardMoney])
+          lineChartOption.series[0].data = option;
+
+          this.answerRedPackMoneyViewerChart.setOption(lineChartOption)
+        }
+      })
+    },
+    handleCourseWatchChart() {
+      let param = this.getParam();
+      param = { ...param, statisticalType: this.viewerType };
+      watchCourseTopTen(param).then(res => {
+        if (res.code === 200) {
+          let data = res.data;
+          let watchUserCountList = data.map(e => e.watchUserCount);
+          let completedUserCountList = data.map(e => e.completedUserCount);
+          let answerUserCountList = data.map(e => e.answerUserCount);
+          let correctUserCountList = data.map(e => e.correctUserCount);
+          let courseNameList = data.map(e => e.courseName);
+          courseWatchOption.xAxis.data = courseNameList;
+          courseWatchOption.series[0].data = watchUserCountList;
+          courseWatchOption.series[1].data = completedUserCountList;
+          courseWatchOption.series[2].data = answerUserCountList;
+          courseWatchOption.series[3].data = correctUserCountList;
+          this.courseWatchChart.setOption(courseWatchOption)
+        }
+      })
+    },
+    handleDealerChartData() {
+      let param = this.getParam();
+
+      // 经销商会员观看TOP10
+      deaMemberTopTen({ ...param, statisticalType: this.viewerType }).then(res => {
+        if (res.code === 200) {
+          let data = res.data;
+          let companyNameList = data.map(e => e.companyName);
+          let watchUserList = data.map(e => e.watchUserCount);
+          dealerOption.yAxis.data = companyNameList;
+          dealerOption.series[0].data = watchUserList;
+
+          this.dealerChart.setOption(dealerOption)
+        }
+      })
+
+    },
+    handleThisMonthOrderCount() {
+      thisMonthOrderCount(this.staticParam).then(res => {
+        if (res.code === 200) {
+          let dates = res.dates;
+          let orderCount = res.orderCount;
+          let payPrice = res.payPrice;
+
+          thisMonthOrderCountOption.series[0].data = orderCount;
+          thisMonthOrderCountOption.series[1].data = payPrice;
+          thisMonthOrderCountOption.xAxis.data = dates;
+
+          this.thisMonthOrderChart.setOption(thisMonthOrderCountOption)
+        }
+      })
+    },
+    handleThisMonthRecvCount() {
+      thisMonthRecvCount(this.staticParam).then(res => {
+        if (res.code === 200) {
+          let dates = res.dates;
+          let orderCount = res.orderCount;
+          let payMoney = res.payMoney;
+
+          thisMonthRecvCountOption.series[0].data = orderCount;
+          thisMonthRecvCountOption.series[1].data = payMoney;
+          thisMonthRecvCountOption.xAxis.data = dates;
+          this.thisMonthRecvChart.setOption(thisMonthRecvCountOption)
+        }
+      })
+    },
+    handleViewChartData() {
+      let param = this.getParam();
+
+      watchEndPlayTrend({ ...param }).then(res => {
+        if (res.code === 200) {
+          let data = res.data;
+          let watchUserCountList = data.map(e => e.watchUserCount);
+          let completedUserCountList = data.map(e => e.completedUserCount);
+          let xAxis = data.map(e => e.x);
+          viewCharOption.series[0].data = watchUserCountList;
+          viewCharOption.series[1].data = completedUserCountList;
+          viewCharOption.xAxis.data = xAxis;
+
+          this.viewerChart.setOption(viewCharOption);
+        }
+      })
+
+    },
+    handleDealerChartDataNew() {
+      let param = this.getParam();
+
+      getWatchCourseStatisticsData({ ...param }).then(res => {
+        if (res.code === 200) {
+          console.log(res.data);
+          // 根据实际数据结构调整
+          let data = res.data;
+          let watchUserCountList = data.map(e => e.watchCount);     // 观看次数
+          let completedUserCountList = data.map(e => e.finishCount); // 完播次数
+          let xAxis = data.map(e => e.companyName);                 // X轴使用公司名称
+
+          // 更新图表配置
+          dealerOptionNew.series[0].data = watchUserCountList;
+          dealerOptionNew.series[1].data = completedUserCountList;
+          dealerOptionNew.xAxis.data = xAxis;
+
+          this.dealerChartNew.setOption(dealerOptionNew);
+
+        }
+      })
+
+    },
+    initThisMonthOrderChart() {
+      this.thisMonthOrderChart = echarts.init(this.$refs.viewerOrderChart)
+      this.thisMonthOrderChart.setOption(thisMonthOrderCountOption)
+    },
+    initThisMonthRecvChart() {
+
+      this.thisMonthRecvChart = echarts.init(this.$refs.viewerReceiveChart)
+      this.thisMonthRecvChart.setOption(thisMonthOrderCountOption)
+    },
+    initViewerChart() {
+      this.viewerChart = echarts.init(this.$refs.viewerChart)
+      this.viewerChart.setOption(viewCharOption)
+    },
+    initDealerChartNew() {
+      this.dealerChartNew = echarts.init(this.$refs.dealerChartNew)
+      this.dealerChartNew.setOption(dealerOptionNew)
+    },
+    initDealerChart() {
+      this.dealerChart = echarts.init(this.$refs.dealerChart)
+
+      this.dealerChart.setOption(dealerOption)
+    },
+    initCourseWatchChart() {
+      this.courseWatchChart = echarts.init(this.$refs.courseWatchChart)
+
+      this.courseWatchChart.setOption(courseWatchOption)
+    },
+    initAnswerRedPackViewerChart() {
+      this.answerRedPackViewerChart = echarts.init(this.$refs.answerRedPackViewerChart)
+
+      this.answerRedPackViewerChart.setOption(redPackageOption)
+    },
+    initAnswerRedPackMoneyViewerChart() {
+      this.answerRedPackMoneyViewerChart = echarts.init(this.$refs.answerRedPackMoneyViewerChart)
+
+      this.answerRedPackMoneyViewerChart.setOption(lineChartOption)
+    }
+  },
+
+  beforeDestroy() {
+    // 组件销毁时清除定时器
+    if (this.timer) {
+      clearInterval(this.timer);
+      this.timer = null;
+    }
+    // window.removeEventListener('resize', this.resizeHandler)
+    this.viewerChart && this.viewerChart.dispose()
+    this.dealerChart && this.dealerChart.dispose()
+    this.dealerChartNew && this.dealerChartNew.dispose()
+  }
+}
+</script>
+
+<style scoped>
+.highlight-today-add {
+  color: green;
+  font-size: 17px;
+  font-weight: normal;
+}
+
+.highlight-today-add2 {
+  color: rgba(49, 185, 154, 1);
+  font-size: 14px;
+  font-weight: normal;
+  transform: scale(.9);
+}
+
+.action-group .el-button + .el-button,
+.action-group .el-dropdown {
+  margin-left: 10px;
+}
+
+.is-active {
+  color: #409EFF;
+  font-weight: bold;
+}
+
+::v-deep .el-radio-button__inner:hover {
+  color: #409EFF;
+  /* 鼠标悬浮时的文字颜色,可以根据需要调整 */
+}
+
+::v-deep .el-radio-button.is-active .el-radio-button__inner {
+  background-color: #409EFF;
+  /* 选中时的背景色 */
+  border-color: #409EFF;
+  /* 选中时的边框色 */
+  color: #FFFFFF;
+  /* 选中时的文字颜色 (通常是白色) */
+  box-shadow: -1px 0 0 0 #409EFF;
+  /* 处理按钮间的连接缝隙 */
+}
+
+/* 如果需要,也可以修改非选中状态下的聚焦(focus)或悬浮(hover)样式 */
+/* 例如,让非选中按钮悬浮时边框和文字也变蓝 */
+::v-deep .el-radio-button:not(.is-active) .el-radio-button__inner:hover {
+  color: #409EFF;
+  /* border-color: #b3d8ff;  Element UI 默认悬浮边框色,可以按需修改 */
+}
+
+/* 聚焦时的外框,如果需要的话 */
+::v-deep .el-radio-button:focus:not(.is-checked) .el-radio-button__inner {
+  /* border-color: #409EFF; */
+  /* Element UI 默认的 focus 颜色通常关联主题色 */
+  /* box-shadow: 0 0 2px 2px rgba(64, 158, 255, 0.2); */
+  /* 示例 focus 光晕 */
+}
+
+.statistics-dashboard {
+  padding: 20px;
+  background-color: #f5f7fa;
+}
+
+.overview-section,
+.analysis-section {
+  margin-bottom: 20px;
+  border-radius: 4px;
+}
+
+.header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  font-size: 16px;
+  font-weight: 500;
+}
+
+.data-card {
+  background-color: #fff;
+  border-radius: 4px;
+  padding: 15px;
+  height: 120px;
+  display: flex;
+  flex-direction: column;
+  position: relative;
+  transition: background-color 0.3s ease-in-out;
+}
+
+.data-card:hover {
+  border: 1px solid #4592ff;
+  background-color: #e7f1ff;
+}
+
+.card-title {
+  color: #606266;
+  font-size: 14px;
+  margin-bottom: 10px;
+}
+
+.card-title1 {
+  color: white;
+  font-size: 14px;
+  margin-bottom: 10px;
+}
+
+.card-value {
+  font-size: 24px;
+  font-weight: bold;
+  margin-top: 20px;
+}
+
+.highlight {
+  color: #409EFF;
+}
+
+.card-sub {
+  display: flex;
+  justify-content: space-between;
+  font-size: 12px;
+  color: #909399;
+  margin-top: 5px;
+}
+
+.card-desc {
+  font-size: 12px;
+  color: #909399;
+  margin-top: 5px;
+}
+
+.card-badge {
+  position: absolute;
+  top: 15px;
+  right: 15px;
+  background: #f0f9eb;
+  color: #67c23a;
+  padding: 2px 5px;
+  border-radius: 4px;
+}
+
+.cdn-label {
+  background-color: #409EFF;
+  color: white;
+  padding: 2px 5px;
+  border-radius: 4px;
+  margin-right: 5px;
+  font-size: 12px;
+}
+
+.tab-group {
+  display: flex;
+  gap: 10px;
+}
+
+.action-group {
+  display: flex;
+  gap: 10px;
+}
+
+.analysis-card {
+  border-radius: 4px;
+  padding: 20px;
+  display: flex;
+  align-items: center;
+}
+
+.card-icon {
+  width: 50px;
+  height: 50px;
+  background-color: rgba(64, 158, 255, 0.1);
+  border-radius: 8px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  font-size: 24px;
+  color: #409EFF;
+  margin-right: 20px;
+}
+
+.card-content {
+  display: flex;
+}
+
+.card-row {
+  display: flex;
+  justify-content: center;
+  justify-items: center;
+  flex-direction: column;
+  padding: 10px;
+
+  .highlight {
+    text-align: center;
+    margin-top: 1em;
+
+    font-family: BebasNeue;
+    color: #1677ff;
+    font-size: 21px;
+    line-height: 42px;
+    font-weight: 600;
+    margin-top: 8px;
+  }
+
+  font-size: 15px;
+  color: #000;
+
+}
+
+.charts-section {
+  margin-top: 20px;
+}
+
+.chart-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.view-more {
+  font-size: 12px;
+}
+
+.legend {
+  display: flex;
+  gap: 15px;
+}
+
+.legend-item {
+  display: flex;
+  align-items: center;
+  font-size: 12px;
+}
+
+.dot {
+  width: 10px;
+  height: 10px;
+  border-radius: 50%;
+  margin-right: 5px;
+}
+
+.viewer-dot {
+  background-color: #409EFF;
+}
+
+.complete-dot {
+  background-color: #67C23A;
+}
+
+.chart-container {
+  height: 350px;
+  width: 100%;
+}
+
+.analysis-card-check {
+  display: flex;
+  flex-direction: row;
+  border: 1px solid transparent;
+  background-color: #fff;
+  border-radius: 4px;
+}
+
+.analysis-card-check:hover {
+  cursor: pointer;
+}
+
+.analysis-card-check-selected:after {
+  content: "";
+  display: block;
+  border-width: 15px;
+  position: absolute;
+  bottom: -30px;
+  left: 50%;
+  margin-left: -32px;
+  border-style: solid dashed dashed solid;
+  border-color: #4592FF transparent transparent transparent;
+  font-size: 0;
+  line-height: 0;
+  z-index: 1;
+}
+
+.analysis-card-check-selected:before {
+  content: "";
+  display: block;
+  border-width: 15px;
+  position: absolute;
+  bottom: -30px;
+  left: 50%;
+  margin-left: -32px;
+  border-style: solid dashed dashed solid;
+  border-color: #4592FF transparent transparent transparent;
+  font-size: 0;
+  line-height: 0;
+  z-index: 1;
+}
+
+.analysis-card-check-selected {
+  border: 1px solid #4592FF;
+  background-color: #e7f1ff;
+}
+
+.color {
+  position: relative;
+  border: 1px solid #4592FF;
+  background-color: #e7f1ff;
+}
+
+.color:after {
+  bottom: -27px;
+  border-color: #E7F1FF transparent transparent transparent;
+}
+
+.companybox {
+  color: white;
+  background-color: #006CFF;
+  padding: 10px 10px 40px 10px;
+  box-sizing: border-box;
+  position: relative;
+  border-radius: 6px;
+
+  .topimg {
+    width: 100px;
+    height: 80px;
+    position: absolute;
+    top: 0px;
+    left: 0;
+  }
+
+  .bottomimg {
+    width: 100px;
+    height: 80px;
+    position: absolute;
+    bottom: -10px;
+    right: 0;
+    transform: rotate(180deg);
+  }
+
+  .companyboxtitle {
+    height: 30px;
+    margin-bottom: 20px;
+    font-weight: 600;
+  }
+
+  .companyflex {
+    display: flex;
+    justify-content: space-around;
+  }
+}
+
+
+.companynumber {
+  color: white;
+}
+
+.companycard {
+
+  width: 25%;
+}
+
+.companyadd {
+  color: white;
+}
+
+.cardafter {
+  position: relative;
+
+}
+
+.cardafter::after {
+  content: "";
+  height: 60px;
+  border-right: 1px solid rgba(255, 255, 255, 0.20);
+  position: absolute;
+  right: 30px;
+  top: 0px;
+}
+
+.highlight1 {
+  margin-top: 10px;
+  margin-left: 20px;
+}
+
+
+.propertyboxtitle {
+  background-image: url(~@/assets/images/zcgl_bg.png);
+  height: 100px;
+}
+
+.propertyboxflex {
+  display: flex;
+  background-color: white;
+  justify-content: space-between;
+}
+
+.property-card {
+  width: 48%;
+  border-radius: 4px;
+  padding: 15px;
+  height: 100px;
+  display: flex;
+  flex-direction: column;
+  position: relative;
+  transition: background-color 0.3s ease-in-out;
+
+}
+
+.property_title {
+  height: 40px;
+  line-height: 40px;
+  color: rgba(32, 33, 36, 1);
+  box-sizing: border-box;
+  padding-left: 10px;
+  font-weight: 600;
+}
+
+.card-compare {
+  margin-top: 5px;
+  font-size: 14px;
+  color: rgba(92, 95, 102, 1);
+
+  span {
+    font-size: 13px;
+    transform: scale(.8);
+    color: rgba(49, 185, 154, 1);
+  }
+}
+
+.propertyline {
+  position: relative;
+}
+
+.propertyline::after {
+  position: absolute;
+  content: "";
+  height: 80px;
+  border-right: 1px solid rgba(237, 239, 242, 1);
+  right: 0;
+}
+
+.operatetitle {
+  font-weight: 600;
+  height: 50px;
+  line-height: 50px;
+}
+
+.operatetitle-col {
+  display: flex;
+  justify-content: space-between;
+  padding-bottom: 20px;
+  padding-right: 5px;
+
+  .operatetitle-card {
+    width: 24%;
+    border: 1px solid transparent;
+    background-color: rgba(245, 247, 250, 1);
+    border-radius: 4px;
+    padding: 15px;
+    display: flex;
+    flex-direction: column;
+    position: relative;
+    transition: background-color 0.3s ease-in-out;
+
+    .operate-value {
+      font-size: 24px;
+      font-weight: bold;
+    }
+  }
+}
+
+.yesterdaybox {
+  font-size: 14px;
+  color: rgba(92, 95, 102, 1);
+  font-weight: 200;
+  margin-top: 10px;
+}
+
+.internetbox {
+  background: linear-gradient(to right, rgba(255, 99, 0, 1), rgba(255, 159, 1, 1));
+  border-radius: 6px;
+  padding: 2px 5px 15px 5px;
+  width: 100%;
+
+  .internet-cardtop {
+    background-color: white;
+    border-radius: 3px;
+    margin-top: 5px;
+    justify-content: space-between;
+    padding: 15px;
+    box-sizing: border-box;
+    color: rgba(32, 33, 36, 1);
+
+    .cardinnerbox {
+      display: flex;
+      justify-content: space-between;
+
+      .cardtopimg {
+        display: flex;
+        align-items: center;
+        font-size: 15px;
+
+        img {
+          height: 18px;
+          width: 18px;
+        }
+      }
+
+      .cardtopnumber {
+        font-size: 25px;
+        color: rgba(32, 33, 36, 1);
+        font-weight: bold;
+      }
+
+    }
+
+    .cardinnerbox2 {
+      display: flex;
+      justify-content: space-between;
+      font-size: 14px;
+      color: rgba(92, 95, 102, 1);
+
+
+    }
+
+  }
+
+  .internetbox-messge {
+    color: white;
+    display: flex;
+    justify-content: space-between;
+    padding: 15px 10px 10px 10px;
+
+    .internet-card {
+      display: flex;
+      font-size: 14px;
+      align-items: center;
+
+      img {
+        height: 18px;
+        width: 18px;
+      }
+
+      span {
+        padding-left: 5px;
+      }
+    }
+
+    .internet-number {
+      font-size: 25px;
+
+    }
+  }
+
+  .internetbox {
+    display: flex;
+    color: white;
+
+    .internet-card {
+      width: 100%;
+      display: flex;
+      color: white;
+
+    }
+  }
+
+  .internet-title {
+    font-size: 14px;
+  }
+
+}
+
+.company {
+  background-color: #006CFF;
+}
+
+.highlight-red {
+  text-align: center;
+  margin-top: 1em;
+  font-family: BebasNeue;
+  color: rgba(255, 82, 82, 1);
+  font-size: 21px;
+  line-height: 42px;
+  font-weight: 600;
+  margin-top: 8px;
+}
+
+.highlight-black {
+  text-align: center;
+  margin-top: 1em;
+  font-family: BebasNeue;
+  color: rgba(32, 33, 36, 1);
+  font-size: 21px;
+  line-height: 42px;
+  font-weight: 600;
+  margin-top: 8px;
+
+}
+
+.operatetitle-card:hover {
+  border: 1px solid #4592ff;
+  background-color: #e7f1ff;
+}
+
+.icon-img {
+  height: 14px;
+  width: 14px;
+}
+
+.progress {
+  transform: rotate(180deg);
+  margin-top: 20px;
+}
+
+.progress ::v-deep .el-progress-bar__outer {
+  background-color: rgba(247, 152, 11, 0.2);
+}
+
+::v-deep .el-progress {
+
+  .el-progress-bar {
+    .el-progress-bar__inner {
+      background: linear-gradient(to right, #FF6300, #FF9F01)
+    }
+  }
+}
+</style>

+ 72 - 0
src/views/components/index/welcomePage.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="app-container welcome-container">
+    <div class="welcome-content">
+      <div class="time-display">{{ currentTime }}</div>
+      <div class="system-name">{{ systemName }}</div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'Welcome',
+  data() {
+    return {
+      currentTime: '',
+      systemName: process.env.VUE_APP_TITLE,
+      timer: null
+    }
+  },
+  mounted() {
+    this.updateTime()
+    this.timer = setInterval(this.updateTime, 1000)
+  },
+  beforeDestroy() {
+    if (this.timer) {
+      clearInterval(this.timer)
+    }
+  },
+  methods: {
+    updateTime() {
+      const now = new Date()
+      this.currentTime = now.toLocaleString('zh-CN', {
+        year: 'numeric',
+        month: '2-digit',
+        day: '2-digit',
+        hour: '2-digit',
+        minute: '2-digit',
+        second: '2-digit',
+        weekday: 'long'
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+.welcome-container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  height: calc(100vh - 84px); /* 减去头部和padding的高度 */
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+}
+
+.welcome-content {
+  text-align: center;
+  color: white;
+}
+
+.time-display {
+  font-size: 36px;
+  font-weight: 300;
+  margin-bottom: 20px;
+  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
+}
+
+.system-name {
+  font-size: 48px;
+  font-weight: bold;
+  text-shadow: 0 2px 15px rgba(0, 0, 0, 0.4);
+}
+</style>

+ 66 - 2
src/views/course/coursePlaySourceConfig/index.vue

@@ -39,6 +39,21 @@
           size="small"
           @keyup.enter.native="handleQuery"
         />
+      </el-form-item>
+            <el-form-item label="状态" prop="status">
+        <el-select
+          v-model="queryParams.status"
+          placeholder="请选择状态"
+          clearable
+          size="small"
+        >
+          <el-option
+            v-for="item in statusOptions"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
       </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -141,6 +156,15 @@
         <template slot-scope="scope">
           <el-tag prop="isMall" v-for="(item, index) in isMallOptions" v-if="scope.row.isMall==item.dictValue">{{item.dictLabel}}</el-tag>
         </template>
+      </el-table-column>
+            <el-table-column label="状态" align="center" prop="status" width="100px">
+        <template slot-scope="scope">
+          <el-tag
+            :type="scope.row.status === 0 ? 'success' : scope.row.status === 1 ? 'warning' : 'danger'"
+          >
+            {{ getStatusLabel(scope.row.status) }}
+          </el-tag>
+        </template>
       </el-table-column>
       <el-table-column label="创建时间" align="center" prop="createTime" />
       <el-table-column label="修改时间" align="center" prop="updateTime" />
@@ -241,6 +265,22 @@
               :value="item.dictValue"
             />
           </el-select>
+        </el-form-item>
+                <el-form-item label="状态" prop="status">
+          <el-select
+            v-model="form.status"
+            placeholder="请选择状态"
+            style="width: 220px"
+            clearable
+            size="small"
+          >
+            <el-option
+              v-for="item in statusOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
         </el-form-item>
         <el-form-item label="图标" prop="img">
           <image-upload v-model="form.img" :file-type='["png", "jpg", "jpeg"]' :limit="1"/>
@@ -308,7 +348,8 @@ export default {
         pageNum: 1,
         pageSize: 10,
         name: null,
-        appid: null
+        appid: null,
+        status: null
       },
       showSearch: true,
       single: true,
@@ -318,6 +359,20 @@ export default {
       list: [],
       total: 0,
       typesOptions: [],
+            statusOptions: [
+        {
+          label: "正常",
+          value: 0
+        },
+        {
+          label: "半封禁",
+          value: 1
+        },
+        {
+          label: "封禁",
+          value: 2
+        }
+      ],
       isMallOptions:[
         {
           dictLabel: "是",
@@ -567,9 +622,18 @@ export default {
         token: 'cbnd7lJvkripVOpyTFAna6NAWCxCrvC',
         aesKey: 'HlEiBB55eaWUaeBVAQO3cWKWPYv1vOVQSq7nFNICw4E',
         msgDataFormat: 'JSON',
-        type: '1'
+        type: '1',
+        status: 0
       }
       this.resetForm("form");
+          },
+    getStatusLabel(status) {
+      const statusMap = {
+        0: '正常',
+        1: '半封禁',
+        2: '封禁'
+      };
+      return statusMap[status] || '未知';
     }
   },
 }

+ 138 - 138
src/views/his/storeOrder/order1.vue

@@ -50,7 +50,7 @@
             >
               {{ code }}
             </el-tag>
-            
+
             <!-- 输入框 -->
             <el-input
               ref="tagInput"
@@ -65,7 +65,7 @@
               @focus="inputVisible = true"
               clearable
             />
-            
+
             <!-- 添加按钮(当没有输入时显示) -->
             <el-button
               v-if="!inputVisible && queryParams.orderCodes.length > 0"
@@ -78,11 +78,11 @@
               添加订单号
             </el-button>
           </div>
-          
+
           <!-- 输入提示 -->
           <div class="input-tips">
             <span class="tip-text">
-              支持:回车、逗号、空格分隔 | 
+              支持:回车、逗号、空格分隔 |
               已添加 {{ queryParams.orderCodes.length }} 个订单号
               <span v-if="maxOrderCodes > 0"> (最多{{ maxOrderCodes }}个)</span>
             </span>
@@ -220,7 +220,7 @@
                 />
               </el-select>
       </el-form-item>
-	 
+
       <el-form-item label="是否首次进线" prop="isFirst">
         <el-select filterable v-model="queryParams.isFirst" placeholder="状态" clearable size="small">
                 <el-option
@@ -414,7 +414,7 @@
               plain
               icon="el-icon-phone"
               size="mini"
-              
+
               @click="setErpPhone"
               v-hasPermi="['his:storeOrder:createErpOrder']"
             >设置推送手机</el-button>
@@ -572,12 +572,12 @@
       <div v-if="currentSort.prop" class="sort-info">
         <el-tag size="small" type="info" closable @close="clearSort">
           <i class="el-icon-sort"></i>
-          当前排序:{{ getSortLabel(currentSort.prop) }} 
+          当前排序:{{ getSortLabel(currentSort.prop) }}
           {{ currentSort.order === 'ascending' ? '升序' : '降序' }}
         </el-tag>
-          <el-button 
-            type="text" 
-            size="mini" 
+          <el-button
+            type="text"
+            size="mini"
             @click="clearSort"
             style="margin-left: 8px; color: #909399;"
           >
@@ -675,7 +675,7 @@
         <el-button @click="uploadStatus.open = false">取 消</el-button>
       </div>
     </el-dialog>
-    
+
     <!-- 设置推送手机对话框 -->
     <el-dialog :title="erpPhone.title" :visible.sync="erpPhone.open" width="600px" append-to-body>
       <div style="margin-bottom: 20px;">
@@ -684,9 +684,9 @@
       <el-table :data="phoneList" border style="width: 100%">
         <el-table-column prop="phone" label="手机号" align="center">
           <template slot-scope="scope">
-            <el-input 
-              v-if="scope.row.editing" 
-              v-model="scope.row.phone" 
+            <el-input
+              v-if="scope.row.editing"
+              v-model="scope.row.phone"
               placeholder="请输入手机号"
               @blur="validatePhone(scope.row)"
               @keyup.enter.native="handleSavePhone(scope.$index)"
@@ -696,27 +696,27 @@
         </el-table-column>
         <el-table-column label="操作" align="center" width="300">
           <template slot-scope="scope">
-            <el-button 
-              v-if="scope.row.editing" 
-              type="success" 
-              size="mini" 
+            <el-button
+              v-if="scope.row.editing"
+              type="success"
+              size="mini"
               @click="handleSavePhone(scope.$index)"
             >保存</el-button>
-            <el-button 
-              v-if="scope.row.editing" 
-              type="info" 
-              size="mini" 
+            <el-button
+              v-if="scope.row.editing"
+              type="info"
+              size="mini"
               @click="handleCancelEdit(scope.$index)"
             >取消</el-button>
-            <el-button 
-              v-if="!scope.row.editing" 
-              type="primary" 
-              size="mini" 
+            <el-button
+              v-if="!scope.row.editing"
+              type="primary"
+              size="mini"
               @click="handleEditPhone(scope.$index)"
             >修改</el-button>
-            <el-button 
-              type="danger" 
-              size="mini" 
+            <el-button
+              type="danger"
+              size="mini"
               @click="handleDeletePhone(scope.$index)"
             >删除</el-button>
           </template>
@@ -747,9 +747,9 @@
       <div v-loading="erpAccountDialog.loading">
         <el-form :model="erpAccountForm" label-width="100px">
           <el-form-item label="ERP账户" required>
-            <el-select 
-              v-model="erpAccountForm.selectedAccount" 
-              placeholder="请选择ERP账户" 
+            <el-select
+              v-model="erpAccountForm.selectedAccount"
+              placeholder="请选择ERP账户"
               style="width: 100%"
               filterable
             >
@@ -765,7 +765,7 @@
             </el-select>
           </el-form-item>
         </el-form>
-        
+
         <!-- 订单统计信息 -->
         <div class="order-summary" v-if="orderSummary">
           <el-divider content-position="left">订单统计</el-divider>
@@ -791,11 +791,11 @@
           </el-row>
         </div>
       </div>
-      
+
       <div slot="footer" class="dialog-footer">
         <el-button @click="cancelErpAccountDialog">取 消</el-button>
-        <el-button 
-          type="primary" 
+        <el-button
+          type="primary"
           @click="confirmCreateErpOrder"
           :disabled="!erpAccountForm.selectedAccount"
           :loading="erpAccountDialog.submitting"
@@ -811,12 +811,12 @@
           <el-button type="default" size="small" @click="unselectAllFields">全不选</el-button>
           <el-button type="success" size="small" @click="selectDefaultFields">选择常用</el-button>
         </div>
-        
+
         <div class="field-selection-container">
           <el-row :gutter="20">
             <el-col :span="8" v-for="field in exportFieldOptions" :key="field.key">
-              <el-checkbox 
-                v-model="field.checked" 
+              <el-checkbox
+                v-model="field.checked"
                 :label="field.label"
                 style="margin-bottom: 12px; width: 100%;"
               >
@@ -825,7 +825,7 @@
             </el-col>
           </el-row>
         </div>
-        
+
         <div class="field-count-info" style="margin-top: 20px; padding: 10px; background: #f5f7fa; border-radius: 4px;">
           <i class="el-icon-info"></i>
           <span v-if="getSelectedFieldsCount() > 0">
@@ -837,11 +837,11 @@
           </span>
         </div>
       </div>
-      
+
       <div slot="footer" class="dialog-footer">
         <el-button @click="cancelExportFieldDialog">取 消</el-button>
-        <el-button 
-          type="primary" 
+        <el-button
+          type="primary"
           @click="confirmExportFields"
         >确认导出</el-button>
       </div>
@@ -880,11 +880,11 @@ export default {
         prop: null,
         order: null
       },
-      
+
       // 排序字段映射
       sortFieldMap: {
         'companyUserName': '员工',
-        'packageName': '套餐名称', 
+        'packageName': '套餐名称',
         'payPrice': '应收金额',
         'payMoney': '实收金额',
         'createTime': '下单时间'
@@ -898,7 +898,7 @@ export default {
       },
       // 输入框是否可见
       inputVisible: false,
-      
+
       // 无效订单号对话框
       showInvalidDialog: false,
       // 当前输入值
@@ -937,7 +937,7 @@ export default {
               title:"订单详情",
               open:false,
             },
-	  sourceOptions:[],		
+	  sourceOptions:[],
       importExpress: {
               // 是否显示弹出层
               open: false,
@@ -1226,13 +1226,13 @@ export default {
     // 新增排序处理方法
     handleSortChange({ column, prop, order }) {
       console.log('排序变化:', { column, prop, order });
-      
+
       // 更新当前排序状态
       this.currentSort = {
         prop: prop,
         order: order
       };
-      
+
       // 更新查询参数
       if (order) {
         this.queryParams.sortField = prop;
@@ -1241,11 +1241,11 @@ export default {
         this.queryParams.sortField = null;
         this.queryParams.sortOrder = null;
       }
-      
+
       // 重新查询数据
       this.queryParams.pageNum = 1; // 重置到第一页
       this.getList();
-      
+
       // 显示排序提示
       if (order) {
         const fieldLabel = this.getSortLabel(prop);
@@ -1253,12 +1253,12 @@ export default {
         this.$message.success(`已按${fieldLabel}${orderLabel}排序`);
       }
     },
-    
+
     // 获取排序字段的中文标签
     getSortLabel(prop) {
       return this.sortFieldMap[prop] || prop;
     },
-    
+
     // 清除排序
     clearSort() {
       this.currentSort = {
@@ -1281,38 +1281,38 @@ export default {
     // 修改查询列表方法,添加排序参数
     getList() {
       this.loading = true;
-      
+
       // 处理多选参数
       if(this.payTypeArr.length>0){
         this.queryParams.payType=this.payTypeArr.toString();
       } else {
         this.queryParams.payType=null
       }
-      
+
       if(this.scheduleIdArr.length>0){
         this.queryParams.scheduleId=this.scheduleIdArr.toString();
       } else {
         this.queryParams.scheduleId=null
       }
-      
+
       if(this.buyTypeArr.length>0){
         this.queryParams.orderBuyType=this.buyTypeArr.toString();
       } else {
         this.queryParams.orderbuyType=null
       }
-      
+
       if(this.channelArr.length>0){
         this.queryParams.orderChannel=this.channelArr.toString();
       } else {
         this.queryParams.orderChannel=null
       }
-      
+
       if(this.qwSubjectArr.length>0){
         this.queryParams.qwSubject=this.qwSubjectArr.toString();
       } else {
         this.queryParams.qwSubject=null
       }
-      
+
       // 处理公司参数
       if(this.companyIds && this.companyIds.length>1){
         this.queryParams.companyIds = this.companyIds
@@ -1322,16 +1322,16 @@ export default {
         this.queryParams.companyId = this.companyId
         this.queryParams.companyIds = null;
       }
-      
+
       // 处理订单号数组
       if (this.queryParams.orderCodes && this.queryParams.orderCodes.length > 0) {
         this.queryParams.orderCodeList = this.queryParams.orderCodes.join(',');
       } else {
         this.queryParams.orderCodeList = null;
       }
-      
+
       console.log('查询参数:', this.queryParams);
-      
+
       listOrder(this.queryParams).then(response => {
         this.orderList = response.rows;
         this.total = response.total;
@@ -1346,15 +1346,15 @@ export default {
           this.payRemainTotal = "0"
           this.productInfo = response.productInfo;
         }
-        
+
         this.loading = false;
-        
+
         if(response.msg == 'jnmy'){
           this.SFDFopen = true;
         } else{
           this.SFDFopen = false;
         }
-        
+
         // 如果有排序,显示排序结果提示
         if (this.currentSort.prop) {
           const fieldLabel = this.getSortLabel(this.currentSort.prop);
@@ -1370,72 +1370,72 @@ export default {
     // 处理键盘按下事件
     handleKeyDown(event) {
       const { key, target } = event
-      
+
       // 处理退格键删除标签
       if (key === 'Backspace' && !target.value && this.queryParams.orderCodes.length > 0) {
         event.preventDefault()
         this.removeOrderCode(this.queryParams.orderCodes.length - 1)
       }
-      
+
       // 处理分隔符
       if ([',', ',', ' ', 'Enter'].includes(key)) {
         event.preventDefault()
         this.handleInputConfirm()
       }
     },
-    
+
     // 处理键盘抬起事件(实时分割输入)
     handleKeyUp(event) {
       const value = event.target.value
-      
+
       // 检查是否包含分隔符
       if (/[,,\s]/.test(value)) {
         this.handleInputConfirm()
       }
     },
-    
+
     // 确认输入
     handleInputConfirm() {
       const inputValue = this.currentInput.trim()
-      
+
       if (inputValue) {
         // 分割多个订单号
         const codes = inputValue.split(/[,,\s]+/).filter(code => code.trim())
-        
+
         codes.forEach(code => {
           this.addOrderCode(code.trim())
         })
       }
-      
+
       this.currentInput = ''
     },
-    
+
     // 添加订单号
     addOrderCode(code) {
       if (!code) return
-      
+
       // 检查数量限制
       if (this.maxOrderCodes > 0 && this.queryParams.orderCodes.length >= this.maxOrderCodes) {
         this.$message.warning(`最多只能添加 ${this.maxOrderCodes} 个订单号`)
         return
       }
-      
+
       // 检查重复
       if (this.queryParams.orderCodes.includes(code)) {
         this.$message.warning(`订单号 "${code}" 已存在`)
         return
       }
-      
+
       // 添加到列表
       this.queryParams.orderCodes.push(code)
-      
+
     },
-    
+
     // 删除订单号
     removeOrderCode(index) {
       this.queryParams.orderCodes.splice(index, 1)
     },
-    
+
     // 清空所有标签
     clearAllTags() {
       this.$confirm('确认清空所有订单号吗?', '提示', {
@@ -1476,7 +1476,7 @@ export default {
       this.erpSettingType = 'push'
       this.calculateOrderSummary();
     },
-    
+
     //获取ERP账户列表
     async getErpAccountList() {
       try {
@@ -1494,7 +1494,7 @@ export default {
           this.$message.error(response.msg || '获取ERP账户列表失败');
           this.erpAccountList = [];
         }
-        
+
       } catch (error) {
         console.error('获取ERP账户列表失败:', error);
         this.$message.error('获取ERP账户列表失败');
@@ -1503,13 +1503,13 @@ export default {
         this.erpAccountDialog.loading = false;
       }
     },
-    
+
     // 新增:计算订单统计信息
     calculateOrderSummary() {
       let selectedCount = 0;
       let totalAmount = 0;
       let queryCount = this.total || 0;
-      
+
       if (this.ids.length > 0) {
         // 如果有选中的订单,统计选中的订单
         selectedCount = this.ids.length;
@@ -1525,14 +1525,14 @@ export default {
           totalAmount += parseFloat(order.payMoney || 0);
         });
       }
-      
+
       this.orderSummary = {
         selectedCount,
         totalAmount: totalAmount.toFixed(2),
         queryCount
       };
     },
-    
+
     //确认创建ERP订单
     confirmCreateErpOrder() {
       if (!this.erpAccountForm.selectedAccount) {
@@ -1542,8 +1542,8 @@ export default {
       console.log("-----------------",this.erpSettingType)
       if(this.erpSettingType == 'set'){
         this.$confirm(
-          `确认将订单设置ERP账户为"${this.erpAccountForm.selectedAccount}"吗?`, 
-          '确认', 
+          `确认将订单设置ERP账户为"${this.erpAccountForm.selectedAccount}"吗?`,
+          '确认',
           {
             confirmButtonText: '确定',
             cancelButtonText: '取消',
@@ -1554,8 +1554,8 @@ export default {
         });
       } else if(this.erpSettingType == 'push'){
         this.$confirm(
-          `确认将订单推送到ERP账户"${this.erpAccountForm.selectedAccount}"吗?`, 
-          '确认推送', 
+          `确认将订单推送到ERP账户"${this.erpAccountForm.selectedAccount}"吗?`,
+          '确认推送',
           {
             confirmButtonText: '确定推送',
             cancelButtonText: '取消',
@@ -1569,12 +1569,12 @@ export default {
 
     async executSetErpOrder() {
       this.erpAccountDialog.submitting = true;
-      
+
       try {
         let param = {
           loginAccount: this.erpAccountForm.selectedAccount
         };
-        
+
         if (this.ids.length > 0) {
           // 如果有选中的订单,只推送选中的
           param.orderIds = this.ids;
@@ -1605,11 +1605,11 @@ export default {
           } else {
             this.queryParams.qwSubject = null;
           }
-          
+
           // 合并查询参数
           param = { ...param, ...this.queryParams };
         }
-        
+
         const response = await batchSetErpOrder(param);
         if (response.code === 200) {
           this.$message.success('订单ERP账号设置成功');
@@ -1626,16 +1626,16 @@ export default {
         this.erpAccountDialog.submitting = false;
       }
     },
-    
+
     //执行创建ERP订单
     async executeCreateErpOrder() {
       this.erpAccountDialog.submitting = true;
-      
+
       try {
         let param = {
           loginAccount: this.erpAccountForm.selectedAccount
         };
-        
+
         if (this.ids.length > 0) {
           // 如果有选中的订单,只推送选中的
           param.orderIds = this.ids;
@@ -1666,11 +1666,11 @@ export default {
           } else {
             this.queryParams.qwSubject = null;
           }
-          
+
           // 合并查询参数
           param = { ...param, ...this.queryParams };
         }
-        
+
         const response = await batchCreateErpOrder(param);
         if (response.code === 200) {
           this.$message.success('ERP订单创建成功');
@@ -1687,7 +1687,7 @@ export default {
         this.erpAccountDialog.submitting = false;
       }
     },
-    
+
     // 新增:取消ERP账户选择对话框
     cancelErpAccountDialog() {
       this.erpAccountDialog.open = false;
@@ -1737,7 +1737,7 @@ export default {
         param = this.queryParams;
         param.erpPhone=this.erpPhoneValue;
       }
-      
+
       editErpPhone(param).then(response=>{
         this.msgSuccess("修改成功");
         this.setPhoneOpen = false;
@@ -1764,7 +1764,7 @@ export default {
             originalPhone: phone.trim()
           }));
         }
-        
+
         // 保存原始数据用于取消操作
         this.originalPhoneList = this.phoneList;
       });
@@ -1795,7 +1795,7 @@ export default {
         return;
       }
       // 检查是否重复
-      const duplicateIndex = this.phoneList.findIndex((item, idx) => 
+      const duplicateIndex = this.phoneList.findIndex((item, idx) =>
         idx !== index && item.phone === phone
       );
       if (duplicateIndex !== -1) {
@@ -1846,17 +1846,17 @@ export default {
         this.$message.error('请先保存正在编辑的手机号');
         return;
       }
-      
+
       // 检查是否有空的手机号
       const emptyPhone = this.phoneList.find(item => !item.phone.trim());
       if (emptyPhone) {
         this.$message.error('存在空的手机号,请删除或填写完整');
         return;
       }
-      
+
       // 构造手机号列表
       const phoneList = this.phoneList.map(item => item.phone);
-      
+
       // 调用保存接口
       saveErpPhone(phoneList).then(response => {
         if (response.code === 200) {
@@ -1876,7 +1876,7 @@ export default {
       this.phoneList = JSON.parse(JSON.stringify(this.originalPhoneList));
       this.erpPhone.open = false;
     },
-    
+
     handleImportExpress() {
           this.importExpress.title = "导入";
           this.importExpress.open = true;
@@ -1911,7 +1911,7 @@ export default {
           this.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
           this.getList();
         },
-        
+
         // 提交上传文件
         submitFileFormExpress() {
           this.$refs.importExpress.submit();
@@ -2108,7 +2108,7 @@ export default {
       };
       this.queryParams.sortField = null;
       this.queryParams.sortOrder = null;
-      
+
       // 清除订单号标签
       this.queryParams.orderCodes = [];
       this.currentInput = '';
@@ -2120,7 +2120,7 @@ export default {
           this.$refs.orderTable.clearSort();
         }
       });
-      
+
       this.handleQuery();
     },
     // 多选框选中数据
@@ -2223,7 +2223,7 @@ export default {
         }).then(response => {
 			console.log(response)
 			if(response.code==200){
-			
+
 			that.msgSuccess(response.msg);
 			that.taskId=response.data;
 			that.time=setInterval(function(){
@@ -2245,7 +2245,7 @@ export default {
       // 打开字段选择对话框
       this.exportFieldDialog.open = true;
     },
-    
+
     // 导出字段选择相关方法
     // 全选字段
     selectAllFields() {
@@ -2253,22 +2253,22 @@ export default {
         field.checked = true;
       });
     },
-    
+
     // 全不选字段
     unselectAllFields() {
       this.exportFieldOptions.forEach(field => {
         field.checked = false;
       });
     },
-    
+
     // 选择常用字段
     selectDefaultFields() {
       // 先全不选
       this.unselectAllFields();
       // 然后选择常用字段
-      const defaultFields = ['orderCode', 'prescribeCode', 'companyName', 'companyUserNickName', 
-                           'storeName', 'miniProgramName', 'userName', 'userPhone', 'userAddress', 'totalPrice', 
-                           'totalNum', 'payPrice', 'payMoney', 'createTime', 'payTime', 
+      const defaultFields = ['orderCode', 'prescribeCode', 'companyName', 'companyUserNickName',
+                           'storeName', 'miniProgramName', 'userName', 'userPhone', 'userAddress', 'totalPrice',
+                           'totalNum', 'payPrice', 'payMoney', 'createTime', 'payTime',
                            'payType', 'status', 'packageName', 'patientName'];
       this.exportFieldOptions.forEach(field => {
         if (defaultFields.includes(field.key)) {
@@ -2276,22 +2276,22 @@ export default {
         }
       });
     },
-    
+
     // 获取已选择字段数量
     getSelectedFieldsCount() {
       return this.exportFieldOptions.filter(field => field.checked).length;
     },
-    
+
     // 取消导出字段选择
     cancelExportFieldDialog() {
       this.exportFieldDialog.open = false;
     },
-    
+
     // 确认导出字段
     confirmExportFields() {
       // 获取已选择的字段
       const selectedFieldsArray = this.exportFieldOptions.filter(field => field.checked);
-      
+
       let selectedFields = '';
       if (selectedFieldsArray.length === 0) {
         // 如果没有选择任何字段,则导出全部字段(不传filter参数)
@@ -2300,51 +2300,51 @@ export default {
         // 如果选择了字段,则只导出选中的字段
         selectedFields = selectedFieldsArray.map(field => field.key).join(',');
       }
-      
+
       // 关闭弹窗
       this.exportFieldDialog.open = false;
-      
+
       // 执行导出操作
       this.doExportOrder(selectedFields);
     },
-    
+
     // 执行导出操作
     doExportOrder(selectedFields) {
       var that = this;
-      
+
       // 处理查询参数
       if(this.payTypeArr.length>0){
         this.queryParams.payType=this.payTypeArr.toString();
       } else {
         this.queryParams.payType=null
       }
-      
+
       if(this.scheduleIdArr.length>0){
         this.queryParams.scheduleId=this.scheduleIdArr.toString();
       } else {
         this.queryParams.scheduleId=null
       }
-      
+
       if(this.buyTypeArr.length>0){
         this.queryParams.orderBuyType=this.buyTypeArr.toString();
       } else {
         this.queryParams.orderbuyType=null
       }
-      
+
       if(this.channelArr.length>0){
         this.queryParams.orderChannel=this.channelArr.toString();
       } else {
         this.queryParams.orderChannel=null
       }
-      
+
       if(this.qwSubjectArr.length>0){
         this.queryParams.qwSubject=this.qwSubjectArr.toString();
       } else {
         this.queryParams.qwSubject=null
       }
-      
+
       const queryParams = this.queryParams;
-      
+
       // 根据是否选择字段显示不同的确认消息
       let confirmMessage = '';
       if (selectedFields === null) {
@@ -2353,21 +2353,21 @@ export default {
         const fieldCount = selectedFields.split(',').length;
         confirmMessage = `确认导出选中的 ${fieldCount} 个字段的订单数据?`;
       }
-      
+
       this.$confirm(confirmMessage, "确认导出", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
       }).then(() => {
         this.exportLoading = true;
-        
+
         // 构建请求参数
         const requestParams = {...queryParams};
         // 只有当selectedFields不为null时才添加filter参数
         if (selectedFields !== null) {
           requestParams.filter = selectedFields;
         }
-        
+
         return exportOrder2(requestParams);
       }).then(response => {
         console.log(response)
@@ -2414,7 +2414,7 @@ export default {
           this.getTreeselect();
         }
       }
-      
+
     },
     // companyChange(val){
     //   console.log(val);
@@ -2578,15 +2578,15 @@ export default {
     min-width: auto;
     width: 100%;
   }
-  
+
   .tags-wrapper {
     min-height: 40px;
   }
-  
+
   .quick-actions {
     flex-direction: column;
     align-items: flex-start;
     gap: 8px;
   }
 }
-</style>
+</style>

+ 3 - 1
src/views/hisStore/menu/index.vue

@@ -207,7 +207,9 @@ export default {
         {"dictLabel": "养生有道",
           "dictValue": "2"},
         {"dictLabel": "个人中心",
-          "dictValue": "3"}
+          "dictValue": "3"},
+        {"dictLabel": "主菜单-热销榜",
+          "dictValue": "4"}
       ],
       statusOptions:[],
       imageArr:[],

+ 11 - 0
src/views/hisStore/storeOrder/healthStoreList.vue

@@ -463,6 +463,12 @@
             <el-tooltip content="按应收金额排序" placement="top"/>
           </template>
         </el-table-column>
+
+      <el-table-column label="成本价格" align="center" prop="cost" v-if="showFinanceTableField"/>
+      <el-table-column label="结算价格" align="center" prop="fprice"  v-if="showFinanceTableField"/>
+      <el-table-column label="额外运费" align="center" prop="payPostage" v-if="showFinanceTableField"/>
+      <el-table-column label="商品编码" align="center" prop="barCode"  v-if="showFinanceTableField"/>
+      <el-table-column label="商品分类" align="center" prop="cateName" v-if="showFinanceTableField"/>
       <el-table-column align="center" label="下单时间" prop="createTime"/>
       <!-- <el-table-column label="支付状态" align="center" prop="paid" /> -->
       <el-table-column align="center" label="支付时间" prop="payTime" width="180">
@@ -976,6 +982,7 @@ import Treeselect from '@riophae/vue-treeselect'
 import '@riophae/vue-treeselect/dist/vue-treeselect.css'
 import { getConfigByKey } from '@/api/system/config'
 import {list as getAppMallOptions} from '@/api/course/coursePlaySourceConfig';
+import {checkPermi} from "@/utils/permission";
 
 export default {
   components: { productOrder, productSelect, addUser, addUserAddress, Treeselect },
@@ -1238,6 +1245,7 @@ export default {
       ruleForm:{
         miniAppId: null,
       },
+      showFinanceTableField: false,
     }
   },
   created() {
@@ -1266,6 +1274,9 @@ export default {
     this.getDicts('store_delivery_pay_status').then((response) => {
       this.deliveryPayStatusOptions = response.data
     })
+    if (checkPermi(['his:storeAfterSales:finance'])) {
+      this.showFinanceTableField = true;
+    }
 
     this.getList()
     this.getErpAccountList();

+ 24 - 7
src/views/hisStore/storeOrder/index.vue

@@ -92,6 +92,16 @@
         />
       </el-form-item>
 
+      <el-form-item label="产品名称" prop="productName">
+        <el-input
+          v-model="queryParams.productName"
+          placeholder="请输入产品名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
       <el-form-item label="手机号" prop="userPhone">
         <el-input
           v-model="queryParams.userPhone"
@@ -470,6 +480,12 @@
               <span v-if="scope.row.totalPrice!=null">{{scope.row.totalPrice.toFixed(2)}}</span>
           </template>
       </el-table-column>
+
+      <el-table-column label="成本价格" align="center" prop="cost" v-if="showFinanceTableField"/>
+      <el-table-column label="结算价格" align="center" prop="fprice"  v-if="showFinanceTableField"/>
+      <el-table-column label="额外运费" align="center" prop="payPostage" v-if="showFinanceTableField"/>
+      <el-table-column label="商品编码" align="center" prop="barCode"  v-if="showFinanceTableField"/>
+      <el-table-column label="商品分类" align="center" prop="cateName" v-if="showFinanceTableField"/>
        <!-- <el-table-column label="应付金额" align="center" prop="payPrice" >
           <template slot-scope="scope">
               <span v-if="scope.row.payPrice!=null">{{scope.row.payPrice.toFixed(2)}}</span>
@@ -511,7 +527,7 @@
               <el-tag prop="orderMedium" v-for="(item, index) in orderMediumOptions"    v-if="scope.row.orderMedium==item.dictValue">{{item.dictLabel}}</el-tag>
           </template>
       </el-table-column>
-      <el-table-column label="订单产品" align="center" width="200px">
+      <el-table-column label="产品名称" align="center" width="200px">
         <template slot-scope="scope">
           <div v-if="scope.row.items && scope.row.items.length > 0">
             <el-tag
@@ -668,7 +684,7 @@
                     </el-popover>
                   </template>
                 </el-table-column>
-                <el-table-column label="品名称" show-overflow-tooltip align="center" prop="productName" />
+                <el-table-column label="品名称" show-overflow-tooltip align="center" prop="productName" />
                 <el-table-column label="商品规格" align="center" prop="sku" />
                 <el-table-column label="库存" align="center" prop="stock" />
                 <el-table-column label="单价" align="center" prop="price" />
@@ -1013,6 +1029,7 @@ import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 import { getConfigByKey } from '@/api/system/config'
 import {list as getAppMallOptions} from '@/api/course/coursePlaySourceConfig';
+import {checkPermi} from "@/utils/permission";
 
 export default {
   components: { productOrder,productSelect,addUser,addUserAddress,Treeselect },
@@ -1230,7 +1247,7 @@ export default {
         isSysDel: null,
         deptId:null,
         isUpload:null,
-
+        productName:null,
       },
       // 表单参数
       form: {
@@ -1280,6 +1297,7 @@ export default {
       ruleForm:{
         miniAppId: null,
       },
+      showFinanceTableField: false,
     };
   },
   created() {
@@ -1320,6 +1338,9 @@ export default {
     getTcmScheduleList().then(response => {
       this.scheduleOptions = response.data;
     });
+    if (checkPermi(['his:storeAfterSales:finance'])) {
+      this.showFinanceTableField = true;
+    }
     this.getList();
     this.getItemsNum();
     this.getErpAccountList();
@@ -1444,10 +1465,6 @@ export default {
 
     },
 
-    // 删除订单号
-    removeOrderCode(index) {
-      this.queryParams.orderCodes.splice(index, 1)
-    },
     // 清空所有标签
     clearAllTags() {
       this.$confirm('确认清空所有订单号吗?', '提示', {

+ 7 - 7
src/views/hisStore/storeProduct/index.vue

@@ -553,13 +553,13 @@
           </el-form-item>
         </div>
         </div>
-<!--        <el-row>-->
-<!--          <el-col :span="24">-->
-<!--            <el-form-item label="商品简介" prop="productInfo">-->
-<!--              <el-input v-model="form.productInfo" type="textarea" :rows="2" placeholder="请输入商品简介" />-->
-<!--            </el-form-item>-->
-<!--          </el-col>-->
-<!--        </el-row>-->
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="商品简介" prop="productInfo">
+              <el-input v-model="form.productInfo" type="textarea" :rows="2" placeholder="请输入商品简介" />
+            </el-form-item>
+          </el-col>
+        </el-row>
         <el-form-item label="商品图片" prop="image">
           <Material v-model="imageArr" type="image" :num="1" :width="150" :height="150" />
         </el-form-item>

+ 44 - 2277
src/views/index.vue

@@ -1,2313 +1,80 @@
 <template>
-  <div class="statistics-dashboard">
-    <!-- 数据概览 (Data Overview) -->
-    <el-card class="overview-section" shadow="never">
-      <el-row :gutter="20">
-        <el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="16" class="companybox">
-          <img src="../assets/images/topbg.png" alt="" class="topimg">
-          <img src="../assets/images/topbg.png" alt="" class="bottomimg">
-          <div class="companyboxtitle">
-            企业数据
-          </div>
-          <div class="companyflex">
-            <div class="topbg companycard cardafter">
-              <div class="card-title1">
-                <img src="../assets/images/tab_company.png" alt="" class="icon-img">
-                分公司数量
-              </div>
-
-              <div class="card-value highlight1">
-                <count-to :start-val="0" :end-val="dealderCount" :duration="3600"
-                          class="card-panel-num companynumber" />
-              </div>
-            </div>
-            <div class="companycard cardafter">
-              <div class="card-title1">
-                <img src="../assets/images/salesperson.png" alt="" class="icon-img">
-                销售数量
-              </div>
-              <div class="card-value highlight1">
-                <count-to :start-val="0" :end-val="groupMgrCount" :duration="3600"
-                          class="card-panel-num companynumber" />
-              </div>
-            </div>
-            <div class="companycard cardafter">
-              <div class="card-title1">
-                <img src="../assets/images/member.png" alt="" class="icon-img">
-                会员数量
-              </div>
-              <div class="card-value highlight1">
-                <count-to :start-val="0" :end-val="memberCount" :duration="3600" class="card-panel-num companynumber" />
-                <span class="highlight-today-add companyadd">+{{todayIncreaseUserNum}}</span>
-              </div>
-
-            </div>
-            <div class="cardafter companycard">
-              <div class="card-title1">
-                <img src="../assets/images/tab_enterprise.png" alt="" class="icon-img">
-                企微数量
-              </div>
-              <div class="card-value highlight1">
-                <count-to :start-val="0" :end-val="qwMemberNum" :duration="3600" class="card-panel-num companynumber" />
-              </div>
-            </div>
-            <div class="botttombg companycard">
-              <div class="card-title1">
-                <svg-icon icon-class="phone" />
-                pad使用情况
-              </div>
-              <div class="card-value highlight1">
-                <count-to :start-val="0" :end-val="padUsedNum" :duration="3600" class="card-panel-num companynumber" />
-                /
-                <template v-if="typeof padTotalNum === 'number'">
-                  <count-to :start-val="0" :end-val="padTotalNum" :duration="1800" class="card-panel-num companynumber" />
-                </template>
-                <template v-else>
-                  <span class="card-panel-num companynumber">{{ padTotalNum }}</span>
-                </template>
-              </div>
-            </div>
-          </div>
-        </el-col>
-
-
-        <el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8" class="propertyboxtitle">
-          <div class="property_title">
-            资产概览
-          </div>
-          <div class="propertyboxflex">
-            <div class="property-card propertyline">
-              <div class="property-title">
-                <i class="el-icon-money"></i>
-                企业资产(元)
-              </div>
-              <div class="card-value highlight">
-                <count-to :start-val="0" :end-val="balance" :duration="3600" class="card-panel-num" />
-              </div>
-            </div>
-            <div class="property-card propertyline">
-              <div class="property-title">
-                <i class="el-icon-money"></i>
-                润天余额(元)
-              </div>
-              <div class="card-value highlight">
-                <count-to :start-val="0" :end-val="runTianBalance" :duration="3600" class="card-panel-num" />
-              </div>
-            </div>
-            <div class="property-card">
-              <div class="property-title">
-                <span>今日消耗 (元)</span>
-              </div>
-              <div class="card-value highlight" style="color: rgba(32, 33, 36, 1);margin-top: 10px;">
-                <count-to :start-val="0" :end-val="todayComsumption" :duration="3600" class="card-panel-num" />
-              </div>
-              <div class="card-compare">
-                较昨日 <span>+1</span>
-              </div>
-            </div>
-          </div>
-
-        </el-col>
-      </el-row>
-
-      <el-row :gutter="20">
-        <el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="16">
-          <div class="operatetitle">
-            经营数据
-          </div>
-          <div class="operatetitle-col">
-            <div class="operatetitle-card">
-              <div class="card-title">
-                <i class="el-icon-shopping-cart-full"></i>
-                收款总数
-              </div>
-              <div class="operate-value highlight">
-                <count-to :start-val="0" :end-val="recvTotalNum" :duration="3600" class="card-panel-num" />
-                <div class="yesterdaybox">
-                  较昨日 <span class="highlight-today-add2">+{{recvTodayNum}}</span>
-                </div>
-              </div>
-              <div class="card-badge">
-              </div>
-            </div>
-            <div class="operatetitle-card">
-              <div class="card-title">
-                <i class="el-icon-shopping-cart-full"></i>
-                订单总数
-              </div>
-              <div class="operate-value highlight">
-                <count-to :start-val="0" :end-val="orderTotalNum" :duration="3600" class="card-panel-num" />
-                <div class="yesterdaybox">
-                  较昨日 <span class="highlight-today-add2">+{{todayOrderNum}}</span>
-                </div>
-
-              </div>
-              <div class="card-badge">
-              </div>
-
-            </div>
-            <div class="operatetitle-card">
-              <div class="card-title">
-                平台今日看课人数
-              </div>
-              <div class="operate-value highlight">
-                <count-to :start-val="0" :end-val="todayWatchUserCount" :duration="3600" class="card-panel-num" />
-              </div>
-              <div class="card-sub">
-                <span>配额上限</span>
-                <span class="sub-value">
-                  <count-to :start-val="0" :end-val="todayWatchUserCount" :duration="3600" class="card-panel-num"
-                            style="color: rgba(49, 185, 154, 1);" />
-                  /
-                  <count-to :start-val="0" :end-val="versionLimit" :duration="3600" class="card-panel-num" />
-                </span>
-              </div>
-              <el-progress :percentage="versionLimitPercent" :show-text="false"
-                           color="#409EFF"></el-progress>
-            </div>
-            <div class="operatetitle-card">
-              <div class="card-title">
-                <i class="el-icon-shopping-cart-full"></i>
-                商品总数
-              </div>
-              <div class="operate-value highlight">
-                <count-to :start-val="0" :end-val="goodsTotalNum" :duration="3600" class="card-panel-num" />
-                <div class="yesterdaybox">
-                  较昨日 <span class="highlight-today-add2">+{{todayGoodsNum}}</span>
-                </div>
-
-              </div>
-              <div class="card-badge">
-              </div>
-            </div>
-          </div>
-
-        </el-col>
-
-
-        <el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8" style="padding-left: 15px;">
-
-          <div class="internetbox">
-            <div class="internet-cardtop">
-              <div class="cardinnerbox">
-                <div class="cardtopimg">
-                  <img src="../assets/images/liuliang.png" alt=""><span>剩余流量</span>
-                </div>
-                <div class="cardtopnumber">
-                  <span>{{formatBytes(this.trafficCount)}}</span>
-                </div>
-              </div>
-              <div class="progress">
-                <el-progress :percentage="90" :show-text="false" define-back-color="#000">
-
-                </el-progress>
-              </div>
-              <div class="cardinnerbox2">
-                <div>
-                  今日消耗 <span>{{formatBytes(this.todayTraffic)}}</span>
-                </div>
-                <div>
-                  本月 <span>{{formatBytes(this.thisMonthTraffic)}}</span>
-                </div>
-              </div>
-            </div>
-
-            <div class="internetbox-messge">
-              <div class="internet-card">
-                <img src="../assets/images/message.png" alt="">
-
-                <span class="internet-title">
-                  短信剩余条数 (条)
-                </span>
-              </div>
-              <div class="internet-number">
-                0
-              </div>
-            </div>
-          </div>
-        </el-col>
-      </el-row>
-    </el-card>
-    <!-- 分析概览 (Analysis Overview) -->
-    <div class="analysis-section" shadow="never">
-      <div slot="header" class="header">
-        <div>分析概览</div>
-        <div class="tab-group">
-          <el-radio-group v-model="queryTime" size="medium" @change="handleAnalysis">
-            <el-radio-button label="今日"></el-radio-button>
-            <el-radio-button label="昨日"></el-radio-button>
-            <el-radio-button label="本周"></el-radio-button>
-            <el-radio-button label="本月"></el-radio-button>
-            <el-radio-button label="上月"></el-radio-button>
-          </el-radio-group>
-        </div>
-        <div class="action-group">
-          <div v-if="this.$store.state.user.medicalMallConfig.statics">
-            <!-- 选择部门 -->
-            <el-select v-model="deptId" placeholder="请选择部门" size="small" @change="handleDeptChange" style="width: 150px">
-              <el-option
-                v-for="company in deptOptions"
-                :key="company.deptId"
-                :label="company.deptName"
-                :value="company.deptId"
-              />
-            </el-select>
-            <!-- 选择销售公司 -->
-            <el-select  v-model="companyId" placeholder="请选择销售公司" size="small" clearable @change="handleCompanyChange" style="width: 180px" >
-              <el-option
-                v-for="company in companyOptions"
-                :key="company.companyId"
-                :label="company.companyName"
-                :value="company.companyId"
-              />
-            </el-select>
-          </div>
-          <el-radio-group v-model="userTypeText" @change="handleUserType">
-            <el-radio-button label="会员"></el-radio-button>
-            <el-radio-button label="企微"></el-radio-button>
-          </el-radio-group>
-
-          <el-dropdown @command="handleAutoRefresh" trigger="click">
-            <el-button size="small" plain>
-              自动刷新
-              <i class="el-icon-arrow-down el-icon--right"></i>
-            </el-button>
-            <el-dropdown-menu slot="dropdown">
-              <el-dropdown-item :command="0" :class="{ 'is-active': !autoRefreshInterval }">关闭</el-dropdown-item>
-              <el-dropdown-item :command="5" :class="{ 'is-active': autoRefreshInterval === 5 }">5分钟</el-dropdown-item>
-              <el-dropdown-item :command="10"
-                                :class="{ 'is-active': autoRefreshInterval === 10 }">10分钟</el-dropdown-item>
-              <el-dropdown-item :command="15"
-                                :class="{ 'is-active': autoRefreshInterval === 15 }">15分钟</el-dropdown-item>
-            </el-dropdown-menu>
-          </el-dropdown>
-          <el-button size="small" plain icon="el-icon-refresh" type="primary" @click="manualRefresh">手动刷新</el-button>
-        </div>
-      </div>
+  <div class="app-container">
+    <!-- 有权限时显示统计仪表板 -->
+    <statistics-dashboard v-if="hasDashboardPermission && !loading" />
+
+    <!-- 无权限时显示欢迎页面 -->
+    <welcome-page v-else-if="!hasDashboardPermission && !loading" />
+
+    <!-- 加载状态 -->
+    <div v-else class="loading-container">
+      <el-skeleton animated>
+        <template #template>
+          <el-skeleton-item variant="image" style="width: 100%; height: 400px;" />
+        </template>
+      </el-skeleton>
     </div>
-    <div>
-      <el-row :gutter="20">
-        <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" style="position: relative">
-          <div class="analysis-card-check" :class="selectedDiv===0?'analysis-card-check-selected color':''"
-               @click="handleToggleDiv(0)">
-            <div class="analysis-card">
-              <img class="card-icon" src="../assets/images/cishu_views.png"></img>
-              <div class="card-content">
-                <div class="card-row">
-                  <span>观看人数</span>
-                  <span class="highlight">
-                    <count-to :start-val="0" :end-val="watchUserCount" :duration="3600" class="card-panel-num" />
-                  </span>
-                </div>
-                <div class="card-row">
-                  <span>完播人数</span>
-                  <span class="highlight">
-                    <count-to :start-val="0" :end-val="completedUserCount" :duration="3600" class="card-panel-num" />
-                  </span>
-                </div>
-                <div class="card-row">
-                  <span>完播率</span>
-                  <span class="highlight">{{completedRate}}%</span>
-                </div>
-              </div>
-            </div>
-            <div class="analysis-card">
-              <img class="card-icon" src="../assets/images/number_views.png"></img>
-              <div class="card-content">
-                <div class="card-row">
-                  <span>观看次数</span>
-                  <span class="highlight-red">
-                    <count-to :start-val="0" :end-val="watchCount" :duration="3600" class="card-panel-num" /></span>
-                </div>
-                <div class="card-row">
-                  <span>完播次数</span>
-                  <span class="highlight-red">
-                    <count-to :start-val="0" :end-val="completedCount" :duration="3600" class="card-panel-num" />
-                  </span>
-                </div>
-                <div class="card-row">
-                  <span>视频完播率</span>
-                  <span class="highlight-red">{{watchRate}}%</span>
-                </div>
-              </div>
-            </div>
-          </div>
-        </el-col>
-
-        <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6" style="position: relative">
-          <div class="analysis-card-check" :class="selectedDiv===1?'analysis-card-check-selected color':''"
-               @click="handleToggleDiv(1)">
-            <div class="analysis-card">
-              <img class="card-icon" src="../assets/images/renshu_views.png"></img>
-              <div class="card-content">
-                <div class="card-row">
-                  <span>答题人数</span>
-                  <span class="highlight-black">
-                    <count-to :start-val="0" :end-val="answerMemberCount" :duration="3600" class="card-panel-num" />
-                  </span>
-                </div>
-                <div class="card-row">
-                  <span>正确人数</span>
-                  <span class="highlight-black">
-                    <count-to :start-val="0" :end-val="correctUserCount" :duration="3600" class="card-panel-num" />
-                  </span>
-                </div>
-                <div class="card-row">
-                  <span>正确率</span>
-                  <span class="highlight-black">{{correctRate}}%</span>
-                </div>
-              </div>
-            </div>
-          </div>
-        </el-col>
-
-        <el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6"  style="position: relative">
-          <div class="analysis-card-check" :class="selectedDiv===2?'analysis-card-check-selected color':''"
-               @click="handleToggleDiv(2)">
-            <div class="analysis-card">
-              <img class="card-icon" src="../assets/images/hongbao_views.png"></img>
-              <div class="card-content">
-                <div class="card-row">
-                  <span>答题红包个数</span>
-                  <span class="highlight-black">
-                    <count-to :start-val="0" :end-val="rewardCount" :duration="3600" class="card-panel-num" />
-                  </span>
-                </div>
-                <div class="card-row">
-                  <span>答题红包金额(元)</span>
-                  <span class="highlight-black">
-                    <count-to :start-val="0" :end-val="rewardMoney" :duration="3600" class="card-panel-num" /></span>
-                </div>
-              </div>
-            </div>
-          </div>
-        </el-col>
-      </el-row>
-    </div>
-
-    <!-- 图表区域 (Charts Area) -->
-    <transition name="fade">
-      <el-row :gutter="20" class="charts-section" v-show="selectedDiv===0">
-        <el-col :span="12">
-          <el-card shadow="never">
-            <div slot="header" class="chart-header">
-              <span>会员观看、完播人数趋势图</span>
-              <div class="legend">
-                <div class="legend-item">
-                  <span class="dot viewer-dot"></span>
-                  <span>观看人数</span>
-                </div>
-                <div class="legend-item">
-                  <span class="dot complete-dot"></span>
-                  <span>完播人数</span>
-                </div>
-              </div>
-              <!--              <el-button size="small" plain class="view-more">平台每日统计 <i class="el-icon-arrow-right"></i></el-button>-->
-            </div>
-            <div ref="viewerChart" class="chart-container"></div>
-          </el-card>
-        </el-col>
-
-
-        <el-col :span="12">
-          <el-card shadow="never">
-            <div slot="header" class="chart-header">
-              <span>经销商看客统计</span>
-              <div class="legend">
-                <div class="legend-item">
-                  <span class="dot viewer-dot"></span>
-                  <span>观看人数</span>
-                </div>
-                <div class="legend-item">
-                  <span class="dot complete-dot"></span>
-                  <span>完播人数</span>
-                </div>
-              </div>
-            </div>
-            <div ref="dealerChartNew" class="chart-container"></div>
-          </el-card>
-        </el-col>
-
-<!--        <el-col :span="12">-->
-<!--          <el-card shadow="never">-->
-<!--            <div slot="header" class="chart-header">-->
-<!--              <span>经销商会员观看TOP10</span>-->
-<!--              <div class="legend">-->
-<!--                <el-radio-group v-model="viewerType" size="small" @change="handleDealerChartData">-->
-<!--                  <el-radio-button label="0">按观看人数</el-radio-button>-->
-<!--                  <el-radio-button label="1">按完播人数</el-radio-button>-->
-<!--                </el-radio-group>-->
-<!--              </div>-->
-<!--              &lt;!&ndash;              <el-button size="small" plain class="view-more">经销商统计 <i class="el-icon-arrow-right"></i></el-button>&ndash;&gt;-->
-<!--            </div>-->
-<!--            <div ref="dealerChart" class="chart-container"></div>-->
-<!--          </el-card>-->
-<!--        </el-col>-->
-      </el-row>
-    </transition>
-    <transition name="fade">
-      <el-row :gutter="20" class="charts-section" v-show="selectedDiv===1">
-        <el-card shadow="never">
-          <div slot="header" class="chart-header">
-            <span>课程观看TOP10</span>
-            <div class="legend">
-              <el-radio-group v-model="viewerType" size="small" @change="handleCourseWatchChart">
-                <el-radio-button label="0">按观看人数</el-radio-button>
-                <el-radio-button label="1">按完播人数</el-radio-button>
-                <el-radio-button label="2">按答题人数</el-radio-button>
-                <el-radio-button label="3">按正确人数</el-radio-button>
-              </el-radio-group>
-            </div>
-            <div class="legend">
-              <el-radio-group v-model="delerSort" @change="handleCourseWatchChart">
-                <el-radio label="DESC">前10名</el-radio>
-                <el-radio label="ASC">倒数10名</el-radio>
-              </el-radio-group>
-            </div>
-            <div class="legend">
-              <div class="legend-item">
-                <span class="dot viewer-dot"></span>
-                <span>观看人数</span>
-              </div>
-              <div class="legend-item">
-                <span class="dot complete-dot"></span>
-                <span>完播人数</span>
-              </div>
-              <div class="legend-item">
-                <span class="dot" style="background-color: #E6A23C"></span>
-                <span>答题人数</span>
-              </div>
-              <div class="legend-item">
-                <span class="dot" style="background-color: #F56C6C"></span>
-                <span>正确人数</span>
-              </div>
-            </div>
-            <!--            <el-button size="small" plain class="view-more">经销商统计 <i class="el-icon-arrow-right"></i></el-button>-->
-          </div>
-          <div ref="courseWatchChart" class="chart-container"></div>
-        </el-card>
-      </el-row>
-    </transition>
-
-    <transition name="fade">
-      <el-row :gutter="20" class="charts-section" v-show="selectedDiv===2">
-        <el-col :span="12">
-          <el-card shadow="never">
-            <div slot="header" class="chart-header">
-              <span>答题红包金额TOP10</span>
-              <div class="legend">
-                <el-radio-group v-model="dataType" size="small" @change="handleAnswerRedPackViewerChart">
-                  <el-radio-button label="0">按经销商排行</el-radio-button>
-                  <el-radio-button label="1">按课程排行</el-radio-button>
-                </el-radio-group>
-              </div>
-              <!--              <el-button size="small" plain class="view-more">红包记录 <i class="el-icon-arrow-right"></i></el-button>-->
-            </div>
-            <div ref="answerRedPackViewerChart" class="chart-container"></div>
-          </el-card>
-        </el-col>
-        <el-col :span="12">
-          <el-card shadow="never">
-            <div slot="header" class="chart-header">
-              <span>答题红包金额趋势图</span>
-              <div class="legend">
-                <div class="legend-item">
-                  <span class="dot viewer-dot"></span>
-                  <span>答题红包金额</span>
-                </div>
-              </div>
-              <!--              <el-button size="small" plain class="view-more">红包记录 <i class="el-icon-arrow-right"></i></el-button>-->
-            </div>
-            <div ref="answerRedPackMoneyViewerChart" class="chart-container"></div>
-          </el-card>
-        </el-col>
-      </el-row>
-    </transition>
-    <el-row :gutter="20" class="charts-section">
-      <el-col :span="12">
-        <el-card shadow="never">
-          <div slot="header" class="chart-header">
-            <span>本月订单数</span>
-            <div class="legend">
-              <div class="legend-item">
-                <span class="dot viewer-dot"></span>
-                <span>订单数</span>
-              </div>
-              <div class="legend-item">
-                <span class="dot complete-dot"></span>
-                <span>订单金额</span>
-              </div>
-            </div>
-          </div>
-          <div ref="viewerOrderChart" class="chart-container"></div>
-        </el-card>
-      </el-col>
-      <el-col :span="12">
-        <el-card shadow="never">
-          <div slot="header" class="chart-header">
-            <span>本月收款数</span>
-            <div class="legend">
-              <div class="legend-item">
-                <span class="dot viewer-dot"></span>
-                <span>收款数</span>
-              </div>
-              <div class="legend-item">
-                <span class="dot complete-dot"></span>
-                <span>收款金额</span>
-              </div>
-            </div>
-          </div>
-          <div ref="viewerReceiveChart" class="chart-container"></div>
-        </el-card>
-      </el-col>
-    </el-row>
-    <br/>
   </div>
 </template>
 
 <script>
-import * as echarts from 'echarts'
-import CountTo from "vue-count-to";
-import {
-  analysisPreview,
-  authorizationInfo,
-  dealerAggregated, deaMemberTopTen, rechargeComsumption, rewardMoneyTopTen, rewardMoneyTrend,
-  smsBalance, thisMonthOrderCount, thisMonthRecvCount, trafficLog,
-  watchCourseTopTen, watchEndPlayTrend,getWatchCourseStatisticsData
-} from "@/api/statistics/statistics";
-import dayjs from 'dayjs';
-import { listDept } from '@/api/system/dept'
-import { listCompany } from '@/api/his/company'
-
-
-const viewCharOption = {
-  tooltip: {
-    trigger: 'axis',
-    axisPointer: {
-      type: 'shadow'
-    }
-  },
-  grid: {
-    left: '3%',
-    right: '4%',
-    bottom: '3%',
-    containLabel: true
-  },
-  xAxis: {
-    type: 'category',
-    data: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23']
-  },
-  yAxis: {
-    type: 'value'
-  },
-  series: [
-    {
-      name: '观看人数',
-      type: 'bar',
-      data: [],
-      itemStyle: {
-        color: '#409EFF'
-      }
-    },
-    {
-      name: '完播人数',
-      type: 'bar',
-      data: [],
-      itemStyle: {
-        color: '#67C23A'
-      }
-    }
-  ]
-}
-
-const dealerOptionNew = {
-  tooltip: {
-    trigger: 'axis',
-    axisPointer: {
-      type: 'shadow'
-    }
-  },
-  grid: {
-    left: '3%',
-    right: '4%',
-    bottom: '3%',
-    containLabel: true
-  },
-  xAxis: {
-    type: 'category',
-    axisLabel: {
-      rotate: 30, // 设置标签倾斜45度
-      // fontSize: 12, // 减小字体大小
-      interval: 0, // 显示所有标签
-      // 可选:限制标签宽度并截断
-      width: 80,
-      overflow: 'truncate',
-      // 可选:设置标签的对齐方式
-      margin: 20,
-      fontWeight: 'bold' // 设置字体加粗
-    }
-  },
-  yAxis: {
-    type: 'value'
-  },
-  series: [
-    {
-      name: '观看人数',
-      type: 'bar',
-      data: [],
-      itemStyle: {
-        color: '#409EFF'
-      }
-    },
-    {
-      name: '完播人数',
-      type: 'bar',
-      data: [],
-      itemStyle: {
-        color: '#67C23A'
-      }
-    }
-  ]
-}
-
-const thisMonthOrderCountOption = {
-  tooltip: {
-    trigger: 'axis',
-    axisPointer: {
-      type: 'shadow'
-    }
-  },
-  grid: {
-    left: '3%',
-    right: '4%',
-    bottom: '3%',
-    containLabel: true
-  },
-  xAxis: {
-    type: 'category',
-    data: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23']
-  },
-  yAxis: {
-    type: 'value'
-  },
-  series: [
-    {
-      name: '订单数',
-      type: 'line',
-      data: [],
-      itemStyle: {
-        color: '#409EFF'
-      }
-    },
-    {
-      name: '订单金额',
-      type: 'line',
-      data: [],
-      itemStyle: {
-        color: '#67C23A'
-      }
-    }
-  ]
-}
-
-const thisMonthRecvCountOption = {
-  tooltip: {
-    trigger: 'axis',
-    axisPointer: {
-      type: 'shadow'
-    }
-  },
-  grid: {
-    left: '3%',
-    right: '4%',
-    bottom: '3%',
-    containLabel: true
-  },
-  xAxis: {
-    type: 'category',
-    data: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23']
-  },
-  yAxis: {
-    type: 'value'
-  },
-  series: [
-    {
-      name: '收款数',
-      type: 'line',
-      data: [],
-      itemStyle: {
-        color: '#409EFF'
-      }
-    },
-    {
-      name: '收款金额',
-      type: 'line',
-      data: [],
-      itemStyle: {
-        color: '#67C23A'
-      }
-    }
-  ]
-}
-const dealerOption = {
-  tooltip: {
-    trigger: 'axis',
-    axisPointer: {
-      type: 'shadow'
-    }
-  },
-  grid: {
-    left: '3%',
-    right: '4%',
-    bottom: '3%',
-    containLabel: true
-  },
-  xAxis: {
-    type: 'value'
-  },
-  yAxis: {
-    type: 'category',
-    data: []
-  },
-  series: [
-    {
-      name: '观看人数',
-      type: 'bar',
-      data: [],
-      itemStyle: {
-        color: '#409EFF'
-      }
-    }
-  ]
-}
-
-const courseWatchOption = {
-  tooltip: {
-    trigger: 'axis',
-    axisPointer: {
-      type: 'shadow'
-    }
-  },
-  grid: {
-    left: '3%',
-    right: '4%',
-    bottom: '8%',
-    top: '3%',
-    containLabel: true
-  },
-  xAxis: {
-    type: 'category',
-    data: [],
-    axisLabel: {
-      interval: 0,
-      rotate: 30,
-      fontSize: 10,
-      width: 100,
-      overflow: 'truncate'
-    }
-  },
-  yAxis: {
-    type: 'value',
-    splitLine: {
-      lineStyle: {
-        type: 'dashed'
-      }
-    }
-  },
-  series: [
-    {
-      name: '观看人数',
-      type: 'bar',
-      data: [],
-      itemStyle: {
-        color: '#409EFF'
-      }
-    },
-    {
-      name: '完播人数',
-      type: 'bar',
-      data: [],
-      itemStyle: {
-        color: '#67C23A'
-      }
-    },
-    {
-      name: '答题人数',
-      type: 'bar',
-      data: [],
-      itemStyle: {
-        color: '#E6A23C'
-      }
-    },
-    {
-      name: '正确人数',
-      type: 'bar',
-      data: [],
-      itemStyle: {
-        color: '#F56C6C'
-      }
-    }
-  ]
-}
-
-const lineChartOption = {
-  tooltip: {
-    trigger: 'axis',
-    axisPointer: {
-      type: 'cross' // 改为 'cross' 更适合折线图
-    }
-  },
-  grid: {
-    left: '3%',
-    right: '4%',
-    bottom: '8%', // 如果x轴标签旋转,可能需要更大的 bottom
-    top: '5%',    // 增加一点顶部空间给可能的 Y 轴名称
-    containLabel: true
-  },
-  xAxis: {
-    type: 'time', // X轴类型改为 'time'
-    // data: [], // 时间轴不需要单独设置 data,数据在 series 中提供
-    axisLabel: {
-      // interval: 0, // 时间轴通常自动处理间隔,可以先移除或注释掉
-      rotate: 30,   // 保留旋转,如果标签可能重叠
-      fontSize: 10,
-      // width: 100, // width 和 overflow 对于时间轴可能行为不同,按需调整
-      // overflow: 'truncate',
-      formatter: null // ECharts 会自动格式化时间,如需特定格式可用 function 或字符串模板
-    }
-  },
-  yAxis: {
-    type: 'value',
-    name: '金额 (元)', // 添加 Y 轴名称
-    nameLocation: 'end', // 名称位置
-    nameTextStyle: {
-      align: 'right',
-      padding: [0, 10, 0, 0] // 调整名称与轴线的距离
-    },
-    splitLine: {
-      lineStyle: {
-        type: 'dashed'
-      }
-    },
-    axisLabel: {
-      formatter: '{value} 元' // 可选:给 Y 轴刻度添加单位
-    }
-  },
-  series: [
-    {
-      name: '答题红包金额',
-      type: 'line', // 系列类型改为 'line'
-      data: [
-      ],
-      itemStyle: { // 控制数据点(标记)的样式
-        color: '#409EFF'
-      },
-      lineStyle: { // 控制线的样式
-        color: '#409EFF'
-      },
-      smooth: false, // 是否平滑曲线,可设为 true
-      symbol: 'circle', // 数据点标记形状,'emptyCircle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow', 'none'
-      symbolSize: 4   // 数据点标记大小
-    }
-  ]
-};
+// 异步加载组件
+const StatisticsDashboard = () => import('./components/index/statisticsDashboard')
+const WelcomePage = () => import('./components/index/welcomePage')
 
-
-const redPackageOption = {
-  tooltip: {
-    trigger: 'axis',
-    axisPointer: {
-      type: 'shadow'
-    }
-  },
-  grid: {
-    left: '3%',
-    right: '4%',
-    bottom: '8%',
-    top: '3%',
-    containLabel: true
-  },
-  xAxis: {
-    type: 'category',
-    data: [],
-    axisLabel: {
-      interval: 0,
-      rotate: 30,
-      fontSize: 10,
-      width: 100,
-      overflow: 'truncate'
-    }
-  },
-  yAxis: {
-    type: 'value',
-    splitLine: {
-      lineStyle: {
-        type: 'dashed'
-      }
-    }
-  },
-  series: [
-    {
-      name: '答题红包金额',
-      type: 'bar',
-      data: [],
-      itemStyle: {
-        color: '#409EFF'
-      }
-    }
-  ]
-}
 export default {
-  name: 'StatisticsDashboard',
-  components: {CountTo},
+  name: 'Index',
+  components: {
+    StatisticsDashboard,
+    WelcomePage
+  },
   data() {
     return {
-      deptInitOptions:[],
-      deptOptions:[],
-      intiDeptId:this.$store.state.user.user.deptId,
-      deptId:this.$store.state.user.user.deptId,
-      staticParam : {companyId:null,deptId:this.$store.state.user.user.deptId},
-      companyIntiOptions:[],
-      companyOptions:[],
-      companyId:null,
-      percentage: 0,
-      // 预测message
-      remainMessage: '',
-      // 当天使用流量
-      todayTraffic: 0,
-      trafficCount: 0,
-      // 当月使用流量
-      thisMonthTraffic: 0,
-      dataType: '0',
-      delerSort: 'DESC',
-      smsRemainCount: 0,
-      viewerType: '0',
-      viewerChart: null,
-      dealerChartNew: null,
-      userTypeText: process.env.VUE_APP_COURSE_DEFAULT==1?"会员":"企微",
-      userType: process.env.VUE_APP_COURSE_DEFAULT,
-      dealerChart: null,
-      // 分公司数量
-      dealderCount: 0,
-      // 销售数量
-      groupMgrCount: 0,
-      // 会员总数量
-      memberCount: 0,
-      // 企微数量
-      qwMemberNum: 0,
-      // pad使用情况
-      padTotalNum: 0,
-      // pad使用情况
-      padUsedNum: 0,
-      // 正常会员数量
-      normalNum: 0,
-      // 黑名单会员数量
-      blackNum: 0,
-      // 观看人数
-      watchUserCount: 0,
-      // 完播人数
-      completedUserCount: 0,
-      // 完播率
-      completedRate: 0,
-      // 观看次数
-      watchCount:0,
-      // 完播次数
-      completedCount: 0,
-      // 视频完播率
-      watchRate: 0,
-      // 答题人数
-      answerMemberCount: 0,
-      // 正确人数
-      correctUserCount: 0,
-      correctRate: 0.0,
-      // 答题红包个数
-      rewardCount: 0,
-      // 答题红包金额
-      rewardMoney: 0.0,
-      queryTime: '今日',
-      todayWatchUserCount: 0,
-      versionLimit: 0,
-      versionLimitPercent : 0.0,
-      /// 选中的分析概览
-      selectedDiv: 0,
-      filterType: 0,
-      answerRedPackViewerChart: null,
-      answerRedPackMoneyViewerChart: null,
-      todayComsumption: 0,
-      yesterdayComsumption: 0,
-      balance: 0,
-      runTianBalance: 0,
-      autoRefreshInterval: null,
-      // 今日新增用户数
-      todayIncreaseUserNum: 0,
-      // 订单总数
-      orderTotalNum: 0,
-      // 今日新增订单数
-      todayOrderNum: 0,
-      // 收款总数
-      recvTotalNum: 0,
-      // 今日收款总数
-      recvTodayNum: 0,
-      // 商品总数
-      goodsTotalNum: 0,
-      // 今日商品总数
-      todayGoodsNum: 0
+      hasDashboardPermission: false,
+      loading: true
     }
   },
-  mounted() {
-    this.$nextTick(() => {
-      this.initViewerChart();
-      this.initDealerChartNew();
-      this.initDealerChart();
-      this.initCourseWatchChart();
-      this.initAnswerRedPackViewerChart();
-      this.initAnswerRedPackMoneyViewerChart();
-      this.initThisMonthOrderChart();
-      this.initThisMonthRecvChart();
-
-
-      // 监听窗口大小变化,重新渲染图表
-      window.addEventListener('resize', () => {
-        this.viewerChart && this.viewerChart.resize()
-        this.dealerChart && this.dealerChart.resize()
-        this.dealerChartNew && this.dealerChartNew.resize()
-      })
-    })
-  },
   created() {
-    this.refresh();
-    listDept().then(res => {
-      this.deptInitOptions = res.data;
-      listCompany().then(res => {
-        this.companyIntiOptions = res.rows;
-        this.getDeptOptions(this.intiDeptId);
-        this.getCompanyOptions(this.intiDeptId);
-      });
-    });
+    this.checkDashboardPermission()
   },
   methods: {
-    getDeptOptions(deptId) {
-      const deptInitOptions = this.deptInitOptions;
-      // 部门本身节点
-      let deptNode = deptInitOptions.filter(item => item.deptId === deptId);
-
-      // 递归查找所有子节点
-      function findChildren(parentId) {
-        //部门的子部门
-        let deptChildren = deptInitOptions.filter(item => item.parentId === parentId);
-        //添加子部门
-        deptChildren.forEach(child => {
-          deptNode.push(child);
-          findChildren(child.deptId); // 递归查找子节点的子节点
-        });
-      }
-
-      // 从目标节点开始查找子节点
-      findChildren(deptId);
-      this.deptOptions = deptNode;
-    },
-    getCompanyOptions(deptId) {
-      this.companyId = null;
-      //修改选择后清空查询参数
-      this.staticParam.companyId = null;
-      this.staticParam.deptId = deptId;
-      const deptInitOptions = this.deptInitOptions;
-      const companyInitOptions = this.companyIntiOptions;
-      // 部门下的公司
-      let companyNode = companyInitOptions.filter(item => item.deptId === deptId);
+    checkDashboardPermission() {
 
-      // 递归查找所有子节点
-      function findChildren(parentId) {
-        //部门的子部门
-        let deptChildren = deptInitOptions.filter(item => item.parentId === parentId);
-        //添加子部门
-        deptChildren.forEach(child => {
-          //子部门下的销售公司
-          let companyChildren = companyInitOptions.filter(item => item.deptId === child.deptId);
-          companyChildren.forEach(companyChild => {
-            companyNode.push(companyChild);
-          })
-          findChildren(child.deptId); // 递归查找子节点的子节点
-        });
+      // 方式2: 检查用户权限
+      if (this.hasPermi(['his:index'])) {
+        this.hasDashboardPermission = true
       }
-
-      // 从目标节点开始查找子节点
-      findChildren(deptId);
-      this.companyOptions = companyNode;
-    },
-    //首页统计选择部门、销售公司
-    handleDeptChange() {
-      this.getCompanyOptions(this.deptId);
-      this.refresh();
-    },
-    handleCompanyChange() {
-      this.staticParam.companyId = this.companyId;
-      this.refresh();
-    },
-    handleUserType() {
-      if (this.userTypeText === '会员') {
-        this.userType = 1
-      } else {
-        this.userType = 2
+      // 方式3: 检查用户角色
+      else if (this.hasRole(['admin'])) {
+        this.hasDashboardPermission = true
       }
 
-      this.refresh()
+      this.loading = false
     },
-    /**
-     * 计算余额预计可持续的天数
-     * @param {number} balance - 当前账户余额
-     * @param {number} runTianBalance - 润天账户余额
-     * @param {number} todayConsumption - 今日消耗金额
-     * @param {number} yesterdayConsumption - 昨日消耗金额
-     * @return {Object} 包含天数和进度百分比的对象
-     */
-    calculateRemainingDays(balance, todayConsumption, yesterdayConsumption) {
-      // 如果今日和昨日消耗都为0,则无法预测(避免除以0)
-      if (todayConsumption === 0 && yesterdayConsumption === 0) {
-        return {
-          days: Infinity,
-          percentage: 0,
-          message: '暂无消耗数据'
-        };
-      }
-
-      // 计算每日平均消耗量
-      const avgDailyConsumption = (todayConsumption + yesterdayConsumption) / 2;
-
-      // 如果平均消耗为0,则无法预测
-      if (avgDailyConsumption === 0) {
-        return {
-          days: Infinity,
-          percentage: 0,
-          message: '暂无消耗数据'
-        };
-      }
-
-      // 计算剩余天数(向下取整)
-      const remainingDays = Math.floor(balance / avgDailyConsumption);
-
-      // 计算进度条百分比,最大为100
-      // 这里假设100天是满值,可以根据需要调整
-      const maxDays = 100;
-      const percentage = Math.min(100, Math.max(0, Math.round((remainingDays / maxDays) * 100)));
-
-      let message = '';
-      if (remainingDays > 365) {
-        message = '预测余额充足';
-      } else {
-        message = `预测不足${remainingDays}天`;
-      }
-
-      return {
-        days: remainingDays,
-        percentage: 100 - percentage,
-        message: message
-      };
-    },
-    /**
-     * 将字节数转换为合适的单位表示(Byte、KB、MB、GB、TB)
-     * @param {number} bytes - 字节数
-     * @param {number} [decimals=2] - 小数点后保留的位数
-     * @returns {string} 格式化后的字符串,包含数值和单位
-     */
-    formatBytes(bytes, decimals = 2) {
-      const isNegative = bytes < 0;  // 判断是否为负数
-      bytes = Math.abs(bytes);  // 获取绝对值
-
-      if (bytes === 0) return '0 Byte';
-
-      const k = 1024;
-      const sizes = ['Byte', 'KB', 'MB', 'GB', 'TB'];
-
-      // 计算合适的单位级别
-      let i = Math.floor(Math.log(bytes) / Math.log(k));
-
-      // 转换为对应单位的值
-      const value = bytes / Math.pow(k, i);
-
-
-      if(this.deptId !== 1 ||  this.companyId !== null){
-        i += 1;
-      }
-      // 格式化为指定小数位的字符串
-      const result = parseFloat(value.toFixed(decimals)) + ' ' + sizes[Math.min(i, sizes.length - 1)];
-
-      // 如果是负数,返回带负号的值
-      return isNegative ? `-${result}` : result;
-    },
-    // 手动刷新
-    manualRefresh() {
-      this.refresh();
-    },
-    // 处理自动刷新选项
-    handleAutoRefresh(command) {
-      // 清除之前的定时器
-      if (this.timer) {
-        clearInterval(this.timer);
-        this.timer = null;
-      }
-
-      // 设置新的刷新间隔
-      this.autoRefreshInterval = parseInt(command);
-
-      // 如果间隔大于0,设置新的定时器
-      if (this.autoRefreshInterval > 0) {
-        this.timer = setInterval(() => {
-          this.refresh();
-        }, this.autoRefreshInterval * 60 * 1000); // 转换为毫秒
-
-        this.$message.success(`已设置${this.autoRefreshInterval}分钟自动刷新`);
-      } else {
-        this.$message.info('已关闭自动刷新');
-      }
-    },
-    refresh() {
-      rechargeComsumption(this.staticParam).then(res => {
-        console.log(res);
-        if (res.code === 200) {
-          this.balance = res.data.balance;
-          this.runTianBalance = res.data.runTianBalance;
-          this.todayComsumption = res.data.todayComsumption;
-          this.yesterdayComsumption = res.data.yesterdayComsumption;
-          let calculateRemainingDays1 = this.calculateRemainingDays(this.balance, this.todayComsumption, this.yesterdayComsumption);
-          this.percentage = calculateRemainingDays1.percentage;
-          this.remainMessage = calculateRemainingDays1.message;
-        }
-      });
-
-      trafficLog(this.staticParam).then(res => {
-        if (res.code === 200) {
-          this.todayTraffic = res.data.today;
-          this.thisMonthTraffic = res.data.thisMonth;
-          this.trafficCount = res.data.traffic;
-        }
-      })
-
-      dealerAggregated(this.staticParam).then(res => {
-        if (res.code === 200) {
-          this.dealderCount = res.data.dealderCount ?? 0;
-          this.groupMgrCount = res.data.groupMgrCount ?? 0;
-          this.memberCount = res.data.memberCount ?? 0;
-          this.qwMemberNum = res.data.qwMemberNum ?? 0;
-          const totalNum = res.data.padTotalNum;
-          //-1 不限 null 未设置
-          if(totalNum != null && totalNum !== -1 && totalNum > 0){
-            this.padTotalNum = totalNum;
-          }else{
-            this.padTotalNum = '不限';
-          }
-          this.padUsedNum = res.data.padUsedNum ?? 0;
-          this.padInfo = res.data.padInfo;
-          this.normalNum = res.data.normalNum ?? 0;
-          this.blackNum = res.data.blackNum ?? 0;
-          this.todayIncreaseUserNum = res.data.todayIncreaseUserNum ?? 0;
-          this.orderTotalNum = res.data.orderTotalNum ?? 0;
-          this.todayOrderNum = res.data.todayOrderNum ?? 0;
-          this.recvTotalNum = res.data.recvTotalNum ?? 0;
-          this.recvTodayNum = res.data.recvTodayNum ?? 0;
-          this.goodsTotalNum = res.data.goodsTotalNum ?? 0;
-          this.todayGoodsNum = res.data.todayGoodsNum ?? 0;
-        }
-      })
-      let param = this.getParam();
 
-      // 获取当前日期时间
-      const today = dayjs();
-      param.startTime = this.formatDate(today);
-      param.endTime = this.formatDate(today);
-      analysisPreview(param).then(res => {
-        if (res.code === 200) {
-          this.watchUserCount = res.data.watchUserCount;
-          this.completedUserCount = res.data.completedUserCount;
-          this.completedRate = res.data.completedRate;
-          this.watchCount = res.data.watchCount;
-          this.completedCount = res.data.completedCount;
-          this.answerMemberCount = res.data.answerMemberCount;
-          this.correctUserCount = res.data.correctUserCount;
-          this.correctRate = res.data.correctRate;
-          this.rewardCount = res.data.rewardCount;
-          this.rewardMoney = res.data.rewardMoney;
-          this.watchRate = res.data.watchRate;
-        }
-      })
-      smsBalance(this.staticParam).then(res => {
-        if (res.code === 200) {
-          if (res.data == null) {
-            this.smsRemainCount = 0;
-          } else {
-            this.smsRemainCount = res.data;
-          }
-        }
-      })
-      authorizationInfo(this.staticParam).then(res => {
-        if (res.code === 200 && res.data != null) {
-          this.todayWatchUserCount = res.data.todayWatchUserCount;
-          this.versionLimit = res.data.versionLimit;
-          if(this.versionLimit){
-            this.versionLimitPercent = this.todayWatchUserCount/this.versionLimit;
-          }
-        }
-      })
-
-      this.handleCourseWatchChart()
-      this.handleViewChartData()
-      this.handleDealerChartDataNew()
-
-      // 经销商会员观看TOP10
-      this.handleDealerChartData()
-
-      this.handleAnswerRedPackViewerChart()
-
-      this.handleAnswerRedPackMoneyViewerChart()
-
-      this.handleThisMonthRecvCount();
-      this.handleThisMonthOrderCount();
-
-    },
-    /**
-     * 将数字添加千位分隔符
-     * @param {number|string} num - 需要格式化的数字
-     * @return {string} 添加千位分隔符后的字符串
-     */
-    formatNumberWithCommas(num) {
-      if (num === null || num === undefined || isNaN(Number(num))) {
-        return '0';
-      }
-
-      const numStr = String(num);
-
-      // 处理负数
-      const isNegative = numStr.startsWith('-');
-      const absNumStr = isNegative ? numStr.slice(1) : numStr;
-
-      // 分离整数部分和小数部分
-      const parts = absNumStr.split('.');
-      const integerPart = parts[0];
-      const decimalPart = parts.length > 1 ? '.' + parts[1] : '';
-
-      const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
-
-      return (isNegative ? '-' : '') + formattedInteger + decimalPart;
-    },
-    handleToggleDiv(selected) {
-      this.selectedDiv = selected;
-
-      if (selected === 1) {
-        this.$nextTick(() => {
-          if (this.courseWatchChart) {
-            this.courseWatchChart.resize();
-          } else {
-          }
-        });
-      } else if (selected === 0) {
-        this.$nextTick(() => {
-          if (this.viewerChart) this.viewerChart.resize();
-          if (this.dealerChart) this.dealerChart.resize();
-        });
-      } else if (selected === 2) {
-        this.$nextTick(() => {
-          if (this.answerRedPackViewerChart) this.answerRedPackViewerChart.resize();
-          if (this.answerRedPackMoneyViewerChart) this.answerRedPackMoneyViewerChart.resize();
-        });
-      }
-      if (this.selectedDiv === 0) {
-        this.handleViewChartData()
-        this.handleDealerChartData()
-        this.handleDealerChartDataNew()
-      } else if (this.selectedDiv === 1) {
-        this.handleCourseWatchChart()
-      } else if (this.selectedDiv === 2) {
-        this.handleAnswerRedPackViewerChart()
-        this.handleAnswerRedPackMoneyViewerChart()
-      }
-    },
-    formatDate(date) {
-      return dayjs(date).format('YYYY-MM-DD');
-    },
-
-    getParam() {
-      let param = {
-        startTime: '',
-        endTime: '',
-        userType: this.userType,
-        companyId: this.companyId,
-        deptId: this.deptId
-      };
-      // 获取当前日期时间
-      const today = dayjs();
-
-      let type = 0;
-      if (this.queryTime === '今日') {
-        param.startTime = this.formatDate(today);
-        param.endTime = this.formatDate(today);
-        type = 0;
-      } else if (this.queryTime === '昨日') {
-        const yesterday = today.subtract(1, 'day');
-        param.startTime = this.formatDate(yesterday);
-        param.endTime = this.formatDate(yesterday);
-        type = 1;
-      } else if (this.queryTime === '本周') {
-        param.startTime = this.formatDate(today.startOf('week'));
-        param.endTime = this.formatDate(today.endOf('week'));
-        type = 2;
-      } else if (this.queryTime === '本月') {
-        param.startTime = this.formatDate(today.startOf('month'));
-        param.endTime = this.formatDate(today.endOf('month'));
-        type = 3;
-      } else if (this.queryTime === '上月') {
-        const lastMonth = today.subtract(1, 'month');
-        param.startTime = this.formatDate(lastMonth.startOf('month'));
-        param.endTime = this.formatDate(lastMonth.endOf('month'));
-        type = 4;
-      } else {
-        console.warn(`未知的 queryTime: ${this.queryTime}, 默认使用今日`);
-        param.startTime = this.formatDate(today);
-        param.endTime = this.formatDate(today);
-      }
-      param.type = type;
-      param.sort = this.delerSort;
-      return param;
-    },
-    // 分析概览
-    handleAnalysis(e) {
-
-      let param = this.getParam();
-      analysisPreview(param).then(res => {
-        if (res.code === 200) {
-          this.watchUserCount = res.data.watchUserCount;
-          this.completedUserCount = res.data.completedUserCount;
-          this.completedRate = res.data.completedRate;
-          this.watchCount = res.data.watchCount;
-          this.completedCount = res.data.completedCount;
-          this.answerMemberCount = res.data.answerMemberCount;
-          this.correctUserCount = res.data.correctUserCount;
-          this.correctRate = res.data.correctRate;
-          this.rewardCount = res.data.rewardCount;
-          this.rewardMoney = res.data.rewardMoney;
-          this.watchRate = res.data.watchRate;
-        }
-      })
-
-      if (this.selectedDiv === 0) {
-        this.handleViewChartData()
-        this.handleDealerChartData()
-        this.handleDealerChartDataNew()
-      } else if (this.selectedDiv === 1) {
-        this.handleCourseWatchChart()
-      } else if (this.selectedDiv === 2) {
-        this.handleAnswerRedPackViewerChart()
-        this.handleAnswerRedPackMoneyViewerChart()
-      }
-    },
-    handleAnswerRedPackViewerChart() {
-      let param = this.getParam();
-      param = { ...param, statisticalType: this.viewerType, dataType: this.dataType };
-      rewardMoneyTopTen(param).then(res => {
-        if (res.code === 200) {
-          let data = res.data;
-          let companyNameList = data.map(e => e.companyName)
-          let courseNameList = data.map(e => e.courseName)
-          let rewardMoneyList = data.map(e => e.rewardMoney)
-          if (this.dataType === '0') {
-            redPackageOption.xAxis.data = companyNameList;
-          } else {
-            redPackageOption.xAxis.data = courseNameList;
-          }
-          redPackageOption.series[0].data = rewardMoneyList;
-
-          this.answerRedPackViewerChart.setOption(redPackageOption)
-        }
-      })
-    },
-    handleAnswerRedPackMoneyViewerChart() {
-      let param = this.getParam();
-      param = { ...param, statisticalType: this.viewerType, dataType: this.dataType };
-      rewardMoneyTrend(param).then(res => {
-        if (res.code === 200) {
-          let data = res.data;
-          let option = data.map(e => [e.x, e.rewardMoney])
-          lineChartOption.series[0].data = option;
-
-          this.answerRedPackMoneyViewerChart.setOption(lineChartOption)
-        }
-      })
-    },
-    handleCourseWatchChart() {
-      let param = this.getParam();
-      param = { ...param, statisticalType: this.viewerType };
-      watchCourseTopTen(param).then(res => {
-        if (res.code === 200) {
-          let data = res.data;
-          let watchUserCountList = data.map(e => e.watchUserCount);
-          let completedUserCountList = data.map(e => e.completedUserCount);
-          let answerUserCountList = data.map(e => e.answerUserCount);
-          let correctUserCountList = data.map(e => e.correctUserCount);
-          let courseNameList = data.map(e => e.courseName);
-          courseWatchOption.xAxis.data = courseNameList;
-          courseWatchOption.series[0].data = watchUserCountList;
-          courseWatchOption.series[1].data = completedUserCountList;
-          courseWatchOption.series[2].data = answerUserCountList;
-          courseWatchOption.series[3].data = correctUserCountList;
-          this.courseWatchChart.setOption(courseWatchOption)
-        }
+    // 使用若依的权限检查方法
+    hasPermi(permissions) {
+      return this.$store.state.user.permissions.some(permission => {
+        return permissions.includes(permission)
       })
     },
-    handleDealerChartData() {
-      let param = this.getParam();
-
-      // 经销商会员观看TOP10
-      deaMemberTopTen({ ...param, statisticalType: this.viewerType }).then(res => {
-        if (res.code === 200) {
-          let data = res.data;
-          let companyNameList = data.map(e => e.companyName);
-          let watchUserList = data.map(e => e.watchUserCount);
-          dealerOption.yAxis.data = companyNameList;
-          dealerOption.series[0].data = watchUserList;
 
-          this.dealerChart.setOption(dealerOption)
-        }
+    // 使用若依的角色检查方法
+    hasRole(roles) {
+      return this.$store.state.user.roles.some(role => {
+        return roles.includes(role)
       })
-
-    },
-    handleThisMonthOrderCount() {
-      thisMonthOrderCount(this.staticParam).then(res => {
-        if (res.code === 200) {
-          let dates = res.dates;
-          let orderCount = res.orderCount;
-          let payPrice = res.payPrice;
-
-          thisMonthOrderCountOption.series[0].data = orderCount;
-          thisMonthOrderCountOption.series[1].data = payPrice;
-          thisMonthOrderCountOption.xAxis.data = dates;
-
-          this.thisMonthOrderChart.setOption(thisMonthOrderCountOption)
-        }
-      })
-    },
-    handleThisMonthRecvCount() {
-      thisMonthRecvCount(this.staticParam).then(res => {
-        if (res.code === 200) {
-          let dates = res.dates;
-          let orderCount = res.orderCount;
-          let payMoney = res.payMoney;
-
-          thisMonthRecvCountOption.series[0].data = orderCount;
-          thisMonthRecvCountOption.series[1].data = payMoney;
-          thisMonthRecvCountOption.xAxis.data = dates;
-          this.thisMonthRecvChart.setOption(thisMonthRecvCountOption)
-        }
-      })
-    },
-    handleViewChartData() {
-      let param = this.getParam();
-
-      watchEndPlayTrend({ ...param }).then(res => {
-        if (res.code === 200) {
-          let data = res.data;
-          let watchUserCountList = data.map(e => e.watchUserCount);
-          let completedUserCountList = data.map(e => e.completedUserCount);
-          let xAxis = data.map(e => e.x);
-          viewCharOption.series[0].data = watchUserCountList;
-          viewCharOption.series[1].data = completedUserCountList;
-          viewCharOption.xAxis.data = xAxis;
-
-          this.viewerChart.setOption(viewCharOption);
-        }
-      })
-
-    },
-    handleDealerChartDataNew() {
-      let param = this.getParam();
-
-      getWatchCourseStatisticsData({ ...param }).then(res => {
-        if (res.code === 200) {
-          console.log(res.data);
-          // 根据实际数据结构调整
-          let data = res.data;
-          let watchUserCountList = data.map(e => e.watchCount);     // 观看次数
-          let completedUserCountList = data.map(e => e.finishCount); // 完播次数
-          let xAxis = data.map(e => e.companyName);                 // X轴使用公司名称
-
-          // 更新图表配置
-          dealerOptionNew.series[0].data = watchUserCountList;
-          dealerOptionNew.series[1].data = completedUserCountList;
-          dealerOptionNew.xAxis.data = xAxis;
-
-          this.dealerChartNew.setOption(dealerOptionNew);
-
-        }
-      })
-
-    },
-    initThisMonthOrderChart() {
-      this.thisMonthOrderChart = echarts.init(this.$refs.viewerOrderChart)
-      this.thisMonthOrderChart.setOption(thisMonthOrderCountOption)
-    },
-    initThisMonthRecvChart() {
-
-      this.thisMonthRecvChart = echarts.init(this.$refs.viewerReceiveChart)
-      this.thisMonthRecvChart.setOption(thisMonthOrderCountOption)
-    },
-    initViewerChart() {
-      this.viewerChart = echarts.init(this.$refs.viewerChart)
-      this.viewerChart.setOption(viewCharOption)
-    },
-    initDealerChartNew() {
-      this.dealerChartNew = echarts.init(this.$refs.dealerChartNew)
-      this.dealerChartNew.setOption(dealerOptionNew)
-    },
-    initDealerChart() {
-      this.dealerChart = echarts.init(this.$refs.dealerChart)
-
-      this.dealerChart.setOption(dealerOption)
-    },
-    initCourseWatchChart() {
-      this.courseWatchChart = echarts.init(this.$refs.courseWatchChart)
-
-      this.courseWatchChart.setOption(courseWatchOption)
-    },
-    initAnswerRedPackViewerChart() {
-      this.answerRedPackViewerChart = echarts.init(this.$refs.answerRedPackViewerChart)
-
-      this.answerRedPackViewerChart.setOption(redPackageOption)
-    },
-    initAnswerRedPackMoneyViewerChart() {
-      this.answerRedPackMoneyViewerChart = echarts.init(this.$refs.answerRedPackMoneyViewerChart)
-
-      this.answerRedPackMoneyViewerChart.setOption(lineChartOption)
     }
-  },
-
-  beforeDestroy() {
-    // 组件销毁时清除定时器
-    if (this.timer) {
-      clearInterval(this.timer);
-      this.timer = null;
-    }
-    // window.removeEventListener('resize', this.resizeHandler)
-    this.viewerChart && this.viewerChart.dispose()
-    this.dealerChart && this.dealerChart.dispose()
-    this.dealerChartNew && this.dealerChartNew.dispose()
   }
 }
 </script>
 
 <style scoped>
-.highlight-today-add {
-  color: green;
-  font-size: 17px;
-  font-weight: normal;
-}
-
-.highlight-today-add2 {
-  color: rgba(49, 185, 154, 1);
-  font-size: 14px;
-  font-weight: normal;
-  transform: scale(.9);
-}
-
-.action-group .el-button + .el-button,
-.action-group .el-dropdown {
-  margin-left: 10px;
-}
-
-.is-active {
-  color: #409EFF;
-  font-weight: bold;
-}
-
-::v-deep .el-radio-button__inner:hover {
-  color: #409EFF;
-  /* 鼠标悬浮时的文字颜色,可以根据需要调整 */
+.app-container {
+  min-height: calc(100vh - 84px);
 }
 
-::v-deep .el-radio-button.is-active .el-radio-button__inner {
-  background-color: #409EFF;
-  /* 选中时的背景色 */
-  border-color: #409EFF;
-  /* 选中时的边框色 */
-  color: #FFFFFF;
-  /* 选中时的文字颜色 (通常是白色) */
-  box-shadow: -1px 0 0 0 #409EFF;
-  /* 处理按钮间的连接缝隙 */
-}
-
-/* 如果需要,也可以修改非选中状态下的聚焦(focus)或悬浮(hover)样式 */
-/* 例如,让非选中按钮悬浮时边框和文字也变蓝 */
-::v-deep .el-radio-button:not(.is-active) .el-radio-button__inner:hover {
-  color: #409EFF;
-  /* border-color: #b3d8ff;  Element UI 默认悬浮边框色,可以按需修改 */
-}
-
-/* 聚焦时的外框,如果需要的话 */
-::v-deep .el-radio-button:focus:not(.is-checked) .el-radio-button__inner {
-  /* border-color: #409EFF; */
-  /* Element UI 默认的 focus 颜色通常关联主题色 */
-  /* box-shadow: 0 0 2px 2px rgba(64, 158, 255, 0.2); */
-  /* 示例 focus 光晕 */
-}
-
-.statistics-dashboard {
+.loading-container {
   padding: 20px;
-  background-color: #f5f7fa;
-}
-
-.overview-section,
-.analysis-section {
-  margin-bottom: 20px;
-  border-radius: 4px;
-}
-
-.header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  font-size: 16px;
-  font-weight: 500;
-}
-
-.data-card {
-  background-color: #fff;
-  border-radius: 4px;
-  padding: 15px;
-  height: 120px;
-  display: flex;
-  flex-direction: column;
-  position: relative;
-  transition: background-color 0.3s ease-in-out;
-}
-
-.data-card:hover {
-  border: 1px solid #4592ff;
-  background-color: #e7f1ff;
-}
-
-.card-title {
-  color: #606266;
-  font-size: 14px;
-  margin-bottom: 10px;
-}
-
-.card-title1 {
-  color: white;
-  font-size: 14px;
-  margin-bottom: 10px;
-}
-
-.card-value {
-  font-size: 24px;
-  font-weight: bold;
-  margin-top: 20px;
-}
-
-.highlight {
-  color: #409EFF;
-}
-
-.card-sub {
-  display: flex;
-  justify-content: space-between;
-  font-size: 12px;
-  color: #909399;
-  margin-top: 5px;
-}
-
-.card-desc {
-  font-size: 12px;
-  color: #909399;
-  margin-top: 5px;
-}
-
-.card-badge {
-  position: absolute;
-  top: 15px;
-  right: 15px;
-  background: #f0f9eb;
-  color: #67c23a;
-  padding: 2px 5px;
-  border-radius: 4px;
-}
-
-.cdn-label {
-  background-color: #409EFF;
-  color: white;
-  padding: 2px 5px;
-  border-radius: 4px;
-  margin-right: 5px;
-  font-size: 12px;
-}
-
-.tab-group {
-  display: flex;
-  gap: 10px;
-}
-
-.action-group {
-  display: flex;
-  gap: 10px;
-}
-
-.analysis-card {
-  border-radius: 4px;
-  padding: 20px;
-  display: flex;
-  align-items: center;
-}
-
-.card-icon {
-  width: 50px;
-  height: 50px;
-  background-color: rgba(64, 158, 255, 0.1);
-  border-radius: 8px;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  font-size: 24px;
-  color: #409EFF;
-  margin-right: 20px;
-}
-
-.card-content {
-  display: flex;
-}
-
-.card-row {
-  display: flex;
-  justify-content: center;
-  justify-items: center;
-  flex-direction: column;
-  padding: 10px;
-
-  .highlight {
-    text-align: center;
-    margin-top: 1em;
-
-    font-family: BebasNeue;
-    color: #1677ff;
-    font-size: 21px;
-    line-height: 42px;
-    font-weight: 600;
-    margin-top: 8px;
-  }
-
-  font-size: 15px;
-  color: #000;
-
-}
-
-.charts-section {
-  margin-top: 20px;
-}
-
-.chart-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.view-more {
-  font-size: 12px;
-}
-
-.legend {
-  display: flex;
-  gap: 15px;
-}
-
-.legend-item {
-  display: flex;
-  align-items: center;
-  font-size: 12px;
-}
-
-.dot {
-  width: 10px;
-  height: 10px;
-  border-radius: 50%;
-  margin-right: 5px;
-}
-
-.viewer-dot {
-  background-color: #409EFF;
-}
-
-.complete-dot {
-  background-color: #67C23A;
-}
-
-.chart-container {
-  height: 350px;
-  width: 100%;
-}
-
-.analysis-card-check {
-  display: flex;
-  flex-direction: row;
-  border: 1px solid transparent;
-  background-color: #fff;
-  border-radius: 4px;
-}
-
-.analysis-card-check:hover {
-  cursor: pointer;
-}
-
-.analysis-card-check-selected:after {
-  content: "";
-  display: block;
-  border-width: 15px;
-  position: absolute;
-  bottom: -30px;
-  left: 50%;
-  margin-left: -32px;
-  border-style: solid dashed dashed solid;
-  border-color: #4592FF transparent transparent transparent;
-  font-size: 0;
-  line-height: 0;
-  z-index: 1;
-}
-
-.analysis-card-check-selected:before {
-  content: "";
-  display: block;
-  border-width: 15px;
-  position: absolute;
-  bottom: -30px;
-  left: 50%;
-  margin-left: -32px;
-  border-style: solid dashed dashed solid;
-  border-color: #4592FF transparent transparent transparent;
-  font-size: 0;
-  line-height: 0;
-  z-index: 1;
-}
-
-.analysis-card-check-selected {
-  border: 1px solid #4592FF;
-  background-color: #e7f1ff;
-}
-
-.color {
-  position: relative;
-  border: 1px solid #4592FF;
-  background-color: #e7f1ff;
-}
-
-.color:after {
-  bottom: -27px;
-  border-color: #E7F1FF transparent transparent transparent;
-}
-
-.companybox {
-  color: white;
-  background-color: #006CFF;
-  padding: 10px 10px 40px 10px;
-  box-sizing: border-box;
-  position: relative;
-  border-radius: 6px;
-
-  .topimg {
-    width: 100px;
-    height: 80px;
-    position: absolute;
-    top: 0px;
-    left: 0;
-  }
-
-  .bottomimg {
-    width: 100px;
-    height: 80px;
-    position: absolute;
-    bottom: -10px;
-    right: 0;
-    transform: rotate(180deg);
-  }
-
-  .companyboxtitle {
-    height: 30px;
-    margin-bottom: 20px;
-    font-weight: 600;
-  }
-
-  .companyflex {
-    display: flex;
-    justify-content: space-around;
-  }
-}
-
-
-.companynumber {
-  color: white;
-}
-
-.companycard {
-
-  width: 25%;
-}
-
-.companyadd {
-  color: white;
-}
-
-.cardafter {
-  position: relative;
-
-}
-
-.cardafter::after {
-  content: "";
-  height: 60px;
-  border-right: 1px solid rgba(255, 255, 255, 0.20);
-  position: absolute;
-  right: 30px;
-  top: 0px;
-}
-
-.highlight1 {
-  margin-top: 10px;
-  margin-left: 20px;
-}
-
-
-.propertyboxtitle {
-  background-image: url(../assets/images/zcgl_bg.png);
-  height: 100px;
-}
-
-.propertyboxflex {
-  display: flex;
-  background-color: white;
-  justify-content: space-between;
-}
-
-.property-card {
-  width: 48%;
-  border-radius: 4px;
-  padding: 15px;
-  height: 100px;
-  display: flex;
-  flex-direction: column;
-  position: relative;
-  transition: background-color 0.3s ease-in-out;
-
-}
-
-.property_title {
-  height: 40px;
-  line-height: 40px;
-  color: rgba(32, 33, 36, 1);
-  box-sizing: border-box;
-  padding-left: 10px;
-  font-weight: 600;
-}
-
-.card-compare {
-  margin-top: 5px;
-  font-size: 14px;
-  color: rgba(92, 95, 102, 1);
-
-  span {
-    font-size: 13px;
-    transform: scale(.8);
-    color: rgba(49, 185, 154, 1);
-  }
-}
-
-.propertyline {
-  position: relative;
-}
-
-.propertyline::after {
-  position: absolute;
-  content: "";
-  height: 80px;
-  border-right: 1px solid rgba(237, 239, 242, 1);
-  right: 0;
-}
-
-.operatetitle {
-  font-weight: 600;
-  height: 50px;
-  line-height: 50px;
-}
-
-.operatetitle-col {
-  display: flex;
-  justify-content: space-between;
-  padding-bottom: 20px;
-  padding-right: 5px;
-
-  .operatetitle-card {
-    width: 24%;
-    border: 1px solid transparent;
-    background-color: rgba(245, 247, 250, 1);
-    border-radius: 4px;
-    padding: 15px;
-    display: flex;
-    flex-direction: column;
-    position: relative;
-    transition: background-color 0.3s ease-in-out;
-
-    .operate-value {
-      font-size: 24px;
-      font-weight: bold;
-    }
-  }
-}
-
-.yesterdaybox {
-  font-size: 14px;
-  color: rgba(92, 95, 102, 1);
-  font-weight: 200;
-  margin-top: 10px;
-}
-
-.internetbox {
-  background: linear-gradient(to right, rgba(255, 99, 0, 1), rgba(255, 159, 1, 1));
-  border-radius: 6px;
-  padding: 2px 5px 15px 5px;
-  width: 100%;
-
-  .internet-cardtop {
-    background-color: white;
-    border-radius: 3px;
-    margin-top: 5px;
-    justify-content: space-between;
-    padding: 15px;
-    box-sizing: border-box;
-    color: rgba(32, 33, 36, 1);
-
-    .cardinnerbox {
-      display: flex;
-      justify-content: space-between;
-
-      .cardtopimg {
-        display: flex;
-        align-items: center;
-        font-size: 15px;
-
-        img {
-          height: 18px;
-          width: 18px;
-        }
-      }
-
-      .cardtopnumber {
-        font-size: 25px;
-        color: rgba(32, 33, 36, 1);
-        font-weight: bold;
-      }
-
-    }
-
-    .cardinnerbox2 {
-      display: flex;
-      justify-content: space-between;
-      font-size: 14px;
-      color: rgba(92, 95, 102, 1);
-
-
-    }
-
-  }
-
-  .internetbox-messge {
-    color: white;
-    display: flex;
-    justify-content: space-between;
-    padding: 15px 10px 10px 10px;
-
-    .internet-card {
-      display: flex;
-      font-size: 14px;
-      align-items: center;
-
-      img {
-        height: 18px;
-        width: 18px;
-      }
-
-      span {
-        padding-left: 5px;
-      }
-    }
-
-    .internet-number {
-      font-size: 25px;
-
-    }
-  }
-
-  .internetbox {
-    display: flex;
-    color: white;
-
-    .internet-card {
-      width: 100%;
-      display: flex;
-      color: white;
-
-    }
-  }
-
-  .internet-title {
-    font-size: 14px;
-  }
-
-}
-
-.company {
-  background-color: #006CFF;
-}
-
-.highlight-red {
-  text-align: center;
-  margin-top: 1em;
-  font-family: BebasNeue;
-  color: rgba(255, 82, 82, 1);
-  font-size: 21px;
-  line-height: 42px;
-  font-weight: 600;
-  margin-top: 8px;
-}
-
-.highlight-black {
-  text-align: center;
-  margin-top: 1em;
-  font-family: BebasNeue;
-  color: rgba(32, 33, 36, 1);
-  font-size: 21px;
-  line-height: 42px;
-  font-weight: 600;
-  margin-top: 8px;
-
-}
-
-.operatetitle-card:hover {
-  border: 1px solid #4592ff;
-  background-color: #e7f1ff;
-}
-
-.icon-img {
-  height: 14px;
-  width: 14px;
-}
-
-.progress {
-  transform: rotate(180deg);
-  margin-top: 20px;
-}
-
-.progress ::v-deep .el-progress-bar__outer {
-  background-color: rgba(247, 152, 11, 0.2);
-}
-
-::v-deep .el-progress {
-
-  .el-progress-bar {
-    .el-progress-bar__inner {
-      background: linear-gradient(to right, #FF6300, #FF9F01)
-    }
-  }
 }
 </style>

+ 38 - 1
src/views/live/liveConsole/LiveConsole.vue

@@ -137,6 +137,7 @@
                     <a style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click="blockUser(m)">拉黑</a>
                     <a v-if="m.singleVisible === 1" style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click="singleVisible(m)">解除用户自见</a>
                     <a v-else style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click="singleVisible(m)">用户自见</a>
+                    <a style="cursor: pointer;color: #ff0000;padding: 8px 8px 0 0;font-size: 12px;" @click="deleteMsg(m)">删除</a>
                   </el-col>
                 </el-row>
               </el-col>
@@ -249,7 +250,7 @@
 <script>
 import LivePlayer from './LivePlayer.vue';
 import {blockUser, changeUserStatus, getLiveUserTotals, dashBoardWatchUserList} from '@/api/live/liveWatchUser'
-import { listLiveSingleMsg } from '@/api/live/liveMsg'
+import { listLiveSingleMsg,delLiveMsg } from '@/api/live/liveMsg'
 import { getLive } from '@/api/live/live'
 import { consoleList } from '@/api/live/task'
 import ScreenScale from './ScreenScale.vue'; // 路径根据实际位置调整
@@ -445,6 +446,42 @@ export default {
       }
       this.socket.send(JSON.stringify(msg))
     },
+    deleteMsg(m){
+      // 1. 弹出确认对话框
+      this.$confirm('此操作将永久删除该消息, 是否继续?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        delLiveMsg(m.msgId).then(res => {
+          if (res.code === 200) {
+            const index = this.msgList.findIndex(item => item.msgId === m.msgId);
+            if (index !== -1) {
+              this.msgList.splice(index, 1);
+              console.log(`消息 ${m.msgId} 已在本地删除。`);
+            }
+            let msg = {
+              liveId: this.liveId,
+              userId: m.userId,
+              msg: m.msgId, // 关键:将消息ID发送给后台
+              cmd: 'deleteMsg',
+            };
+            this.socket.send(JSON.stringify(msg));
+            // 可以在这里给用户一个删除成功的提示
+            this.$message({
+              type: 'success',
+              message: '消息删除成功!'
+            });
+          }
+        })
+      }).catch(() => {
+        // 3. 用户点击“取消”或关闭对话框后的回调
+        this.$message({
+          type: 'info',
+          message: '已取消删除'
+        });
+      });
+    },
     globalVisibleChange( val){
       // 消息自可见
       let msg = {

+ 16 - 2
src/views/live/liveOrder/index.vue

@@ -45,6 +45,16 @@
         />
       </el-form-item>
 
+      <el-form-item label="收货人姓名" prop="userName">
+        <el-input
+          v-model="queryParams.userName"
+          placeholder="请输入收货人姓名"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
       <el-form-item label="商品规格" prop="productSpec">
         <el-input
           v-model="queryParams.productSpec"
@@ -183,7 +193,7 @@
           <span v-else>-</span>
         </template>
       </el-table-column>
-      <el-table-column label="绑定销售昵称" align="center" prop="companyUserName" />
+      <el-table-column label="绑定销售昵称" align="center" prop="companyUserNickName" />
       <el-table-column label="客户编码" align="center" prop="userId" />
       <el-table-column label="会员等级" align="center" prop="userLevel">
       </el-table-column>
@@ -196,7 +206,8 @@
       <el-table-column label="客户ID" align="center" prop="userId" />
       <el-table-column label="客户昵称" align="center" prop="nickName" />
       <el-table-column label="客户绑定手机号" align="center" prop="userBindPhone" />
-      <el-table-column label="收货手机号" align="center" prop="userPhone" />
+      <el-table-column label="收货人电话" align="center" prop="userPhone" />
+      <el-table-column label="收货人姓名" align="center" prop="userName" />
       <el-table-column label="累计成交笔数" align="center" prop="totalOrderCount" />
       <el-table-column label="累计成交总额" align="center" prop="totalOrderAmount" />
       <el-table-column label="最新绑定时间" align="center" prop="latestBindTime" width="180">
@@ -218,6 +229,9 @@
       <el-table-column label="销售价格" align="center" prop="totalPrice" />
       <el-table-column label="成本价格" align="center" prop="costPrice" v-if="showFinanceTableField"/>
       <el-table-column label="结算价格" align="center" prop="fprice"  v-if="showFinanceTableField"/>
+      <el-table-column label="额外运费" align="center" prop="payDelivery" v-if="showFinanceTableField"/>
+      <el-table-column label="商品编码" align="center" prop="barCode"  v-if="showFinanceTableField"/>
+      <el-table-column label="商品分类" align="center" prop="cateName" v-if="showFinanceTableField"/>
       <el-table-column label="成交价" align="center" prop="payMoney"/>
       <el-table-column label="收货地址" align="center" prop="userAddress" width="200" />
       <el-table-column label="对应供应商" align="center" prop="supplierName" width="120" />

+ 1 - 1
src/views/live/liveOrder/liveOrderDetails.vue

@@ -6,7 +6,7 @@
     <div class="contentx" v-if="item!=null">
       <div class="desct"></div>
       <div class="order-status" v-if="item!=null" >
-        <el-steps  :active="item.status==3?item.status+1:item.status" align-center>
+        <el-steps  :active="item.status+1" align-center>
           <el-step title="待支付"></el-step>
           <el-step title="待发货"></el-step>
           <el-step title="待收货"></el-step>

+ 1388 - 0
src/views/qw/applyIpad/index.vue

@@ -0,0 +1,1388 @@
+<template>
+  <div class="app-container">
+    <!-- 数据统计卡片 -->
+    <div class="statistics-cards">
+      <el-row :gutter="20">
+        <el-col :span="6">
+          <el-card class="stat-card" shadow="hover">
+            <div class="stat-content">
+              <div class="stat-icon pending">
+                <i class="el-icon-time"></i>
+              </div>
+              <div class="stat-info">
+                <div class="stat-value">{{ statistics.pending }}</div>
+                <div class="stat-label">待审核</div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="stat-card" shadow="hover">
+            <div class="stat-content">
+              <div class="stat-icon approved">
+                <i class="el-icon-check"></i>
+              </div>
+              <div class="stat-info">
+                <div class="stat-value">{{ statistics.approved }}</div>
+                <div class="stat-label">已通过</div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="stat-card" shadow="hover">
+            <div class="stat-content">
+              <div class="stat-icon rejected">
+                <i class="el-icon-close"></i>
+              </div>
+              <div class="stat-info">
+                <div class="stat-value">{{ statistics.rejected }}</div>
+                <div class="stat-label">已拒绝</div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="stat-card" shadow="hover">
+            <div class="stat-content">
+              <div class="stat-icon total">
+                <i class="el-icon-data-line"></i>
+              </div>
+              <div class="stat-info">
+                <div class="stat-value">{{ statistics.total }}</div>
+                <div class="stat-label">总申请数</div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+    </div>
+
+    <!-- 搜索表单 -->
+    <el-card class="search-card" shadow="hover">
+      <div class="search-header">
+        <div class="search-title">
+          <i class="el-icon-search"></i>
+          <span>筛选条件</span>
+        </div>
+        <el-button type="text" @click="toggleSearch">
+          {{ showSearch ? '收起' : '展开' }}
+          <i :class="showSearch ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
+        </el-button>
+      </div>
+
+      <el-collapse-transition>
+        <el-form v-show="showSearch" :model="queryParams" ref="queryForm" :inline="true" label-width="80px"
+          class="search-form">
+          <el-row :gutter="20">
+            <el-col :span="6">
+              <el-form-item label="公司名称" prop="companyName">
+                <el-input v-model="queryParams.companyName" placeholder="请输入公司名称" clearable
+                  prefix-icon="el-icon-office-building" class="search-input" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="提交单号" prop="applicationNumber">
+                <el-input v-model="queryParams.applicationNumber" placeholder="请输入提交单号" clearable
+                  prefix-icon="el-icon-document" class="search-input" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="申请数量" prop="applyQuantity">
+                <el-input v-model="queryParams.applyQuantity" placeholder="请输入申请数量" clearable
+                  prefix-icon="el-icon-s-data" class="search-input" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="审核状态" prop="auditStatus">
+                <el-select v-model="queryParams.auditStatus" placeholder="请选择审核状态" clearable class="search-select">
+                  <el-option label="待审核" value="0" />
+                  <el-option label="审核通过" value="1" />
+                  <el-option label="审核拒绝" value="2" />
+                  <el-option label="部分分配" value="3" />
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row :gutter="20">
+            <el-col :span="6">
+              <el-form-item label="提交时间" prop="submitTime">
+                <el-date-picker clearable v-model="queryParams.submitTime" type="datetime"
+                  value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择提交时间" class="search-date">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="审核时间" prop="reviewTime">
+                <el-date-picker clearable v-model="queryParams.reviewTime" type="datetime"
+                  value-format="yyyy-MM-dd HH:mm:ss" placeholder="选择审核时间" class="search-date">
+                </el-date-picker>
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="实际分配" prop="allocatedQuantity">
+                <el-input v-model="queryParams.allocatedQuantity" placeholder="请输入实际分配数量" clearable
+                  prefix-icon="el-icon-s-marketing" class="search-input" />
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item>
+                <el-button type="primary" icon="el-icon-search" @click="handleQuery" class="search-btn">
+                  搜索
+                </el-button>
+                <el-button icon="el-icon-refresh" @click="resetQuery" class="reset-btn">
+                  重置
+                </el-button>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-form>
+      </el-collapse-transition>
+    </el-card>
+
+    <!-- 批量操作工具栏 -->
+    <div class="batch-toolbar" v-show="selectedRows.length > 0">
+      <el-card class="batch-card" shadow="hover">
+        <div class="batch-content">
+          <div class="batch-info">
+            <i class="el-icon-warning-outline"></i>
+            <span>已选择 {{ selectedRows.length }} 项</span>
+          </div>
+          <div class="batch-actions">
+            <el-button size="small" @click="batchApprove" v-if="canBatchApprove" type="success">
+              <i class="el-icon-check"></i> 批量通过
+            </el-button>
+            <el-button size="small" @click="batchReject" v-if="canBatchReject" type="danger">
+              <i class="el-icon-close"></i> 批量拒绝
+            </el-button>
+            <el-button size="small" @click="handleBatchSync" type="warning">
+              <i class="el-icon-refresh"></i> 批量同步
+            </el-button>
+            <el-button size="small" @click="clearSelection">
+              <i class="el-icon-close"></i> 清空选择
+            </el-button>
+          </div>
+        </div>
+      </el-card>
+    </div>
+
+    <!-- 操作按钮区域 -->
+    <el-card class="action-card" shadow="never">
+      <div class="action-bar">
+        <div class="action-group">
+          <el-button type="primary" icon="el-icon-plus" @click="handleAdd" class="action-btn"
+            >
+            申请iPad
+          </el-button>
+
+          <el-button type="success" icon="el-icon-edit" @click="handleUpdate" :disabled="single" class="action-btn"
+            >
+            修改
+          </el-button>
+
+          <el-dropdown @command="handleBatchCommand" class="action-dropdown">
+            <el-button type="warning" class="action-btn">
+              批量操作<i class="el-icon-arrow-down el-icon--right"></i>
+            </el-button>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item command="sync">
+                批量同步
+              </el-dropdown-item>
+              <el-dropdown-item command="export">
+                导出数据
+              </el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+        </div>
+
+        <div class="action-right">
+          <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+        </div>
+      </div>
+    </el-card>
+
+    <!-- 数据表格 -->
+    <el-card class="table-card" shadow="hover">
+      <el-table border v-loading="loading" :data="recordsList" @selection-change="handleSelectionChange"
+        class="modern-table" :header-cell-class-name="headerCellClass" :cell-class-name="cellClass"
+        @row-click="handleRowClick">
+
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="公司名称" align="center" prop="companyName" min-width="150">
+          <template slot-scope="scope">
+            <div class="company-name">
+              <i class="el-icon-office-building"></i>
+              {{ scope.row.companyName }}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="申请数量" align="center" prop="applyQuantity" width="100">
+          <template slot-scope="scope">
+            <el-tag type="info" effect="plain">{{ scope.row.applyQuantity }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="实际分配数量" align="center" prop="allocatedQuantity" width="120">
+          <template slot-scope="scope">
+            <el-tag type="success" effect="plain">{{ scope.row.allocatedQuantity || 0 }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="提交时间" align="center" prop="submitTime" width="180">
+          <template slot-scope="scope">
+            <div class="time-info">
+              <i class="el-icon-time"></i>
+              <span>{{ parseTime(scope.row.submitTime) }}</span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="审核时间" align="center" prop="reviewTime" width="180">
+          <template slot-scope="scope">
+            <div class="time-info" v-if="scope.row.reviewTime">
+              <i class="el-icon-check"></i>
+              <span>{{ parseTime(scope.row.reviewTime) }}</span>
+            </div>
+            <span v-else class="no-data">-</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="审核状态" align="center" prop="auditStatus" width="120">
+          <template slot-scope="scope">
+            <div class="status-wrapper">
+              <el-tag :class="getStatusClass(scope.row.auditStatus)"
+                :effect="scope.row.auditStatus === 1 ? 'dark' : 'light'">
+                <i :class="getStatusIcon(scope.row.auditStatus)"></i>
+                {{ getStatusText(scope.row.auditStatus) }}
+              </el-tag>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="拒绝原因" align="center" prop="rejectionReason" min-width="150">
+          <template slot-scope="scope">
+            <el-tooltip :content="scope.row.rejectionReason" placement="top" v-if="scope.row.rejectionReason">
+              <span class="rejection-reason">{{ scope.row.rejectionReason }}</span>
+            </el-tooltip>
+            <span v-else class="no-data">-</span>
+          </template>
+        </el-table-column>
+
+        <el-table-column label="操作" align="center" width="180" fixed="right">
+          <template slot-scope="scope">
+            <div class="action-buttons">
+              <el-tooltip content="同步数据" placement="top">
+                <el-button type="text" icon="el-icon-refresh" class="action-icon-btn sync-btn"
+                  @click="handleSingleSync(scope.row)" />
+              </el-tooltip>
+
+              <el-tooltip content="释放管理" placement="top"
+                v-if="scope.row.auditStatus == 1 || scope.row.auditStatus == 3">
+                <el-button type="text" icon="el-icon-unlock" class="action-icon-btn release-btn"
+                  @click="handleRelease(scope.row)" />
+              </el-tooltip>
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <!-- 分页 -->
+      <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+        @pagination="getList" class="pagination-wrapper" />
+    </el-card>
+
+    <!-- 申请iPad对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="600px" :close-on-click-modal="false"
+      custom-class="modern-dialog" append-to-body>
+      <div class="dialog-content">
+        <div class="form-header">
+          <i class="el-icon-mobile-phone"></i>
+          <span>请填写申请信息</span>
+        </div>
+
+        <el-form ref="form" :model="form" :rules="rules" label-width="100px" class="modern-form">
+          <el-form-item label="申请地区" prop="area">
+            <el-input v-model="form.area" placeholder="请输入申请地区,如:广州、上海、重庆、北京等"
+              prefix-icon="el-icon-location" class="area-input" />
+            <div class="form-tip">
+              <i class="el-icon-info"></i>
+              请填写申请iPad使用的地区
+            </div>
+          </el-form-item>
+          <el-form-item label="申请数量" prop="applyQuantity">
+            <el-input-number v-model="form.applyQuantity" :min="1" :max="100" controls-position="right"
+              class="number-input" placeholder="请输入申请数量" />
+            <div class="form-tip">
+              <i class="el-icon-info"></i>
+              建议根据实际需求申请合理数量
+            </div>
+          </el-form-item>
+        </el-form>
+      </div>
+
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="cancel" class="cancel-btn">取 消</el-button>
+        <el-button type="primary" @click="submitForm" :loading="submitting" class="confirm-btn">
+          {{ submitting ? '提交中...' : '确定申请' }}
+        </el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 释放信息抽屉 -->
+    <el-drawer title="服务器分配信息" :visible.sync="releaseOpen" direction="rtl" size="70%" :before-close="handleDrawerClose"
+      custom-class="modern-drawer">
+      <div class="drawer-content">
+        <el-table :data="serverInfoList" border v-loading="releaseLoading" class="server-table">
+          <el-table-column label="访问地址" align="center" prop="accessUrl" min-width="200">
+            <template slot-scope="scope">
+              <a :href="scope.row.accessUrl" target="_blank" class="access-url">
+                <i class="el-icon-link"></i>
+                {{ scope.row.accessUrl }}
+              </a>
+            </template>
+          </el-table-column>
+          <el-table-column label="已分配座位数" align="center" prop="allocatedSeats" width="120">
+            <template slot-scope="scope">
+              <el-tag type="primary">{{ scope.row.allocatedSeats }}</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="分配时间" align="center" prop="allocatedTime" width="180">
+            <template slot-scope="scope">
+              <span>{{ parseTime(scope.row.allocatedTime) }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="分配状态" align="center" prop="allocationStatus" width="100">
+            <template slot-scope="scope">
+              <el-tag :type="scope.row.allocationStatus === 1 ? 'success' : 'info'">
+                {{ scope.row.allocationStatus === 1 ? '有效' : '已释放' }}
+              </el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="IP地址" align="center" prop="ipAddress" width="120" />
+          <el-table-column label="端口" align="center" prop="port" width="80" />
+          <el-table-column label="地区" align="center" prop="region" width="100" />
+          <el-table-column label="创建时间" align="center" prop="createdTime" width="180">
+            <template slot-scope="scope">
+              <span>{{ parseTime(scope.row.createdTime) }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center" width="120">
+            <template slot-scope="scope">
+              <el-button size="mini" type="primary" @click="handleReleaseSeats(scope.row)"
+                :disabled="scope.row.allocationStatus !== 1" class="release-seats-btn">
+                释放座位
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </el-drawer>
+
+    <!-- 释放座位数量输入弹窗 -->
+    <el-dialog title="释放座位" :visible.sync="releaseSeatsOpen" width="400px" custom-class="release-dialog" append-to-body>
+      <el-form :model="releaseForm" :rules="releaseRules" ref="releaseForm" label-width="100px">
+        <el-form-item label="释放数量" prop="releaseCount">
+          <el-input-number v-model="releaseForm.releaseCount" :min="1" :max="releaseForm.maxSeats" placeholder="请输入释放数量"
+            controls-position="right" style="width: 100%" />
+          <div class="form-tip">
+            <i class="el-icon-info"></i>
+            最大可释放数量:{{ releaseForm.maxSeats }}
+          </div>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="releaseSeatsOpen = false">取 消</el-button>
+        <el-button type="primary" @click="submitReleaseSeats()">确 定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listRecords, getServerInfo, getRecords, delRecords, release, updateRecords, exportRecords, apply, batchUpdate } from "@/api/qw/applyIpad";
+
+export default {
+  name: "Records",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 提交状态
+      submitting: false,
+      // 选中数组
+      ids: [],
+      // 选中的行数据
+      selectedRows: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 分配记录表格数据
+      recordsList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        companyId: null,
+        companyName: null,
+        applicationNumber: null,
+        applyQuantity: null,
+        allocatedQuantity: null,
+        submitTime: null,
+        reviewTime: null,
+        auditStatus: null,
+        rejectionReason: null,
+        createdTime: null,
+        updatedTime: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        area: [
+          { required: true, message: "申请地区不能为空", trigger: "blur" }
+        ],
+        applyQuantity: [
+          { required: true, message: "申请数量不能为空", trigger: "blur" },
+          { pattern: /^[1-9]\d*$/, message: "申请数量必须为正整数", trigger: "blur" }
+        ]
+      },
+      // 释放抽屉显示状态
+      releaseOpen: false,
+      // 释放信息加载状态
+      releaseLoading: false,
+      // 服务器信息列表
+      serverInfoList: [],
+      // 释放座位弹窗显示状态
+      releaseSeatsOpen: false,
+      // 释放座位表单
+      releaseForm: {
+        releaseCount: null,
+        maxSeats: 0,
+        currentServer: null
+      },
+      // 释放座位表单校验规则
+      releaseRules: {
+        releaseCount: [
+          { required: true, message: "释放数量不能为空", trigger: "blur" },
+          { type: 'number', min: 1, message: "释放数量必须大于0", trigger: "blur" },
+          {
+            validator: (rule, value, callback) => {
+              if (value > this.releaseForm.maxSeats) {
+                callback(new Error(`释放数量不能超过${this.releaseForm.maxSeats}`));
+              } else {
+                callback();
+              }
+            },
+            trigger: "blur"
+          }
+        ]
+      },
+      // 当前选中的申请记录ID
+      currentRecordId: null,
+      // 统计数据
+      statistics: {
+        pending: 0,
+        approved: 0,
+        rejected: 0,
+        total: 0
+      }
+    };
+  },
+  computed: {
+    // 是否可以批量审核通过
+    canBatchApprove() {
+      return this.selectedRows.some(row => row.auditStatus === 0);
+    },
+    // 是否可以批量审核拒绝
+    canBatchReject() {
+      return this.selectedRows.some(row => row.auditStatus === 0);
+    }
+  },
+  created() {
+    this.getList();
+    this.calculateStatistics();
+    // 添加键盘事件监听
+    document.addEventListener('keydown', this.handleKeydown);
+  },
+  beforeDestroy() {
+    document.removeEventListener('keydown', this.handleKeydown);
+  },
+  methods: {
+    /** 查询分配记录列表 */
+    getList() {
+      this.loading = true;
+      listRecords(this.queryParams).then(response => {
+        this.recordsList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+        this.calculateStatistics();
+      });
+    },
+
+    /** 计算统计数据 */
+    calculateStatistics() {
+      this.statistics = {
+        pending: this.recordsList.filter(item => item.auditStatus === 0).length,
+        approved: this.recordsList.filter(item => item.auditStatus === 1).length,
+        rejected: this.recordsList.filter(item => item.auditStatus === 2).length,
+        total: this.recordsList.length
+      };
+    },
+
+    /** 键盘事件处理 */
+    handleKeydown(e) {
+      // Ctrl + N: 新建申请
+      if (e.ctrlKey && e.key === 'n') {
+        e.preventDefault();
+        this.handleAdd();
+      }
+      // Ctrl + E: 导出数据
+      if (e.ctrlKey && e.key === 'e') {
+        e.preventDefault();
+        this.handleExport();
+      }
+      // F5: 刷新数据
+      if (e.key === 'F5') {
+        e.preventDefault();
+        this.getList();
+      }
+    },
+
+    /** 切换搜索显示 */
+    toggleSearch() {
+      this.showSearch = !this.showSearch;
+    },
+
+    /** 表格头部样式 */
+    headerCellClass({ row, column, rowIndex, columnIndex }) {
+      return 'modern-header';
+    },
+
+    /** 表格单元格样式 */
+    cellClass({ row, column, rowIndex, columnIndex }) {
+      return 'modern-cell';
+    },
+
+    /** 行点击事件 */
+    handleRowClick(row, column, event) {
+      // 可以添加行点击后的处理逻辑
+    },
+
+    /** 获取状态样式类 */
+    getStatusClass(status) {
+      const statusMap = {
+        0: 'status-pending',
+        1: 'status-approved',
+        2: 'status-rejected',
+        3: 'status-partial'
+      };
+      return statusMap[status] || '';
+    },
+
+    /** 获取状态图标 */
+    getStatusIcon(status) {
+      const iconMap = {
+        0: 'el-icon-time',
+        1: 'el-icon-check',
+        2: 'el-icon-close',
+        3: 'el-icon-warning'
+      };
+      return iconMap[status] || 'el-icon-question';
+    },
+
+    /** 获取状态文本 */
+    getStatusText(status) {
+      const textMap = {
+        0: '待审核',
+        1: '审核通过',
+        2: '审核拒绝',
+        3: '部分分配'
+      };
+      return textMap[status] || '-';
+    },
+
+    /** 批量命令处理 */
+    handleBatchCommand(command) {
+      if (command === 'sync') {
+        this.handleBatchSync();
+      } else if (command === 'export') {
+        this.handleExport();
+      }
+    },
+
+    /** 批量审核通过 */
+    batchApprove() {
+      const pendingRows = this.selectedRows.filter(row => row.auditStatus === 0);
+      if (pendingRows.length === 0) {
+        this.msgWarning('没有可审核通过的记录');
+        return;
+      }
+
+      this.$confirm(`确认审核通过选中的 ${pendingRows.length} 条记录?`, '批量审核', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        // 这里调用批量审核通过的API
+        this.msgSuccess('批量审核通过成功');
+        this.getList();
+      });
+    },
+
+    /** 批量审核拒绝 */
+    batchReject() {
+      const pendingRows = this.selectedRows.filter(row => row.auditStatus === 0);
+      if (pendingRows.length === 0) {
+        this.msgWarning('没有可审核拒绝的记录');
+        return;
+      }
+
+      this.$confirm(`确认审核拒绝选中的 ${pendingRows.length} 条记录?`, '批量审核', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        // 这里调用批量审核拒绝的API
+        this.msgSuccess('批量审核拒绝成功');
+        this.getList();
+      });
+    },
+
+    /** 清空选择 */
+    clearSelection() {
+      this.$refs.multipleTable && this.$refs.multipleTable.clearSelection();
+      this.selectedRows = [];
+      this.ids = [];
+    },
+
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        area: null,
+        applyQuantity: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.selectedRows = selection;
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "申请iPad";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getRecords(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改分配记录";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          this.submitting = true;
+          // 调用apply接口,传递申请数量和地区作为参数对象
+          apply({
+            applyCount: this.form.applyQuantity,
+            area: this.form.area
+          }).then(response => {
+            this.msgSuccess("申请成功");
+            this.open = false;
+            this.getList();
+          }).catch(() => {
+            // this.msgError("申请失败");
+          }).finally(() => {
+            this.submitting = false;
+          });
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除分配记录编号为"' + ids + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return delRecords(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => { });
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有分配记录数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportRecords(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => { });
+    },
+    /** 单个同步按钮操作 */
+    handleSingleSync(row) {
+      const id = row.id;
+      this.$confirm('是否确认同步编号为"' + id + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return batchUpdate([id]);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("同步成功");
+      }).catch(() => { });
+    },
+    /** 批量同步按钮操作 */
+    handleBatchSync() {
+      const ids = this.ids;
+      this.$confirm('是否确认同步选中的' + ids.length + '条数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        return batchUpdate(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("批量同步成功");
+      }).catch(() => { });
+    },
+    /** 释放按钮操作 */
+    handleRelease(row) {
+      this.releaseLoading = true;
+      this.releaseOpen = true;
+      this.serverInfoList = [];
+      this.currentRecordId = row.id;
+
+      // 调用getServerInfo接口获取服务器信息
+      getServerInfo(row.id).then(response => {
+        this.serverInfoList = response.data || [];
+        this.releaseLoading = false;
+      }).catch(error => {
+        this.releaseLoading = false;
+        this.msgError("获取服务器信息失败");
+      });
+    },
+
+    /** 抽屉关闭处理 */
+    handleDrawerClose(done) {
+      this.releaseOpen = false;
+      done();
+    },
+
+    /** 释放座位按钮操作 */
+    handleReleaseSeats(server) {
+      this.releaseForm = {
+        releaseCount: null,
+        maxSeats: server.allocatedSeats || 0,
+        currentServer: server
+      };
+
+      this.releaseSeatsOpen = true;
+      this.$nextTick(() => {
+        this.$refs.releaseForm && this.$refs.releaseForm.clearValidate();
+      });
+    },
+
+    /** 提交释放座位 */
+    submitReleaseSeats() {
+      this.$refs.releaseForm.validate(valid => {
+        if (valid) {
+          // 根据后端ServerParam类结构组装参数
+          const params = {
+            ipadServerId: this.releaseForm.currentServer.ipadRecordId, // 服务器ID
+            recordId: this.currentRecordId,                 // 记录ID
+            releaseCount: this.releaseForm.releaseCount,    // 释放数量
+            ipAddress: this.releaseForm.currentServer.ipAddress, // iPad地址
+            port: this.releaseForm.currentServer.port       // 端口号
+          };
+
+          // 调用release接口
+          release(params).then(response => {
+            this.msgSuccess("释放成功");
+            this.releaseSeatsOpen = false;
+            // 重新加载服务器信息
+            this.handleRelease({ id: this.currentRecordId });
+          }).catch(error => {
+            this.msgError("释放失败");
+          });
+        }
+      });
+    },
+
+    /** 重置释放座位表单 */
+    resetReleaseForm() {
+      this.releaseForm = {
+        releaseCount: null,
+        maxSeats: 0,
+        currentServer: null
+      };
+      this.$refs.releaseForm && this.$refs.releaseForm.clearValidate();
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.app-container {
+  padding: 20px;
+  background: #f0f2f5;
+  min-height: calc(100vh - 84px);
+}
+
+// 统计卡片样式
+.statistics-cards {
+  margin-bottom: 20px;
+
+  .stat-card {
+    border-radius: 12px;
+    border: none;
+    transition: all 0.3s ease;
+
+    &:hover {
+      transform: translateY(-5px);
+      box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
+    }
+
+    .stat-content {
+      display: flex;
+      align-items: center;
+      padding: 10px;
+
+      .stat-icon {
+        width: 60px;
+        height: 60px;
+        border-radius: 12px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        margin-right: 15px;
+        font-size: 24px;
+        color: white;
+
+        &.pending {
+          background: #409eff;
+        }
+
+        &.approved {
+          background: #67c23a;
+        }
+
+        &.rejected {
+          background: #f56c6c;
+        }
+
+        &.total {
+          background: #909399;
+        }
+      }
+
+      .stat-info {
+        flex: 1;
+
+        .stat-value {
+          font-size: 28px;
+          font-weight: bold;
+          color: #2c3e50;
+          line-height: 1;
+        }
+
+        .stat-label {
+          font-size: 14px;
+          color: #7f8c8d;
+          margin-top: 5px;
+        }
+      }
+    }
+  }
+}
+
+// 搜索卡片样式
+.search-card {
+  border-radius: 12px;
+  margin-bottom: 20px;
+  border: none;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
+  transition: all 0.3s ease;
+
+  &:hover {
+    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
+  }
+
+  .search-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding-bottom: 15px;
+    border-bottom: 1px solid #ebeef5;
+    margin-bottom: 20px;
+
+    .search-title {
+      display: flex;
+      align-items: center;
+      font-size: 16px;
+      font-weight: 600;
+      color: #2c3e50;
+
+      i {
+        margin-right: 8px;
+        color: #409eff;
+      }
+    }
+  }
+
+  .search-form {
+
+    .search-input,
+    .search-select,
+    .search-date {
+      width: 100%;
+    }
+
+    .search-btn,
+    .reset-btn {
+      border-radius: 8px;
+      font-weight: 500;
+      transition: all 0.3s ease;
+    }
+
+    .search-btn:hover {
+      background-color: #66b1ff;
+    }
+
+    .reset-btn:hover {
+      color: #409eff;
+      border-color: #c6e2ff;
+      background-color: #ecf5ff;
+    }
+  }
+}
+
+// 批量操作工具栏
+.batch-toolbar {
+  margin-bottom: 20px;
+
+  .batch-card {
+    border-radius: 12px;
+    border: none;
+    background: #fdf6ec;
+
+    .batch-content {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      .batch-info {
+        display: flex;
+        align-items: center;
+        color: #f39c12;
+        font-weight: 500;
+
+        i {
+          margin-right: 8px;
+          font-size: 18px;
+        }
+      }
+
+      .batch-actions {
+        display: flex;
+        gap: 10px;
+
+        .el-button {
+          border-radius: 6px;
+          font-weight: 500;
+        }
+      }
+    }
+  }
+}
+
+// 操作按钮区域
+.action-card {
+  border-radius: 12px;
+  margin-bottom: 20px;
+  border: none;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
+
+  .action-bar {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .action-group {
+      display: flex;
+      gap: 15px;
+
+      .action-btn {
+        border-radius: 4px;
+        font-weight: 500;
+        transition: all 0.3s ease;
+
+        &:hover {
+          opacity: 0.8;
+        }
+      }
+    }
+  }
+}
+
+// 表格卡片样式
+.table-card {
+  border-radius: 12px;
+  border: none;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
+  transition: all 0.3s ease;
+
+  &:hover {
+    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
+  }
+
+  .modern-table {
+    border-radius: 8px;
+    overflow: hidden;
+
+    ::v-deep .modern-header {
+      background: #f5f7fa;
+      color: #606266;
+      font-weight: 600;
+    }
+
+    ::v-deep .modern-cell {
+      .company-name {
+        display: flex;
+        align-items: center;
+
+        i {
+          margin-right: 5px;
+          color: #409eff;
+        }
+      }
+
+      .time-info {
+        display: flex;
+        align-items: center;
+        font-size: 12px;
+
+        i {
+          margin-right: 5px;
+          color: #909399;
+        }
+      }
+
+      .no-data {
+        color: #c0c4cc;
+      }
+
+      .rejection-reason {
+        max-width: 150px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        display: inline-block;
+      }
+    }
+
+    ::v-deep .el-table__row {
+      transition: all 0.3s ease;
+
+      &:hover {
+        background-color: #f5f7fa;
+      }
+    }
+
+    .action-buttons {
+      display: flex;
+      justify-content: center;
+      gap: 10px;
+
+      .action-icon-btn {
+        width: 32px;
+        height: 32px;
+        border-radius: 6px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        transition: all 0.3s ease;
+
+        &:hover {
+          transform: scale(1.1);
+        }
+
+        &.sync-btn {
+          color: #409eff;
+
+          &:hover {
+            background: rgba(64, 158, 255, 0.1);
+          }
+        }
+
+        &.release-btn {
+          color: #e6a23c;
+
+          &:hover {
+            background: rgba(230, 162, 60, 0.1);
+          }
+        }
+      }
+    }
+  }
+
+  .pagination-wrapper {
+    margin-top: 20px;
+    text-align: right;
+  }
+}
+
+// 状态标签样式
+.status-wrapper {
+  .el-tag {
+    border-radius: 20px;
+    padding: 4px 12px;
+    font-weight: 500;
+    border: none;
+
+    i {
+      margin-right: 5px;
+    }
+
+    &.status-pending {
+      background-color: #e1f3d8;
+      color: #67c23a;
+      border-color: #e1f3d8;
+    }
+
+    &.status-approved {
+      background-color: #f0f9ff;
+      color: #409eff;
+      border-color: #f0f9ff;
+    }
+
+    &.status-rejected {
+      background-color: #fef0f0;
+      color: #f56c6c;
+      border-color: #fef0f0;
+    }
+
+    &.status-partial {
+      background-color: #fdf6ec;
+      color: #e6a23c;
+      border-color: #fdf6ec;
+    }
+  }
+}
+
+// 对话框样式
+::v-deep .modern-dialog {
+  border-radius: 12px;
+
+  .el-dialog__header {
+    background: #f5f7fa;
+    color: #606266;
+    border-radius: 12px 12px 0 0;
+    padding: 20px;
+
+    .el-dialog__title {
+      font-weight: 600;
+    }
+  }
+
+  .el-dialog__body {
+    padding: 30px 20px;
+  }
+
+  .dialog-content {
+    .form-header {
+      display: flex;
+      align-items: center;
+      margin-bottom: 20px;
+      padding-bottom: 15px;
+      border-bottom: 1px solid #ebeef5;
+
+      i {
+        margin-right: 10px;
+        color: #409eff;
+        font-size: 20px;
+      }
+
+      span {
+        font-size: 16px;
+        font-weight: 600;
+        color: #2c3e50;
+      }
+    }
+
+    .modern-form {
+      .area-input {
+        width: 100%;
+      }
+      
+      .number-input {
+        width: 100%;
+      }
+
+      .form-tip {
+        display: flex;
+        align-items: center;
+        color: #909399;
+        font-size: 12px;
+        margin-top: 5px;
+
+        i {
+          margin-right: 5px;
+        }
+      }
+    }
+  }
+
+  .dialog-footer {
+    text-align: right;
+    padding: 15px 20px;
+    border-top: 1px solid #ebeef5;
+
+    .cancel-btn,
+    .confirm-btn {
+      border-radius: 8px;
+      font-weight: 500;
+      transition: all 0.3s ease;
+    }
+
+    .confirm-btn:hover {
+      background-color: #66b1ff;
+    }
+  }
+}
+
+// 抽屉样式
+::v-deep .modern-drawer {
+  .el-drawer__header {
+    background: #f5f7fa;
+    color: #606266;
+    padding: 20px;
+    margin-bottom: 0;
+
+    span {
+      font-weight: 600;
+    }
+  }
+
+  .drawer-content {
+    padding: 20px;
+
+    .server-table {
+      border-radius: 8px;
+      overflow: hidden;
+
+      .access-url {
+        color: #409eff;
+        text-decoration: none;
+
+        &:hover {
+          text-decoration: underline;
+        }
+
+        i {
+          margin-right: 5px;
+        }
+      }
+
+      .release-seats-btn {
+        border-radius: 6px;
+        font-weight: 500;
+      }
+    }
+  }
+}
+
+// 释放对话框样式
+::v-deep .release-dialog {
+  border-radius: 12px;
+
+  .el-dialog__header {
+    background: #f5f7fa;
+    color: #606266;
+    border-radius: 12px 12px 0 0;
+
+    .el-dialog__title {
+      font-weight: 600;
+    }
+  }
+}
+
+// 响应式设计
+@media (max-width: 768px) {
+  .app-container {
+    padding: 10px;
+  }
+
+  .statistics-cards {
+    .el-col {
+      margin-bottom: 10px;
+    }
+  }
+
+  .search-form {
+    .el-col {
+      margin-bottom: 10px;
+    }
+  }
+
+  .action-bar {
+    flex-direction: column;
+    align-items: stretch;
+
+    .action-group {
+      margin-bottom: 10px;
+      justify-content: center;
+    }
+  }
+
+  .batch-content {
+    flex-direction: column;
+    align-items: flex-start;
+
+    .batch-actions {
+      margin-top: 10px;
+      flex-wrap: wrap;
+    }
+  }
+}
+</style>

+ 13 - 0
src/views/system/config/config.vue

@@ -730,6 +730,16 @@
       <el-tab-pane label="短信配置" name="his.sms">
 
         <el-form ref="form14" :model="form14" label-width="150px">
+          <el-form-item label="是否开启APP短信验证" label-width="160px">
+            <el-switch
+              v-model="form14.isSmsVerification"
+              active-color="#13ce66"
+              inactive-color="#ff4949"
+              active-value="1"
+              inactive-value="0"
+            >
+            </el-switch>
+          </el-form-item>
           <el-form-item label="短信服务商" prop="type">
             <el-radio-group v-model="form14.type">
               <el-radio label="rf">重庆润芳</el-radio>
@@ -2927,6 +2937,9 @@ export default {
       })
     },
     submitForm14() {
+      if (!this.form14.isSmsVerification) {
+        this.form14.isSmsVerification = 0;
+      }
       var param = { configId: this.configId, configValue: JSON.stringify(this.form14) }
       updateConfigByKey(param).then(response => {
         if (response.code === 200) {