Explorar o código

feat: 新增8个数据分析报表(销售分析、利润分析、库存库龄、客户分析、物流报表、渠道绩效、采购报表、营销报表)

docker hai 2 meses
pai
achega
24a7978e37

+ 9 - 1
src/router/menu.ts

@@ -19,7 +19,15 @@ export const menuGroups: MenuGroup[] = [
     title: '数据与报表',
     items: [
       { key: 'report-dashboard', title: '运营看板', path: '/report/dashboard', roles: ['admin', 'manager', 'operator', 'procurement'] },
-      { key: 'report-center', title: '报表中心', path: '/report/center', roles: ['admin', 'manager', 'operator', 'procurement'] }
+      { key: 'report-center', title: '报表中心', path: '/report/center', roles: ['admin', 'manager', 'operator', 'procurement'] },
+      { key: 'sales-analysis', title: '销售分析', path: '/report/sales-analysis', roles: ['admin', 'manager', 'operator'] },
+      { key: 'profit-analysis', title: '利润分析', path: '/report/profit-analysis', roles: ['admin', 'manager', 'finance'] },
+      { key: 'inventory-age', title: '库存库龄分析', path: '/report/inventory-age', roles: ['admin', 'manager', 'procurement', 'warehouse'] },
+      { key: 'customer-analysis', title: '客户分析', path: '/report/customer-analysis', roles: ['admin', 'manager', 'operator'] },
+      { key: 'logistics-report', title: '物流报表', path: '/report/logistics-report', roles: ['admin', 'manager', 'warehouse'] },
+      { key: 'channel-performance', title: '渠道绩效', path: '/report/channel-performance', roles: ['admin', 'manager', 'operator'] },
+      { key: 'procurement-report', title: '采购报表', path: '/report/procurement-report', roles: ['admin', 'manager', 'procurement'] },
+      { key: 'marketing-report', title: '营销报表', path: '/report/marketing-report', roles: ['admin', 'manager', 'operator'] }
     ]
   },
   {

+ 48 - 0
src/router/routes.ts

@@ -268,6 +268,54 @@ export const routes: RouteRecordRaw[] = [
         name: 'system-department',
         component: () => import('@/views/system/DepartmentView.vue'),
         meta: { title: '部门管理', pageKey: 'system-department', roles: ['admin'] }
+      },
+      {
+        path: '/report/sales-analysis',
+        name: 'sales-analysis',
+        component: () => import('@/views/report/SalesAnalysisView.vue'),
+        meta: { title: '销售分析', pageKey: 'sales-analysis', roles: ['admin', 'manager', 'operator'] }
+      },
+      {
+        path: '/report/profit-analysis',
+        name: 'profit-analysis',
+        component: () => import('@/views/report/ProfitAnalysisView.vue'),
+        meta: { title: '利润分析', pageKey: 'profit-analysis', roles: ['admin', 'manager', 'finance'] }
+      },
+      {
+        path: '/report/inventory-age',
+        name: 'inventory-age',
+        component: () => import('@/views/report/InventoryAgeAnalysisView.vue'),
+        meta: { title: '库存库龄分析', pageKey: 'inventory-age', roles: ['admin', 'manager', 'procurement', 'warehouse'] }
+      },
+      {
+        path: '/report/customer-analysis',
+        name: 'customer-analysis',
+        component: () => import('@/views/report/CustomerAnalysisView.vue'),
+        meta: { title: '客户分析', pageKey: 'customer-analysis', roles: ['admin', 'manager', 'operator'] }
+      },
+      {
+        path: '/report/logistics-report',
+        name: 'logistics-report',
+        component: () => import('@/views/report/LogisticsReportView.vue'),
+        meta: { title: '物流报表', pageKey: 'logistics-report', roles: ['admin', 'manager', 'warehouse'] }
+      },
+      {
+        path: '/report/channel-performance',
+        name: 'channel-performance',
+        component: () => import('@/views/report/ChannelPerformanceView.vue'),
+        meta: { title: '渠道绩效', pageKey: 'channel-performance', roles: ['admin', 'manager', 'operator'] }
+      },
+      {
+        path: '/report/procurement-report',
+        name: 'procurement-report',
+        component: () => import('@/views/report/ProcurementReportView.vue'),
+        meta: { title: '采购报表', pageKey: 'procurement-report', roles: ['admin', 'manager', 'procurement'] }
+      },
+      {
+        path: '/report/marketing-report',
+        name: 'marketing-report',
+        component: () => import('@/views/report/MarketingReportView.vue'),
+        meta: { title: '营销报表', pageKey: 'marketing-report', roles: ['admin', 'manager', 'operator'] }
       }
     ]
   },

+ 262 - 0
src/views/report/ChannelPerformanceView.vue

@@ -0,0 +1,262 @@
+<template>
+  <div class="app-page">
+    <section class="glass-card page-hero">
+      <div class="page-hero__meta">
+        <span class="page-hero__eyebrow">Channel Performance</span>
+        <h1>渠道绩效报表</h1>
+        <p>分析各渠道GMV占比、增长率、库存周转和盈利能力,优化渠道资源配置。</p>
+      </div>
+      <div class="chip-list">
+        <span class="chip">渠道对比</span>
+        <span class="chip">绩效排名</span>
+      </div>
+    </section>
+
+    <section class="glass-card section-card">
+      <el-form inline class="filter-form">
+        <el-form-item label="时间范围">
+          <el-date-picker v-model="filters.dateRange" type="daterange" range-separator="至" start-placeholder="开始" end-placeholder="结束" style="width:240px" />
+        </el-form-item>
+        <el-form-item label="渠道">
+          <el-select v-model="filters.channel" placeholder="全部渠道" clearable style="width:140px">
+            <el-option label="Shopify" value="Shopify" />
+            <el-option label="TikTok Shop" value="TikTok Shop" />
+            <el-option label="Amazon" value="Amazon" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="loadData">查询</el-button>
+          <el-button @click="resetFilters">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </section>
+
+    <section class="stat-grid" style="grid-template-columns:repeat(4, 1fr)">
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">总GMV</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-primary)">$328,560</div>
+        <div class="stat-card__trend trend-up">+12.5% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">活跃渠道</div>
+        <div class="stat-card__value" style="font-size:22px">3</div>
+        <div class="stat-card__trend">个</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">平均毛利率</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-success)">38.2%</div>
+        <div class="stat-card__trend trend-up">+2.1pp ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">库存周转</div>
+        <div class="stat-card__value" style="font-size:22px">28.5天</div>
+        <div class="stat-card__trend trend-down">-3.2天 ↓</div>
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">各渠道GMV占比</h3>
+        <v-chart :option="gmvShareOption" autoresize style="height:280px" />
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">各渠道增长率对比</h3>
+        <v-chart :option="growthCompareOption" autoresize style="height:280px" />
+      </article>
+    </section>
+
+    <section class="glass-card section-card">
+      <h3 style="margin:0 0 16px">渠道绩效明细</h3>
+      <el-table :data="channelPerformance" stripe v-loading="loading">
+        <el-table-column prop="channel" label="渠道" width="130">
+          <template #default="{ row }">
+            <div style="display:flex;align-items:center;gap:8px">
+              <span class="channel-dot" :style="{ backgroundColor: row.color }"></span>
+              {{ row.channel }}
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column prop="shopCount" label="店铺数" width="80" />
+        <el-table-column prop="gmv" label="GMV" width="130">
+          <template #default="{ row }">
+            <span style="font-weight:600">${{ row.gmv.toLocaleString() }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="orderCount" label="订单数" width="100" />
+        <el-table-column prop="avgOrderValue" label="客单价" width="100" />
+        <el-table-column prop="growth" label="增长率" width="100">
+          <template #default="{ row }">
+            <span :class="row.growth >= 0 ? 'trend-up' : 'trend-down'">
+              {{ row.growth >= 0 ? '+' : '' }}{{ row.growth }}%
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="profitRate" label="毛利率" width="90">
+          <template #default="{ row }">
+            <el-tag :type="row.profitRate >= 35 ? 'success' : row.profitRate >= 25 ? 'warning' : 'danger'" size="small">
+              {{ row.profitRate }}%
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="inventoryTurnover" label="库存周转" width="100">
+          <template #default="{ row }">
+            {{ row.inventoryTurnover }}天
+          </template>
+        </el-table-column>
+        <el-table-column prop="rating" label="店铺评分" width="100">
+          <template #default="{ row }">
+            <el-rate v-model="row.rating" disabled text-color="#ff9900" />
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="100" fixed="right">
+          <template #default="{ row }">
+            <el-button link type="primary" @click="viewDetail(row)">详情</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">各渠道月度GMV趋势</h3>
+        <v-chart :option="monthlyTrendOption" autoresize style="height:280px" />
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">各渠道盈利能力对比</h3>
+        <v-chart :option="profitCompareOption" autoresize style="height:280px" />
+      </article>
+    </section>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, computed } from 'vue';
+import VChart from 'vue-echarts';
+import { use } from 'echarts/core';
+import { CanvasRenderer } from 'echarts/renderers';
+import { LineChart, BarChart, PieChart } from 'echarts/charts';
+import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components';
+
+use([CanvasRenderer, LineChart, BarChart, PieChart, GridComponent, TooltipComponent, LegendComponent]);
+
+const loading = ref(false);
+
+const filters = ref({
+  dateRange: null as [Date, Date] | null,
+  channel: ''
+});
+
+const channelPerformance = ref([
+  { channel: 'Shopify', shopCount: 2, gmv: 158200, orderCount: 856, avgOrderValue: 184.8, growth: 15.2, profitRate: 42.5, inventoryTurnover: 25.2, rating: 4.8, color: '#409EFF' },
+  { channel: 'TikTok Shop', shopCount: 3, gmv: 89200, orderCount: 428, avgOrderValue: 208.4, growth: 28.5, profitRate: 35.8, inventoryTurnover: 30.5, rating: 4.5, color: '#67C23A' },
+  { channel: 'Amazon', shopCount: 2, gmv: 81200, orderCount: 385, avgOrderValue: 211.0, growth: 8.6, profitRate: 32.1, inventoryTurnover: 28.8, rating: 4.3, color: '#E6A23C' }
+]);
+
+const months = ['1月', '2月', '3月', '4月'];
+
+const gmvShareOption = computed(() => ({
+  tooltip: { trigger: 'item', formatter: '{b}: ${c} ({d}%)' },
+  legend: { orient: 'vertical', right: 20, top: 'center' },
+  series: [{
+    type: 'pie',
+    radius: ['40%', '70%'],
+    center: ['35%', '50%'],
+    data: [
+      { value: 158200, name: 'Shopify', itemStyle: { color: '#409EFF' } },
+      { value: 89200, name: 'TikTok Shop', itemStyle: { color: '#67C23A' } },
+      { value: 81200, name: 'Amazon', itemStyle: { color: '#E6A23C' } }
+    ]
+  }]
+}));
+
+const growthCompareOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: ['Shopify', 'TikTok Shop', 'Amazon'] },
+  yAxis: { type: 'value', axisLabel: { formatter: '{value}%' } },
+  series: [{
+    name: '增长率',
+    type: 'bar',
+    data: [15.2, 28.5, 8.6],
+    itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] }
+  }]
+}));
+
+const monthlyTrendOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: months },
+  yAxis: { type: 'value', axisLabel: { formatter: '${value}' } },
+  series: [
+    {
+      name: 'Shopify',
+      type: 'line',
+      smooth: true,
+      data: [125600, 138200, 152800, 158200],
+      itemStyle: { color: '#409EFF' }
+    },
+    {
+      name: 'TikTok Shop',
+      type: 'line',
+      smooth: true,
+      data: [65800, 72500, 82800, 89200],
+      itemStyle: { color: '#67C23A' }
+    },
+    {
+      name: 'Amazon',
+      type: 'line',
+      smooth: true,
+      data: [72000, 75800, 79200, 81200],
+      itemStyle: { color: '#E6A23C' }
+    }
+  ]
+}));
+
+const profitCompareOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: ['Shopify', 'TikTok Shop', 'Amazon'] },
+  yAxis: { type: 'value', axisLabel: { formatter: '${value}' } },
+  series: [
+    {
+      name: '销售额',
+      type: 'bar',
+      data: [158200, 89200, 81200],
+      itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] }
+    },
+    {
+      name: '毛利',
+      type: 'bar',
+      data: [67235, 31936, 26065],
+      itemStyle: { color: '#67C23A', borderRadius: [4, 4, 0, 0] }
+    }
+  ]
+}));
+
+const loadData = () => {
+  loading.value = true;
+  setTimeout(() => { loading.value = false; }, 300);
+};
+
+const resetFilters = () => {
+  filters.value = { dateRange: null, channel: '' };
+};
+
+const viewDetail = (row: any) => {
+  console.log('View channel detail:', row);
+};
+
+onMounted(loadData);
+</script>
+
+<style scoped>
+.filter-form :deep(.el-form-item) { margin-bottom: 0; }
+.channel-dot {
+  width: 10px;
+  height: 10px;
+  border-radius: 50%;
+  display: inline-block;
+}
+.trend-up { color: var(--el-color-success); }
+.trend-down { color: var(--el-color-danger); }
+</style>

