EditableTocTree.tsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import { Button, message } from "antd";
  2. import { useEffect, useState } from "react";
  3. import { FolderOpenOutlined } from "@ant-design/icons";
  4. import { get as getUiLang } from "../../locales";
  5. import { get, post, put } from "../../request";
  6. import {
  7. IAnthologyDataResponse,
  8. IArticleCreateRequest,
  9. IArticleDataResponse,
  10. IArticleMapAddResponse,
  11. IArticleMapListResponse,
  12. IArticleMapRequest,
  13. IArticleMapUpdateRequest,
  14. IArticleResponse,
  15. } from "../api/Article";
  16. import ArticleListModal from "../article/ArticleListModal";
  17. import EditableTree, {
  18. ListNodeData,
  19. TreeNodeData,
  20. } from "../article/EditableTree";
  21. import ArticleDrawer from "../article/ArticleDrawer";
  22. import { fullUrl, randomString } from "../../utils";
  23. interface IWidget {
  24. anthologyId?: string;
  25. studioName?: string;
  26. myStudioName?: string;
  27. anthology?: IAnthologyDataResponse;
  28. onSelect?: Function;
  29. }
  30. const EditableTocTreeWidget = ({
  31. anthologyId,
  32. anthology,
  33. studioName,
  34. myStudioName,
  35. onSelect,
  36. }: IWidget) => {
  37. const [tocData, setTocData] = useState<ListNodeData[]>([]);
  38. const [addArticle, setAddArticle] = useState<TreeNodeData>();
  39. const [updatedArticle, setUpdatedArticle] = useState<TreeNodeData>();
  40. const [openViewer, setOpenViewer] = useState(false);
  41. const [viewArticle, setViewArticle] = useState<TreeNodeData>();
  42. const save = (data?: ListNodeData[]) => {
  43. console.debug("onSave", data);
  44. if (typeof data === "undefined") {
  45. console.warn("data === undefined");
  46. return;
  47. }
  48. const url = `/v2/article-map/${anthologyId}`;
  49. console.info("url", url);
  50. const newData: IArticleMapRequest[] = data.map((item) => {
  51. let title = "";
  52. if (typeof item.title === "string") {
  53. title = item.title;
  54. }
  55. //TODO 整一个string title
  56. return {
  57. article_id: item.key,
  58. level: item.level,
  59. title: title,
  60. children: item.children,
  61. status: item.status,
  62. deleted_at: item.deletedAt,
  63. };
  64. });
  65. put<IArticleMapUpdateRequest, IArticleMapAddResponse>(url, {
  66. data: newData,
  67. operation: "anthology",
  68. })
  69. .finally(() => {})
  70. .then((json) => {
  71. if (json.ok) {
  72. message.success(json.data);
  73. } else {
  74. message.error(json.message);
  75. }
  76. })
  77. .catch((e) => message.error(e));
  78. };
  79. useEffect(() => {
  80. get<IArticleMapListResponse>(
  81. `/v2/article-map?view=anthology&id=${anthologyId}`
  82. ).then((json) => {
  83. if (json.ok) {
  84. const toc: ListNodeData[] = json.data.rows.map((item) => {
  85. return {
  86. key: item.article_id ? item.article_id : item.title,
  87. title: item.title,
  88. title_text: item.title_text ? item.title_text : item.title,
  89. level: item.level,
  90. status: item.status,
  91. deletedAt: item.deleted_at,
  92. };
  93. });
  94. setTocData(toc);
  95. }
  96. });
  97. }, [anthologyId]);
  98. return (
  99. <div>
  100. <EditableTree
  101. treeData={tocData}
  102. addOnArticle={addArticle}
  103. addFileButton={
  104. <ArticleListModal
  105. studioName={myStudioName}
  106. trigger={<Button icon={<FolderOpenOutlined />}>添加</Button>}
  107. multiple={false}
  108. onSelect={(id: string, title: string) => {
  109. console.log("add article", id);
  110. const newNode: TreeNodeData = {
  111. key: randomString(),
  112. id: id,
  113. title: title,
  114. title_text: title,
  115. children: [],
  116. level: 1,
  117. };
  118. setAddArticle(newNode);
  119. }}
  120. />
  121. }
  122. updatedNode={updatedArticle}
  123. onChange={(data: ListNodeData[]) => {
  124. save(data);
  125. }}
  126. onSave={(data: ListNodeData[]) => {
  127. save(data);
  128. }}
  129. onAppend={async (
  130. node: TreeNodeData
  131. ): Promise<TreeNodeData | undefined> => {
  132. /**
  133. * 在某节点下append新的节点
  134. */
  135. if (typeof studioName === "undefined") {
  136. console.log("studio", studioName);
  137. return;
  138. }
  139. const res = await post<IArticleCreateRequest, IArticleResponse>(
  140. `/v2/article`,
  141. {
  142. title: "new article",
  143. lang: anthology?.lang ?? getUiLang(),
  144. studio: studioName,
  145. anthologyId: anthologyId,
  146. status: anthology?.status ?? undefined,
  147. }
  148. );
  149. console.log(res);
  150. if (res.ok) {
  151. return {
  152. key: randomString(),
  153. id: res.data.uid,
  154. title: res.data.title,
  155. title_text: res.data.title,
  156. children: [],
  157. level: node.level + 1,
  158. };
  159. } else {
  160. return;
  161. }
  162. }}
  163. onTitleClick={(
  164. e: React.MouseEvent<HTMLElement, MouseEvent>,
  165. node: TreeNodeData
  166. ) => {
  167. if (e.ctrlKey || e.metaKey) {
  168. window.open(fullUrl(`/article/article/${node.id}`), "_blank");
  169. } else {
  170. setViewArticle(node);
  171. setOpenViewer(true);
  172. }
  173. }}
  174. />
  175. <ArticleDrawer
  176. articleId={viewArticle?.id}
  177. anthologyId={anthologyId}
  178. type="article"
  179. open={openViewer}
  180. title={viewArticle?.title_text}
  181. onClose={() => setOpenViewer(false)}
  182. onArticleEdit={(value: IArticleDataResponse) => {
  183. setUpdatedArticle({
  184. key: randomString(),
  185. id: value.uid,
  186. title: value.title,
  187. title_text: value.title_text,
  188. level: 0,
  189. children: [],
  190. });
  191. }}
  192. onTitleChange={(value: string) => {
  193. if (viewArticle?.id) {
  194. setUpdatedArticle({
  195. key: randomString(),
  196. id: viewArticle?.id,
  197. title: value,
  198. title_text: value,
  199. level: 0,
  200. children: [],
  201. });
  202. }
  203. }}
  204. />
  205. </div>
  206. );
  207. };
  208. export default EditableTocTreeWidget;