2026-04-09 17:17:52 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="my-orders-index mini-scrollbar">
|
|
|
|
|
<div class="total-box">
|
|
|
|
|
<div class="total-item" v-for="v in totals" :key="v.title">
|
|
|
|
|
<div class="title">
|
|
|
|
|
<span class="icon"><svg-icon :name="v.icon" size="18" /></span>
|
|
|
|
|
<span class="label">{{ v.title }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="value">{{ v.value }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="filter-box">
|
|
|
|
|
<div class="left">
|
|
|
|
|
<div class="title">All Invoice</div>
|
|
|
|
|
<div class="tip">A summary of all completed transactions.</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="right">
|
|
|
|
|
<div class="input">
|
2026-04-13 14:35:12 +08:00
|
|
|
<span class="icon"
|
|
|
|
|
><svg-icon name="seller-search" size="20" @click="getList(true)"
|
|
|
|
|
/></span>
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
v-model="nameOrId"
|
|
|
|
|
placeholder="Search by item name or order ID"
|
|
|
|
|
@keydown.enter.prevent="getList(true)"
|
|
|
|
|
/>
|
2026-04-09 17:17:52 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="table">
|
|
|
|
|
<div class="header">
|
|
|
|
|
<div class="order-id">Order ID</div>
|
|
|
|
|
<div class="item">Item</div>
|
|
|
|
|
<div class="price">Price</div>
|
|
|
|
|
<div class="buyer-username">Buyer Username</div>
|
|
|
|
|
<div class="date">Date</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="body">
|
2026-04-13 14:35:12 +08:00
|
|
|
<div class="item" v-for="v in list" :key="v.orderId">
|
|
|
|
|
<div class="order-id">{{ v.orderId }}</div>
|
2026-04-09 17:17:52 +08:00
|
|
|
<div class="item">
|
|
|
|
|
<div class="images">
|
2026-04-13 14:35:12 +08:00
|
|
|
<img
|
|
|
|
|
v-for="(v, i) in v.item.slice(0, maxItemNum)"
|
|
|
|
|
:key="i"
|
|
|
|
|
:src="v.url"
|
|
|
|
|
/>
|
|
|
|
|
<span v-if="v.item.length > maxItemNum"
|
|
|
|
|
>+{{ v.item.length - maxItemNum }} more</span
|
|
|
|
|
>
|
2026-04-09 17:17:52 +08:00
|
|
|
</div>
|
|
|
|
|
<div class="titles">
|
2026-04-13 14:35:12 +08:00
|
|
|
<div v-for="(v, i) in v.item.slice(0, maxItemNum)" :key="i">
|
|
|
|
|
{{ v.title }}
|
|
|
|
|
</div>
|
|
|
|
|
<span v-if="v.item.length > maxItemNum">...</span>
|
2026-04-09 17:17:52 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-04-13 14:35:12 +08:00
|
|
|
<div class="price">{{ v.price }}</div>
|
|
|
|
|
<div class="buyer-username">{{ v.username }}</div>
|
2026-04-09 17:17:52 +08:00
|
|
|
<div class="date">
|
2026-04-13 14:35:12 +08:00
|
|
|
<div>{{ v.date }}</div>
|
|
|
|
|
<div>{{ v.time }}</div>
|
2026-04-09 17:17:52 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-04-13 14:35:12 +08:00
|
|
|
<div class="placeholder" ref="placeholderRef" v-show="!loading"></div>
|
2026-04-17 10:17:03 +08:00
|
|
|
<div class="footer" :class="{ null: list.length === 0 }" v-if="!finish">
|
|
|
|
|
<a-spin :delay="0.5" v-show="loading" />
|
|
|
|
|
</div>
|
2026-04-09 17:17:52 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2026-04-13 14:35:12 +08:00
|
|
|
import { ref, onMounted, onBeforeUnmount } from "vue"
|
2026-04-09 17:17:52 +08:00
|
|
|
const totals = ref([
|
|
|
|
|
{
|
|
|
|
|
icon: "seller-qiandaizi",
|
|
|
|
|
title: "Total Revenue",
|
|
|
|
|
value: "HK$ 54,32.00"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
icon: "seller-gouwudai",
|
|
|
|
|
title: "Total Purchases",
|
|
|
|
|
value: "128"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
icon: "seller-eye",
|
|
|
|
|
title: "Total Views",
|
|
|
|
|
value: "4,982"
|
|
|
|
|
}
|
|
|
|
|
])
|
2026-04-13 14:35:12 +08:00
|
|
|
const maxItemNum = ref(2)
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
const finish = ref(false)
|
2026-04-14 15:07:20 +08:00
|
|
|
const total = ref(0)
|
2026-04-13 14:35:12 +08:00
|
|
|
const page = ref(1)
|
|
|
|
|
const size = ref(10)
|
|
|
|
|
const nameOrId = ref("")
|
|
|
|
|
const list = ref([])
|
|
|
|
|
const getList = (isReload = false) => {
|
2026-04-17 10:17:03 +08:00
|
|
|
if (loading.value) return
|
2026-04-13 14:35:12 +08:00
|
|
|
loading.value = true
|
|
|
|
|
if (isReload) {
|
|
|
|
|
list.value = []
|
|
|
|
|
page.value = 1
|
|
|
|
|
finish.value = false
|
|
|
|
|
}
|
|
|
|
|
const data = {
|
|
|
|
|
page: page.value,
|
2026-04-14 15:07:20 +08:00
|
|
|
size: size.value
|
2026-04-13 14:35:12 +08:00
|
|
|
}
|
2026-04-14 15:07:20 +08:00
|
|
|
if (nameOrId.value) data.nameOrId = nameOrId.value
|
2026-04-13 14:35:12 +08:00
|
|
|
console.log(data)
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
for (let i = 0; i < size.value; i++) {
|
|
|
|
|
let { date, time, dateTime } = formatTimestamp(new Date(2026, 4, 20, 13, 14).getTime())
|
|
|
|
|
list.value.push({
|
|
|
|
|
orderId: "SP" + Math.random().toString().substring(2, 10),
|
|
|
|
|
price: "HK$ " + (Math.random() * 500).toFixed(2),
|
|
|
|
|
username: "@liuyuchen",
|
|
|
|
|
date: date,
|
|
|
|
|
time: time,
|
|
|
|
|
item: [
|
|
|
|
|
{
|
|
|
|
|
url: "http://118.31.39.42:3000/falls/o-1.png",
|
|
|
|
|
title: "North Outfit Set"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
url: "http://118.31.39.42:3000/falls/o-2.png",
|
|
|
|
|
title: "Heritage Layered Set"
|
|
|
|
|
},
|
|
|
|
|
{},
|
|
|
|
|
{}
|
|
|
|
|
]
|
|
|
|
|
})
|
|
|
|
|
}
|
2026-04-14 15:07:20 +08:00
|
|
|
total.value = 30
|
2026-04-13 14:35:12 +08:00
|
|
|
page.value++
|
|
|
|
|
finish.value = page.value > total.value / 10
|
|
|
|
|
loading.value = false
|
|
|
|
|
}, 1000)
|
|
|
|
|
}
|
|
|
|
|
getList(true)
|
|
|
|
|
const placeholderRef = ref(null)
|
|
|
|
|
const observer = new IntersectionObserver(
|
|
|
|
|
(entries) => {
|
|
|
|
|
if (!entries[0].intersectionRatio || loading.value || finish.value) return
|
|
|
|
|
getList()
|
|
|
|
|
},
|
|
|
|
|
{ root: document.body }
|
|
|
|
|
)
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
observer.observe(placeholderRef.value)
|
|
|
|
|
})
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
observer.disconnect()
|
|
|
|
|
})
|
|
|
|
|
const formatTimestamp = (ts) => {
|
|
|
|
|
const d = new Date(ts)
|
|
|
|
|
const h = d.getHours()
|
|
|
|
|
const m = d.getMinutes()
|
|
|
|
|
const date = `${d.toLocaleString("en-US", {
|
|
|
|
|
month: "long"
|
|
|
|
|
})} ${d.getDate()}, ${d.getFullYear()}`
|
|
|
|
|
const time = `${h.toString().padStart(2, "0")}:${m.toString().padStart(2, "0")} ${
|
|
|
|
|
h >= 12 ? "PM" : "AM"
|
|
|
|
|
}`
|
|
|
|
|
return {
|
|
|
|
|
date,
|
|
|
|
|
time,
|
|
|
|
|
dateTime: `${date}\n${time}`
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-09 17:17:52 +08:00
|
|
|
</script>
|
|
|
|
|
<style scoped lang="less">
|
|
|
|
|
.my-orders-index {
|
|
|
|
|
position: relative;
|
|
|
|
|
flex: 1;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
padding: 0 3rem;
|
|
|
|
|
margin: 0 3rem;
|
|
|
|
|
gap: 4rem;
|
|
|
|
|
> .total-box {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 1.8rem;
|
|
|
|
|
> .total-item {
|
|
|
|
|
flex: 1;
|
|
|
|
|
padding: 2.4rem;
|
|
|
|
|
background-color: #f6f6f6;
|
|
|
|
|
border-radius: 1.2rem;
|
|
|
|
|
> .title {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 1.2rem;
|
|
|
|
|
gap: 1.2rem;
|
|
|
|
|
> .icon {
|
|
|
|
|
width: 4rem;
|
|
|
|
|
height: 4rem;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
background-color: #ffffff;
|
|
|
|
|
border: 0.08rem solid #e4e4e4;
|
|
|
|
|
}
|
|
|
|
|
> .label {
|
|
|
|
|
font-size: 2rem;
|
|
|
|
|
color: #585858;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
> .value {
|
|
|
|
|
font-family: "pingfang_heavy";
|
|
|
|
|
font-size: 3.6rem;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
> .filter-box {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: flex-end;
|
|
|
|
|
> .left {
|
|
|
|
|
> .title {
|
|
|
|
|
font-family: "pingfang_heavy";
|
|
|
|
|
font-size: 2.4rem;
|
|
|
|
|
color: #000;
|
|
|
|
|
}
|
|
|
|
|
> .tip {
|
|
|
|
|
font-family: "pingfang_regular";
|
|
|
|
|
font-size: 1.4rem;
|
|
|
|
|
color: #999;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
> .right {
|
|
|
|
|
> .input {
|
|
|
|
|
width: 30rem;
|
|
|
|
|
height: 4rem;
|
|
|
|
|
border-bottom: 0.15rem solid #000000;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
> .icon {
|
|
|
|
|
margin: 0 0.5rem;
|
|
|
|
|
}
|
|
|
|
|
> input {
|
|
|
|
|
padding: 0 2rem;
|
|
|
|
|
width: 0;
|
|
|
|
|
flex: 1;
|
|
|
|
|
outline: none;
|
|
|
|
|
border: none;
|
|
|
|
|
height: 100%;
|
|
|
|
|
font-family: "pingfang_regular";
|
|
|
|
|
font-size: 1.2rem;
|
|
|
|
|
color: #000;
|
|
|
|
|
&::placeholder {
|
|
|
|
|
color: #999999;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
> .table {
|
|
|
|
|
width: 100%;
|
|
|
|
|
> .body > .item,
|
|
|
|
|
> .header {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
> div {
|
|
|
|
|
padding: 0 1.5rem;
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
> .order-id {
|
2026-04-13 14:35:12 +08:00
|
|
|
flex: 1.5;
|
2026-04-09 17:17:52 +08:00
|
|
|
}
|
|
|
|
|
> .item {
|
|
|
|
|
flex: 3;
|
|
|
|
|
}
|
|
|
|
|
> .buyer-username {
|
|
|
|
|
flex: 1.5;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
> .header {
|
|
|
|
|
position: sticky;
|
|
|
|
|
top: 0;
|
|
|
|
|
background-color: #f6f6f6;
|
|
|
|
|
height: 5.6rem;
|
|
|
|
|
border-width: 0.15rem 0 0.15rem 0;
|
|
|
|
|
border-style: solid;
|
|
|
|
|
border-color: #eaeaea;
|
|
|
|
|
> div {
|
|
|
|
|
font-size: 2rem;
|
|
|
|
|
color: #979797;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
> .body {
|
|
|
|
|
> .item {
|
|
|
|
|
padding-top: 1.6rem;
|
|
|
|
|
padding-bottom: 1.6rem;
|
|
|
|
|
border-bottom: 0.1rem solid #f6f6f6;
|
|
|
|
|
color: #000;
|
|
|
|
|
> .order-id {
|
|
|
|
|
font-family: "pingfang_regular";
|
|
|
|
|
font-size: 1.8rem;
|
|
|
|
|
}
|
|
|
|
|
> .price {
|
|
|
|
|
font-family: "pingfang_medium";
|
|
|
|
|
font-size: 1.8rem;
|
|
|
|
|
}
|
|
|
|
|
> .buyer-username {
|
|
|
|
|
font-family: "pingfang_regular";
|
|
|
|
|
font-size: 1.8rem;
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
> .date {
|
|
|
|
|
font-family: "pingfang_regular";
|
|
|
|
|
font-size: 1.6rem;
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
> .item {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 3rem;
|
|
|
|
|
> .images {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
gap: 1.2rem;
|
|
|
|
|
> img {
|
|
|
|
|
width: auto;
|
|
|
|
|
height: 10rem;
|
|
|
|
|
border-radius: 0.8rem;
|
|
|
|
|
border: 0.1rem solid #e9e9e9;
|
|
|
|
|
}
|
|
|
|
|
> span {
|
|
|
|
|
font-family: "pingfang_medium";
|
|
|
|
|
font-size: 1.4rem;
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
> .titles {
|
|
|
|
|
font-family: "pingfang_medium";
|
|
|
|
|
font-size: 1.8rem;
|
|
|
|
|
color: #000;
|
|
|
|
|
> span {
|
|
|
|
|
user-select: none;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-13 14:35:12 +08:00
|
|
|
> .footer {
|
|
|
|
|
min-height: 10rem;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
2026-04-17 10:17:03 +08:00
|
|
|
&.null {
|
|
|
|
|
height: 30rem;
|
|
|
|
|
}
|
2026-04-13 14:35:12 +08:00
|
|
|
}
|
|
|
|
|
> .placeholder {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 1px;
|
|
|
|
|
}
|
2026-04-09 17:17:52 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|