114 lines
3.7 KiB
TypeScript
114 lines
3.7 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { eq } from "drizzle-orm";
|
|
import { auth } from "@/app/(auth)/auth";
|
|
import { db } from "@/lib/db";
|
|
import { 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 === "gift") return "管理员赠送";
|
|
if (reason === "recharge") return "积分充值";
|
|
if (reason === "adjust") return "积分调整";
|
|
return 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, configSetting, overridesSetting] =
|
|
await Promise.all([
|
|
getUserById({ id: session.user.id }),
|
|
getPointsSystemConfig(),
|
|
getPointsLedgerByUserId({ userId: session.user.id, limit: 200 }),
|
|
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: item.note || mapLedgerReasonLabel(item.reason),
|
|
status: item.amount < 0 ? "consumed" : "earned",
|
|
amount: item.amount,
|
|
createdAt: item.createdAt?.toISOString() || new Date().toISOString(),
|
|
}));
|
|
|
|
const billingRecords = ledger
|
|
.filter((item) => item.reason === "recharge" || item.reason === "gift")
|
|
.map((item) => ({
|
|
id: item.id,
|
|
date: item.createdAt?.toISOString() || new Date().toISOString(),
|
|
category: item.reason === "recharge" ? "积分充值" : "积分赠送",
|
|
amount: item.amount,
|
|
status: "completed",
|
|
invoice: "-",
|
|
}));
|
|
|
|
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 }
|
|
);
|
|
}
|
|
}
|
|
|