fix: 修复侧边栏导航 P0 — 所有导航路径统一添加 /app 前缀
Deploy / Staging E2E Tests (push) Failing after 115h14m0s
Deploy / Deploy Staging (push) Failing after 115h15m38s
CI/CD Pipeline / Frontend Lint (push) Failing after 115h16m4s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 115h17m38s
Deploy / Production Browser E2E (push) Failing after 1773h51m7s
Deploy / Build Production Runtime Images (push) Failing after 1773h51m11s
Deploy / Deploy Production (push) Failing after 1774h22m35s

根因:导航配置中所有 path 缺少 /app 前缀,与路由配置不匹配。
侧边栏 navigate('/dashboard') 但路由实际为 /app/dashboard,
导致所有侧边栏按钮点击后 URL 停在 /app/dashboard。

修复内容:
- navigation.ts/tsx: NAV_ITEMS 和 NAV_GROUPS 所有 path 加 /app 前缀
- Sidebar.tsx: isMenuItemActive 中 dashboard 特殊判断更新为 /app/dashboard
- Header.tsx: isActive 函数 + logo 点击 + 用户菜单导航路径修复
- 页面内硬编码路径修复:
  - Dashboard.tsx: /history → /app/history
  - MyTemplates.tsx: /editing-planner → /app/editing-planner
  - DuplicationResults.tsx: /duplication → /app/duplication
  - DuplicationDetail.tsx: /duplication/results → /app/duplication/results
  - UpgradeSubscription.tsx: /subscription → /app/subscription
  - AdminComingSoon.tsx: / → /app/dashboard
  - Login.tsx: 登录成功后 / → /app/dashboard

