现在涉及到应用或者网站开发的东西,都少不了收藏功能,我本人在做一个新手项目时也需要这个功能,于是我就通过自己的想法实现了一个简单的收藏功能,下面分享给大家,希望对大家思路有帮助。
整体思路
首先是数据库表的设计,这里准备用两个表,一个是课程内容的表,一个是专门用来收藏的表,我们在收藏的同时给课程表的选择人数加一,并且在收藏表里新增一条相关内容,用课程id这个字段将两张表联系起来。
数据库表的设计
public class Course {
@TableId(type = IdType.AUTO)
private int id;
private String courseName;
private String courseCover;
private String courseVip;
private String courseAge;
private String courseAdmin;
private long peopleNumber;
}
收藏表:
public class Collect {
@TableId(type = IdType.AUTO)
private int id;
private int userId;
private int courseId;
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date collectDate;
}
这是我的持久层相关代码,也就是与数据库的表相对应的工具类,大家可以参考,收藏表里的courseId就对应课程表里的id。
收藏与取消收藏功能
首先需要在前端绑定一个点击事件方法:
collect(id) {
this.$confirm('是否确定收藏课程?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(
() => {
this.$axios.post("/collect/course",{
courseId: id,
userId: 1,
}).then(res => {
if (res && res.status === 200) {
this.isCollect = true;
this.$message({
type: 'success',
message: '已收藏成功'
})
}
})
}
)
},
这里我们将相应的课程id与用户id发送到后端,然后进行收藏表字段的增添和人数增加就行,然后里面有一个属性叫isCollect是用于判断是否收藏的,后面用于前端图标的显示。
然后是Controller接口的编写:
@PostMapping("/course")
public Result collectCourse(@RequestBody CollectDTO collect){
try {
collectService.collectCourse(collect);
courseService.collectCourse(collect.getCourseId());
return R.success();
}
catch (Exception e){
e.printStackTrace();
return R.fail("上传失败");
}
}
这里需要调用两个service,因为我们既需要在收藏表里增添,也需要在课程表里增加收藏人数。
Service层代码在MyBatis Plus的加持下很简单:
//收藏课程
@Override
public void collectCourse(CollectDTO collect) {
Collect newCollect = new Collect();
newCollect.setCourseId(collect.getCourseId());
newCollect.setUserId(collect.getUserId());
newCollect.setCollectDate(new Date());
collectMapper.insert(newCollect);
}
增加人数我们将相应的课程字段取出,然后数量加一再进行更新就行
//收藏使课程选择人数加一
@Override
public void collectCourse(int id) {
Course course = courseMapper.selectById(id);
long a = courseMapper.selectById(id).getPeopleNumber();
a=a+1;
course.setPeopleNumber(a);
courseMapper.updateById(course);
}
取消收藏也是同样的道理,大家可以尝试自己编写。
然后是前端页面加载时判断是否收藏,这里我们可以用到Vue的v-if和v-else:
<!-- 已收藏 如果iscollect为true显示已收藏,绑定取消收藏功能-->
<el-button class="button" v-if="isCollect" @click.prevent="delCollect(course.id)" circle><i class="el-icon-star-on"/></el-button>
<!-- 未收藏 绑定点击收藏按钮-->
<el-button class="button" v-else @click.prevent="collect(course.id)" circle><i class="el-icon-star-off"/></el-button>
这里就与我们刚刚的收藏功能属性相关联了,如果收藏了我们属性设置为true,如果没有收藏则设置为false。
现在我们需要在加载页面时就判断是否收藏了当前课程,需要在前端编写一个方法:
api() {
return [
axios.get("/course/selectCourse",{
params: {
id: this.$route.query.id,
}
}),
axios.get("/collect/isCollect",{
params: {
courseId: this.$route.query.id,
userId: 1
}
})
]
},
loadCourse () {
axios.all(this.api()).then(axios.spread((res1,res2) => {
this.course = res1.data
console.log(this.course);
if(res2.data.hasOwnProperty('id')){
this.isCollect = true;
}
}))
},
这里我用到了axios的并发请求,因为需要取到课程数据渲染到页面的同时判断是否收藏,判断收藏时我们需要向后端发送userId和courseId两个字段同时比对才能判断出是否收藏,如果收藏了就返回相应的数据,没有收藏的话就会返回空,这里我们就取其中的id属性判断是否存在就行(isCollect默认为false)。
判断收藏的Controller很简单,直接调用collectService就行
@GetMapping("/isCollect")
public Collect isCollect(int userId,int courseId){
return collectService.isCollect(userId,courseId);
}
然后是service层代码:
//通过两个字段判断用户是否收藏
@Override
public Collect isCollect(int userId, int courseId) {
LambdaQueryWrapper<Collect> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Collect::getUserId,userId).eq(Collect::getCourseId,courseId);
return collectMapper.selectOne(wrapper);
}
直接使用MyBatis Plus的相关功能进行比对就行,很方便,以上就是简易的收藏功能。
查询用户的所有收藏功能
这个问题最开始非常困扰我,因为我也是第一次做,我这样实现的收藏功能如果要查看一个用户的所有收藏的话我需要先从收藏表里将所有的课程id查询出来,再用这些id去课程表里面查询,查询出来还需要是Page类型,因为方便前端布局,好在最后实现了想法。
首先是前端页面编写一个初始加载方法,将用户的id以及页码和当页大小传给后端:
methods: {
load() {
axios.get('/collect/view',{
params: {
userId: 1,
page: 1,
size: this.size
}
}).then(
res => {
this.courses = res.data.records
this.total = res.data.total
console.log(this.courses)
}
)
},
handleCurrentChange(page) {
axios.get('/course/view?',{
params: {
userId: 1,
page: page,
size: this.size
}
}).then(
res => {
this.courses = res.data.records
this.total = res.data.total
console.log(this.courses)
}
)
}
},
created() {
this.load()
},
分页的地方我用了element-ui的分页工具。
然后是Controller的编写:
@GetMapping("/view")
public Page<Course> view(int userId,int page, int size) {
List<Collect> collects = collectService.view(userId);
return courseService.selectCollect(collects,page,size);
}
这里我先用list将收藏表的相关对象查询后放在里面,然后再遍历这个list来进行查询相关课程
collectService:
//找出收藏的书籍
@Override
public List<Collect> view(int userId) {
LambdaQueryWrapper<Collect> wrapper = new LambdaQueryWrapper<>();
List<Collect> collects = collectMapper.selectList(wrapper.eq(Collect::getUserId,userId));
return collects;
}
courseService:
//遍历list获取书籍信息再修改为page类型
@Override
public Page<Course> selectCollect(List<Collect> collects,int pageNum,int pageSize) {
List<Course> list = new ArrayList<>();
for(int i=0;i<collects.size();i++){
Collect c = collects.get(i);
list.add(courseMapper.selectById(c.getCourseId()));
}
System.out.println(list);
Page<Course> page = new Page<>(pageNum, pageSize);
int start = (int)((page.getCurrent() - 1) * page.getSize());
// 当前页最后一条数据在List中的位置
int end = (int)((start + page.getSize()) > list.size() ? list.size() : (page.getSize() * page.getCurrent()));
page.setRecords(new ArrayList<>());
if (page.getSize()*(page.getCurrent()-1) <= page.getTotal()) {
// 分隔列表 当前页存在数据时 设置
page.setRecords(list.subList(start, end));
}
page.setTotal(list.size());
return page;
}
这里我没有想到直接查询成为Page类型的方法所以我先一个个查询之后放入list里面再将list转化为page。
以上就是简单收藏功能的实现,方法肯定不是最好的,但是思路希望对大家有帮助,需要源码可以私。
VX公众号** loquat分享站**,回复 收藏 获取源码
版权归原作者 编程彦祖 所有, 如有侵权,请联系我们删除。