164 lines
5.3 KiB
TypeScript
164 lines
5.3 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { desc, eq } from "drizzle-orm";
|
|
import { auth } from "@/app/(auth)/auth";
|
|
import { db } from "@/lib/db";
|
|
import { paymentOrder, systemSettings } from "@/lib/db/schema";
|
|
import {
|
|
getPointsLedgerByUserId,
|
|
getPointsSystemConfig,
|
|
getUserById,
|
|
} from "@/lib/db/queries";
|
|
import {
|
|
defaultMembershipConfig,
|
|
defaultMembershipUserOverrides,
|
|
getMembershipPlanById,
|
|
normalizeMembershipConfig,
|
|
normalizeMembershipUserOverrides,
|
|
resolveMembershipPlanIdForUser,
|
|
} from "@/lib/membership/config";
|
|
|
|
const MEMBERSHIP_CONFIG_KEY = "membership_config";
|
|
const MEMBERSHIP_USER_OVERRIDES_KEY = "membership_user_plan_overrides";
|
|
|
|
function mapLedgerReasonLabel(reason: string) {
|
|
if (reason === "image_generation") return "图片生成";
|
|
if (reason === "model3d_generation") return "3D模型生成";
|
|
if (reason === "world3d_generation") return "3D世界生成";
|
|
if (reason === "video_generation") return "视频生成";
|
|
if (reason === "enhance_pro_generation") return "图像增强 Pro";
|
|
if (reason === "enhance_pro_refund") return "图像增强 Pro 失败退回";
|
|
if (reason === "deduct") return "管理员扣减";
|
|
if (reason === "gift") return "管理员赠送";
|
|
if (reason === "recharge") return "积分充值";
|
|
if (reason === "adjust") return "积分调整";
|
|
return reason || "积分变动";
|
|
}
|
|
|
|
function formatLedgerDetail(reason: string, note: string | null | undefined) {
|
|
if (reason === "recharge") {
|
|
return "充值积分";
|
|
}
|
|
|
|
const trimmedNote = typeof note === "string" ? note.trim() : "";
|
|
return trimmedNote || mapLedgerReasonLabel(reason);
|
|
}
|
|
|
|
export async function GET() {
|
|
try {
|
|
const session = await auth();
|
|
if (!session?.user?.id) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
|
|
const [
|
|
dbUser,
|
|
pointsConfig,
|
|
ledger,
|
|
paymentOrders,
|
|
configSetting,
|
|
overridesSetting,
|
|
] =
|
|
await Promise.all([
|
|
getUserById({ id: session.user.id }),
|
|
getPointsSystemConfig(),
|
|
getPointsLedgerByUserId({ userId: session.user.id, limit: 200 }),
|
|
db
|
|
.select({
|
|
id: paymentOrder.id,
|
|
amountCents: paymentOrder.amountCents,
|
|
status: paymentOrder.status,
|
|
createdAt: paymentOrder.createdAt,
|
|
})
|
|
.from(paymentOrder)
|
|
.where(eq(paymentOrder.userId, session.user.id))
|
|
.orderBy(desc(paymentOrder.createdAt))
|
|
.limit(100),
|
|
db
|
|
.select()
|
|
.from(systemSettings)
|
|
.where(eq(systemSettings.key, MEMBERSHIP_CONFIG_KEY))
|
|
.limit(1)
|
|
.then((rows) => rows[0]),
|
|
db
|
|
.select()
|
|
.from(systemSettings)
|
|
.where(eq(systemSettings.key, MEMBERSHIP_USER_OVERRIDES_KEY))
|
|
.limit(1)
|
|
.then((rows) => rows[0]),
|
|
]);
|
|
|
|
const membershipConfig = configSetting?.value
|
|
? normalizeMembershipConfig(configSetting.value)
|
|
: defaultMembershipConfig;
|
|
const membershipOverrides = overridesSetting?.value
|
|
? normalizeMembershipUserOverrides(overridesSetting.value)
|
|
: defaultMembershipUserOverrides;
|
|
const currentPlanId = resolveMembershipPlanIdForUser(
|
|
session.user.id,
|
|
session.user.email,
|
|
membershipConfig,
|
|
membershipOverrides
|
|
);
|
|
const currentPlan = getMembershipPlanById(membershipConfig, currentPlanId);
|
|
|
|
const usageRecords = ledger.map((item) => ({
|
|
id: item.id,
|
|
detail: formatLedgerDetail(item.reason, item.note),
|
|
status: item.amount < 0 ? "consumed" : "earned",
|
|
amount: item.amount,
|
|
createdAt: item.createdAt?.toISOString() || new Date().toISOString(),
|
|
}));
|
|
|
|
const rechargeRecords = paymentOrders.map((order) => ({
|
|
id: order.id,
|
|
date: order.createdAt?.toISOString() || new Date().toISOString(),
|
|
category: "积分充值",
|
|
amount: Number((order.amountCents / 100).toFixed(2)),
|
|
status:
|
|
order.status === "paid"
|
|
? "completed"
|
|
: order.status === "pending"
|
|
? "pending"
|
|
: "failed",
|
|
invoice: "-",
|
|
}));
|
|
|
|
const giftedRecords = ledger
|
|
.filter((item) => item.reason === "gift")
|
|
.map((item) => ({
|
|
id: item.id,
|
|
date: item.createdAt?.toISOString() || new Date().toISOString(),
|
|
category: "积分赠送",
|
|
amount: item.amount,
|
|
status: "completed",
|
|
invoice: "-",
|
|
}));
|
|
|
|
const billingRecords = [...rechargeRecords, ...giftedRecords].sort((a, b) => {
|
|
return new Date(b.date).getTime() - new Date(a.date).getTime();
|
|
});
|
|
|
|
return NextResponse.json({
|
|
profile: {
|
|
name: dbUser?.name || session.user.name || "",
|
|
email: dbUser?.email || session.user.email || "",
|
|
currentPlanName: currentPlan.name,
|
|
currentPlanId,
|
|
availablePoints: pointsConfig.enabled
|
|
? Math.max(0, Number(dbUser?.pointsBalance || 0))
|
|
: currentPlan.monthlyCredits,
|
|
monthlyCredits: currentPlan.monthlyCredits,
|
|
dailyFreeCredits: currentPlan.dailyFreeCredits,
|
|
},
|
|
usageRecords,
|
|
billingRecords,
|
|
});
|
|
} catch (error) {
|
|
console.error("[Account Center API] Error:", error);
|
|
return NextResponse.json(
|
|
{ error: "Failed to fetch account center data" },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|