TocTree.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import { Tree, Typography } from "antd";
  2. import { useEffect, useState } from "react";
  3. import type { ListNodeData } from "./EditableTree";
  4. import PaliText from "../template/Wbw/PaliText";
  5. import { Key } from "antd/lib/table/interface";
  6. const { Text } = Typography;
  7. export interface TreeNodeData {
  8. key: string;
  9. title: string | React.ReactNode;
  10. children?: TreeNodeData[];
  11. level: number;
  12. deletedAt?: string;
  13. }
  14. function tocGetTreeData(
  15. listData: ListNodeData[],
  16. active = ""
  17. ): TreeNodeData[] | undefined {
  18. let treeData: TreeNodeData[] = [];
  19. let tocActivePath: TreeNodeData[] = [];
  20. let treeParents = [];
  21. let rootNode: TreeNodeData = {
  22. key: "0",
  23. title: "root",
  24. level: 0,
  25. children: [],
  26. };
  27. treeData.push(rootNode);
  28. let lastInsNode: TreeNodeData = rootNode;
  29. let iCurrLevel = 0;
  30. for (let index = 0; index < listData.length; index++) {
  31. const element = listData[index];
  32. let newNode: TreeNodeData = {
  33. key: element.key,
  34. title: element.title,
  35. level: element.level,
  36. deletedAt: element.deletedAt,
  37. };
  38. if (newNode.level > iCurrLevel) {
  39. //新的层级比较大,为上一个的子目录
  40. treeParents.push(lastInsNode);
  41. if (typeof lastInsNode.children === "undefined") {
  42. lastInsNode.children = [];
  43. }
  44. lastInsNode.children.push(newNode);
  45. } else if (newNode.level === iCurrLevel) {
  46. //目录层级相同,为平级
  47. const parentNode = treeParents[treeParents.length - 1];
  48. if (typeof parentNode !== "undefined") {
  49. if (typeof parentNode.children === "undefined") {
  50. parentNode.children = [];
  51. }
  52. parentNode.children.push(newNode);
  53. }
  54. } else {
  55. // 小于 挂在上一个层级
  56. while (treeParents.length > 1) {
  57. treeParents.pop();
  58. if (treeParents[treeParents.length - 1].level < newNode.level) {
  59. break;
  60. }
  61. }
  62. const parentNode = treeParents[treeParents.length - 1];
  63. if (typeof parentNode !== "undefined") {
  64. if (typeof parentNode.children === "undefined") {
  65. parentNode.children = [];
  66. }
  67. parentNode.children.push(newNode);
  68. }
  69. }
  70. lastInsNode = newNode;
  71. iCurrLevel = newNode.level;
  72. if (active === element.key) {
  73. tocActivePath = [];
  74. for (let index = 1; index < treeParents.length; index++) {
  75. //treeParents[index]["expanded"] = true;
  76. tocActivePath.push(treeParents[index]);
  77. }
  78. }
  79. }
  80. return treeData[0].children;
  81. }
  82. interface IWidgetTocTree {
  83. treeData?: ListNodeData[];
  84. expandedKeys?: Key[];
  85. selectedKeys?: Key[];
  86. onSelect?: Function;
  87. }
  88. const TocTreeWidget = ({
  89. treeData,
  90. expandedKeys,
  91. selectedKeys,
  92. onSelect,
  93. }: IWidgetTocTree) => {
  94. const [tree, setTree] = useState<TreeNodeData[]>();
  95. const [expanded, setExpanded] = useState<Key[]>();
  96. const [selected, setSelected] = useState<Key[]>();
  97. useEffect(() => {
  98. console.log("new tree data", treeData);
  99. if (treeData && treeData.length > 0) {
  100. const data = tocGetTreeData(treeData);
  101. setTree(data);
  102. console.log("create tree", treeData.length);
  103. } else {
  104. setTree([]);
  105. }
  106. }, [treeData]);
  107. useEffect(() => setSelected(selectedKeys), [selectedKeys]);
  108. useEffect(() => setExpanded(expandedKeys), [expandedKeys]);
  109. return (
  110. <Tree
  111. treeData={tree}
  112. expandedKeys={expanded}
  113. selectedKeys={selected}
  114. onExpand={(expandedKeys: Key[]) => {
  115. setExpanded(expandedKeys);
  116. }}
  117. onSelect={(selectedKeys: Key[]) => {
  118. setSelected(selectedKeys);
  119. if (typeof onSelect !== "undefined") {
  120. onSelect(selectedKeys);
  121. }
  122. }}
  123. blockNode
  124. titleRender={(node: TreeNodeData) => {
  125. const currNode =
  126. typeof node.title === "string" ? (
  127. node.title === "" ? (
  128. "[unnamed]"
  129. ) : (
  130. <PaliText text={node.title} />
  131. )
  132. ) : (
  133. <>{node.title}</>
  134. );
  135. return node.deletedAt ? (
  136. <Text delete disabled>
  137. {currNode}
  138. </Text>
  139. ) : (
  140. <>{currNode}</>
  141. );
  142. }}
  143. />
  144. );
  145. };
  146. export default TocTreeWidget;