From 3632b0d7261db1f34ab578808069958654ccfb76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=AE=8F=E5=87=AF?= Date: Thu, 28 May 2026 17:49:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend-web/.env.development | 8 ++- frontend-web/.env.development.local.example | 5 +- frontend-web/.env.example | 5 ++ frontend-web/.env.production | 5 +- .../src/components/page-sidebar-dark.tsx | 22 +++++++- frontend-web/src/components/page-sidebar.tsx | 22 +++++++- .../src/core/strategy/external-links.ts | 38 +++++++++++++ frontend-web/src/main.tsx | 1 + frontend-web/src/pages/StrategyRoutes.tsx | 29 +++++++++- .../{qa => chat-qa}/GeneralQA.mock.ts | 2 +- .../components/{qa => chat-qa}/GeneralQA.tsx | 25 +++++---- .../{qa => chat-qa}/GeneralQA.types.ts | 2 +- .../GeneralQAConfigSidebar.tsx | 0 .../{qa => chat-qa}/GeneralQAHeader.tsx | 14 ++++- .../KnowledgeBaseResourceManagement.tsx | 50 +++++++++++++++++ .../NetworkActorResourceManagement.tsx | 20 +++++++ .../task-components/css/strategy-data.css | 56 +++++++++++++++++++ 17 files changed, 279 insertions(+), 25 deletions(-) create mode 100644 frontend-web/src/core/strategy/external-links.ts rename frontend-web/src/strategy-components/components/{qa => chat-qa}/GeneralQA.mock.ts (99%) rename frontend-web/src/strategy-components/components/{qa => chat-qa}/GeneralQA.tsx (99%) rename frontend-web/src/strategy-components/components/{qa => chat-qa}/GeneralQA.types.ts (95%) rename frontend-web/src/strategy-components/components/{qa => chat-qa}/GeneralQAConfigSidebar.tsx (100%) rename frontend-web/src/strategy-components/components/{qa => chat-qa}/GeneralQAHeader.tsx (90%) create mode 100644 frontend-web/src/strategy-components/components/resource-management/KnowledgeBaseResourceManagement.tsx create mode 100644 frontend-web/src/strategy-components/components/resource-management/NetworkActorResourceManagement.tsx diff --git a/frontend-web/.env.development b/frontend-web/.env.development index 41decf09..6228c720 100644 --- a/frontend-web/.env.development +++ b/frontend-web/.env.development @@ -16,7 +16,13 @@ VITE_AIPI_GENERATE_CHAT_URL=https://ch1.b.uat.4.cn/jialai_b1_chat VITE_AIPI_TASK_CHAT_URL=https://ch1.b.uat.4.cn/qq_b1_chat VITE_AIPI_KNOWLEDGE_URL=https://chlib.b.uat.4.cn/knowlibrary VITE_AIPI_B1COH_URL=https://ch1.b.uat.4.cn/web -VITE_AIPI_B2ACTOR_URL=htttps://ty.b.uat.4.cn +VITE_AIPI_B2ACTOR_URL=https://ty.b.uat.4.cn +VITE_AIPI_B2ACTOR_XWT_PATH=/fromB/toXWT?isFrame=1 +VITE_AIPI_KNOWLEDGE_IFRAME_API_URL=https://ch1.b.uat.4.cn/knowes/api/iframeKnowledgeUrl +VITE_AIPI_KNOWLEDGE_IFRAME_SKIN=red +VITE_AIPI_B2ACTOR_XWT_PATH=/fromB/toXWT?isFrame=1 +VITE_AIPI_KNOWLEDGE_IFRAME_API_URL=https://ch1.b.uat.4.cn/knowes/api/iframeKnowledgeUrl +VITE_AIPI_KNOWLEDGE_IFRAME_SKIN=red VITE_AIPI_MOPECHAT_URL=https://ch1.b.uat.4.cn/likun_b1_mope VITE_AIPI_BACKENP_URL=https://knowledgetoolserver.b.uat.4.cn VITE_AIPI_CONSUMER_URL=https://ch1.b.uat.4.cn/consumer diff --git a/frontend-web/.env.development.local.example b/frontend-web/.env.development.local.example index 471b2649..f01f2187 100644 --- a/frontend-web/.env.development.local.example +++ b/frontend-web/.env.development.local.example @@ -10,7 +10,10 @@ VITE_AIPI_GENERATE_CHAT_URL=https://ch1.b.uat.4.cn/jialai_b1_chat VITE_AIPI_TASK_CHAT_URL=https://ch1.b.uat.4.cn/qq_b1_chat VITE_AIPI_KNOWLEDGE_URL=https://chlib.b.uat.4.cn/knowlibrary VITE_AIPI_B1COH_URL=https://ch1.b.uat.4.cn/web -VITE_AIPI_B2ACTOR_URL=htttps://ty.b.uat.4.cn +VITE_AIPI_B2ACTOR_URL=https://ty.b.uat.4.cn +VITE_AIPI_B2ACTOR_XWT_PATH=/fromB/toXWT?isFrame=1 +VITE_AIPI_KNOWLEDGE_IFRAME_API_URL=https://ch1.b.uat.4.cn/knowes/api/iframeKnowledgeUrl +VITE_AIPI_KNOWLEDGE_IFRAME_SKIN=red VITE_AIPI_MOPECHAT_URL=https://ch1.b.uat.4.cn/likun_b1_mope VITE_AIPI_BACKENP_URL=https://knowledgetoolserver.b.uat.4.cn VITE_AIPI_CONSUMER_URL=https://ch1.b.uat.4.cn/consumer diff --git a/frontend-web/.env.example b/frontend-web/.env.example index 30e82ad6..adb14fb8 100644 --- a/frontend-web/.env.example +++ b/frontend-web/.env.example @@ -24,6 +24,11 @@ # --- 生产打包(见 .env.production)--- # 部署前修改 .env.production 中的地址,再执行 pnpm build +# VITE_AIPI_B2ACTOR_URL=https://ty.b.uat.4.cn +# VITE_AIPI_B2ACTOR_XWT_PATH=/fromB/toXWT?isFrame=1 +# VITE_AIPI_KNOWLEDGE_IFRAME_API_URL=https://ch1.b.uat.4.cn/knowes/api/iframeKnowledgeUrl +# VITE_AIPI_KNOWLEDGE_IFRAME_SKIN=red + # 可选 # VITE_CANVAS_LANGGRAPH_BASE_URL= # VITE_STATIC_WEBSITE_ONLY= diff --git a/frontend-web/.env.production b/frontend-web/.env.production index 0e94e082..0f10b55c 100644 --- a/frontend-web/.env.production +++ b/frontend-web/.env.production @@ -14,7 +14,10 @@ VITE_AIPI_GENERATE_CHAT_URL=https://ch1.b.uat.4.cn/jialai_b1_chat VITE_AIPI_TASK_CHAT_URL=https://ch1.b.uat.4.cn/qq_b1_chat VITE_AIPI_KNOWLEDGE_URL=https://chlib.b.uat.4.cn/knowlibrary VITE_AIPI_B1COH_URL=https://ch1.b.uat.4.cn/web -VITE_AIPI_B2ACTOR_URL=htttps://ty.b.uat.4.cn +VITE_AIPI_B2ACTOR_URL=https://ty.b.uat.4.cn +VITE_AIPI_B2ACTOR_XWT_PATH=/fromB/toXWT?isFrame=1 +VITE_AIPI_KNOWLEDGE_IFRAME_API_URL=https://ch1.b.uat.4.cn/knowes/api/iframeKnowledgeUrl +VITE_AIPI_KNOWLEDGE_IFRAME_SKIN=red VITE_AIPI_MOPECHAT_URL=https://ch1.b.uat.4.cn/likun_b1_mope VITE_AIPI_BACKENP_URL=https://knowledgetoolserver.b.uat.4.cn VITE_AIPI_CONSUMER_URL=https://ch1.b.uat.4.cn/consumer diff --git a/frontend-web/src/components/page-sidebar-dark.tsx b/frontend-web/src/components/page-sidebar-dark.tsx index 171eeef7..d67f34b1 100644 --- a/frontend-web/src/components/page-sidebar-dark.tsx +++ b/frontend-web/src/components/page-sidebar-dark.tsx @@ -74,6 +74,7 @@ const menuItems: MenuItem[] = [ 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" }, { 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" }, @@ -237,9 +238,24 @@ const menuItems: MenuItem[] = [ label: "资源管理", icon: Database, children: [ - { id: "resource-network-xwt", label: "网络xwt资源管理", icon: Network }, - { id: "resource-knowledge-base", label: "知识库资源管理", icon: Library }, - { id: "resource-zz", label: "ZZ资源管理", icon: FileBox }, + { + 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", + }, ], }, ]; diff --git a/frontend-web/src/components/page-sidebar.tsx b/frontend-web/src/components/page-sidebar.tsx index 95314386..11dec345 100644 --- a/frontend-web/src/components/page-sidebar.tsx +++ b/frontend-web/src/components/page-sidebar.tsx @@ -73,6 +73,7 @@ const menuItems: MenuItem[] = [ 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,只是不在侧边栏出现。 // 需要重新开放时取消注释即可。 // { @@ -291,9 +292,24 @@ const menuItems: MenuItem[] = [ label: "资源管理", icon: Database, children: [ - { id: "resource-network-xwt", label: "网络xwt资源管理", icon: Network }, - { id: "resource-knowledge-base", label: "知识库资源管理", icon: Library }, - { id: "resource-zz", label: "ZZ资源管理", icon: FileBox }, + { + 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", + }, ], }, ]; diff --git a/frontend-web/src/core/strategy/external-links.ts b/frontend-web/src/core/strategy/external-links.ts new file mode 100644 index 00000000..2f9fd1fd --- /dev/null +++ b/frontend-web/src/core/strategy/external-links.ts @@ -0,0 +1,38 @@ +/** Strategy 模块外部 iframe / 嵌入页链接(来自 Vite 环境变量) */ + +function trimTrailingSlash(url: string): string { + return url.replace(/\/+$/, ""); +} + +function readEnv(key: string): string { + const value = import.meta.env[key]; + return typeof value === "string" ? value.trim() : ""; +} + +/** B2 网络 xwt 资源管理 iframe 基础地址 */ +export function getB2ActorBaseUrl(): string { + return trimTrailingSlash(readEnv("VITE_AIPI_B2ACTOR_URL")); +} + +/** B2 网络 xwt 资源管理 iframe 路径 */ +export function getNetworkActorIframePath(): string { + return readEnv("VITE_AIPI_B2ACTOR_XWT_PATH") || "/fromB/toXWT?isFrame=1"; +} + +/** 网络 xwt 资源管理完整 iframe URL */ +export function getNetworkActorIframeUrl(): string { + const base = getB2ActorBaseUrl(); + const path = getNetworkActorIframePath(); + if (!base) return ""; + return `${base}${path.startsWith("/") ? path : `/${path}`}`; +} + +/** 知识库 iframe 地址换取 API */ +export function getKnowledgeIframeApiUrl(): string { + return readEnv("VITE_AIPI_KNOWLEDGE_IFRAME_API_URL"); +} + +/** 知识库 iframe 皮肤参数 */ +export function getKnowledgeIframeSkin(): string { + return readEnv("VITE_AIPI_KNOWLEDGE_IFRAME_SKIN") || "red"; +} diff --git a/frontend-web/src/main.tsx b/frontend-web/src/main.tsx index 1bdda945..924e3e76 100644 --- a/frontend-web/src/main.tsx +++ b/frontend-web/src/main.tsx @@ -1,4 +1,5 @@ import "./styles/globals.css"; +import "tdesign-react/es/style/index.css"; import "katex/dist/katex.min.css"; import React from "react"; diff --git a/frontend-web/src/pages/StrategyRoutes.tsx b/frontend-web/src/pages/StrategyRoutes.tsx index 3c10efce..8e9781c9 100644 --- a/frontend-web/src/pages/StrategyRoutes.tsx +++ b/frontend-web/src/pages/StrategyRoutes.tsx @@ -5,7 +5,7 @@ import { getStoredAuth } from "@/core/auth"; import { RouteBaseProvider } from "@/core/route-base"; import { SidebarProvider } from "@/components/ui/sidebar"; -import GeneralQA from "@/strategy-components/components/qa/GeneralQA"; +import GeneralQA from "@/strategy-components/components/chat-qa/GeneralQA"; import { ChatRuntime } from "./WorkspaceRoutes"; import AgentsPage from "./AgentsPage"; import ChatsPage from "./ChatsPage"; @@ -37,6 +37,8 @@ import XXTyPage from "@/strategy-components/components/task-components/XXTy"; import SentimentAnalyzes from "@/strategy-components/components/task-components/SentimentAnalyzes"; import TaskAnalyzes from "@/strategy-components/components/task-components/TaskAnalyzes"; import { ActionAnalyzes } from "@/strategy-components/components/task-components/ActionAnalyzes"; +import NetworkActorResourceManagement from "@/strategy-components/components/resource-management/NetworkActorResourceManagement"; +import KnowledgeBaseResourceManagement from "@/strategy-components/components/resource-management/KnowledgeBaseResourceManagement"; export default function StrategyRoutes() { return ( @@ -48,6 +50,16 @@ export default function StrategyRoutes() { {/* 问答中心 */} } /> + + } + /> {/* 任务管理 */} }> {/* XK任务 */} @@ -155,6 +167,21 @@ export default function StrategyRoutes() { } /> + {/* 资源管理 */} + } + /> + } + /> + + } + /> {/* 轻应用 */} } /> } /> diff --git a/frontend-web/src/strategy-components/components/qa/GeneralQA.mock.ts b/frontend-web/src/strategy-components/components/chat-qa/GeneralQA.mock.ts similarity index 99% rename from frontend-web/src/strategy-components/components/qa/GeneralQA.mock.ts rename to frontend-web/src/strategy-components/components/chat-qa/GeneralQA.mock.ts index e16d54e4..6a590092 100644 --- a/frontend-web/src/strategy-components/components/qa/GeneralQA.mock.ts +++ b/frontend-web/src/strategy-components/components/chat-qa/GeneralQA.mock.ts @@ -1,4 +1,4 @@ -import type { QASingleRagTrace, QAThinkingTrace } from './QACommon'; +import type { QASingleRagTrace, QAThinkingTrace } from '../qa/QACommon'; import type { ComparePane, KnowledgeBaseChunk, Message, QAMode, SourceItem } from './GeneralQA.types'; /** diff --git a/frontend-web/src/strategy-components/components/qa/GeneralQA.tsx b/frontend-web/src/strategy-components/components/chat-qa/GeneralQA.tsx similarity index 99% rename from frontend-web/src/strategy-components/components/qa/GeneralQA.tsx rename to frontend-web/src/strategy-components/components/chat-qa/GeneralQA.tsx index e2542628..20557ba6 100644 --- a/frontend-web/src/strategy-components/components/qa/GeneralQA.tsx +++ b/frontend-web/src/strategy-components/components/chat-qa/GeneralQA.tsx @@ -11,7 +11,7 @@ import { } from 'lucide-react'; import { Dialog, Select, Slider } from 'tdesign-react'; import { useTheme } from '@/contexts/ThemeContext'; -import { ChatMessage, EmptyChatState, QAAvatar, QAComposer, QASingleRagTrace, QAThinkingRound, QAThinkingTrace, RetrievalThinkingTrace, SingleRagAnswer, TypingIndicator } from './QACommon'; +import { ChatMessage, EmptyChatState, QAAvatar, QAComposer, QASingleRagTrace, QAThinkingRound, QAThinkingTrace, RetrievalThinkingTrace, SingleRagAnswer, TypingIndicator } from '../qa/QACommon'; import GeneralQAHeader from './GeneralQAHeader'; import GeneralQAConfigSidebar from './GeneralQAConfigSidebar'; import type { ComparePane, CompareResult, KnowledgeBaseChunk, Message, QAMode, SourceItem, ToolCallData, ViewMode } from './GeneralQA.types'; @@ -26,13 +26,21 @@ import { parseSingleRagStream, } from './GeneralQA.mock'; +type GeneralQAProps = { + pageTitle?: string; + pageSubtitle?: string; + initialMode?: 'general' | 'new'; +}; + /** - * 通用问答组件 + * 通用/专家问答组件 * 支持单轮RAG、多轮RAG、深度检索及结果对比功能 - * @param onNavigate - 页面导航函数 - * @param initialMode - 初始模式(可选) */ -const GeneralQA: React.FC = () => { +const GeneralQA: React.FC = ({ + pageTitle = '通用问答', + pageSubtitle = '支持单轮RAG、多轮RAG、深度检索及结果对比', + initialMode: _initialMode = 'general', +}) => { const { theme } = useTheme(); const isDark = theme === 'dark'; @@ -1390,10 +1398,6 @@ const GeneralQA: React.FC = () => { runAfterGenerationConfirm(() => setViewMode(mode)); }; - const handleSafeNavigate = (page: string) => { - // runAfterGenerationConfirm(() => onNavigate(page)); - }; - const handleSafeReset = () => { runAfterGenerationConfirm(() => { setMessages([]); @@ -1633,7 +1637,8 @@ const GeneralQA: React.FC = () => { isDark={isDark} viewMode={viewMode} setViewMode={handleSafeViewModeChange} - onNavigate={handleSafeNavigate} + pageTitle={pageTitle} + pageSubtitle={pageSubtitle} /> {/* 主体内容区 */} diff --git a/frontend-web/src/strategy-components/components/qa/GeneralQA.types.ts b/frontend-web/src/strategy-components/components/chat-qa/GeneralQA.types.ts similarity index 95% rename from frontend-web/src/strategy-components/components/qa/GeneralQA.types.ts rename to frontend-web/src/strategy-components/components/chat-qa/GeneralQA.types.ts index 2e36a2ea..811bbf7a 100644 --- a/frontend-web/src/strategy-components/components/qa/GeneralQA.types.ts +++ b/frontend-web/src/strategy-components/components/chat-qa/GeneralQA.types.ts @@ -1,4 +1,4 @@ -import type { QASingleRagTrace, QAThinkingTrace } from './QACommon'; +import type { QASingleRagTrace, QAThinkingTrace } from '../qa/QACommon'; export type QAMode = 'single-round' | 'multi-round' | 'deep-search'; export type ViewMode = 'single' | 'compare'; diff --git a/frontend-web/src/strategy-components/components/qa/GeneralQAConfigSidebar.tsx b/frontend-web/src/strategy-components/components/chat-qa/GeneralQAConfigSidebar.tsx similarity index 100% rename from frontend-web/src/strategy-components/components/qa/GeneralQAConfigSidebar.tsx rename to frontend-web/src/strategy-components/components/chat-qa/GeneralQAConfigSidebar.tsx diff --git a/frontend-web/src/strategy-components/components/qa/GeneralQAHeader.tsx b/frontend-web/src/strategy-components/components/chat-qa/GeneralQAHeader.tsx similarity index 90% rename from frontend-web/src/strategy-components/components/qa/GeneralQAHeader.tsx rename to frontend-web/src/strategy-components/components/chat-qa/GeneralQAHeader.tsx index 7a94364f..67a8f405 100644 --- a/frontend-web/src/strategy-components/components/qa/GeneralQAHeader.tsx +++ b/frontend-web/src/strategy-components/components/chat-qa/GeneralQAHeader.tsx @@ -11,6 +11,8 @@ type Props = { isDark: boolean; // 当前是否为暗黑主题,用于样式适配 viewMode: ViewMode; // 当前视图模式:'single' 单一模式 或 'compare' 对比模式 setViewMode: (mode: ViewMode) => void; // 设置视图模式回调函数 + pageTitle?: string; + pageSubtitle?: string; }; /** @@ -20,15 +22,21 @@ type Props = { * 这样拆分后,顶部导航的样式和交互不会和中间问答流处理逻辑混在一起,后续如果要新增 * “保存模板”“导出记录”等入口,也可以只改这个文件。 */ -export default function GeneralQAHeader({ isDark, viewMode, setViewMode }: Props): JSX.Element { +export default function GeneralQAHeader({ + isDark, + viewMode, + setViewMode, + pageTitle = '通用问答', + pageSubtitle = '支持单轮RAG、多轮RAG、深度检索及结果对比', +}: Props): JSX.Element { return (

