فهرست منبع

🔄 fix: improve vendor-tab filtering & counts, resolve SQL ambiguity, and reload data correctly

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.
t0ng7u 10 ماه پیش
والد
کامیت
232612898b
3فایلهای تغییر یافته به همراه26 افزوده شده و 15 حذف شده
  1. 8 2
      model/model_meta.go
  2. 4 3
      web/src/components/table/models/modals/EditModelModal.jsx
  3. 14 10
      web/src/hooks/models/useModelsData.js

+ 8 - 2
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
 }

+ 4 - 3
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: '',

+ 14 - 10
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);