speakeloudest c0e22f5a6e
All checks were successful
site-dist-deploy / build-and-deploy (push) Successful in 1m3s
订单弹窗
2026-01-07 06:48:47 -08:00

164 lines
4.9 KiB
Vue

<template>
<div class="flex flex-1 flex-col overflow-hidden">
<!-- List Container -->
<div class="h-[470px]">
<div v-if="loading" class="flex h-40 items-center justify-center">
<div
class="h-8 w-8 animate-spin rounded-full border-4 border-[#ADFF5B] border-t-transparent"
></div>
</div>
<div
v-else-if="list.length === 0"
class="flex h-40 items-center justify-center text-gray-500"
>
暂无订单记录
</div>
<div v-else class="space-y-[10px]">
<div
v-for="order in list"
:key="order.id"
class="rounded-[20px] bg-[#CECECF] py-2 text-[14px] font-normal text-black"
>
<div class="grid grid-cols-2 gap-y-1">
<!-- Order No -->
<div class="col-span-2 pl-4">
<div class="">订单号</div>
<div class="break-all">{{ order.order_no }}</div>
</div>
<!-- Name and Status -->
<div class="pl-4">
<div class="text-gray-500">名称</div>
<div class="whitespace-nowrap">{{ order.quantity }}天VPN服务</div>
</div>
<div class="">
<div class="text-gray-500">状态</div>
<div>{{ statusText(order.status) }}</div>
</div>
<!-- Amount and Time -->
<div class="pl-4">
<div class="text-gray-500">支付金额</div>
<div>${{ order.amount / 100 }}</div>
</div>
<div class="overflow-hidden">
<div class="text-gray-500">支付时间</div>
<div class="whitespace-nowrap">{{ formatTime(order.created_at) }}</div>
</div>
</div>
</div>
</div>
</div>
<!-- Pagination Controls -->
<div v-if="total > 0" class="flex flex-col items-center pt-[18px]">
<div class="mb-2 flex items-center gap-[10px]">
<button
@click="changePage(1)"
:disabled="page === 1"
class="flex h-[30px] min-w-[30px] items-center justify-center rounded-full bg-[#EAEAEA] transition-opacity"
>
<span class="text-lg font-bold text-[#848484]">&lt;&lt;</span>
</button>
<button
@click="changePage(page - 1)"
:disabled="page === 1"
class="flex h-[30px] min-w-[30px] items-center justify-center rounded-full bg-[#EAEAEA] transition-opacity"
>
<span class="text-lg font-bold text-[#848484]">&lt;</span>
</button>
<div
class="flex h-[30px] min-w-[65px] items-center justify-center rounded-full bg-[#EAEAEA] px-2"
>
<span class="text-base text-[#848484]">{{ page }}</span>
<span class="ml-1 text-base text-[#848484]">v</span>
</div>
<button
@click="changePage(page + 1)"
:disabled="page >= totalPages"
class="flex h-[30px] min-w-[30px] items-center justify-center rounded-full bg-[#EAEAEA] transition-opacity"
>
<span class="text-lg font-bold text-[#848484]">&gt;</span>
</button>
<button
@click="changePage(totalPages)"
:disabled="page >= totalPages"
class="flex h-[30px] min-w-[30px] items-center justify-center rounded-full bg-[#EAEAEA] transition-opacity"
>
<span class="text-lg font-bold text-[#848484]">&gt;&gt;</span>
</button>
</div>
<div class="text-xs font-[300] text-[#848484]"> {{ page }} / {{ totalPages }} </div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import request from '@/utils/request'
const page = ref(1)
const size = ref(3)
const total = ref(0)
const list = ref<any[]>([])
const loading = ref(false)
const totalPages = computed(() => Math.ceil(total.value / size.value) || 1)
async function fetchOrders() {
loading.value = true
try {
const res: any = await request.get('/api/v1/public/order/list', {
page: page.value,
size: size.value,
status: 5,
})
list.value = res.list || []
total.value = res.total || 0
} catch (error) {
console.error('Fetch orders error:', error)
} finally {
loading.value = false
}
}
function changePage(p: number) {
if (p < 1 || p > totalPages.value) return
page.value = p
fetchOrders()
}
function statusText(status: number) {
const map: Record<number, string> = {
1: '待支付',
2: '已支付',
3: '已关闭',
4: '支付失败',
5: '已完成',
}
return map[status] || '未知'
}
function formatTime(timestamp: number) {
if (!timestamp) return '-'
const date = new Date(timestamp > 10000000000 ? timestamp : timestamp * 1000)
return date.toLocaleString('en-US', {
month: 'numeric',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: '2-digit',
second: '2-digit',
hour12: false,
})
}
onMounted(() => {
fetchOrders()
})
</script>
<style scoped></style>