feat: 订阅套餐展示优化、平台图标、默认月、用户订阅查询

- 新建共享平台样式模块 platform-style.ts,含各平台 SVG 图标 + 彩色 badge
- SubscriptionPlanCard 重设计:平台图标 badge、倍率/限额 grid 展示、OpenAI messages 调度信息
- UserSubscriptions 显示 group_name + 平台 badge
- ChannelCard 复用共享平台样式模块
- 管理后台:新建套餐默认 1 月、去掉模型展示、平台图标 badge、OpenAI 信息
- 管理后台用户订阅 tab 默认查询所有订阅(user_id 可选)
- Sub2API client 新增 listSubscriptions 函数
- API 返回 allowMessagesDispatch / defaultMappedModel / group_name / platform
This commit is contained in:
erio
2026-03-14 01:23:21 +08:00
parent 10e3e445ed
commit 1218b31461
10 changed files with 408 additions and 145 deletions

View File

@@ -1,6 +1,6 @@
import { NextRequest, NextResponse } from 'next/server';
import { verifyAdminToken, unauthorizedResponse } from '@/lib/admin-auth';
import { getUserSubscriptions, getUser } from '@/lib/sub2api/client';
import { getUserSubscriptions, getUser, listSubscriptions } from '@/lib/sub2api/client';
export async function GET(request: NextRequest) {
if (!(await verifyAdminToken(request))) return unauthorizedResponse(request);
@@ -8,30 +8,47 @@ export async function GET(request: NextRequest) {
try {
const searchParams = request.nextUrl.searchParams;
const userId = searchParams.get('user_id');
if (!userId) {
return NextResponse.json({ error: '缺少必填参数: user_id' }, { status: 400 });
}
const parsedUserId = Number(userId);
if (!Number.isFinite(parsedUserId) || parsedUserId <= 0) {
return NextResponse.json({ error: '无效的 user_id' }, { status: 400 });
}
const [subscriptions, user] = await Promise.all([
getUserSubscriptions(parsedUserId),
getUser(parsedUserId).catch(() => null),
]);
// 如果提供了 group_id 筛选,过滤结果
const groupId = searchParams.get('group_id');
const filtered = groupId
? subscriptions.filter((s) => s.group_id === Number(groupId))
: subscriptions;
const status = searchParams.get('status');
const page = searchParams.get('page');
const pageSize = searchParams.get('page_size');
if (userId) {
// 按用户查询(原有逻辑)
const parsedUserId = Number(userId);
if (!Number.isFinite(parsedUserId) || parsedUserId <= 0) {
return NextResponse.json({ error: '无效的 user_id' }, { status: 400 });
}
const [subscriptions, user] = await Promise.all([
getUserSubscriptions(parsedUserId),
getUser(parsedUserId).catch(() => null),
]);
const filtered = groupId
? subscriptions.filter((s) => s.group_id === Number(groupId))
: subscriptions;
return NextResponse.json({
subscriptions: filtered,
user: user ? { id: user.id, username: user.username, email: user.email } : null,
});
}
// 无 user_id 时列出所有订阅
const result = await listSubscriptions({
group_id: groupId ? Number(groupId) : undefined,
status: status || undefined,
page: page ? Number(page) : undefined,
page_size: pageSize ? Number(pageSize) : undefined,
});
return NextResponse.json({
subscriptions: filtered,
user: user ? { id: user.id, username: user.username, email: user.email } : null,
subscriptions: result.subscriptions,
total: result.total,
page: result.page,
page_size: result.page_size,
user: null,
});
} catch (error) {
console.error('Failed to query subscriptions:', error);