这篇文章 开始 编写 标签管理的页面
首先 新建 pages/tag/index.tsx和 pages/tag/index.module.scss分别 存放 标签的 页面和样式
这个页面 我们采用 csr的方式来渲染页面,看看和ssr渲染页面的方式有何不同
在这个页面 我们设计成 全部标签 和关注的标签,页面效果如下:
首先 我们 先 编写接口, 来获取 全部标签和已关注的标签
新建 pages/api/tag/get.ts
1.首先 引入 数据库等的配置
import { NextApiRequest, NextApiResponse } from 'next';
import { withIronSessionApiRoute } from 'iron-session/next';
import { ironOptions } from 'config/index';
import { ISession } from 'pages/api/index';
import { prepareConnection } from 'db/index';
import { Tag } from 'db/entity/index';
2.通过 session 获取 当前用户的id,因为我们需要根据用户id获取该用户的标签数据
const { userId = 0 } = session;
3.链接 标签 数据库的 配置
const db = await prepareConnection();
const tagRepo = db.getRepository(Tag);
4.首先 获取 全部标签的数据,这个我们只需要 根据 关联 的用户表去 标签的 数据表 查询即可
const allTags = await tagRepo.find({
relations: ['users'],
});
5.接下来 获取 关注的标签,关注的标签逻辑是,根据当前用户的id去查询标签数据,这样获取的数据就是该用户关注的标签数据
const followTags = await tagRepo.find({
relations: ['users'],
where: (qb: any) => {
qb.where('user_id = :id', {
id: Number(userId),
});
},
});
6.最后将 获取的 所有标签数据 和 关注的标签数据 返回
res?.status(200)?.json({
code: 0,
msg: '',
data: {
followTags,
allTags,
},
});
7.接下来 我们在客户端 使用 csr的方式 来获取 全部标签和已关注的标签数据。同followTags和allTags来分别存储全部标签数据和已关注的标签数据
const [followTags, setFollowTags] = useState<ITag[]>();
const [allTags, setAllTags] = useState<ITag[]>();
useEffect(() => {
request('/api/tag/get').then((res: any) => {
if (res?.code === 0) {
const { followTags = [], allTags = [] } = res?.data || {};
setFollowTags(followTags);
setAllTags(allTags);
}
})
}, [needRefresh]);
8.接下来 来渲染 全部标签的数据,这里有个逻辑,就是 显示 关注 还是已关注。当 当前用户id 能够在 接口返回的users中返回的id中能够找打,则表明 当前用户 已关注了 这个标签,则页面上显示 已关注,否则显示关注。当显示已关注的时候,按钮事件则是 取消关注的逻辑,否则则是 关注的逻辑。
<TabPane tab="全部标签" key="all" className={styles.tags}>
{
allTags?.map(tag => (
<div key={tag?.title} className={styles.tagWrapper}>
<div>{(ANTD_ICONS as any)[tag?.icon]?.render()}</div>
<div className={styles.title}>{tag?.title}</div>
<div>{tag?.follow_count} 关注 {tag?.article_count} 文章</div>
{
tag?.users?.find((user) => Number(user?.id) === Number(userId)) ? (
<Button type='primary' onClick={() => handleUnFollow(tag?.id)}>已关注</Button>
) : (
<Button onClick={() => handleFollow(tag?.id)}>关注</Button>
)
}
</div>
))
}
</TabPane>
9.首先 编写 关注 标签的逻辑,新建 pages/api/tag/follow.ts
10.首先引入数据库配置
import { NextApiRequest, NextApiResponse } from 'next';
import { withIronSessionApiRoute } from 'iron-session/next';
import { ironOptions } from 'config/index';
import { ISession } from 'pages/api/index';
import { prepareConnection } from 'db/index';
import { Tag, User } from 'db/entity/index';
import { EXCEPTION_USER, EXCEPTION_TAG } from 'pages/api/config/codes';
export default withIronSessionApiRoute(follow, ironOptions);
11.从session获取用户的id
const session: ISession = req.session;
const { userId = 0 } = session;
12.从 body中获取 前端传过来的参数,一共两个参数,一个type,值分别是follow和unfollow,表示是取消关注还是关注,另外一个参数数标签的id
const { tagId, type } = req?.body || {};
13.链接 标签和用户的数据库
const db = await prepareConnection();
const tagRepo = db.getRepository(Tag);
const userRepo = db.getRepository(User);
14.根据用户id去用户表中查询该用户信息,如果没找到,则提示当前用户不存在
const user = await userRepo.findOne({
where: {
id: userId,
},
});
if (!user) {
res?.status(200).json({
...EXCEPTION_USER?.NOT_LOGIN,
});
return;
}
15.根据标签id从标签的数据表中查询所有标签
const tag = await tagRepo.findOne({
relations: ['users'],
where: {
id: tagId,
},
});
16.如果从标签表中查询出有用户,如果类型是follow,则表示是关注操作,则将当前用户添加到 关注该标签的用户数据中,并且将关注该标签的数据增加1,如果类型是unfollow,则表示取消关注操作,则将当前用户从 关注该标签的用户数据中剔除,并且将关注该标签的数据减1.
if (tag?.users) {
if (type === 'follow') {
tag.users = tag?.users?.concat([user]);
tag.follow_count = tag?.follow_count + 1;
} else if (type === 'unfollow') {
tag.users = tag?.users?.filter((user) => user.id !== userId);
tag.follow_count = tag?.follow_count - 1;
}
}
17.最后将 标签的数据存入 标签的数据表中,如果成功,则返回200,否则提示失败
if (tag) {
const resTag = await tagRepo?.save(tag);
res?.status(200)?.json({
code: 0,
msg: '',
data: resTag,
});
} else {
res?.status(200)?.json({
...EXCEPTION_TAG?.FOLLOW_FAILED,
});
}
18.在前端点击关注的时候,传入两个参数,一个参数是type,值为follw,另外一个参数是标签id,如果接口成功,在前端提示关注成功,并且重新调标签的数据,刷新页面
request.post('/api/tag/follow', {
type: 'follow',
tagId
}).then((res: any) => {
if (res?.code === 0) {
message.success('关注成功');
setNeedRefresh(!needRefresh);
} else {
message.error(res?.msg || '关注失败');
}
})
19.取消关注,则是将type参数的值改成 unfollow。