+ 232 - 0
src/views/report/CustomerAnalysisView.vue

@@ -0,0 +1,232 @@
+<template>
+  <div class="app-page">
+    <section class="glass-card page-hero">
+      <div class="page-hero__meta">
+        <span class="page-hero__eyebrow">Customer Analytics</span>
+        <h1>客户分析报表</h1>
+        <p>分析新客/老客占比、复购率、客单价分布和地域分布,支持客户画像和精准营销。</p>
+      </div>
+      <div class="chip-list">
+        <span class="chip">客户画像</span>
+        <span class="chip">复购分析</span>
+      </div>
+    </section>
+
+    <section class="glass-card section-card">
+      <el-form inline class="filter-form">
+        <el-form-item label="时间范围">
+          <el-date-picker v-model="filters.dateRange" type="daterange" range-separator="至" start-placeholder="开始" end-placeholder="结束" style="width:240px" />
+        </el-form-item>
+        <el-form-item label="客户类型">
+          <el-select v-model="filters.customerType" placeholder="全部" clearable style="width:120px">
+            <el-option label="新客" value="new" />
+            <el-option label="老客" value="returning" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="渠道">
+          <el-select v-model="filters.channel" placeholder="全部渠道" clearable style="width:140px">
+            <el-option label="Shopify" value="Shopify" />
+            <el-option label="TikTok Shop" value="TikTok Shop" />
+            <el-option label="Amazon" value="Amazon" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="loadData">查询</el-button>
+          <el-button @click="resetFilters">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </section>
+
+    <section class="stat-grid" style="grid-template-columns:repeat(5, 1fr)">
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">客户总数</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-primary)">12,586</div>
+        <div class="stat-card__trend trend-up">+8.5% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">新客数</div>
+        <div class="stat-card__value" style="font-size:22px">4,852</div>
+        <div class="stat-card__trend">占比38.5%</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">老客数</div>
+        <div class="stat-card__value" style="font-size:22px">7,734</div>
+        <div class="stat-card__trend">占比61.5%</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">复购率</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-success)">18.5%</div>
+        <div class="stat-card__trend trend-up">+2.1% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">平均客单价</div>
+        <div class="stat-card__value" style="font-size:22px">¥1,852</div>
+        <div class="stat-card__trend trend-up">+5.2% ↑</div>
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">新客/老客占比</h3>
+        <v-chart :option="customerTypeOption" autoresize style="height:280px" />
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">客单价分布</h3>
+        <v-chart :option="orderValueDistOption" autoresize style="height:280px" />
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">地域分布 TOP 10</h3>
+        <el-table :data="regionDistribution" stripe size="small">
+          <el-table-column prop="rank" label="排名" width="60" />
+          <el-table-column prop="region" label="国家/地区" width="120" />
+          <el-table-column prop="customerCount" label="客户数" width="90" />
+          <el-table-column prop="orderCount" label="订单数" width="90" />
+          <el-table-column prop="gmv" label="GMV" width="110">
+            <template #default="{ row }">
+              <span style="font-weight:600">${{ row.gmv.toLocaleString() }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="avgOrderValue" label="客单价" width="100" />
+        </el-table>
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">复购周期分析</h3>
+        <v-chart :option="repurchaseCycleOption" autoresize style="height:260px" />
+      </article>
+    </section>
+
+    <section class="glass-card section-card">
+      <h3 style="margin:0 0 16px">客户明细</h3>
+      <el-table :data="customerDetail" stripe v-loading="loading">
+        <el-table-column prop="customerId" label="客户ID" width="120" />
+        <el-table-column prop="name" label="客户名称" width="120" />
+        <el-table-column prop="channel" label="渠道" width="100" />
+        <el-table-column prop="totalOrders" label="累计订单" width="90" />
+        <el-table-column prop="totalAmount" label="累计消费" width="120">
+          <template #default="{ row }">
+            <span style="font-weight:600">${{ row.totalAmount.toLocaleString() }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="avgOrderValue" label="平均客单价" width="120" />
+        <el-table-column prop="lastOrderDate" label="最近下单" width="110" />
+        <el-table-column prop="customerType" label="客户类型" width="90">
+          <template #default="{ row }">
+            <el-tag :type="row.customerType === '新客' ? 'primary' : 'success'" size="small">
+              {{ row.customerType }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="vipLevel" label="VIP等级" width="90">
+          <template #default="{ row }">
+            <el-tag :type="row.vipLevel === '钻石' ? 'danger' : row.vipLevel === '金牌' ? 'warning' : 'info'" size="small">
+              {{ row.vipLevel }}
+            </el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+    </section>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, computed } from 'vue';
+import VChart from 'vue-echarts';
+import { use } from 'echarts/core';
+import { CanvasRenderer } from 'echarts/renderers';
+import { LineChart, BarChart, PieChart } from 'echarts/charts';
+import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components';
+
+use([CanvasRenderer, LineChart, BarChart, PieChart, GridComponent, TooltipComponent, LegendComponent]);
+
+const loading = ref(false);
+
+const filters = ref({
+  dateRange: null as [Date, Date] | null,
+  customerType: '',
+  channel: ''
+});
+
+const regionDistribution = ref([
+  { rank: 1, region: '美国', customerCount: 4250, orderCount: 8560, gmv: 128600, avgOrderValue: 150.2 },
+  { rank: 2, region: '英国', customerCount: 2860, orderCount: 5280, gmv: 89200, avgOrderValue: 169.0 },
+  { rank: 3, region: '日本', customerCount: 1950, orderCount: 3680, gmv: 65800, avgOrderValue: 178.8 },
+  { rank: 4, region: '德国', customerCount: 1280, orderCount: 2350, gmv: 42800, avgOrderValue: 182.1 },
+  { rank: 5, region: '法国', customerCount: 960, orderCount: 1820, gmv: 32600, avgOrderValue: 179.1 },
+  { rank: 6, region: '加拿大', customerCount: 820, orderCount: 1580, gmv: 28500, avgOrderValue: 180.4 },
+  { rank: 7, region: '澳大利亚', customerCount: 680, orderCount: 1290, gmv: 23800, avgOrderValue: 184.5 },
+  { rank: 8, region: '意大利', customerCount: 520, orderCount: 980, gmv: 17200, avgOrderValue: 175.5 },
+  { rank: 9, region: '西班牙', customerCount: 420, orderCount: 820, gmv: 14800, avgOrderValue: 180.5 },
+  { rank: 10, region: '荷兰', customerCount: 380, orderCount: 720, gmv: 13200, avgOrderValue: 183.3 }
+]);
+
+const customerDetail = ref([
+  { customerId: 'CUS001', name: 'John Smith', channel: 'Shopify', totalOrders: 12, totalAmount: 4856, avgOrderValue: 404.7, lastOrderDate: '2026-04-18', customerType: '老客', vipLevel: '钻石' },
+  { customerId: 'CUS002', name: 'Emma Johnson', channel: 'TikTok Shop', totalOrders: 8, totalAmount: 3280, avgOrderValue: 410.0, lastOrderDate: '2026-04-19', customerType: '老客', vipLevel: '金牌' },
+  { customerId: 'CUS003', name: 'Michael Brown', channel: 'Amazon', totalOrders: 1, totalAmount: 1280, avgOrderValue: 1280.0, lastOrderDate: '2026-04-20', customerType: '新客', vipLevel: '普通' },
+  { customerId: 'CUS004', name: 'Sarah Davis', channel: 'Shopify', totalOrders: 5, totalAmount: 2890, avgOrderValue: 578.0, lastOrderDate: '2026-04-17', customerType: '老客', vipLevel: '金牌' },
+  { customerId: 'CUS005', name: 'James Wilson', channel: 'Shopify', totalOrders: 15, totalAmount: 6850, avgOrderValue: 456.7, lastOrderDate: '2026-04-20', customerType: '老客', vipLevel: '钻石' },
+  { customerId: 'CUS006', name: 'Lisa Anderson', channel: 'TikTok Shop', totalOrders: 1, totalAmount: 890, avgOrderValue: 890.0, lastOrderDate: '2026-04-19', customerType: '新客', vipLevel: '普通' }
+]);
+
+const customerTypeOption = computed(() => ({
+  tooltip: { trigger: 'item', formatter: '{b}: {c}人 ({d}%)' },
+  legend: { orient: 'vertical', right: 20, top: 'center' },
+  series: [{
+    type: 'pie',
+    radius: ['40%', '70%'],
+    center: ['35%', '50%'],
+    data: [
+      { value: 4852, name: '新客', itemStyle: { color: '#409EFF' } },
+      { value: 7734, name: '老客', itemStyle: { color: '#67C23A' } }
+    ]
+  }]
+}));
+
+const orderValueDistOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: ['0-100', '100-300', '300-500', '500-1000', '1000+'] },
+  yAxis: { type: 'value' },
+  series: [{
+    name: '客户数',
+    type: 'bar',
+    data: [3250, 5280, 2850, 980, 226],
+    itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] }
+  }]
+}));
+
+const repurchaseCycleOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: ['7天内', '7-15天', '15-30天', '30-60天', '60-90天', '90天以上'] },
+  yAxis: { type: 'value' },
+  series: [{
+    name: '复购客户数',
+    type: 'line',
+    smooth: true,
+    data: [1250, 2180, 1850, 1280, 680, 320],
+    areaStyle: { opacity: 0.15 },
+    itemStyle: { color: '#67C23A' }
+  }]
+}));
+
+const loadData = () => {
+  loading.value = true;
+  setTimeout(() => { loading.value = false; }, 300);
+};
+
+const resetFilters = () => {
+  filters.value = { dateRange: null, customerType: '', channel: '' };
+};
+
+onMounted(loadData);
+</script>
+
+<style scoped>
+.filter-form :deep(.el-form-item) { margin-bottom: 0; }
+.trend-up { color: var(--el-color-success); }
+.trend-down { color: var(--el-color-danger); }
+</style>

