From 5e70274003fd654004bbce7948a9215000f6ff00 Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Mon, 4 Aug 2025 15:38:01 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=B0=20feat:=20Add=20model=20billing=20?= =?UTF-8?q?type=20(`quota=5Ftype`)=20support=20across=20backend=20&=20fron?= =?UTF-8?q?tend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary • Backend 1. model/model_meta.go – Added `QuotaType` field to `Model` struct (JSON only, gorm `-`). 2. model/model_groups.go – Implemented `GetModelQuotaType(modelName)` leveraging cached pricing map. 3. controller/model_meta.go – Enhanced `fillModelExtra` to populate `QuotaType` using new helper. • Frontend 1. web/src/components/table/models/ModelsColumnDefs.js – Introduced `renderQuotaType` helper that visualises billing mode with coloured tags (`teal = per-call`, `violet = per-token`). – Added “计费类型” column (`quota_type`) to models table. Why Providing the billing mode alongside existing pricing/group information gives administrators instant visibility into whether each model is priced per call or per token, aligning UI with new backend metadata. Notes No database migration required – `quota_type` is transient, delivered via API. Frontend labels/colours can be adjusted via i18n or theme tokens if necessary. --- controller/model_meta.go | 2 ++ model/model_extra.go | 24 +++++++++++++++++++ model/model_groups.go | 12 ---------- model/model_meta.go | 1 + .../table/models/ModelsColumnDefs.js | 24 +++++++++++++++++++ 5 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 model/model_extra.go delete mode 100644 model/model_groups.go diff --git a/controller/model_meta.go b/controller/model_meta.go index 3ba09240..24329555 100644 --- a/controller/model_meta.go +++ b/controller/model_meta.go @@ -147,5 +147,7 @@ func fillModelExtra(m *model.Model) { } // 填充启用分组 m.EnableGroups = model.GetModelEnableGroups(m.ModelName) + // 填充计费类型 + m.QuotaType = model.GetModelQuotaType(m.ModelName) } diff --git a/model/model_extra.go b/model/model_extra.go new file mode 100644 index 00000000..3724346e --- /dev/null +++ b/model/model_extra.go @@ -0,0 +1,24 @@ +package model + +// GetModelEnableGroups 返回指定模型名称可用的用户分组列表。 +// 复用缓存的定价映射,避免额外的数据库查询。 +func GetModelEnableGroups(modelName string) []string { + for _, p := range GetPricing() { + if p.ModelName == modelName { + return p.EnableGroup + } + } + return make([]string, 0) +} + +// GetModelQuotaType 返回指定模型的计费类型(quota_type)。 +// 复用缓存的定价映射,避免额外数据库查询。 +// 如果未找到对应模型,默认返回 0。 +func GetModelQuotaType(modelName string) int { + for _, p := range GetPricing() { + if p.ModelName == modelName { + return p.QuotaType + } + } + return 0 +} diff --git a/model/model_groups.go b/model/model_groups.go deleted file mode 100644 index 3957b909..00000000 --- a/model/model_groups.go +++ /dev/null @@ -1,12 +0,0 @@ -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 84742288..3598cb7c 100644 --- a/model/model_meta.go +++ b/model/model_meta.go @@ -39,6 +39,7 @@ type Model struct { BoundChannels []BoundChannel `json:"bound_channels,omitempty" gorm:"-"` EnableGroups []string `json:"enable_groups,omitempty" gorm:"-"` + QuotaType int `json:"quota_type" gorm:"-"` } // Insert 创建新的模型元数据记录 diff --git a/web/src/components/table/models/ModelsColumnDefs.js b/web/src/components/table/models/ModelsColumnDefs.js index a2af1c95..f71686fc 100644 --- a/web/src/components/table/models/ModelsColumnDefs.js +++ b/web/src/components/table/models/ModelsColumnDefs.js @@ -98,6 +98,25 @@ const renderEndpoints = (text) => { }); }; +// Render quota type +const renderQuotaType = (qt, t) => { + if (qt === 1) { + return ( + + {t('按次计费')} + + ); + } + if (qt === 0) { + return ( + + {t('按量计费')} + + ); + } + return qt ?? '-'; +}; + // Render bound channels const renderBoundChannels = (channels) => { if (!channels || channels.length === 0) return '-'; @@ -213,6 +232,11 @@ export const getModelsColumns = ({ dataIndex: 'enable_groups', render: renderGroups, }, + { + title: t('计费类型'), + dataIndex: 'quota_type', + render: (qt) => renderQuotaType(qt, t), + }, { title: t('创建时间'), dataIndex: 'created_time',