🚀 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:
t0ng7u
2025-08-06 01:40:08 +08:00
parent d61a862fa2
commit 7c814a5fd9
12 changed files with 334 additions and 175 deletions

View File

@@ -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
}, []);