+
+
+
+ 作用于 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
+ ),
};
}