From 232612898b9d4d3a697943805faf60c31d9da144 Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Thu, 31 Jul 2025 23:30:45 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=84=20fix:=20improve=20vendor-tab=20fi?= =?UTF-8?q?ltering=20&=20counts,=20resolve=20SQL=20ambiguity,=20and=20relo?= =?UTF-8?q?ad=20data=20correctly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend • model/model_meta.go – Import strconv – SearchModels: support numeric vendor ID filter vs. fuzzy name search – Explicitly order by `models.id` to avoid “ambiguous column name: id” error Frontend • hooks/useModelsData.js – Change vendor-filter API to pass vendor ID – Automatically reload models when `activeVendorKey` changes – Update vendor counts only when viewing “All” to preserve other tab totals • Add missing effect in EditModelModal to refresh vendor list only when modal visible • Other minor updates to keep lints clean Result Tabs now: 1. Trigger API requests on click 2. Show accurate per-vendor totals 3. Filter models without resetting other counts Backend search handles both vendor IDs and names without SQL errors. --- model/model_meta.go | 10 ++++++-- .../table/models/modals/EditModelModal.jsx | 7 +++--- web/src/hooks/models/useModelsData.js | 24 +++++++++++-------- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/model/model_meta.go b/model/model_meta.go index f9b3dfc9..ef5e883a 100644 --- a/model/model_meta.go +++ b/model/model_meta.go @@ -2,6 +2,7 @@ package model import ( "one-api/common" + "strconv" "gorm.io/gorm" ) @@ -96,13 +97,18 @@ func SearchModels(keyword string, vendor string, offset int, limit int) ([]*Mode db = db.Where("model_name LIKE ? OR description LIKE ? OR tags LIKE ?", like, like, like) } if vendor != "" { - db = db.Joins("JOIN vendors ON vendors.id = models.vendor_id").Where("vendors.name LIKE ?", "%"+vendor+"%") + // 如果是数字,按供应商 ID 精确匹配;否则按名称模糊匹配 + if vid, err := strconv.Atoi(vendor); err == nil { + db = db.Where("models.vendor_id = ?", vid) + } else { + db = db.Joins("JOIN vendors ON vendors.id = models.vendor_id").Where("vendors.name LIKE ?", "%"+vendor+"%") + } } var total int64 err := db.Count(&total).Error if err != nil { return nil, 0, err } - err = db.Offset(offset).Limit(limit).Order("id DESC").Find(&models).Error + err = db.Offset(offset).Limit(limit).Order("models.id DESC").Find(&models).Error return models, total, err } diff --git a/web/src/components/table/models/modals/EditModelModal.jsx b/web/src/components/table/models/modals/EditModelModal.jsx index 70015cca..038a50d9 100644 --- a/web/src/components/table/models/modals/EditModelModal.jsx +++ b/web/src/components/table/models/modals/EditModelModal.jsx @@ -75,9 +75,10 @@ const EditModelModal = (props) => { }; useEffect(() => { - fetchVendors(); - }, []); - + if (props.visiable) { + fetchVendors(); + } + }, [props.visiable]); const getInitValues = () => ({ model_name: '', diff --git a/web/src/hooks/models/useModelsData.js b/web/src/hooks/models/useModelsData.js index fe83168e..93b68783 100644 --- a/web/src/hooks/models/useModelsData.js +++ b/web/src/hooks/models/useModelsData.js @@ -87,7 +87,7 @@ export const useModelsData = () => { setModels(models); }; - // 获取供应商列表 + // Vendor list const [vendors, setVendors] = useState([]); const [vendorCounts, setVendorCounts] = useState({}); const [activeVendorKey, setActiveVendorKey] = useState('all'); @@ -103,7 +103,7 @@ export const useModelsData = () => { return map; }, [vendors]); - // 加载供应商列表 + // Load vendor list const loadVendors = async () => { try { const res = await API.get('/api/vendors/?page_size=1000'); @@ -122,11 +122,8 @@ export const useModelsData = () => { try { let url = `/api/models/?p=${page}&page_size=${size}`; if (vendorKey && vendorKey !== 'all') { - // 按供应商筛选,通过vendor搜索接口 - const vendor = vendors.find(v => String(v.id) === vendorKey); - if (vendor) { - url = `/api/models/search?vendor=${vendor.name}&p=${page}&page_size=${size}`; - } + // Filter by vendor ID + url = `/api/models/search?vendor=${vendorKey}&p=${page}&page_size=${size}`; } const res = await API.get(url); @@ -138,8 +135,10 @@ export const useModelsData = () => { setModelCount(data.total || newPageData.length); setModelFormat(newPageData); - // 更新供应商统计 - updateVendorCounts(newPageData); + // Refresh vendor counts only when viewing 'all' to preserve other counts + if (vendorKey === 'all') { + updateVendorCounts(newPageData); + } } else { showError(message); setModels([]); @@ -227,7 +226,7 @@ export const useModelsData = () => { } }; - // 更新供应商统计 + // Update vendor counts const updateVendorCounts = (models) => { const counts = { all: models.length }; models.forEach(model => { @@ -244,6 +243,11 @@ export const useModelsData = () => { loadModels(page, pageSize, activeVendorKey); }; + // Reload models when activeVendorKey changes + useEffect(() => { + loadModels(1, pageSize, activeVendorKey); + }, [activeVendorKey]); + // Handle page size change const handlePageSizeChange = async (size) => { setPageSize(size);