Vue3+java开发组队功能

Vue3+java开发系统组队功能

需求分析

  1. 创建用户可以创建一个队伍(一个房间队长),设置队伍人数,队伍名称(标题),描述,超时时间。
  2. 搜索
  3. 加入,用户可以加入未满的队伍(其他人,未满,未过期),是否需要队长同意
  4. 分享队伍,邀请人员
  5. 显示队伍人数
  6. 聊天
  7. 修改队伍信息
  8. 退出
  9. 解散

系统(接口)设计

  1. 判断请求参数是否为空
  2. 是否登录,未登录直接跳转到登录,不允许创建
  3. 校验信息
    1. 队伍人数大于1小于20
    2. 队伍名称<=20
    3. 队伍人数<=412
    4. 是否公开(int)不穿默认位0,公开
    5. 如果是加密状态,一定3要有密码,且密码<=32
    6. 超时时间>当前时间
    7. 校验用户最多创建5个队伍
  4. 插入队伍信息到队伍表
  5. 插入用户 => 队伍关系到关系表

实现

1. 库表设计(10min)

  1. 数据库表设计,队伍表,队伍用户表
    -- 队伍表
    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)

  1. 使用mybatisX-generation插件自动生成实体类服务层,持久层代码
  2. 队伍基本增删改查代码编写
    /**
     * 队伍接口
     */
    @RestController
    @RequestMapping("/team")
    @CrossOrigin(origins = {"http://localhost:5173"}, allowCredentials = "true")
    @Slf4j //lombok的注解,可以在类中使用log打日志
    public class TeamController {
    
        @Resource
        private UserService userService;
    
        @Resource
        private 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);
        }
    }
    
    
  3. 查询队伍列表功能实现
    1. 新建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;
        }
        
    2. 实现查询队伍列表
      /**
       * 查询组队列表
       * @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);
      }
      
  4. 分页查询队伍列表功能实现
    1. 新建请求分页类
      /**
       * 分页请求类
       *
       * @author Erha
       */
      @Data
      public class PageRequest implements Serializable {
          //使对象序列化保持唯一
          private static final long serialVersionUID = -9075033996918167511L;
      
          /**
           * 页面大小
           */
          protected int pageSize;
          /**
           * 当前第几页
           */
          protected int pageNum;
      }
      
    2. 分页查询队伍实现代码
      /**
       * 分页查询组队列表
       * @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);
      
      }
      
  5. 使用Swagger+knif4j文档接口
    在这里插入图片描述

3. 业务逻辑(30min)

  1. 创建队伍业务逻辑实现
    /**
    * @author serendipity
    * @description 针对表【team(队伍)】的数据库操作Service实现
    * @createDate 2023-11-28 19:33:44
    */
    @Service
    public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
            implements TeamService {
        @Resource
        private 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且<=20
            int maxNum = Optional.ofNullable(team.getMaxNum()).orElse(0);//如果为空,直接赋值为0
            if (maxNum < 1 || maxNum > 20) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍人数不满足要求");
            }
            //(2).队伍标题 <=20
            String name = team.getName();
            if (StringUtils.isBlank(name) || name.length() > 20) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍标题不满足要求");
            }
            // (3) 描述<= 512
            String description = team.getDescription();
            if (StringUtils.isNotBlank(description) && description.length() > 512) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍描述过长");
            }
            //(4)status 是否公开,不传默认为0
            int status = Optional.ofNullable(team.getStatus()).orElse(0);
            TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByValue(status);
            if (statusEnum == null) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍状态不满足要求");
            }
            //(5)如果status是加密状态,一定要密码 且密码<=32
            String 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;
        }
    }
    
  2. 用户退出队伍
    • 请求参数:队伍id
    • 逻辑:
      1. 校验请求参数
      2. 校验队伍是否存在
      3. 校验我是否已加入队伍
      4. 如果队伍
        1. 只剩一人,队伍解散
        2. 还有其他人
          1. 如果是队长退出队伍,权限转移给第二早加入的用户 —— 先来后到
          2. 只用取 id 最小的 2 条数据,其中一条是当前队长的id,当前队长退出后,新队长顺位给最早加
            入的下一位队员
      5. 非队长,自己退出队伍
  • 27
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

D. D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值