fix: 订阅套餐 API features 字段序列化及返回格式修复

- POST/PUT 写入前 JSON.stringify(features),修复数组写入 TEXT 列报错
- GET/POST/PUT 返回时统一字段映射(validDays/enabled/groupName/features 数组)
This commit is contained in:
erio
2026-03-13 22:30:20 +08:00
parent bc9ae8370c
commit 38156bd4ef
2 changed files with 41 additions and 6 deletions

View File

@@ -37,7 +37,7 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
if (body.validity_unit !== undefined && ['day', 'week', 'month'].includes(body.validity_unit)) { if (body.validity_unit !== undefined && ['day', 'week', 'month'].includes(body.validity_unit)) {
data.validityUnit = body.validity_unit; data.validityUnit = body.validity_unit;
} }
if (body.features !== undefined) data.features = body.features; if (body.features !== undefined) data.features = body.features ? JSON.stringify(body.features) : null;
if (body.for_sale !== undefined) data.forSale = body.for_sale; if (body.for_sale !== undefined) data.forSale = body.for_sale;
if (body.sort_order !== undefined) data.sortOrder = body.sort_order; if (body.sort_order !== undefined) data.sortOrder = body.sort_order;
@@ -47,9 +47,20 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
}); });
return NextResponse.json({ return NextResponse.json({
...plan, id: plan.id,
groupId: String(plan.groupId),
groupName: null,
name: plan.name,
description: plan.description,
price: Number(plan.price), price: Number(plan.price),
originalPrice: plan.originalPrice ? Number(plan.originalPrice) : null, originalPrice: plan.originalPrice ? Number(plan.originalPrice) : null,
validDays: plan.validityDays,
validityUnit: plan.validityUnit,
features: plan.features ? JSON.parse(plan.features) : [],
sortOrder: plan.sortOrder,
enabled: plan.forSale,
createdAt: plan.createdAt,
updatedAt: plan.updatedAt,
}); });
} catch (error) { } catch (error) {
console.error('Failed to update subscription plan:', error); console.error('Failed to update subscription plan:', error);

View File

@@ -11,21 +11,34 @@ export async function GET(request: NextRequest) {
orderBy: { sortOrder: 'asc' }, orderBy: { sortOrder: 'asc' },
}); });
// 并发检查每个套餐对应的 Sub2API 分组是否仍然存在 // 并发检查每个套餐对应的 Sub2API 分组是否仍然存在,并获取分组名称
const results = await Promise.all( const results = await Promise.all(
plans.map(async (plan) => { plans.map(async (plan) => {
let groupExists = false; let groupExists = false;
let groupName: string | null = null;
try { try {
const group = await getGroup(plan.groupId); const group = await getGroup(plan.groupId);
groupExists = group !== null; groupExists = group !== null;
groupName = group?.name ?? null;
} catch { } catch {
groupExists = false; groupExists = false;
} }
return { return {
...plan, id: plan.id,
groupId: String(plan.groupId),
groupName,
name: plan.name,
description: plan.description,
price: Number(plan.price), price: Number(plan.price),
originalPrice: plan.originalPrice ? Number(plan.originalPrice) : null, originalPrice: plan.originalPrice ? Number(plan.originalPrice) : null,
validDays: plan.validityDays,
validityUnit: plan.validityUnit,
features: plan.features ? JSON.parse(plan.features) : [],
sortOrder: plan.sortOrder,
enabled: plan.forSale,
groupExists, groupExists,
createdAt: plan.createdAt,
updatedAt: plan.updatedAt,
}; };
}), }),
); );
@@ -69,7 +82,7 @@ export async function POST(request: NextRequest) {
originalPrice: original_price ?? null, originalPrice: original_price ?? null,
validityDays: validity_days ?? 30, validityDays: validity_days ?? 30,
validityUnit: ['day', 'week', 'month'].includes(validity_unit) ? validity_unit : 'day', validityUnit: ['day', 'week', 'month'].includes(validity_unit) ? validity_unit : 'day',
features: features ?? null, features: features ? JSON.stringify(features) : null,
forSale: for_sale ?? false, forSale: for_sale ?? false,
sortOrder: sort_order ?? 0, sortOrder: sort_order ?? 0,
}, },
@@ -77,9 +90,20 @@ export async function POST(request: NextRequest) {
return NextResponse.json( return NextResponse.json(
{ {
...plan, id: plan.id,
groupId: String(plan.groupId),
groupName: null,
name: plan.name,
description: plan.description,
price: Number(plan.price), price: Number(plan.price),
originalPrice: plan.originalPrice ? Number(plan.originalPrice) : null, originalPrice: plan.originalPrice ? Number(plan.originalPrice) : null,
validDays: plan.validityDays,
validityUnit: plan.validityUnit,
features: plan.features ? JSON.parse(plan.features) : [],
sortOrder: plan.sortOrder,
enabled: plan.forSale,
createdAt: plan.createdAt,
updatedAt: plan.updatedAt,
}, },
{ status: 201 }, { status: 201 },
); );