|
|
@@ -1,209 +1,209 @@
|
|
|
import React, { useState } from "react";
|
|
|
+import { useEffect } from "react";
|
|
|
import { Tree } from "antd";
|
|
|
import type { DataNode, TreeProps } from "antd/es/tree";
|
|
|
-import { useEffect } from "react";
|
|
|
|
|
|
type TreeNodeData = {
|
|
|
- key: string;
|
|
|
- title: string;
|
|
|
- children: TreeNodeData[];
|
|
|
- level: number;
|
|
|
+ key: string;
|
|
|
+ title: string;
|
|
|
+ children: TreeNodeData[];
|
|
|
+ level: number;
|
|
|
};
|
|
|
export type ListNodeData = {
|
|
|
- key: string;
|
|
|
- title: string;
|
|
|
- level: number;
|
|
|
+ key: string;
|
|
|
+ title: string;
|
|
|
+ level: number;
|
|
|
};
|
|
|
|
|
|
var tocActivePath: TreeNodeData[] = [];
|
|
|
function tocGetTreeData(articles: ListNodeData[], active = "") {
|
|
|
- let treeData = [];
|
|
|
-
|
|
|
- let treeParents = [];
|
|
|
- let rootNode: TreeNodeData = {
|
|
|
- key: "0",
|
|
|
- title: "root",
|
|
|
- level: 0,
|
|
|
- children: [],
|
|
|
- };
|
|
|
- treeData.push(rootNode);
|
|
|
- let lastInsNode: TreeNodeData = rootNode;
|
|
|
-
|
|
|
- let iCurrLevel = 0;
|
|
|
- for (let index = 0; index < articles.length; index++) {
|
|
|
- const element = articles[index];
|
|
|
-
|
|
|
- let newNode: TreeNodeData = {
|
|
|
- key: element.key,
|
|
|
- title: element.title,
|
|
|
- children: [],
|
|
|
- level: element.level,
|
|
|
- };
|
|
|
- /*
|
|
|
+ let treeData = [];
|
|
|
+
|
|
|
+ let treeParents = [];
|
|
|
+ let rootNode: TreeNodeData = {
|
|
|
+ key: "0",
|
|
|
+ title: "root",
|
|
|
+ level: 0,
|
|
|
+ children: [],
|
|
|
+ };
|
|
|
+ treeData.push(rootNode);
|
|
|
+ let lastInsNode: TreeNodeData = rootNode;
|
|
|
+
|
|
|
+ let iCurrLevel = 0;
|
|
|
+ for (let index = 0; index < articles.length; index++) {
|
|
|
+ const element = articles[index];
|
|
|
+
|
|
|
+ let newNode: TreeNodeData = {
|
|
|
+ key: element.key,
|
|
|
+ title: element.title,
|
|
|
+ children: [],
|
|
|
+ level: element.level,
|
|
|
+ };
|
|
|
+ /*
|
|
|
if (active == element.article) {
|
|
|
newNode["extraClasses"] = "active";
|
|
|
}
|
|
|
*/
|
|
|
- if (newNode.level > iCurrLevel) {
|
|
|
- //新的层级比较大,为上一个的子目录
|
|
|
- treeParents.push(lastInsNode);
|
|
|
- lastInsNode.children.push(newNode);
|
|
|
- } else if (newNode.level === iCurrLevel) {
|
|
|
- //目录层级相同,为平级
|
|
|
- treeParents[treeParents.length - 1].children.push(newNode);
|
|
|
- } else {
|
|
|
- // 小于 挂在上一个层级
|
|
|
- while (treeParents.length > 1) {
|
|
|
- treeParents.pop();
|
|
|
- if (treeParents[treeParents.length - 1].level < newNode.level) {
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- treeParents[treeParents.length - 1].children.push(newNode);
|
|
|
- }
|
|
|
- lastInsNode = newNode;
|
|
|
- iCurrLevel = newNode.level;
|
|
|
-
|
|
|
- if (active === element.key) {
|
|
|
- tocActivePath = [];
|
|
|
- for (let index = 1; index < treeParents.length; index++) {
|
|
|
- tocActivePath.push(treeParents[index]);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return treeData[0].children;
|
|
|
+ if (newNode.level > iCurrLevel) {
|
|
|
+ //新的层级比较大,为上一个的子目录
|
|
|
+ treeParents.push(lastInsNode);
|
|
|
+ lastInsNode.children.push(newNode);
|
|
|
+ } else if (newNode.level === iCurrLevel) {
|
|
|
+ //目录层级相同,为平级
|
|
|
+ treeParents[treeParents.length - 1].children.push(newNode);
|
|
|
+ } else {
|
|
|
+ // 小于 挂在上一个层级
|
|
|
+ while (treeParents.length > 1) {
|
|
|
+ treeParents.pop();
|
|
|
+ if (treeParents[treeParents.length - 1].level < newNode.level) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ treeParents[treeParents.length - 1].children.push(newNode);
|
|
|
+ }
|
|
|
+ lastInsNode = newNode;
|
|
|
+ iCurrLevel = newNode.level;
|
|
|
+
|
|
|
+ if (active === element.key) {
|
|
|
+ tocActivePath = [];
|
|
|
+ for (let index = 1; index < treeParents.length; index++) {
|
|
|
+ tocActivePath.push(treeParents[index]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return treeData[0].children;
|
|
|
}
|
|
|
|
|
|
function treeToList(treeNode: TreeNodeData[]): ListNodeData[] {
|
|
|
- let iTocTreeCurrLevel = 1;
|
|
|
-
|
|
|
- let arrTocTree: ListNodeData[] = [];
|
|
|
-
|
|
|
- for (const iterator of treeNode) {
|
|
|
- getTreeNodeData(iterator);
|
|
|
- }
|
|
|
-
|
|
|
- function getTreeNodeData(node: TreeNodeData) {
|
|
|
- let children = 0;
|
|
|
- if (typeof node.children != "undefined") {
|
|
|
- children = node.children.length;
|
|
|
- }
|
|
|
- arrTocTree.push({
|
|
|
- key: node.key,
|
|
|
- title: node.title,
|
|
|
- level: iTocTreeCurrLevel,
|
|
|
- });
|
|
|
- if (children > 0) {
|
|
|
- iTocTreeCurrLevel++;
|
|
|
- for (const iterator of node.children) {
|
|
|
- getTreeNodeData(iterator);
|
|
|
- }
|
|
|
- iTocTreeCurrLevel--;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return arrTocTree;
|
|
|
+ let iTocTreeCurrLevel = 1;
|
|
|
+
|
|
|
+ let arrTocTree: ListNodeData[] = [];
|
|
|
+
|
|
|
+ for (const iterator of treeNode) {
|
|
|
+ getTreeNodeData(iterator);
|
|
|
+ }
|
|
|
+
|
|
|
+ function getTreeNodeData(node: TreeNodeData) {
|
|
|
+ let children = 0;
|
|
|
+ if (typeof node.children != "undefined") {
|
|
|
+ children = node.children.length;
|
|
|
+ }
|
|
|
+ arrTocTree.push({
|
|
|
+ key: node.key,
|
|
|
+ title: node.title,
|
|
|
+ level: iTocTreeCurrLevel,
|
|
|
+ });
|
|
|
+ if (children > 0) {
|
|
|
+ iTocTreeCurrLevel++;
|
|
|
+ for (const iterator of node.children) {
|
|
|
+ getTreeNodeData(iterator);
|
|
|
+ }
|
|
|
+ iTocTreeCurrLevel--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return arrTocTree;
|
|
|
}
|
|
|
interface IWidgetEditableTree {
|
|
|
- treeData: ListNodeData[];
|
|
|
- onChange?: Function;
|
|
|
+ treeData: ListNodeData[];
|
|
|
+ onChange?: Function;
|
|
|
}
|
|
|
const Widget = (prop: IWidgetEditableTree) => {
|
|
|
- const data = tocGetTreeData(prop.treeData);
|
|
|
- console.log("treedata", data);
|
|
|
- const [gData, setGData] = useState(data);
|
|
|
- useEffect(() => {
|
|
|
- const data = tocGetTreeData(prop.treeData);
|
|
|
- setGData(data);
|
|
|
- }, [prop]);
|
|
|
-
|
|
|
- const onDragEnter: TreeProps["onDragEnter"] = (info) => {
|
|
|
- console.log(info);
|
|
|
- // expandedKeys 需要受控时设置
|
|
|
- // setExpandedKeys(info.expandedKeys)
|
|
|
- };
|
|
|
-
|
|
|
- const onDrop: TreeProps["onDrop"] = (info) => {
|
|
|
- console.log(info);
|
|
|
- const dropKey = info.node.key;
|
|
|
- const dragKey = info.dragNode.key;
|
|
|
- const dropPos = info.node.pos.split("-");
|
|
|
- const dropPosition =
|
|
|
- info.dropPosition - Number(dropPos[dropPos.length - 1]);
|
|
|
-
|
|
|
- const loop = (
|
|
|
- data: DataNode[],
|
|
|
- key: React.Key,
|
|
|
- callback: (node: DataNode, i: number, data: DataNode[]) => void
|
|
|
- ) => {
|
|
|
- for (let i = 0; i < data.length; i++) {
|
|
|
- if (data[i].key === key) {
|
|
|
- return callback(data[i], i, data);
|
|
|
- }
|
|
|
- if (data[i].children) {
|
|
|
- loop(data[i].children!, key, callback);
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
- const data = [...gData];
|
|
|
-
|
|
|
- // Find dragObject
|
|
|
- let dragObj: DataNode;
|
|
|
- loop(data, dragKey, (item, index, arr) => {
|
|
|
- arr.splice(index, 1);
|
|
|
- dragObj = item;
|
|
|
- });
|
|
|
-
|
|
|
- if (!info.dropToGap) {
|
|
|
- // Drop on the content
|
|
|
- loop(data, dropKey, (item) => {
|
|
|
- item.children = item.children || [];
|
|
|
- // where to insert 示例添加到头部,可以是随意位置
|
|
|
- item.children.unshift(dragObj);
|
|
|
- });
|
|
|
- } else if (
|
|
|
- ((info.node as any).props.children || []).length > 0 && // Has children
|
|
|
- (info.node as any).props.expanded && // Is expanded
|
|
|
- dropPosition === 1 // On the bottom gap
|
|
|
- ) {
|
|
|
- loop(data, dropKey, (item) => {
|
|
|
- item.children = item.children || [];
|
|
|
- // where to insert 示例添加到头部,可以是随意位置
|
|
|
- item.children.unshift(dragObj);
|
|
|
- // in previous version, we use item.children.push(dragObj) to insert the
|
|
|
- // item to the tail of the children
|
|
|
- });
|
|
|
- } else {
|
|
|
- let ar: DataNode[] = [];
|
|
|
- let i: number;
|
|
|
- loop(data, dropKey, (_item, index, arr) => {
|
|
|
- ar = arr;
|
|
|
- i = index;
|
|
|
- });
|
|
|
- if (dropPosition === -1) {
|
|
|
- ar.splice(i!, 0, dragObj!);
|
|
|
- } else {
|
|
|
- ar.splice(i! + 1, 0, dragObj!);
|
|
|
- }
|
|
|
- }
|
|
|
- setGData(data);
|
|
|
- if (typeof prop.onChange !== "undefined") {
|
|
|
- prop.onChange(treeToList(data));
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- return (
|
|
|
- <>
|
|
|
- <Tree
|
|
|
- rootClassName="draggable-tree"
|
|
|
- draggable
|
|
|
- blockNode
|
|
|
- onDragEnter={onDragEnter}
|
|
|
- onDrop={onDrop}
|
|
|
- treeData={gData}
|
|
|
- />
|
|
|
- </>
|
|
|
- );
|
|
|
+ const data = tocGetTreeData(prop.treeData);
|
|
|
+ console.log("treedata", data);
|
|
|
+ const [gData, setGData] = useState(data);
|
|
|
+ useEffect(() => {
|
|
|
+ const data = tocGetTreeData(prop.treeData);
|
|
|
+ setGData(data);
|
|
|
+ }, [prop]);
|
|
|
+
|
|
|
+ const onDragEnter: TreeProps["onDragEnter"] = (info) => {
|
|
|
+ console.log(info);
|
|
|
+ // expandedKeys 需要受控时设置
|
|
|
+ // setExpandedKeys(info.expandedKeys)
|
|
|
+ };
|
|
|
+
|
|
|
+ const onDrop: TreeProps["onDrop"] = (info) => {
|
|
|
+ console.log(info);
|
|
|
+ const dropKey = info.node.key;
|
|
|
+ const dragKey = info.dragNode.key;
|
|
|
+ const dropPos = info.node.pos.split("-");
|
|
|
+ const dropPosition =
|
|
|
+ info.dropPosition - Number(dropPos[dropPos.length - 1]);
|
|
|
+
|
|
|
+ const loop = (
|
|
|
+ data: DataNode[],
|
|
|
+ key: React.Key,
|
|
|
+ callback: (node: DataNode, i: number, data: DataNode[]) => void
|
|
|
+ ) => {
|
|
|
+ for (let i = 0; i < data.length; i++) {
|
|
|
+ if (data[i].key === key) {
|
|
|
+ return callback(data[i], i, data);
|
|
|
+ }
|
|
|
+ if (data[i].children) {
|
|
|
+ loop(data[i].children!, key, callback);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const data = [...gData];
|
|
|
+
|
|
|
+ // Find dragObject
|
|
|
+ let dragObj: DataNode;
|
|
|
+ loop(data, dragKey, (item, index, arr) => {
|
|
|
+ arr.splice(index, 1);
|
|
|
+ dragObj = item;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!info.dropToGap) {
|
|
|
+ // Drop on the content
|
|
|
+ loop(data, dropKey, (item) => {
|
|
|
+ item.children = item.children || [];
|
|
|
+ // where to insert 示例添加到头部,可以是随意位置
|
|
|
+ item.children.unshift(dragObj);
|
|
|
+ });
|
|
|
+ } else if (
|
|
|
+ ((info.node as any).props.children || []).length > 0 && // Has children
|
|
|
+ (info.node as any).props.expanded && // Is expanded
|
|
|
+ dropPosition === 1 // On the bottom gap
|
|
|
+ ) {
|
|
|
+ loop(data, dropKey, (item) => {
|
|
|
+ item.children = item.children || [];
|
|
|
+ // where to insert 示例添加到头部,可以是随意位置
|
|
|
+ item.children.unshift(dragObj);
|
|
|
+ // in previous version, we use item.children.push(dragObj) to insert the
|
|
|
+ // item to the tail of the children
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ let ar: DataNode[] = [];
|
|
|
+ let i: number;
|
|
|
+ loop(data, dropKey, (_item, index, arr) => {
|
|
|
+ ar = arr;
|
|
|
+ i = index;
|
|
|
+ });
|
|
|
+ if (dropPosition === -1) {
|
|
|
+ ar.splice(i!, 0, dragObj!);
|
|
|
+ } else {
|
|
|
+ ar.splice(i! + 1, 0, dragObj!);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ setGData(data);
|
|
|
+ if (typeof prop.onChange !== "undefined") {
|
|
|
+ prop.onChange(treeToList(data));
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <Tree
|
|
|
+ rootClassName="draggable-tree"
|
|
|
+ draggable
|
|
|
+ blockNode
|
|
|
+ onDragEnter={onDragEnter}
|
|
|
+ onDrop={onDrop}
|
|
|
+ treeData={gData}
|
|
|
+ />
|
|
|
+ </>
|
|
|
+ );
|
|
|
};
|
|
|
|
|
|
export default Widget;
|