Browse Source

add:首页权限

ct 1 day ago
parent
commit
1a2f10e81a

+ 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>

+ 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>