+ 252 - 0
src/views/report/InventoryAgeAnalysisView.vue

@@ -0,0 +1,252 @@
+<template>
+  <div class="app-page">
+    <section class="glass-card page-hero">
+      <div class="page-hero__meta">
+        <span class="page-hero__eyebrow">Inventory Age Analytics</span>
+        <h1>库存库龄分析</h1>
+        <p>分析库存库龄分布,识别呆滞库存和老库存,支持设置滞销天数阈值和预警规则。</p>
+      </div>
+      <div class="chip-list">
+        <span class="chip">呆滞预警</span>
+        <span class="chip">库龄分布</span>
+      </div>
+    </section>
+
+    <section class="glass-card section-card">
+      <el-form inline class="filter-form">
+        <el-form-item label="仓库">
+          <el-select v-model="filters.warehouse" placeholder="全部仓库" clearable style="width:140px">
+            <el-option label="华东仓" value="华东仓" />
+            <el-option label="华南仓" value="华南仓" />
+            <el-option label="海外仓-US" value="海外仓-US" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="库龄区间">
+          <el-select v-model="filters.ageRange" placeholder="全部" clearable style="width:130px">
+            <el-option label="0-30天" value="0-30" />
+            <el-option label="31-60天" value="31-60" />
+            <el-option label="61-90天" value="61-90" />
+            <el-option label="90天以上" value="90+" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="预警状态">
+          <el-select v-model="filters.alertStatus" placeholder="全部" clearable style="width:120px">
+            <el-option label="正常" value="normal" />
+            <el-option label="预警" value="warning" />
+            <el-option label="呆滞" value="stagnant" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="loadData">查询</el-button>
+          <el-button @click="resetFilters">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </section>
+
+    <section class="stat-grid" style="grid-template-columns:repeat(4, 1fr)">
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">总库存量</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-primary)">58,620</div>
+        <div class="stat-card__trend">件</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">库存成本</div>
+        <div class="stat-card__value" style="font-size:22px">¥2,856,200</div>
+        <div class="stat-card__trend trend-down">-3.2% ↓</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">平均库龄</div>
+        <div class="stat-card__value" style="font-size:22px">42.5天</div>
+        <div class="stat-card__trend trend-up">+5.8天 ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">呆滞库存</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-danger)">8,420</div>
+        <div class="stat-card__trend">件 (占比14.4%)</div>
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">库龄分布</h3>
+        <v-chart :option="ageDistributionOption" autoresize style="height:280px" />
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">各仓库库存对比</h3>
+        <v-chart :option="warehouseCompareOption" autoresize style="height:280px" />
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">TOP 10 呆滞商品</h3>
+        <el-table :data="stagnantProducts" stripe size="small">
+          <el-table-column prop="rank" label="排名" width="60" />
+          <el-table-column prop="sku" label="SKU" width="120" />
+          <el-table-column prop="title" label="商品名称" min-width="160" show-overflow-tooltip />
+          <el-table-column prop="qty" label="库存" width="80" />
+          <el-table-column prop="age" label="库龄" width="80">
+            <template #default="{ row }">
+              <el-tag type="danger" size="small">{{ row.age }}天</el-tag>
+            </template>
+          </el-table-column>
+        </el-table>
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">库龄趋势</h3>
+        <v-chart :option="ageTrendOption" autoresize style="height:260px" />
+      </article>
+    </section>
+
+    <section class="glass-card section-card">
+      <h3 style="margin:0 0 16px">库存库龄明细</h3>
+      <el-table :data="inventoryAgeDetail" stripe v-loading="loading">
+        <el-table-column prop="sku" label="SKU" width="120" />
+        <el-table-column prop="productTitle" label="商品名称" min-width="180" show-overflow-tooltip />
+        <el-table-column prop="warehouse" label="仓库" width="100" />
+        <el-table-column prop="qty" label="库存数量" width="90" />
+        <el-table-column prop="cost" label="成本" width="100">
+          <template #default="{ row }">
+            ¥{{ row.cost.toLocaleString() }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="inboundDate" label="入库日期" width="110" />
+        <el-table-column prop="age" label="库龄" width="80">
+          <template #default="{ row }">
+            <el-tag :type="row.age > 90 ? 'danger' : row.age > 60 ? 'warning' : 'success'" size="small">
+              {{ row.age }}天
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="turnoverDays" label="周转天数" width="90" />
+        <el-table-column prop="alertStatus" label="预警状态" width="90">
+          <template #default="{ row }">
+            <el-tag :type="row.alertStatus === '正常' ? 'success' : row.alertStatus === '预警' ? 'warning' : 'danger'" size="small">
+              {{ row.alertStatus }}
+            </el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+    </section>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, computed } from 'vue';
+import VChart from 'vue-echarts';
+import { use } from 'echarts/core';
+import { CanvasRenderer } from 'echarts/renderers';
+import { LineChart, BarChart, PieChart, RadarChart } from 'echarts/charts';
+import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components';
+
+use([CanvasRenderer, LineChart, BarChart, PieChart, RadarChart, GridComponent, TooltipComponent, LegendComponent]);
+
+const loading = ref(false);
+
+const filters = ref({
+  warehouse: '',
+  ageRange: '',
+  alertStatus: ''
+});
+
+const stagnantProducts = ref([
+  { rank: 1, sku: 'SKU-NM-BK-S', title: 'Nomad 防水背包 黑色 小号', qty: 580, age: 128 },
+  { rank: 2, sku: 'SKU-UT-WH-XL', title: 'UrbanTrail 徒步鞋 白色 XL', qty: 320, age: 115 },
+  { rank: 3, sku: 'SKU-AE-GR-L', title: 'AeroDry 速干T恤 绿色 L码', qty: 850, age: 98 },
+  { rank: 4, sku: 'SKU-NM-GY-L', title: 'Nomad 防水背包 灰色 L号', qty: 420, age: 95 },
+  { rank: 5, sku: 'SKU-UT-BK-42', title: 'UrbanTrail 登山靴 黑色 42码', qty: 185, age: 92 },
+  { rank: 6, sku: 'SKU-AE-BL-M', title: 'AeroDry 运动短裤 蓝色 M码', qty: 620, age: 88 },
+  { rank: 7, sku: 'SKU-NM-BK-M', title: 'Nomad 防水背包 黑色 中号', qty: 280, age: 85 },
+  { rank: 8, sku: 'SKU-UT-RD-41', title: 'UrbanTrail 登山靴 红色 41码', qty: 95, age: 82 },
+  { rank: 9, sku: 'SKU-AE-WH-M', title: 'AeroDry 速干T恤 白色 M码', qty: 450, age: 78 },
+  { rank: 10, sku: 'SKU-NM-NY-UN', title: 'Nomad 收纳袋 黑色 套装', qty: 1200, age: 75 }
+]);
+
+const inventoryAgeDetail = ref([
+  { sku: 'SKU-NM-BK-M', productTitle: 'Nomad 防水背包 黑色 中号', warehouse: '华东仓', qty: 520, cost: 124800, inboundDate: '2026-03-15', age: 36, turnoverDays: 28, alertStatus: '正常' },
+  { sku: 'SKU-AE-GR-L', productTitle: 'AeroDry 速干T恤 绿色 L码', warehouse: '华南仓', qty: 850, cost: 68000, inboundDate: '2026-01-22', age: 98, turnoverDays: 45, alertStatus: '呆滞' },
+  { sku: 'SKU-UT-WH-XL', productTitle: 'UrbanTrail 徒步鞋 白色 XL', warehouse: '华东仓', qty: 320, cost: 89600, inboundDate: '2025-12-26', age: 115, turnoverDays: 52, alertStatus: '呆滞' },
+  { sku: 'SKU-NM-BK-S', productTitle: 'Nomad 防水背包 黑色 小号', warehouse: '海外仓-US', qty: 580, cost: 104400, inboundDate: '2025-12-12', age: 128, turnoverDays: 38, alertStatus: '呆滞' },
+  { sku: 'SKU-AE-BL-M', productTitle: 'AeroDry 运动短裤 蓝色 M码', warehouse: '华南仓', qty: 620, cost: 37200, inboundDate: '2026-02-10', age: 68, turnoverDays: 32, alertStatus: '预警' },
+  { sku: 'SKU-UT-BK-42', productTitle: 'UrbanTrail 登山靴 黑色 42码', warehouse: '华东仓', qty: 185, cost: 55500, inboundDate: '2026-01-28', age: 82, turnoverDays: 48, alertStatus: '呆滞' }
+]);
+
+const ageDistributionOption = computed(() => ({
+  tooltip: { trigger: 'item', formatter: '{b}: {c}件 ({d}%)' },
+  legend: { orient: 'vertical', right: 20, top: 'center' },
+  series: [{
+    type: 'pie',
+    radius: ['40%', '70%'],
+    center: ['35%', '50%'],
+    data: [
+      { value: 28650, name: '0-30天', itemStyle: { color: '#67C23A' } },
+      { value: 15280, name: '31-60天', itemStyle: { color: '#409EFF' } },
+      { value: 8270, name: '61-90天', itemStyle: { color: '#E6A23C' } },
+      { value: 6420, name: '90天以上', itemStyle: { color: '#F56C6C' } }
+    ]
+  }]
+}));
+
+const warehouseCompareOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: ['华东仓', '华南仓', '海外仓-US'] },
+  yAxis: { type: 'value' },
+  series: [
+    {
+      name: '库存数量',
+      type: 'bar',
+      data: [28500, 22100, 8020],
+      itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] }
+    },
+    {
+      name: '呆滞库存',
+      type: 'bar',
+      data: [3200, 2850, 2370],
+      itemStyle: { color: '#F56C6C', borderRadius: [4, 4, 0, 0] }
+    }
+  ]
+}));
+
+const ageTrendOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: ['4/14', '4/15', '4/16', '4/17', '4/18', '4/19', '4/20'] },
+  yAxis: { type: 'value', axisLabel: { formatter: '{value}天' } },
+  series: [
+    {
+      name: '平均库龄',
+      type: 'line',
+      smooth: true,
+      data: [38.2, 39.5, 40.1, 41.2, 42.0, 42.3, 42.5],
+      areaStyle: { opacity: 0.15 },
+      itemStyle: { color: '#409EFF' }
+    },
+    {
+      name: '呆滞库存占比',
+      type: 'line',
+      smooth: true,
+      data: [12.5, 13.1, 13.5, 13.8, 14.1, 14.3, 14.4],
+      yAxisIndex: 0,
+      itemStyle: { color: '#F56C6C' }
+    }
+  ]
+}));
+
+const loadData = () => {
+  loading.value = true;
+  setTimeout(() => { loading.value = false; }, 300);
+};
+
+const resetFilters = () => {
+  filters.value = { warehouse: '', ageRange: '', alertStatus: '' };
+};
+
+onMounted(loadData);
+</script>
+
+<style scoped>
+.filter-form :deep(.el-form-item) { margin-bottom: 0; }
+.trend-up { color: var(--el-color-success); }
+.trend-down { color: var(--el-color-danger); }
+</style>

