perf(core): 资产预览改 TOS 公读直链 + 通知只取首页,减刷新开销与缓存失效
- 资产 preview_url 从「逐图签发预签名 URL」改为虚拟主机式公读直链 (https://{bucket}.{host}/{key})。桶公读已验证免签可访问;直链稳定可被浏览器/CDN 缓存,而签名链每次都变、1h 过期反而打不到缓存。boto3 也移出序列化热路径。 - allNotifications 不再逐页翻全部(原 O(N) 随消息增长拖慢每次刷新),只取首页 100 条 (侧边栏徽标 unread_count + 团队动态仅展示最近 6 条已足够);「共 N」改用后端真实 count。 - perf-probe:page_size 由 API 级硬闸确定性守住后,浏览器端「资产翻页」降为提示 (翻 1~2 页是资产真超 200 的合法分页,仅 ≥3 页才疑似 page_size 失效)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -110,6 +110,7 @@ export function App() {
|
||||
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);
|
||||
@@ -162,6 +163,7 @@ export function App() {
|
||||
setBillingTrend(trendData);
|
||||
if (notificationData) {
|
||||
setNotifications(notificationData.results);
|
||||
setNotificationTotal(notificationData.count);
|
||||
setUnreadCount(notificationData.unread_count);
|
||||
}
|
||||
setActiveProjectId((current) => current || projectData.results[0]?.id || "");
|
||||
@@ -214,6 +216,7 @@ export function App() {
|
||||
const data = await api.allNotifications().catch(() => null);
|
||||
if (data) {
|
||||
setNotifications(data.results);
|
||||
setNotificationTotal(data.count);
|
||||
setUnreadCount(data.unread_count);
|
||||
}
|
||||
}, []);
|
||||
@@ -674,6 +677,7 @@ export function App() {
|
||||
members={teamMembers}
|
||||
billing={billing}
|
||||
notifications={notifications}
|
||||
notificationTotal={notificationTotal}
|
||||
navigate={navigate}
|
||||
onCreateMember={(payload) => action(() => api.createTeamMember(payload), "成员账户已创建")}
|
||||
onUpdateMember={(id, payload) => action(() => api.updateTeamMember(id, payload), "成员已更新")}
|
||||
@@ -771,7 +775,7 @@ export function App() {
|
||||
}, "故事板已生成")
|
||||
}
|
||||
onAdoptBaseAsset={(groupId, assetId) => action(() => api.adoptBaseAsset(pipelineProject.id, { group_id: groupId, asset_id: assetId }), "已采用该候选")}
|
||||
onAttachBaseAsset={(groupId, assetId) => action(() => api.attachBaseAsset(pipelineProject.id, { group_id: groupId, asset_id: assetId }), "已替换为所选演员")}
|
||||
onAttachBaseAsset={(target, assetId) => action(() => api.attachBaseAsset(pipelineProject.id, { ...target, asset_id: assetId }), "已替换为所选演员")}
|
||||
onGenerateTriview={async (portraitAssetId) => {
|
||||
// 异步:image_edit 慢出图在 worker 跑,轮询期间整站不卡;出图后刷新即见三视图
|
||||
const assetId = await submitAndPollAsset(() => api.generateTriview(pipelineProject.id, { portrait_asset_id: portraitAssetId }), "三视图已据立绘生成");
|
||||
@@ -784,8 +788,11 @@ export function App() {
|
||||
fd.append("name", file.name);
|
||||
fd.append("asset_type", "image");
|
||||
fd.append("category", "person");
|
||||
return action(() => api.uploadAsset(fd), "演员已保存到演员库");
|
||||
// 返回上传后的 Asset(供添加人物工作台进右侧栏做三视图/命名)
|
||||
return action(() => api.uploadAsset(fd), "");
|
||||
}}
|
||||
// 流程步骤4 · 添加人物工作台命名:把名字写回该人物资产
|
||||
onRenameActor={(assetId, name) => action(() => api.updateAsset(assetId, { name }), "")}
|
||||
onSkipStoryboard={() => action(() => api.skipStoryboard(pipelineProject.id), "已跳过故事板")}
|
||||
onSubmitVideo={(segmentId, prompt) => action(() => api.submitVideo(pipelineProject.id, { video_segment_id: segmentId, prompt }), "视频片段已提交,生成中…")}
|
||||
onSubmitAllVideos={(prompt) =>
|
||||
|
||||
Reference in New Issue
Block a user