Jelajahi Sumber

修改首页

hurx 1 bulan lalu
induk
melakukan
7156b6f663
1 mengubah file dengan 309 tambahan dan 116 penghapusan
  1. 309 116
      src/views/index.vue

+ 309 - 116
src/views/index.vue

@@ -1,147 +1,340 @@
 <template>
   <div class="app-container home">
-    <!-- <el-divider /> -->
-    <div class="index-style">
-      <div class="typewriter-container">
-        <span v-for="(char, index) in 'welcome!'" :key="index" :style="{ animationDelay: `${index * 0.5}s` }" class="typewriter-char">{{
-          char
-        }}</span>
-      </div>
-    </div>
+    <!-- 数据统计卡片 -->
+    <el-row :gutter="20" class="panel-group">
+      <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+        <div class="card-panel">
+          <div class="card-panel-icon-wrapper icon-blue">
+            <el-icon><ShoppingCart /></el-icon>
+          </div>
+          <div class="card-panel-description">
+            <div class="card-panel-text">今日新增订单</div>
+            <div class="card-panel-num">156</div>
+          </div>
+        </div>
+      </el-col>
+      <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+        <div class="card-panel">
+          <div class="card-panel-icon-wrapper icon-green">
+            <el-icon><Money /></el-icon>
+          </div>
+          <div class="card-panel-description">
+            <div class="card-panel-text">本周销售总额</div>
+            <div class="card-panel-num">¥ 45,600</div>
+          </div>
+        </div>
+      </el-col>
+      <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+        <div class="card-panel">
+          <div class="card-panel-icon-wrapper icon-orange">
+            <el-icon><Van /></el-icon>
+          </div>
+          <div class="card-panel-description">
+            <div class="card-panel-text">待发货数量</div>
+            <div class="card-panel-num">32</div>
+          </div>
+        </div>
+      </el-col>
+      <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
+        <div class="card-panel">
+          <div class="card-panel-icon-wrapper icon-purple">
+            <el-icon><Goods /></el-icon>
+          </div>
+          <div class="card-panel-description">
+            <div class="card-panel-text">在售商品数</div>
+            <div class="card-panel-num">1,245</div>
+          </div>
+        </div>
+      </el-col>
+    </el-row>
+
+    <!-- 图表和列表 -->
+    <el-row :gutter="20" class="chart-container">
+      <!-- 折线图 -->
+      <el-col :xs="24" :sm="24" :lg="16">
+        <el-card shadow="hover">
+          <template #header>
+            <div class="card-header">
+              <span>近期订单与发货量走势</span>
+            </div>
+          </template>
+          <div ref="lineChartRef" style="height: 350px"></div>
+        </el-card>
+      </el-col>
+
+      <!-- 饼图 -->
+      <el-col :xs="24" :sm="24" :lg="8">
+        <el-card shadow="hover">
+          <template #header>
+            <div class="card-header">
+              <span>商品类型销售占比</span>
+            </div>
+          </template>
+          <div ref="pieChartRef" style="height: 350px"></div>
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <!-- 最近订单列表 -->
+    <el-row :gutter="20" class="list-container">
+      <el-col :span="24">
+        <el-card shadow="hover">
+          <template #header>
+            <div class="card-header">
+              <span>最新发货动态</span>
+            </div>
+          </template>
+          <el-table :data="recentOrders" style="width: 100%" stripe border>
+            <el-table-column prop="orderNo" label="订单编号" width="180" />
+            <el-table-column prop="productName" label="商品名称" />
+            <el-table-column prop="amount" label="订单金额" width="120" />
+            <el-table-column prop="customer" label="收货人" width="120" />
+            <el-table-column prop="status" label="发货状态" width="100">
+              <template #default="scope">
+                <el-tag :type="scope.row.status === '已发货' ? 'success' : 'warning'">{{ scope.row.status }}</el-tag>
+              </template>
+            </el-table-column>
+            <el-table-column prop="date" label="时间" width="160" />
+          </el-table>
+        </el-card>
+      </el-col>
+    </el-row>
   </div>
 </template>
 
-<script setup name="Index" lang="ts">
-const goTarget = (url: string) => {
-  window.open(url, '__blank');
-};
-</script>
+<script setup lang="ts" name="Index">
+import { ref, onMounted, onUnmounted, nextTick } from 'vue';
+import { ShoppingCart, Money, Van, Goods } from '@element-plus/icons-vue';
+import * as echarts from 'echarts';
 
