* feat(canvas): 短剧项目空间 - 建立项目章节与画布关联 MVP * feat(canvas): 短剧项目空间 - 完善项目资产、镜头与流程闭环 Refs #30 * fix(deploy): 本地部署 - 修复前端构建并忽略本地 PostgreSQL 配置 * feat(*): 短剧项目空间 - 完成项目、章节、资产、角色与画布创作闭环 Refs #30 --------- Co-authored-by: ddCat <ddcat666@88.com>
35 lines
1.4 KiB
TypeScript
35 lines
1.4 KiB
TypeScript
import type { ComponentProps } from "react";
|
|
import { Coins } from "lucide-react";
|
|
|
|
export function CreditSymbol({ className, ...props }: ComponentProps<"span">) {
|
|
return (
|
|
<span {...props} className={`inline-flex items-center justify-center ${className || ""}`}>
|
|
<Coins className="size-[1em]" strokeWidth={2.2} />
|
|
</span>
|
|
);
|
|
}
|
|
|
|
export type ModelCreditCost = {
|
|
model: string;
|
|
billingMode: "fixed_request" | "per_second";
|
|
unitPriceMicrocredits: number;
|
|
};
|
|
|
|
function modelCreditCost(modelCosts: ModelCreditCost[] | undefined, model: string) {
|
|
return modelCosts?.find((item) => item.model === model) || null;
|
|
}
|
|
|
|
export function formatCredits(value: number, maximumFractionDigits = 6) {
|
|
return (value / 1_000_000).toLocaleString("zh-CN", { maximumFractionDigits });
|
|
}
|
|
|
|
export function requestCreditCost(options: { channelMode: string; modelCosts?: ModelCreditCost[]; model: string; count?: string | number; seconds?: string | number }) {
|
|
if (options.channelMode !== "remote") return null;
|
|
const cost = modelCreditCost(options.modelCosts, options.model);
|
|
if (!cost) return null;
|
|
const quantity = cost.billingMode === "per_second"
|
|
? Math.max(1, Math.floor(Math.abs(Number(options.seconds)) || 1))
|
|
: Math.max(1, Math.floor(Math.abs(Number(options.count)) || 1));
|
|
return (cost.unitPriceMicrocredits / 1_000_000) * quantity;
|
|
}
|