feat: 订单列表支持分页查询,分页大小可选 20/50/100
- /api/orders/my 新增 page/page_size 参数,返回分页信息和全局状态统计 - 用户订单页:分页控件(首/上/下/末页)+ 分页大小选择,摘要卡片改为全局统计 - 管理员订单页:分页大小选择器(20/50/100)+ 首尾页跳转按钮
This commit is contained in:
@@ -3,28 +3,44 @@ import { prisma } from '@/lib/db';
|
||||
import { getCurrentUserByToken } from '@/lib/sub2api/client';
|
||||
import { deriveOrderState, isRechargeRetryable } from '@/lib/order/status';
|
||||
|
||||
const VALID_PAGE_SIZES = [20, 50, 100];
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const token = request.nextUrl.searchParams.get('token')?.trim();
|
||||
const searchParams = request.nextUrl.searchParams;
|
||||
const token = searchParams.get('token')?.trim();
|
||||
if (!token) {
|
||||
return NextResponse.json({ error: 'token is required' }, { status: 400 });
|
||||
}
|
||||
|
||||
const page = Math.max(1, Number(searchParams.get('page') || '1'));
|
||||
const rawPageSize = Number(searchParams.get('page_size') || '20');
|
||||
const pageSize = VALID_PAGE_SIZES.includes(rawPageSize) ? rawPageSize : 20;
|
||||
|
||||
try {
|
||||
const user = await getCurrentUserByToken(token);
|
||||
const orders = await prisma.order.findMany({
|
||||
where: { userId: user.id },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 20,
|
||||
select: {
|
||||
id: true,
|
||||
amount: true,
|
||||
status: true,
|
||||
paymentType: true,
|
||||
createdAt: true,
|
||||
paidAt: true,
|
||||
completedAt: true,
|
||||
},
|
||||
});
|
||||
const where = { userId: user.id };
|
||||
|
||||
const [orders, total, statusGroups] = await Promise.all([
|
||||
prisma.order.findMany({
|
||||
where,
|
||||
orderBy: { createdAt: 'desc' },
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
select: {
|
||||
id: true,
|
||||
amount: true,
|
||||
status: true,
|
||||
paymentType: true,
|
||||
createdAt: true,
|
||||
paidAt: true,
|
||||
completedAt: true,
|
||||
},
|
||||
}),
|
||||
prisma.order.count({ where }),
|
||||
prisma.order.groupBy({ by: ['status'], where, _count: true }),
|
||||
]);
|
||||
|
||||
const sc = Object.fromEntries(statusGroups.map((g) => [g.status, g._count]));
|
||||
|
||||
return NextResponse.json({
|
||||
user: {
|
||||
@@ -48,6 +64,15 @@ export async function GET(request: NextRequest) {
|
||||
rechargeRetryable: isRechargeRetryable(item),
|
||||
};
|
||||
}),
|
||||
summary: {
|
||||
total,
|
||||
pending: sc['PENDING'] || 0,
|
||||
completed: (sc['COMPLETED'] || 0) + (sc['PAID'] || 0) + (sc['RECHARGING'] || 0),
|
||||
failed: (sc['FAILED'] || 0) + (sc['CANCELLED'] || 0) + (sc['EXPIRED'] || 0),
|
||||
},
|
||||
page,
|
||||
page_size: pageSize,
|
||||
total_pages: Math.ceil(total / pageSize),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Get my orders error:', error);
|
||||
|
||||
Reference in New Issue
Block a user