ArticleEdit.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import { useRef, useState } from "react";
  2. import { useIntl } from "react-intl";
  3. import {
  4. ProForm,
  5. ProFormInstance,
  6. ProFormSwitch,
  7. ProFormText,
  8. ProFormTextArea,
  9. } from "@ant-design/pro-components";
  10. import { Alert, Button, Form, message, Result } from "antd";
  11. import { get, put } from "../../request";
  12. import {
  13. IArticleDataRequest,
  14. IArticleResponse,
  15. } from "../../components/api/Article";
  16. import LangSelect from "../../components/general/LangSelect";
  17. import PublicitySelect from "../../components/studio/PublicitySelect";
  18. import MDEditor from "@uiw/react-md-editor";
  19. import ArticlePrevDrawer from "../../components/article/ArticlePrevDrawer";
  20. import { IStudio } from "../auth/Studio";
  21. interface IFormData {
  22. uid: string;
  23. title: string;
  24. subtitle: string;
  25. summary?: string | null;
  26. content?: string;
  27. content_type?: string;
  28. status: number;
  29. lang: string;
  30. to_tpl?: boolean;
  31. }
  32. interface IWidget {
  33. studioName?: string;
  34. articleId?: string;
  35. anthologyId?: string;
  36. onReady?: Function;
  37. onLoad?: Function;
  38. onChange?: Function;
  39. }
  40. const ArticleEditWidget = ({
  41. studioName,
  42. articleId,
  43. anthologyId,
  44. onReady,
  45. onLoad,
  46. onChange,
  47. }: IWidget) => {
  48. const intl = useIntl();
  49. const [unauthorized, setUnauthorized] = useState(false);
  50. const [readonly, setReadonly] = useState(false);
  51. const [content, setContent] = useState<string>();
  52. const [owner, setOwner] = useState<IStudio>();
  53. const formRef = useRef<ProFormInstance>();
  54. return unauthorized ? (
  55. <Result
  56. status="403"
  57. title="无权访问"
  58. subTitle="您无权访问该内容。您可能没有登录,或者内容的所有者没有给您所需的权限。"
  59. extra={<></>}
  60. />
  61. ) : (
  62. <>
  63. {readonly ? (
  64. <Alert
  65. message={`该资源为只读,如果需要修改,请联络拥有者${owner?.nickName}分配权限。`}
  66. type="warning"
  67. closable
  68. action={
  69. <Button disabled size="small" type="text">
  70. 详情
  71. </Button>
  72. }
  73. />
  74. ) : undefined}
  75. <ProForm<IFormData>
  76. formRef={formRef}
  77. onFinish={async (values: IFormData) => {
  78. const request: IArticleDataRequest = {
  79. uid: articleId ? articleId : "",
  80. title: values.title,
  81. subtitle: values.subtitle,
  82. summary: values.summary,
  83. content: values.content,
  84. content_type: "markdown",
  85. status: values.status,
  86. lang: values.lang,
  87. to_tpl: values.to_tpl,
  88. anthology_id: anthologyId,
  89. };
  90. const url = `/v2/article/${articleId}`;
  91. console.log("save", url, request);
  92. put<IArticleDataRequest, IArticleResponse>(url, request)
  93. .then((res) => {
  94. console.log("save response", res);
  95. if (res.ok) {
  96. if (typeof onChange !== "undefined") {
  97. onChange(res.data);
  98. }
  99. formRef.current?.setFieldValue("content", res.data.content);
  100. message.success(intl.formatMessage({ id: "flashes.success" }));
  101. } else {
  102. message.error(res.message);
  103. }
  104. })
  105. .catch((e: IArticleResponse) => {
  106. message.error(e.message);
  107. });
  108. }}
  109. request={async () => {
  110. const url = `/v2/article/${articleId}`;
  111. console.info("url", url);
  112. const res = await get<IArticleResponse>(url);
  113. console.log("article", res);
  114. let mTitle: string,
  115. mReadonly = false;
  116. if (res.ok) {
  117. setOwner(res.data.studio);
  118. mReadonly = res.data.role === "editor" ? false : true;
  119. setReadonly(mReadonly);
  120. mTitle = res.data.title;
  121. setContent(res.data.content);
  122. } else {
  123. setUnauthorized(true);
  124. mTitle = "无权访问";
  125. }
  126. if (typeof onReady !== "undefined") {
  127. onReady(
  128. mTitle,
  129. mReadonly,
  130. res.data.studio?.realName,
  131. res.data.parent_uid
  132. );
  133. }
  134. return {
  135. uid: res.data.uid,
  136. title: res.data.title,
  137. subtitle: res.data.subtitle,
  138. summary: res.data.summary,
  139. content: res.data.content,
  140. content_type: res.data.content_type,
  141. lang: res.data.lang,
  142. status: res.data.status,
  143. };
  144. }}
  145. >
  146. <ProForm.Group>
  147. <ProFormText
  148. width="md"
  149. name="title"
  150. required
  151. label={intl.formatMessage({
  152. id: "forms.fields.title.label",
  153. })}
  154. rules={[
  155. {
  156. required: true,
  157. message: intl.formatMessage({
  158. id: "forms.message.title.required",
  159. }),
  160. },
  161. ]}
  162. />
  163. <ProFormText
  164. width="md"
  165. name="subtitle"
  166. label={intl.formatMessage({
  167. id: "forms.fields.subtitle.label",
  168. })}
  169. />
  170. </ProForm.Group>
  171. <ProForm.Group>
  172. <LangSelect width="md" />
  173. <PublicitySelect width="md" />
  174. </ProForm.Group>
  175. <ProForm.Group>
  176. <ProFormTextArea
  177. name="summary"
  178. width="lg"
  179. label={intl.formatMessage({
  180. id: "forms.fields.summary.label",
  181. })}
  182. />
  183. </ProForm.Group>
  184. <Form.Item
  185. name="content"
  186. style={{ width: "100%" }}
  187. label={
  188. <>
  189. {intl.formatMessage({
  190. id: "forms.fields.content.label",
  191. })}
  192. {articleId ? (
  193. <ArticlePrevDrawer
  194. trigger={<Button>预览</Button>}
  195. articleId={articleId}
  196. content={content}
  197. />
  198. ) : undefined}
  199. </>
  200. }
  201. >
  202. <MDEditor
  203. onChange={(value) => setContent(value)}
  204. height={450}
  205. minHeight={200}
  206. style={{ width: "100%" }}
  207. />
  208. </Form.Item>
  209. <ProForm.Group>
  210. <ProFormSwitch
  211. name="to_tpl"
  212. label="转换为模版"
  213. disabled={anthologyId ? false : true}
  214. />
  215. </ProForm.Group>
  216. </ProForm>
  217. </>
  218. );
  219. };
  220. export default ArticleEditWidget;