+ 245 - 0
src/views/report/LogisticsReportView.vue

@@ -0,0 +1,245 @@
+<template>
+  <div class="app-page">
+    <section class="glass-card page-hero">
+      <div class="page-hero__meta">
+        <span class="page-hero__eyebrow">Logistics Analytics</span>
+        <h1>物流报表</h1>
+        <p>追踪发货及时率、物流成本、配送时效和妥投率,优化物流效率和成本。</p>
+      </div>
+      <div class="chip-list">
+        <span class="chip">时效监控</span>
+        <span class="chip">成本分析</span>
+      </div>
+    </section>
+
+    <section class="glass-card section-card">
+      <el-form inline class="filter-form">
+        <el-form-item label="时间范围">
+          <el-date-picker v-model="filters.dateRange" type="daterange" range-separator="至" start-placeholder="开始" end-placeholder="结束" style="width:240px" />
+        </el-form-item>
+        <el-form-item label="仓库">
+          <el-select v-model="filters.warehouse" placeholder="全部仓库" clearable style="width:140px">
+            <el-option label="华东仓" value="华东仓" />
+            <el-option label="华南仓" value="华南仓" />
+            <el-option label="海外仓-US" value="海外仓-US" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="物流商">
+          <el-select v-model="filters.carrier" placeholder="全部物流商" clearable style="width:140px">
+            <el-option label="DHL" value="DHL" />
+            <el-option label="FedEx" value="FedEx" />
+            <el-option label="UPS" value="UPS" />
+            <el-option label="顺丰" value="SF" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="loadData">查询</el-button>
+          <el-button @click="resetFilters">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </section>
+
+    <section class="stat-grid" style="grid-template-columns:repeat(5, 1fr)">
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">本月发货量</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-primary)">28,560</div>
+        <div class="stat-card__trend">件</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">发货及时率</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-success)">96.8%</div>
+        <div class="stat-card__trend trend-up">+1.2% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">平均配送时效</div>
+        <div class="stat-card__value" style="font-size:22px">5.2天</div>
+        <div class="stat-card__trend trend-up">-0.3天 ↓</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">妥投率</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-success)">98.5%</div>
+        <div class="stat-card__trend trend-up">+0.5% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">物流成本</div>
+        <div class="stat-card__value" style="font-size:22px">¥186,420</div>
+        <div class="stat-card__trend trend-down">+5.8% ↑</div>
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">发货及时率趋势</h3>
+        <v-chart :option="onTimeRateOption" autoresize style="height:280px" />
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">物流成本趋势</h3>
+        <v-chart :option="costTrendOption" autoresize style="height:280px" />
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">物流商对比</h3>
+        <el-table :data="carrierComparison" stripe size="small">
+          <el-table-column prop="carrier" label="物流商" width="100" />
+          <el-table-column prop="shipmentCount" label="发货量" width="90" />
+          <el-table-column prop="onTimeRate" label="及时率" width="80">
+            <template #default="{ row }">
+              <span :style="{ color: row.onTimeRate >= 95 ? 'var(--cb-success)' : 'var(--cb-danger)' }">{{ row.onTimeRate }}%</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="avgDeliveryDays" label="平均时效" width="90">
+            <template #default="{ row }">
+              {{ row.avgDeliveryDays }}天
+            </template>
+          </el-table-column>
+          <el-table-column prop="deliveryRate" label="妥投率" width="80">
+            <template #default="{ row }">
+              <span style="color:var(--cb-success)">{{ row.deliveryRate }}%</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="costPerItem" label="单件成本" width="100">
+            <template #default="{ row }">
+              ¥{{ row.costPerItem }}
+            </template>
+          </el-table-column>
+        </el-table>
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">配送时效分布</h3>
+        <v-chart :option="deliveryTimeDistOption" autoresize style="height:260px" />
+      </article>
+    </section>
+
+    <section class="glass-card section-card">
+      <h3 style="margin:0 0 16px">物流明细</h3>
+      <el-table :data="logisticsDetail" stripe v-loading="loading">
+        <el-table-column prop="shipmentNo" label="发货单号" width="160" />
+        <el-table-column prop="orderNo" label="订单号" width="150" />
+        <el-table-column prop="warehouse" label="仓库" width="100" />
+        <el-table-column prop="carrier" label="物流商" width="80" />
+        <el-table-column prop="trackingNo" label="运单号" width="150" show-overflow-tooltip />
+        <el-table-column prop="shipTime" label="发货时间" width="110" />
+        <el-table-column prop="deliveryDays" label="配送天数" width="90">
+          <template #default="{ row }">
+            <el-tag :type="row.deliveryDays <= 5 ? 'success' : row.deliveryDays <= 10 ? 'warning' : 'danger'" size="small">
+              {{ row.deliveryDays }}天
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="deliveryStatus" label="配送状态" width="90">
+          <template #default="{ row }">
+            <el-tag :type="row.deliveryStatus === '已签收' ? 'success' : row.deliveryStatus === '配送中' ? 'primary' : 'warning'" size="small">
+              {{ row.deliveryStatus }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="cost" label="物流费用" width="100">
+          <template #default="{ row }">
+            ¥{{ row.cost }}
+          </template>
+        </el-table-column>
+      </el-table>
+    </section>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, computed } from 'vue';
+import VChart from 'vue-echarts';
+import { use } from 'echarts/core';
+import { CanvasRenderer } from 'echarts/renderers';
+import { LineChart, BarChart, PieChart } from 'echarts/charts';
+import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components';
+
+use([CanvasRenderer, LineChart, BarChart, PieChart, GridComponent, TooltipComponent, LegendComponent]);
+
+const loading = ref(false);
+
+const filters = ref({
+  dateRange: null as [Date, Date] | null,
+  warehouse: '',
+  carrier: ''
+});
+
+const carrierComparison = ref([
+  { carrier: 'DHL', shipmentCount: 8560, onTimeRate: 98.2, avgDeliveryDays: 4.5, deliveryRate: 99.1, costPerItem: 28.5 },
+  { carrier: 'FedEx', shipmentCount: 6280, onTimeRate: 97.5, avgDeliveryDays: 4.8, deliveryRate: 98.8, costPerItem: 26.8 },
+  { carrier: 'UPS', shipmentCount: 5420, onTimeRate: 96.8, avgDeliveryDays: 5.2, deliveryRate: 98.5, costPerItem: 25.2 },
+  { carrier: '顺丰', shipmentCount: 4280, onTimeRate: 99.1, avgDeliveryDays: 3.2, deliveryRate: 99.5, costPerItem: 32.0 },
+  { carrier: '邮政小包', shipmentCount: 3020, onTimeRate: 92.5, avgDeliveryDays: 12.5, deliveryRate: 96.2, costPerItem: 12.8 }
+]);
+
+const logisticsDetail = ref([
+  { shipmentNo: 'SH20260420001', orderNo: 'ORD-20260420-0123', warehouse: '华东仓', carrier: 'DHL', trackingNo: 'JD014602384265', shipTime: '2026-04-20 10:30', deliveryDays: 4, deliveryStatus: '已签收', cost: 28.5 },
+  { shipmentNo: 'SH20260420002', orderNo: 'ORD-20260420-0456', warehouse: '华南仓', carrier: 'FedEx', trackingNo: 'FX782940185736', shipTime: '2026-04-20 09:15', deliveryDays: 5, deliveryStatus: '已签收', cost: 26.8 },
+  { shipmentNo: 'SH20260419003', orderNo: 'ORD-20260419-0789', warehouse: '华东仓', carrier: 'UPS', trackingNo: 'UP849261028475', shipTime: '2026-04-19 14:20', deliveryDays: 6, deliveryStatus: '配送中', cost: 25.2 },
+  { shipmentNo: 'SH20260419004', orderNo: 'ORD-20260419-0321', warehouse: '海外仓-US', carrier: '顺丰', trackingNo: 'SF108425926847', shipTime: '2026-04-19 11:45', deliveryDays: 3, deliveryStatus: '已签收', cost: 32.0 },
+  { shipmentNo: 'SH20260418005', orderNo: 'ORD-20260418-0654', warehouse: '华南仓', carrier: 'DHL', trackingNo: 'JD014602384299', shipTime: '2026-04-18 16:30', deliveryDays: 5, deliveryStatus: '已签收', cost: 28.5 }
+]);
+
+const days = ['4/14', '4/15', '4/16', '4/17', '4/18', '4/19', '4/20'];
+
+const onTimeRateOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: days },
+  yAxis: { type: 'value', min: 90, max: 100, axisLabel: { formatter: '{value}%' } },
+  series: [{
+    name: '发货及时率',
+    type: 'line',
+    smooth: true,
+    data: [95.2, 96.1, 95.8, 97.2, 96.5, 97.8, 96.8],
+    areaStyle: { opacity: 0.15 },
+    itemStyle: { color: '#67C23A' }
+  }]
+}));
+
+const costTrendOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: days },
+  yAxis: { type: 'value', axisLabel: { formatter: '¥{value}' } },
+  series: [{
+    name: '物流成本',
+    type: 'bar',
+    data: [25200, 28600, 26800, 29500, 27200, 31200, 28420],
+    itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] }
+  }]
+}));
+
+const deliveryTimeDistOption = computed(() => ({
+  tooltip: { trigger: 'item', formatter: '{b}: {c}件 ({d}%)' },
+  legend: { orient: 'vertical', right: 20, top: 'center' },
+  series: [{
+    type: 'pie',
+    radius: ['40%', '70%'],
+    center: ['35%', '50%'],
+    data: [
+      { value: 12580, name: '1-3天', itemStyle: { color: '#67C23A' } },
+      { value: 8920, name: '4-5天', itemStyle: { color: '#409EFF' } },
+      { value: 4280, name: '6-7天', itemStyle: { color: '#E6A23C' } },
+      { value: 1860, name: '8-10天', itemStyle: { color: '#F56C6C' } },
+      { value: 920, name: '10天以上', itemStyle: { color: '#909399' } }
+    ]
+  }]
+}));
+
+const loadData = () => {
+  loading.value = true;
+  setTimeout(() => { loading.value = false; }, 300);
+};
+
+const resetFilters = () => {
+  filters.value = { dateRange: null, warehouse: '', carrier: '' };
+};
+
+onMounted(loadData);
+</script>
+
+<style scoped>
+.filter-form :deep(.el-form-item) { margin-bottom: 0; }
+.trend-up { color: var(--el-color-success); }
+.trend-down { color: var(--el-color-danger); }
+</style>

