diff --git a/app/(admin)/settings/admin-settings-client.tsx b/app/(admin)/settings/admin-settings-client.tsx index 61273b9bf..fe9f484f3 100644 --- a/app/(admin)/settings/admin-settings-client.tsx +++ b/app/(admin)/settings/admin-settings-client.tsx @@ -7413,7 +7413,7 @@ export function AdminSettingsClient() {
- 开启后按模型单价和图片张数扣除积分 + 开启后按不同功能配置的单价扣除积分
- 开启后积分不足直接返回错误,不执行生图任务 + 开启后积分不足直接返回错误,不执行生成任务
-
-
- -
- 作用于 3D 生成功能(文生3D / 图生3D / - 多视图3D),每次提交任务扣除一次。 +
+
+
+ +
+ 作用于 3D模型模式(文生3D / 图生3D / 多视图3D),每次提交任务扣除一次。 +
+
+
+ + setSiteSettings({ + ...siteSettings, + pointsSystemConfig: { + ...siteSettings.pointsSystemConfig, + creditCostPer3DModel: Math.max( + 0, + Number.parseInt(e.target.value || "0", 10) || 0 + ), + }, + }) + } + />
-
- - setSiteSettings({ - ...siteSettings, - pointsSystemConfig: { - ...siteSettings.pointsSystemConfig, - creditCostPer3D: Math.max( - 0, - Number.parseInt(e.target.value || "0", 10) || 0 - ), - }, - }) - } - /> +
+
+ +
+ 作用于 3D世界模式(文本 / 图片 / 多图 / 视频生成世界),每次提交任务扣除一次。 +
+
+
+ + setSiteSettings({ + ...siteSettings, + pointsSystemConfig: { + ...siteSettings.pointsSystemConfig, + creditCostPer3DWorld: Math.max( + 0, + Number.parseInt(e.target.value || "0", 10) || 0 + ), + }, + }) + } + /> +
diff --git a/app/api/canvas/3d/tasks/route.ts b/app/api/canvas/3d/tasks/route.ts index 50ed0b1b8..c9565139a 100644 --- a/app/api/canvas/3d/tasks/route.ts +++ b/app/api/canvas/3d/tasks/route.ts @@ -341,8 +341,8 @@ export async function POST(request: Request) { const pointsConfig = await getPointsSystemConfig(); const shouldChargePoints = shouldCharge3DPoints(taskType); - const unitCost = Number.isFinite(Number(pointsConfig.creditCostPer3D)) - ? Math.max(0, Math.round(Number(pointsConfig.creditCostPer3D))) + const unitCost = Number.isFinite(Number(pointsConfig.creditCostPer3DModel)) + ? Math.max(0, Math.round(Number(pointsConfig.creditCostPer3DModel))) : 0; if ( @@ -399,7 +399,7 @@ export async function POST(request: Request) { amount: unitCost, reason: "model3d_generation", modelId: "tripo-3d", - note: "3D生成消耗积分", + note: "3D模型生成消耗积分", }); if (!consumeResult.ok) { @@ -412,7 +412,7 @@ export async function POST(request: Request) { ); } else { console.log( - `[Points] Consumed ${unitCost} points for 3D generation. user=${session.user.id} task=${taskId} balance=${consumeResult.balance}` + `[Points] Consumed ${unitCost} points for 3D model generation. user=${session.user.id} task=${taskId} balance=${consumeResult.balance}` ); } } catch (error) { diff --git a/app/api/canvas/world/tasks/route.ts b/app/api/canvas/world/tasks/route.ts index 9fa04fc7c..b499585a2 100644 --- a/app/api/canvas/world/tasks/route.ts +++ b/app/api/canvas/world/tasks/route.ts @@ -143,8 +143,8 @@ export async function POST(request: Request) { const pointsConfig = await getPointsSystemConfig(); const shouldChargePoints = shouldCharge3DPoints(mode); - const unitCost = Number.isFinite(Number(pointsConfig.creditCostPer3D)) - ? Math.max(0, Math.round(Number(pointsConfig.creditCostPer3D))) + const unitCost = Number.isFinite(Number(pointsConfig.creditCostPer3DWorld)) + ? Math.max(0, Math.round(Number(pointsConfig.creditCostPer3DWorld))) : 0; if ( @@ -209,7 +209,7 @@ export async function POST(request: Request) { await consumeUserPoints({ userId: session.user.id, amount: unitCost, - reason: "model3d_generation", + reason: "world3d_generation", modelId: "worldlabs-3d", note: "3D世界生成消耗积分", }); diff --git a/app/api/user/account-center/route.ts b/app/api/user/account-center/route.ts index 8b2f30582..d74eb5104 100644 --- a/app/api/user/account-center/route.ts +++ b/app/api/user/account-center/route.ts @@ -22,7 +22,8 @@ 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 === "model3d_generation") return "3D模型生成"; + if (reason === "world3d_generation") return "3D世界生成"; if (reason === "video_generation") return "视频生成"; if (reason === "deduct") return "管理员扣减"; if (reason === "gift") return "管理员赠送"; diff --git a/lib/points/config.ts b/lib/points/config.ts index 0302315c7..c76bf62e8 100644 --- a/lib/points/config.ts +++ b/lib/points/config.ts @@ -4,7 +4,8 @@ export const POINTS_PACKAGES_KEY = "points_packages"; export type PointsSystemConfig = { enabled: boolean; blockOnInsufficient: boolean; - creditCostPer3D: number; + creditCostPer3DModel: number; + creditCostPer3DWorld: number; }; export type PointsPackage = { @@ -19,7 +20,8 @@ export type PointsPackage = { export const defaultPointsSystemConfig: PointsSystemConfig = { enabled: false, blockOnInsufficient: true, - creditCostPer3D: 0, + creditCostPer3DModel: 0, + creditCostPer3DWorld: 0, }; export const defaultPointsPackages: PointsPackage[] = [ @@ -46,15 +48,25 @@ export function normalizePointsSystemConfig(value: unknown): PointsSystemConfig return defaultPointsSystemConfig; } - const raw = value as Partial; - const parsed3DCost = Number(raw.creditCostPer3D); + const raw = value as Partial & { + creditCostPer3D?: number; + }; + const normalizeCost = (input: unknown) => { + const parsedValue = Number(input); + return Number.isFinite(parsedValue) && parsedValue > 0 + ? Math.min(100000, Math.round(parsedValue)) + : 0; + }; + const legacy3DCost = normalizeCost(raw.creditCostPer3D); return { enabled: raw.enabled === true, blockOnInsufficient: raw.blockOnInsufficient !== false, - creditCostPer3D: - Number.isFinite(parsed3DCost) && parsed3DCost > 0 - ? Math.min(100000, Math.round(parsed3DCost)) - : 0, + creditCostPer3DModel: normalizeCost( + raw.creditCostPer3DModel ?? legacy3DCost + ), + creditCostPer3DWorld: normalizeCost( + raw.creditCostPer3DWorld ?? legacy3DCost + ), }; }