ArticleEdit.tsx 5.9 KB

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