🚀 refactor: migrate vendor-count aggregation to model layer & align frontend logic
Summary • Backend – Moved duplicate-name validation and total vendor-count aggregation from controllers (`controller/model_meta.go`, `controller/vendor_meta.go`, `controller/prefill_group.go`) to model layer (`model/model_meta.go`, `model/vendor_meta.go`, `model/prefill_group.go`). – Added `GetVendorModelCounts()` and `Is*NameDuplicated()` helpers; controllers now call these instead of duplicating queries. – API response for `/api/models` now returns `vendor_counts` with per-vendor totals across all pages, plus `all` summary. – Removed redundant checks and unused imports, eliminating `go vet` warnings. • Frontend – `useModelsData.js` updated to consume backend-supplied `vendor_counts`, calculate the `all` total once, and drop legacy client-side counting logic. – Simplified initial data flow: first render now triggers only one models request. – Deleted obsolete `updateVendorCounts` helper and related comments. – Ensured search flow also sets `vendorCounts`, keeping tab badges accurate. Why This refactor enforces single-responsibility (aggregation in model layer), delivers consistent totals irrespective of pagination, and removes redundant client queries, leading to cleaner code and better performance.
This commit is contained in:
@@ -135,9 +135,9 @@ export const useModelsData = () => {
|
||||
setModelCount(data.total || newPageData.length);
|
||||
setModelFormat(newPageData);
|
||||
|
||||
// Refresh vendor counts only when viewing 'all' to preserve other counts
|
||||
if (vendorKey === 'all') {
|
||||
updateVendorCounts(newPageData);
|
||||
if (data.vendor_counts) {
|
||||
const sumAll = Object.values(data.vendor_counts).reduce((acc, v) => acc + v, 0);
|
||||
setVendorCounts({ ...data.vendor_counts, all: sumAll });
|
||||
}
|
||||
} else {
|
||||
showError(message);
|
||||
@@ -151,27 +151,9 @@ export const useModelsData = () => {
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
// Fetch vendor counts separately to keep tab numbers accurate
|
||||
const refreshVendorCounts = async () => {
|
||||
try {
|
||||
// Load all models (large page_size) to compute counts for every vendor
|
||||
const res = await API.get('/api/models/?p=1&page_size=100000');
|
||||
if (res.data.success) {
|
||||
const newItems = extractItems(res.data.data);
|
||||
updateVendorCounts(newItems);
|
||||
}
|
||||
} catch (_) {
|
||||
// ignore count refresh errors
|
||||
}
|
||||
};
|
||||
|
||||
// Refresh data
|
||||
const refresh = async (page = activePage) => {
|
||||
await loadModels(page, pageSize);
|
||||
// When not viewing 'all', tab counts need a separate refresh
|
||||
if (activeVendorKey !== 'all') {
|
||||
await refreshVendorCounts();
|
||||
}
|
||||
};
|
||||
|
||||
// Search models with keyword and vendor
|
||||
@@ -195,6 +177,10 @@ export const useModelsData = () => {
|
||||
setActivePage(data.page || 1);
|
||||
setModelCount(data.total || newPageData.length);
|
||||
setModelFormat(newPageData);
|
||||
if (data.vendor_counts) {
|
||||
const sumAll = Object.values(data.vendor_counts).reduce((acc, v) => acc + v, 0);
|
||||
setVendorCounts({ ...data.vendor_counts, all: sumAll });
|
||||
}
|
||||
} else {
|
||||
showError(message);
|
||||
setModels([]);
|
||||
@@ -242,16 +228,6 @@ export const useModelsData = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// Update vendor counts
|
||||
const updateVendorCounts = (models) => {
|
||||
const counts = { all: models.length };
|
||||
models.forEach(model => {
|
||||
if (model.vendor_id) {
|
||||
counts[model.vendor_id] = (counts[model.vendor_id] || 0) + 1;
|
||||
}
|
||||
});
|
||||
setVendorCounts(counts);
|
||||
};
|
||||
|
||||
// Handle page change
|
||||
const handlePageChange = (page) => {
|
||||
@@ -335,7 +311,6 @@ export const useModelsData = () => {
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
await loadVendors();
|
||||
await loadModels();
|
||||
})();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
Reference in New Issue
Block a user