Bläddra i källkod

refactor(dashboard): 注释隐藏仪表盘部分内容

- 注释隐藏 GitHub 角标组件
- 注释隐藏右侧图标区域及其内容
- 注释隐藏最新动态模块及相关时间轴内容

feat(operationsManage): 添加数据看板页面及相关组件

- 实现数据看板界面布局及标签页切换
- 添加实时数据和今日实时数据展示卡片
- 实现所有站点充电度数日时段对比趋势图表
- 添加历史营业数据面积图及表格视图
- 支持热门充电站与波动充电站数据分页展示
- 实现用户流失率展示及报表下载功能

refactor(user-info): 移除未使用的用户订单API导入代码

- 清理多余的 UserOrderInfoAPI 导入声明
zouzexu 1 vecka sedan
förälder
incheckning
76f73eceab

BIN
src/assets/kanban/cdds.png


BIN
src/assets/kanban/cdje.png


BIN
src/assets/kanban/dkqje.png


BIN
src/assets/kanban/fwfje.png


BIN
src/assets/kanban/fxyj.png


BIN
src/assets/kanban/qyzxjj.png


BIN
src/assets/kanban/sdje.png


BIN
src/assets/kanban/sfje.png


BIN
src/assets/kanban/tkje.png


BIN
src/assets/kanban/yhqjm.png


+ 116 - 116
src/views/dashboard/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="dashboard-container">
     <!-- github 角标 -->
-    <github-corner class="github-corner" />
+<!--    <github-corner class="github-corner" />-->
 
     <el-card shadow="never" class="mt-2">
       <div class="flex flex-wrap">
@@ -13,71 +13,71 @@
           />
           <div class="ml-5">
             <p>{{ greetings }}</p>
-            <p class="text-sm text-gray">今日天气晴朗,气温在15℃至25℃之间,东南风。</p>
+<!--            <p class="text-sm text-gray">今日天气晴朗,气温在15℃至25℃之间,东南风。</p>-->
           </div>
         </div>
 
         <!-- 右侧图标区域 - PC端 -->
         <div class="hidden sm:block">
