后端生成闸+多项修复;前端全站更新;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
+13 -4
View File
@@ -30,8 +30,9 @@ export function AuthScreen({
onAuthed: (payload: { token: string; user: User; team: Team }) => void;
}) {
const [mode, setMode] = useState<AuthMode>(initialMode);
const [username, setUsername] = useState("li@shop.com");
const [password, setPassword] = useState("demo-1234");
// 不预填设计稿假账号:真实登录页字段必须从空开始
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [teamName, setTeamName] = useState("");
const [email, setEmail] = useState("");
const [registerPassword, setRegisterPassword] = useState("");
@@ -66,6 +67,9 @@ export function AuthScreen({
setBusy(true);
setError("");
try {
if (mode === "login") {
if (!username.trim() || !password) throw new Error("请输入邮箱和密码");
}
if (mode === "register") {
if (registerPassword.length < 8) throw new Error("密码至少 8 位");
if (registerPassword !== registerPassword2) throw new Error("两次密码不一致");
@@ -82,7 +86,12 @@ export function AuthScreen({
});
onAuthed(payload);
} catch (err) {
setError(err instanceof Error ? err.message : "登录失败");
const raw = err instanceof Error ? err.message : "";
// 后端错误是英文原文(invalid credentials 等),映射成用户可读的中文
const friendly = /invalid credentials|unable to log in|non_field_errors/i.test(raw)
? "邮箱或密码不正确"
: raw || (mode === "login" ? "登录失败,请稍后重试" : "注册失败,请稍后重试");
setError(friendly);
} finally {
setBusy(false);
}
@@ -141,7 +150,7 @@ export function AuthScreen({
</div>
<div className="row-between">
<label><input type="checkbox" defaultChecked /> 记住我 7 天</label>
<a href="#" onClick={(event) => { event.preventDefault(); showToast("已发送重置邮件", "请到 li@shop.com 收件箱查看 · 链接 30 分钟有效"); }}>忘记密码?</a>
<a href="#" onClick={(event) => { event.preventDefault(); showToast("已发送重置邮件", `请到 ${username.trim() || "登录邮箱"} 收件箱查看 · 链接 30 分钟有效`); }}>忘记密码?</a>
</div>
{error && <div className="form-error">{error}</div>}
<button className="btn-cta" type="submit" disabled={busy}>