+ 259 - 0
src/views/report/MarketingReportView.vue

@@ -0,0 +1,259 @@
+<template>
+  <div class="app-page">
+    <section class="glass-card page-hero">
+      <div class="page-hero__meta">
+        <span class="page-hero__eyebrow">Marketing Analytics</span>
+        <h1>营销报表</h1>
+        <p>追踪促销ROI、优惠券核销率和活动效果,分析营销效率并优化投放策略。</p>
+      </div>
+      <div class="chip-list">
+        <span class="chip">活动效果</span>
+        <span class="chip">ROI分析</span>
+      </div>
+    </section>
+
+    <section class="glass-card section-card">
+      <el-form inline class="filter-form">
+        <el-form-item label="时间范围">
+          <el-date-picker v-model="filters.dateRange" type="daterange" range-separator="至" start-placeholder="开始" end-placeholder="结束" style="width:240px" />
+        </el-form-item>
+        <el-form-item label="活动类型">
+          <el-select v-model="filters.activityType" placeholder="全部" clearable style="width:130px">
+            <el-option label="折扣活动" value="discount" />
+            <el-option label="满减活动" value="off" />
+            <el-option label="买赠活动" value="gift" />
+            <el-option label="优惠券" value="coupon" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="状态">
+          <el-select v-model="filters.status" placeholder="全部" clearable style="width:120px">
+            <el-option label="进行中" value="进行中" />
+            <el-option label="已结束" value="已结束" />
+            <el-option label="未开始" value="未开始" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="loadData">查询</el-button>
+          <el-button @click="resetFilters">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </section>
+
+    <section class="stat-grid" style="grid-template-columns:repeat(5, 1fr)">
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">活动数量</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-primary)">28</div>
+        <div class="stat-card__trend">进行中: 8</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">优惠券核销</div>
+        <div class="stat-card__value" style="font-size:22px">12,580</div>
+        <div class="stat-card__trend">张</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">核销金额</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-success)">¥458,200</div>
+        <div class="stat-card__trend trend-up">+18.5% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">活动GMV</div>
+        <div class="stat-card__value" style="font-size:22px">¥1,856,000</div>
+        <div class="stat-card__trend trend-up">+25.3% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">平均ROI</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-success)">3.8x</div>
+        <div class="stat-card__trend trend-up">+0.5x ↑</div>
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">活动效果趋势</h3>
+        <v-chart :option="activityTrendOption" autoresize style="height:280px" />
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">各渠道活动效果</h3>
+        <v-chart :option="channelEffectOption" autoresize style="height:280px" />
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">优惠券核销TOP</h3>
+        <el-table :data="couponTop" stripe size="small">
+          <el-table-column prop="rank" label="排名" width="60" />
+          <el-table-column prop="name" label="优惠券名称" min-width="160" show-overflow-tooltip />
+          <el-table-column prop="usedCount" label="核销数" width="90" />
+          <el-table-column prop="amount" label="核销金额" width="110">
+            <template #default="{ row }">
+              <span style="font-weight:600">¥{{ row.amount.toLocaleString() }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="roi" label="ROI" width="80">
+            <template #default="{ row }">
+              <span style="color:var(--cb-success)">{{ row.roi }}x</span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">活动ROI对比</h3>
+        <v-chart :option="roiCompareOption" autoresize style="height:260px" />
+      </article>
+    </section>
+
+    <section class="glass-card section-card">
+      <h3 style="margin:0 0 16px">营销活动明细</h3>
+      <el-table :data="marketingDetail" stripe v-loading="loading">
+        <el-table-column prop="activityName" label="活动名称" min-width="180" show-overflow-tooltip />
+        <el-table-column prop="type" label="活动类型" width="100">
+          <template #default="{ row }">
+            <el-tag size="small">{{ row.type }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="channel" label="渠道" width="100" />
+        <el-table-column prop="startTime" label="开始时间" width="110" />
+        <el-table-column prop="endTime" label="结束时间" width="110" />
+        <el-table-column prop="gmv" label="活动GMV" width="120">
+          <template #default="{ row }">
+            <span style="font-weight:600">¥{{ row.gmv.toLocaleString() }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="cost" label="活动成本" width="110">
+          <template #default="{ row }">
+            ¥{{ row.cost.toLocaleString() }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="roi" label="ROI" width="80">
+          <template #default="{ row }">
+            <el-tag :type="row.roi >= 3 ? 'success' : row.roi >= 2 ? 'warning' : 'danger'" size="small">
+              {{ row.roi }}x
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="participation" label="参与数" width="90" />
+        <el-table-column prop="status" label="状态" width="90">
+          <template #default="{ row }">
+            <el-tag :type="row.status === '进行中' ? 'success' : row.status === '已结束' ? 'info' : 'warning'" size="small">
+              {{ row.status }}
+            </el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+    </section>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, computed } from 'vue';
+import VChart from 'vue-echarts';
+import { use } from 'echarts/core';
+import { CanvasRenderer } from 'echarts/renderers';
+import { LineChart, BarChart, PieChart } from 'echarts/charts';
+import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components';
+
+use([CanvasRenderer, LineChart, BarChart, PieChart, GridComponent, TooltipComponent, LegendComponent]);
+
+const loading = ref(false);
+
+const filters = ref({
+  dateRange: null as [Date, Date] | null,
+  activityType: '',
+  status: ''
+});
+
+const couponTop = ref([
+  { rank: 1, name: '新人专享满99减20', usedCount: 3280, amount: 65600, roi: 4.2 },
+  { rank: 2, name: '会员专享8折券', usedCount: 2850, amount: 45600, roi: 3.8 },
+  { rank: 3, name: '老客回归满149减30', usedCount: 1890, amount: 56700, roi: 4.5 },
+  { rank: 4, name: '限时9折券', usedCount: 1200, amount: 19200, roi: 3.2 },
+  { rank: 5, name: '新品兑换券', usedCount: 156, amount: 0, roi: 2.8 }
+]);
+
+const marketingDetail = ref([
+  { activityName: '4月大促活动', type: '折扣活动', channel: 'Shopify', startTime: '2026-04-01', endTime: '2026-04-30', gmv: 856000, cost: 198000, roi: 4.3, participation: 5280, status: '进行中' },
+  { activityName: '会员月活动', type: '优惠券', channel: 'Shopify', startTime: '2026-04-01', endTime: '2026-04-30', gmv: 428000, cost: 112000, roi: 3.8, participation: 2850, status: '进行中' },
+  { activityName: '新品首发活动', type: '买赠活动', channel: 'TikTok Shop', startTime: '2026-04-18', endTime: '2026-05-18', gmv: 285000, cost: 85000, roi: 3.4, participation: 1280, status: '进行中' },
+  { activityName: '春季促销', type: '满减活动', channel: 'Amazon', startTime: '2026-03-15', endTime: '2026-04-15', gmv: 528000, cost: 156000, roi: 3.4, participation: 3560, status: '已结束' },
+  { activityName: '复活节特惠', type: '折扣活动', channel: 'TikTok Shop', startTime: '2026-04-01', endTime: '2026-04-12', gmv: 186000, cost: 52000, roi: 3.6, participation: 1680, status: '已结束' }
+]);
+
+const days = ['4/14', '4/15', '4/16', '4/17', '4/18', '4/19', '4/20'];
+
+const activityTrendOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: days },
+  yAxis: { type: 'value', axisLabel: { formatter: '¥{value}' } },
+  series: [
+    {
+      name: '活动GMV',
+      type: 'bar',
+      data: [268000, 312000, 285000, 325000, 298000, 358000, 312000],
+      itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] }
+    },
+    {
+      name: '活动成本',
+      type: 'line',
+      smooth: true,
+      yAxisIndex: 0,
+      data: [68000, 78000, 72000, 82000, 75000, 89000, 78000],
+      itemStyle: { color: '#E6A23C' }
+    }
+  ]
+}));
+
+const channelEffectOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: ['Shopify', 'TikTok Shop', 'Amazon'] },
+  yAxis: { type: 'value' },
+  series: [
+    {
+      name: 'GMV',
+      type: 'bar',
+      data: [856000, 428000, 528000],
+      itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] }
+    },
+    {
+      name: 'ROI',
+      type: 'line',
+      smooth: true,
+      yAxisIndex: 0,
+      data: [4.3, 3.8, 3.4],
+      itemStyle: { color: '#67C23A' }
+    }
+  ]
+}));
+
+const roiCompareOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: ['折扣活动', '满减活动', '买赠活动', '优惠券'] },
+  yAxis: { type: 'value' },
+  series: [{
+    name: 'ROI',
+    type: 'bar',
+    data: [4.2, 3.8, 3.5, 3.2],
+    itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] }
+  }]
+}));
+
+const loadData = () => {
+  loading.value = true;
+  setTimeout(() => { loading.value = false; }, 300);
+};
+
+const resetFilters = () => {
+  filters.value = { dateRange: null, activityType: '', status: '' };
+};
+
+onMounted(loadData);
+</script>
+
+<style scoped>
+.filter-form :deep(.el-form-item) { margin-bottom: 0; }
+.trend-up { color: var(--el-color-success); }
+.trend-down { color: var(--el-color-danger); }
+</style>

+ 240 - 0
src/views/report/ProcurementReportView.vue

