导入 AKSRT 主题开发源码
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<div class="aksrt-page-container">
|
||||
<PageHeader title="商城&商品" desc="商品管理、订单系统、库存管理等电商功能。" />
|
||||
|
||||
<div class="aksrt-shop-dashboard">
|
||||
<!-- 统计卡片 -->
|
||||
<div class="aksrt-shop-dashboard__stats">
|
||||
<div class="aksrt-shop-stat-card">
|
||||
<div class="aksrt-shop-stat-card__icon"><i class="fas fa-box"></i></div>
|
||||
<div class="aksrt-shop-stat-card__info">
|
||||
<span class="aksrt-shop-stat-card__value">{{ overview.product_count }}</span>
|
||||
<span class="aksrt-shop-stat-card__label">商品数量</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aksrt-shop-stat-card">
|
||||
<div class="aksrt-shop-stat-card__icon"><i class="fas fa-file-invoice"></i></div>
|
||||
<div class="aksrt-shop-stat-card__info">
|
||||
<span class="aksrt-shop-stat-card__value">{{ overview.order_count }}</span>
|
||||
<span class="aksrt-shop-stat-card__label">订单数量</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aksrt-shop-stat-card">
|
||||
<div class="aksrt-shop-stat-card__icon"><i class="fas fa-coins"></i></div>
|
||||
<div class="aksrt-shop-stat-card__info">
|
||||
<span class="aksrt-shop-stat-card__value">{{ revenueDisplay }}</span>
|
||||
<span class="aksrt-shop-stat-card__label">累计收入 (元)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="aksrt-shop-stat-card">
|
||||
<div class="aksrt-shop-stat-card__icon"><i class="fas fa-clock"></i></div>
|
||||
<div class="aksrt-shop-stat-card__info">
|
||||
<span class="aksrt-shop-stat-card__value">{{ overview.order_pending }}</span>
|
||||
<span class="aksrt-shop-stat-card__label">待处理订单</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 最近商品 -->
|
||||
<n-card class="aksrt-section-card" title="最近商品">
|
||||
<n-data-table
|
||||
v-if="products.length"
|
||||
:columns="productColumns"
|
||||
:data="products"
|
||||
:bordered="false"
|
||||
size="small"
|
||||
/>
|
||||
<n-empty v-else description="暂无商品" />
|
||||
</n-card>
|
||||
|
||||
<!-- 最近订单 -->
|
||||
<n-card class="aksrt-section-card" title="最近订单" style="margin-top:16px;">
|
||||
<n-data-table
|
||||
v-if="orders.length"
|
||||
:columns="orderColumns"
|
||||
:data="orders"
|
||||
:bordered="false"
|
||||
size="small"
|
||||
/>
|
||||
<n-empty v-else description="暂无订单" />
|
||||
</n-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, h } from 'vue'
|
||||
import { NTag } from 'naive-ui'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
import api from '@/api/index.js'
|
||||
|
||||
const overview = ref({ product_count: 0, order_count: 0, order_pending: 0, revenue_total: 0 })
|
||||
const products = ref([])
|
||||
const orders = ref([])
|
||||
|
||||
const revenueDisplay = computed(() => (overview.value.revenue_total || 0).toFixed(2))
|
||||
|
||||
const statusMap = {
|
||||
created: { label: '已创建', type: 'default' },
|
||||
pending: { label: '待支付', type: 'warning' },
|
||||
paid: { label: '已支付', type: 'success' },
|
||||
delivered: { label: '已发货', type: 'info' },
|
||||
completed: { label: '已完成', type: 'success' },
|
||||
cancelled: { label: '已取消', type: 'default' },
|
||||
expired: { label: '已过期', type: 'default' },
|
||||
refunding: { label: '退款中', type: 'warning' },
|
||||
refunded: { label: '已退款', type: 'error' },
|
||||
}
|
||||
|
||||
const productColumns = [
|
||||
{ title: '商品名称', key: 'title', ellipsis: { tooltip: true } },
|
||||
{ title: '价格', key: 'price', width: 100, render: (row) => '¥' + (row.price || 0).toFixed(2) },
|
||||
{ title: '库存', key: 'stock', width: 80 },
|
||||
{ title: '销量', key: 'sales', width: 80 },
|
||||
{ title: '创建时间', key: 'created', width: 160 },
|
||||
]
|
||||
|
||||
const orderColumns = [
|
||||
{ title: '订单号', key: 'order_number', width: 180, ellipsis: { tooltip: true } },
|
||||
{ title: '产品类型', key: 'product_type', width: 100 },
|
||||
{ title: '金额', key: 'amount', width: 100, render: (row) => '¥' + (row.amount || 0).toFixed(2) },
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
width: 100,
|
||||
render: (row) => {
|
||||
const s = statusMap[row.status] || { label: row.status, type: 'default' }
|
||||
return h(NTag, { size: 'small', type: s.type }, () => s.label)
|
||||
},
|
||||
},
|
||||
{ title: '创建时间', key: 'created_at', width: 160 },
|
||||
]
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const [overviewRes, productsRes, ordersRes] = await Promise.all([
|
||||
api.request('/shop/overview'),
|
||||
api.request('/shop/products?per_page=5'),
|
||||
api.request('/shop/orders?per_page=5'),
|
||||
])
|
||||
if (overviewRes?.success && overviewRes.data) {
|
||||
overview.value = { ...overview.value, ...overviewRes.data }
|
||||
}
|
||||
if (productsRes?.success && productsRes.data) {
|
||||
products.value = productsRes.data.items || []
|
||||
}
|
||||
if (ordersRes?.success && ordersRes.data) {
|
||||
orders.value = ordersRes.data.items || []
|
||||
}
|
||||
} catch {
|
||||
// endpoints may not be available yet
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.aksrt-shop-dashboard__stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.aksrt-shop-stat-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.aksrt-shop-stat-card__icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
background: #f0f5ff;
|
||||
color: #1890ff;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.aksrt-shop-stat-card__info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.aksrt-shop-stat-card__value {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #1a1a2e;
|
||||
}
|
||||
|
||||
.aksrt-shop-stat-card__label {
|
||||
font-size: 13px;
|
||||
color: #7a7f8a;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user