From b64c8ea56b25e3134fe9bed48b7d10b750c6d18a Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Mon, 4 Aug 2025 00:00:51 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=80=20feat:=20expose=20=E2=80=9CEnable?= =?UTF-8?q?d=20Groups=E2=80=9D=20for=20models=20with=20real-time=20refresh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend • model/model_meta.go – Added `EnableGroups []string` to Model struct – fillModelExtra now populates EnableGroups • model/model_groups.go – New helper `GetModelEnableGroups` (reuses Pricing cache) • model/pricing_refresh.go – Added `RefreshPricing()` to force immediate cache rebuild • controller/model_meta.go – `GetAllModelsMeta` & `SearchModelsMeta` call `model.RefreshPricing()` before querying, ensuring groups / endpoints are up-to-date Frontend • ModelsColumnDefs.js – Added `renderGroups` util and “可用分组” table column displaying color-coded tags Result Admins can now see which user groups can access each model, and any ability/group changes are reflected instantly without the previous 1-minute delay. --- controller/model_meta.go | 10 +++++++++- model/model_groups.go | 12 ++++++++++++ model/model_meta.go | 1 + model/pricing_refresh.go | 14 ++++++++++++++ .../table/models/ModelsColumnDefs.js | 18 ++++++++++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 model/model_groups.go create mode 100644 model/pricing_refresh.go diff --git a/controller/model_meta.go b/controller/model_meta.go index 9039419d..3ba09240 100644 --- a/controller/model_meta.go +++ b/controller/model_meta.go @@ -12,6 +12,9 @@ import ( // GetAllModelsMeta 获取模型列表(分页) func GetAllModelsMeta(c *gin.Context) { + + model.RefreshPricing() + pageInfo := common.GetPageQuery(c) modelsMeta, err := model.GetAllModels(pageInfo.GetStartIdx(), pageInfo.GetPageSize()) if err != nil { @@ -31,6 +34,9 @@ func GetAllModelsMeta(c *gin.Context) { // SearchModelsMeta 搜索模型列表 func SearchModelsMeta(c *gin.Context) { + + model.RefreshPricing() + keyword := c.Query("keyword") vendor := c.Query("vendor") pageInfo := common.GetPageQuery(c) @@ -128,7 +134,7 @@ func DeleteModelMeta(c *gin.Context) { common.ApiSuccess(c, nil) } -// 辅助函数:填充 Endpoints 和 BoundChannels +// 辅助函数:填充 Endpoints 和 BoundChannels 和 EnableGroups func fillModelExtra(m *model.Model) { if m.Endpoints == "" { eps := model.GetModelSupportEndpointTypes(m.ModelName) @@ -139,5 +145,7 @@ func fillModelExtra(m *model.Model) { if channels, err := model.GetBoundChannels(m.ModelName); err == nil { m.BoundChannels = channels } + // 填充启用分组 + m.EnableGroups = model.GetModelEnableGroups(m.ModelName) } diff --git a/model/model_groups.go b/model/model_groups.go new file mode 100644 index 00000000..3957b909 --- /dev/null +++ b/model/model_groups.go @@ -0,0 +1,12 @@ +package model + +// GetModelEnableGroups 返回指定模型名称可用的用户分组列表。 +// 复用缓存的定价映射,避免额外的数据库查询。 +func GetModelEnableGroups(modelName string) []string { + for _, p := range GetPricing() { + if p.ModelName == modelName { + return p.EnableGroup + } + } + return make([]string, 0) +} diff --git a/model/model_meta.go b/model/model_meta.go index 6f6c5e22..84742288 100644 --- a/model/model_meta.go +++ b/model/model_meta.go @@ -38,6 +38,7 @@ type Model struct { DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` BoundChannels []BoundChannel `json:"bound_channels,omitempty" gorm:"-"` + EnableGroups []string `json:"enable_groups,omitempty" gorm:"-"` } // Insert 创建新的模型元数据记录 diff --git a/model/pricing_refresh.go b/model/pricing_refresh.go new file mode 100644 index 00000000..de72a8bb --- /dev/null +++ b/model/pricing_refresh.go @@ -0,0 +1,14 @@ +package model + +// RefreshPricing 强制立即重新计算与定价相关的缓存。 +// 该方法用于需要最新数据的内部管理 API, +// 因此会绕过默认的 1 分钟延迟刷新。 +func RefreshPricing() { + updatePricingLock.Lock() + defer updatePricingLock.Unlock() + + modelSupportEndpointsLock.Lock() + defer modelSupportEndpointsLock.Unlock() + + updatePricing() +} diff --git a/web/src/components/table/models/ModelsColumnDefs.js b/web/src/components/table/models/ModelsColumnDefs.js index 7e12ed6f..e02090d8 100644 --- a/web/src/components/table/models/ModelsColumnDefs.js +++ b/web/src/components/table/models/ModelsColumnDefs.js @@ -91,6 +91,19 @@ const renderDescription = (text) => { ); }; +// Render groups (enable_groups) +const renderGroups = (groups) => { + if (!groups || groups.length === 0) return '-'; + return renderLimitedItems({ + items: groups, + renderItem: (g, idx) => ( + + {g} + + ), + }); +}; + // Render tags const renderTags = (text) => { if (!text) return '-'; @@ -232,6 +245,11 @@ export const getModelsColumns = ({ dataIndex: 'bound_channels', render: renderBoundChannels, }, + { + title: t('可用分组'), + dataIndex: 'enable_groups', + render: renderGroups, + }, { title: t('创建时间'), dataIndex: 'created_time',