-          <div class="flex items-end space-x-6">
-            <!-- 仓库 -->
-            <div>
-              <div class="font-bold color-#ff9a2e text-sm flex items-center">
-                <el-icon class="mr-2px"><Folder /></el-icon>
-                仓库
-              </div>
-              <div class="mt-3 whitespace-nowrap">
-                <el-link href="https://gitee.com/youlaiorg/vue3-element-admin" target="_blank">
-                  <div class="i-svg:gitee text-lg color-#F76560" />
-                </el-link>
-                <el-divider direction="vertical" />
-                <el-link href="https://github.com/youlaitech/vue3-element-admin" target="_blank">
-                  <div class="i-svg:github text-lg color-#4080FF" />
-                </el-link>
-                <el-divider direction="vertical" />
-                <el-link href="https://gitcode.com/youlai/vue3-element-admin" target="_blank">
-                  <div class="i-svg:gitcode text-lg color-#FF9A2E" />
-                </el-link>
-              </div>
-            </div>
-
-            <!-- 文档 -->
-            <div>
-              <div class="font-bold color-#4080ff text-sm flex items-center">
-                <el-icon class="mr-2px"><Document /></el-icon>
-                文档
-              </div>
-              <div class="mt-3 whitespace-nowrap">
-                <el-link href="https://juejin.cn/post/7228990409909108793" target="_blank">
-                  <div class="i-svg:juejin text-lg" />
-                </el-link>
-                <el-divider direction="vertical" />
-                <el-link
-                  href="https://youlai.blog.csdn.net/article/details/130191394"
-                  target="_blank"
-                >
-                  <div class="i-svg:csdn text-lg" />
-                </el-link>
-                <el-divider direction="vertical" />
-                <el-link href="https://www.cnblogs.com/haoxianrui/p/17331952.html" target="_blank">
-                  <div class="i-svg:cnblogs text-lg" />
-                </el-link>
-              </div>
-            </div>
-
-            <!-- 视频 -->
-            <div>
-              <div class="font-bold color-#f76560 text-sm flex items-center">
-                <el-icon class="mr-2px"><VideoCamera /></el-icon>
-                视频
-              </div>
-              <div class="mt-3 whitespace-nowrap">
-                <el-link href="https://www.bilibili.com/video/BV1eFUuYyEFj" target="_blank">
-                  <div class="i-svg:bilibili text-lg" />
-                </el-link>
-              </div>
-            </div>
-          </div>
+<!--          <div class="flex items-end space-x-6">-->
+<!--            &lt;!&ndash; 仓库 &ndash;&gt;-->
+<!--            <div>-->
+<!--              <div class="font-bold color-#ff9a2e text-sm flex items-center">-->
+<!--                <el-icon class="mr-2px"><Folder /></el-icon>-->
+<!--                仓库-->
+<!--              </div>-->
+<!--              <div class="mt-3 whitespace-nowrap">-->
+<!--                <el-link href="https://gitee.com/youlaiorg/vue3-element-admin" target="_blank">-->
+<!--                  <div class="i-svg:gitee text-lg color-#F76560" />-->
+<!--                </el-link>-->
+<!--                <el-divider direction="vertical" />-->
+<!--                <el-link href="https://github.com/youlaitech/vue3-element-admin" target="_blank">-->
+<!--                  <div class="i-svg:github text-lg color-#4080FF" />-->
+<!--                </el-link>-->
+<!--                <el-divider direction="vertical" />-->
+<!--                <el-link href="https://gitcode.com/youlai/vue3-element-admin" target="_blank">-->
+<!--                  <div class="i-svg:gitcode text-lg color-#FF9A2E" />-->
+<!--                </el-link>-->
+<!--              </div>-->
+<!--            </div>-->
+
+<!--            &lt;!&ndash; 文档 &ndash;&gt;-->
+<!--            <div>-->
+<!--              <div class="font-bold color-#4080ff text-sm flex items-center">-->
+<!--                <el-icon class="mr-2px"><Document /></el-icon>-->
+<!--                文档-->
+<!--              </div>-->
+<!--              <div class="mt-3 whitespace-nowrap">-->
+<!--                <el-link href="https://juejin.cn/post/7228990409909108793" target="_blank">-->
+<!--                  <div class="i-svg:juejin text-lg" />-->
+<!--                </el-link>-->
+<!--                <el-divider direction="vertical" />-->
+<!--                <el-link-->
+<!--                  href="https://youlai.blog.csdn.net/article/details/130191394"-->
+<!--                  target="_blank"-->
+<!--                >-->
+<!--                  <div class="i-svg:csdn text-lg" />-->
+<!--                </el-link>-->
+<!--                <el-divider direction="vertical" />-->
+<!--                <el-link href="https://www.cnblogs.com/haoxianrui/p/17331952.html" target="_blank">-->
+<!--                  <div class="i-svg:cnblogs text-lg" />-->
+<!--                </el-link>-->
+<!--              </div>-->
+<!--            </div>-->
+
+<!--            &lt;!&ndash; 视频 &ndash;&gt;-->
+<!--            <div>-->
+<!--              <div class="font-bold color-#f76560 text-sm flex items-center">-->
+<!--                <el-icon class="mr-2px"><VideoCamera /></el-icon>-->
+<!--                视频-->
+<!--              </div>-->
+<!--              <div class="mt-3 whitespace-nowrap">-->
+<!--                <el-link href="https://www.bilibili.com/video/BV1eFUuYyEFj" target="_blank">-->
+<!--                  <div class="i-svg:bilibili text-lg" />-->
+<!--                </el-link>-->
+<!--              </div>-->
+<!--            </div>-->
+<!--          </div>-->
         </div>
 
         <!-- 移动端图标区域 -->
@@ -288,61 +288,61 @@
         </el-card>
       </el-col>
       <!-- 最新动态 -->
