fix: charge style pro image generation
This commit is contained in:
parent
5ece717e31
commit
ce5daaea45
@ -1,8 +1,10 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { z } from "zod";
|
||||
import { auth } from "@/app/(auth)/auth";
|
||||
import { getModelGenerationCreditCost } from "@/lib/ai/image-model-pricing";
|
||||
import { generateCanvasImage } from "@/lib/canvas/generate-image";
|
||||
import { getSystemSetting } from "@/lib/db/queries";
|
||||
import { prepareFeaturePointsCharge } from "@/lib/points/feature-charge";
|
||||
import {
|
||||
findStyleProImageModelByRef,
|
||||
getStyleProImageModelEntries,
|
||||
@ -194,12 +196,21 @@ export async function POST(request: Request) {
|
||||
);
|
||||
}
|
||||
|
||||
let selectedModelRef = config.modelId || undefined;
|
||||
const imageModelEntries = await getStyleProImageModelEntries({
|
||||
includeHidden: false,
|
||||
});
|
||||
const configuredDefaultModel = findStyleProImageModelByRef(
|
||||
imageModelEntries,
|
||||
config.modelId
|
||||
);
|
||||
let selectedModel =
|
||||
configuredDefaultModel ||
|
||||
imageModelEntries.find((entry) => entry.model.isDefault) ||
|
||||
imageModelEntries[0] ||
|
||||
null;
|
||||
|
||||
if (body.modelId) {
|
||||
const imageModelEntries = await getStyleProImageModelEntries({
|
||||
includeHidden: false,
|
||||
});
|
||||
const selectedModel = findStyleProImageModelByRef(
|
||||
selectedModel = findStyleProImageModelByRef(
|
||||
imageModelEntries,
|
||||
body.modelId
|
||||
);
|
||||
@ -209,7 +220,26 @@ export async function POST(request: Request) {
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
selectedModelRef = selectedModel.model.id;
|
||||
}
|
||||
if (!selectedModel) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: "暂无可用的风格化 PRO 生图模型" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
const selectedModelRef = selectedModel.model.id;
|
||||
const unitCost = getModelGenerationCreditCost(selectedModel.model, "image");
|
||||
const pointsCharge = await prepareFeaturePointsCharge({
|
||||
userId: session.user.id,
|
||||
unitCost,
|
||||
reason: "style_pro_generation",
|
||||
modelId: selectedModel.model.id,
|
||||
note: `风格化 PRO 生图消耗积分(${selectedModel.model.displayName})`,
|
||||
});
|
||||
if (!pointsCharge.ok) {
|
||||
return NextResponse.json(pointsCharge.payload, {
|
||||
status: pointsCharge.status,
|
||||
});
|
||||
}
|
||||
|
||||
const prompt = composePrompt({
|
||||
@ -239,6 +269,23 @@ export async function POST(request: Request) {
|
||||
{ status: 502 }
|
||||
);
|
||||
}
|
||||
let chargedPoints = 0;
|
||||
if (pointsCharge.chargeable) {
|
||||
try {
|
||||
const consumeResult = await pointsCharge.consume();
|
||||
if (consumeResult?.ok && !consumeResult.skipped) {
|
||||
chargedPoints = pointsCharge.unitCost;
|
||||
} else if (!consumeResult?.ok) {
|
||||
console.warn("[Style Pro Generate] Failed to consume points:", {
|
||||
userId: session.user.id,
|
||||
modelId: selectedModel.model.id,
|
||||
unitCost: pointsCharge.unitCost,
|
||||
});
|
||||
}
|
||||
} catch (pointsError) {
|
||||
console.error("[Style Pro Generate] Points consume failed:", pointsError);
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
@ -247,6 +294,7 @@ export async function POST(request: Request) {
|
||||
thumbnailUrl: image.thumbnailUrl || image.originalUrl,
|
||||
model: result.model,
|
||||
modelRef: result.modelRef,
|
||||
chargedPoints,
|
||||
selections: selectionResult.normalizedSelections,
|
||||
optionLabels: selectionResult.selectedOptions.map(
|
||||
({ category, option }) => `${category.title}:${option.label}`
|
||||
|
||||
@ -27,6 +27,7 @@ const WORLD3D_LEDGER_NOTE_PATTERN = /^3D世界生成消耗积分((.+?))$/;
|
||||
|
||||
function mapLedgerReasonLabel(reason: string) {
|
||||
if (reason === "image_generation") return "图片生成";
|
||||
if (reason === "style_pro_generation") return "风格化 PRO";
|
||||
if (reason === "model3d_generation") return "3D模型生成";
|
||||
if (reason === "model3d_task") return "3D模型任务";
|
||||
if (reason === "model3d_task_refund") return "3D模型任务失败退回";
|
||||
@ -233,8 +234,29 @@ export async function GET() {
|
||||
status: "completed",
|
||||
invoice: "-",
|
||||
}));
|
||||
const pointsBillingRecords = ledger
|
||||
.filter((item) => item.reason !== "gift" && item.reason !== "recharge")
|
||||
.map((item) => ({
|
||||
id: item.id,
|
||||
date: item.createdAt?.toISOString() || new Date().toISOString(),
|
||||
category: formatLedgerDetail({
|
||||
reason: item.reason,
|
||||
note: item.note,
|
||||
modelId: item.modelId,
|
||||
tripoModels: threeDModelAliasConfig.tripoModels,
|
||||
worldModels: threeDModelAliasConfig.worldModels,
|
||||
tripoTaskDisplayNamesByTaskId: model3dTaskDisplayNamesByTaskId,
|
||||
}),
|
||||
amount: item.amount,
|
||||
status: "completed",
|
||||
invoice: "-",
|
||||
}));
|
||||
|
||||
const billingRecords = [...rechargeRecords, ...giftedRecords].sort((a, b) => {
|
||||
const billingRecords = [
|
||||
...rechargeRecords,
|
||||
...giftedRecords,
|
||||
...pointsBillingRecords,
|
||||
].sort((a, b) => {
|
||||
return new Date(b.date).getTime() - new Date(a.date).getTime();
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user