package com.ycl.jxkg.service.impl; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ycl.jxkg.base.Result; import com.ycl.jxkg.base.SystemCode; import com.ycl.jxkg.context.WebContext; import com.ycl.jxkg.domain.entity.*; import com.ycl.jxkg.domain.form.MeetForm; import com.ycl.jxkg.domain.query.MeetQuery; import com.ycl.jxkg.domain.vo.ClassesVO; import com.ycl.jxkg.domain.vo.MeetClassesVo; import com.ycl.jxkg.domain.vo.MeetVO; import com.ycl.jxkg.domain.vo.StudentSimpleVO; import com.ycl.jxkg.enums.MeetStatusEnum; import com.ycl.jxkg.mapper.*; import com.ycl.jxkg.rabbitmq.msg.MeetStatusMsg; import com.ycl.jxkg.rabbitmq.product.Producer; import com.ycl.jxkg.service.MeetService; import com.ycl.jxkg.utils.DateTimeUtil; import com.ycl.jxkg.utils.PageUtil; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import java.util.Date; import java.util.List; import java.util.stream.Collectors; /** * 会议表 服务实现类 * * @author flq * @since 2024-06-17 */ @Service @RequiredArgsConstructor public class MeetServiceImpl extends ServiceImpl implements MeetService { private final MeetMapper meetMapper; @Autowired private WebContext webContext; @Autowired private ClassesUserMapper classesUserMapper; private final Producer producer; private final MeetStudentMapper meetStudentMapper; private final StudyRecordMapper studyRecordMapper; private final MeetClassesMapper meetClassesMapper; /** * 添加 * @param form * @return */ @Override @Transactional(rollbackFor = Exception.class) public Result add(MeetForm form) { Meet entity = MeetForm.getEntityByForm(form, null); entity.setStatus(MeetStatusEnum.Wait.getCode()); entity.setCreateUser(webContext.getCurrentUser().getId()); // 设置乐观锁版本 entity.setUpdateVersion(0); if (baseMapper.insert(entity) > 0) { this.sendMQ(entity, 0); } // 向会议班级中间表中插入数据 form.getClassesIds().forEach(classId -> { MeetClasses meetClasses = new MeetClasses(); meetClasses.setMeetId(entity.getId()); meetClasses.setClassesId(classId); meetClassesMapper.insert(meetClasses); }); return Result.ok("添加成功"); } /** * 修改 * @param form * @return */ @Override public Result update(MeetForm form) { Meet entity = baseMapper.selectById(form.getId()); // 为空抛IllegalArgumentException,做全局异常处理 Assert.notNull(entity, "记录不存在"); BeanUtils.copyProperties(form, entity); // 先删除再新增 new LambdaUpdateChainWrapper<>(meetClassesMapper) .eq(MeetClasses::getMeetId, entity.getId()) .remove(); // 向会议班级中间表中插入数据 form.getClassesIds().forEach(classId -> { MeetClasses meetClasses = new MeetClasses(); meetClasses.setMeetId(entity.getId()); meetClasses.setClassesId(classId); meetClassesMapper.insert(meetClasses); }); // 如果修改成功发送mq消息 if (baseMapper.updateById(entity) > 0) { this.sendMQ(entity, entity.getUpdateVersion()); } return Result.ok("修改成功"); } /** * 批量删除 * @param ids * @return */ @Override public Result remove(List ids) { baseMapper.deleteBatchIds(ids); return Result.ok("删除成功"); } /** * id删除 * @param id * @return */ @Override public Result removeById(String id) { baseMapper.deleteById(id); return Result.ok("删除成功"); } /** * 教师分页查询 * @param query * @return */ @Override public Result page(MeetQuery query) { Integer userId = webContext.getCurrentUser().getId(); //查自己的会议 List classes = new LambdaQueryChainWrapper<>(classesUserMapper) .eq(ClassesUser::getUserId, userId) .eq(ClassesUser::getTeacher, Boolean.TRUE) .list(); List classesIds = classes.stream().map(ClassesUser::getClassesId).collect(Collectors.toList()); if (CollectionUtils.isEmpty(classesIds) && 3 != webContext.getCurrentUser().getRole()) { throw new RuntimeException("您暂时无法访问该页面"); } query.setClassesIds(classesIds); IPage page = PageUtil.getPage(query, MeetVO.class); baseMapper.teacherPage(page, query); page.getRecords().forEach(vo -> { if (! CollectionUtils.isEmpty(vo.getClassesIds())) { // 查主讲老师 List teacherNames = classesUserMapper.getTeachersByClassesIds(vo.getClassesIds()); if (! CollectionUtils.isEmpty(teacherNames)) { vo.setTeacherNamesStr(teacherNames.stream().collect(Collectors.joining("、"))); } } }); return Result.ok().data(page.getRecords()).total(page.getTotal()); } /** * 学生分页查询 * @param query * @return */ @Override public Result studentPage(MeetQuery query) { Integer userId = webContext.getCurrentUser().getId(); if (CollectionUtils.isEmpty(query.getClassesIds())) { //查出学生所在班级 List classes = classesUserMapper.getClassesByUserId(userId); if(CollectionUtils.isEmpty(classes)){ return Result.fail(500, "您暂未加入班级"); } query.setClassesIds(classes); } IPage page = PageUtil.getPage(query, MeetVO.class); baseMapper.studentPage(page, query); for (MeetVO vo : page.getRecords()) { if (! CollectionUtils.isEmpty(vo.getClassesIds())) { // 查主讲老师 List teacherNames = classesUserMapper.getTeachersByClassesIds(vo.getClassesIds()); if (! CollectionUtils.isEmpty(teacherNames)) { vo.setTeacherNamesStr(teacherNames.stream().collect(Collectors.joining("、"))); } } } return Result.ok().data(page.getRecords()).total(page.getTotal()); } @Override public Result start(MeetForm form) { Meet entity = baseMapper.selectById(form.getId()); // 为空抛IllegalArgumentException,做全局异常处理 Assert.notNull(entity, "记录不存在"); // 不使用updateById这种方式,避免乐观锁加一。 new LambdaUpdateChainWrapper<>(meetMapper) .eq(Meet::getId, entity.getId()) .set(Meet::getStatus,form.getStatus()) .update(); return Result.ok(); } /** * 根据id查找 * @param id * @return */ @Override public Result detail(Integer id) { Meet vo = baseMapper.getById(id); Assert.notNull(vo, "记录不存在"); if(vo.getStatus().equals(MeetStatusEnum.Starting.getCode())){ Integer userId = webContext.getCurrentUser().getId(); //验证有没有重复进入(重复进入会导致上课次数增多) QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("meet_id",id); queryWrapper.eq("student_id",userId); queryWrapper.eq("version",vo.getUpdateVersion()); MeetStudent one = meetStudentMapper.selectOne(queryWrapper); if(one != null){ return Result.ok(); } //增加学生上课记录 MeetStudent meetStudent = new MeetStudent(); meetStudent.setMeetId(id); meetStudent.setStudentId(userId); meetStudent.setCreateTime(new Date()); meetStudent.setStartTime(vo.getStartTime()); meetStudent.setVersion(vo.getUpdateVersion()); meetStudent.setMeetName(vo.getMeetName()); //TODO:暂时处理,后期考虑jitsiApi meetStudent.setDuringTime(0L); meetStudentMapper.insert(meetStudent); //学生学习档案更新 StudyRecord studyRecord = studyRecordMapper.getByStudentId(userId); if(studyRecord ==null){ StudyRecord record = new StudyRecord(); record.setMeetCount(0); record.setStudyTime(0L); record.setStudentId(userId); studyRecordMapper.insert(record); }else { studyRecord.setMeetCount(studyRecord.getMeetCount()+1); studyRecordMapper.updateById(studyRecord); } return Result.ok(); }else { return Result.fail(SystemCode.InnerError.getCode(),"房间尚未开始或已结束"); } } /** * 列表 * @return */ @Override public Result all() { List entities = baseMapper.selectList(null); List vos = entities.stream() .map(entity -> MeetVO.getVoByEntity(entity, null)) .collect(Collectors.toList()); return Result.ok().data(vos); } @Override public Result getStudentList(Integer meetId, String keyword) { List studentList = baseMapper.getStudentList(meetId, keyword); return Result.ok().data(studentList); } @Override public Result getStudentClasses() { Integer userId = webContext.getCurrentUser().getId(); List classes = classesUserMapper.getClassesByUserId1(userId); return Result.ok().data(classes); } /** * 发送mq消息 * * @param entity 考试实体类 * @param version 乐观锁版本 */ public void sendMQ(Meet entity, Integer version) { MeetStatusMsg finishedMsg = new MeetStatusMsg(); finishedMsg.setVersion(version); finishedMsg.setMeetId(entity.getId()); finishedMsg.setMeetStatus(MeetStatusEnum.End.getCode()); producer.meetMsg(entity.getId(), JSON.toJSONString(finishedMsg), DateTimeUtil.getTwoTimeDiffMS(entity.getEndTime(), new Date())); } }