feat: 导航/侧边栏菜单脱敏 + 圆桌会商各步输入框自适应高度
- 菜单标签展示层脱敏:useSidebarMenuItems 直接用 /api/sensitive-words 结果构造脱敏器,覆盖导航栏/三套侧边栏皮肤/三级子导航;菜单管理页用原始树不受影响 - 新增可复用 AutoGrowTextarea(自适应高度多行框),替换圆桌 Step1/2/3 输入框: 多行时自动扩展、到上限框内滚动;Step2 两个单行 input 改多行;统一 Enter 发送/Shift+Enter 换行 - 各步输入框最大展开高度翻倍(Step1 320 / Step2 280 / Step3 224) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
25e4e3dbc9
commit
6746fe4a78
9 files changed
+141
-29
No files matched your search
@@ -12,8 +12,10 @@ import { useLocation } from "react-router-dom";
|
||||
import { Layout } from "lucide-react";
|
||||
|
||||
import { getStoredAuth } from "@/core/auth";
|
||||
import { desensitize, makeDesensitizer } from "@/lib/desensitize";
|
||||
import { useLightApps, type LightApp } from "@/strategy-components/api/light-apps";
|
||||
import { useMenuOverrides } from "@/strategy-components/api/menu-overrides";
|
||||
import { useSensitiveWords, wordsToMap } from "@/strategy-components/api/sensitive-words";
|
||||
|
||||
import { applyMenuOverrides } from "./menu-overrides";
|
||||
import {
|
||||
@@ -58,23 +60,43 @@ export function injectLightApps(items: MenuItem[], apps: LightApp[]): MenuItem[]
|
||||
return walk(items);
|
||||
}
|
||||
|
||||
/** 递归对菜单标签做脱敏(仅改 `label`,path/id/icon 不动,保证高亮与路由不受影响)。 */
|
||||
function desensitizeLabels(items: MenuItem[], fn: (text: string) => string): MenuItem[] {
|
||||
return items.map((node) => ({
|
||||
...node,
|
||||
label: fn(node.label),
|
||||
children: node.children ? desensitizeLabels(node.children, fn) : node.children,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回合并了 iframe 轻应用、套用了后端「菜单覆盖层」(改名/停用/排序/层级)、
|
||||
* 并按 admin 角色过滤后的菜单。
|
||||
* 按 admin 角色过滤、并对标签做**展示层脱敏**后的菜单。
|
||||
*
|
||||
* 管线顺序:静态菜单 → 注入 iframe 轻应用 → 套覆盖层(停用项被剔除)→ 角色过滤。
|
||||
* 管线顺序:静态菜单 → 注入 iframe 轻应用 → 套覆盖层(停用项被剔除)→ 角色过滤 → 标签脱敏。
|
||||
* 覆盖层作用在合并后的整棵树上,所以 iframe 轻应用节点同样可被改名/停用/移层级。
|
||||
*
|
||||
* 脱敏直接用 `/api/sensitive-words` 查询结果构造(后台非空时用其映射,否则回退到内置种子的
|
||||
* 全局 {@link desensitize}),避免依赖 {@link replaceDesensitizeMap} 的 effect 回灌时序。
|
||||
*/
|
||||
export function useSidebarMenuItems(isAdmin: boolean): MenuItem[] {
|
||||
const { data: iframeApps = [] } = useLightApps({ appType: "iframe", enabledOnly: true });
|
||||
const { data: overrides = [] } = useMenuOverrides();
|
||||
const { data: words = [] } = useSensitiveWords();
|
||||
const desensitizeLabel = useMemo(
|
||||
() => (words.length > 0 ? makeDesensitizer(wordsToMap(words)) : desensitize),
|
||||
[words],
|
||||
);
|
||||
return useMemo(
|
||||
() =>
|
||||
filterMenuItemsByRole(
|
||||
applyMenuOverrides(injectLightApps(sidebarMenuItems, iframeApps), overrides),
|
||||
isAdmin,
|
||||
desensitizeLabels(
|
||||
filterMenuItemsByRole(
|
||||
applyMenuOverrides(injectLightApps(sidebarMenuItems, iframeApps), overrides),
|
||||
isAdmin,
|
||||
),
|
||||
desensitizeLabel,
|
||||
),
|
||||
[iframeApps, overrides, isAdmin],
|
||||
[iframeApps, overrides, isAdmin, desensitizeLabel],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user