因为 编辑文章是编辑不同的文章,所以这里需要 使用动态 路由
首先新建 pages/editor/[id].tsx 和 index.module.scss
编辑文章 首先 需要 把 当前的文章详情 回显到页面上
这里通过 url 获取 当前 文章的 id
然后通过ssr渲染的方式进行渲染
根据 文章 id 和 关联的 用户表,链接 文章的 数据表,查询出来 属于 当前用户发布的这篇文章
最后将 查询出来的 文章详情返回
export async function getServerSideProps({ params }: any) {const articleId = params?.id;const db = await prepareConnection();const articleRepo = db.getRepository(Article);const article = await articleRepo.findOne({where: {id: articleId,},relations: ['user'],});return {props: {article: JSON.parse(JSON.stringify(article)),},};}
在react客户端组件中,通过props获取article数据
将 文章标题,文章内容通过state来控制,初始值是props获取的数据
const [title, setTitle] = useState(article?.title || '');const [content, setContent] = useState(article?.content || '');
通过 useRouter hooks 获取 文章Id
const { push, query } = useRouter();const articleId = Number(query?.id)
将获取的文章数据渲染出来
return (<div className={styles.container}><div className={styles.operation}><InputclassName={styles.title}placeholder="请输入文章标题"value={title}onChange={handleTitleChange}/><SelectclassName={styles.tag}mode="multiple"allowClearplaceholder="请选择标签"onChange={handleSelectTag}>{allTags?.map((tag: any) => (<Select.Option key={tag?.id} value={tag?.id}>{tag?.title}</Select.Option>))}</Select><ButtonclassName={styles.button}type="primary"onClick={handlePublish}>发布</Button></div><MDEditor value={content} height={1080} onChange={handleContentChange} /></div>);
修改标题,通过state控制
const handleTitleChange = (event: ChangeEvent<HTMLInputElement>) => {setTitle(event?.target?.value);};
修改 文章内容的时候,也是通过state控制
const handleContentChange = (content: any) => {setContent(content);};
这里 新增一个 获取所有标签的接口
首先 调用 标签接口,将标签数据存到state中
useEffect(() => {request.get('/api/tag/get').then((res: any) => {if (res?.code === 0) {setAllTags(res?.data?.allTags || [])}})}, []);
接下来编写下 获取标签的接口
新建 pages/api/tag/get.ts
1.首先通过session获取当前用户信息
const session: ISession = req.session;const { userId = 0 } = session;
2.链接 标签的数据表
const db = await prepareConnection();const tagRepo = db.getRepository(Tag);
3.根据当前关联的用户表,查询出来所有标签
const allTags = await tagRepo.find({relations: ['users'],});
4.根据用户id查询出来 当前用户关注的标签
const followTags = await tagRepo.find({relations: ['users'],where: (qb: any) => {qb.where('user_id = :id', {id: Number(userId),});},});
5.最后将所有的标签 和 当前用户 关注的 标签 返回
res?.status(200)?.json({code: 0,msg: '',data: {followTags,allTags,},});
6.在客户端 拿到 所有标签数据后渲染出来
<SelectclassName={styles.tag}mode="multiple"allowClearplaceholder="请选择标签"onChange={handleSelectTag}>{allTags?.map((tag: any) => (<Select.Option key={tag?.id} value={tag?.id}>{tag?.title}</Select.Option>))}</Select>
接着开始写 更新 文章的逻辑
1、当点击更新的时候,首先判断一下 是否 输入了标题,如果没有输入标题,则提示用户输入标题
if (!title) {message.warning('请输入文章标题');return ;}
2、然后传参数调用更新文章的接口
3、传的参数包括 文章id、标题、内容、标签
4、当调用更新文章接口成功的时候提示更新文章成功并跳到当前文章
5、如果失败,则提示发布失败
request.post('/api/article/update', {id: articleId,title,content,tagIds}).then((res: any) => {if (res?.code === 0) {articleId ? push(`/article/${articleId}`) : push('/');message.success('更新成功');} else {message.error(res?.msg || '发布失败');}})
6、接着编写 更新文章的接口,新建 pages/api/article/update.ts
7、通过body获取 前端传过来的数据
const { title = '', content = '', id = 0, tagIds = [] } = req.body;
8、链接文章和标签的数据库
const articleRepo = db.getRepository(Article);const tagRepo = db.getRepository(Tag);
9、根据文章的id,关联用户表和标签表,查询出来当前文章
const article = await articleRepo.findOne({where: {id,},relations: ['user', 'tags'],});
10、判断查询出来的article是否存在,如果不存在,则提示文章不存在
res.status(200).json({ ...EXCEPTION_ARTICLE.NOT_FOUND });
11、如果存在,则将传过来的文章数据 覆盖之前的数据,如果保存成功,则提示成功,否则提示失败
if (article) {article.title = title;article.content = content;article.update_time = new Date();article.tags = newTags;const resArticle = await articleRepo.save(article);if (resArticle) {res.status(200).json({ data: resArticle, code: 0, msg: '更新成功' });} else {res.status(200).json({ ...EXCEPTION_ARTICLE.UPDATE_FAILED });}}
12、这里需要根据传过来的标签id,查询出来所有标签,然后将标签数量加1
const tags = await tagRepo.find({where: tagIds?.map((tagId: number) => ({ id: tagId })),});const newTags = tags?.map((tag) => {tag.article_count = tag.article_count + 1;return tag;});
13、最后记得将 需要的 第三方库引入进来
import { NextApiRequest, NextApiResponse } from 'next';import { withIronSessionApiRoute } from 'iron-session/next';import { ironOptions } from 'config/index';import { prepareConnection } from 'db/index';import { Article, Tag } from 'db/entity/index';import { EXCEPTION_ARTICLE } from 'pages/api/config/codes';
这样就完成了编辑文章的前后端开发。