@@ -0,0 +1,240 @@
+<template>
+  <div class="app-page">
+    <section class="glass-card page-hero">
+      <div class="page-hero__meta">
+        <span class="page-hero__eyebrow">Procurement Analytics</span>
+        <h1>采购报表</h1>
+        <p>追踪采购额、到货及时率、质量合格率和供应商排名,优化采购策略。</p>
+      </div>
+      <div class="chip-list">
+        <span class="chip">供应商排名</span>
+        <span class="chip">质量分析</span>
+      </div>
+    </section>
+
+    <section class="glass-card section-card">
+      <el-form inline class="filter-form">
+        <el-form-item label="时间范围">
+          <el-date-picker v-model="filters.dateRange" type="daterange" range-separator="至" start-placeholder="开始" end-placeholder="结束" style="width:240px" />
+        </el-form-item>
+        <el-form-item label="供应商">
+          <el-select v-model="filters.supplier" placeholder="全部供应商" clearable style="width:150px">
+            <el-option label="深圳华通" value="深圳华通" />
+            <el-option label="广州鼎盛" value="广州鼎盛" />
+            <el-option label="东莞鑫达" value="东莞鑫达" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="状态">
+          <el-select v-model="filters.status" placeholder="全部" clearable style="width:120px">
+            <el-option label="已完成" value="已完成" />
+            <el-option label="进行中" value="进行中" />
+            <el-option label="已取消" value="已取消" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="loadData">查询</el-button>
+          <el-button @click="resetFilters">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </section>
+
+    <section class="stat-grid" style="grid-template-columns:repeat(5, 1fr)">
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">本月采购额</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-primary)">¥1,258,600</div>
+        <div class="stat-card__trend trend-up">+15.2% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">采购单数</div>
+        <div class="stat-card__value" style="font-size:22px">86</div>
+        <div class="stat-card__trend">单</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">到货及时率</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-success)">94.2%</div>
+        <div class="stat-card__trend trend-up">+2.1% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">质量合格率</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-success)">97.8%</div>
+        <div class="stat-card__trend trend-up">+0.8% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">平均交期</div>
+        <div class="stat-card__value" style="font-size:22px">12.5天</div>
+        <div class="stat-card__trend trend-down">-1.2天 ↓</div>
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">采购额趋势</h3>
+        <v-chart :option="purchaseTrendOption" autoresize style="height:280px" />
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">供应商采购占比</h3>
+        <v-chart :option="supplierShareOption" autoresize style="height:280px" />
+      </article>
+    </section>
+
+    <section class="glass-card section-card">
+      <h3 style="margin:0 0 16px">供应商排名</h3>
+      <el-table :data="supplierRanking" stripe v-loading="loading">
+        <el-table-column prop="rank" label="排名" width="70" />
+        <el-table-column prop="supplierName" label="供应商" min-width="180" />
+        <el-table-column prop="purchaseAmount" label="采购额" width="130">
+          <template #default="{ row }">
+            <span style="font-weight:600">¥{{ row.purchaseAmount.toLocaleString() }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="orderCount" label="订单数" width="90" />
+        <el-table-column prop="deliveryRate" label="交期达成率" width="110">
+          <template #default="{ row }">
+            <span :style="{ color: row.deliveryRate >= 95 ? 'var(--cb-success)' : 'var(--cb-danger)' }">
+              {{ row.deliveryRate }}%
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="qualityRate" label="合格率" width="90">
+          <template #default="{ row }">
+            <span :style="{ color: row.qualityRate >= 98 ? 'var(--cb-success)' : 'var(--cb-danger)' }">
+              {{ row.qualityRate }}%
+            </span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="avgLeadTime" label="平均交期" width="100">
+          <template #default="{ row }">
+            {{ row.avgLeadTime }}天
+          </template>
+        </el-table-column>
+        <el-table-column prop="ratingLevel" label="等级" width="80">
+          <template #default="{ row }">
+            <el-tag :type="row.ratingLevel === 'A' ? 'success' : row.ratingLevel === 'B' ? '' : 'warning'" size="small">
+              {{ row.ratingLevel }}
+            </el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+    </section>
+
+    <section class="glass-card section-card">
+      <h3 style="margin:0 0 16px">采购明细</h3>
+      <el-table :data="purchaseDetail" stripe v-loading="loading">
+        <el-table-column prop="poNo" label="采购单号" width="160" />
+        <el-table-column prop="supplier" label="供应商" width="150" />
+        <el-table-column prop="sku" label="SKU" width="120" />
+        <el-table-column prop="qty" label="数量" width="80" />
+        <el-table-column prop="unitPrice" label="单价" width="100">
+          <template #default="{ row }">
+            ¥{{ row.unitPrice }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="amount" label="金额" width="120">
+          <template #default="{ row }">
+            <span style="font-weight:600">¥{{ row.amount.toLocaleString() }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="expectedDate" label="预计交期" width="110" />
+        <el-table-column prop="actualDate" label="实际交期" width="110" />
+        <el-table-column prop="status" label="状态" width="100">
+          <template #default="{ row }">
+            <el-tag :type="row.status === '已完成' ? 'success' : row.status === '进行中' ? 'primary' : 'info'" size="small">
+              {{ row.status }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="qualityStatus" label="质检状态" width="100">
+          <template #default="{ row }">
+            <el-tag :type="row.qualityStatus === '合格' ? 'success' : row.qualityStatus === '待检' ? 'warning' : 'danger'" size="small">
+              {{ row.qualityStatus }}
+            </el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+    </section>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, computed } from 'vue';
+import VChart from 'vue-echarts';
+import { use } from 'echarts/core';
+import { CanvasRenderer } from 'echarts/renderers';
+import { LineChart, BarChart, PieChart } from 'echarts/charts';
+import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components';
+
+use([CanvasRenderer, LineChart, BarChart, PieChart, GridComponent, TooltipComponent, LegendComponent]);
+
+const loading = ref(false);
+
+const filters = ref({
+  dateRange: null as [Date, Date] | null,
+  supplier: '',
+  status: ''
+});
+
+const supplierRanking = ref([
+  { rank: 1, supplierName: '深圳华通供应链有限公司', purchaseAmount: 428600, orderCount: 28, deliveryRate: 98.5, qualityRate: 99.2, avgLeadTime: 10, ratingLevel: 'A' },
+  { rank: 2, supplierName: '广州鼎盛纺织制衣厂', purchaseAmount: 325800, orderCount: 22, deliveryRate: 95.0, qualityRate: 97.5, avgLeadTime: 12, ratingLevel: 'A' },
+  { rank: 3, supplierName: '东莞鑫达皮革制品厂', purchaseAmount: 258200, orderCount: 18, deliveryRate: 88.0, qualityRate: 94.0, avgLeadTime: 15, ratingLevel: 'B' },
+  { rank: 4, supplierName: '宁波海天塑业有限公司', purchaseAmount: 185600, orderCount: 12, deliveryRate: 92.0, qualityRate: 96.0, avgLeadTime: 14, ratingLevel: 'B' },
+  { rank: 5, supplierName: '苏州金诚纺织集团', purchaseAmount: 125400, orderCount: 8, deliveryRate: 82.0, qualityRate: 91.0, avgLeadTime: 18, ratingLevel: 'C' }
+]);
+
+const purchaseDetail = ref([
+  { poNo: 'PO-20260420-001', supplier: '深圳华通', sku: 'SKU-NM-BK-M', qty: 500, unitPrice: 85, amount: 42500, expectedDate: '2026-04-25', actualDate: '2026-04-23', status: '已完成', qualityStatus: '合格' },
+  { poNo: 'PO-20260419-002', supplier: '广州鼎盛', sku: 'SKU-AE-GR-L', qty: 800, unitPrice: 42, amount: 33600, expectedDate: '2026-04-28', actualDate: '-', status: '进行中', qualityStatus: '待检' },
+  { poNo: 'PO-20260418-003', supplier: '东莞鑫达', sku: 'SKU-UT-WH-XL', qty: 200, unitPrice: 156, amount: 31200, expectedDate: '2026-04-22', actualDate: '2026-04-25', status: '已完成', qualityStatus: '合格' },
+  { poNo: 'PO-20260417-004', supplier: '宁波海天', sku: 'SKU-UT-BK-42', qty: 150, unitPrice: 185, amount: 27750, expectedDate: '2026-04-30', actualDate: '-', status: '进行中', qualityStatus: '待检' },
+  { poNo: 'PO-20260416-005', supplier: '深圳华通', sku: 'SKU-NM-BK-S', qty: 400, unitPrice: 68, amount: 27200, expectedDate: '2026-04-20', actualDate: '2026-04-19', status: '已完成', qualityStatus: '合格' }
+]);
+
+const days = ['4/14', '4/15', '4/16', '4/17', '4/18', '4/19', '4/20'];
+
+const purchaseTrendOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: days },
+  yAxis: { type: 'value', axisLabel: { formatter: '¥{value}' } },
+  series: [{
+    name: '采购额',
+    type: 'bar',
+    data: [168000, 185000, 172000, 198000, 182000, 215000, 186000],
+    itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] }
+  }]
+}));
+
+const supplierShareOption = computed(() => ({
+  tooltip: { trigger: 'item', formatter: '{b}: ¥{c} ({d}%)' },
+  legend: { orient: 'vertical', right: 20, top: 'center' },
+  series: [{
+    type: 'pie',
+    radius: ['40%', '70%'],
+    center: ['35%', '50%'],
+    data: [
+      { value: 428600, name: '深圳华通', itemStyle: { color: '#409EFF' } },
+      { value: 325800, name: '广州鼎盛', itemStyle: { color: '#67C23A' } },
+      { value: 258200, name: '东莞鑫达', itemStyle: { color: '#E6A23C' } },
+      { value: 185600, name: '宁波海天', itemStyle: { color: '#F56C6C' } },
+      { value: 125400, name: '苏州金诚', itemStyle: { color: '#909399' } }
+    ]
+  }]
+}));
+
+const loadData = () => {
+  loading.value = true;
+  setTimeout(() => { loading.value = false; }, 300);
+};
+
+const resetFilters = () => {
+  filters.value = { dateRange: null, supplier: '', status: '' };
+};
+
+onMounted(loadData);
+</script>
+
+<style scoped>
+.filter-form :deep(.el-form-item) { margin-bottom: 0; }
+.trend-up { color: var(--el-color-success); }
+.trend-down { color: var(--el-color-danger); }
+</style>

+ 251 - 0
src/views/report/ProfitAnalysisView.vue

