| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- <template>
- <div class="app-page">
- <section class="glass-card section-card">
- <el-form :model="filters" inline class="filter-form">
- <el-form-item label="SKU">
- <el-input v-model="filters.sku" placeholder="SKU编号" clearable style="width:160px" @keyup.enter="loadData" />
- </el-form-item>
- <el-form-item label="仓库">
- <el-select v-model="filters.warehouse" placeholder="全部仓库" clearable style="width:140px">
- <el-option v-for="w in warehouses" :key="w" :label="w" :value="w" />
- </el-select>
- </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="category" />
- <el-option label="按仓库" value="warehouse" />
- </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="glass-card section-card" style="padding:12px 24px">
- <div class="table-toolbar" style="margin-bottom:0">
- <div class="chip-list">
- <el-button type="primary" @click="setAlert">设置预警</el-button>
- <el-button @click="doExport">导出报表</el-button>
- </div>
- <el-button @click="loadData">刷新</el-button>
- </div>
- </section>
- <section class="glass-card section-card" style="padding:16px">
- <div class="stat-grid" style="grid-template-columns:repeat(5, 1fr)">
- <article class="stat-card">
- <div class="stat-card__label">库存周转天数</div>
- <div class="stat-card__value" style="font-size:24px;color:var(--cb-primary)">28天</div>
- </article>
- <article class="stat-card">
- <div class="stat-card__label">动销率</div>
- <div class="stat-card__value" style="font-size:24px">76%</div>
- </article>
- <article class="stat-card">
- <div class="stat-card__label">滞销SKU</div>
- <div class="stat-card__value" style="font-size:24px;color:var(--cb-accent)">15</div>
- </article>
- <article class="stat-card">
- <div class="stat-card__label">库存覆盖天数</div>
- <div class="stat-card__value" style="font-size:24px">42天</div>
- </article>
- <article class="stat-card">
- <div class="stat-card__label">平均库龄</div>
- <div class="stat-card__value" style="font-size:24px">35天</div>
- </article>
- </div>
- </section>
- <section class="glass-card section-card">
- <el-table :data="filteredItems" stripe style="width:100%" v-loading="loading">
- <el-table-column prop="sku" label="SKU" width="160" />
- <el-table-column prop="productTitle" label="商品名称" min-width="200" show-overflow-tooltip />
- <el-table-column prop="warehouse" label="仓库" width="120" />
- <el-table-column prop="available" label="可用库存" width="90" align="center" />
- <el-table-column prop="sales30d" label="30天销量" width="90" align="center" />
- <el-table-column prop="turnoverDays" label="周转天数" width="90" align="center">
- <template #default="{ row }">
- <span :class="turnoverClass(row.turnoverDays)">{{ row.turnoverDays }}天</span>
- </template>
- </el-table-column>
- <el-table-column prop="stockDays" label="库存覆盖天数" width="110" align="center">
- <template #default="{ row }">
- <span :class="stockDaysClass(row.stockDays)">{{ row.stockDays }}天</span>
- </template>
- </el-table-column>
- <el-table-column prop="avgAge" label="平均库龄" width="90" align="center">
- <template #default="{ row }">
- {{ row.avgAge }}天
- </template>
- </el-table-column>
- <el-table-column prop="status" label="状态" width="90">
- <template #default="{ row }">
- <el-tag :type="statusTag(row.status)" size="small">{{ row.status }}</el-tag>
- </template>
- </el-table-column>
- <el-table-column label="操作" width="120" fixed="right">
- <template #default="{ row }">
- <el-button link type="primary" @click="openDetail(row)">详情</el-button>
- <el-button link type="primary" @click="createOrder(row)">补货</el-button>
- </template>
- </el-table-column>
- <template #empty>
- <el-empty description="暂无数据" />
- </template>
- </el-table>
- </section>
- </div>
- </template>
- <script setup lang="ts">
- import { computed, onMounted, ref } from 'vue';
- import { ElMessage } from 'element-plus';
- interface TurnoverItem {
- sku: string;
- productTitle: string;
- warehouse: string;
- available: number;
- sales30d: number;
- turnoverDays: number;
- stockDays: number;
- avgAge: number;
- status: string;
- }
- const items = ref<TurnoverItem[]>([
- { sku: 'SKU-LUGG-20-BLK', productTitle: 'TravelFlex Carry-On / Black', warehouse: '深圳南山仓', available: 15, sales30d: 240, turnoverDays: 15, stockDays: 18, avgAge: 20, status: '正常' },
- { sku: 'SKU-BAG-ML-BRW', productTitle: 'Classic Leather Tote / Brown', warehouse: '义乌商贸仓', available: 45, sales30d: 150, turnoverDays: 28, stockDays: 30, avgAge: 25, status: '正常' },
- { sku: 'SKU-SPRT-YGA-BLU', productTitle: 'Yoga Mat Pro / Blue', warehouse: '深圳南山仓', available: 20, sales30d: 360, turnoverDays: 8, stockDays: 5, avgAge: 12, status: '滞销' },
- { sku: 'SKU-LUGG-28-NVY', productTitle: 'TravelFlex Large Check-In / Navy', warehouse: '洛杉矶海外仓', available: 8, sales30d: 90, turnoverDays: 45, stockDays: 9, avgAge: 60, status: '滞销' },
- { sku: 'SKU-BAG-BPK-OLV', productTitle: 'Urban Backpack / Olive', warehouse: '义乌商贸仓', available: 55, sales30d: 180, turnoverDays: 32, stockDays: 30, avgAge: 40, status: '正常' },
- { sku: 'SKU-TOWEL-SET-MIX', productTitle: 'AeroDry Towel Set', warehouse: '深圳南山仓', available: 30, sales30d: 300, turnoverDays: 12, stockDays: 10, avgAge: 18, status: '正常' },
- { sku: 'SKU-SPRT-BTL-GRN', productTitle: 'Sports Bottle 750ml / Green', warehouse: '洛杉矶海外仓', available: 120, sales30d: 60, turnoverDays: 60, stockDays: 200, avgAge: 90, status: '严重滞销' }
- ]);
- const loading = ref(false);
- const warehouses = ['深圳南山仓', '义乌商贸仓', '洛杉矶海外仓'];
- const filters = ref({ sku: '', warehouse: '', dimension: '' });
- const filteredItems = computed(() => {
- return items.value.filter(item => {
- if (filters.value.sku && !item.sku.includes(filters.value.sku) && !item.productTitle.includes(filters.value.sku)) return false;
- if (filters.value.warehouse && item.warehouse !== filters.value.warehouse) return false;
- return true;
- });
- });
- const turnoverClass = (days: number) => {
- if (days > 60) return 'text-danger';
- if (days > 30) return 'text-warning';
- return '';
- };
- const stockDaysClass = (days: number) => {
- if (days < 10) return 'text-danger';
- if (days < 20) return 'text-warning';
- return '';
- };
- const statusTag = (status: string) => {
- const map: Record<string, string> = { '正常': 'success', '滞销': 'warning', '严重滞销': 'danger' };
- return map[status] || '';
- };
- const loadData = () => { loading.value = true; setTimeout(() => { loading.value = false; }, 300); };
- const resetFilters = () => { filters.value = { sku: '', warehouse: '', dimension: '' }; };
- const setAlert = () => { ElMessage.info('预警设置功能开发中'); };
- const doExport = () => { ElMessage.info('导出开始'); };
- const openDetail = (row: TurnoverItem) => { ElMessage.info(`查看 ${row.sku} 详情`); };
- const createOrder = (row: TurnoverItem) => { ElMessage.success(`已为 ${row.sku} 生成补货建议`); };
- onMounted(loadData);
- </script>
- <style scoped>
- .filter-form :deep(.el-form-item) { margin-bottom: 0; }
- .text-danger { color: var(--cb-danger); font-weight: 600; }
- .text-warning { color: var(--cb-accent); font-weight: 600; }
- </style>
|