You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
3.9 KiB

4 years ago
import { Box, Button, Text, useToast } from '@chakra-ui/react';
4 years ago
import React, { useEffect, useState } from 'react';
import { MarkdownEditor } from 'components/markdown-editor/editor';
import PageContainer from 'layouts/page-container';
4 years ago
import EditorNav from 'layouts/nav/editor-nav'
4 years ago
import { EditMode } from 'src/types/editor';
import { MarkdownRender } from 'components/markdown-editor/render';
4 years ago
import { Story, StoryStatus } from 'src/types/story';
4 years ago
import { requestApi } from 'utils/axios/request';
import { useRouter } from 'next/router';
4 years ago
import { config } from 'configs/config';
4 years ago
import { cloneDeep } from 'lodash';
4 years ago
import Card from 'components/card';
4 years ago
import { updateUrl } from 'utils/url';
import { IDType } from 'src/types/id';
4 years ago
4 years ago
let saveDraftHandler = undefined;
4 years ago
function PostEditPage() {
const router = useRouter()
4 years ago
const { id } = router.query
4 years ago
const [editMode, setEditMode] = useState(EditMode.Edit)
4 years ago
const [saved,setSaved] = useState(null)
const [ar, setAr]:[Story,any] = useState({
type: IDType.Post,
md: '',
title: '',
status: StoryStatus.Draft
4 years ago
})
4 years ago
4 years ago
const toast = useToast()
4 years ago
useEffect(() => {
if (id && id !== 'new') {
4 years ago
requestApi.get(`/story/post/${id}`).then(res => setAr(res.data))
4 years ago
}
4 years ago
}, [id])
4 years ago
const onMdChange = newMd => {
4 years ago
const newAr = {
4 years ago
...ar,
md: newMd
4 years ago
}
setAr(newAr)
if (ar.status === StoryStatus.Draft) {
onSaveDraft(newAr)
}
}
const onSaveDraft = (post?) => {
if (saveDraftHandler === undefined) {
// 没有任何保存动作,开始保存
saveDraftHandler = setTimeout(() => saveDraft(post),2000)
return
} else if (saveDraftHandler !== null) {
// 不在保存过程中,连续输入, 取消之前的定时器重新设置handler
clearTimeout(saveDraftHandler)
saveDraftHandler = setTimeout(() => saveDraft(post),2000)
return
}
}
const saveDraft = async (post?) => {
saveDraftHandler = null
setSaved(false)
const res = await requestApi.post(`/story/post/draft`, post??ar)
setSaved(true)
saveDraftHandler = undefined
if (!ar.id) {
ar.id = res.data.id
let url = window.location.origin + `/editor/post/${ar.id}`
window.history.pushState({},null,url);
}
4 years ago
}
4 years ago
4 years ago
const onChange = () => {
4 years ago
const newAr = cloneDeep(ar)
if (ar.status === StoryStatus.Draft) {
onSaveDraft(newAr)
}
setAr(newAr)
4 years ago
}
const onChangeTitle = title => {
if (title.length > config.posts.titleMaxLen) {
toast({
description: `Title长度不能超过${config.posts.titleMaxLen}`,
status: "error",
duration: 2000,
isClosable: true,
4 years ago
})
return
4 years ago
}
4 years ago
const newAr = { ...ar, title: title }
if (ar.status === StoryStatus.Draft) {
onSaveDraft(newAr)
}
setAr(newAr)
4 years ago
}
4 years ago
const publish = async () => {
4 years ago
if (!ar.tags || ar.tags?.length === 0) {
4 years ago
toast({
description: "请设置文章标签",
status: "error",
duration: 3000,
isClosable: true,
})
return
}
const res = await requestApi.post(`/story`, ar)
4 years ago
toast({
4 years ago
description: "发布成功",
status: "success",
duration: 2000,
isClosable: true,
4 years ago
})
4 years ago
router.push(`/${res.data.username}/${res.data.id}`)
4 years ago
}
return (
<PageContainer
nav={<EditorNav
ar={ar}
4 years ago
onChange={onChange}
4 years ago
changeEditMode={(v) => setEditMode(v)}
4 years ago
changeTitle={(e) => onChangeTitle(e.target.value)}
4 years ago
publish={() => publish()}
4 years ago
saved={saved}
4 years ago
/>}
>
4 years ago
{editMode === EditMode.Edit ?
<Card style={{ height: 'calc(100vh - 145px)' }}>
4 years ago
<MarkdownEditor
4 years ago
onChange={(md) => onMdChange(md)}
4 years ago
md={ar.md}
4 years ago
/></Card> :
<Card>
4 years ago
<Box height="100%" p="6">
<MarkdownRender md={ar.md} />
</Box>
4 years ago
</Card>
}
4 years ago
</PageContainer>
);
}
export default PostEditPage