-      <el-col :xs="24" :span="8">
-        <el-card>
-          <template #header>
-            <div class="flex-x-between">
-              <span class="header-title">最新动态</span>
-              <el-link
-                type="primary"
-                underline="never"
-                href="https://gitee.com/youlaiorg/vue3-element-admin/releases"
-                target="_blank"
-              >
-                完整记录
-                <el-icon class="link-icon"><TopRight /></el-icon>
-              </el-link>
-            </div>
-          </template>
-
-          <el-scrollbar height="400px">
-            <el-timeline class="p-3">
-              <el-timeline-item
-                v-for="(item, index) in vesionList"
-                :key="index"
-                :timestamp="item.date"
-                placement="top"
-                :color="index === 0 ? '#67C23A' : '#909399'"
-                :hollow="index !== 0"
-                size="large"
-              >
-                <div class="version-item" :class="{ 'latest-item': index === 0 }">
-                  <div>
-                    <el-text tag="strong">{{ item.title }}</el-text>
-                    <el-tag v-if="item.tag" :type="index === 0 ? 'success' : 'info'" size="small">
-                      {{ item.tag }}
-                    </el-tag>
-                  </div>
-
-                  <el-text class="version-content">{{ item.content }}</el-text>
-
-                  <div v-if="item.link">
-                    <el-link
-                      :type="index === 0 ? 'primary' : 'info'"
-                      :href="item.link"
-                      target="_blank"
-                      underline="never"
-                    >
-                      详情
-                      <el-icon class="link-icon"><TopRight /></el-icon>
-                    </el-link>
-                  </div>
-                </div>
-              </el-timeline-item>
-            </el-timeline>
-          </el-scrollbar>
-        </el-card>
-      </el-col>
+<!--      <el-col :xs="24" :span="8">-->
+<!--        <el-card>-->
+<!--          <template #header>-->
+<!--            <div class="flex-x-between">-->
+<!--              <span class="header-title">最新动态</span>-->
+<!--              <el-link-->
+<!--                type="primary"-->
+<!--                underline="never"-->
+<!--                href="https://gitee.com/youlaiorg/vue3-element-admin/releases"-->
+<!--                target="_blank"-->
+<!--              >-->
+<!--                完整记录-->
+<!--                <el-icon class="link-icon"><TopRight /></el-icon>-->
+<!--              </el-link>-->
+<!--            </div>-->
+<!--          </template>-->
+
+<!--          <el-scrollbar height="400px">-->
+<!--            <el-timeline class="p-3">-->
+<!--              <el-timeline-item-->
+<!--                v-for="(item, index) in vesionList"-->
+<!--                :key="index"-->
+<!--                :timestamp="item.date"-->
+<!--                placement="top"-->
+<!--                :color="index === 0 ? '#67C23A' : '#909399'"-->
+<!--                :hollow="index !== 0"-->
+<!--                size="large"-->
+<!--              >-->
+<!--                <div class="version-item" :class="{ 'latest-item': index === 0 }">-->
+<!--                  <div>-->
+<!--                    <el-text tag="strong">{{ item.title }}</el-text>-->
+<!--                    <el-tag v-if="item.tag" :type="index === 0 ? 'success' : 'info'" size="small">-->
+<!--                      {{ item.tag }}-->
+<!--                    </el-tag>-->
+<!--                  </div>-->
+
+<!--                  <el-text class="version-content">{{ item.content }}</el-text>-->
+
+<!--                  <div v-if="item.link">-->
+<!--                    <el-link-->
+<!--                      :type="index === 0 ? 'primary' : 'info'"-->
+<!--                      :href="item.link"-->
+<!--                      target="_blank"-->
+<!--                      underline="never"-->
+<!--                    >-->
+<!--                      详情-->
+<!--                      <el-icon class="link-icon"><TopRight /></el-icon>-->
+<!--                    </el-link>-->
+<!--                  </div>-->
+<!--                </div>-->
+<!--              </el-timeline-item>-->
+<!--            </el-timeline>-->
+<!--          </el-scrollbar>-->
+<!--        </el-card>-->
+<!--      </el-col>-->
     </el-row>
   </div>
 </template>

+ 620 - 0
src/views/operationsManage/data-kanban/index.vue