-<style lang="scss" scoped>
-.home {
-  blockquote {
-    padding: 10px 20px;
-    margin: 0 0 20px;
-    font-size: 17.5px;
-    border-left: 5px solid #eee;
-  }
-  hr {
-    margin-top: 20px;
-    margin-bottom: 20px;
-    border: 0;
-    border-top: 1px solid #eee;
-  }
-  .col-item {
-    margin-bottom: 20px;
-  }
+const lineChartRef = ref<HTMLElement | null>(null);
+const pieChartRef = ref<HTMLElement | null>(null);
 
-  ul {
-    padding: 0;
-    margin: 0;
-  }
+let lineChart: echarts.ECharts | null = null;
+let pieChart: echarts.ECharts | null = null;
 
-  font-family: 'open sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
-  font-size: 13px;
-  color: #676a6c;
-  overflow-x: hidden;
+// Mock 列表数据
+const recentOrders = ref([
+  { orderNo: 'ORD-20261015-001', productName: '高级人体工学椅', amount: '¥899.00', customer: '张三', status: '已发货', date: '2026-01-15 10:23:45' },
+  { orderNo: 'ORD-20261015-002', productName: '无线机械键盘', amount: '¥450.00', customer: '李四', status: '待发货', date: '2026-02-15 11:05:12' },
+  {
+    orderNo: 'ORD-20261015-003',
+    productName: '27英寸4K显示器',
+    amount: '¥1,299.00',
+    customer: '王五',
+    status: '已发货',
+    date: '2026-01-18 15:30:00'
+  },
+  { orderNo: 'ORD-20261015-004', productName: '降噪蓝牙耳机', amount: '¥699.00', customer: '赵六', status: '已发货', date: '2026-01-16 09:15:22' },
+  { orderNo: 'ORD-20261015-005', productName: '智能桌面护眼灯', amount: '¥199.00', customer: '钱七', status: '待发货', date: '2026-01-13 18:45:30' }
+]);
 
-  ul {
-    list-style-type: none;
-  }
+// 初始化折线图
+const initLineChart = () => {
+  if (!lineChartRef.value) return;
+  lineChart = echarts.init(lineChartRef.value);
+  const option = {
+    tooltip: { trigger: 'axis' },
+    legend: { data: ['订单量', '发货量'] },
+    grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
+    xAxis: {
+      type: 'category',
+      boundaryGap: false,
+      data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
+    },
+    yAxis: { type: 'value' },
+    series: [
+      {
+        name: '订单量',
+        type: 'line',
+        itemStyle: { color: '#409EFF' },
+        areaStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: 'rgba(64,158,255,0.3)' },
+            { offset: 1, color: 'rgba(64,158,255,0)' }
+          ])
+        },
+        data: [120, 132, 101, 134, 90, 230, 210]
+      },
+      {
+        name: '发货量',
+        type: 'line',
+        itemStyle: { color: '#67C23A' },
+        areaStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: 'rgba(103,194,58,0.3)' },
+            { offset: 1, color: 'rgba(103,194,58,0)' }
+          ])
+        },
+        data: [110, 120, 95, 120, 80, 200, 190]
+      }
+    ]
+  };
+  lineChart.setOption(option);
+};
 
-  h4 {
-    margin-top: 0px;
-  }
+// 初始化饼图
+const initPieChart = () => {
+  if (!pieChartRef.value) return;
+  pieChart = echarts.init(pieChartRef.value);
+  const option = {
+    tooltip: { trigger: 'item' },
+    legend: { top: 'bottom' },
+    series: [
+      {
+        name: '销售占比',
+        type: 'pie',
+        radius: ['40%', '70%'],
+        avoidLabelOverlap: false,
+        itemStyle: {
+          borderRadius: 10,
+          borderColor: '#fff',
+          borderWidth: 2
+        },
+        label: { show: false, position: 'center' },
+        emphasis: {
+          label: { show: true, fontSize: '18', fontWeight: 'bold' }
+        },
+        labelLine: { show: false },
+        data: [
+          { value: 1048, name: '日用百货' },
+          { value: 735, name: '生鲜食品' },
+          { value: 580, name: '电子数码' },
+          { value: 484, name: '家用电器' },
+          { value: 300, name: '服饰鞋包' }
+        ],
+        color: ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C', '#909399']
+      }
+    ]
+  };
+  pieChart.setOption(option);
+};
 
