diff --git a/next-redirect.js b/next-redirect.js
index 2179fb42..c7ce7514 100644
--- a/next-redirect.js
+++ b/next-redirect.js
@@ -8,7 +8,7 @@ async function redirect() {
// GENERAL
{
source: "/editor",
- destination: "/editor/articles",
+ destination: "/editor/posts",
permanent: true,
}
]
diff --git a/package.json b/package.json
index a71dbfb3..59a90e7f 100644
--- a/package.json
+++ b/package.json
@@ -28,18 +28,22 @@
"eventemitter3": "^4.0.4",
"formik": "^2.2.6",
"framer-motion": "^3.1.1",
+ "highlight.js": "^9.16.2",
"json-bigint": "^1.0.0",
"lodash": "^4.17.15",
+ "markdown-to-jsx": "^7.1.1",
"moment": "^2.27.0",
"next": "^10.0.4",
"next-seo": "^4.17.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-icons": "^4.1.0",
+ "react-markdown-editor-lite": "^1.2.4",
"validator": "^13.5.2"
},
"devDependencies": {
"@next/bundle-analyzer": "^10.0.4",
+ "@types/highlight.js": "^9.12.3",
"@types/lodash": "^4.14.123",
"@types/moment": "^2.13.0",
"@types/node": "^14.14.19",
diff --git a/pages/[username]/[post_slug].tsx b/pages/[username]/[post_slug].tsx
new file mode 100644
index 00000000..0951ca30
--- /dev/null
+++ b/pages/[username]/[post_slug].tsx
@@ -0,0 +1,26 @@
+import { chakra } from "@chakra-ui/react"
+import Container from "components/container"
+import SEO from "components/seo"
+import siteConfig from "configs/site-config"
+import Nav from "layouts/nav/nav"
+import PageContainer from "layouts/page-container"
+import { useRouter } from "next/router"
+import React from "react"
+
+const UserPage = () => {
+ const router = useRouter()
+ return (
+ <>
+
+
+
+ {router.query.username}的博文{router.query.post_slug}
+
+ >
+)}
+
+export default UserPage
+
diff --git a/pages/[username]/index.tsx b/pages/[username]/index.tsx
new file mode 100644
index 00000000..99a92b3f
--- /dev/null
+++ b/pages/[username]/index.tsx
@@ -0,0 +1,26 @@
+import { chakra } from "@chakra-ui/react"
+import Container from "components/container"
+import SEO from "components/seo"
+import siteConfig from "configs/site-config"
+import Nav from "layouts/nav/nav"
+import PageContainer from "layouts/page-container"
+import { useRouter } from "next/router"
+import React from "react"
+
+const UserPage = () => {
+ const router = useRouter()
+ return (
+ <>
+
+
+
+ {router.query.username}'s home
+
+ >
+)}
+
+export default UserPage
+
diff --git a/pages/editor/post/[id].tsx b/pages/editor/post/[id].tsx
new file mode 100644
index 00000000..4e07c899
--- /dev/null
+++ b/pages/editor/post/[id].tsx
@@ -0,0 +1,83 @@
+import { Box, Button,createStandaloneToast} from '@chakra-ui/react';
+import React, { useEffect, useState } from 'react';
+import { MarkdownEditor } from 'components/markdown-editor/editor';
+import PageContainer from 'layouts/page-container';
+import EditorNav from 'layouts/editor-nav'
+import { EditMode } from 'src/types/editor';
+import { MarkdownRender } from 'components/markdown-editor/render';
+import { Post } from 'src/types/posts';
+import { requestApi } from 'utils/axios/request';
+import { useRouter } from 'next/router';
+const toast = createStandaloneToast()
+
+const content = `
+# test原创
+`
+
+function PostEditPage() {
+ const router = useRouter()
+ const {id} = router.query
+ const [editMode, setEditMode] = useState(EditMode.Edit)
+ const [ar,setAr] = useState({
+ md: content,
+ title: ''
+ })
+
+ useEffect(() => {
+ if (id && id !== 'new') {
+ requestApi.get(`/editor/post/${id}`).then(res => setAr(res.data))
+ }
+ },[id])
+ const onChange = newMd => {
+ setAr({
+ ...ar,
+ md: newMd
+ })
+ }
+
+ const publish = async () => {
+ await requestApi.post(`/editor/post`, ar)
+ toast({
+ description: "发布成功",
+ status: "success",
+ duration: 2000,
+ isClosable: true,
+ })
+ router.push('/editor/posts')
+ }
+
+ console.log(ar)
+ return (
+
setEditMode(v)}
+ changeTitle={(e) => {setAr({...ar, title: e.target.value})}}
+ publish={() => publish()}
+ />}
+ >
+
+ {editMode === EditMode.Edit ?
+ onChange(md)}
+ md={ar.md}
+ /> :
+
+
+
+ }
+
+
+ );
+}
+
+export default PostEditPage
+
+
diff --git a/pages/editor/articles.tsx b/pages/editor/posts.tsx
similarity index 75%
rename from pages/editor/articles.tsx
rename to pages/editor/posts.tsx
index 89dec20e..1c1fb0f9 100644
--- a/pages/editor/articles.tsx
+++ b/pages/editor/posts.tsx
@@ -1,4 +1,4 @@
-import { createStandaloneToast, Text, Box, Heading, Image, HStack, Center, Button, Flex, Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalFooter, FormControl, FormLabel, FormHelperText, Input, FormErrorMessage, VStack, Textarea, Divider } from "@chakra-ui/react"
+import { Menu,MenuButton,MenuList,MenuItem,createStandaloneToast, Text, Box, Heading, Image, HStack, Center, Button, Flex, Modal, ModalOverlay, ModalContent, ModalHeader, ModalBody, ModalFooter, FormControl, FormLabel, FormHelperText, Input, FormErrorMessage, VStack, Textarea, Divider, useColorModeValue } from "@chakra-ui/react"
import Card from "components/card"
import Nav from "layouts/nav/nav"
import PageContainer from "layouts/page-container"
@@ -9,24 +9,27 @@ import { requestApi } from "utils/axios/request"
import { useDisclosure } from "@chakra-ui/react"
import { Field, Form, Formik } from "formik"
import { config } from "utils/config"
-import TextArticleCard from "components/articles/text-article-card"
-import { Article } from "src/types/posts"
+import TextPostCard from "components/posts/text-post-card"
+import { Post } from "src/types/posts"
+import { FaExternalLinkAlt, FaRegEdit } from "react-icons/fa"
+import { useRouter } from "next/router"
var validator = require('validator');
const toast = createStandaloneToast()
-const newPost: Article = { title: '', url: '', cover: '' }
-const ArticlesPage = () => {
- const [posts, setPosts] = useState([])
+const newPost: Post = { title: '', url: '', cover: '' }
+const PostsPage = () => {
const [currentPost, setCurrentPost] = useState(newPost)
+ const [posts, setPosts] = useState([])
+ const { isOpen, onOpen, onClose } = useDisclosure()
+ const router = useRouter()
+ const getPosts = () => {
+ requestApi.get(`/editor/posts`).then((res) => setPosts(res.data)).catch(_ => setPosts([]))
+ }
+
useEffect(() => {
getPosts()
}, [])
- const getPosts = () => {
- requestApi.get(`/editor/articles`).then((res) => setPosts(res.data)).catch(_ => setPosts([]))
- }
-
- const { isOpen, onOpen, onClose } = useDisclosure()
function validateTitle(value) {
console.log(value)
@@ -53,8 +56,8 @@ const ArticlesPage = () => {
return error
}
- const submitArticle = async (values, _) => {
- await requestApi.post(`/editor/article`, values)
+ const submitPost = async (values, _) => {
+ await requestApi.post(`/editor/post`, values)
onClose()
toast({
description: "提交成功",
@@ -66,12 +69,17 @@ const ArticlesPage = () => {
getPosts()
}
- const editArticle = (ar: Article) => {
- setCurrentPost(ar)
- onOpen()
+ const editPost = (post: Post) => {
+ if (post.url.trim() === "") {
+ router.push(`/editor/post/${post.id}`)
+ } else {
+ setCurrentPost(post)
+ onOpen()
+ }
}
- const onDeleteArticle = () => {
+ const onDeletePost= async (id) => {
+ await requestApi.delete(`/editor/post/${id}`)
getPosts()
toast({
description: "删除成功",
@@ -90,7 +98,18 @@ const ArticlesPage = () => {
文章列表({posts.length})
-
+ {config.posts.writingEnabled ?
+
+ :
+ }
{
posts.length === 0 ?
@@ -107,12 +126,12 @@ const ArticlesPage = () => {
{posts.map(post =>
- editArticle(post)} onDelete={() => onDeleteArticle()} />
+ editPost(post)} onDelete={() => onDeletePost(post.id)} />
)}
- 没有更多文章了
+ 没有更多文章了
>
}
@@ -122,11 +141,11 @@ const ArticlesPage = () => {
- 编辑文章
+ {currentPost.id ? "编辑文章" : "新建文章"}
{(props) => (