Merge remote-tracking branch 'origin/master' into ji
# Conflicts: # frontend-web/src/core/page-layout/sidebar-menu.ts # frontend-web/src/core/system-settings/api.ts # frontend-web/src/core/system-settings/hooks.ts # frontend-web/src/strategy-components/Header.tsx # offline-backend-20260512/backend/CLAUDE.md # offline-backend-20260512/backend/app/gateway/routers/system_settings.py # offline-backend-20260512/backend/packages/harness/deerflow/config/system_settings.py # offline-backend-20260512/backend/scripts/sql/column_additions_mysql.sql
This commit is contained in:
commit
b380575f16
103 files changed
+5915
-859
No files matched your search
@@ -0,0 +1,175 @@
|
||||
/**
|
||||
* 外部系统跳转登录时的「任务深链」:登录 URL 带 ``taskId`` + ``goPath`` 时,
|
||||
* 拉取任务详情并据 goPath 把用户直接送到对应的智能体问答 / 多智能体会商页。
|
||||
*
|
||||
* 流程:
|
||||
* 1. 调 consumer 接口 ``GET {VITE_AIPI_CONSUMER_URL}/taskAnalysSearch/cop-task-detail?taskId=``,
|
||||
* 请求头 ``Authorization: Bearer admin``(由 service 拦截器统一注入)。
|
||||
* 2. 把返回的 data(id/overview/taskDirection/taskName/taskContent)整包存到 sessionStorage。
|
||||
* 3. 按 goPath 解析出业务码 + 模式:
|
||||
* - ``3qfx`` / ``rwfx`` / ``xdfx`` → 单智能体问答(用「配置管理」里该业务配置的智能体)
|
||||
* - ``3qfx-A`` / ``rwfx-A`` / ``xdfx-A`` → 多智能体会商(用该业务配置的业务链条)
|
||||
* 携带 taskName / taskContent 作为开场信息。
|
||||
*
|
||||
* 业务码映射与「配置管理」(`/api/business-mapping`) 一致:
|
||||
* 3Q=三情分析(3QFX)、6BF=任务分析(任务FX)、7BF=行动分析(XDFX)。
|
||||
*/
|
||||
|
||||
import { requestCrudService } from "@/service/request-axios-service";
|
||||
import { listBusinessMappings } from "@/strategy-components/api/business-mapping";
|
||||
|
||||
/** consumer 接口返回的任务详情(data 字段)。 */
|
||||
export interface CopTaskDetail {
|
||||
id: string | number | null;
|
||||
overview: string;
|
||||
taskDirection: string;
|
||||
taskName: string;
|
||||
taskContent: string;
|
||||
}
|
||||
|
||||
/** 任务详情整包暂存的 sessionStorage key(目标页/后续可读取)。 */
|
||||
export const COP_TASK_DETAIL_STORAGE_KEY = "login.copTaskDetail";
|
||||
|
||||
/** goPath 基础码 → 业务码(配置管理 businessCode)。 */
|
||||
const GOPATH_BUSINESS_CODE: Record<string, string> = {
|
||||
"3qfx": "3Q", // 三情分析
|
||||
rwfx: "6BF", // 任务分析(任务FX)
|
||||
xdfx: "7BF", // 行动分析(XDFX)
|
||||
};
|
||||
|
||||
/**
|
||||
* 业务码 → 「任务管理」布局下的路由前缀(与 sidebar-menu.ts 的 COH 中任务菜单路径一致)。
|
||||
* 会商 / 智能体问答都挂在此前缀下,保证侧边栏停留在 任务管理 → COH中任务 → 对应业务 高亮。
|
||||
*/
|
||||
const BUSINESS_TASK_BASE: Record<string, string> = {
|
||||
"3Q": "/page/strategy/task-management/plan-task-sentiment",
|
||||
"6BF": "/page/strategy/task-management/plan-task/plan-task-fx",
|
||||
"7BF": "/page/strategy/task-management/plan-task/plan-task-action",
|
||||
};
|
||||
|
||||
export interface ParsedGoPath {
|
||||
businessCode: string;
|
||||
/** true = 多智能体会商(``-A`` 后缀);false = 单智能体问答。 */
|
||||
roundtable: boolean;
|
||||
}
|
||||
|
||||
/** 解析 goPath(大小写不敏感);``-A`` 后缀表示多智能体会商。无法识别返回 null。 */
|
||||
export function parseGoPath(goPath: string): ParsedGoPath | null {
|
||||
const raw = goPath.trim().toLowerCase();
|
||||
if (!raw) return null;
|
||||
const roundtable = raw.endsWith("-a");
|
||||
const base = roundtable ? raw.slice(0, -2) : raw;
|
||||
const businessCode = GOPATH_BUSINESS_CODE[base];
|
||||
if (!businessCode) return null;
|
||||
return { businessCode, roundtable };
|
||||
}
|
||||
|
||||
function consumerBaseUrl(): string {
|
||||
const value = import.meta.env.VITE_AIPI_CONSUMER_URL;
|
||||
return typeof value === "string" ? value.replace(/\/+$/, "") : "";
|
||||
}
|
||||
|
||||
/** 拉取任务详情;缺少 consumer 地址 / 返回不合法时返回 null。 */
|
||||
export async function fetchCopTaskDetail(taskId: string): Promise<CopTaskDetail | null> {
|
||||
const base = consumerBaseUrl();
|
||||
if (!base || !taskId) return null;
|
||||
// service 拦截器已统一注入 `Authorization: Bearer admin` 并返回 response.data(整包 body)。
|
||||
const body = await requestCrudService.get(`${base}/taskAnalysSearch/cop-task-detail`, { taskId });
|
||||
const data = body && typeof body === "object" ? (body as { data?: unknown }).data : null;
|
||||
if (!data || typeof data !== "object") return null;
|
||||
const d = data as Record<string, unknown>;
|
||||
return {
|
||||
id: (d.id as string | number | null) ?? null,
|
||||
overview: typeof d.overview === "string" ? d.overview : "",
|
||||
taskDirection: typeof d.taskDirection === "string" ? d.taskDirection : "",
|
||||
taskName: typeof d.taskName === "string" ? d.taskName : "",
|
||||
taskContent: typeof d.taskContent === "string" ? d.taskContent : "",
|
||||
};
|
||||
}
|
||||
|
||||
/** 把任务详情整包暂存到 sessionStorage(隐私模式/quota 异常时静默失败)。 */
|
||||
export function persistCopTaskDetail(detail: CopTaskDetail): void {
|
||||
try {
|
||||
sessionStorage.setItem(COP_TASK_DETAIL_STORAGE_KEY, JSON.stringify(detail));
|
||||
} catch {
|
||||
/* noop */
|
||||
}
|
||||
}
|
||||
|
||||
/** 读取暂存的任务详情。 */
|
||||
export function readCopTaskDetail(): CopTaskDetail | null {
|
||||
try {
|
||||
const raw = sessionStorage.getItem(COP_TASK_DETAIL_STORAGE_KEY);
|
||||
return raw ? (JSON.parse(raw) as CopTaskDetail) : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export interface TaskDeeplinkTarget {
|
||||
path: string;
|
||||
/** react-router navigate 的 state(多智能体会商用 roundtablePrefill)。 */
|
||||
state?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/** 用 taskName / taskContent 拼出开场信息文本。 */
|
||||
function buildOpeningText(detail: CopTaskDetail): string {
|
||||
return [
|
||||
detail.taskName ? `任务名称:${detail.taskName}` : "",
|
||||
detail.taskContent ? `任务内容:${detail.taskContent}` : "",
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* 据 goPath + 任务详情解析跳转目标。
|
||||
* - 多智能体会商:返回带 ``roundtablePrefill``(businessCode 让会商页自动选用配置的业务链条)的 state。
|
||||
* - 单智能体问答:解析「配置管理」里该业务配置的智能体;把开场信息写入
|
||||
* ``sessionStorage.pendingAgentMessage``(AgentChatPage 自动发出)。
|
||||
* 无法识别 goPath / 未配置智能体时返回 null(调用方回退到默认首页)。
|
||||
*/
|
||||
export async function resolveTaskDeeplinkTarget(
|
||||
goPath: string,
|
||||
detail: CopTaskDetail,
|
||||
): Promise<TaskDeeplinkTarget | null> {
|
||||
const parsed = parseGoPath(goPath);
|
||||
if (!parsed) return null;
|
||||
const taskBase = BUSINESS_TASK_BASE[parsed.businessCode];
|
||||
if (!taskBase) return null;
|
||||
|
||||
if (parsed.roundtable) {
|
||||
// 多智能体会商:嵌进对应业务的「任务管理」布局;businessCode 让会商页自动选用配置的业务链条。
|
||||
return {
|
||||
path: `${taskBase}/roundtable`,
|
||||
state: {
|
||||
roundtablePrefill: {
|
||||
taskTitle: detail.taskName,
|
||||
taskGoal: detail.taskContent,
|
||||
businessCode: parsed.businessCode,
|
||||
autoStart: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
let agentId: string | null = null;
|
||||
try {
|
||||
const mappings = await listBusinessMappings();
|
||||
agentId = mappings.find((m) => m.businessCode === parsed.businessCode)?.agentId ?? null;
|
||||
} catch {
|
||||
agentId = null;
|
||||
}
|
||||
if (!agentId) return null;
|
||||
|
||||
try {
|
||||
sessionStorage.setItem(
|
||||
"pendingAgentMessage",
|
||||
JSON.stringify({ agentId, text: buildOpeningText(detail) }),
|
||||
);
|
||||
} catch {
|
||||
/* noop */
|
||||
}
|
||||
// 单智能体问答:同样嵌进对应业务的「任务管理」布局。
|
||||
return { path: `${taskBase}/agent/${agentId}/chats/new` };
|
||||
}
|
||||
@@ -44,6 +44,8 @@ export type MenuItem = {
|
||||
label: string;
|
||||
icon: ElementType;
|
||||
path?: string;
|
||||
/** 非 admin 用户使用的路由(菜单对普通用户可见时生效,与简洁模式公开排行榜一致) */
|
||||
userPath?: string;
|
||||
adminOnly?: boolean;
|
||||
children?: MenuItem[];
|
||||
};
|
||||
@@ -51,7 +53,7 @@ export type MenuItem = {
|
||||
export const sidebarMenuItems: MenuItem[] = [
|
||||
{
|
||||
id: "qa-center",
|
||||
label: "问答中心",
|
||||
label: "问答管理",
|
||||
icon: HelpCircle,
|
||||
children: [
|
||||
{ id: "general-qa", label: "通用问答", icon: CircleHelp, path: "/page/workspace/chats/new" },
|
||||
@@ -64,11 +66,11 @@ export const sidebarMenuItems: MenuItem[] = [
|
||||
// { id: "expert-qa", label: "专家问答", icon: Brain, path: "/page/strategy/qa/expert-qa" },
|
||||
{
|
||||
id: "qa-zzjc",
|
||||
label: "zzJC支持",
|
||||
label: "JC支持",
|
||||
icon: Bot,
|
||||
path: "/page/strategy/agents/6bf/chats/new",
|
||||
path: "/page/strategy/qa/zzjc",
|
||||
},
|
||||
{ id: "qa-zzxd", label: "zzXD应用", icon: Layout, path: "/page/strategy/agents/10d69686718349688e58a8790cb61024/chats/new", },
|
||||
{ id: "qa-zzxd", label: "XD应用", icon: Layout, path: "/page/strategy/qa/zzxd" },
|
||||
{ id: "qa-research", label: "课题研究", icon: FileText, path: "/page/canvas/ai-writing" },
|
||||
],
|
||||
},
|
||||
@@ -82,18 +84,18 @@ export const sidebarMenuItems: MenuItem[] = [
|
||||
label: "XK中任务",
|
||||
icon: ClipboardList,
|
||||
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: "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",
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -101,24 +103,24 @@ export const sidebarMenuItems: MenuItem[] = [
|
||||
label: "COH中任务",
|
||||
icon: Activity,
|
||||
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: "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",
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -126,24 +128,24 @@ export const sidebarMenuItems: MenuItem[] = [
|
||||
label: "PG中任务",
|
||||
icon: Gauge,
|
||||
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: "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",
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -151,24 +153,24 @@ export const sidebarMenuItems: MenuItem[] = [
|
||||
label: "TY中任务",
|
||||
icon: Radar,
|
||||
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: "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",
|
||||
// },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -198,6 +200,13 @@ export const sidebarMenuItems: MenuItem[] = [
|
||||
label: "综合管理",
|
||||
icon: Settings,
|
||||
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-business-chain-mapping",
|
||||
@@ -268,12 +277,12 @@ export const sidebarMenuItems: MenuItem[] = [
|
||||
label: "资源管理",
|
||||
icon: Database,
|
||||
children: [
|
||||
{
|
||||
id: "resource-network-xwt",
|
||||
label: "网络xwt资源管理",
|
||||
icon: Network,
|
||||
path: "/page/strategy/resource-management/resource-network-actor",
|
||||
},
|
||||
// {
|
||||
// id: "resource-network-xwt",
|
||||
// label: "网络xwt资源管理",
|
||||
// icon: Network,
|
||||
// path: "/page/strategy/resource-management/resource-network-actor",
|
||||
// },
|
||||
{
|
||||
id: "resource-knowledge-native",
|
||||
label: "问答梳理",
|
||||
@@ -286,12 +295,12 @@ export const sidebarMenuItems: MenuItem[] = [
|
||||
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: "resource-evaluation-index",
|
||||
// label: "作战资源管理",
|
||||
// icon: FileBox,
|
||||
// path: "/page/strategy/resource-management/resource-evaluation-index",
|
||||
// },
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -306,9 +315,9 @@ export const defaultExpandedIds: ReadonlySet<string> = new Set([
|
||||
"comprehensive-management",
|
||||
]);
|
||||
|
||||
/** 该菜单项自身或任意后代的 path 是否等于当前路由 */
|
||||
/** 该菜单项自身或任意后代的 path 是否匹配当前路由(支持子路径,如 /knowledge/:id) */
|
||||
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 item.children?.some((child) => menuItemContainsPath(child, pathname)) ?? false;
|
||||
@@ -316,7 +325,8 @@ export function menuItemContainsPath(item: MenuItem, pathname: string): boolean
|
||||
|
||||
/**
|
||||
* 在「一级 → 二级 → 三级」菜单中,取当前路由所在的「激活二级项」的三级子项。
|
||||
* 浅色侧边栏据此在二级右侧展开三级列;无三级则返回空数组(侧边栏保持窄栏)。
|
||||
* 浅色侧边栏据此在二级右侧展开三级列;深色顶栏据此渲染三级横条。
|
||||
* 全量模式:三级仅一项时不返回(无选择必要,侧边栏保持窄栏 / 不渲染横条)。
|
||||
*/
|
||||
export function getActiveThirdLevelItems(
|
||||
items: MenuItem[],
|
||||
@@ -328,16 +338,23 @@ export function getActiveThirdLevelItems(
|
||||
const activeSecond = secondary.find(
|
||||
(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[] {
|
||||
return items
|
||||
.filter((item) => !item.adminOnly || isAdmin)
|
||||
.map((item) =>
|
||||
item.children
|
||||
? { ...item, children: filterMenuItemsByRole(item.children, isAdmin) }
|
||||
: item,
|
||||
);
|
||||
.map((item) => {
|
||||
const children = item.children
|
||||
? filterMenuItemsByRole(item.children, isAdmin)
|
||||
: undefined;
|
||||
const base = children ? { ...item, children } : item;
|
||||
if (!isAdmin && base.userPath) {
|
||||
const { userPath: _userPath, ...rest } = base;
|
||||
return { ...rest, path: base.userPath };
|
||||
}
|
||||
return base;
|
||||
});
|
||||
}
|
||||
@@ -291,6 +291,45 @@ export async function updateSkillCompressionSettings(
|
||||
return (await response.json()) as SkillCompressionSettings;
|
||||
}
|
||||
|
||||
/** 「按类型聚合」模块(zzJC / zzXD)选中的智能体标签配置(需求 0616 #3/#4)。 */
|
||||
export interface AgentModuleConfig {
|
||||
key: string;
|
||||
tag_ids: string[];
|
||||
}
|
||||
|
||||
export async function loadAgentModuleConfig(
|
||||
key: string,
|
||||
): Promise<AgentModuleConfig> {
|
||||
const response = await apiFetch(
|
||||
`${getBackendBaseURL()}/api/system-settings/agent-modules/${encodeURIComponent(key)}`,
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to load agent module config: ${response.status}`);
|
||||
}
|
||||
return (await response.json()) as AgentModuleConfig;
|
||||
}
|
||||
|
||||
export async function updateAgentModuleConfig(
|
||||
key: string,
|
||||
tagIds: string[],
|
||||
): Promise<AgentModuleConfig> {
|
||||
const response = await apiFetch(
|
||||
`${getBackendBaseURL()}/api/system-settings/agent-modules/${encodeURIComponent(key)}`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ tag_ids: tagIds }),
|
||||
},
|
||||
);
|
||||
if (!response.ok) {
|
||||
const detail = await response
|
||||
.json()
|
||||
.catch(() => ({ detail: "Failed to update agent module config" }));
|
||||
throw new Error(detail.detail ?? "Failed to update agent module config");
|
||||
}
|
||||
return (await response.json()) as AgentModuleConfig;
|
||||
}
|
||||
|
||||
export interface LogSystemSettings {
|
||||
enabled: boolean;
|
||||
url: string;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useLocalSettings } from "@/core/settings";
|
||||
|
||||
import {
|
||||
loadAgentModuleConfig,
|
||||
loadAppearanceSettings,
|
||||
loadCitationDisplaySettings,
|
||||
loadLeaderboardSettings,
|
||||
@@ -10,6 +11,7 @@ import {
|
||||
loadPromptPrefixSettings,
|
||||
loadPublishSquares,
|
||||
loadSkillCompressionSettings,
|
||||
updateAgentModuleConfig,
|
||||
updateAppearanceSettings,
|
||||
updateCitationDisplaySettings,
|
||||
updateLeaderboardSettings,
|
||||
@@ -169,6 +171,29 @@ export function useLayoutMode(): [
|
||||
return [mode, setMode];
|
||||
}
|
||||
|
||||
/** 「按类型聚合」模块(zzJC / zzXD)选中标签配置(需求 0616 #3/#4)。 */
|
||||
const agentModuleKey = (key: string) =>
|
||||
["systemSettings", "agentModule", key] as const;
|
||||
|
||||
export function useAgentModuleConfig(key: string) {
|
||||
return useQuery({
|
||||
queryKey: agentModuleKey(key),
|
||||
queryFn: () => loadAgentModuleConfig(key),
|
||||
staleTime: 60_000,
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpdateAgentModuleConfig(key: string) {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (tagIds: string[]) => updateAgentModuleConfig(key, tagIds),
|
||||
onSuccess: (data) => {
|
||||
queryClient.setQueryData(agentModuleKey(key), data);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useCitationDisplaySettings() {
|
||||
return useQuery({
|
||||
queryKey: CITATION_DISPLAY_KEY,
|
||||
|
||||
Reference in new issue
Block a user