@@ -0,0 +1,251 @@
+<template>
+  <div class="app-page">
+    <section class="glass-card page-hero">
+      <div class="page-hero__meta">
+        <span class="page-hero__eyebrow">Profit Analytics</span>
+        <h1>利润分析报表</h1>
+        <p>追踪SKU/渠道/供应商维度的成本、毛利和利润率,支持自定义成本分摊规则。</p>
+      </div>
+      <div class="chip-list">
+        <span class="chip">成本自动分摊</span>
+        <span class="chip">利润预警</span>
+      </div>
+    </section>
+
+    <section class="glass-card section-card">
+      <el-form inline class="filter-form">
+        <el-form-item label="时间范围">
+          <el-date-picker v-model="filters.dateRange" type="daterange" range-separator="至" start-placeholder="开始" end-placeholder="结束" style="width:240px" />
+        </el-form-item>
+        <el-form-item label="分析维度">
+          <el-select v-model="filters.dimension" placeholder="选择维度" clearable style="width:130px">
+            <el-option label="按SKU" value="sku" />
+            <el-option label="按渠道" value="channel" />
+            <el-option label="按供应商" value="supplier" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="利润预警">
+          <el-select v-model="filters.alertStatus" placeholder="全部" clearable style="width:120px">
+            <el-option label="正常" value="normal" />
+            <el-option label="预警" value="warning" />
+            <el-option label="亏损" value="loss" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="loadData">查询</el-button>
+          <el-button @click="resetFilters">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </section>
+
+    <section class="stat-grid" style="grid-template-columns:repeat(4, 1fr)">
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">销售额</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-primary)">$328,560</div>
+        <div class="stat-card__trend trend-up">+12.5% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">总成本</div>
+        <div class="stat-card__value" style="font-size:22px">$198,420</div>
+        <div class="stat-card__trend trend-down">+8.2% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">毛利</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-success)">$130,140</div>
+        <div class="stat-card__trend trend-up">+18.3% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">毛利率</div>
+        <div class="stat-card__value" style="font-size:22px">39.6%</div>
+        <div class="stat-card__trend trend-up">+2.1pp ↑</div>
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">成本结构分析</h3>
+        <v-chart :option="costStructureOption" autoresize style="height:280px" />
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">毛利趋势</h3>
+        <v-chart :option="profitTrendOption" autoresize style="height:280px" />
+      </article>
+    </section>
+
+    <section class="glass-card section-card">
+      <h3 style="margin:0 0 16px">利润明细</h3>
+      <el-table :data="profitDetail" stripe v-loading="loading">
+        <el-table-column prop="sku" label="SKU" width="130" />
+        <el-table-column prop="productTitle" label="商品名称" min-width="180" show-overflow-tooltip />
+        <el-table-column prop="salesAmount" label="销售额" width="110">
+          <template #default="{ row }">
+            <span style="font-weight:600">${{ row.salesAmount.toLocaleString() }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="cost" label="成本" width="100">
+          <template #default="{ row }">
+            ${{ row.cost.toLocaleString() }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="grossProfit" label="毛利" width="100">
+          <template #default="{ row }">
+            <span style="color:var(--cb-success);font-weight:600">${{ row.grossProfit.toLocaleString() }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="profitRate" label="毛利率" width="80">
+          <template #default="{ row }">
+            <el-tag :type="row.profitRate >= 30 ? 'success' : row.profitRate >= 15 ? 'warning' : 'danger'" size="small">
+              {{ row.profitRate }}%
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="channel" label="渠道" width="100" />
+        <el-table-column prop="supplier" label="供应商" width="120" show-overflow-tooltip />
+        <el-table-column label="操作" width="100" fixed="right">
+          <template #default="{ row }">
+            <el-button link type="primary" @click="viewCostDetail(row)">成本明细</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </section>
+
+    <el-dialog v-model="costDetailVisible" title="成本明细" width="600px">
+      <el-descriptions :column="2" border v-if="selectedItem">
+        <el-descriptions-item label="SKU">{{ selectedItem.sku }}</el-descriptions-item>
+        <el-descriptions-item label="商品名称" :span="2">{{ selectedItem.productTitle }}</el-descriptions-item>
+        <el-descriptions-item label="商品成本">${{ selectedItem.productCost }}</el-descriptions-item>
+        <el-descriptions-item label="头程运费">${{ selectedItem.freightCost }}</el-descriptions-item>
+        <el-descriptions-item label="平台佣金">${{ selectedItem.platformFee }}</el-descriptions-item>
+        <el-descriptions-item label="关税">${{ selectedItem.customDuty }}</el-descriptions-item>
+        <el-descriptions-item label="其他费用">${{ selectedItem.otherFee }}</el-descriptions-item>
+        <el-descriptions-item label="总成本">${{ selectedItem.cost }}</el-descriptions-item>
+        <el-descriptions-item label="毛利率">
+          <el-tag :type="selectedItem.profitRate >= 30 ? 'success' : selectedItem.profitRate >= 15 ? 'warning' : 'danger'">
+            {{ selectedItem.profitRate }}%
+          </el-tag>
+        </el-descriptions-item>
+      </el-descriptions>
+      <template #footer>
+        <el-button @click="costDetailVisible = false">关闭</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, computed } from 'vue';
+import VChart from 'vue-echarts';
+import { use } from 'echarts/core';
+import { CanvasRenderer } from 'echarts/renderers';
+import { LineChart, BarChart, PieChart } from 'echarts/charts';
+import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components';
+
+use([CanvasRenderer, LineChart, BarChart, PieChart, GridComponent, TooltipComponent, LegendComponent]);
+
+interface ProfitItem {
+  sku: string;
+  productTitle: string;
+  salesAmount: number;
+  cost: number;
+  grossProfit: number;
+  profitRate: number;
+  channel: string;
+  supplier: string;
+  productCost: number;
+  freightCost: number;
+  platformFee: number;
+  customDuty: number;
+  otherFee: number;
+}
+
+const loading = ref(false);
+const costDetailVisible = ref(false);
+const selectedItem = ref<ProfitItem | null>(null);
+
+const filters = ref({
+  dateRange: null as [Date, Date] | null,
+  dimension: 'sku',
+  alertStatus: ''
+});
+
+const profitDetail = ref<ProfitItem[]>([
+  { sku: 'SKU-NM-BK-M', productTitle: 'Nomad 防水背包 黑色 中号', salesAmount: 45800, cost: 26800, grossProfit: 19000, profitRate: 41.5, channel: 'Shopify', supplier: '深圳华通', productCost: 18500, freightCost: 3200, platformFee: 2750, customDuty: 1800, otherFee: 550 },
+  { sku: 'SKU-AE-GR-L', productTitle: 'AeroDry 速干T恤 绿色 L码', salesAmount: 28500, cost: 18200, grossProfit: 10300, profitRate: 36.1, channel: 'TikTok Shop', supplier: '广州鼎盛', productCost: 12800, freightCost: 2100, platformFee: 1710, customDuty: 1200, otherFee: 390 },
+  { sku: 'SKU-UT-WH-XL', productTitle: 'UrbanTrail 徒步鞋 白色 XL', salesAmount: 38600, cost: 26500, grossProfit: 12100, profitRate: 31.3, channel: 'Amazon', supplier: '东莞鑫达', productCost: 18500, freightCost: 3500, platformFee: 2700, customDuty: 1400, otherFee: 400 },
+  { sku: 'SKU-NM-BK-S', productTitle: 'Nomad 防水背包 黑色 小号', salesAmount: 32600, cost: 21800, grossProfit: 10800, profitRate: 33.1, channel: 'Shopify', supplier: '深圳华通', productCost: 15200, freightCost: 2600, platformFee: 1956, customDuty: 1600, otherFee: 444 },
+  { sku: 'SKU-AE-BL-M', productTitle: 'AeroDry 运动短裤 蓝色 M码', salesAmount: 19800, cost: 14200, grossProfit: 5600, profitRate: 28.3, channel: 'TikTok Shop', supplier: '广州鼎盛', productCost: 9800, freightCost: 1800, platformFee: 1188, customDuty: 1000, otherFee: 412 },
+  { sku: 'SKU-UT-BK-42', productTitle: 'UrbanTrail 登山靴 黑色 42码', salesAmount: 42800, cost: 35200, grossProfit: 7600, profitRate: 17.8, channel: 'Amazon', supplier: '宁波海天', productCost: 25800, freightCost: 4200, platformFee: 3200, customDuty: 1600, otherFee: 400 }
+]);
+
+const days = ['4/14', '4/15', '4/16', '4/17', '4/18', '4/19', '4/20'];
+
+const costStructureOption = computed(() => ({
+  tooltip: { trigger: 'item', formatter: '{b}: ${c} ({d}%)' },
+  legend: { orient: 'vertical', right: 20, top: 'center' },
+  series: [{
+    type: 'pie',
+    radius: ['40%', '70%'],
+    center: ['35%', '50%'],
+    data: [
+      { value: 120600, name: '商品成本', itemStyle: { color: '#409EFF' } },
+      { value: 21600, name: '头程运费', itemStyle: { color: '#67C23A' } },
+      { value: 13500, name: '平台佣金', itemStyle: { color: '#E6A23C' } },
+      { value: 8600, name: '关税', itemStyle: { color: '#F56C6C' } },
+      { value: 2600, name: '其他费用', itemStyle: { color: '#909399' } }
+    ]
+  }]
+}));
+
+const profitTrendOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: days },
+  yAxis: { type: 'value', axisLabel: { formatter: '${value}' } },
+  series: [
+    {
+      name: '销售额',
+      type: 'bar',
+      stack: 'total',
+      data: [42800, 51200, 48600, 55200, 49800, 57500, 52300],
+      itemStyle: { color: '#409EFF' }
+    },
+    {
+      name: '成本',
+      type: 'bar',
+      stack: 'total',
+      data: [25800, 30800, 29200, 33200, 29800, 34600, 31600],
+      itemStyle: { color: '#E6A23C' }
+    },
+    {
+      name: '毛利',
+      type: 'line',
+      smooth: true,
+      yAxisIndex: 0,
+      data: [17000, 20400, 19400, 22000, 20000, 22900, 20700],
+      itemStyle: { color: '#67C23A' }
+    }
+  ]
+}));
+
+const loadData = () => {
+  loading.value = true;
+  setTimeout(() => { loading.value = false; }, 300);
+};
+
+const resetFilters = () => {
+  filters.value = { dateRange: null, dimension: 'sku', alertStatus: '' };
+};
+
+const viewCostDetail = (row: ProfitItem) => {
+  selectedItem.value = row;
+  costDetailVisible.value = true;
+};
+
+onMounted(loadData);
+</script>
+
+<style scoped>
+.filter-form :deep(.el-form-item) { margin-bottom: 0; }
+.trend-up { color: var(--el-color-success); }
+.trend-down { color: var(--el-color-danger); }
+</style>

+ 258 - 0
src/views/report/SalesAnalysisView.vue

