feat: 更新订单和用户视图,增强订单信息展示,支持充值类型订单
This commit is contained in:
@@ -50,19 +50,24 @@
|
||||
<div class="space-y-4">
|
||||
<div v-for="order in recentOrders" :key="order.id" @click="$router.push(`/me/orders/${order.id}`)"
|
||||
class="flex items-center gap-4 p-4 border border-slate-100 rounded-lg hover:border-primary-100 hover:shadow-sm transition-all cursor-pointer active:scale-[0.99] group">
|
||||
<div class="w-16 h-16 bg-slate-100 rounded object-cover flex-shrink-0">
|
||||
<img v-if="order.items && order.items.length > 0"
|
||||
<div class="w-16 h-16 bg-slate-100 rounded flex-shrink-0 flex items-center justify-center relative overflow-hidden">
|
||||
<template v-if="order.type === 'recharge' || !order.items?.length">
|
||||
<i class="pi pi-wallet text-2xl text-primary-500"></i>
|
||||
</template>
|
||||
<img v-else-if="order.items && order.items.length > 0"
|
||||
:src="order.items[0].cover"
|
||||
class="w-full h-full object-cover rounded transition-transform group-hover:scale-105">
|
||||
<i v-else class="pi pi-box text-2xl text-slate-400"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h3 class="font-bold text-slate-900 truncate group-hover:text-primary-600 transition-colors">
|
||||
{{ order.items && order.items.length > 0 ? order.items[0].title : '未知商品' }}</h3>
|
||||
{{ (order.type === 'recharge' || !order.items?.length) ? '账户充值' : (order.items?.[0]?.title || '未知商品') }}
|
||||
</h3>
|
||||
<div class="text-sm text-slate-500 mt-1">{{ order.create_time }} · 订单号: {{ order.id }}</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="font-bold text-slate-900">¥ {{ order.amount }}</div>
|
||||
<div class="text-sm text-green-600 mt-1">{{ order.status }}</div>
|
||||
<div class="text-sm mt-1 font-medium" :class="statusColor(order.status)">{{ order.status_description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="recentOrders.length === 0" class="text-center text-slate-400 py-4">暂无订单</div>
|
||||
@@ -90,22 +95,38 @@ const wallet = ref({ balance: 0, points: 0 });
|
||||
const couponCount = ref(0);
|
||||
const recentOrders = ref([]);
|
||||
|
||||
const statusColor = (status) => {
|
||||
const map = {
|
||||
created: 'text-orange-600',
|
||||
paid: 'text-blue-600',
|
||||
completed: 'text-green-600',
|
||||
refunding: 'text-purple-600',
|
||||
refunded: 'text-slate-500',
|
||||
cancelled: 'text-slate-400'
|
||||
};
|
||||
return map[status] || 'text-slate-500';
|
||||
};
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const w = await userApi.getWallet();
|
||||
wallet.value.balance = w.balance || 0;
|
||||
|
||||
const u = await userApi.getMe();
|
||||
wallet.value.points = u.points || 0;
|
||||
|
||||
const c = await userApi.getCoupons('unused');
|
||||
couponCount.value = c.length;
|
||||
|
||||
const o = await userApi.getOrders('all');
|
||||
recentOrders.value = (o || []).slice(0, 3);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
// Fetch Wallet
|
||||
userApi.getWallet()
|
||||
.then(w => { wallet.value.balance = w.balance || 0; })
|
||||
.catch(e => console.error("Wallet fetch failed:", e));
|
||||
|
||||
// Fetch User Info (Points)
|
||||
userApi.getMe()
|
||||
.then(u => { wallet.value.points = u.points || 0; })
|
||||
.catch(e => console.error("Me fetch failed:", e));
|
||||
|
||||
// Fetch Coupons
|
||||
userApi.getCoupons('unused')
|
||||
.then(c => { couponCount.value = (c || []).length; })
|
||||
.catch(e => console.error("Coupons fetch failed:", e));
|
||||
|
||||
// Fetch Recent Orders
|
||||
userApi.getOrders('all')
|
||||
.then(o => { recentOrders.value = (o || []).slice(0, 3); })
|
||||
.catch(e => console.error("Orders fetch failed:", e));
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -32,25 +32,40 @@
|
||||
<!-- Order Header -->
|
||||
<div class="bg-slate-50 px-4 py-3 flex items-center justify-between text-sm text-slate-500">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="font-medium text-slate-900">{{ order.date }}</span>
|
||||
<span class="font-medium text-slate-900">{{ order.create_time }}</span>
|
||||
<span class="select-all">订单号: {{ order.id }}</span>
|
||||
<span class="hover:text-primary-600 cursor-pointer transition-colors">{{ order.tenantName }} <i class="pi pi-angle-right text-xs"></i></span>
|
||||
<span class="hover:text-primary-600 cursor-pointer transition-colors" v-if="order.tenant_id !== '0'">{{ order.tenant_name }} <i class="pi pi-angle-right text-xs"></i></span>
|
||||
<span v-else class="text-slate-500">平台自营</span>
|
||||
</div>
|
||||
<div class="font-bold" :class="statusColor(order.status)">{{ statusText(order.status) }}</div>
|
||||
<div class="font-bold" :class="statusColor(order.status)">{{ order.status_description }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Order Body -->
|
||||
<div class="p-4 flex flex-col sm:flex-row gap-6">
|
||||
<!-- Product Info (Clickable Area) -->
|
||||
<div class="flex-1 flex gap-4 cursor-pointer" @click="$router.push(`/me/orders/${order.id}`)">
|
||||
<div class="w-24 h-16 bg-slate-100 rounded object-cover flex-shrink-0 relative overflow-hidden group-hover:opacity-90 transition-opacity">
|
||||
<img :src="order.cover" class="w-full h-full object-cover">
|
||||
<div v-if="order.type === 'video'" class="absolute inset-0 flex items-center justify-center bg-black/20 text-white"><i class="pi pi-play-circle"></i></div>
|
||||
<div class="w-24 h-16 bg-slate-100 rounded flex-shrink-0 relative overflow-hidden group-hover:opacity-90 transition-opacity flex items-center justify-center">
|
||||
<template v-if="order.type === 'recharge' || !order.items?.length">
|
||||
<i class="pi pi-wallet text-3xl text-primary-500"></i>
|
||||
</template>
|
||||
<template v-else-if="order.items && order.items.length > 0">
|
||||
<img :src="order.items[0].cover" class="w-full h-full object-cover">
|
||||
<!-- Assuming genre is on item, not order.type -->
|
||||
</template>
|
||||
<template v-else>
|
||||
<i class="pi pi-box text-2xl text-slate-400"></i>
|
||||
</template>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="font-bold text-slate-900 line-clamp-1 mb-1 group-hover:text-primary-600 transition-colors">{{ order.title }}</h3>
|
||||
<div class="text-xs text-slate-500 mb-2">{{ order.typeLabel }}</div>
|
||||
<div v-if="order.isVirtual" class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-blue-50 text-blue-600">虚拟发货</div>
|
||||
<h3 class="font-bold text-slate-900 line-clamp-1 mb-1 group-hover:text-primary-600 transition-colors">
|
||||
{{ (order.type === 'recharge' || !order.items?.length) ? '账户充值' : (order.items?.[0]?.title || '未知商品') }}
|
||||
</h3>
|
||||
<div class="text-xs text-slate-500 mb-2">
|
||||
{{ (order.type === 'recharge' || !order.items?.length) ? '在线充值' : (order.items?.[0]?.genre || '数字内容') }}
|
||||
</div>
|
||||
<div v-if="order.is_virtual || order.type === 'recharge' || !order.items?.length" class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-blue-50 text-blue-600">
|
||||
{{ (order.type === 'recharge' || !order.items?.length) ? '即时到账' : '虚拟发货' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -61,10 +76,10 @@
|
||||
<div class="text-xs text-slate-400">在线支付</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<button v-if="order.status === 'unpaid'" class="px-4 py-1.5 bg-primary-600 text-white text-sm font-medium rounded-lg hover:bg-primary-700 transition-colors shadow-sm active:scale-95 cursor-pointer">去支付</button>
|
||||
<button v-if="order.status === 'created'" class="px-4 py-1.5 bg-primary-600 text-white text-sm font-medium rounded-lg hover:bg-primary-700 transition-colors shadow-sm active:scale-95 cursor-pointer">去支付</button>
|
||||
<router-link :to="`/me/orders/${order.id}`" v-if="order.status === 'paid' || order.status === 'completed'" class="px-4 py-1.5 border border-slate-300 text-slate-700 text-sm font-medium rounded-lg hover:bg-slate-50 hover:border-slate-400 transition-colors inline-block text-center cursor-pointer active:scale-95">查看详情</router-link>
|
||||
<button v-if="order.status === 'completed'" class="px-4 py-1.5 text-primary-600 text-sm hover:underline cursor-pointer">申请售后</button>
|
||||
<button v-if="order.status === 'unpaid'" class="text-xs text-slate-400 hover:text-slate-600 cursor-pointer">取消订单</button>
|
||||
<button v-if="order.status === 'completed' && order.type !== 'recharge'" class="px-4 py-1.5 text-primary-600 text-sm hover:underline cursor-pointer">申请售后</button>
|
||||
<button v-if="order.status === 'created'" class="text-xs text-slate-400 hover:text-slate-600 cursor-pointer">取消订单</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -124,18 +139,6 @@ watch(currentTab, () => {
|
||||
// Use orders directly (filtered by backend)
|
||||
const filteredOrders = computed(() => orders.value);
|
||||
|
||||
const statusText = (status) => {
|
||||
const map = {
|
||||
created: '待支付',
|
||||
paid: '已支付',
|
||||
completed: '交易成功',
|
||||
refunding: '退款中',
|
||||
refunded: '已退款',
|
||||
cancelled: '已取消'
|
||||
};
|
||||
return map[status] || status;
|
||||
};
|
||||
|
||||
const statusColor = (status) => {
|
||||
const map = {
|
||||
created: 'text-orange-600',
|
||||
|
||||
Reference in New Issue
Block a user