后端生成闸+多项修复;前端全站更新;QA 审计与报告

后端:
- 新增 celery_health 生成前置闸——无 worker 在线时图片/视频生成入口
  一律 503,防"提交到 ARK 后无人轮询、结果悬空+额度冻结"的数据丢失
- 拼接导出:帧率跟随源众数、字幕逐句重映射、原声/BGM 混音修复
- 资金核算审计脚本 + genesis 账目回填 + 滞留预留清理命令
- 接入 yunqi provider 与豆包 TTS 模型(catalog/migrations/bootstrap 命令)

前端:全站页面更新(pipeline/library/products/projects/team/account 等),
新增共享 pager 分页组件

QA:刷新 function-audit 全量输出,新增 full-qa 报告
文档:BP 产品介绍资料、design/CLAUDE.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
zyc
2026-06-15 10:06:15 +08:00
co-authored by Claude Fable 5
parent 890cb9ab67
commit 216a711291
92 changed files with 5114 additions and 2027 deletions
+10 -14
View File
@@ -23,6 +23,7 @@ import {
} from "lucide-react";
import type { AITask, Asset, ModelConfig, Product } from "../types";
import { MediaLightbox } from "../components/overlays";
import { Pager } from "../components/pager";
import type { Page } from "./route-config";
import { statusPill } from "./stage-config";
import "../ai-tools-page.css";
@@ -133,9 +134,9 @@ export function AssetFactoryPage({ navigate, aiTasks, assets = [] }: { navigate:
const [typeFilter, setTypeFilter] = useState("");
const [view, setView] = useState<"grid" | "list">("grid");
const [openChip, setOpenChip] = useState<"" | "time" | "type">("");
// 任务中心分页:每次加载 12 条,「加载更多」递增;筛选/搜索变化时重置
const TASKS_PER_LOAD = 12;
const [shown, setShown] = useState(TASKS_PER_LOAD);
// 任务中心分页:每页 10 条,筛选/搜索变化时回第 1 页
const TASKS_PER_PAGE = 10;
const [taskPage, setTaskPage] = useState(1);
useEffect(() => {
if (!openChip) return;
const close = (event: MouseEvent) => { if (!(event.target as HTMLElement).closest(".chip-wrap")) setOpenChip(""); };
@@ -163,10 +164,11 @@ export function AssetFactoryPage({ navigate, aiTasks, assets = [] }: { navigate:
}
return true;
});
// 筛选条件变化时回到第一屏(12 条)
useEffect(() => { setShown(TASKS_PER_LOAD); }, [filter, query, timeFilter, typeFilter]);
const paged = visible.slice(0, shown);
const hasMore = visible.length > paged.length;
// 筛选条件变化时回到第 1 页
useEffect(() => { setTaskPage(1); }, [filter, query, timeFilter, typeFilter]);
const taskTotalPages = Math.max(1, Math.ceil(visible.length / TASKS_PER_PAGE));
const taskCurPage = Math.min(taskPage, taskTotalPages);
const paged = visible.slice((taskCurPage - 1) * TASKS_PER_PAGE, taskCurPage * TASKS_PER_PAGE);
return (
<div className="asset-factory">
@@ -366,13 +368,7 @@ export function AssetFactoryPage({ navigate, aiTasks, assets = [] }: { navigate:
</div>
)}
{hasMore && (
<div className="task-load-more">
<button className="btn" type="button" onClick={() => setShown((n) => n + TASKS_PER_LOAD)}>
加载更多 <span className="lm-rest">还有 {visible.length - paged.length} 个</span>
</button>
</div>
)}
<Pager page={taskCurPage} total={visible.length} pageSize={TASKS_PER_PAGE} onChange={setTaskPage} />
</div>
);
}