TypeScript 零错误。
This commit is contained in:
灵应
2026-07-04 17:35:30 +08:00
parent efb9d6c57f
commit 319dd2c839
11 changed files with 69 additions and 64 deletions
+6 -5
View File
@@ -30,13 +30,13 @@ const Header: React.FC = () => {
key: "profile",
icon: <UserOutlined />,
label: "个人设置",
onClick: () => navigate("/profile"),
onClick: () => navigate("/app/profile"),
},
{
key: "subscription",
icon: <SettingOutlined />,
label: "订阅管理",
onClick: () => navigate("/subscription"),
onClick: () => navigate("/app/subscription"),
},
{ type: "divider" },
{
@@ -49,8 +49,9 @@ const Header: React.FC = () => {
/** 判断导航项是否激活 */
const isActive = (path: string) => {
if (path === "/dashboard") {
return location.pathname === "/" || location.pathname === "/dashboard";
// 首页特殊处理:/ 和 /app/dashboard 都算激活
if (path === "/app/dashboard") {
return location.pathname === "/" || location.pathname === "/app" || location.pathname === "/app/dashboard";
}
return location.pathname.startsWith(path);
};
@@ -61,7 +62,7 @@ const Header: React.FC = () => {
<button
className="xx-brand"
type="button"
onClick={() => navigate("/dashboard")}
onClick={() => navigate("/app/dashboard")}
>
<span className="xx-logo">🦐</span>
<span className="xx-brand-text">小虾自动剪辑</span>
+3 -2
View File
@@ -17,8 +17,9 @@ import "./Sidebar.css";
/** 判断菜单项是否激活 */
const isMenuItemActive = (pathname: string, path: string): boolean => {
if (path === "/dashboard") {
return pathname === "/" || pathname === "/dashboard";
// 首页特殊处理:/ 和 /app/dashboard 都算激活
if (path === "/app/dashboard") {
return pathname === "/" || pathname === "/app" || pathname === "/app/dashboard";
}
return pathname.startsWith(path);
};
+28 -25
View File
@@ -33,72 +33,75 @@ export interface NavGroup {
items: NavItem[];
}
/** 全量导航项(Header 扁平列表使用) */
/**
* 全量导航项(Header 扁平列表使用)
* 所有路径统一使用 /app 前缀,与路由配置保持一致
*/
export const NAV_ITEMS: NavItem[] = [
{
key: "dashboard",
label: "概览",
path: "/dashboard",
path: "/app/dashboard",
icon: React.createElement(DashboardOutlined),
},
{
key: "assets",
label: "素材库",
path: "/assets",
path: "/app/assets",
icon: React.createElement(FileOutlined),
},
{
key: "titles",
label: "标题库",
path: "/titles",
path: "/app/titles",
icon: React.createElement(FileTextOutlined),
},
{
key: "voices",
label: "配音库",
path: "/voices",
path: "/app/voices",
icon: React.createElement(AudioOutlined),
},
{
key: "templates",
label: "模板库",
path: "/templates",
path: "/app/templates",
icon: React.createElement(AppstoreOutlined),
},
{
key: "editing-planner",
label: "剪辑编辑器",
path: "/editing-planner",
path: "/app/editing-planner",
icon: React.createElement(EditOutlined),
},
{
key: "my-templates",
label: "我的模板",
path: "/my-templates",
path: "/app/my-templates",
icon: React.createElement(FolderOutlined),
},
{
key: "generate",
label: "一键生成",
path: "/generate",
path: "/app/generate",
icon: React.createElement(VideoCameraOutlined),
},
{
key: "history",
label: "任务历史",
path: "/history",
path: "/app/history",
icon: React.createElement(HistoryOutlined),
},
{
key: "products",
label: "成品库",
path: "/products",
path: "/app/products",
icon: React.createElement(TrophyOutlined),
},
{
key: "duplication",
label: "查重",
path: "/duplication",
path: "/app/duplication",
icon: React.createElement(ScanOutlined),
},
];
@@ -111,19 +114,19 @@ export const NAV_GROUPS: NavGroup[] = [
{
key: "dashboard",
label: "概览",
path: "/dashboard",
path: "/app/dashboard",
icon: React.createElement(DashboardOutlined),
},
{
key: "generate",
label: "一键生成",
path: "/generate",
path: "/app/generate",
icon: React.createElement(VideoCameraOutlined),
},
{
key: "editing-planner",
label: "剪辑编辑器",
path: "/editing-planner",
path: "/app/editing-planner",
icon: React.createElement(EditOutlined),
},
],
@@ -134,37 +137,37 @@ export const NAV_GROUPS: NavGroup[] = [
{
key: "assets",
label: "素材库",
path: "/assets",
path: "/app/assets",
icon: React.createElement(FileOutlined),
},
{
key: "voices",
label: "配音库",
path: "/voices",
path: "/app/voices",
icon: React.createElement(AudioOutlined),
},
{
key: "titles",
label: "标题库",
path: "/titles",
path: "/app/titles",
icon: React.createElement(FileTextOutlined),
},
{
key: "products",
label: "成品库",
path: "/products",
path: "/app/products",
icon: React.createElement(TrophyOutlined),
},
{
key: "templates",
label: "模板库",
path: "/templates",
path: "/app/templates",
icon: React.createElement(AppstoreOutlined),
},
{
key: "my-templates",
label: "我的模板",
path: "/my-templates",
path: "/app/my-templates",
icon: React.createElement(FolderOutlined),
},
],
@@ -175,25 +178,25 @@ export const NAV_GROUPS: NavGroup[] = [
{
key: "history",
label: "任务历史",
path: "/history",
path: "/app/history",
icon: React.createElement(HistoryOutlined),
},
{
key: "duplication",
label: "查重",
path: "/duplication",
path: "/app/duplication",
icon: React.createElement(ScanOutlined),
},
{
key: "admin",
label: "控制台",
path: "/admin",
path: "/app/admin",
icon: React.createElement(ControlOutlined),
},
{
key: "subscription",
label: "订阅管理",
path: "/subscription",
path: "/app/subscription",
icon: React.createElement(CrownOutlined),
},
],
+23 -23
View File
@@ -40,63 +40,63 @@ export const NAV_ITEMS: NavItem[] = [
{
key: "dashboard",
label: "概览",
path: "/dashboard",
path: "/app/dashboard",
icon: <DashboardOutlined />,
},
{ key: "assets", label: "素材库", path: "/assets", icon: <FileOutlined /> },
{ key: "assets", label: "素材库", path: "/app/assets", icon: <FileOutlined /> },
{
key: "titles",
label: "标题库",
path: "/titles",
path: "/app/titles",
icon: <FileTextOutlined />,
},
{ key: "voices", label: "配音库", path: "/voices", icon: <AudioOutlined /> },
{ key: "voices", label: "配音库", path: "/app/voices", icon: <AudioOutlined /> },
{
key: "voice-clone",
label: "我的音色",
path: "/voice-clone",
path: "/app/voice-clone",
icon: <AudioOutlined />,
},
{
key: "templates",
label: "模板库",
path: "/templates",
path: "/app/templates",
icon: <AppstoreOutlined />,
},
{
key: "editing-planner",
label: "剪辑编辑器",
path: "/editing-planner",
path: "/app/editing-planner",
icon: <EditOutlined />,
},
{
key: "my-templates",
label: "我的模板",
path: "/my-templates",
path: "/app/my-templates",
icon: <FolderOutlined />,
},
{
key: "generate",
label: "一键生成",
path: "/generate",
path: "/app/generate",
icon: <VideoCameraOutlined />,
},
{
key: "history",
label: "任务历史",
path: "/history",
path: "/app/history",
icon: <HistoryOutlined />,
},
{
key: "products",
label: "成品库",
path: "/products",
path: "/app/products",
icon: <TrophyOutlined />,
},
{
key: "duplication",
label: "查重",
path: "/duplication",
path: "/app/duplication",
icon: <ScanOutlined />,
},
];
@@ -111,13 +111,13 @@ export const NAV_GROUPS: NavGroup[] = [
{
key: "dashboard",
label: "首页",
path: "/dashboard",
path: "/app/dashboard",
icon: <DashboardOutlined />,
},
{
key: "generate",
label: "一键生成",
path: "/generate",
path: "/app/generate",
icon: <VideoCameraOutlined />,
},
],
@@ -128,37 +128,37 @@ export const NAV_GROUPS: NavGroup[] = [
{
key: "assets",
label: "素材库",
path: "/assets",
path: "/app/assets",
icon: <FileOutlined />,
},
{
key: "voices",
label: "配音库",
path: "/voices",
path: "/app/voices",
icon: <AudioOutlined />,
},
{
key: "voice-clone",
label: "我的音色",
path: "/voice-clone",
path: "/app/voice-clone",
icon: <AudioOutlined />,
},
{
key: "titles",
label: "标题库",
path: "/titles",
path: "/app/titles",
icon: <FileTextOutlined />,
},
{
key: "products",
label: "成片库",
path: "/products",
path: "/app/products",
icon: <TrophyOutlined />,
},
{
key: "templates",
label: "模板库",
path: "/templates",
path: "/app/templates",
icon: <AppstoreOutlined />,
},
],
@@ -169,19 +169,19 @@ export const NAV_GROUPS: NavGroup[] = [
{
key: "history",
label: "任务历史",
path: "/history",
path: "/app/history",
icon: <HistoryOutlined />,
},
{
key: "admin",
label: "控制台",
path: "/admin",
path: "/app/admin",
icon: <ControlOutlined />,
},
{
key: "subscription",
label: "订阅管理",
path: "/subscription",
path: "/app/subscription",
icon: <CrownOutlined />,
},
],
+1 -1
View File
@@ -17,7 +17,7 @@ const AdminComingSoon: React.FC = () => {
extra={[
<Button
type="primary"
onClick={() => navigate("/")}
onClick={() => navigate("/app/dashboard")}
className="xx-primary-btn"
>
返回首页
+1 -1
View File
@@ -25,7 +25,7 @@ const Login: React.FC = () => {
password: values.password,
});
message.success("登录成功!");
navigate("/");
navigate("/app/dashboard");
} catch (error: unknown) {
if (!(error as { __msgShown?: boolean })?.__msgShown)
message.error("登录失败,请检查邮箱和密码");
+2 -2
View File
@@ -293,7 +293,7 @@ const Dashboard: React.FC = () => {
<div className="xx-dashboard-section">
<div className="xx-dashboard-section-header">
<h3>最近任务</h3>
<button onClick={() => navigate("/history")}>查看全部</button>
<button onClick={() => navigate("/app/history")}>查看全部</button>
</div>
<div className="xx-task-list">
{recentTasks.map((task) => (
@@ -331,7 +331,7 @@ const Dashboard: React.FC = () => {
<Button
buttonType="ghost"
buttonSize="sm"
onClick={() => navigate("/history")}
onClick={() => navigate("/app/history")}
>
查看
</Button>
@@ -170,7 +170,7 @@ const DuplicationDetail: React.FC = () => {
<Button
buttonType="primary"
buttonSize="md"
onClick={() => navigate("/duplication/results")}
onClick={() => navigate("/app/duplication/results")}
style={{ marginTop: 16 }}
>
返回列表
@@ -158,7 +158,7 @@ const DuplicationResults: React.FC = () => {
<Button
buttonType="primary"
buttonSize="md"
onClick={() => navigate("/duplication")}
onClick={() => navigate("/app/duplication")}
>
📤 上传查重
</Button>
@@ -141,7 +141,7 @@ const MyTemplates: React.FC = () => {
<Button
type="primary"
icon={<PlusOutlined />}
onClick={() => navigate("/editing-planner")}
onClick={() => navigate("/app/editing-planner")}
>
新建模板
</Button>
@@ -178,7 +178,7 @@ const MyTemplates: React.FC = () => {
description="还没有模板,点击右上角「新建模板」开始创建"
style={{ padding: 80 }}
>
<Button type="primary" onClick={() => navigate("/editing-planner")}>
<Button type="primary" onClick={() => navigate("/app/editing-planner")}>
新建模板
</Button>
</Empty>
@@ -160,7 +160,7 @@ const UpgradeSubscription: React.FC = () => {
try {
const res = await cancelSubscription();
message.success(res.message);
navigate("/subscription");
navigate("/app/subscription");
} catch (err: unknown) {
if (!(err as { __msgShown?: boolean })?.__msgShown)
message.error("取消失败");