最后我们再来实现下收藏功能:
聊天的时候可以收藏某条消息,然后在收藏列表查看。
消息分为文字、图片、文件三类,收藏也是这三类。
我们先加一个收藏表:
javascript
model Favorite {
id Int @id @default(autoincrement())
chatHistoryId Int
uerId Int
createTime DateTime @default(now())
updateTime DateTime @updatedAt
}
每个收藏只要记录对应的 chatHistoryId 和 userId 即可。
这里我们同样没有用外键。
用 migrate dev 生成表:
npx prisma migrate dev --name favorite
sql 没啥问题:
然后创建一个模块:
nest g resource favorite
在 FavorateController 添加三个路由:
javascript
import { Controller, Get, Query } from '@nestjs/common';
import { FavoriteService } from './favorite.service';
import { RequireLogin, UserInfo } from 'src/custom.decorator';
@Controller('favorite')
@RequireLogin()
export class FavoriteController {
constructor(private readonly favoriteService: FavoriteService) {}
@Get('list')
async list(@UserInfo('userId') userId: number) {
return this.favoriteService.list(userId);
}
@Get('add')
async add(@UserInfo('userId') userId: number, @Query('chatHistoryId') chatHistoryId: number) {
return this.favoriteService.add(userId, chatHistoryId);
}
@Get('del')
async del(@Query('id') id: number) {
return this.favoriteService.del(id);
}
}
list、add、del 这三个路由都需要登录,在 Controller 上加上 @RequireLogin 装饰器。
然后取 request.user 里的 userId 传入 handler。
分别在 service 实现这三个方法:
javascript
import { Inject, Injectable } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
@Injectable()
export class FavoriteService {
@Inject(PrismaService)
private prismaService: PrismaService;
async list(userId: number) {
const favorites = await this.prismaService.favorite.findMany({
where: {
uerId: userId
}
})
const res = [];
for(let i = 0; i< favorites.length; i++) {
const chatHistory = await this.prismaService.chatHistory.findUnique({
where: {
id: favorites[i].chatHistoryId
}
})
res.push({
...favorites[i],
chatHistory
})
}
return res;
}
async add(userId: number, chatHistoryId: number) {
return this.prismaService.favorite.create({
data: {
uerId: userId,
chatHistoryId
}
})
}
async del(id: number) {
return this.prismaService.favorite.deleteMany({
where: {
id
}
})
}
}
list 方法把关联的 chatHistory 查出来。
测试下:
添加两条收藏:
查看下:
删除一条:
查看下:
这样,接口就都完成了。
我们再写下前端页面:
先在 interfaces 添加几个接口:
javascript
export async function queryFavoriteList() {
return axiosInstance.get(`/favorite/list`);
}
export async function favoriteAdd(chatHistoryId: number) {
return axiosInstance.get(`/favorite/add`, {
params: {
chatHistoryId
}
});
}
export async function favoriteDel(id: number) {
return axiosInstance.get(`/favorite/del`, {
params: {
id
}
});
}
写下页面 src/pages/Collection/index.tsx
javascript
import { Table, message } from "antd";
import { useEffect, useState } from "react";
import { ColumnsType } from "antd/es/table";
import { queryFavoriteList } from "../../interfaces";
interface Favorite {
id: number
chatHistory: {
id: number
content: string
type: number
createTime: Date
}
}
export function Collection() {
const [favoriteList, setFavoriteList] = useState<Array<Favorite>>([]);
const columns: ColumnsType<Favorite> = [
{
title: 'ID',
dataIndex: 'id'
},
{
title: '内容',
render: (_, record) => (
<div>
{
record.chatHistory.type === 0
? record.chatHistory.content
: record.chatHistory.type === 1
? <img src={record.chatHistory.content} style={{maxHeight: 200}}/>
: <a href={record.chatHistory.content} download>{record.chatHistory.content}</a>
}
</div>
)
},
{
title: '发表时间',
render: (_, record) => (
<div>
{new Date(record.chatHistory.createTime).toLocaleString()}
</div>
)
},
{
title: '操作',
render: (_, record) => (
<div>
<a href="" onClick={() => {}}>删除</a>
</div>
)
}
]
const query = async () => {
try{
const res = await queryFavoriteList();
if(res.status === 201 || res.status === 200) {
setFavoriteList(res.data.map((item: Favorite) => {
return {
...item,
key: item.id
}
}));
}
} catch(e: any){
message.error(e.response?.data?.message || '系统繁忙,请稍后再试');
}
};
useEffect(() => {
query();
}, []);
return <div id="friendship-container">
<div className="favorite-table">
<Table columns={columns} dataSource={favoriteList} style={{width: '1000px'}}/>
</div>
</div>
}
就是请求列表接口,用 table 展示。
我们实现下收藏功能。
简化下交互,双击聊天记录触发收藏:
javascript
onDoubleClick={() => {
addToFavorite(item.id)
}}
javascript
async function addToFavorite(chatHistoryId: number) {
try{
const res = await favoriteAdd(chatHistoryId);
if(res.status === 201 || res.status === 200) {
message.success('收藏成功')
}
} catch(e: any){
message.error(e.response?.data?.message || '系统繁忙,请稍后再试');
}
}
我们收藏几条消息:
提示收藏成功,之后在收藏页面就可以看到了:
然后再做下删除:
javascript
<Popconfirm
title="删除收藏"
description="确认删除吗?"
onConfirm={() => delFavorite(record.id)}
okText="Yes"
cancelText="No"
>
<a href="#" >删除</a>
</Popconfirm>
javascript
async function delFavorite(id: number) {
try{
const res = await favoriteDel(id);
if(res.status === 201 || res.status === 200) {
message.success('删除成功');
query();
}
} catch(e: any){
message.error(e.response?.data?.message || '系统繁忙,请稍后再试');
}
}
测试下:
没啥问题。
这样,收藏功能就完成了。
总结
这节我们实现了收藏功能。
首先创建了收藏表,关联 user 和 chatHistory。
然后创建了 list、add、del 三个接口。
之后在前端通过 table 展示 list 接口的数据,然后双击聊天记录的时候调用 add 添加收藏,点击删除的时候调用 del 删除收藏
这样就实现了收藏功能。