feat(*): 模型计费与渠道目录 - 支持视频 Token 报价结算和稳定模型展示

This commit is contained in:
ddCat committed 2026-09-18 23:26:54 +08:00
1 parent 9eb2fcd453
commit 531019b368
57 files changed
+2904 -341

No files matched your search

@@ -8,6 +8,8 @@ export type ChannelModelFormValues = {
modelKey: string;
providerModelKey?: string;
displayName?: string;
channelLabel?: string;
description?: string;
icon?: string;
capability: ModelCapabilityChoice;
protocol?: string;
@@ -30,6 +32,8 @@ export function initialChannelModelValues(item: ChannelModel | null, protocols:
modelKey: item?.modelKey || "",
providerModelKey: upstreamModel,
displayName: item?.displayName || "",
channelLabel: item?.channelLabel || "",
description: item?.description || "",
icon: item?.icon || "",
capability,
protocol,
@@ -54,6 +58,7 @@ export function changeChannelModelCapability(values: ChannelModelFormValues, pro
size: "*",
resolution: "*",
videoSeconds: 0,
videoGenerateAudio: "*",
imageCount: 0,
})),
};
@@ -81,15 +86,15 @@ export function validateChannelModelPrices(values: Pick<ChannelModelFormValues,
};
if (!["fixed_request", "per_second", "token"].includes(tier.billingMode)) fail("请选择计费方式");
if (tier.billingMode === "per_second" && capability !== "video") fail("按秒计费仅支持视频,请重新选择计费方式并核对价格");
if (tier.billingMode === "token" && !modelProtocolSupportsTokenBilling(capability, protocol)) fail("当前协议不支持 Token 计费,请重新选择计费方式并核对价格");
if (tier.billingMode === "token" && !modelProtocolSupportsTokenBilling(capability, protocol)) fail("当前模型能力不支持 Token 计费,请重新选择计费方式并核对价格");
if (tier.matchMode === "advanced") {
if (tier.operation && tier.operation !== "*" && !operations[capability]?.includes(tier.operation)) fail("生成方式与模型能力不匹配");
const specific = (value: string | undefined) => Boolean(value && value !== "*");
if (!(specific(tier.operation) || (capability === "image" && (specific(tier.quality) || specific(tier.size))) || (capability === "video" && (specific(tier.resolution) || tier.videoSeconds > 0 || tier.imageCount > 0))))
if (capability === "video" && tier.videoGenerateAudio && !["*", "true", "false"].includes(tier.videoGenerateAudio)) fail("请选择任意音频、有声或无声");
if (!(specific(tier.operation) || (capability === "image" && (specific(tier.quality) || specific(tier.size))) || (capability === "video" && (specific(tier.resolution) || tier.videoSeconds > 0 || tier.imageCount > 0 || specific(tier.videoGenerateAudio)))))
fail("规格价格至少需要一个匹配条件;统一价格请选择默认价格");
}
const prices = tier.billingMode !== "token" ? [tier.unitPrice] : capability === "video" ? [tier.outputTokenPrice] : [tier.inputTokenPrice, tier.outputTokenPrice, tier.cachedTokenPrice];
if (prices.some((price) => typeof price !== "number" || !Number.isFinite(price) || price < 0 || price > 1_000_000)) fail("积分价格必须是 0 到 1000000 之间的有效数值");
if (tier.billingMode === "token" && capability === "video" && tier.outputTokenPrice < 0.000001) fail("视频 Token 价格必须至少为 0.000001");
});
}