简单收藏功能的实现(SpringBoot,MybatisPlus,Vue)
Posted 编程彦祖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单收藏功能的实现(SpringBoot,MybatisPlus,Vue)相关的知识,希望对你有一定的参考价值。
现在涉及到应用或者网站开发的东西,都少不了收藏功能,我本人在做一个新手项目时也需要这个功能,于是我就通过自己的想法实现了一个简单的收藏功能,下面分享给大家,希望对大家思路有帮助。
目录
整体思路
首先是数据库表的设计,这里准备用两个表,一个是课程内容的表,一个是专门用来收藏的表,我们在收藏的同时给课程表的选择人数加一,并且在收藏表里新增一条相关内容,用课程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。
以上就是简单收藏功能的实现,方法肯定不是最好的,但是思路希望对大家有帮助,需要源码可以私。
基于SpringBoot+mybatis+layui实现就业管理系统简单版《建议收藏》
目录
GIF动图演示 :
项目摘要:
过去高校毕生就管理主要采用人工管理方式存在信息更新不及时查询、更改和管理信息繁琐人工管理耗费大量人力、物力等的问题,使得高校不能及时掌握毕业生的就业信息因此研究并开发高校毕业生的就业管理系统就显得十分重要本课题基于Java 语言和MySQL数据库采用Java Web、springboot 技术设计并开发一个基于Javaweb、springboot的就业信息管理系统为学校提供一个方便有效的系统来管理大学生的就业信息本系统主要包括毕业生管理、企业信息管理、学生就信息管理、信息查询等功能实现了对高校毕牛就,情况的管理,以及能够对毕业生毕业情况进行记录和查询测试表明系统允许稳定可靠应用该系统能够有利于对毕业生的就业信息进行及时全面的管理,同时也为管理者节约了大量的时间和精力.
主要技术和软件:
主要技术:springboot+mybatis+mysql+layui+templates模板等
软件工具:JDK1.8+idea+navicat等
项目功能实现:
用户登录:
前端登录HTML样式
<!DOCTYPE html>
<html>
<head th:include="include/commoncss::commoncss(~{::link})">
<link rel="stylesheet" href="/resources/css/login.css">
</head>
<body>
<div class="login-content">
<div class="layui-row">
<div class="layui-col-md12">
<div class="layui-row">
<div class="layui-col-md12 login-promt">
<span>就业管理系统</span>
</div>
<div class="layui-col-md12">
<form class="layui-form" action="">
<div class="layui-form-item">
<label class="layui-form-label"><i class="layui-icon layui-icon-username"></i></label>
<div class="layui-input-block">
<input type="text" name="userAccount" required lay-verify="required" placeholder="请输入帐号" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><i class="layui-icon layui-icon-password"></i></label>
<div class="layui-input-block">
<input type="password" name="userPwd" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" class="layui-btn" lay-submit="" lay-filter="formLogin">登录</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<div th:include="include/commonjs::commonjs(~{::script})">
<script type="text/javascript" src="/resources/js/system/home/login.js"></script>
</div>
</body>
</html>
后台java controller登录接口实现
@ResponseBody
@RequestMapping("/employment/login")
public CommonResult<User> login(User user){
user.setUserPwd(MD5Util.getMD5(user.getUserPwd()));
User loginUser = userService.getUserByAccount(user.getUserAccount());
if(loginUser == null || !loginUser.getUserPwd().equals(user.getUserPwd())){
return CommonResult.generateFailureResult("帐号或密码不正确", 1, null);
}else{
return CommonResult.generateSuccessResult(1, loginUser);
}
}
管理员主页:
用户验证登录成功后跳转对应页面、管理员页面的主要功能有就业信息管理、就业信息统计和用户信息管理以及退出等功能操作。
后台主要代码实现:
登录成功后跳转到后台就业信息列表页面展示数据
import java.util.UUID;
@Controller
public class EmploymentInfoController {
@Autowired
EmploymentInfoService employmentInfoService;
@RequestMapping({"/employment/index", "/employment/employmentinfo"})
public String index(){
return "system/employmentinfo/employmentinfo";
}
@ResponseBody
@RequestMapping("/employment/getallinfo")
public CommonResult<List<EmploymentInfo>> getAllInfo(EmploymentInfo employmentInfo, @RequestParam("limit") int pageSize, @RequestParam("page") int pageNum){
List<EmploymentInfo> infoList = employmentInfoService.getAllEmploymentInfo(employmentInfo, pageNum, pageSize);
CommonResult<List<EmploymentInfo>> rtInfoResult = CommonResult.generateSuccessResult(infoList.size(), infoList);
return rtInfoResult;
}
@ResponseBody
@RequestMapping("/employment/getinfo")
public CommonResult<List<EmploymentInfo>> getinfo(EmploymentInfo info, @RequestParam("limit") int pageSize, @RequestParam("page") int pageNum){
List<EmploymentInfo> infoList = employmentInfoService.getEmploymentInfo(info, pageNum, pageSize);
CommonResult<List<EmploymentInfo>> rtInfoResult = CommonResult.generateSuccessResult(infoList.size(), infoList);
return rtInfoResult;
}
@ResponseBody
@RequestMapping("/employment/addinfo")
public CommonResult<Integer> addInfo(EmploymentInfo info){
info.setInformationId(UUID.randomUUID().toString());
employmentInfoService.addEmploymentInfo(info);
return CommonResult.generateSuccessResult(1, 1);
}
@ResponseBody
@RequestMapping("/employment/updateinfo")
public CommonResult<Integer> updateInfo(EmploymentInfo info){
employmentInfoService.updateEmploymentInfo(info);
return CommonResult.generateSuccessResult(1, 1);
}
@ResponseBody
@RequestMapping("/employment/delinfo/{infoId}")
public CommonResult<Integer> delInfo(@PathVariable("infoId") String infoId){
employmentInfoService.deleteEmploymentInfo(infoId);
return CommonResult.generateSuccessResult(1, 1);
}
}
添加就业信息:
前端添加就业信息代码块
<!DOCTYPE html>
<html >
<head th:include="include/commoncss::commoncss(~{})">
</head>
<body class="layui-layout-body">
<div class="layui-layout layui-layout-admin">
<div th:replace="include/header::header"></div>
<!--查询条件-->
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 15px;">
<legend>搜索条件</legend>
</fieldset>
<form action="" method="post" id="searchinfo" lay-filter="searchinfo" class="layui-form">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">专业</label>
<div class="layui-input-inline">
<input type="text" name="studentMajor" class="layui-input input-radius"
placeholder="请输入专业名称">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">班级</label>
<div class="layui-input-inline">
<input type="text" name="studentClass" class="layui-input input-radius"
placeholder="请输入班级名称">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">性别</label>
<div class="layui-input-inline">
<input type="text" name="studentGender" class="layui-input input-radius"
placeholder="请输入学生性别">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">企业</label>
<div class="layui-input-inline">
<input type="text" name="companyName" class="layui-input input-radius"
placeholder="请输入企业名称">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">岗位</label>
<div class="layui-input-inline">
<input type="text" name="employmentStation" class="layui-input input-radius"
placeholder="请输入岗位名称">
</div>
</div>
<div class="layui-inline" style="padding-left: 3%">
<button type="button" class="layui-btn layui-btn-sm layui-btn-radius" lay-submit="" lay-filter="doSearch"><i
class="layui-icon layui-icon-search layui-icon-normal"></i>查询
</button>
<button type="reset" class="layui-btn layui-btn-sm layui-btn-radius layui-btn-warm"><i
class="layui-icon layui-icon-refresh"></i><span>重置</span>
</button>
</div>
</div>
</form>
<!-- 用户列表 -->
<div>
<table class="layui-hide" id="infoList" lay-filter="infoList"></table>
</div>
<!-- 表格操作 -->
<script type="text/html" id="infoToolBar">
<button type="button" lay-event="infoAdd" class="layui-btn layui-btn-sm layui-btn-normal layui-btn-radius">
<i class="layui-icon layui-icon-add-1"></i>添加就业信息
</button>
</script>
<!-- 用户操作 -->
<script type="text/html" id="infoListOpt">
<a class="layui-btn layui-btn-xs" lay-event="infoEdit">编辑</a>
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="infoDel">删除</a>
</script>
<!-- 添加或修改弹出层 -->
<div style="display: none;padding: 10px;" id="addOrUpdateinfo">
<form action="" method="post" class="layui-form" id="addOrUpdateForm" lay-filter="addOrUpdateForm">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">就业单位</label>
<div class="layui-input-block">
<input type="hidden" name="informationId">
<input type="text" name="companyName" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入就业单位名称">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">就业单位地址</label>
<div class="layui-input-block">
<input type="text" name="companyAddress" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入就业单位地址">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">就业岗位</label>
<div class="layui-input-block">
<input type="text" name="employmentStation" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入就业岗位">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">待遇</label>
<div class="layui-input-block">
<input type="text" name="treatment" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入待遇">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">能力要求</label>
<div class="layui-input-block">
<input type="text" name="abilityRequirement" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入能力要求">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">学生姓名</label>
<div class="layui-input-block">
<input type="text" name="studentName" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入学生姓名">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">学生专业</label>
<div class="layui-input-block">
<input type="text" name="studentMajor" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入学生专业">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">学生性别</label>
<div class="layui-input-block">
<input type="radio" name="studentGender" value="男" title="男" checked>
<input type="radio" name="studentGender" value="女" title="女" >
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">学生班级</label>
<div class="layui-input-block">
<input type="text" name="studentClass" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入学生班级">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">学生电话</label>
<div class="layui-input-block">
<input type="text" name="studentMobile" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入学生电话">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">就业时间</label>
<div class="layui-input-block">
<input type="text" name="employmentTime" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入就业时间">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">单位联系人</label>
<div class="layui-input-block">
<input type="text" name="companyContactName" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入单位联系人">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">单位联系人电话</label>
<div class="layui-input-block">
<input type="text" name="companyContactMobile" lay-verify="required" autocomplete="off"
class="layui-input input-radius" placeholder="请输入单位联系人电话">
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block" style="text-align: center;padding-right: 7%">
<button type="button" class="layui-btn layui-btn-radius" lay-submit="" lay-filter="infoSubmitBtn" id="infoSubmitBtn"><i
class="layui-icon layui-icon-search layui-icon-normal"></i>提交
</button>
<button type="userReset" class="layui-btn layui-btn-radius layui-btn-warm"><i
class="layui-icon layui-icon-refresh"></i><span>重置</span>
</button>
</div>
</div>
</form>
</div>
<div th:include="include/commonjs::commonjs(~{::script})">
<script type="text/javascript" src="/resources/js/common/header.js"></script>
<script type="text/javascript" src="/resources/js/system/employmentinfo/employmentinfo.js"></script>
</div>
</div>
</body>
</html>
添加用户信息:
数据库表设计:
用户表:
CREATE TABLE `NewTable` (
`user_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL ,
`user_account` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`user_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`user_pwd` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`user_type` int(1) NULL DEFAULT NULL COMMENT '0-管理员,1-普通用户' ,
PRIMARY KEY (`user_id`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_bin
ROW_FORMAT=COMPACT
;
就业信息表:
CREATE TABLE `NewTable` (
`information_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL ,
`company_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`company_address` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`employment_station` varchar(128) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`treatment` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`ability_requirement` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`student_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`student_major` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`student_class` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`student_mobile` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`employment_time` date NULL DEFAULT NULL ,
`company_contact_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`company_contact_mobile` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
`student_gender` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL ,
PRIMARY KEY (`information_id`)
)
ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_bin
ROW_FORMAT=COMPACT
;
总结:
通过最近对Java面向对象编程、前端知识和Java Springboot框架的掌握和学习,我更加明白了学习Java的重要性。在开发这个系统的过程中,我完成了很多实验和测试。在这一阶段的学习和发展中,我意识到我已经熟悉了它,并能够独立使用它。通过对Java的了解,我发现它确实有很多的便利性,它集成了抽象性、封装性、继承性和多态性,实现了代码重用和代码扩展,提高了软件开发的效率。学好Java语言对于我们的专业来说是非常重要的,所以在这个项目的开发过程中,我尽可能的了解Java编程思想,掌握基本的技能,学习尽可能多的知识。我学习编程的基本目的是培养用编程方法解决实际问题的关键技能。Java面向对象编程是一种高度实用的语言,springMVC框架的MVC三层架构将数据访问和逻辑操作集中到组件中,增强了系统的重用性。大大提高了系统的可扩展性。以及前端jQuery, JS和CSS风格,我可以使网页布局,风格调整和字体更准确。
获取源码:
查看主页博主联系或下方微信获取
往前精彩分享:
总体来说这个项目功能相对还是比较简单优秀的、适合初学者作为课程设计和毕业设计参考
另外需要其他毕设项目或者白嫖java学习资料包括《JVM、Netty、Mysql、Mybatis、Redis、Dubbo、Nginx、设计模式》等10G资料礼包、可以看我主页或私信博主都行
打卡Java项目更新 41 / 100天
大家可以点赞、收藏、关注、评论我啦 、
以上是关于简单收藏功能的实现(SpringBoot,MybatisPlus,Vue)的主要内容,如果未能解决你的问题,请参考以下文章
基于java+springboot+mybatis+laiyu实现学科竞赛管理系统《建议收藏》
基于java+springboot+mybatis+laiyu实现学科竞赛管理系统《建议收藏》