TocTree.tsx 4.6 KB

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