Merge branch 'master' of http://192.168.0.200/knowledge-base-bj/deerflow-server into xuhd
This commit is contained in:
commit
e30b44dae1
68 files changed
+10813
-3976
No files matched your search
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 外部系统跳转登录时透传的参数:
|
||||
* theme —— 主题色,"dark-blue" => 深色,其他 => 浅色(在 LoginPage 调 setTheme 直接生效)
|
||||
* ticket —— 第三方 ticket,持久化到 localStorage 供后续请求使用
|
||||
* userId —— 外部用户 id,同上
|
||||
* env —— 环境标识,同上
|
||||
*
|
||||
* 这里只暴露 ``ticket / userId / env`` 三个 storage key 和读写工具;
|
||||
* theme 不存(直接走 ThemeContext,避免双源)。
|
||||
*/
|
||||
|
||||
export const EXTERNAL_LOGIN_STORAGE_KEYS = {
|
||||
ticket: "login.ticket",
|
||||
userId: "login.userId",
|
||||
env: "login.env",
|
||||
} as const;
|
||||
|
||||
export type ExternalLoginParams = {
|
||||
ticket?: string;
|
||||
userId?: string;
|
||||
env?: string;
|
||||
};
|
||||
|
||||
/** 把外部跳转带来的三个参数写到 localStorage;隐私模式 / quota 异常时静默失败 */
|
||||
export function persistExternalLoginParams(params: ExternalLoginParams): void {
|
||||
try {
|
||||
if (params.ticket) {
|
||||
localStorage.setItem(EXTERNAL_LOGIN_STORAGE_KEYS.ticket, params.ticket);
|
||||
}
|
||||
if (params.userId) {
|
||||
localStorage.setItem(EXTERNAL_LOGIN_STORAGE_KEYS.userId, params.userId);
|
||||
}
|
||||
if (params.env) {
|
||||
localStorage.setItem(EXTERNAL_LOGIN_STORAGE_KEYS.env, params.env);
|
||||
}
|
||||
} catch {
|
||||
// localStorage 不可用时不阻断登录流程
|
||||
}
|
||||
}
|
||||
|
||||
/** 读取持久化的外部登录参数;不可用时返回空字符串 */
|
||||
export function readExternalLoginParams(): Required<ExternalLoginParams> {
|
||||
try {
|
||||
return {
|
||||
ticket: localStorage.getItem(EXTERNAL_LOGIN_STORAGE_KEYS.ticket) ?? "",
|
||||
userId: localStorage.getItem(EXTERNAL_LOGIN_STORAGE_KEYS.userId) ?? "",
|
||||
env: localStorage.getItem(EXTERNAL_LOGIN_STORAGE_KEYS.env) ?? "",
|
||||
};
|
||||
} catch {
|
||||
return { ticket: "", userId: "", env: "" };
|
||||
}
|
||||
}
|
||||
|
||||
/** 把 ``theme`` query 值映射成 ThemeContext 的 ``'dark' | 'light'`` */
|
||||
export function resolveThemeFromQuery(themeParam: string | null | undefined): "dark" | "light" {
|
||||
return themeParam === "dark-blue" ? "dark" : "light";
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { requestCrudService } from "@/service/request-axios-service";
|
||||
|
||||
const CONSUMER_URL = import.meta.env.VITE_AIPI_CONSUMER_URL || "";
|
||||
|
||||
export const TOOLS_TOKEN_STORAGE_KEY = "tools_token";
|
||||
export const EXTERNAL_USER_ID_STORAGE_KEY = "userId";
|
||||
export const EXTERNAL_USER_INFO_STORAGE_KEY = "userInfo";
|
||||
export const GENERAL_QA_ROUTE = "/page/strategy/qa/general";
|
||||
|
||||
type UserDetailResponse = {
|
||||
data?: {
|
||||
id?: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* External login via yUserId + optional token (same flow as web-code Login.tsx):
|
||||
* persist tools_token, resolve user via consumer API, store userId/userInfo.
|
||||
*/
|
||||
export async function loginByYUserId(
|
||||
yUserId: string,
|
||||
token?: string | null,
|
||||
): Promise<void> {
|
||||
if (token) {
|
||||
localStorage.setItem(TOOLS_TOKEN_STORAGE_KEY, token);
|
||||
}
|
||||
|
||||
const res = (await requestCrudService.get(
|
||||
`${CONSUMER_URL}/cop/userDetailByYuserId`,
|
||||
{ yuserId: yUserId },
|
||||
)) as UserDetailResponse;
|
||||
|
||||
const result = res.data;
|
||||
if (!result?.id) {
|
||||
throw new Error("无法根据 yUserId 获取用户信息。");
|
||||
}
|
||||
|
||||
localStorage.setItem(EXTERNAL_USER_ID_STORAGE_KEY, result.id);
|
||||
localStorage.setItem(EXTERNAL_USER_INFO_STORAGE_KEY, JSON.stringify(result));
|
||||
}
|
||||
|
||||
export function persistToolsToken(token: string): void {
|
||||
localStorage.setItem(TOOLS_TOKEN_STORAGE_KEY, token);
|
||||
}
|
||||
@@ -6,7 +6,14 @@ export function isSidebarEnabledFromSearch(search: string): boolean {
|
||||
const params = new URLSearchParams(
|
||||
search.startsWith("?") ? search : `?${search}`,
|
||||
);
|
||||
return params.get(PAGE_SIDEBAR_QUERY_PARAM) === "1";
|
||||
if (params.get(PAGE_SIDEBAR_QUERY_PARAM) === "1") {
|
||||
return true;
|
||||
}
|
||||
// External yUserId login enables the page sidebar (see LoginPage + yuser-login).
|
||||
if (params.get("yUserId")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function persistSidebarEnabled(enabled: boolean): void {
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
/**
|
||||
* 全局侧边栏菜单数据与权限过滤逻辑。
|
||||
*
|
||||
* 浅色 ``PageSidebar`` 和深色 ``PageSidebarDark`` 共用这份数据 —— 菜单结构与
|
||||
* adminOnly 权限策略对两种皮肤完全一致;UI 渲染(icon 显示/折叠样式/hover flyout)
|
||||
* 在各自组件里实现。
|
||||
*
|
||||
* 修改菜单只需改这一处,两个 sidebar 自动同步。
|
||||
*/
|
||||
import type { ElementType } from "react";
|
||||
import {
|
||||
Bot,
|
||||
Brain,
|
||||
CalendarClock,
|
||||
CircleHelp,
|
||||
Database,
|
||||
FileBox,
|
||||
FileText,
|
||||
Folder,
|
||||
Gauge,
|
||||
Grid3X3,
|
||||
HelpCircle,
|
||||
History,
|
||||
Layout,
|
||||
Library,
|
||||
List,
|
||||
ListChecks,
|
||||
ListTodo,
|
||||
MessageSquareCode,
|
||||
MessageSquarePlus,
|
||||
Network,
|
||||
NotebookPen,
|
||||
Plus,
|
||||
Settings,
|
||||
ShieldCheck,
|
||||
Sparkles,
|
||||
Target,
|
||||
Users,
|
||||
} from "lucide-react";
|
||||
|
||||
export type MenuItem = {
|
||||
id: string;
|
||||
label: string;
|
||||
icon: ElementType;
|
||||
path?: string;
|
||||
adminOnly?: boolean;
|
||||
children?: MenuItem[];
|
||||
};
|
||||
|
||||
export const sidebarMenuItems: MenuItem[] = [
|
||||
{
|
||||
id: "qa-center",
|
||||
label: "问答中心",
|
||||
icon: HelpCircle,
|
||||
children: [
|
||||
{ id: "general-qa", label: "通用问答", icon: CircleHelp, path: "/page/workspace/chats/new" },
|
||||
{ id: "expert-qa", label: "专家问答", icon: Brain, path: "/page/strategy/qa/expert-qa" },
|
||||
// 「圆桌规划」入口暂时隐藏 —— 功能仍在 /page/roundtable/planning,只是不在侧边栏出现。
|
||||
// 需要重新开放时取消注释即可。
|
||||
// {
|
||||
// id: "qa-roundtable",
|
||||
// label: "圆桌规划",
|
||||
// icon: Bot,
|
||||
// path: "/page/roundtable/planning",
|
||||
// },
|
||||
{ id: "qa-zzjc", label: "zzjc支持", icon: Bot },
|
||||
{ id: "qa-zzxd", label: "zzXD应用", icon: Layout },
|
||||
{ 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",
|
||||
label: "任务管理",
|
||||
icon: Target,
|
||||
children: [
|
||||
{
|
||||
id: "xk-center-task",
|
||||
label: "XK中任务",
|
||||
icon: Folder,
|
||||
children: [
|
||||
{
|
||||
id: "xk-task-jc",
|
||||
label: "任务JC",
|
||||
icon: ListTodo,
|
||||
path: "/page/strategy/task-management/xk-task-jc",
|
||||
},
|
||||
{
|
||||
id: "xk-task-dispatch",
|
||||
label: "任务调度",
|
||||
icon: ListTodo,
|
||||
path: "/page/strategy/task-management/xk-task-dispatch",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "coh-center-task",
|
||||
label: "COH中任务",
|
||||
icon: Folder,
|
||||
children: [
|
||||
{
|
||||
id: "coh-task-3qfx",
|
||||
label: "3QFX",
|
||||
icon: ListTodo,
|
||||
path: "/page/strategy/task-management/plan-task-sentiment",
|
||||
},
|
||||
{
|
||||
id: "coh-task-fx",
|
||||
label: "任务FX",
|
||||
icon: ListTodo,
|
||||
path: "/page/strategy/task-management/plan-task/plan-task-fx",
|
||||
},
|
||||
{
|
||||
id: "coh-task-xdfx",
|
||||
label: "XDFX",
|
||||
icon: ListTodo,
|
||||
path: "/page/strategy/task-management/plan-task/plan-task-action",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "pg-center-task",
|
||||
label: "PG中任务",
|
||||
icon: Folder,
|
||||
children: [
|
||||
{
|
||||
id: "pg-task-pg",
|
||||
label: "任务PG",
|
||||
icon: ListTodo,
|
||||
path: "/page/strategy/task-management/effect-task-pg",
|
||||
},
|
||||
{
|
||||
id: "pg-task-xdpg",
|
||||
label: "XDPG",
|
||||
icon: ListTodo,
|
||||
path: "/page/strategy/task-management/effect-action-pg",
|
||||
},
|
||||
{
|
||||
id: "pg-task-info-pg",
|
||||
label: "信息PG",
|
||||
icon: ListTodo,
|
||||
path: "/page/strategy/task-management/effect-info-pg",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "ty-center-task",
|
||||
label: "TY中任务",
|
||||
icon: Folder,
|
||||
children: [
|
||||
{
|
||||
id: "ty-task-xdty",
|
||||
label: "XDTY任务",
|
||||
icon: ListTodo,
|
||||
path: "/page/strategy/task-management/mnty-task-mechanism",
|
||||
},
|
||||
{
|
||||
id: "ty-task-plan",
|
||||
label: "方案TY任务",
|
||||
icon: ListTodo,
|
||||
path: "/page/strategy/task-management/mnty-task-plan",
|
||||
},
|
||||
{
|
||||
id: "ty-task-xxty",
|
||||
label: "XXTY任务",
|
||||
icon: ListTodo,
|
||||
path: "/page/strategy/task-management/mnty-task-zsty",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "comprehensive-management",
|
||||
label: "综合管理",
|
||||
icon: Settings,
|
||||
children: [
|
||||
{ id: "mgmt-agents", label: "智能体管理", icon: Bot, path: "/page/strategy/agents" },
|
||||
{ id: "mgmt-skills", label: "技能管理", icon: Sparkles, path: "/page/strategy/skills" },
|
||||
{ id: "mgmt-memory", label: "记忆管理", icon: Brain, path: "/page/strategy/memory" },
|
||||
{
|
||||
id: "mgmt-tasks",
|
||||
label: "定时任务",
|
||||
icon: ListChecks,
|
||||
path: "/page/strategy/scheduled/tasks",
|
||||
},
|
||||
{
|
||||
id: "mgmt-recommended-questions",
|
||||
label: "推荐问题配置",
|
||||
icon: MessageSquarePlus,
|
||||
path: "/page/strategy/settings/recommended-questions",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
id: "mgmt-prompt-prefix",
|
||||
label: "问答前缀配置",
|
||||
icon: MessageSquareCode,
|
||||
path: "/page/strategy/settings/prompt-prefix",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
id: "mgmt-private-square",
|
||||
label: "私密广场配置",
|
||||
icon: ShieldCheck,
|
||||
path: "/page/strategy/settings/private-square",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
id: "mgmt-llm-metrics",
|
||||
label: "大模型调用统计",
|
||||
icon: Gauge,
|
||||
path: "/page/strategy/settings/llm-metrics",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
id: "mgmt-users",
|
||||
label: "用户管理",
|
||||
icon: Users,
|
||||
path: "/page/strategy/admin/users",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
id: "mgmt-admin-scheduled-tasks",
|
||||
label: "定时任务管理",
|
||||
icon: CalendarClock,
|
||||
path: "/page/strategy/admin/scheduled-tasks",
|
||||
adminOnly: true,
|
||||
},
|
||||
{
|
||||
id: "mgmt-user-activity",
|
||||
label: "用户活动审计",
|
||||
icon: History,
|
||||
path: "/page/strategy/admin/user-activity",
|
||||
adminOnly: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "resource-management",
|
||||
label: "资源管理",
|
||||
icon: Database,
|
||||
children: [
|
||||
{
|
||||
id: "resource-network-xwt",
|
||||
label: "网络xwt资源管理",
|
||||
icon: Network,
|
||||
path: "/page/strategy/resource-management/resource-network-actor",
|
||||
},
|
||||
{
|
||||
id: "resource-knowledge-base",
|
||||
label: "知识库资源管理",
|
||||
icon: Library,
|
||||
path: "/page/strategy/resource-management/resource-knowledge-base",
|
||||
},
|
||||
{
|
||||
id: "resource-evaluation-index",
|
||||
label: "作战资源管理",
|
||||
icon: FileBox,
|
||||
path: "/page/strategy/resource-management/resource-evaluation-index",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
/** 默认展开的菜单 id 集合(浅色版可折叠交互的初始状态) */
|
||||
export const defaultExpandedIds: ReadonlySet<string> = new Set([
|
||||
"qa-center",
|
||||
"light-app-center",
|
||||
"light-app-note-management",
|
||||
"task-management",
|
||||
"xk-center-task",
|
||||
]);
|
||||
|
||||
/** 按 admin 角色过滤菜单:非 admin 不展示 ``adminOnly: true`` 的项及其子项 */
|
||||
export function filterMenuItemsByRole(items: MenuItem[], isAdmin: boolean): MenuItem[] {
|
||||
return items
|
||||
.filter((item) => !item.adminOnly || isAdmin)
|
||||
.map((item) =>
|
||||
item.children
|
||||
? { ...item, children: filterMenuItemsByRole(item.children, isAdmin) }
|
||||
: item,
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user