fix(*): 视频计费与结果解析 - 按 Token 预估展示并解析数组媒体结果
This commit is contained in:
@@ -33,7 +33,9 @@ import { useCopyText } from "@/hooks/use-copy-text";
|
||||
import { buildImageResolutionOptions, formatImageResolutionSize, supportsImageResolutionPresets } from "@/lib/image-resolution-tiers";
|
||||
import { modelCapabilityConfigFor, normalizeVideoValue, videoDurationOptions, type ImageCapabilityConfig, type VideoCapabilityConfig } from "@/lib/model-capabilities";
|
||||
import { mergedImageCapabilityConfig, type ModelRequirements } from "@/lib/model-selection";
|
||||
import { modelQuoteDescription, modelQuoteRequest } from "@/lib/model-pricing";
|
||||
import type { Skill } from "@/services/api/skills";
|
||||
import { quoteModel, type LogicalModelQuote } from "@/services/api/logical-models";
|
||||
import { resolveResourceUrl } from "@/services/api/resources";
|
||||
import { modelOptionName, resolveModelChannel, type AiConfig } from "@/stores/use-config-store";
|
||||
import { useAppearanceStore } from "@/stores/use-appearance-store";
|
||||
@@ -367,6 +369,8 @@ export function CreationComposer(props: ComposerProps) {
|
||||
const canSubmit = Boolean(props.prompt.trim()) && !interactionBusy;
|
||||
const creditsEnabled = useUserStore((state) => state.features.creditsEnabled);
|
||||
const priceChannel = resolveModelChannel(props.config, props.model);
|
||||
const quoteRequest = useMemo(() => modelQuoteRequest(props.config, props.model, props.mode, props.modelRequirements), [props.config, props.mode, props.model, props.modelRequirements]);
|
||||
const [routeQuote, setRouteQuote] = useState<LogicalModelQuote | null>(null);
|
||||
const canOptimizePrompt = Boolean(props.promptOptimizerProvider) && (props.mode === "image" || props.mode === "video");
|
||||
const optimizerReferences = props.references.filter((reference) => reference.active && reference.kind !== "skill");
|
||||
const credits = requestCreditCost({
|
||||
@@ -375,10 +379,28 @@ export function CreationComposer(props: ComposerProps) {
|
||||
model: modelOptionName(props.model),
|
||||
count: props.mode === "image" ? props.count : 1,
|
||||
seconds: props.mode === "video" ? props.seconds : 1,
|
||||
capability: props.mode,
|
||||
config: props.config,
|
||||
requirements: props.modelRequirements,
|
||||
});
|
||||
const showCost = creditsEnabled && credits !== null;
|
||||
const formattedCredits = credits?.toLocaleString("zh-CN", { maximumFractionDigits: 6 });
|
||||
const actionLabel = props.referenceReplacementBusy ? "正在替换参考图" : interactionBusy || (props.generationActive && !canSubmit) ? "生成中" : showCost ? `预计消耗 ${formattedCredits} 积分,发送` : "发送";
|
||||
useEffect(() => {
|
||||
if (!creditsEnabled || !quoteRequest) {
|
||||
setRouteQuote(null);
|
||||
return;
|
||||
}
|
||||
const controller = new AbortController();
|
||||
setRouteQuote(null);
|
||||
quoteModel(quoteRequest, controller.signal)
|
||||
.then(({ quote }) => setRouteQuote(quote))
|
||||
.catch(() => {
|
||||
if (!controller.signal.aborted) setRouteQuote(null);
|
||||
});
|
||||
return () => controller.abort();
|
||||
}, [creditsEnabled, quoteRequest]);
|
||||
const generationCredits = routeQuote ? routeQuote.amountMicrocredits / 1_000_000 : credits;
|
||||
const showCost = creditsEnabled && generationCredits !== null && generationCredits !== undefined;
|
||||
const formattedCredits = generationCredits?.toLocaleString("zh-CN", { maximumFractionDigits: 6 });
|
||||
const actionLabel = props.referenceReplacementBusy ? "正在替换参考图" : interactionBusy || (props.generationActive && !canSubmit) ? "生成中" : showCost ? `${routeQuote?.estimated ? "预估" : "消耗"} ${formattedCredits} 积分,发送` : "发送";
|
||||
// Send-button working state must span the WHOLE generation (not just the
|
||||
// submit-lock window): spinner + glow stay while a message is pending and
|
||||
// the composer is empty; typing a next prompt returns the arrow so the
|
||||
@@ -610,7 +632,7 @@ export function CreationComposer(props: ComposerProps) {
|
||||
title={!canSubmit && !interactionBusy ? "输入创作想法后即可生成" : actionLabel}
|
||||
>
|
||||
{showWorkingGlow ? <WorkingGlow active color="var(--creation-text)" radius="999px" /> : null}
|
||||
{showCost ? <span className="creation-submit-cost"><CreditSymbol /><span>{formattedCredits}</span></span> : null}
|
||||
{showCost ? <span className="creation-submit-cost" title={routeQuote ? modelQuoteDescription(routeQuote) : undefined}><CreditSymbol /><span>{routeQuote?.estimated ? `预估:${formattedCredits}` : formattedCredits}</span></span> : null}
|
||||
<span className="creation-submit-action" aria-hidden>{showWorkingSpinner ? <LoaderCircle className="size-4 animate-spin" /> : <ArrowUp className="size-4" />}<span>{showWorkingSpinner ? "生成中" : "开始创作"}</span></span>
|
||||
</Button>
|
||||
</footer>
|
||||
|
||||
Reference in New Issue
Block a user