This commit is contained in:
fengxiangdebaozi committed 2026-06-16 10:06:14 +08:00
commit e1da39253a
10 files changed
+161 -101

No files matched your search

@@ -54,7 +54,7 @@ export function PageSidebarDark({ collapsed, onToggleCollapsed }: PageSidebarDar
}; };
const hasActiveChild = (item: MenuItem): boolean => { const hasActiveChild = (item: MenuItem): boolean => {
if (item.path && pathname === item.path) { if (item.path && (pathname === item.path || pathname.startsWith(item.path + "/"))) {
return true; return true;
} }
@@ -153,7 +153,7 @@ export function PageSidebarDark({ collapsed, onToggleCollapsed }: PageSidebarDar
inWujieEnv inWujieEnv
? item.id === activeTopId ? item.id === activeTopId
: item.path : item.path
? pathname === item.path ? pathname === item.path || pathname.startsWith(item.path + "/")
: hasActiveChild(item); : hasActiveChild(item);
const handleSidebarItemClick = (item: MenuItem) => { const handleSidebarItemClick = (item: MenuItem) => {
if (inWujieEnv) { if (inWujieEnv) {
+5 -3
View File
@@ -42,7 +42,7 @@ type PageSidebarProps = {
type SettingsSection = "account" | "appearance" | "memory" | "tools" | "about"; type SettingsSection = "account" | "appearance" | "memory" | "tools" | "about";
const hasActiveChild = (item: MenuItem, pathname: string): boolean => { const hasActiveChild = (item: MenuItem, pathname: string): boolean => {
if (item.path && pathname === item.path) { if (item.path && (pathname === item.path || pathname.startsWith(item.path + "/"))) {
return true; return true;
} }
return item.children?.some((child) => hasActiveChild(child, pathname)) ?? false; return item.children?.some((child) => hasActiveChild(child, pathname)) ?? false;
@@ -116,7 +116,9 @@ function SecondaryNavSidebar() {
const secondaryItems = activeTopItem?.children ?? []; const secondaryItems = activeTopItem?.children ?? [];
const isItemActive = (item: MenuItem) => const isItemActive = (item: MenuItem) =>
item.path ? pathname === item.path : hasActiveChild(item, pathname); item.path
? pathname === item.path || pathname.startsWith(item.path + "/")
: hasActiveChild(item, pathname);
const handleItemClick = (item: MenuItem) => { const handleItemClick = (item: MenuItem) => {
const path = item.path ?? findFirstRoutePath(item.children); const path = item.path ?? findFirstRoutePath(item.children);
@@ -210,7 +212,7 @@ function SecondaryNavSidebar() {
{thirdItems.map((child) => { {thirdItems.map((child) => {
const ChildIcon = child.icon; const ChildIcon = child.icon;
const childActive = child.path const childActive = child.path
? pathname === child.path ? pathname === child.path || pathname.startsWith(child.path + "/")
: hasActiveChild(child, pathname); : hasActiveChild(child, pathname);
return ( return (
<button <button
@@ -1,7 +1,8 @@
import type { Message } from "@langchain/langgraph-sdk"; import type { Message } from "@langchain/langgraph-sdk";
import type { BaseStream } from "@langchain/langgraph-sdk/react"; import type { BaseStream } from "@langchain/langgraph-sdk/react";
import { CheckIcon, SendIcon, XIcon } from "lucide-react"; import { CheckIcon, SendIcon, XIcon } from "lucide-react";
import { useCallback, useContext, useEffect, useMemo, useState } from "react"; import { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import { useStickToBottomContext } from "use-stick-to-bottom";
import { import {
Conversation, Conversation,
@@ -52,6 +53,38 @@ import { SubtaskCard } from "./subtask-card";
export const MESSAGE_LIST_DEFAULT_PADDING_BOTTOM = 160; export const MESSAGE_LIST_DEFAULT_PADDING_BOTTOM = 160;
export const MESSAGE_LIST_FOLLOWUPS_EXTRA_PADDING_BOTTOM = 80; export const MESSAGE_LIST_FOLLOWUPS_EXTRA_PADDING_BOTTOM = 80;
/** 用户发送新问题时强制滚到底部(即使用户此前上滑看过历史)。 */
function ScrollToBottomOnUserMessage({
threadId,
messages,
}: {
threadId: string;
messages: Message[];
}) {
const { scrollToBottom } = useStickToBottomContext();
const prevHumanCountRef = useRef<number | null>(null);
useEffect(() => {
prevHumanCountRef.current = null;
}, [threadId]);
useEffect(() => {
const humanCount = messages.reduce(
(count, message) => count + (message.type === "human" ? 1 : 0),
0,
);
const prev = prevHumanCountRef.current;
prevHumanCountRef.current = humanCount;
if (prev !== null && humanCount > prev) {
requestAnimationFrame(() => {
requestAnimationFrame(() => scrollToBottom());
});
}
}, [messages, scrollToBottom]);
return null;
}
export function MessageList({ export function MessageList({
className, className,
contentClassName, contentClassName,
@@ -266,6 +299,7 @@ export function MessageList({
<Conversation <Conversation
className={cn("flex size-full flex-col justify-center", className)} className={cn("flex size-full flex-col justify-center", className)}
> >
<ScrollToBottomOnUserMessage threadId={threadId} messages={messages} />
<ConversationContent <ConversationContent
className={cn( className={cn(
"mx-auto w-full max-w-(--container-width-lg) gap-8 pt-12", "mx-auto w-full max-w-(--container-width-lg) gap-8 pt-12",
@@ -165,7 +165,7 @@ export function WorkspaceNavMenu() {
Checkpoint 迁移 Checkpoint 迁移
</DropdownMenuItem> </DropdownMenuItem>
)} )}
{isAdmin && ( {isAdmin ? (
<DropdownMenuItem <DropdownMenuItem
onClick={() => onClick={() =>
navigate("/page/strategy/admin/user-leaderboard") navigate("/page/strategy/admin/user-leaderboard")
@@ -174,6 +174,15 @@ export function WorkspaceNavMenu() {
<TrophyIcon /> <TrophyIcon />
用户排行榜 用户排行榜
</DropdownMenuItem> </DropdownMenuItem>
) : (
<DropdownMenuItem
onClick={() =>
navigate("/page/strategy/user-leaderboard")
}
>
<TrophyIcon />
用户排行榜
</DropdownMenuItem>
)} )}
{isAdmin && ( {isAdmin && (
<DropdownMenuItem <DropdownMenuItem
@@ -50,7 +50,7 @@ export function WorkspaceSidebar({
variant="sidebar" variant="sidebar"
collapsible="none" collapsible="none"
className={cn( className={cn(
"h-full w-(--sidebar-width)", "h-full w-(--sidebar-width) border-r border-border",
useWhiteSidebar && useWhiteSidebar &&
"[&_[data-slot=sidebar-inner]]:bg-white [&_[data-slot=sidebar-container]]:bg-white", "[&_[data-slot=sidebar-inner]]:bg-white [&_[data-slot=sidebar-container]]:bg-white",
className, className,
@@ -43,6 +43,8 @@ export type MenuItem = {
label: string; label: string;
icon: ElementType; icon: ElementType;
path?: string; path?: string;
/** 非 admin 用户使用的路由(菜单对普通用户可见时生效,与简洁模式公开排行榜一致) */
userPath?: string;
adminOnly?: boolean; adminOnly?: boolean;
children?: MenuItem[]; children?: MenuItem[];
}; };
@@ -81,18 +83,18 @@ export const sidebarMenuItems: MenuItem[] = [
label: "XK中任务", label: "XK中任务",
icon: ClipboardList, icon: ClipboardList,
children: [ children: [
{ // {
id: "xk-task-jc", // id: "xk-task-jc",
label: "任务JC", // label: "任务JC",
icon: ListTodo, // icon: ListTodo,
path: "/page/strategy/task-management/xk-task-jc", // path: "/page/strategy/task-management/xk-task-jc",
}, // },
{ // {
id: "xk-task-dispatch", // id: "xk-task-dispatch",
label: "任务调度", // label: "任务调度",
icon: ListTodo, // icon: ListTodo,
path: "/page/strategy/task-management/xk-task-dispatch", // path: "/page/strategy/task-management/xk-task-dispatch",
}, // },
], ],
}, },
{ {
@@ -125,24 +127,24 @@ export const sidebarMenuItems: MenuItem[] = [
label: "PG中任务", label: "PG中任务",
icon: Gauge, icon: Gauge,
children: [ children: [
{ // {
id: "pg-task-pg", // id: "pg-task-pg",
label: "任务PG", // label: "任务PG",
icon: ListTodo, // icon: ListTodo,
path: "/page/strategy/task-management/effect-task-pg", // path: "/page/strategy/task-management/effect-task-pg",
}, // },
{ // {
id: "pg-task-xdpg", // id: "pg-task-xdpg",
label: "XDPG", // label: "XDPG",
icon: ListTodo, // icon: ListTodo,
path: "/page/strategy/task-management/effect-action-pg", // path: "/page/strategy/task-management/effect-action-pg",
}, // },
{ // {
id: "pg-task-info-pg", // id: "pg-task-info-pg",
label: "信息PG", // label: "信息PG",
icon: ListTodo, // icon: ListTodo,
path: "/page/strategy/task-management/effect-info-pg", // path: "/page/strategy/task-management/effect-info-pg",
}, // },
], ],
}, },
{ {
@@ -150,24 +152,24 @@ export const sidebarMenuItems: MenuItem[] = [
label: "TY中任务", label: "TY中任务",
icon: Radar, icon: Radar,
children: [ children: [
{ // {
id: "ty-task-xdty", // id: "ty-task-xdty",
label: "XDTY任务", // label: "XDTY任务",
icon: ListTodo, // icon: ListTodo,
path: "/page/strategy/task-management/mnty-task-mechanism", // path: "/page/strategy/task-management/mnty-task-mechanism",
}, // },
{ // {
id: "ty-task-plan", // id: "ty-task-plan",
label: "方案TY任务", // label: "方案TY任务",
icon: ListTodo, // icon: ListTodo,
path: "/page/strategy/task-management/mnty-task-plan", // path: "/page/strategy/task-management/mnty-task-plan",
}, // },
{ // {
id: "ty-task-xxty", // id: "ty-task-xxty",
label: "XXTY任务", // label: "XXTY任务",
icon: ListTodo, // icon: ListTodo,
path: "/page/strategy/task-management/mnty-task-zsty", // path: "/page/strategy/task-management/mnty-task-zsty",
}, // },
], ],
}, },
], ],
@@ -197,6 +199,13 @@ export const sidebarMenuItems: MenuItem[] = [
label: "综合管理", label: "综合管理",
icon: Settings, icon: Settings,
children: [ children: [
{
id: "mgmt-user-leaderboard",
label: "用户排行榜",
icon: Trophy,
path: "/page/strategy/admin/user-leaderboard",
userPath: "/page/strategy/user-leaderboard",
},
{ id: "mgmt-agents", label: "智能体管理", icon: Bot, path: "/page/strategy/agents" }, { id: "mgmt-agents", label: "智能体管理", icon: Bot, path: "/page/strategy/agents" },
{ {
id: "mgmt-business-chain-mapping", id: "mgmt-business-chain-mapping",
@@ -232,13 +241,6 @@ export const sidebarMenuItems: MenuItem[] = [
path: "/page/strategy/admin/users", path: "/page/strategy/admin/users",
adminOnly: true, adminOnly: true,
}, },
{
id: "mgmt-user-leaderboard",
label: "用户排行榜",
icon: Trophy,
path: "/page/strategy/admin/user-leaderboard",
adminOnly: true,
},
{ {
id: "mgmt-admin-scheduled-tasks", id: "mgmt-admin-scheduled-tasks",
label: "定时任务管理", label: "定时任务管理",
@@ -260,12 +262,12 @@ export const sidebarMenuItems: MenuItem[] = [
label: "资源管理", label: "资源管理",
icon: Database, icon: Database,
children: [ children: [
{ // {
id: "resource-network-xwt", // id: "resource-network-xwt",
label: "网络xwt资源管理", // label: "网络xwt资源管理",
icon: Network, // icon: Network,
path: "/page/strategy/resource-management/resource-network-actor", // path: "/page/strategy/resource-management/resource-network-actor",
}, // },
{ {
id: "resource-knowledge-native", id: "resource-knowledge-native",
label: "问答梳理", label: "问答梳理",
@@ -278,12 +280,12 @@ export const sidebarMenuItems: MenuItem[] = [
icon: Library, icon: Library,
path: "/page/strategy/resource-management/resource-knowledge-base", path: "/page/strategy/resource-management/resource-knowledge-base",
}, },
{ // {
id: "resource-evaluation-index", // id: "resource-evaluation-index",
label: "作战资源管理", // label: "作战资源管理",
icon: FileBox, // icon: FileBox,
path: "/page/strategy/resource-management/resource-evaluation-index", // path: "/page/strategy/resource-management/resource-evaluation-index",
}, // },
], ],
}, },
]; ];
@@ -298,9 +300,9 @@ export const defaultExpandedIds: ReadonlySet<string> = new Set([
"comprehensive-management", "comprehensive-management",
]); ]);
/** 该菜单项自身或任意后代的 path 是否等于当前路由 */ /** 该菜单项自身或任意后代的 path 是否匹配当前路由(支持子路径,如 /knowledge/:id) */
export function menuItemContainsPath(item: MenuItem, pathname: string): boolean { export function menuItemContainsPath(item: MenuItem, pathname: string): boolean {
if (item.path && item.path === pathname) { if (item.path && (pathname === item.path || pathname.startsWith(item.path + "/"))) {
return true; return true;
} }
return item.children?.some((child) => menuItemContainsPath(child, pathname)) ?? false; return item.children?.some((child) => menuItemContainsPath(child, pathname)) ?? false;
@@ -308,7 +310,8 @@ export function menuItemContainsPath(item: MenuItem, pathname: string): boolean
/** /**
* 在「一级 → 二级 → 三级」菜单中,取当前路由所在的「激活二级项」的三级子项。 * 在「一级 → 二级 → 三级」菜单中,取当前路由所在的「激活二级项」的三级子项。
* 浅色侧边栏据此在二级右侧展开三级列;无三级则返回空数组(侧边栏保持窄栏)。 * 浅色侧边栏据此在二级右侧展开三级列;深色顶栏据此渲染三级横条。
* 全量模式:三级仅一项时不返回(无选择必要,侧边栏保持窄栏 / 不渲染横条)。
*/ */
export function getActiveThirdLevelItems( export function getActiveThirdLevelItems(
items: MenuItem[], items: MenuItem[],
@@ -320,16 +323,23 @@ export function getActiveThirdLevelItems(
const activeSecond = secondary.find( const activeSecond = secondary.find(
(item) => (item.children?.length ?? 0) > 0 && menuItemContainsPath(item, pathname), (item) => (item.children?.length ?? 0) > 0 && menuItemContainsPath(item, pathname),
); );
return activeSecond?.children ?? []; const third = activeSecond?.children ?? [];
return third.length <= 1 ? [] : third;
} }
/** 按 admin 角色过滤菜单:非 admin 不展示 ``adminOnly: true`` 的项及其子项 */ /** 按 admin 角色过滤菜单:非 admin 不展示 ``adminOnly: true`` 的项;``userPath`` 替换 ``path``。 */
export function filterMenuItemsByRole(items: MenuItem[], isAdmin: boolean): MenuItem[] { export function filterMenuItemsByRole(items: MenuItem[], isAdmin: boolean): MenuItem[] {
return items return items
.filter((item) => !item.adminOnly || isAdmin) .filter((item) => !item.adminOnly || isAdmin)
.map((item) => .map((item) => {
item.children const children = item.children
? { ...item, children: filterMenuItemsByRole(item.children, isAdmin) } ? filterMenuItemsByRole(item.children, isAdmin)
: item, : undefined;
); const base = children ? { ...item, children } : item;
if (!isAdmin && base.userPath) {
const { userPath: _userPath, ...rest } = base;
return { ...rest, path: base.userPath };
}
return base;
});
} }
@@ -650,7 +650,7 @@ export default function LightAppManagementPage() {
onClick={() => setDialogOpen(false)} onClick={() => setDialogOpen(false)}
/> />
<div className="lam-dialog relative z-[110] m-4 flex max-h-[90vh] w-full max-w-[580px] flex-col rounded-[5px] border border-[#E8E8E8] bg-white p-6 shadow-[0_8px_32px_rgba(34,34,34,0.16)]"> <div className="lam-dialog relative z-[110] m-4 flex max-h-[90vh] w-full max-w-[900px] flex-col rounded-[5px] border border-[#E8E8E8] bg-white p-6 shadow-[0_8px_32px_rgba(34,34,34,0.16)]">
<div className="lam-dialog-header flex flex-shrink-0 items-center justify-between border-b border-[#E8E8E8] pb-4"> <div className="lam-dialog-header flex flex-shrink-0 items-center justify-between border-b border-[#E8E8E8] pb-4">
<div className="flex items-center space-x-2.5"> <div className="flex items-center space-x-2.5">
<span className="lam-dialog-icon rounded-[5px] bg-rose-50 p-1.5 text-[#A8071A]"> <span className="lam-dialog-icon rounded-[5px] bg-rose-50 p-1.5 text-[#A8071A]">
@@ -25,6 +25,7 @@ import ChatPage from "./ChatPage";
import ChatsPage from "./ChatsPage"; import ChatsPage from "./ChatsPage";
import AdminUserLeaderboardPage from "./AdminUserLeaderboardPage"; import AdminUserLeaderboardPage from "./AdminUserLeaderboardPage";
import AdminUserLeaderboardSettingsPage from "./AdminUserLeaderboardSettingsPage"; import AdminUserLeaderboardSettingsPage from "./AdminUserLeaderboardSettingsPage";
import PublicLeaderboardPage from "./PublicLeaderboardPage";
import LightAppIframeView from "./LightAppIframeView"; import LightAppIframeView from "./LightAppIframeView";
import LightAppListPage from "./LightAppListPage"; import LightAppListPage from "./LightAppListPage";
import LightAppManagementPage from "./LightAppManagementPage"; import LightAppManagementPage from "./LightAppManagementPage";
@@ -253,6 +254,7 @@ export default function StrategyRoutes() {
) )
} }
/> />
<Route path="user-leaderboard" element={<PublicLeaderboardPage />} />
<Route <Route
path="admin/user-leaderboard" path="admin/user-leaderboard"
element={ element={
+6 -4
View File
@@ -70,6 +70,7 @@ export function WorkspaceLayout({
workspaceSidebarHidden = false, workspaceSidebarHidden = false,
headerHidden = false, headerHidden = false,
compactWorkspaceSidebar = false, compactWorkspaceSidebar = false,
defaultHistorySidebarOpen,
wrapperOverflowHidden = false, wrapperOverflowHidden = false,
insetOverflowHidden = false, insetOverflowHidden = false,
pageSidebarDark = false, pageSidebarDark = false,
@@ -80,6 +81,8 @@ export function WorkspaceLayout({
workspaceSidebarHidden?: boolean; workspaceSidebarHidden?: boolean;
headerHidden?: boolean; headerHidden?: boolean;
compactWorkspaceSidebar?: boolean; compactWorkspaceSidebar?: boolean;
/** 全量模式下通用问答等页:聊天记录侧栏默认展开;未指定时紧凑模式仍默认收起。 */
defaultHistorySidebarOpen?: boolean;
wrapperOverflowHidden?: boolean; wrapperOverflowHidden?: boolean;
insetOverflowHidden?: boolean; insetOverflowHidden?: boolean;
pageSidebarDark?: boolean; pageSidebarDark?: boolean;
@@ -110,8 +113,7 @@ export function WorkspaceLayout({
} }
key={String(compactWorkspaceSidebar)} key={String(compactWorkspaceSidebar)}
data-page-sidebar-collapsed={pageSidebarCollapsed} data-page-sidebar-collapsed={pageSidebarCollapsed}
// 紧凑模式下历史侧栏默认收起(聊天区更宽),由聊天页右上角图标钮展开 defaultOpen={defaultHistorySidebarOpen ?? !compactWorkspaceSidebar}
defaultOpen={!compactWorkspaceSidebar}
> >
{!workspaceSidebarHidden && ( {!workspaceSidebarHidden && (
<WorkspaceSidebar compactChrome={compactWorkspaceSidebar} /> <WorkspaceSidebar compactChrome={compactWorkspaceSidebar} />
@@ -153,7 +155,7 @@ function NewChatEntryRoute({
} }
return ( return (
<WorkspaceLayout {...layoutProps}> <WorkspaceLayout {...layoutProps} defaultHistorySidebarOpen>
<ChatRuntime> <ChatRuntime>
<ChatPage /> <ChatPage />
</ChatRuntime> </ChatRuntime>
@@ -201,7 +203,7 @@ export default function WorkspaceRoutes({
<Route <Route
path="chats/:thread_id" path="chats/:thread_id"
element={ element={
<WorkspaceLayout {...layoutProps}> <WorkspaceLayout {...layoutProps} defaultHistorySidebarOpen>
<ChatRuntime> <ChatRuntime>
<ChatPage /> <ChatPage />
</ChatRuntime> </ChatRuntime>
+12 -11
View File
@@ -8,7 +8,10 @@ import { NotificationDialog } from "@/components/workspace/notification-dialog";
import { getStoredAuth } from "@/core/auth"; import { getStoredAuth } from "@/core/auth";
import { isWujieEnv } from "@/core/embed/wujie"; import { isWujieEnv } from "@/core/embed/wujie";
import { useUnreadCount } from "@/core/notifications"; import { useUnreadCount } from "@/core/notifications";
import type { MenuItem } from "@/core/page-layout/sidebar-menu"; import {
getActiveThirdLevelItems,
type MenuItem,
} from "@/core/page-layout/sidebar-menu";
import { useSidebarMenuItems } from "@/core/page-layout/use-sidebar-menu"; import { useSidebarMenuItems } from "@/core/page-layout/use-sidebar-menu";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
@@ -145,7 +148,7 @@ const Header = ({ collapsed }: HeaderProps) => {
const showLightTopNav = !isDark && !isWujieEnv(); const showLightTopNav = !isDark && !isWujieEnv();
const hasActiveChild = (item: MenuItem): boolean => { const hasActiveChild = (item: MenuItem): boolean => {
if (item.path && pathname === item.path) { if (item.path && (pathname === item.path || pathname.startsWith(item.path + "/"))) {
return true; return true;
} }
@@ -170,9 +173,7 @@ const Header = ({ collapsed }: HeaderProps) => {
return null; return null;
}; };
const activeTopItem = visibleMenuItems.find(hasActiveChild); const thirdSubNavItems = getActiveThirdLevelItems(visibleMenuItems, pathname);
const activeSecondItem = activeTopItem?.children?.find(hasActiveChild);
const thirdSubNavItems = activeSecondItem?.children ?? [];
const leftMenuItems = visibleMenuItems.filter((i) => LEFT_MENU_IDS.includes(i.id)); const leftMenuItems = visibleMenuItems.filter((i) => LEFT_MENU_IDS.includes(i.id));
const rightMenuItems = visibleMenuItems.filter((i) => RIGHT_MENU_IDS.includes(i.id)); const rightMenuItems = visibleMenuItems.filter((i) => RIGHT_MENU_IDS.includes(i.id));
@@ -185,7 +186,7 @@ const Header = ({ collapsed }: HeaderProps) => {
}; };
const renderTopItem = (item: MenuItem) => { const renderTopItem = (item: MenuItem) => {
const isSelected = item.path ? pathname === item.path : hasActiveChild(item); const isSelected = item.path ? (pathname === item.path || pathname.startsWith(item.path + "/")) : hasActiveChild(item);
return ( return (
<button <button
key={item.id} key={item.id}
@@ -199,7 +200,7 @@ const Header = ({ collapsed }: HeaderProps) => {
}; };
const renderLightTopItem = (item: MenuItem) => { const renderLightTopItem = (item: MenuItem) => {
const isSelected = item.path ? pathname === item.path : hasActiveChild(item); const isSelected = item.path ? (pathname === item.path || pathname.startsWith(item.path + "/")) : hasActiveChild(item);
return ( return (
<button <button
key={item.id} key={item.id}
@@ -310,7 +311,7 @@ const Header = ({ collapsed }: HeaderProps) => {
</div> </div>
{/* 中:CM助手(落在背景图发光基座上,纯文字无图标) */} {/* 中:CM助手(落在背景图发光基座上,纯文字无图标) */}
<div className="header-center-title">CM助手</div> <div className="header-center-title">CM业务中心</div>
{/* 右分区(flex-1):菜单靠左贴近中间基座,操作区靠最右 */} {/* 右分区(flex-1):菜单靠左贴近中间基座,操作区靠最右 */}
<div className="flex h-full min-w-0 flex-1 items-center justify-between"> <div className="flex h-full min-w-0 flex-1 items-center justify-between">
@@ -336,7 +337,7 @@ const Header = ({ collapsed }: HeaderProps) => {
<FileText className="h-4 w-4 text-white" /> <FileText className="h-4 w-4 text-white" />
</div> </div>
<span className="whitespace-nowrap text-base font-semibold text-white"> <span className="whitespace-nowrap text-base font-semibold text-white">
CM助手 CM业务中心
</span> </span>
</div> </div>
<nav className="light-topnav" aria-label="一级菜单"> <nav className="light-topnav" aria-label="一级菜单">
@@ -363,7 +364,7 @@ const Header = ({ collapsed }: HeaderProps) => {
</div> </div>
{!collapsed && ( {!collapsed && (
<span className="text-sm font-semibold text-white"> <span className="text-sm font-semibold text-white">
CM助手 CM业务中心
</span> </span>
)} )}
</div> </div>
@@ -379,7 +380,7 @@ const Header = ({ collapsed }: HeaderProps) => {
<nav className="third-submenu-bar" aria-label="三级菜单"> <nav className="third-submenu-bar" aria-label="三级菜单">
<div className="third-submenu-list"> <div className="third-submenu-list">
{thirdSubNavItems.map((item) => { {thirdSubNavItems.map((item) => {
const isSelected = item.path ? pathname === item.path : hasActiveChild(item); const isSelected = item.path ? (pathname === item.path || pathname.startsWith(item.path + "/")) : hasActiveChild(item);
return ( return (
<button <button