后端生成闸+多项修复;前端全站更新;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
+42
View File
@@ -0,0 +1,42 @@
// 通用列表分页器:沿用项目向导 pp-pager / 消费页 bill-pager 的视觉(mono 总数 + 页码窗口 + 每页条数)。
// 纯前端切片分页:父组件持有 page state,自己 slice;本组件只画控件。
// total <= pageSize 时不渲染(单页无需分页器)。
// 页码窗口:超过 7 页折叠成 1 … cur-1 cur cur+1 … last
export function pageWindow(current: number, total: number): Array<number | "ellipsis"> {
if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1);
const items: Array<number | "ellipsis"> = [1];
const start = Math.max(2, current - 1);
const end = Math.min(total - 1, current + 1);
if (start > 2) items.push("ellipsis");
for (let p = start; p <= end; p++) items.push(p);
if (end < total - 1) items.push("ellipsis");
items.push(total);
return items;
}
export function Pager({ page, total, pageSize, onChange }: {
page: number;
total: number;
pageSize: number;
onChange: (page: number) => void;
}) {
const totalPages = Math.max(1, Math.ceil(total / pageSize));
const cur = Math.min(Math.max(1, page), totalPages);
if (total <= pageSize) return null;
return (
<div className="list-pager">
<span className="total">// 共 {total} 条 · 第 {cur} / {totalPages} 页</span>
<div className="pages">
<button type="button" disabled={cur === 1} onClick={() => onChange(cur - 1)} aria-label="上一页">‹</button>
{pageWindow(cur, totalPages).map((p, i) => (
p === "ellipsis"
? <span key={`e${i}`} className="ellipsis">…</span>
: <button type="button" key={p} className={p === cur ? "active" : ""} onClick={() => onChange(p)}>{p}</button>
))}
<button type="button" disabled={cur === totalPages} onClick={() => onChange(cur + 1)} aria-label="下一页">›</button>
</div>
<span className="page-size">每页 {pageSize} 条</span>
</div>
);
}