fix(channels): support kimi/zhipu/deepseek platforms in channel pricing

- ChannelsView platformOrder now includes the three CN provider
  platforms so channel pricing can be configured for them; composite
  group expansion/attachment stays limited to the five main platforms
  (matches backend isConcreteRequestPlatform and composite-routes
  target_platform validation)
- SyncPricingModels maps kimi->moonshot, zhipu->zhipu,
  deepseek->deepseek; also fixes gemini mapping to "google" which
  matched zero catalog entries (provider key is "gemini")
- Add CN platform colors to channel pricing model tag classes
This commit is contained in:
shaw
2026-08-18 17:12:01 +08:00
parent 58ccea4eaa
commit 8f6f459835
4 changed files with 21 additions and 6 deletions
@@ -568,9 +568,12 @@ func (h *ChannelHandler) GetModelDefaultPricing(c *gin.Context) {
var platformToLiteLLMProvider = map[string]string{
service.PlatformAnthropic: "anthropic",
service.PlatformOpenAI: "openai",
service.PlatformGemini: "google",
service.PlatformGemini: "gemini",
service.PlatformAntigravity: "anthropic",
service.PlatformGrok: "xai",
service.PlatformKimi: "moonshot",
service.PlatformZhipu: "zhipu",
service.PlatformDeepseek: "deepseek",
}
// SyncPricingModels 返回 LiteLLM 定价目录中指定平台的最新模型列表
@@ -502,7 +502,7 @@ func TestSyncPricingModels_ValidPlatform_EmptyService(t *testing.T) {
svc := service.NewPricingService(nil, nil)
router := setupSyncPricingModelsRouter(svc)
for _, platform := range []string{"anthropic", "openai", "gemini", "antigravity"} {
for _, platform := range []string{"anthropic", "openai", "gemini", "antigravity", "grok", "kimi", "zhipu", "deepseek"} {
req := httptest.NewRequest(http.MethodGet, "/channels/pricing/sync-models?platform="+platform, nil)
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
@@ -368,6 +368,9 @@ export function getPlatformTagClass(platform: string): string {
case 'gemini': return 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400'
case 'antigravity': return 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400'
case 'grok': return 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300'
case 'kimi': return 'bg-pink-100 text-pink-700 dark:bg-pink-900/30 dark:text-pink-400'
case 'zhipu': return 'bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-400'
case 'deepseek': return 'bg-teal-100 text-teal-700 dark:bg-teal-900/30 dark:text-teal-400'
default: return 'bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400'
}
}
@@ -380,6 +383,9 @@ export function getPlatformTextClass(platform: string): string {
case 'gemini': return 'text-blue-700 dark:text-blue-400'
case 'antigravity': return 'text-purple-700 dark:text-purple-400'
case 'grok': return 'text-slate-700 dark:text-slate-300'
case 'kimi': return 'text-pink-700 dark:text-pink-400'
case 'zhipu': return 'text-indigo-700 dark:text-indigo-400'
case 'deepseek': return 'text-teal-700 dark:text-teal-400'
default: return ''
}
}
+10 -4
View File
@@ -762,7 +762,10 @@ const form = reactive({
let abortController: AbortController | null = null
// ── Platform config ──
const platformOrder: GroupPlatform[] = ['anthropic', 'openai', 'gemini', 'antigravity', 'grok']
const platformOrder: GroupPlatform[] = ['anthropic', 'openai', 'gemini', 'antigravity', 'grok', 'kimi', 'zhipu', 'deepseek']
// composite 分组仅覆盖主平台(与后端 isConcreteRequestPlatform / composite-routes target_platform 一致),
// 不含国产供应商平台。
const compositePlatforms: GroupPlatform[] = ['anthropic', 'openai', 'gemini', 'antigravity', 'grok']
// ── Helpers ──
function formatDate(value: string): string {
@@ -801,7 +804,9 @@ function togglePlatform(platform: GroupPlatform) {
}
function getGroupsForPlatform(platform: GroupPlatform): AdminGroup[] {
return allGroups.value.filter(g => g.platform === platform || g.platform === 'composite')
return allGroups.value.filter(
g => g.platform === platform || (g.platform === 'composite' && compositePlatforms.includes(platform))
)
}
// ── Group helpers ──
@@ -1183,7 +1188,7 @@ function apiToForm(channel: Channel): PlatformSection[] {
for (const gid of channel.group_ids || []) {
const p = groupPlatformMap.get(gid)
if (p === 'composite') {
platformOrder.forEach(platform => activePlatforms.add(platform))
compositePlatforms.forEach(platform => activePlatforms.add(platform))
} else if (p) {
activePlatforms.add(p)
}
@@ -1202,7 +1207,8 @@ function apiToForm(channel: Channel): PlatformSection[] {
const groupIds = (channel.group_ids || []).filter(gid => {
const groupPlatform = groupPlatformMap.get(gid)
return groupPlatform === platform || groupPlatform === 'composite'
return groupPlatform === platform ||
(groupPlatform === 'composite' && compositePlatforms.includes(platform))
})
const mapping = (channel.model_mapping || {})[platform] || {}
const pricing = (channel.model_pricing || [])