feat: 更新订单和用户视图,增强订单信息展示,支持充值类型订单

This commit is contained in:
2025-12-31 12:19:01 +08:00
parent 95bc5bdb5d
commit c133169c7b
5 changed files with 161 additions and 105 deletions

View File

@@ -40,16 +40,19 @@ type RechargeResponse struct {
} }
type Order struct { type Order struct {
ID string `json:"id"` ID string `json:"id"`
CreateTime string `json:"create_time"` Type string `json:"type"` // consts.OrderType...
PayTime string `json:"pay_time"` TypeDescription string `json:"type_description"`
Status string `json:"status"` CreateTime string `json:"create_time"`
Amount float64 `json:"amount"` PayTime string `json:"pay_time"`
Quantity int `json:"quantity"` Status string `json:"status"`
Items []ContentItem `json:"items"` StatusDescription string `json:"status_description"`
TenantID string `json:"tenant_id"` Amount float64 `json:"amount"`
TenantName string `json:"tenant_name"` Quantity int `json:"quantity"`
IsVirtual bool `json:"is_virtual"` Items []ContentItem `json:"items"`
TenantID string `json:"tenant_id"`
TenantName string `json:"tenant_name"`
IsVirtual bool `json:"is_virtual"`
} }
type Notification struct { type Notification struct {

View File

@@ -353,11 +353,14 @@ func (s *order) Status(ctx context.Context, id string) (*transaction_dto.OrderSt
func (s *order) composeOrderDTO(ctx context.Context, o *models.Order) (user_dto.Order, error) { func (s *order) composeOrderDTO(ctx context.Context, o *models.Order) (user_dto.Order, error) {
dto := user_dto.Order{ dto := user_dto.Order{
ID: cast.ToString(o.ID), ID: cast.ToString(o.ID),
Status: string(o.Status), Type: string(o.Type),
Amount: float64(o.AmountPaid) / 100.0, TypeDescription: o.Type.Description(),
CreateTime: o.CreatedAt.Format(time.RFC3339), Status: string(o.Status),
TenantID: cast.ToString(o.TenantID), StatusDescription: o.Status.Description(),
Amount: float64(o.AmountPaid) / 100.0,
CreateTime: o.CreatedAt.Format(time.RFC3339),
TenantID: cast.ToString(o.TenantID),
} }
// Fetch Tenant Name // Fetch Tenant Name

View File

@@ -10,8 +10,9 @@
<p class="text-sm text-slate-500">订单号: {{ order.id }}</p> <p class="text-sm text-slate-500">订单号: {{ order.id }}</p>
</div> </div>
<div class="ml-auto"> <div class="ml-auto">
<span class="px-3 py-1 rounded-full text-sm font-bold bg-green-50 text-green-600 border border-green-100" v-if="order.status === 'completed'">交易成功</span> <span class="px-3 py-1 rounded-full text-sm font-bold border" :class="statusBadgeClass(order.status)">
<span class="px-3 py-1 rounded-full text-sm font-bold bg-orange-50 text-orange-600 border border-orange-100" v-else-if="order.status === 'unpaid'">待支付</span> {{ order.status_description }}
</span>
</div> </div>
</div> </div>
@@ -29,22 +30,22 @@
<div class="w-9 h-9 rounded-full bg-green-500 text-white flex items-center justify-center font-bold text-sm border-4 border-slate-50"><i class="pi pi-check"></i></div> <div class="w-9 h-9 rounded-full bg-green-500 text-white flex items-center justify-center font-bold text-sm border-4 border-slate-50"><i class="pi pi-check"></i></div>
<div class="text-center"> <div class="text-center">
<div class="text-sm font-bold text-slate-900">提交订单</div> <div class="text-sm font-bold text-slate-900">提交订单</div>
<div class="text-xs text-slate-500 mt-1">{{ order.createTime }}</div> <div class="text-xs text-slate-500 mt-1">{{ order.create_time }}</div>
</div> </div>
</div> </div>
<!-- Step 2 --> <!-- Step 2 -->
<div class="flex flex-col items-center gap-2 w-24"> <div class="flex flex-col items-center gap-2 w-24">
<div class="w-9 h-9 rounded-full flex items-center justify-center font-bold text-sm border-4 border-slate-50 transition-colors" :class="order.payTime ? 'bg-green-500 text-white' : 'bg-slate-200 text-slate-500'"><i class="pi pi-wallet"></i></div> <div class="w-9 h-9 rounded-full flex items-center justify-center font-bold text-sm border-4 border-slate-50 transition-colors" :class="order.pay_time ? 'bg-green-500 text-white' : 'bg-slate-200 text-slate-500'"><i class="pi pi-wallet"></i></div>
<div class="text-center"> <div class="text-center">
<div class="text-sm font-bold" :class="order.payTime ? 'text-slate-900' : 'text-slate-500'">付款成功</div> <div class="text-sm font-bold" :class="order.pay_time ? 'text-slate-900' : 'text-slate-500'">付款成功</div>
<div class="text-xs text-slate-500 mt-1" v-if="order.payTime">{{ order.payTime }}</div> <div class="text-xs text-slate-500 mt-1" v-if="order.pay_time">{{ order.pay_time }}</div>
</div> </div>
</div> </div>
<!-- Step 3 --> <!-- Step 3 -->
<div class="flex flex-col items-center gap-2 w-24"> <div class="flex flex-col items-center gap-2 w-24">
<div class="w-9 h-9 rounded-full flex items-center justify-center font-bold text-sm border-4 border-slate-50 transition-colors" :class="order.status === 'completed' ? 'bg-green-500 text-white' : 'bg-slate-200 text-slate-500'"><i class="pi pi-box"></i></div> <div class="w-9 h-9 rounded-full flex items-center justify-center font-bold text-sm border-4 border-slate-50 transition-colors" :class="order.status === 'completed' ? 'bg-green-500 text-white' : 'bg-slate-200 text-slate-500'"><i class="pi pi-box"></i></div>
<div class="text-center"> <div class="text-center">
<div class="text-sm font-bold" :class="order.status === 'completed' ? 'text-slate-900' : 'text-slate-500'">{{ order.isVirtual ? '自动发货' : '商家发货' }}</div> <div class="text-sm font-bold" :class="order.status === 'completed' ? 'text-slate-900' : 'text-slate-500'">{{ order.is_virtual ? '自动发货' : '商家发货' }}</div>
</div> </div>
</div> </div>
<!-- Step 4 --> <!-- Step 4 -->
@@ -61,18 +62,38 @@
<!-- Info Stack (Single Column Layout) --> <!-- Info Stack (Single Column Layout) -->
<div class="space-y-8"> <div class="space-y-8">
<!-- 1. Product Info --> <!-- 1. Product Info -->
<div class="border border-slate-200 rounded-lg overflow-hidden"> <div class="border border-slate-200 rounded-lg overflow-hidden" v-if="order.id">
<div class="bg-slate-50 px-6 py-3 border-b border-slate-200 font-bold text-slate-900 text-lg">商品信息</div> <div class="bg-slate-50 px-6 py-3 border-b border-slate-200 font-bold text-slate-900 text-lg">
<div class="p-6 flex flex-col sm:flex-row gap-6"> {{ order.type === 'recharge' ? '服务信息' : '商品信息' }}
<img :src="order.cover" class="w-32 h-20 object-cover rounded bg-slate-100 flex-shrink-0"> </div>
<div class="flex-1 min-w-0">
<h3 class="font-bold text-slate-900 text-xl mb-2">{{ order.title }}</h3> <!-- Recharge View -->
<div class="text-base text-slate-500 mb-3">{{ order.sku || '默认规格' }}</div> <div v-if="order.type === 'recharge'" class="p-6 flex items-center gap-6">
<div v-if="order.isVirtual" class="inline-flex items-center px-2.5 py-1 rounded text-sm font-medium bg-blue-50 text-blue-600">虚拟商品</div> <div class="w-20 h-20 rounded-full bg-slate-50 flex items-center justify-center text-primary-500">
<i class="pi pi-wallet text-3xl"></i>
</div> </div>
<div class="text-right sm:text-right text-left"> <div>
<div class="font-bold text-slate-900 text-xl">¥ {{ order.price }}</div> <h3 class="font-bold text-slate-900 text-xl mb-2">账户余额充值</h3>
<div class="text-slate-500 text-base mt-1">x {{ order.quantity }}</div> <div class="text-slate-500">充值金额将会即时到账</div>
</div>
<div class="ml-auto text-right">
<div class="font-bold text-slate-900 text-xl">¥ {{ order.amount }}</div>
</div>
</div>
<!-- Content Items View -->
<div v-else class="divide-y divide-slate-100">
<div v-for="(item, idx) in order.items" :key="idx" class="p-6 flex flex-col sm:flex-row gap-6">
<img :src="item.cover" class="w-32 h-20 object-cover rounded bg-slate-100 flex-shrink-0">
<div class="flex-1 min-w-0">
<h3 class="font-bold text-slate-900 text-xl mb-2">{{ item.title }}</h3>
<div class="text-base text-slate-500 mb-3">{{ item.sku || '默认规格' }}</div>
<div v-if="order.is_virtual" class="inline-flex items-center px-2.5 py-1 rounded text-sm font-medium bg-blue-50 text-blue-600">虚拟商品</div>
</div>
<div class="text-right sm:text-right text-left">
<div class="font-bold text-slate-900 text-xl">¥ {{ item.price }}</div>
<!-- Quantity is on order level usually for single-SKU, or item level? Assuming item price is unit price * quantity or just price paid -->
</div>
</div> </div>
</div> </div>
@@ -81,16 +102,12 @@
<div class="flex flex-col gap-2 ml-auto max-w-sm"> <div class="flex flex-col gap-2 ml-auto max-w-sm">
<div class="flex justify-between text-base text-slate-600"> <div class="flex justify-between text-base text-slate-600">
<span>商品总额</span> <span>商品总额</span>
<span>¥ {{ (order.price * order.quantity).toFixed(2) }}</span> <span>¥ {{ order.amount }}</span>
</div> </div>
<div class="flex justify-between text-base text-slate-600"> <div class="flex justify-between text-base text-slate-600">
<span>运费</span> <span>运费</span>
<span>¥ 0.00</span> <span>¥ 0.00</span>
</div> </div>
<div class="flex justify-between text-base text-slate-600">
<span>优惠券</span>
<span class="text-red-600">- ¥ 0.00</span>
</div>
<div class="border-t border-slate-200 my-2 pt-4 flex justify-between items-center"> <div class="border-t border-slate-200 my-2 pt-4 flex justify-between items-center">
<span class="font-bold text-slate-900 text-lg">实付金额</span> <span class="font-bold text-slate-900 text-lg">实付金额</span>
<span class="text-3xl font-bold text-red-600">¥ {{ order.amount }}</span> <span class="text-3xl font-bold text-red-600">¥ {{ order.amount }}</span>
@@ -108,12 +125,12 @@
<h3 class="font-bold text-slate-900 text-lg mb-4 border-l-4 border-primary-500 pl-3">订单信息</h3> <h3 class="font-bold text-slate-900 text-lg mb-4 border-l-4 border-primary-500 pl-3">订单信息</h3>
<div class="space-y-3 text-slate-600"> <div class="space-y-3 text-slate-600">
<p>订单编号: <span class="text-slate-900 select-all">{{ order.id }}</span> <button class="text-primary-600 ml-2 hover:underline font-medium cursor-pointer">复制</button></p> <p>订单编号: <span class="text-slate-900 select-all">{{ order.id }}</span> <button class="text-primary-600 ml-2 hover:underline font-medium cursor-pointer">复制</button></p>
<p>创建时间: {{ order.createTime }}</p> <p>创建时间: {{ order.create_time }}</p>
<p v-if="order.payTime">付款时间: {{ order.payTime }}</p> <p v-if="order.pay_time">付款时间: {{ order.pay_time }}</p>
</div> </div>
</div> </div>
<div v-if="!order.isVirtual"> <div v-if="!order.is_virtual && order.type !== 'recharge'">
<h3 class="font-bold text-slate-900 text-lg mb-4 border-l-4 border-primary-500 pl-3">收货信息</h3> <h3 class="font-bold text-slate-900 text-lg mb-4 border-l-4 border-primary-500 pl-3">收货信息</h3>
<div class="space-y-2 text-slate-600"> <div class="space-y-2 text-slate-600">
<p class="font-bold text-slate-900 text-lg">张三 138****8888</p> <p class="font-bold text-slate-900 text-lg">张三 138****8888</p>
@@ -123,13 +140,13 @@
</div> </div>
<!-- Right Column: Merchant & Actions --> <!-- Right Column: Merchant & Actions -->
<div class="space-y-6"> <div class="space-y-6" v-if="order.tenant_id !== '0' && order.type !== 'recharge'">
<div> <div>
<h3 class="font-bold text-slate-900 text-lg mb-4 border-l-4 border-primary-500 pl-3">商家信息</h3> <h3 class="font-bold text-slate-900 text-lg mb-4 border-l-4 border-primary-500 pl-3">商家信息</h3>
<div class="flex items-center gap-4 p-4 bg-slate-50 rounded-lg"> <div class="flex items-center gap-4 p-4 bg-slate-50 rounded-lg">
<img :src="order.tenantAvatar" class="w-12 h-12 rounded-full"> <img :src="order.tenant_avatar || 'https://api.dicebear.com/7.x/initials/svg?seed=' + order.tenant_name" class="w-12 h-12 rounded-full">
<div> <div>
<div class="font-bold text-slate-900">{{ order.tenantName }}</div> <div class="font-bold text-slate-900">{{ order.tenant_name }}</div>
<button class="text-primary-600 text-sm mt-1 hover:underline cursor-pointer">联系商家</button> <button class="text-primary-600 text-sm mt-1 hover:underline cursor-pointer">联系商家</button>
</div> </div>
</div> </div>
@@ -142,32 +159,41 @@
</template> </template>
<script setup> <script setup>
import { ref, computed } from 'vue'; import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { userApi } from '../../api/user';
const route = useRoute(); const route = useRoute();
const orderId = route.params.id; const orderId = route.params.id;
const order = ref({});
const loading = ref(true);
// Mock Data logic based on ID logic or just static for demo onMounted(async () => {
const order = ref({ try {
id: orderId || '82934712', const res = await userApi.getOrder(orderId);
createTime: '2025-12-24 14:30:00', order.value = res || {};
payTime: '2025-12-24 14:30:05', } catch (e) {
status: 'completed', console.error(e);
isVirtual: true, } finally {
cover: 'https://images.unsplash.com/photo-1514306191717-452ec28c7f31?ixlib=rb-1.2.1&auto=format&fit=crop&w=100&q=60', loading.value = false;
title: '《霸王别姬》全本实录珍藏版', }
sku: '高清数字版',
price: 9.90,
quantity: 1,
amount: '9.90',
tenantName: '梅派传人小林',
tenantAvatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Master1'
}); });
const progressWidth = computed(() => { const progressWidth = computed(() => {
if (order.value.status === 'completed') return '100%'; if (order.value.status === 'completed' || order.value.status === 'paid') return '100%';
if (order.value.status === 'paid') return '66%'; if (order.value.status === 'paid') return '66%'; // 'paid' can be 100% for virtual/recharge
return '33%'; return '33%';
}); });
const statusBadgeClass = (status) => {
const map = {
created: 'bg-orange-50 text-orange-600 border-orange-100',
paid: 'bg-blue-50 text-blue-600 border-blue-100',
completed: 'bg-green-50 text-green-600 border-green-100',
refunding: 'bg-purple-50 text-purple-600 border-purple-100',
refunded: 'bg-slate-100 text-slate-500 border-slate-200',
cancelled: 'bg-slate-100 text-slate-400 border-slate-200'
};
return map[status] || 'bg-slate-50 text-slate-500 border-slate-100';
};
</script> </script>

View File

@@ -50,19 +50,24 @@
<div class="space-y-4"> <div class="space-y-4">
<div v-for="order in recentOrders" :key="order.id" @click="$router.push(`/me/orders/${order.id}`)" <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"> 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"> <div class="w-16 h-16 bg-slate-100 rounded flex-shrink-0 flex items-center justify-center relative overflow-hidden">
<img v-if="order.items && order.items.length > 0" <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" :src="order.items[0].cover"
class="w-full h-full object-cover rounded transition-transform group-hover:scale-105"> 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>
<div class="flex-1 min-w-0"> <div class="flex-1 min-w-0">
<h3 class="font-bold text-slate-900 truncate group-hover:text-primary-600 transition-colors"> <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 class="text-sm text-slate-500 mt-1">{{ order.create_time }} · 订单号: {{ order.id }}</div>
</div> </div>
<div class="text-right"> <div class="text-right">
<div class="font-bold text-slate-900">¥ {{ order.amount }}</div> <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> </div>
<div v-if="recentOrders.length === 0" class="text-center text-slate-400 py-4">暂无订单</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 couponCount = ref(0);
const recentOrders = ref([]); 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 () => { const fetchData = async () => {
try { // Fetch Wallet
const w = await userApi.getWallet(); userApi.getWallet()
wallet.value.balance = w.balance || 0; .then(w => { wallet.value.balance = w.balance || 0; })
.catch(e => console.error("Wallet fetch failed:", e));
const u = await userApi.getMe();
wallet.value.points = u.points || 0; // Fetch User Info (Points)
userApi.getMe()
const c = await userApi.getCoupons('unused'); .then(u => { wallet.value.points = u.points || 0; })
couponCount.value = c.length; .catch(e => console.error("Me fetch failed:", e));
const o = await userApi.getOrders('all'); // Fetch Coupons
recentOrders.value = (o || []).slice(0, 3); userApi.getCoupons('unused')
} catch (e) { .then(c => { couponCount.value = (c || []).length; })
console.error(e); .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(() => { onMounted(() => {

View File

@@ -32,25 +32,40 @@
<!-- Order Header --> <!-- Order Header -->
<div class="bg-slate-50 px-4 py-3 flex items-center justify-between text-sm text-slate-500"> <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"> <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="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>
<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> </div>
<!-- Order Body --> <!-- Order Body -->
<div class="p-4 flex flex-col sm:flex-row gap-6"> <div class="p-4 flex flex-col sm:flex-row gap-6">
<!-- Product Info (Clickable Area) --> <!-- Product Info (Clickable Area) -->
<div class="flex-1 flex gap-4 cursor-pointer" @click="$router.push(`/me/orders/${order.id}`)"> <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"> <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">
<img :src="order.cover" class="w-full h-full object-cover"> <template v-if="order.type === 'recharge' || !order.items?.length">
<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> <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>
<div> <div>
<h3 class="font-bold text-slate-900 line-clamp-1 mb-1 group-hover:text-primary-600 transition-colors">{{ order.title }}</h3> <h3 class="font-bold text-slate-900 line-clamp-1 mb-1 group-hover:text-primary-600 transition-colors">
<div class="text-xs text-slate-500 mb-2">{{ order.typeLabel }}</div> {{ (order.type === 'recharge' || !order.items?.length) ? '账户充值' : (order.items?.[0]?.title || '未知商品') }}
<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>
<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>
</div> </div>
@@ -61,10 +76,10 @@
<div class="text-xs text-slate-400">在线支付</div> <div class="text-xs text-slate-400">在线支付</div>
</div> </div>
<div class="flex flex-col gap-2"> <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> <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 === '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 === 'unpaid'" class="text-xs text-slate-400 hover:text-slate-600 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> </div>
</div> </div>
@@ -124,18 +139,6 @@ watch(currentTab, () => {
// Use orders directly (filtered by backend) // Use orders directly (filtered by backend)
const filteredOrders = computed(() => orders.value); const filteredOrders = computed(() => orders.value);
const statusText = (status) => {
const map = {
created: '待支付',
paid: '已支付',
completed: '交易成功',
refunding: '退款中',
refunded: '已退款',
cancelled: '已取消'
};
return map[status] || status;
};
const statusColor = (status) => { const statusColor = (status) => {
const map = { const map = {
created: 'text-orange-600', created: 'text-orange-600',