0.1.07 文件树拖拽与多思维导图
This commit is contained in:
@@ -24,22 +24,15 @@ import {
|
||||
} from "./mindmapOptions";
|
||||
import iconConfig from "./mindmapIconConfig";
|
||||
import imageConfig from "./mindmapImageConfig";
|
||||
import { sidebarTitles, type SidebarPanel } from "./mindmapSidebarConfig";
|
||||
import { sidebarTitles, type SidebarPanel } from "./mindmapSidebarConfig";
|
||||
import type { MindMapNode } from "./mindmapTypes";
|
||||
// 避免 SSR 阶段触发浏览器依赖,改为运行时动态引入
|
||||
// @ts-expect-error 第三方库缺少类型定义
|
||||
const loadIconModules = async () => {
|
||||
const { nodeIconList } = await import("simple-mind-map/src/svg/icons.js");
|
||||
const { mergerIconList } = await import("simple-mind-map/src/utils/index.js");
|
||||
return { nodeIconList, mergerIconList };
|
||||
};
|
||||
|
||||
type MindMapNode = {
|
||||
getStyle: (prop: string, checkRoot?: boolean) => any;
|
||||
setStyle: (prop: string, value: any) => void;
|
||||
setIcon: (icons: string[]) => void;
|
||||
getData: (key: string) => any;
|
||||
};
|
||||
|
||||
type SidebarProps = {
|
||||
mindmap: any;
|
||||
activeNodes: MindMapNode[];
|
||||
@@ -118,12 +111,12 @@ const StylePanel = ({ activeNodes }: { activeNodes: MindMapNode[] }) => {
|
||||
}
|
||||
}, [activeNodes]);
|
||||
|
||||
const updateStyle = (prop: string, value: any) => {
|
||||
setStyle((prev) => ({ ...prev, [prop]: value }));
|
||||
activeNodes.forEach((node) => {
|
||||
node.setStyle(prop, value);
|
||||
});
|
||||
};
|
||||
const updateStyle = (prop: string, value: any) => {
|
||||
setStyle((prev) => ({ ...prev, [prop]: value }));
|
||||
activeNodes.forEach((node) => {
|
||||
node.setStyle?.(prop, value);
|
||||
});
|
||||
};
|
||||
|
||||
if (activeNodes.length === 0) {
|
||||
return (
|
||||
@@ -446,26 +439,27 @@ const IconPanel = ({ activeNodes }: { activeNodes: MindMapNode[] }) => {
|
||||
const addIcon = (type: string, name: string) => {
|
||||
const key = `${type}_${name}`;
|
||||
activeNodes.forEach((node) => {
|
||||
const icons = node.getData("icon") || [];
|
||||
const newIcons = icons.filter((i: string) => !i.startsWith(`${type}_`));
|
||||
const rawIcons = node.getData("icon");
|
||||
const icons = Array.isArray(rawIcons) ? (rawIcons as string[]) : [];
|
||||
const newIcons = icons.filter((i) => !i.startsWith(`${type}_`));
|
||||
newIcons.push(key);
|
||||
node.setIcon(newIcons);
|
||||
node.setIcon?.(newIcons);
|
||||
});
|
||||
};
|
||||
|
||||
const removeIcon = (type: string) => {
|
||||
activeNodes.forEach((node) => {
|
||||
const icons = node.getData("icon") || [];
|
||||
const newIcons = icons.filter((i: string) => !i.startsWith(`${type}_`));
|
||||
node.setIcon(newIcons);
|
||||
const rawIcons = node.getData("icon");
|
||||
const icons = Array.isArray(rawIcons) ? (rawIcons as string[]) : [];
|
||||
const newIcons = icons.filter((i) => !i.startsWith(`${type}_`));
|
||||
node.setIcon?.(newIcons);
|
||||
});
|
||||
};
|
||||
|
||||
const setSticker = (img: { url: string; width?: number; height?: number }) => {
|
||||
activeNodes.forEach((node) => {
|
||||
// simple-mind-map 支持 setImage 接收对象,包含 url/width/height
|
||||
// @ts-expect-error 第三方库无类型
|
||||
node.setImage({
|
||||
node.setImage?.({
|
||||
url: img.url,
|
||||
width: img.width || 100,
|
||||
height: img.height || 100,
|
||||
@@ -476,8 +470,7 @@ const IconPanel = ({ activeNodes }: { activeNodes: MindMapNode[] }) => {
|
||||
const clearSticker = () => {
|
||||
activeNodes.forEach((node) => {
|
||||
// 传入 null 以清除贴纸
|
||||
// @ts-expect-error 第三方库无类型
|
||||
node.setImage(null);
|
||||
node.setImage?.(null);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -511,7 +504,7 @@ const IconPanel = ({ activeNodes }: { activeNodes: MindMapNode[] }) => {
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{group.list.map((item) => (
|
||||
{group.list.map((item: any) => (
|
||||
<button
|
||||
key={`${group.type}-${item.name}`}
|
||||
onClick={() => addIcon(group.type, item.name)}
|
||||
@@ -521,7 +514,6 @@ const IconPanel = ({ activeNodes }: { activeNodes: MindMapNode[] }) => {
|
||||
typeof item.icon === "string" && item.icon.trim().startsWith("<svg") ? (
|
||||
<span
|
||||
className="inline-flex h-6 w-6 items-center justify-center overflow-hidden"
|
||||
// @ts-expect-error: dangerouslySetInnerHTML 用于复用官方 SVG 片段
|
||||
dangerouslySetInnerHTML={{ __html: item.icon }}
|
||||
/>
|
||||
) : (
|
||||
@@ -599,16 +591,13 @@ const OutlinePanel = ({ mindmap }: { mindmap: any }) => {
|
||||
if (!node || !r) return;
|
||||
// 仅通过已有方法触发激活,避免直接改 renderer 属性
|
||||
if (typeof r.clearActiveNodeList === "function") {
|
||||
// @ts-expect-error 第三方库缺少类型
|
||||
r.clearActiveNodeList();
|
||||
}
|
||||
if (typeof r.addNodeToActiveList === "function") {
|
||||
// @ts-expect-error 第三方库缺少类型
|
||||
r.addNodeToActiveList(node, true);
|
||||
} else {
|
||||
// 兜底:仍保留最小副作用写入
|
||||
try {
|
||||
// @ts-expect-error 第三方库 renderer 缺类型
|
||||
r?.setActiveNode?.(node);
|
||||
} catch {
|
||||
// 最后兜底:不再直接改引用,避免 lint 报错
|
||||
@@ -1215,7 +1204,6 @@ const AiPanel = ({ mindmap, activeNodes }: { mindmap: any; activeNodes: MindMapN
|
||||
try {
|
||||
const r = mindmap?.renderer;
|
||||
if (r && Array.isArray((r as any).renderCallbackList)) {
|
||||
// @ts-expect-error 第三方库内部字段
|
||||
r.renderCallbackList = (r.renderCallbackList as any[]).filter(
|
||||
(fn) => typeof fn === "function",
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user