@@ -0,0 +1,620 @@
+<template>
+  <div class="app-container h-full flex flex-1 flex-col overflow-auto">
+    <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+      <el-tab-pane label="平台数据" name="first">
+        <!-- 实时数据 -->
+        <el-card shadow="hover">
+          <div class="flex items-center gap-10px">
+            <div class="flex items-center gap-6px">
+              <span class="font-bold text-24px">实时数据</span>
+              <el-icon color="#4080ff" size="20" class="cursor-pointer" @click="refreshData">
+                <Refresh />
+              </el-icon>
+            </div>
+            <div class="font-400 text-14px text-#949494">{{ lastUpdateTime }} 更新</div>
+          </div>
+          <div class="mt-10px flex flex-wrap gap-16px">
+            <DataCard
+              v-for="item in totalDataList"
+              :key="item.type"
+              :label="item.label"
+              :icon="item.icon"
+              :value="item.value"
+              :unit="item.unit"
+            />
+          </div>
+        </el-card>
+
+        <div class="h-16px"></div>
+
+        <!-- 今日实时数据 -->
+        <el-card shadow="hover">
+          <div class="flex items-center gap-10px">
+            <div class="flex items-center gap-6px">
+              <span class="font-bold text-24px">今日实时数据</span>
+              <el-icon color="#4080ff" size="20" class="cursor-pointer" @click="refreshData">
+                <Refresh />
+              </el-icon>
+            </div>
+            <div class="font-400 text-14px text-#949494">{{ lastUpdateTime }} 更新</div>
+          </div>
+          <div class="mt-10px flex flex-wrap gap-16px">
+            <DataCard
+              v-for="item in todayDataList"
+              :key="item.type"
+              :label="item.label"
+              :icon="item.icon"
+              :value="item.value"
+              :unit="item.unit"
+            />
+          </div>
+        </el-card>
+
+        <div class="h-16px"></div>
+
+        <!-- 所有站点充电度数 日时段对比趋势 -->
+        <el-card shadow="hover">
+          <div class="flex items-center gap-16px mb-16px">
+            <span class="font-bold text-18px">所有站点充电度数 日时段对比趋势</span>
+          </div>
+          <div class="flex items-center gap-24px mb-16px">
+            <div class="flex items-center gap-8px">
+              <span class="w-20px h-20px bg-#4868FE rounded"></span>
+              <span class="text-14px">今日</span>
+            </div>
+            <div class="flex items-center gap-8px">
+              <span class="w-20px h-20px bg-#0CD489 rounded"></span>
+              <el-date-picker
+                v-model="selectedCompareDate"
+                type="date"
+                placeholder="选择对比日期"
+                format="MM.DD"
+                value-format="YYYY-MM-DD"
+                size="small"
+                style="width: 120px"
+                :disabled-date="disableCompareDate"
+                :clearable="false"
+              />
+            </div>
+          </div>
+          <ECharts :options="hourlyTrendChartOptions" height="350px" />
+        </el-card>
+
+        <div class="h-16px"></div>
+
+        <!-- 历史营业数据(面积图) -->
+        <el-card shadow="hover">
+          <div class="flex items-center justify-between mb-16px">
+            <span class="font-bold text-18px">历史营业数据</span>
+          </div>
+          <div class="flex items-center justify-between flex-wrap gap-16px mb-16px">
+            <div class="flex items-center gap-16px">
+              <div class="flex items-center gap-8px">
+                <span class="text-14px text-#666">时间维度</span>
+                <el-select v-model="historyTimeType" style="width: 100px" size="small">
+                  <el-option label="日趋势" value="day" />
+                  <el-option label="月趋势" value="month" />
+                </el-select>
+              </div>
+              <el-date-picker
+                v-model="historyDateValue"
+                :type="historyTimeType === 'day' ? 'month' : 'year'"
+                :placeholder="historyTimeType === 'day' ? '选择月份' : '选择年份'"
+                :format="historyTimeType === 'day' ? 'YYYY-MM' : 'YYYY'"
+                :value-format="historyTimeType === 'day' ? 'YYYY-MM' : 'YYYY'"
+                size="small"
+                style="width: 140px"
+              />
+            </div>
+            <div class="flex items-center gap-8px">
+              <span class="text-14px text-#666">指标筛选</span>
+              <el-radio-group v-model="historyMetric" size="small">
+                <el-radio-button value="chargeDegree">充电度数</el-radio-button>
+                <el-radio-button value="chargeAmount">充电金额</el-radio-button>
+                <el-radio-button value="validOrder">有效订单</el-radio-button>
+                <el-radio-button value="registerUser">注册用户</el-radio-button>
+              </el-radio-group>
+            </div>
+          </div>
+          <ECharts :options="historyAreaChartOptions" height="350px" />
+        </el-card>
+
+        <div class="h-16px"></div>
+
+        <!-- 历史营业数据(表格) -->
+        <el-card shadow="hover">
+          <div class="flex items-center justify-between flex-wrap gap-16px mb-16px">
+            <div class="flex items-center gap-8px">
+              <el-radio-group v-model="tableDataType" size="small">
+                <el-radio-button value="degree">按充电度数</el-radio-button>
+                <el-radio-button value="order">按有效订单</el-radio-button>
+              </el-radio-group>
+            </div>
+            <div class="flex items-center gap-8px flex-wrap">
+              <el-radio-group v-model="tableDateRange" size="small">
+                <el-radio-button value="yesterday">昨天</el-radio-button>
+                <el-radio-button value="week">近七天</el-radio-button>
+                <el-radio-button value="month">近30天</el-radio-button>
+              </el-radio-group>
+              <el-date-picker
+                v-model="tableStartDate"
+                type="date"
+                placeholder="开始日期"
+                format="YYYY-MM-DD"
+                value-format="YYYY-MM-DD"
+                size="small"
+                style="width: 130px"
+              />
+              <span class="text-#999">至</span>
+              <el-date-picker
+                v-model="tableEndDate"
+                type="date"
+                placeholder="结束日期"
+                format="YYYY-MM-DD"
+                value-format="YYYY-MM-DD"
+                size="small"
+                style="width: 130px"
+              />
+              <span class="text-14px text-#999 ml-16px">已选时间: {{ selectedDateRange }}</span>
+            </div>
+          </div>
+
+          <div class="flex gap-24px flex-wrap">
+            <!-- 热门充电站 -->
+            <div class="flex-1 min-w-400px">
+              <div class="font-bold text-16px mb-12px">热门充电站</div>
+              <el-table :data="hotStationData" border stripe size="small">
+                <el-table-column type="index" label="序号" width="60" align="center" />
+                <el-table-column prop="name" label="电站名称" min-width="180" />
+                <el-table-column
+                  prop="value"
+                  :label="tableDataType === 'degree' ? '充电度数' : '有效订单'"
+                  width="120"
+                  align="right"
+                />
+              </el-table>
+              <div class="flex items-center justify-between mt-12px">
+                <span class="text-12px text-#999">共{{ hotStationTotal }}条</span>
+                <el-pagination
+                  v-model:current-page="hotCurrentPage"
+                  v-model:page-size="hotPageSize"
+                  :page-sizes="[5, 10, 20]"
+                  :total="hotStationTotal"
+                  size="small"
+                  layout="sizes, prev, pager, next, jumper"
+                />
+              </div>
+            </div>
+
+            <!-- 波动充电站 -->
+            <div class="flex-1 min-w-400px">
+              <div class="font-bold text-16px mb-12px">波动充电站</div>
+              <el-table :data="fluctuationStationData" border stripe size="small">
+                <el-table-column type="index" label="序号" width="60" align="center" />
+                <el-table-column prop="name" label="电站名称" min-width="180" />
+                <el-table-column prop="rate" label="涨幅 | 跌幅" width="120" align="right">
+                  <template #default="{ row }">
+                    <span :class="row.rate >= 0 ? 'text-#F56C6C' : 'text-#67C23A'">
+                      <el-icon v-if="row.rate >= 0"><CaretTop /></el-icon>
+                      <el-icon v-else><CaretBottom /></el-icon>
+                      {{ Math.abs(row.rate).toFixed(2) }}%
+                    </span>
+                  </template>
+                </el-table-column>
+              </el-table>
+              <div class="flex items-center justify-between mt-12px">
+                <span class="text-12px text-#999">共{{ fluctuationStationTotal }}条</span>
+                <el-pagination
+                  v-model:current-page="fluctuationCurrentPage"
+                  v-model:page-size="fluctuationPageSize"
+                  :page-sizes="[5, 10, 20]"
+                  :total="fluctuationStationTotal"
+                  size="small"
+                  layout="sizes, prev, pager, next, jumper"
+                />
+              </div>
+            </div>
+          </div>
+        </el-card>
+
+        <div class="h-16px"></div>
+
+        <!-- 用户流失率 -->
+        <el-card shadow="hover">
+          <div class="font-bold text-18px mb-24px">用户流失率</div>
+          <div class="flex items-center gap-48px flex-wrap">
+            <div class="flex items-center gap-200px bg-#F3F9FF rounded-8px p-32px">
+              <div>
+                <div class="text-14px text-#666 mb-8px">近七天 流失率</div>
+                <div class="font-bold text-32px text-#333">{{ lossRate.sevenDay }}%</div>
+              </div>
+              <el-button type="primary" link @click="downloadReport('sevenDay')">
+                <el-icon><Download /></el-icon>
+                下载表格
+              </el-button>
+            </div>
+            <div class="flex items-center gap-200px bg-#F3F9FF rounded-8px p-32px">
+              <div>
+                <div class="text-14px text-#666 mb-8px">近1个月 流失率</div>
+                <div class="font-bold text-32px text-#333">{{ lossRate.oneMonth }}%</div>
+              </div>
+              <el-button type="primary" link @click="downloadReport('oneMonth')">
+                <el-icon><Download /></el-icon>
+                下载表格
+              </el-button>
+            </div>
+            <div class="flex items-center gap-200px bg-#F3F9FF rounded-8px p-32px">
+              <div>
+                <div class="text-14px text-#666 mb-8px">近3个月 流失率</div>
+                <div class="font-bold text-32px text-#333">{{ lossRate.threeMonth }}%</div>
+              </div>
+              <el-button type="primary" link @click="downloadReport('threeMonth')">
+                <el-icon><Download /></el-icon>
+                下载表格
+              </el-button>
+            </div>
+          </div>
+        </el-card>
+      </el-tab-pane>
+      <el-tab-pane label="场站方数据" name="second">场站方数据内容</el-tab-pane>
+      <el-tab-pane label="销售方数据" name="third">销售方数据内容</el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, computed, onMounted } from "vue";
+import { dayjs, ElMessage } from "element-plus";
+import { CaretTop, CaretBottom, Download, Refresh } from "@element-plus/icons-vue";
+import type { TabsPaneContext } from "element-plus";
+import DataCard from "./components/DataCard.vue";
+
+const activeName = ref("first");
+
+// 最后更新时间
+const lastUpdateTime = ref(dayjs().format("MM-DD HH:mm"));
+
+// 对比日期选择
+const selectedCompareDate = ref(dayjs().subtract(1, "day").format("YYYY-MM-DD"));
+// 对比日期显示格式
+const compareDate = computed(() => dayjs(selectedCompareDate.value).format("MM.DD"));
+
+// 禁用日期:只允许选择昨天之前的15天(含昨天)
+const disableCompareDate = (date: Date) => {
+  const today = dayjs().startOf("day");
+  const yesterday = today.subtract(1, "day");
+  const fifteenDaysAgo = today.subtract(15, "day");
+  const currentDate = dayjs(date);
+  // 禁用今天及之后的日期,以及15天之前的日期
+  return currentDate.isAfter(yesterday) || currentDate.isBefore(fifteenDaysAgo);
+};
+
+// 刷新数据
+const refreshData = () => {
+  lastUpdateTime.value = dayjs().format("MM-DD HH:mm");
+  ElMessage.success("数据已刷新");
+};
+
+// 数据指标配置
+const dataMetrics = [
+  { type: "cdds", label: "充电度数", icon: "cdds.png", unit: "度" },
+  { type: "cdje", label: "充电金额", icon: "cdje.png", unit: "元" },
+  { type: "dkqje", label: "抵扣券金额", icon: "dkqje.png", unit: "元" },
+  { type: "fwfje", label: "服务费金额", icon: "fwfje.png", unit: "元" },
+  { type: "tkje", label: "退款金额", icon: "tkje.png", unit: "元" },
+  { type: "sfje", label: "实付金额", icon: "sfje.png", unit: "元" },
+  { type: "sdje", label: "首单金额", icon: "sdje.png", unit: "元" },
+  { type: "yhqjm", label: "优惠券减免", icon: "yhqjm.png", unit: "元" },
+  { type: "qyzxjj", label: "企业专享价减", icon: "qyzxjj.png", unit: "元" },
+  { type: "fxyj", label: "分销佣金", icon: "fxyj.png", unit: "元" },
+];
+
+// 总数据列表
+const totalDataList = computed(() =>
+  dataMetrics.map((item) => ({
+    ...item,
+    label: `总${item.label}`,
+    value: "198,708.45",
+  }))
+);
+
+// 今日数据列表
+const todayDataList = computed(() =>
+  dataMetrics.map((item) => ({
+    ...item,
+    label: `今日${item.label}`,
+    value: "198,708.45",
+  }))
+);
+
+// ==================== 日时段对比趋势图表 ====================
+const hourlyTrendChartOptions = computed(() => {
+  const hours = Array.from({ length: 24 }, (_, i) => i);
+  // 模拟今日数据
+  const todayData = [
+    50, 80, 120, 150, 200, 280, 350, 450, 520, 580, 620, 580, 520, 480, 450, 420, 400, 450, 500,
+    480, 420, 350, 200, 100,
+  ];
+  // 模拟昨日数据
+  const yesterdayData = [
+    40, 70, 100, 130, 180, 250, 320, 420, 480, 550, 600, 560, 500, 460, 430, 400, 380, 420, 470,
+    450, 400, 320, 180, 80,
+  ];
+
+  return {
+    tooltip: {
+      trigger: "axis",
+      axisPointer: {
+        type: "cross",
+      },
+      formatter: (params: any) => {
+        let result = `时间: ${params[0].axisValue}:00:00<br/>`;
+        params.forEach((item: any) => {
+          result += `${item.marker} ${item.seriesName}: ${item.value}<br/>`;
+        });
+        return result;
+      },
+    },
+    grid: {
+      left: "3%",
+      right: "4%",
+      bottom: "3%",
+      containLabel: true,
+    },
+    xAxis: {
+      type: "category",
+      boundaryGap: false,
+      data: hours,
+      axisLabel: {
+        formatter: "{value}",
+      },
+    },
+    yAxis: {
+      type: "value",
+      splitLine: {
+        lineStyle: {
+          type: "dashed",
+        },
+      },
+    },
+    series: [
+      {
+        name: "今日",
+        type: "line",
+        data: todayData,
+        smooth: true,
+        symbol: "circle",
+        symbolSize: 6,
+        areaStyle: {
+          color: {
+            type: "linear",
+            x: 0,
+            y: 0,
+            x2: 0,
+            y2: 1,
+            colorStops: [
+              { offset: 0, color: "rgba(72, 104, 254, 0.3)" },
+              { offset: 1, color: "rgba(72, 104, 254, 0.05)" },
+            ],
+          },
+        },
+        itemStyle: {
+          color: "#4868FE",
+        },
+        lineStyle: {
+          color: "#4868FE",
+          width: 2,
+        },
+      },
+      {
+        name: compareDate.value,
+        type: "line",
+        data: yesterdayData,
+        smooth: true,
+        symbol: "circle",
+        symbolSize: 6,
+        areaStyle: {
+          color: {
+            type: "linear",
+            x: 0,
+            y: 0,
+            x2: 0,
+            y2: 1,
+            colorStops: [
+              { offset: 0, color: "rgba(12, 212, 137, 0.3)" },
+              { offset: 1, color: "rgba(12, 212, 137, 0.05)" },
+            ],
+          },
+        },
+        itemStyle: {
+          color: "#0CD489",
+        },
+        lineStyle: {
+          color: "#0CD489",
+          width: 2,
+        },
+      },
+    ],
+  };
+});
+
+// ==================== 历史营业数据(面积图) ====================
+const historyTimeType = ref("day");
+const historyDateValue = ref(dayjs().format("YYYY-MM"));
+const historyMetric = ref("chargeDegree");
+
+// 监听时间维度变化,重置日期值
+watch(historyTimeType, (newType) => {
+  if (newType === "day") {
+    historyDateValue.value = dayjs().format("YYYY-MM");
+  } else {
+    historyDateValue.value = dayjs().format("YYYY");
+  }
+});
+
+const historyAreaChartOptions = computed(() => {
+  let dates: string[];
+  let mockData: number[];
+
+  if (historyTimeType.value === "day") {
+    // 日趋势:显示月份中的每一天
+    const daysInMonth = dayjs(historyDateValue.value).daysInMonth();
+    dates = Array.from({ length: daysInMonth }, (_, i) =>
+      dayjs(historyDateValue.value).startOf("month").add(i, "day").format("MM.DD")
+    );
+    mockData = Array.from({ length: daysInMonth }, () => Math.floor(Math.random() * 5000) + 2000);
+  } else {
+    // 月趋势:显示年份中的12个月
+    dates = Array.from({ length: 12 }, (_, i) => `${i + 1}月`);
+    mockData = Array.from({ length: 12 }, () => Math.floor(Math.random() * 50000) + 20000);
+  }
+
+  const metricLabels: Record<string, string> = {
+    chargeDegree: "充电度数",
+    chargeAmount: "充电金额",
+    validOrder: "有效订单",
+    registerUser: "注册用户",
+  };
+
+  return {
+    tooltip: {
+      trigger: "axis",
+      axisPointer: {
+        type: "cross",
+      },
+    },
+    grid: {
+      left: "3%",
+      right: "4%",
+      bottom: "3%",
+      containLabel: true,
+    },
+    xAxis: {
+      type: "category",
+      boundaryGap: false,
+      data: dates,
+    },
+    yAxis: {
+      type: "value",
+      splitLine: {
+        lineStyle: {
+          type: "dashed",
+        },
+      },
+    },
+    series: [
+      {
+        name: metricLabels[historyMetric.value],
+        type: "line",
+        data: mockData,
+        smooth: true,
+        areaStyle: {
+          color: {
+            type: "linear",
+            x: 0,
+            y: 0,
+            x2: 0,
+            y2: 1,
+            colorStops: [
+              { offset: 0, color: "rgba(64, 158, 255, 0.3)" },
+              { offset: 1, color: "rgba(64, 158, 255, 0.05)" },
+            ],
+          },
+        },
+        itemStyle: {
+          color: "#409EFF",
+        },
+        lineStyle: {
+          color: "#409EFF",
+          width: 2,
+        },
+      },
+    ],
+  };
+});
+
+// ==================== 历史营业数据(表格) ====================
+const tableDataType = ref("degree");
+const tableDateRange = ref("week");
+const tableStartDate = ref("");
+const tableEndDate = ref("");
+
+// 热门充电站分页
+const hotCurrentPage = ref(1);
+const hotPageSize = ref(5);
+const hotStationTotal = ref(50);
+
+// 波动充电站分页
+const fluctuationCurrentPage = ref(1);
+const fluctuationPageSize = ref(5);
+const fluctuationStationTotal = ref(50);
+
+// 选中的日期范围显示
+const selectedDateRange = computed(() => {
+  if (tableStartDate.value && tableEndDate.value) {
+    return `${tableStartDate.value} 至 ${tableEndDate.value}`;
+  }
+  const today = dayjs();
+  switch (tableDateRange.value) {
+    case "yesterday":
+      return today.subtract(1, "day").format("YYYY-MM-DD");
+    case "week":
+      return `${today.subtract(7, "day").format("YYYY-MM-DD")} 至 ${today.format("YYYY-MM-DD")}`;
+    case "month":
+      return `${today.subtract(30, "day").format("YYYY-MM-DD")} 至 ${today.format("YYYY-MM-DD")}`;
+    default:
+      return "";
+  }
+});
+
+// 热门充电站数据
+const hotStationData = computed(() => [
+  { name: "小关停车场B区-小站", value: 100.01 },
+  { name: "延安西路智慧停车楼", value: 99.01 },
+  { name: "花果园立交桥南广场停车场", value: 97.01 },
+  { name: "花果园立交北广场停车场", value: 97 },
+  { name: "轩宇智慧停车场", value: 96 },
+]);
+
+// 波动充电站数据
+const fluctuationStationData = computed(() => [
+  { name: "小关停车场B区-小站", rate: 6.29 },
+  { name: "延安西路智慧停车楼", rate: 5.34 },
+  { name: "花果园立交桥南广场停车场", rate: 4.21 },
+  { name: "花果园立交北广场停车场", rate: -3.52 },
+  { name: "轩宇智慧停车场", rate: -1.98 },
+]);
+
+// ==================== 用户流失率 ====================
+const lossRate = ref({
+  sevenDay: "59.99",
+  oneMonth: "70.12",
+  threeMonth: "70.12",
+});
+
+// 下载报表
+const downloadReport = (type: string) => {
+  const typeLabels: Record<string, string> = {
+    sevenDay: "近七天",
+    oneMonth: "近1个月",
+    threeMonth: "近3个月",
+  };
+  ElMessage.success(`正在下载${typeLabels[type]}流失率报表...`);
+};
+
+const handleClick = (tab: TabsPaneContext, event: Event) => {
+  console.log(tab, event);
+};
+
+onMounted(() => {
+  // 初始化数据
+});
+</script>
+
+<style scoped lang="scss">
+.demo-tabs {
+  :deep(.el-tabs__content) {
+    padding: 0;
+  }
+}
+</style>

+ 0 - 2
src/views/userManage/user-info/index.vue

@@ -165,8 +165,6 @@
 </template>
 
 <script setup lang="ts">
-import UserOrderInfoAPI from "@/api/orderManage/user-order-info-api";
-
 defineOptions({ name: "UserInfo" });
 
 import UserInfoAPI, {