Merge branch 'origin/dhk-1' into dhk-1,解决 sidebar-menu 冲突并保留应用中心菜单。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
commit
becfd9b211
5 files changed
+164
-103
No files matched your search
@@ -43,8 +43,8 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 75px;
|
height: 75px;
|
||||||
margin-top: 13px;
|
margin-top: 13px;
|
||||||
font-family: Noto Sans S Chinese;
|
font-family: "Source Han Sans SC", "Noto Sans SC", "Noto Sans S Chinese", "Microsoft YaHei", sans-serif;
|
||||||
font-weight: 500;
|
font-weight: 700;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -111,6 +111,42 @@
|
|||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-contnet--top-submenu .sidebar-contents {
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-contnet--top-submenu .item-nav {
|
||||||
|
height: auto;
|
||||||
|
min-height: 75px;
|
||||||
|
padding: 10px 2px;
|
||||||
|
font-size: 19px;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-contnet--top-submenu .item-nav__label {
|
||||||
|
width: 3.1em;
|
||||||
|
max-width: 100%;
|
||||||
|
padding-left: 0;
|
||||||
|
letter-spacing: 0;
|
||||||
|
line-height: 1.35;
|
||||||
|
text-align: center;
|
||||||
|
word-break: normal;
|
||||||
|
overflow-wrap: normal;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-contnet--top-submenu .item-nav__label--four-char {
|
||||||
|
width: 2.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-contnet--top-submenu .item-nav:hover::after,
|
||||||
|
.sidebar-contnet--top-submenu .item-nav-active::after,
|
||||||
|
.sidebar-contnet--top-submenu .item-nav-hovered::after {
|
||||||
|
top: auto;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.item-nav-content {
|
.item-nav-content {
|
||||||
width: 155px;
|
width: 155px;
|
||||||
height: calc(100vh - 4rem - 20px);
|
height: calc(100vh - 4rem - 20px);
|
||||||
@@ -194,10 +230,10 @@
|
|||||||
border: 0;
|
border: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 3px 0;
|
padding: 3px 0;
|
||||||
font-family: Noto Sans S Chinese;
|
font-family: "Source Han Sans SC", "Noto Sans SC", "Noto Sans S Chinese", "Microsoft YaHei", sans-serif;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
font-weight: 500;
|
font-weight: 700;
|
||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
color: rgba(255, 255, 255, 0.8);
|
color: rgba(255, 255, 255, 0.8);
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -363,10 +399,10 @@
|
|||||||
padding: 0 18px;
|
padding: 0 18px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: rgba(224, 242, 255, 0.9);
|
color: rgba(224, 242, 255, 0.9);
|
||||||
font-family: Noto Sans S Chinese;
|
font-family: "Source Han Sans SC", "Noto Sans SC", "Noto Sans S Chinese", "Microsoft YaHei", sans-serif;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
font-weight: 500;
|
font-weight: 700;
|
||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -443,10 +479,10 @@
|
|||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
background: rgba(2, 28, 65, 0.36);
|
background: rgba(2, 28, 65, 0.36);
|
||||||
color: rgba(221, 242, 255, 0.78);
|
color: rgba(221, 242, 255, 0.78);
|
||||||
font-family: Noto Sans S Chinese;
|
font-family: "Source Han Sans SC", "Noto Sans SC", "Noto Sans S Chinese", "Microsoft YaHei", sans-serif;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
font-weight: 500;
|
font-weight: 700;
|
||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
@@ -124,6 +124,13 @@ export function PageSidebarDark({ collapsed, onToggleCollapsed }: PageSidebarDar
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSecondItemClick = (item: MenuItem) => {
|
||||||
|
const path = item.path ?? findFirstRoutePath(item.children);
|
||||||
|
if (path) {
|
||||||
|
navigate(path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleMenuItemClick = (item: MenuItem) => {
|
const handleMenuItemClick = (item: MenuItem) => {
|
||||||
if (item.children?.length) {
|
if (item.children?.length) {
|
||||||
toggleExpanded(item.id);
|
toggleExpanded(item.id);
|
||||||
@@ -135,6 +142,35 @@ export function PageSidebarDark({ collapsed, onToggleCollapsed }: PageSidebarDar
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const activeTopItem =
|
||||||
|
visibleMenuItems.find((item) => item.id === activeTopId) ??
|
||||||
|
visibleMenuItems.find(hasActiveChild) ??
|
||||||
|
visibleMenuItems[0];
|
||||||
|
const sidebarMenuItemsToRender = inWujieEnv
|
||||||
|
? visibleMenuItems
|
||||||
|
: activeTopItem?.children ?? [];
|
||||||
|
const isSidebarItemActive = (item: MenuItem) =>
|
||||||
|
inWujieEnv
|
||||||
|
? item.id === activeTopId
|
||||||
|
: item.path
|
||||||
|
? pathname === item.path
|
||||||
|
: hasActiveChild(item);
|
||||||
|
const handleSidebarItemClick = (item: MenuItem) => {
|
||||||
|
if (inWujieEnv) {
|
||||||
|
handleTopItemClick(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSecondItemClick(item);
|
||||||
|
};
|
||||||
|
const getSidebarLabelClassName = (label: string) => {
|
||||||
|
if (!inWujieEnv && Array.from(label.trim()).length === 4) {
|
||||||
|
return "item-nav__label item-nav__label--four-char";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "item-nav__label";
|
||||||
|
};
|
||||||
|
|
||||||
const renderFlyoutMenu = (items: MenuItem[], level = 0) => (
|
const renderFlyoutMenu = (items: MenuItem[], level = 0) => (
|
||||||
<div className={`sidebar-flyout-list sidebar-flyout-list--level-${level}`}>
|
<div className={`sidebar-flyout-list sidebar-flyout-list--level-${level}`}>
|
||||||
{items.map((item) => {
|
{items.map((item) => {
|
||||||
@@ -181,7 +217,7 @@ export function PageSidebarDark({ collapsed, onToggleCollapsed }: PageSidebarDar
|
|||||||
return (
|
return (
|
||||||
<aside className={`sidebar-contnet ${inWujieEnv ? "" : "sidebar-contnet--top-submenu"}`}>
|
<aside className={`sidebar-contnet ${inWujieEnv ? "" : "sidebar-contnet--top-submenu"}`}>
|
||||||
<div className="sidebar-contents">
|
<div className="sidebar-contents">
|
||||||
{visibleMenuItems.map((item) => (
|
{sidebarMenuItemsToRender.map((item) => (
|
||||||
<div
|
<div
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className="item-nav-group"
|
className="item-nav-group"
|
||||||
@@ -198,10 +234,10 @@ export function PageSidebarDark({ collapsed, onToggleCollapsed }: PageSidebarDar
|
|||||||
<div className="item-nav-wrap">
|
<div className="item-nav-wrap">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`item-nav ${item.id === activeTopId ? "item-nav-active" : ""} ${hoveredTopId === item.id ? "item-nav-hovered" : ""}`}
|
className={`item-nav ${isSidebarItemActive(item) ? "item-nav-active" : ""} ${hoveredTopId === item.id ? "item-nav-hovered" : ""}`}
|
||||||
onClick={() => handleTopItemClick(item)}
|
onClick={() => handleSidebarItemClick(item)}
|
||||||
>
|
>
|
||||||
<span className="item-nav__label">{item.label}</span>
|
<span className={getSidebarLabelClassName(item.label)}>{item.label}</span>
|
||||||
</button>
|
</button>
|
||||||
{inWujieEnv && item.children?.length && hoveredTopId === item.id ? (
|
{inWujieEnv && item.children?.length && hoveredTopId === item.id ? (
|
||||||
<span className="item-nav-hover-bridge" aria-hidden="true" />
|
<span className="item-nav-hover-bridge" aria-hidden="true" />
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* ?????????????????
|
* 全局侧边栏菜单数据与权限过滤逻辑。
|
||||||
*
|
*
|
||||||
* ?? ``PageSidebar`` ??? ``PageSidebarDark`` ?????? ?? ?????
|
* 浅色 ``PageSidebar`` 和深色 ``PageSidebarDark`` 共用这份数据 —— 菜单结构与
|
||||||
* adminOnly ??????????????UI ???icon ??/????/hover flyout?
|
* adminOnly 权限策略对两种皮肤完全一致;UI 渲染(icon 显示/折叠样式/hover flyout)
|
||||||
* ?????????
|
* 在各自组件里实现。
|
||||||
*
|
*
|
||||||
* ????????????? sidebar ?????
|
* 修改菜单只需改这一处,两个 sidebar 自动同步。
|
||||||
*/
|
*/
|
||||||
import type { ElementType } from "react";
|
import type { ElementType } from "react";
|
||||||
import {
|
import {
|
||||||
@@ -24,13 +24,11 @@ import {
|
|||||||
History,
|
History,
|
||||||
Layers,
|
Layers,
|
||||||
Layout,
|
Layout,
|
||||||
|
Library,
|
||||||
List,
|
List,
|
||||||
ListChecks,
|
ListChecks,
|
||||||
ListTodo,
|
ListTodo,
|
||||||
MessageSquareCode,
|
|
||||||
Network,
|
Network,
|
||||||
NotebookPen,
|
|
||||||
Plus,
|
|
||||||
Settings,
|
Settings,
|
||||||
Sparkles,
|
Sparkles,
|
||||||
Target,
|
Target,
|
||||||
@@ -50,80 +48,46 @@ export type MenuItem = {
|
|||||||
export const sidebarMenuItems: MenuItem[] = [
|
export const sidebarMenuItems: MenuItem[] = [
|
||||||
{
|
{
|
||||||
id: "qa-center",
|
id: "qa-center",
|
||||||
label: "????",
|
label: "问答中心",
|
||||||
icon: HelpCircle,
|
icon: HelpCircle,
|
||||||
children: [
|
children: [
|
||||||
{ id: "general-qa", label: "????", icon: CircleHelp, path: "/page/workspace/chats/new" },
|
{ id: "general-qa", label: "通用问答", icon: CircleHelp, path: "/page/workspace/chats/new" },
|
||||||
{
|
{
|
||||||
id: "multi-agent-roundtable",
|
id: "multi-agent-roundtable",
|
||||||
label: "??????",
|
label: "多智能体会商",
|
||||||
icon: Users,
|
icon: Users,
|
||||||
path: "/page/strategy/qa/multi-agent-roundtable",
|
path: "/page/strategy/qa/multi-agent-roundtable",
|
||||||
},
|
},
|
||||||
// { id: "expert-qa", label: "????", icon: Brain, path: "/page/strategy/qa/expert-qa" },
|
// { id: "expert-qa", label: "专家问答", icon: Brain, path: "/page/strategy/qa/expert-qa" },
|
||||||
{
|
{
|
||||||
id: "qa-zzjc",
|
id: "qa-zzjc",
|
||||||
label: "zzjc??",
|
label: "zzJC支持",
|
||||||
icon: Bot,
|
icon: Bot,
|
||||||
path: "/page/strategy/agents/6bf/chats/new",
|
path: "/page/strategy/agents/6bf/chats/new",
|
||||||
},
|
},
|
||||||
{ id: "qa-zzxd", label: "zzXD??", icon: Layout, path: "/page/strategy/agents/10d69686718349688e58a8790cb61024/chats/new", },
|
{ id: "qa-zzxd", label: "zzXD应用", icon: Layout, path: "/page/strategy/agents/10d69686718349688e58a8790cb61024/chats/new", },
|
||||||
{ id: "qa-research", label: "????", icon: FileText, path: "/page/canvas/ai-writing" },
|
{ id: "qa-research", label: "课题研究", icon: FileText, path: "/page/canvas/ai-writing" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// id: "light-app-center",
|
|
||||||
// label: "???",
|
|
||||||
// icon: Grid3X3,
|
|
||||||
// children: [
|
|
||||||
// {
|
|
||||||
// id: "light-app-note-management",
|
|
||||||
// label: "????",
|
|
||||||
// icon: NotebookPen,
|
|
||||||
// children: [
|
|
||||||
// {
|
|
||||||
// id: "light-app-new-note",
|
|
||||||
// label: "????",
|
|
||||||
// icon: Plus,
|
|
||||||
// path: "/page/strategy/light-app/new-note",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: "light-app-note-list",
|
|
||||||
// label: "????",
|
|
||||||
// icon: List,
|
|
||||||
// path: "/page/strategy/light-app/notes",
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// id: "light-app-note-qa",
|
|
||||||
// label: "????",
|
|
||||||
// icon: MessageSquareCode,
|
|
||||||
// path: "/page/strategy/light-app/note-qa",
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// { id: "light-app-square", label: "????", icon: Layout },
|
|
||||||
// { id: "light-app-records", label: "????", icon: History },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
id: "task-management",
|
id: "task-management",
|
||||||
label: "????",
|
label: "任务管理",
|
||||||
icon: Target,
|
icon: Target,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
id: "xk-center-task",
|
id: "xk-center-task",
|
||||||
label: "XK???",
|
label: "XK中任务",
|
||||||
icon: Folder,
|
icon: Folder,
|
||||||
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",
|
||||||
},
|
},
|
||||||
@@ -131,7 +95,7 @@ export const sidebarMenuItems: MenuItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "coh-center-task",
|
id: "coh-center-task",
|
||||||
label: "COH???",
|
label: "COH中任务",
|
||||||
icon: Folder,
|
icon: Folder,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@@ -142,7 +106,7 @@ export const sidebarMenuItems: MenuItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "coh-task-fx",
|
id: "coh-task-fx",
|
||||||
label: "??FX",
|
label: "任务FX",
|
||||||
icon: ListTodo,
|
icon: ListTodo,
|
||||||
path: "/page/strategy/task-management/plan-task/plan-task-fx",
|
path: "/page/strategy/task-management/plan-task/plan-task-fx",
|
||||||
},
|
},
|
||||||
@@ -156,12 +120,12 @@ export const sidebarMenuItems: MenuItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "pg-center-task",
|
id: "pg-center-task",
|
||||||
label: "PG???",
|
label: "PG中任务",
|
||||||
icon: Folder,
|
icon: Folder,
|
||||||
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",
|
||||||
},
|
},
|
||||||
@@ -173,7 +137,7 @@ export const sidebarMenuItems: MenuItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
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",
|
||||||
},
|
},
|
||||||
@@ -181,24 +145,24 @@ export const sidebarMenuItems: MenuItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "ty-center-task",
|
id: "ty-center-task",
|
||||||
label: "TY???",
|
label: "TY中任务",
|
||||||
icon: Folder,
|
icon: Folder,
|
||||||
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",
|
||||||
},
|
},
|
||||||
@@ -206,63 +170,83 @@ export const sidebarMenuItems: MenuItem[] = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "light-app-center",
|
||||||
|
label: "应用中心",
|
||||||
|
icon: Grid3X3,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: "light-app-management",
|
||||||
|
label: "应用管理",
|
||||||
|
icon: Layout,
|
||||||
|
path: "/page/strategy/light-app/management",
|
||||||
|
adminOnly: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "light-app-apps",
|
||||||
|
label: "应用列表",
|
||||||
|
icon: List,
|
||||||
|
path: "/page/strategy/light-app/apps",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "comprehensive-management",
|
id: "comprehensive-management",
|
||||||
label: "????",
|
label: "综合管理",
|
||||||
icon: Settings,
|
icon: Settings,
|
||||||
children: [
|
children: [
|
||||||
{ 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",
|
||||||
label: "????",
|
label: "配置管理",
|
||||||
icon: Network,
|
icon: Network,
|
||||||
path: "/page/strategy/business-chain-mapping",
|
path: "/page/strategy/business-chain-mapping",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "mgmt-business-chains",
|
id: "mgmt-business-chains",
|
||||||
label: "??????",
|
label: "业务链条配置",
|
||||||
icon: Layers,
|
icon: Layers,
|
||||||
path: "/page/strategy/business-chains",
|
path: "/page/strategy/business-chains",
|
||||||
},
|
},
|
||||||
{ id: "mgmt-skills", label: "????", icon: Sparkles, path: "/page/strategy/skills" },
|
{ id: "mgmt-skills", label: "技能管理", icon: Sparkles, path: "/page/strategy/skills" },
|
||||||
{ id: "mgmt-memory", label: "????", icon: Brain, path: "/page/strategy/memory" },
|
{ id: "mgmt-memory", label: "记忆管理", icon: Brain, path: "/page/strategy/memory" },
|
||||||
{
|
{
|
||||||
id: "mgmt-tasks",
|
id: "mgmt-tasks",
|
||||||
label: "????",
|
label: "定时任务",
|
||||||
icon: ListChecks,
|
icon: ListChecks,
|
||||||
path: "/page/strategy/scheduled/tasks",
|
path: "/page/strategy/scheduled/tasks",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "mgmt-llm-metrics",
|
id: "mgmt-llm-metrics",
|
||||||
label: "???????",
|
label: "大模型调用统计",
|
||||||
icon: Gauge,
|
icon: Gauge,
|
||||||
path: "/page/strategy/settings/llm-metrics",
|
path: "/page/strategy/settings/llm-metrics",
|
||||||
adminOnly: true,
|
adminOnly: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "mgmt-users",
|
id: "mgmt-users",
|
||||||
label: "????",
|
label: "用户管理",
|
||||||
icon: Users,
|
icon: Users,
|
||||||
path: "/page/strategy/admin/users",
|
path: "/page/strategy/admin/users",
|
||||||
adminOnly: true,
|
adminOnly: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "mgmt-user-leaderboard",
|
id: "mgmt-user-leaderboard",
|
||||||
label: "?????",
|
label: "用户排行榜",
|
||||||
icon: Trophy,
|
icon: Trophy,
|
||||||
path: "/page/strategy/admin/user-leaderboard",
|
path: "/page/strategy/admin/user-leaderboard",
|
||||||
adminOnly: true,
|
adminOnly: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "mgmt-admin-scheduled-tasks",
|
id: "mgmt-admin-scheduled-tasks",
|
||||||
label: "??????",
|
label: "定时任务管理",
|
||||||
icon: CalendarClock,
|
icon: CalendarClock,
|
||||||
path: "/page/strategy/admin/scheduled-tasks",
|
path: "/page/strategy/admin/scheduled-tasks",
|
||||||
adminOnly: true,
|
adminOnly: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "mgmt-user-activity",
|
id: "mgmt-user-activity",
|
||||||
label: "??????",
|
label: "用户活动审计",
|
||||||
icon: History,
|
icon: History,
|
||||||
path: "/page/strategy/admin/user-activity",
|
path: "/page/strategy/admin/user-activity",
|
||||||
adminOnly: true,
|
adminOnly: true,
|
||||||
@@ -271,24 +255,30 @@ export const sidebarMenuItems: MenuItem[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "resource-management",
|
id: "resource-management",
|
||||||
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: "问答梳理",
|
||||||
icon: BookOpen,
|
icon: BookOpen,
|
||||||
path: "/page/workspace/knowledge",
|
path: "/page/workspace/knowledge",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "resource-knowledge-base",
|
||||||
|
label: "知识库资源管理",
|
||||||
|
icon: Library,
|
||||||
|
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",
|
||||||
},
|
},
|
||||||
@@ -296,7 +286,7 @@ export const sidebarMenuItems: MenuItem[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/** ??????? id ????????????????? */
|
/** 默认展开的菜单 id 集合(浅色版可折叠交互的初始状态) */
|
||||||
export const defaultExpandedIds: ReadonlySet<string> = new Set([
|
export const defaultExpandedIds: ReadonlySet<string> = new Set([
|
||||||
"qa-center",
|
"qa-center",
|
||||||
"light-app-center",
|
"light-app-center",
|
||||||
@@ -306,7 +296,7 @@ export const defaultExpandedIds: ReadonlySet<string> = new Set([
|
|||||||
"comprehensive-management",
|
"comprehensive-management",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/** ? admin ???????? admin ??? ``adminOnly: true`` ?????? */
|
/** 按 admin 角色过滤菜单:非 admin 不展示 ``adminOnly: true`` 的项及其子项 */
|
||||||
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)
|
||||||
|
|||||||
@@ -78,11 +78,11 @@ export default function StrategyRoutes() {
|
|||||||
<Route index element={<Navigate to="xk-task-jc" replace />} />
|
<Route index element={<Navigate to="xk-task-jc" replace />} />
|
||||||
<Route
|
<Route
|
||||||
path="xk-task-jc"
|
path="xk-task-jc"
|
||||||
element={<TaskXkFrom gopath="#/pageIndie/pageHome/pageSwrw" />}
|
element={<TaskXkFrom gopath="/#/pageIndie/pageHome/pageSwrw" />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="xk-task-dispatch"
|
path="xk-task-dispatch"
|
||||||
element={<TaskXkFrom gopath="#/pageIndie/pageJczl" />}
|
element={<TaskXkFrom gopath="/#/pageIndie/pageJczl" />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="effect-task-pg"
|
path="effect-task-pg"
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const Header = ({ collapsed }: HeaderProps) => {
|
|||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
const isAdmin = getStoredAuth()?.system_role === "admin";
|
const isAdmin = getStoredAuth()?.system_role === "admin";
|
||||||
const visibleMenuItems = useSidebarMenuItems(!!isAdmin);
|
const visibleMenuItems = useSidebarMenuItems(!!isAdmin);
|
||||||
const showTopSubmenu = isDark && !collapsed && !isWujieEnv();
|
const showTopNav = isDark && !collapsed && !isWujieEnv();
|
||||||
|
|
||||||
const hasActiveChild = (item: MenuItem): boolean => {
|
const hasActiveChild = (item: MenuItem): boolean => {
|
||||||
if (item.path && pathname === item.path) {
|
if (item.path && pathname === item.path) {
|
||||||
@@ -64,11 +64,10 @@ const Header = ({ collapsed }: HeaderProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const activeTopItem = visibleMenuItems.find(hasActiveChild);
|
const activeTopItem = visibleMenuItems.find(hasActiveChild);
|
||||||
const topSubNavItems = activeTopItem?.children ?? [];
|
const activeSecondItem = activeTopItem?.children?.find(hasActiveChild);
|
||||||
const activeSecondItem = topSubNavItems.find(hasActiveChild);
|
|
||||||
const thirdSubNavItems = activeSecondItem?.children ?? [];
|
const thirdSubNavItems = activeSecondItem?.children ?? [];
|
||||||
|
|
||||||
const handleTopSubNavClick = (item: MenuItem) => {
|
const handleNavItemClick = (item: MenuItem) => {
|
||||||
const path = item.path ?? findFirstRoutePath(item.children);
|
const path = item.path ?? findFirstRoutePath(item.children);
|
||||||
if (path) {
|
if (path) {
|
||||||
navigate(path);
|
navigate(path);
|
||||||
@@ -103,10 +102,10 @@ const Header = ({ collapsed }: HeaderProps) => {
|
|||||||
CM助手
|
CM助手
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{showTopSubmenu && topSubNavItems.length ? (
|
{showTopNav && visibleMenuItems.length ? (
|
||||||
<nav className="top-submenu-bar" aria-label="二级菜单">
|
<nav className="top-submenu-bar" aria-label="二级菜单">
|
||||||
<div className="top-submenu-list">
|
<div className="top-submenu-list">
|
||||||
{topSubNavItems.map((item) => {
|
{visibleMenuItems.map((item) => {
|
||||||
const isSelected = item.path ? pathname === item.path : hasActiveChild(item);
|
const isSelected = item.path ? pathname === item.path : hasActiveChild(item);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -114,7 +113,7 @@ const Header = ({ collapsed }: HeaderProps) => {
|
|||||||
key={item.id}
|
key={item.id}
|
||||||
type="button"
|
type="button"
|
||||||
className={`top-submenu-item ${isSelected ? "top-submenu-item--active" : ""}`}
|
className={`top-submenu-item ${isSelected ? "top-submenu-item--active" : ""}`}
|
||||||
onClick={() => handleTopSubNavClick(item)}
|
onClick={() => handleNavItemClick(item)}
|
||||||
>
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</button>
|
</button>
|
||||||
@@ -219,7 +218,7 @@ const Header = ({ collapsed }: HeaderProps) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
{showTopSubmenu && thirdSubNavItems.length ? (
|
{showTopNav && thirdSubNavItems.length ? (
|
||||||
<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) => {
|
||||||
@@ -230,7 +229,7 @@ const Header = ({ collapsed }: HeaderProps) => {
|
|||||||
key={item.id}
|
key={item.id}
|
||||||
type="button"
|
type="button"
|
||||||
className={`third-submenu-item ${isSelected ? "third-submenu-item--active" : ""}`}
|
className={`third-submenu-item ${isSelected ? "third-submenu-item--active" : ""}`}
|
||||||
onClick={() => handleTopSubNavClick(item)}
|
onClick={() => handleNavItemClick(item)}
|
||||||
>
|
>
|
||||||
{item.label}
|
{item.label}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in new issue
Block a user