@@ -0,0 +1,258 @@
+<template>
+  <div class="app-page">
+    <section class="glass-card page-hero">
+      <div class="page-hero__meta">
+        <span class="page-hero__eyebrow">Sales Analytics</span>
+        <h1>销售分析报表</h1>
+        <p>多维度分析销售数据,洞察GMV、订单量、客单价趋势,支持按渠道/国家/商品维度下钻。</p>
+      </div>
+      <div class="chip-list">
+        <span class="chip">实时数据</span>
+        <span class="chip">支持导出</span>
+      </div>
+    </section>
+
+    <section class="glass-card section-card">
+      <el-form inline class="filter-form">
+        <el-form-item label="时间范围">
+          <el-date-picker v-model="filters.dateRange" type="daterange" range-separator="至" start-placeholder="开始" end-placeholder="结束" style="width:240px" />
+        </el-form-item>
+        <el-form-item label="渠道">
+          <el-select v-model="filters.channel" placeholder="全部渠道" clearable style="width:140px">
+            <el-option label="Shopify" value="Shopify" />
+            <el-option label="TikTok Shop" value="TikTok Shop" />
+            <el-option label="Amazon" value="Amazon" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="国家">
+          <el-select v-model="filters.country" placeholder="全部国家" clearable style="width:120px">
+            <el-option label="美国" value="US" />
+            <el-option label="英国" value="UK" />
+            <el-option label="日本" value="JP" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="对比周期">
+          <el-select v-model="filters.comparePeriod" placeholder="选择对比周期" clearable style="width:130px">
+            <el-option label="上周同期" value="lastWeek" />
+            <el-option label="上月同期" value="lastMonth" />
+            <el-option label="去年同期" value="lastYear" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="loadData">查询</el-button>
+          <el-button @click="resetFilters">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </section>
+
+    <section class="stat-grid" style="grid-template-columns:repeat(5, 1fr)">
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">GMV</div>
+        <div class="stat-card__value" style="font-size:22px;color:var(--cb-primary)">$328,560</div>
+        <div class="stat-card__trend trend-up">+12.5% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">订单量</div>
+        <div class="stat-card__value" style="font-size:22px">1,258</div>
+        <div class="stat-card__trend trend-up">+8.3% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">客单价</div>
+        <div class="stat-card__value" style="font-size:22px">$261.2</div>
+        <div class="stat-card__trend trend-up">+3.8% ↑</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">转化率</div>
+        <div class="stat-card__value" style="font-size:22px">3.8%</div>
+        <div class="stat-card__trend trend-down">-0.2% ↓</div>
+      </article>
+      <article class="glass-card stat-card">
+        <div class="stat-card__label">复购率</div>
+        <div class="stat-card__value" style="font-size:22px">18.5%</div>
+        <div class="stat-card__trend trend-up">+1.2% ↑</div>
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">GMV 趋势</h3>
+        <v-chart :option="gmvTrendOption" autoresize style="height:300px" />
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">订单量趋势</h3>
+        <v-chart :option="orderTrendOption" autoresize style="height:300px" />
+      </article>
+    </section>
+
+    <section class="page-grid page-grid--two">
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">渠道销售占比</h3>
+        <v-chart :option="channelPieOption" autoresize style="height:280px" />
+      </article>
+      <article class="glass-card section-card">
+        <h3 style="margin:0 0 16px">TOP 10 销售商品</h3>
+        <el-table :data="topProducts" stripe size="small">
+          <el-table-column prop="rank" label="排名" width="60" />
+          <el-table-column prop="title" label="商品名称" min-width="180" show-overflow-tooltip />
+          <el-table-column prop="salesQty" label="销量" width="80" />
+          <el-table-column prop="salesAmount" label="销售额" width="100" />
+        </el-table>
+      </article>
+    </section>
+
+    <section class="glass-card section-card">
+      <h3 style="margin:0 0 16px">销售明细</h3>
+      <el-table :data="salesDetail" stripe v-loading="loading">
+        <el-table-column prop="date" label="日期" width="110" />
+        <el-table-column prop="channel" label="渠道" width="100" />
+        <el-table-column prop="country" label="国家" width="80" />
+        <el-table-column prop="orderCount" label="订单数" width="80" />
+        <el-table-column prop="gmv" label="GMV" width="120">
+          <template #default="{ row }">
+            <span style="font-weight:600">${{ row.gmv.toLocaleString() }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="avgOrderValue" label="客单价" width="100" />
+        <el-table-column prop="conversionRate" label="转化率" width="80" />
+        <el-table-column prop="mom" label="环比" width="80">
+          <template #default="{ row }">
+            <span :class="row.mom >= 0 ? 'trend-up' : 'trend-down'">{{ row.mom >= 0 ? '+' : '' }}{{ row.mom }}%</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="yoy" label="同比" width="80">
+          <template #default="{ row }">
+            <span :class="row.yoy >= 0 ? 'trend-up' : 'trend-down'">{{ row.yoy >= 0 ? '+' : '' }}{{ row.yoy }}%</span>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div style="display:flex;justify-content:flex-end;margin-top:16px">
+        <el-pagination v-model:current-page="page" v-model:page-size="pageSize" :total="total" :page-sizes="[10, 20, 50]" layout="total, sizes, prev, pager, next" />
+      </div>
+    </section>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { onMounted, ref, computed } from 'vue';
+import VChart from 'vue-echarts';
+import { use } from 'echarts/core';
+import { CanvasRenderer } from 'echarts/renderers';
+import { LineChart, BarChart, PieChart } from 'echarts/charts';
+import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components';
+
+use([CanvasRenderer, LineChart, BarChart, PieChart, GridComponent, TooltipComponent, LegendComponent]);
+
+const loading = ref(false);
+const page = ref(1);
+const pageSize = ref(10);
+const total = ref(0);
+
+const filters = ref({
+  dateRange: null as [Date, Date] | null,
+  channel: '',
+  country: '',
+  comparePeriod: 'lastWeek'
+});
+
+const salesDetail = ref([
+  { date: '2026-04-20', channel: 'Shopify', country: 'US', orderCount: 128, gmv: 35680, avgOrderValue: 278.75, conversionRate: 4.2, mom: 5.8, yoy: 12.3 },
+  { date: '2026-04-20', channel: 'TikTok Shop', country: 'UK', orderCount: 86, gmv: 18920, avgOrderValue: 220.00, conversionRate: 3.5, mom: 8.2, yoy: 25.6 },
+  { date: '2026-04-19', channel: 'Shopify', country: 'JP', orderCount: 95, gmv: 28450, avgOrderValue: 299.47, conversionRate: 3.8, mom: -2.1, yoy: 8.9 },
+  { date: '2026-04-19', channel: 'Amazon', country: 'US', orderCount: 156, gmv: 42180, avgOrderValue: 270.38, conversionRate: 4.5, mom: 12.4, yoy: 15.2 },
+  { date: '2026-04-18', channel: 'TikTok Shop', country: 'US', orderCount: 68, gmv: 15200, avgOrderValue: 223.53, conversionRate: 3.2, mom: -5.6, yoy: 32.1 }
+]);
+
+const topProducts = ref([
+  { rank: 1, title: 'Nomad 防水背包 黑色 中号', salesQty: 258, salesAmount: '¥186,240' },
+  { rank: 2, title: 'AeroDry 速干T恤 绿色 L码', salesQty: 425, salesAmount: '¥89,250' },
+  { rank: 3, title: 'UrbanTrail 徒步鞋 白色 XL', salesQty: 186, salesAmount: '¥128,340' },
+  { rank: 4, title: 'Nomad 防水背包 黑色 小号', salesQty: 168, salesAmount: '¥100,632' },
+  { rank: 5, title: 'AeroDry 运动短裤 蓝色 M码', salesQty: 312, salesAmount: '¥54,600' },
+  { rank: 6, title: 'UrbanTrail 登山靴 黑色 42码', salesQty: 95, salesAmount: '¥86,450' },
+  { rank: 7, title: 'Nomad 防水背包 灰色 大号', salesQty: 142, salesAmount: '¥109,340' },
+  { rank: 8, title: 'AeroDry 速干帽 黑色', salesQty: 520, salesAmount: '¥41,600' },
+  { rank: 9, title: 'UrbanTrail 徒步袜 专业款', salesQty: 680, salesAmount: '¥27,200' },
+  { rank: 10, title: 'Nomad 收纳袋 套装', salesQty: 385, salesAmount: '¥34,650' }
+]);
+
+const days = ['4/14', '4/15', '4/16', '4/17', '4/18', '4/19', '4/20'];
+
+const gmvTrendOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 60, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: days },
+  yAxis: { type: 'value', axisLabel: { formatter: '${value}' } },
+  series: [
+    {
+      name: '本期GMV',
+      type: 'line',
+      smooth: true,
+      data: [32800, 41200, 38600, 45200, 39800, 47500, 42300],
+      areaStyle: { opacity: 0.15 },
+      itemStyle: { color: '#409EFF' }
+    },
+    {
+      name: '上期GMV',
+      type: 'line',
+      smooth: true,
+      data: [29000, 35500, 34200, 38800, 36500, 41200, 37600],
+      itemStyle: { color: '#909399' },
+      lineStyle: { type: 'dashed' }
+    }
+  ]
+}));
+
+const orderTrendOption = computed(() => ({
+  tooltip: { trigger: 'axis' },
+  grid: { left: 50, right: 20, top: 20, bottom: 30 },
+  xAxis: { type: 'category', data: days },
+  yAxis: { type: 'value' },
+  series: [
+    {
+      name: '本期订单',
+      type: 'bar',
+      data: [128, 156, 142, 168, 152, 178, 156],
+      itemStyle: { color: '#409EFF', borderRadius: [4, 4, 0, 0] }
+    },
+    {
+      name: '上期订单',
+      type: 'bar',
+      data: [112, 138, 128, 148, 138, 162, 142],
+      itemStyle: { color: '#E6A23C', borderRadius: [4, 4, 0, 0] }
+    }
+  ]
+}));
+
+const channelPieOption = computed(() => ({
+  tooltip: { trigger: 'item', formatter: '{b}: ${c} ({d}%)' },
+  legend: { orient: 'vertical', right: 20, top: 'center' },
+  series: [{
+    type: 'pie',
+    radius: ['40%', '70%'],
+    center: ['35%', '50%'],
+    data: [
+      { value: 158200, name: 'Shopify', itemStyle: { color: '#409EFF' } },
+      { value: 89200, name: 'TikTok Shop', itemStyle: { color: '#67C23A' } },
+      { value: 81200, name: 'Amazon', itemStyle: { color: '#E6A23C' } }
+    ],
+    label: { show: false }
+  }]
+}));
+
+const loadData = () => {
+  loading.value = true;
+  setTimeout(() => { loading.value = false; }, 300);
+};
+
+const resetFilters = () => {
+  filters.value = { dateRange: null, channel: '', country: '', comparePeriod: 'lastWeek' };
+};
+
+onMounted(loadData);
+</script>
+
+<style scoped>
+.filter-form :deep(.el-form-item) { margin-bottom: 0; }
+.trend-up { color: var(--el-color-success); }
+.trend-down { color: var(--el-color-danger); }
+</style>