Vue3+java开发系统组队功能
需求分析
- 创建用户可以创建一个队伍(一个房间队长),设置队伍人数,队伍名称(标题),描述,超时时间。
- 搜索
- 加入,用户可以加入未满的队伍(其他人,未满,未过期),是否需要队长同意
- 分享队伍,邀请人员
- 显示队伍人数
- 聊天
- 修改队伍信息
- 退出
- 解散
系统(接口)设计
- 判断请求参数是否为空
- 是否登录,未登录直接跳转到登录,不允许创建
- 校验信息
- 队伍人数大于1小于20
- 队伍名称<=20
- 队伍人数<=412
- 是否公开(int)不穿默认位0,公开
- 如果是加密状态,一定3要有密码,且密码<=32
- 超时时间>当前时间
- 校验用户最多创建5个队伍
- 插入队伍信息到队伍表
- 插入用户 => 队伍关系到关系表
实现
1. 库表设计(10min)
- 数据库表设计,队伍表,队伍用户表
-- 队伍表 create table team (id bigint auto_increment comment 'id'primary key,name varchar(256) not null comment '队伍名称',description varchar(1024) null comment '描述',maxNum int default 1 not null comment '最大人数',expireTime datetime null comment '过期时间',userId bigint comment '用户id',status int default 0 not null comment '0 - 公开,1 - 私有,2 - 加密',password varchar(512) null comment '密码',createTime datetime default CURRENT_TIMESTAMP null comment '创建时间',updateTime datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP,isDelete tinyint default 0 not null comment '是否删除' )comment '队伍';-- 用户队伍关系表 create table user_team (id bigint auto_increment comment 'id'primary key,userId bigint comment '用户id',teamId bigint comment '队伍id',joinTime datetime null comment '加入时间',createTime datetime default CURRENT_TIMESTAMP null comment '创建时间',updateTime datetime default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP,isDelete tinyint default 0 not null comment '是否删除' )comment '用户队伍关系';
2. 增删改查代码实现(10min)
- 使用mybatisX-generation插件自动生成实体类服务层,持久层代码
- 队伍基本增删改查代码编写
/*** 队伍接口*/ @RestController @RequestMapping("/team") @CrossOrigin(origins = {"http://localhost:5173"}, allowCredentials = "true") @Slf4j //lombok的注解,可以在类中使用log打日志 public class TeamController {@Resourceprivate UserService userService;@Resourceprivate TeamService teamService;/*** 增加队伍* @param team* @return*/@PostMapping("/add")public BaseResponse<Long> addTeam(@RequestBody Team team){//接收前端传来队伍的信息if(team == null){throw new BusinessException(ErrorCode.PARAMS_ERROR);}boolean save = teamService.save(team);//teamService继承自Iservices的接口,底层实现了serviceImpl//需要返回新生成数据的id,使用mybatis的组件回写if(!save){throw new BusinessException(ErrorCode.SYSTEM_ERROR,"插入失败");}return ResultUtils.success(team.getId());}/*** 删除队伍** @param id* @return*/@PostMapping("/delete")public BaseResponse<Boolean> deleteTeam(@RequestBody long id){//接收前端传来队伍的信息if(id <= 0){throw new BusinessException(ErrorCode.PARAMS_ERROR);}boolean result = teamService.removeById(id);//teamService继承自Iservices的接口,底层实现了serviceImpl//需要返回新生成数据的id,使用mybatis的组件回写if(!result){throw new BusinessException(ErrorCode.SYSTEM_ERROR,"删除失败");}return ResultUtils.success(true);}/*** 改动队伍** @param team* @return*/@PostMapping("/delete")public BaseResponse<Boolean> updateTeam(@RequestBody Team team){//接收前端传来队伍的信息if(team == null){throw new BusinessException(ErrorCode.PARAMS_ERROR);}boolean result = teamService.updateById(team);//teamService继承自Iservices的接口,底层实现了serviceImpl//需要返回新生成数据的id,使用mybatis的组件回写if(!result){throw new BusinessException(ErrorCode.SYSTEM_ERROR,"更新失败");}return ResultUtils.success(true);}/*** 查询队伍** @param id* @return*/@GetMapping("/delete")public BaseResponse<Team> getTeamById(@RequestBody long id){//接收前端传来队伍id的信息if(id <= 0){throw new BusinessException(ErrorCode.PARAMS_ERROR);}Team team = teamService.getById(id);//teamService继承自Iservices的接口,底层实现了serviceImpl//需要返回新生成数据的id,使用mybatis的组件回写if(team == null){throw new BusinessException(ErrorCode.NULL_ERROR,"数据为空!");}return ResultUtils.success(team);} }
- 查询队伍列表功能实现
- 新建TeamQuery业务请求参数封装类作为作为参数
- 原因:
1. 请求参数和实体类不一样;
2. 有些参数用不到;
3. 多个实体类映射到同一个字段
4. 有些字段要隐藏不返回到前端 - 代码实现
/*** 队伍查询封装类*/ @EqualsAndHashCode(callSuper = true) @Data public class TeamQuery extends PageRequest {/*** id*/@TableId(type = IdType.AUTO)private Long id;/*** 队伍名称*/private String name;/*** 描述*/private String description;/*** 最大人数*/private Integer maxNum;/*** 用户id*/private Long userId;/*** 0 - 公开,1 - 私有,2 - 加密*/private Integer status; }
- 原因:
- 实现查询队伍列表
/*** 查询组队列表* @param teamQuery* @return*/ @GetMapping("/list") //新建teamQuery业务请求参数封装类作为,原因:1.请求参数和实体类不一样;2.有些参数用不到;3.有些字段要隐藏不返回到前端 public BaseResponse<List<Team>> listTeams(TeamQuery teamQuery){if (teamQuery == null){throw new BusinessException(ErrorCode.PARAMS_ERROR);}Team team = new Team();BeanUtils.copyProperties(team,teamQuery);QueryWrapper<Team> queryWrapper = new QueryWrapper<>();List<Team> teamList = teamService.list(queryWrapper);return ResultUtils.success(teamList); }
- 新建TeamQuery业务请求参数封装类作为作为参数
- 分页查询队伍列表功能实现
- 新建请求分页类
/*** 分页请求类** @author Erha*/ @Data public class PageRequest implements Serializable {//使对象序列化保持唯一private static final long serialVersionUID = -9075033996918167511L;/*** 页面大小*/protected int pageSize;/*** 当前第几页*/protected int pageNum; }
- 分页查询队伍实现代码
/*** 分页查询组队列表* @param teamQuery* @return*/ @GetMapping("/list/page") public BaseResponse<Page<Team>> listTeamsByPage(TeamQuery teamQuery){if(teamQuery == null){throw new BusinessException(ErrorCode.PARAMS_ERROR);}Team team = new Team();BeanUtils.copyProperties(team, teamQuery);//把哪个对象的字段复制到另外一个中Page<Team> page = new Page<>(teamQuery.getPageNum(), teamQuery.getPageSize());QueryWrapper<Team> queryWrapper = new QueryWrapper<>(team);Page<Team> Resultpage = teamService.page(page, queryWrapper);return ResultUtils.success(Resultpage);}
- 新建请求分页类
- 使用Swagger+knif4j文档接口
3. 业务逻辑(30min)
- 创建队伍业务逻辑实现
/** * @author serendipity * @description 针对表【team(队伍)】的数据库操作Service实现 * @createDate 2023-11-28 19:33:44 */ @Service public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>implements TeamService {@Resourceprivate UserTeamService userTeamService;@Override@Transactional(rollbackFor = Exception.class)public long addTeam(Team team, User loginUser) {//1.请求参数是否为空if (team == null) {throw new BusinessException(ErrorCode.PARAMS_ERROR);}//2.是否登录,未登录不允许创建if (loginUser == null) {throw new BusinessException(ErrorCode.NO_AUTH);}final long userId = loginUser.getId();//3.检验信息//(1).队伍人数>1且<=20int maxNum = Optional.ofNullable(team.getMaxNum()).orElse(0);//如果为空,直接赋值为0if (maxNum < 1 || maxNum > 20) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍人数不满足要求");}//(2).队伍标题 <=20String name = team.getName();if (StringUtils.isBlank(name) || name.length() > 20) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍标题不满足要求");}// (3) 描述<= 512String description = team.getDescription();if (StringUtils.isNotBlank(description) && description.length() > 512) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍描述过长");}//(4)status 是否公开,不传默认为0int status = Optional.ofNullable(team.getStatus()).orElse(0);TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByValue(status);if (statusEnum == null) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍状态不满足要求");}//(5)如果status是加密状态,一定要密码 且密码<=32String password = team.getPassword();if (TeamStatusEnum.SECRET.equals(statusEnum)) {if (StringUtils.isBlank(password) || password.length() > 32) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码设置不正确");}}//(6)超出时间 > 当前时间Date expireTime = team.getExpireTime();if (new Date().after(expireTime)) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "超出时间 > 当前时间");}//(7)校验用户最多创建5个队伍//todo 有bug。可能同时创建100个队伍QueryWrapper<Team> queryWrapper = new QueryWrapper<>();queryWrapper.eq("userId", userId);long hasTeamNum = this.count(queryWrapper);if (hasTeamNum >= 5) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户最多创建5个队伍");}//4.插入队伍消息到队伍表team.setId(null);team.setUserId(userId);boolean result = this.save(team);Long teamId = team.getId();if (!result || teamId == null) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "创建队伍失败");}//5. 插入用户 ==> 队伍关系 到关系表UserTeam userTeam = new UserTeam();userTeam.setUserId(userId);userTeam.setTeamId(teamId);userTeam.setJoinTime(new Date());result = userTeamService.save(userTeam);if (!result) {throw new BusinessException(ErrorCode.PARAMS_ERROR, "创建队伍失败");}return teamId;} }