-  h2 {
-    margin-top: 10px;
-    font-size: 26px;
-    font-weight: 100;
-  }
+// 监听窗口大小变化以重绘图表
+const handleResize = () => {
+  lineChart?.resize();
+  pieChart?.resize();
+};
 
-  p {
-    margin-top: 10px;
+onMounted(() => {
+  nextTick(() => {
+    initLineChart();
+    initPieChart();
+    window.addEventListener('resize', handleResize);
+  });
+});
 
-    b {
-      font-weight: 700;
-    }
-  }
+onUnmounted(() => {
+  window.removeEventListener('resize', handleResize);
+  lineChart?.dispose();
+  pieChart?.dispose();
+});
+</script>
 
-  .update-log {
-    ol {
-      display: block;
-      list-style-type: decimal;
-      margin-block-start: 1em;
-      margin-block-end: 1em;
-      margin-inline-start: 0;
-      margin-inline-end: 0;
-      padding-inline-start: 40px;
-    }
+<style lang="scss" scoped>
+.app-container {
+  padding: 20px;
+  background-color: #f0f2f5;
+  min-height: calc(100vh - 84px);
+}
+
+.panel-group {
+  margin-bottom: 20px;
+
+  .card-panel-col {
+    margin-bottom: 20px;
   }
-  .index-style {
-    font-size: 48px;
-    font-weight: bold;
-    letter-spacing: 15px;
+
+  .card-panel {
+    height: 108px;
+    cursor: pointer;
+    font-size: 12px;
+    position: relative;
+    overflow: hidden;
+    color: #666;
+    background: #fff;
+    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
+    border-radius: 8px;
     display: flex;
-    justify-content: center;
     align-items: center;
-    height: 300px;
-    background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
-    border-radius: 10px;
-    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
+    transition: all 0.3s ease;
 
-    .typewriter-container {
-      display: flex;
-    }
+    &:hover {
+      transform: translateY(-5px);
+      box-shadow: 0 15px 30px rgba(0, 0, 0, 0.1);
 
-    .typewriter-char {
-      opacity: 0;
-      transform: translateY(20px) rotate(-5deg);
-      animation:
-        typewriter-animation 0.8s ease forwards,
-        pulse 2s ease-in-out infinite 1s;
-      color: #2d8cf0;
-      text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
-      transition: color 0.3s ease;
-
-      &:hover {
-        color: #f06292;
-        transform: scale(1.1);
-        animation-play-state: paused;
+      .card-panel-icon-wrapper {
+        color: #fff;
+      }
+      .icon-blue {
+        background: #409eff;
+      }
+      .icon-green {
+        background: #67c23a;
+      }
+      .icon-orange {
+        background: #e6a23c;
+      }
+      .icon-purple {
+        background: #b050e6;
       }
     }
-  }
 
-  @keyframes typewriter-animation {
-    0% {
-      opacity: 0;
-      transform: translateY(20px) rotate(-5deg);
+    .card-panel-icon-wrapper {
+      margin: 14px 0 0 14px;
+      padding: 16px;
+      transition: all 0.3s ease-out;
+      border-radius: 6px;
+      font-size: 48px;
     }
-    50% {
-      opacity: 0.5;
-      transform: translateY(10px) rotate(-2deg);
+
+    .icon-blue {
+      color: #409eff;
     }
-    100% {
-      opacity: 1;
-      transform: translateY(0) rotate(0deg);
+    .icon-green {
+      color: #67c23a;
     }
-  }
-
-  @keyframes pulse {
-    0% {
-      text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
-      transform: scale(1);
+    .icon-orange {
+      color: #e6a23c;
     }
-    50% {
-      text-shadow:
-        0 0 15px rgba(45, 140, 240, 0.8),
-        0 0 30px rgba(45, 140, 240, 0.4);
-      transform: scale(1.05);
+    .icon-purple {
+      color: #b050e6;
     }
-    100% {
-      text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
-      transform: scale(1);
+
+    .card-panel-description {
+      margin-left: auto;
+      margin-right: 20px;
+      font-weight: bold;
+      text-align: right;
+
+      .card-panel-text {
+        line-height: 18px;
+        color: #8c8c8c;
+        font-size: 16px;
+        margin-bottom: 12px;
+      }
+
+      .card-panel-num {
+        font-size: 24px;
+        color: #333;
+      }
     }
   }
 }
+
+.chart-container {
+  margin-bottom: 20px;
+}
+
+.card-header {
+  font-weight: bold;
+  color: #333;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.list-container {
+  margin-bottom: 20px;
+}
 </style>