perf(core): 非资产全局态也改按页懒加载,bootstrap 从 ~10 接口瘦到 ~6
启动只保留「每页 shell 都要」的全局数据:商品/项目(侧栏+导航)、余额(顶栏)、 模型配置(多生成页+pipeline 共用)、未读数(侧栏徽标,page_size=1 轻量)。其余移到各页按需: - 账户页:流水(本就服务端分页)+ 趋势 + 团队成员 本页自取,充值后刷新。 - 团队页:成员 + 团队动态 本页自取,增删成员/充值后刷新。 - 生图工厂:任务历史 + 任务缩略图本页自取。 - 通知:bootstrap 只取 page_size=1 拿未读数(notificationsBadge),列表由消息中心/团队页各自拉。 - 全局默认分页改 DefaultPagination(支持 ?page_size 覆盖,默认 20 上限 200): 根治 projects/products 等列表端点忽略 page_size、数据过 20 即被迫翻页(同 assets 旧病)。 闸:9 页功能正常、无瀑布、API 检查全过;首屏接口数 5~8(原 8~13)。perf 预算下调到新基线。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+10
-35
@@ -102,14 +102,8 @@ export function App() {
|
||||
const [team, setTeam] = useState<Team | null>(null);
|
||||
const [products, setProducts] = useState<Product[]>([]);
|
||||
const [projects, setProjects] = useState<Project[]>([]);
|
||||
const [teamMembers, setTeamMembers] = useState<TeamMember[]>([]);
|
||||
const [modelConfigs, setModelConfigs] = useState<ModelConfig[]>([]);
|
||||
const [aiTasks, setAiTasks] = useState<AITask[]>([]);
|
||||
const [billing, setBilling] = useState<BillingSummary | null>(null);
|
||||
const [ledgers, setLedgers] = useState<Ledger[]>([]);
|
||||
const [billingTrend, setBillingTrend] = useState<BillingTrend | null>(null);
|
||||
const [notifications, setNotifications] = useState<Notification[]>([]);
|
||||
const [notificationTotal, setNotificationTotal] = useState(0); // 后端真实总数(团队动态「共 N」用,与已加载的近期 100 条区分)
|
||||
const [unreadCount, setUnreadCount] = useState(0);
|
||||
const [projectDetail, setProjectDetail] = useState<Project | null>(null);
|
||||
const [exportResult, setExportResult] = useState<ExportPoll | null>(null);
|
||||
@@ -138,32 +132,22 @@ export function App() {
|
||||
);
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
// 资产不再全局取全:各页按需服务端分页懒加载(library/生图/商品详情/dashboard 自取)。
|
||||
const [productData, projectData, billingData, ledgerData, trendData, memberData, modelData, taskData, notificationData] =
|
||||
// bootstrap 只拉「每页 shell 都要」的全局数据:商品/项目(侧栏+导航+active 解析)、余额(顶栏)、
|
||||
// 模型配置(多生成页+pipeline 共用)、未读数(侧栏徽标,page_size=1 轻量)。
|
||||
// 资产/流水/趋势/成员/任务/通知列表均改各页按需懒加载,不再全局取全。
|
||||
const [productData, projectData, billingData, modelData, badgeData] =
|
||||
await Promise.all([
|
||||
api.products(),
|
||||
api.projects(),
|
||||
api.billingSummary().catch(() => null),
|
||||
api.ledgers(1, 10).catch(() => ({ count: 0, page: 1, page_size: 10, results: [] as Ledger[] })),
|
||||
api.billingTrend().catch(() => null),
|
||||
api.teamMembers().catch(() => []),
|
||||
api.modelConfigs().catch(() => null),
|
||||
api.aiTasks().catch(() => null),
|
||||
api.allNotifications().catch(() => null)
|
||||
api.notificationsBadge().catch(() => null)
|
||||
]);
|
||||
setProducts(productData.results);
|
||||
setProjects(projectData.results);
|
||||
setTeamMembers(memberData);
|
||||
setModelConfigs(modelData?.results || []);
|
||||
setAiTasks(taskData?.results || []);
|
||||
if (billingData) setBilling(billingData);
|
||||
setLedgers(ledgerData.results);
|
||||
setBillingTrend(trendData);
|
||||
if (notificationData) {
|
||||
setNotifications(notificationData.results);
|
||||
setNotificationTotal(notificationData.count);
|
||||
setUnreadCount(notificationData.unread_count);
|
||||
}
|
||||
if (badgeData) setUnreadCount(badgeData.unread_count);
|
||||
setActiveProjectId((current) => current || projectData.results[0]?.id || "");
|
||||
setActiveProductId((current) => current || productData.results[0]?.id || "");
|
||||
}, []);
|
||||
@@ -210,13 +194,10 @@ export function App() {
|
||||
setSessions(await api.loginSessions().catch(() => []));
|
||||
}
|
||||
|
||||
// 只刷新侧边栏未读徽标(通知列表由消息中心/团队页各自拉);标记已读后调用
|
||||
const reloadNotifications = useCallback(async () => {
|
||||
const data = await api.allNotifications().catch(() => null);
|
||||
if (data) {
|
||||
setNotifications(data.results);
|
||||
setNotificationTotal(data.count);
|
||||
setUnreadCount(data.unread_count);
|
||||
}
|
||||
const data = await api.notificationsBadge().catch(() => null);
|
||||
if (data) setUnreadCount(data.unread_count);
|
||||
}, []);
|
||||
|
||||
// Boot: validate token, hydrate identity + data.
|
||||
@@ -659,10 +640,7 @@ export function App() {
|
||||
return (
|
||||
<AccountPage
|
||||
billing={billing}
|
||||
ledgers={ledgers}
|
||||
trend={billingTrend}
|
||||
projects={projects}
|
||||
teamMembers={teamMembers}
|
||||
onRecharge={(amount, bonus) => action(() => api.recharge({ amount, bonus }), "充值成功")}
|
||||
/>
|
||||
);
|
||||
@@ -671,10 +649,7 @@ export function App() {
|
||||
<TeamPage
|
||||
team={currentTeam}
|
||||
user={currentUser}
|
||||
members={teamMembers}
|
||||
billing={billing}
|
||||
notifications={notifications}
|
||||
notificationTotal={notificationTotal}
|
||||
navigate={navigate}
|
||||
onCreateMember={(payload) => action(() => api.createTeamMember(payload), "成员账户已创建")}
|
||||
onUpdateMember={(id, payload) => action(() => api.updateTeamMember(id, payload), "成员已更新")}
|
||||
@@ -693,7 +668,7 @@ export function App() {
|
||||
/>
|
||||
);
|
||||
case "assetFactory":
|
||||
return <AssetFactoryPage navigate={navigate} aiTasks={aiTasks} />;
|
||||
return <AssetFactoryPage navigate={navigate} />;
|
||||
case "imageOptimize":
|
||||
return <ImageWorkbenchPage mode="image" products={products} modelConfigs={modelConfigs} initialProductId={activeProductId} onBack={() => navigate("assetFactory")} navigate={navigate} onGenerate={generateImages} onResume={resumeImages} />;
|
||||
case "modelPhoto":
|
||||
|
||||
Reference in New Issue
Block a user