From c8f7aa76e7840a91de3e067512181512f1593a85 Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Sun, 10 Aug 2025 21:32:18 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=8D=20feat:=20Show=20matched=20model?= =?UTF-8?q?=20names=20&=20counts=20for=20non-exact=20model=20rules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary ------- 1. **Backend** • `model/model_meta.go` – Add `MatchedModels []string` and `MatchedCount int` (ignored by GORM) to expose matching details in API responses. • `controller/model_meta.go` – When processing prefix/suffix/contains rules in `fillModelExtra`, collect every matched model name, fill `MatchedModels`, and calculate `MatchedCount`. 2. **Frontend** • `web/src/components/table/models/ModelsColumnDefs.js` – Import `Tooltip`. – Enhance `renderNameRule` to: – Display tag text like “前缀 5个模型” for non-exact rules. – Show a tooltip listing all matched model names on hover. Impact ------ Users now see the total number of concrete models aggregated under each prefix/suffix/contains rule and can inspect the exact list via tooltip, improving transparency in model management. --- controller/model_meta.go | 10 +++++++ model/model_meta.go | 3 ++ .../table/models/ModelsColumnDefs.js | 28 +++++++++++++++---- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/controller/model_meta.go b/controller/model_meta.go index 72ba4a41..e7d29fcf 100644 --- a/controller/model_meta.go +++ b/controller/model_meta.go @@ -183,6 +183,9 @@ func fillModelExtra(m *model.Model) { // 非精确匹配:计算并集 pricings := model.GetPricing() + // 匹配到的模型名称集合 + matchedNames := make([]string, 0) + // 端点去重集合 endpointSet := make(map[constant.EndpointType]struct{}) // 已绑定渠道去重集合 @@ -206,6 +209,9 @@ func fillModelExtra(m *model.Model) { continue } + // 记录匹配到的模型名称 + matchedNames = append(matchedNames, p.ModelName) + // 收集端点 for _, et := range p.SupportedEndpointTypes { endpointSet[et] = struct{}{} @@ -265,4 +271,8 @@ func fillModelExtra(m *model.Model) { } else { m.QuotaType = -1 } + + // 设置匹配信息 + m.MatchedModels = matchedNames + m.MatchedCount = len(matchedNames) } diff --git a/model/model_meta.go b/model/model_meta.go index b69608f1..d7bc78c6 100644 --- a/model/model_meta.go +++ b/model/model_meta.go @@ -51,6 +51,9 @@ type Model struct { EnableGroups []string `json:"enable_groups,omitempty" gorm:"-"` QuotaType int `json:"quota_type" gorm:"-"` NameRule int `json:"name_rule" gorm:"default:0"` + + MatchedModels []string `json:"matched_models,omitempty" gorm:"-"` + MatchedCount int `json:"matched_count,omitempty" gorm:"-"` } // Insert 创建新的模型元数据记录 diff --git a/web/src/components/table/models/ModelsColumnDefs.js b/web/src/components/table/models/ModelsColumnDefs.js index 4306730e..e1fc257e 100644 --- a/web/src/components/table/models/ModelsColumnDefs.js +++ b/web/src/components/table/models/ModelsColumnDefs.js @@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com */ import React from 'react'; -import { Button, Space, Tag, Typography, Modal } from '@douyinfe/semi-ui'; +import { Button, Space, Tag, Typography, Modal, Tooltip } from '@douyinfe/semi-ui'; import { timestamp2string, getLobeHubIcon, @@ -208,8 +208,8 @@ const renderOperations = (text, record, setEditingModel, setShowEdit, manageMode ); }; -// 名称匹配类型渲染 -const renderNameRule = (rule, t) => { +// 名称匹配类型渲染(带匹配数量 Tooltip) +const renderNameRule = (rule, record, t) => { const map = { 0: { color: 'green', label: t('精确') }, 1: { color: 'blue', label: t('前缀') }, @@ -218,11 +218,27 @@ const renderNameRule = (rule, t) => { }; const cfg = map[rule]; if (!cfg) return '-'; - return ( + + let label = cfg.label; + if (rule !== 0 && record.matched_count) { + label = `${cfg.label} ${record.matched_count}${t('个模型')}`; + } + + const tagElement = ( - {cfg.label} + {label} ); + + if (rule === 0 || !record.matched_models || record.matched_models.length === 0) { + return tagElement; + } + + return ( + + {tagElement} + + ); }; export const getModelsColumns = ({ @@ -253,7 +269,7 @@ export const getModelsColumns = ({ { title: t('匹配类型'), dataIndex: 'name_rule', - render: (val) => renderNameRule(val, t), + render: (val, record) => renderNameRule(val, record, t), }, { title: t('描述'),