diff --git a/web/src/pages/settings/channel-video-pricing.tsx b/web/src/pages/settings/channel-video-pricing.tsx index 292d25815..dc33a7654 100644 --- a/web/src/pages/settings/channel-video-pricing.tsx +++ b/web/src/pages/settings/channel-video-pricing.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; -import { App, Button, InputNumber, Segmented } from "antd"; -import { FlaskConical } from "lucide-react"; +import { App, Button, Drawer, InputNumber, Segmented, Tag } from "antd"; +import { ChevronRight, FlaskConical, Settings2 } from "lucide-react"; import { testChannelModelConnection } from "@/lib/model-connection-test"; import { ModelCapabilityEditor } from "@/components/model-capability-editor"; @@ -14,6 +14,7 @@ type ModelCost = NonNullable[number]; export function ChannelModelSettings({ channel, onChange }: { channel: ModelChannel; onChange: (costs: ModelCost[]) => void }) { const { message } = App.useApp(); const [testingModel, setTestingModel] = useState(""); + const [activeModel, setActiveModel] = useState(null); if (!channel.models.length) return null; const updateCost = (model: string, patch: Partial) => { @@ -41,10 +42,18 @@ export function ChannelModelSettings({ channel, onChange }: { channel: ModelChan } }; + const activeModelCost = activeModel ? channel.modelCosts?.find((item) => item.model === activeModel) : undefined; + const activeProtocol = activeModel ? activeModelCost?.protocol || defaultProtocolForModel(channel, activeModel) : undefined; + const activeCapability = activeModel ? activeModelCost?.capability || modelProtocolCapability(activeProtocol) || "text" : undefined; + const activeBillingMode = activeModelCost?.billingMode || "fixed_request"; + return (
-
模型能力与请求协议
与运营后台使用同一能力目录;测试会发起真实请求并可能产生供应商费用
+
+
模型能力与请求协议
+
与运营后台使用同一能力目录;测试会发起真实请求并可能产生供应商费用
+
{channel.models.length} 个模型
@@ -55,23 +64,102 @@ export function ChannelModelSettings({ channel, onChange }: { channel: ModelChan const capability = cost?.capability || modelProtocolCapability(protocol) || "text"; const billingMode = cost?.billingMode || "fixed_request"; return ( -
-
-
{model}
{modelProtocolDefinition(protocol)?.create}
- -
-
- updateCost(model, { protocol: nextProtocol, capability: nextCapability, billingMode: nextCapability === "video" ? billingMode : "fixed_request", capabilityConfig: nextCapability === "video" ? defaultModelCapabilityConfig(nextProtocol) : undefined })} - /> - {capability === "video" ?
updateCost(model, { billingMode: value as ModelCost["billingMode"] })} /> updateCost(model, { unitPriceMicrocredits: Math.round(Number(value || 0) * 1_000_000) })} />
: null} - {capability === "video" ? updateCost(model, { capabilityConfig })} /> : null} +
+ + + +
+
+ {model} +
+
+ + {capabilityLabel(capability)} + + + {modelProtocolDefinition(protocol)?.create || "待配置请求协议"} + +
+
); })}
+ setActiveModel(null)} + size="min(720px, 100vw)" + destroyOnHidden + extra={ + activeModel && activeCapability && activeProtocol ? ( + + ) : null + } + > + {activeModel && activeCapability && activeProtocol ? ( +
+
+
模型能力与请求协议
+
这些设置只影响当前渠道的这个模型,保存后会同步到生成校验。
+
+ + updateCost(activeModel, { + protocol: nextProtocol, + capability: nextCapability, + billingMode: nextCapability === "video" ? activeBillingMode : "fixed_request", + capabilityConfig: nextCapability === "video" ? defaultModelCapabilityConfig(nextProtocol) : undefined, + }) + } + /> + {activeCapability === "video" ? ( +
+
计费方式
+
+ updateCost(activeModel, { billingMode: value as ModelCost["billingMode"] })} + /> + updateCost(activeModel, { unitPriceMicrocredits: Math.round(Number(value || 0) * 1_000_000) })} + /> +
+
+ ) : null} + {activeCapability === "video" ? ( + updateCost(activeModel, { capabilityConfig })} /> + ) : null} +
+ ) : null} +
); }