🔄 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.
This commit is contained in:
@@ -2,6 +2,7 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"one-api/common"
|
"one-api/common"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"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)
|
db = db.Where("model_name LIKE ? OR description LIKE ? OR tags LIKE ?", like, like, like)
|
||||||
}
|
}
|
||||||
if vendor != "" {
|
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
|
var total int64
|
||||||
err := db.Count(&total).Error
|
err := db.Count(&total).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
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
|
return models, total, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,9 +75,10 @@ const EditModelModal = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchVendors();
|
if (props.visiable) {
|
||||||
}, []);
|
fetchVendors();
|
||||||
|
}
|
||||||
|
}, [props.visiable]);
|
||||||
|
|
||||||
const getInitValues = () => ({
|
const getInitValues = () => ({
|
||||||
model_name: '',
|
model_name: '',
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ export const useModelsData = () => {
|
|||||||
setModels(models);
|
setModels(models);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取供应商列表
|
// Vendor list
|
||||||
const [vendors, setVendors] = useState([]);
|
const [vendors, setVendors] = useState([]);
|
||||||
const [vendorCounts, setVendorCounts] = useState({});
|
const [vendorCounts, setVendorCounts] = useState({});
|
||||||
const [activeVendorKey, setActiveVendorKey] = useState('all');
|
const [activeVendorKey, setActiveVendorKey] = useState('all');
|
||||||
@@ -103,7 +103,7 @@ export const useModelsData = () => {
|
|||||||
return map;
|
return map;
|
||||||
}, [vendors]);
|
}, [vendors]);
|
||||||
|
|
||||||
// 加载供应商列表
|
// Load vendor list
|
||||||
const loadVendors = async () => {
|
const loadVendors = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await API.get('/api/vendors/?page_size=1000');
|
const res = await API.get('/api/vendors/?page_size=1000');
|
||||||
@@ -122,11 +122,8 @@ export const useModelsData = () => {
|
|||||||
try {
|
try {
|
||||||
let url = `/api/models/?p=${page}&page_size=${size}`;
|
let url = `/api/models/?p=${page}&page_size=${size}`;
|
||||||
if (vendorKey && vendorKey !== 'all') {
|
if (vendorKey && vendorKey !== 'all') {
|
||||||
// 按供应商筛选,通过vendor搜索接口
|
// Filter by vendor ID
|
||||||
const vendor = vendors.find(v => String(v.id) === vendorKey);
|
url = `/api/models/search?vendor=${vendorKey}&p=${page}&page_size=${size}`;
|
||||||
if (vendor) {
|
|
||||||
url = `/api/models/search?vendor=${vendor.name}&p=${page}&page_size=${size}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await API.get(url);
|
const res = await API.get(url);
|
||||||
@@ -138,8 +135,10 @@ export const useModelsData = () => {
|
|||||||
setModelCount(data.total || newPageData.length);
|
setModelCount(data.total || newPageData.length);
|
||||||
setModelFormat(newPageData);
|
setModelFormat(newPageData);
|
||||||
|
|
||||||
// 更新供应商统计
|
// Refresh vendor counts only when viewing 'all' to preserve other counts
|
||||||
updateVendorCounts(newPageData);
|
if (vendorKey === 'all') {
|
||||||
|
updateVendorCounts(newPageData);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
setModels([]);
|
setModels([]);
|
||||||
@@ -227,7 +226,7 @@ export const useModelsData = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新供应商统计
|
// Update vendor counts
|
||||||
const updateVendorCounts = (models) => {
|
const updateVendorCounts = (models) => {
|
||||||
const counts = { all: models.length };
|
const counts = { all: models.length };
|
||||||
models.forEach(model => {
|
models.forEach(model => {
|
||||||
@@ -244,6 +243,11 @@ export const useModelsData = () => {
|
|||||||
loadModels(page, pageSize, activeVendorKey);
|
loadModels(page, pageSize, activeVendorKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Reload models when activeVendorKey changes
|
||||||
|
useEffect(() => {
|
||||||
|
loadModels(1, pageSize, activeVendorKey);
|
||||||
|
}, [activeVendorKey]);
|
||||||
|
|
||||||
// Handle page size change
|
// Handle page size change
|
||||||
const handlePageSizeChange = async (size) => {
|
const handlePageSizeChange = async (size) => {
|
||||||
setPageSize(size);
|
setPageSize(size);
|
||||||
|
|||||||
Reference in New Issue
Block a user