- 通用问答 + {pageTitle}

- 支持单轮RAG、多轮RAG、深度检索及结果对比 + {pageSubtitle}
diff --git a/frontend-web/src/strategy-components/components/resource-management/KnowledgeBaseResourceManagement.tsx b/frontend-web/src/strategy-components/components/resource-management/KnowledgeBaseResourceManagement.tsx new file mode 100644 index 00000000..10b4d741 --- /dev/null +++ b/frontend-web/src/strategy-components/components/resource-management/KnowledgeBaseResourceManagement.tsx @@ -0,0 +1,50 @@ +import React, { useEffect, useState } from "react"; + +import { + getKnowledgeIframeApiUrl, + getKnowledgeIframeSkin, +} from "@/core/strategy/external-links"; +import { requestCrudService } from "@/service/request-axios-service"; +import "@/strategy-components/components/task-components/css/strategy-data.css"; + +const service = requestCrudService; + +const KnowledgeBaseResourceManagement: React.FC = () => { + const [iframeUrl, setIframeUrl] = useState(""); + + useEffect(() => { + const initIframeUrl = async () => { + const apiUrl = getKnowledgeIframeApiUrl(); + if (!apiUrl) return; + + const jsonStr = localStorage.getItem("userInfo"); + if (!jsonStr) return; + + try { + const userInfo = JSON.parse(jsonStr); + const token = userInfo.accessToken; + if (!token) return; + + const res = (await service.post(apiUrl, { + token, + skin: getKnowledgeIframeSkin(), + })) as { iframeUrl?: string }; + if (res?.iframeUrl) { + setIframeUrl(res.iframeUrl); + } + } catch (error) { + console.error("Failed to load knowledge iframe url:", error); + } + }; + + void initIframeUrl(); + }, []); + + return ( +
+