后端生成闸+多项修复;前端全站更新;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:
@@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { Check } from "lucide-react";
|
||||
import { IconKitSvg } from "./IconKitSvg";
|
||||
import { useBodyScrollLock } from "./overlays";
|
||||
import type { Product, Project, Team, User } from "../types";
|
||||
import type { Notice, Page } from "../routes/route-config";
|
||||
|
||||
@@ -28,6 +29,7 @@ const SHELL_COMMANDS: Command[] = [
|
||||
|
||||
function CommandPalette({ open, onClose, navigate }: { open: boolean; onClose: () => void; navigate: Navigate }) {
|
||||
const [query, setQuery] = useState("");
|
||||
useBodyScrollLock(open);
|
||||
useEffect(() => { if (open) setQuery(""); }, [open]);
|
||||
const items = useMemo(() => {
|
||||
const q = query.trim().toLowerCase();
|
||||
@@ -149,6 +151,16 @@ export function Sidebar({ page, navigate, user, team, products, projects }: {
|
||||
return () => document.body.classList.remove("sidebar-collapsed");
|
||||
}, [collapsed]);
|
||||
|
||||
// 移动端导航抽屉:窄屏侧栏默认收起(display:none),靠左上汉堡键拉出为浮层 + 背景遮罩。
|
||||
// 点导航项 / 遮罩 / Esc 关闭。桌面端(>1100px)汉堡键 CSS 隐藏,不影响原有收窄逻辑。
|
||||
const [mobileNavOpen, setMobileNavOpen] = useState(false);
|
||||
useEffect(() => {
|
||||
if (!mobileNavOpen) return;
|
||||
const onKey = (event: KeyboardEvent) => { if (event.key === "Escape") setMobileNavOpen(false); };
|
||||
document.addEventListener("keydown", onKey);
|
||||
return () => document.removeEventListener("keydown", onKey);
|
||||
}, [mobileNavOpen]);
|
||||
|
||||
// 命令面板:Ctrl/Cmd K 开关,点搜索框打开
|
||||
const [paletteOpen, setPaletteOpen] = useState(false);
|
||||
const openCommandPalette = () => setPaletteOpen(true);
|
||||
@@ -165,7 +177,12 @@ export function Sidebar({ page, navigate, user, team, products, projects }: {
|
||||
|
||||
return (
|
||||
<>
|
||||
<aside className="sidebar">
|
||||
{/* 移动端汉堡键(桌面 CSS 隐藏)+ 抽屉遮罩 */}
|
||||
<button className="mobile-nav-btn" type="button" aria-label="打开导航" aria-expanded={mobileNavOpen} onClick={() => setMobileNavOpen(true)}>
|
||||
<span /><span /><span />
|
||||
</button>
|
||||
{mobileNavOpen && <div className="mobile-nav-backdrop" onClick={() => setMobileNavOpen(false)} />}
|
||||
<aside className={`sidebar${mobileNavOpen ? " mobile-open" : ""}`}>
|
||||
<div className="sidebar-head">
|
||||
<a className="brand" href="/dashboard" aria-label="Airshelf 工作台" onClick={(event) => { event.preventDefault(); navigate("dashboard"); }}>
|
||||
<span className="brand-clip"><img className="brand-logo" src="/assets/logo.png" alt="Airshelf" /></span>
|
||||
@@ -196,7 +213,7 @@ export function Sidebar({ page, navigate, user, team, products, projects }: {
|
||||
className={activeNav === item.page ? "active" : ""}
|
||||
title={item.label}
|
||||
aria-label={item.label}
|
||||
onClick={(event) => { event.preventDefault(); navigate(item.page); }}
|
||||
onClick={(event) => { event.preventDefault(); setMobileNavOpen(false); navigate(item.page); }}
|
||||
>
|
||||
<IconKitSvg name={item.icon} />
|
||||
<span>{item.label}</span>
|
||||
|
||||
Reference in New Issue
Block a user