All checks were successful
site-dist-deploy / build-and-deploy (push) Successful in 1m3s
164 lines
4.9 KiB
Vue
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]"><<</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]"><</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]">></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]">>></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>
|