DiscussionCreate.tsx 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import { useIntl } from "react-intl";
  2. import { Form, message } from "antd";
  3. import {
  4. ProForm,
  5. ProFormInstance,
  6. ProFormText,
  7. ProFormTextArea,
  8. } from "@ant-design/pro-components";
  9. import ReactQuill from "react-quill";
  10. import "react-quill/dist/quill.snow.css";
  11. import { IComment } from "./DiscussionItem";
  12. import { post } from "../../request";
  13. import {
  14. ICommentApiData,
  15. ICommentRequest,
  16. ICommentResponse,
  17. } from "../api/Comment";
  18. import { useAppSelector } from "../../hooks";
  19. import { currentUser as _currentUser } from "../../reducers/current-user";
  20. import { useEffect, useRef, useState } from "react";
  21. import MDEditor from "@uiw/react-md-editor";
  22. export type TContentType = "text" | "markdown" | "html" | "json";
  23. export const toIComment = (value: ICommentApiData): IComment => {
  24. return {
  25. id: value.id,
  26. resId: value.res_id,
  27. resType: value.res_type,
  28. user: value.editor,
  29. title: value.title,
  30. parent: value.parent,
  31. tplId: value.tpl_id,
  32. content: value.content,
  33. createdAt: value.created_at,
  34. updatedAt: value.updated_at,
  35. };
  36. };
  37. interface IWidget {
  38. resId?: string;
  39. resType?: string;
  40. parent?: string;
  41. topic?: IComment;
  42. contentType?: TContentType;
  43. onCreated?: Function;
  44. onTopicCreated?: Function;
  45. }
  46. const DiscussionCreateWidget = ({
  47. resId,
  48. resType,
  49. contentType = "html",
  50. parent,
  51. topic,
  52. onCreated,
  53. onTopicCreated,
  54. }: IWidget) => {
  55. const intl = useIntl();
  56. const formRef = useRef<ProFormInstance>();
  57. const _currUser = useAppSelector(_currentUser);
  58. const [currParent, setCurrParent] = useState(parent);
  59. useEffect(() => setCurrParent(parent), [parent]);
  60. if (typeof _currUser === "undefined") {
  61. return <></>;
  62. } else {
  63. return (
  64. <div>
  65. <div>{_currUser?.nickName}:</div>
  66. <div>
  67. <ProForm<IComment>
  68. formRef={formRef}
  69. onFinish={async (values) => {
  70. //新建
  71. console.log("create", resId, resType, currParent, topic);
  72. console.log("value", values);
  73. let newParent: string | undefined;
  74. if (typeof currParent === "undefined") {
  75. if (typeof topic !== "undefined" && topic.tplId) {
  76. const topicData: ICommentRequest = {
  77. res_id: resId,
  78. res_type: resType,
  79. title: topic.title,
  80. tpl_id: topic.tplId,
  81. content: topic.content,
  82. content_type: "markdown",
  83. };
  84. console.log("create topic", topicData);
  85. const newTopic = await post<
  86. ICommentRequest,
  87. ICommentResponse
  88. >(`/v2/discussion`, topicData);
  89. if (newTopic.ok) {
  90. setCurrParent(newTopic.data.id);
  91. newParent = newTopic.data.id;
  92. if (typeof onTopicCreated !== "undefined") {
  93. onTopicCreated(toIComment(newTopic.data));
  94. }
  95. } else {
  96. console.error("no parent id");
  97. return;
  98. }
  99. }
  100. }
  101. console.log("parent", currParent);
  102. post<ICommentRequest, ICommentResponse>(`/v2/discussion`, {
  103. res_id: resId,
  104. res_type: resType,
  105. parent: newParent ? newParent : currParent,
  106. title: values.title,
  107. content: values.content,
  108. content_type: contentType,
  109. })
  110. .then((json) => {
  111. console.log("new discussion", json);
  112. if (json.ok) {
  113. formRef.current?.resetFields();
  114. if (typeof onCreated !== "undefined") {
  115. onCreated(toIComment(json.data));
  116. }
  117. } else {
  118. message.error(json.message);
  119. }
  120. })
  121. .catch((e) => {
  122. message.error(e.message);
  123. });
  124. }}
  125. params={{}}
  126. >
  127. <ProForm.Group>
  128. <ProFormText
  129. name="title"
  130. width={"lg"}
  131. hidden={
  132. typeof currParent !== "undefined" ||
  133. typeof topic?.tplId !== "undefined"
  134. }
  135. label={intl.formatMessage({ id: "forms.fields.title.label" })}
  136. tooltip="最长为 24 位"
  137. placeholder={intl.formatMessage({
  138. id: "forms.message.question.required",
  139. })}
  140. rules={[
  141. { required: currParent || topic?.tplId ? false : true },
  142. ]}
  143. />
  144. </ProForm.Group>
  145. <ProForm.Group>
  146. {contentType === "text" ? (
  147. <ProFormTextArea
  148. name="content"
  149. label={intl.formatMessage({
  150. id: "forms.fields.content.label",
  151. })}
  152. placeholder={intl.formatMessage({
  153. id: "forms.fields.content.placeholder",
  154. })}
  155. />
  156. ) : contentType === "html" ? (
  157. <Form.Item
  158. name="content"
  159. label={intl.formatMessage({
  160. id: "forms.fields.content.label",
  161. })}
  162. tooltip="可以直接粘贴屏幕截图"
  163. >
  164. <ReactQuill
  165. theme="snow"
  166. style={{ height: 180 }}
  167. modules={{
  168. toolbar: [
  169. ["bold", "italic", "underline", "strike"],
  170. ["blockquote", "code-block"],
  171. [{ header: 1 }, { header: 2 }],
  172. [{ list: "ordered" }, { list: "bullet" }],
  173. [{ indent: "-1" }, { indent: "+1" }],
  174. [{ size: ["small", false, "large", "huge"] }],
  175. [{ header: [1, 2, 3, 4, 5, 6, false] }],
  176. ["link", "image", "video"],
  177. [{ color: [] }, { background: [] }],
  178. [{ font: [] }],
  179. [{ align: [] }],
  180. ],
  181. }}
  182. />
  183. </Form.Item>
  184. ) : contentType === "markdown" ? (
  185. <Form.Item
  186. name="content"
  187. rules={[
  188. {
  189. required:
  190. typeof currParent !== "undefined" ||
  191. typeof topic?.tplId !== "undefined",
  192. },
  193. ]}
  194. label={
  195. typeof currParent === "undefined" &&
  196. typeof topic?.tplId === "undefined"
  197. ? intl.formatMessage({
  198. id: "forms.message.question.description.option",
  199. })
  200. : intl.formatMessage({
  201. id: "forms.fields.replay.label",
  202. })
  203. }
  204. >
  205. <MDEditor
  206. placeholder={
  207. "问题的详细描述" +
  208. (typeof currParent !== "undefined" &&
  209. typeof topic?.tplId !== "undefined"
  210. ? ""
  211. : "(选填)")
  212. }
  213. />
  214. </Form.Item>
  215. ) : (
  216. <></>
  217. )}
  218. </ProForm.Group>
  219. </ProForm>
  220. </div>
  221. </div>
  222. );
  223. }
  224. };
  225. export default DiscussionCreateWidget;