package com.xjrsoft.module.teacher.service.impl; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.github.yulichang.base.MPJBaseServiceImpl; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.xjrsoft.common.enums.DeleteMark; import com.xjrsoft.common.exception.MyException; import com.xjrsoft.common.model.result.RT; import com.xjrsoft.common.page.ConventPage; import com.xjrsoft.common.utils.LocalDateTimeUtil; import com.xjrsoft.common.utils.VoToColumnUtil; import com.xjrsoft.config.CommonPropertiesConfig; import com.xjrsoft.module.base.entity.BaseCourseSubject; import com.xjrsoft.module.base.entity.BaseUserStudent; import com.xjrsoft.module.base.service.IBaseUserStudentService; import com.xjrsoft.module.organization.dto.WeChatSendMessageDto; import com.xjrsoft.module.organization.entity.User; import com.xjrsoft.module.organization.entity.UserStudent; import com.xjrsoft.module.organization.mapper.UserMapper; import com.xjrsoft.module.organization.service.IWeChatService; import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll; import com.xjrsoft.module.student.service.IBaseStudentSchoolRollService; import com.xjrsoft.module.system.entity.File; import com.xjrsoft.module.system.service.IFileService; import com.xjrsoft.module.teacher.dto.AddClassInternshipDynamicDto; import com.xjrsoft.module.teacher.dto.AddClassInternshipDynamicReadDto; import com.xjrsoft.module.teacher.dto.ClassInternshipDynamicPageDto; import com.xjrsoft.module.teacher.dto.ClassInternshipDynamicReadListDto; import com.xjrsoft.module.teacher.entity.*; import com.xjrsoft.module.teacher.mapper.ClassInternshipDynamicClassMapper; import com.xjrsoft.module.teacher.mapper.ClassInternshipDynamicMapper; import com.xjrsoft.module.teacher.mapper.ClassInternshipDynamicReadMapper; import com.xjrsoft.module.teacher.mapper.XjrUserMapper; import com.xjrsoft.module.teacher.service.IClassInternshipDynamicService; import com.xjrsoft.module.teacher.vo.ClassHomeworkPageVo; import com.xjrsoft.module.teacher.vo.ClassHomeworkReadListVo; import com.xjrsoft.module.teacher.vo.ClassInternshipDynamicPageVo; import com.xjrsoft.module.teacher.vo.ClassInternshipDynamicReadListVo; import com.xjrsoft.module.workflow.entity.WorkflowFormRelation; import lombok.AllArgsConstructor; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.camunda.bpm.engine.history.HistoricProcessInstance; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.*; import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; import com.baomidou.mybatisplus.core.toolkit.Wrappers; /** * @title: 实习动态表 * @Author szs * @Date: 2025-04-27 * @Version 1.0 */ @Service @AllArgsConstructor public class ClassInternshipDynamicServiceImpl extends MPJBaseServiceImpl implements IClassInternshipDynamicService { private final ClassInternshipDynamicClassMapper classInternshipDynamicClassMapper; private final UserMapper userMapper; private final IWeChatService weChatService; private final IBaseStudentSchoolRollService rollService; private final IBaseUserStudentService userStudentService; private final IFileService fileService; private final XjrUserMapper xjrUserMapper; private final ClassInternshipDynamicReadMapper classInternshipDynamicReadMapper; private final CommonPropertiesConfig commonPropertiesConfig; @Override public IPage pageClassInternshipDynamic(ClassInternshipDynamicPageDto dto) { // 处理日期 if (ObjectUtils.isNotEmpty(dto.getEndDate())) { dto.setEndDate(dto.getEndDate().plusDays(1)); } // 需要划分权限 // 教职工看到自己发的所有的,学生和家长看到自己的 List roleList = StpUtil.getRoleList(); long userId = StpUtil.getLoginIdAsLong(); // 角色存在标记 boolean isParent = roleList.contains("PARENT"); boolean isStudent = roleList.contains("STUDENT"); boolean isTeacher = roleList.contains("TEACHER"); List studentClassIds = new ArrayList<>(); List parentClassIds = new ArrayList<>(); // 获取学生班级 ID if (isStudent) { studentClassIds.add(rollService.getClassIdByUserId(userId)); } // 获取家长关联的学生班级 ID if (isParent) { List userStudents = userStudentService.list( new QueryWrapper().lambda() .eq(BaseUserStudent::getUserId, userId) ); for (BaseUserStudent userStudent : userStudents) { Long classId = rollService.getClassIdByUserId(userStudent.getStudentId()); if (classId != null) { parentClassIds.add(classId); } } } MPJLambdaWrapper queryWrapper = new MPJLambdaWrapper<>(); queryWrapper.distinct() .select(ClassInternshipDynamic::getId) .select(ClassInternshipDynamic.class, x -> VoToColumnUtil.fieldsToColumns(ClassInternshipDynamicPageVo.class).contains(x.getProperty())) .select("(SELECT GROUP_CONCAT(b.name) FROM class_internship_dynamic_class a INNER JOIN base_class b ON a.class_id = b.id WHERE a.class_internship_dynamic_id = t.id) AS class_id_cns") .select("(SELECT GROUP_CONCAT(a.class_id) FROM class_internship_dynamic_class a WHERE a.class_internship_dynamic_id = t.id) AS class_ids") .leftJoin(XjrUser.class, XjrUser::getId, ClassInternshipDynamic::getPublisherId, wrapper -> wrapper.selectAs(XjrUser::getName, ClassInternshipDynamicPageVo::getPublisherIdCn) ) .innerJoin(ClassInternshipDynamicClass.class, ClassInternshipDynamicClass::getClassInternshipDynamicId, ClassInternshipDynamic::getId) .ge(ObjectUtils.isNotEmpty(dto.getStartDate()), ClassInternshipDynamic::getCreateDate, dto.getStartDate()) .le(ObjectUtils.isNotEmpty(dto.getEndDate()), ClassInternshipDynamic::getCreateDate, dto.getEndDate()) .orderByDesc(ClassInternshipDynamic::getCreateDate); // 收集所有角色的 OR 条件 List>> roleConditions = new ArrayList<>(); boolean hasConditions = false; // 教师条件 if (isTeacher) { roleConditions.add(wrapper -> wrapper .eq(ClassInternshipDynamic::getPublisherId, userId)); hasConditions = true; } // 学生条件 if (isStudent && CollectionUtils.isNotEmpty(studentClassIds)) { roleConditions.add(wrapper -> wrapper .in(ClassInternshipDynamicClass::getClassId, studentClassIds) .and(innerWrapper -> innerWrapper .eq(ClassInternshipDynamic::getRoleType, 1) .or() .eq(ClassInternshipDynamic::getRoleType, 3) )); hasConditions = true; } // 家长条件 if (isParent && CollectionUtils.isNotEmpty(parentClassIds)) { roleConditions.add(wrapper -> wrapper .in(ClassInternshipDynamicClass::getClassId, parentClassIds) .and(innerWrapper -> innerWrapper .eq(ClassInternshipDynamic::getRoleType, 2) .or() .eq(ClassInternshipDynamic::getRoleType, 3) )); hasConditions = true; } // 如果有任意角色条件,则用 and 包裹所有 or 条件 if (hasConditions) { queryWrapper.and(wrapper -> { if (!roleConditions.isEmpty()) { // 从第二个条件开始,前面已经有一个条件了 Iterator>> iterator = roleConditions.iterator(); iterator.next().accept(wrapper); // 添加第一个条件 while (iterator.hasNext()) { wrapper.or(); // 开启 OR 分支 iterator.next().accept(wrapper); } } }); } else { queryWrapper.eq("1", "0"); // 无权限 } // int roleType = 1; // // List classIds = new ArrayList<>(); // // if (roleList.contains("PARENT")) { // roleType = 4; // List list = userStudentService.list(new QueryWrapper().lambda().eq(BaseUserStudent::getUserId, userId)); // for (BaseUserStudent userStudent : list) { // classIds.add(rollService.getClassIdByUserId(userStudent.getStudentId())); // } // } // if (roleList.contains("STUDENT")) { // roleType = 3; // classIds.add(rollService.getClassIdByUserId(userId)); // } // if (roleList.contains("TEACHER")) { // roleType = 2; // } // // MPJLambdaWrapper queryWrapper = new MPJLambdaWrapper<>(); // queryWrapper // .distinct() // .select(ClassInternshipDynamic::getId) // .select(ClassInternshipDynamic.class,x -> VoToColumnUtil.fieldsToColumns(ClassInternshipDynamicPageVo.class).contains(x.getProperty())) // .select("(select\n" + // " group_concat(b.name)\n" + // " from class_internship_dynamic_class a\n" + // " inner join base_class b on a.class_id = b.id\n" + // " where a.class_internship_dynamic_id = t.id\n" + // " ) as class_id_cns") // .select("(select\n" + // " group_concat(a.class_id)\n" + // " from class_internship_dynamic_class a\n" + // " where a.class_internship_dynamic_id = t.id\n" + // " ) as class_ids") // .leftJoin(XjrUser.class, XjrUser::getId, ClassInternshipDynamic::getPublisherId, // wrapper -> wrapper // .selectAs(XjrUser::getName, ClassInternshipDynamicPageVo::getPublisherIdCn) // ) // .ge(ObjectUtils.isNotEmpty(dto.getStartDate()), ClassInternshipDynamic::getCreateDate, dto.getStartDate()) // .le(ObjectUtils.isNotEmpty(dto.getEndDate()), ClassInternshipDynamic::getCreateDate, dto.getEndDate().plusDays(1)) // .orderByDesc(ClassInternshipDynamic::getCreateDate) // ; // if(roleType == 2){ // queryWrapper // .eq(ClassInternshipDynamic::getPublisherId, userId); // } // // if(roleType == 3){ // queryWrapper // .innerJoin(ClassInternshipDynamicClass.class, ClassInternshipDynamicClass::getClassInternshipDynamicId, ClassInternshipDynamic::getId) // .in(CollectionUtils.isNotEmpty(classIds), ClassInternshipDynamicClass::getClassId, classIds) // .and( // wrapper -> wrapper // .eq(ClassInternshipDynamic::getRoleType, 1) // .or() // .eq(ClassInternshipDynamic::getRoleType, 3) // ) // ; // } // // if(roleType == 4){ // queryWrapper // .innerJoin(ClassInternshipDynamicClass.class, ClassInternshipDynamicClass::getClassInternshipDynamicId, ClassInternshipDynamic::getId) // .in(CollectionUtils.isNotEmpty(classIds), ClassInternshipDynamicClass::getClassId, classIds) // .and( // wrapper -> wrapper // .eq(ClassInternshipDynamic::getRoleType, 2) // .or() // .eq(ClassInternshipDynamic::getRoleType, 3) // ) // ; // } IPage page = this.selectJoinListPage(ConventPage.getPage(dto), ClassInternshipDynamicPageVo.class, queryWrapper); for (ClassInternshipDynamicPageVo vo : page.getRecords()) { if (ObjectUtils.isNotEmpty(vo.getFolderId())) { List files = fileService.list(Wrappers.query().lambda().eq(File::getFolderId, vo.getFolderId())); vo.setFiles(files); } } return page; } @Override @Transactional(rollbackFor = Exception.class) public Boolean addClassInternshipDynamic(AddClassInternshipDynamicDto dto) { Long loginId = StpUtil.getLoginIdAsLong(); LocalDateTime nowLocalDateTime = LocalDateTime.now(); ClassInternshipDynamic classInternshipDynamic = BeanUtil.toBean(dto, ClassInternshipDynamic.class); classInternshipDynamic.setPublisherId(loginId); classInternshipDynamic.setCreateUserId(loginId); classInternshipDynamic.setCreateDate(nowLocalDateTime); this.save(classInternshipDynamic); for (Long classid : dto.getClassIds()) { ClassInternshipDynamicClass classInternshipDynamicClass = new ClassInternshipDynamicClass(); classInternshipDynamicClass.setClassInternshipDynamicId(classInternshipDynamic.getId()); classInternshipDynamicClass.setClassId(classid); classInternshipDynamicClass.setCreateUserId(loginId); classInternshipDynamicClass.setCreateDate(nowLocalDateTime); classInternshipDynamicClassMapper.insert(classInternshipDynamicClass); } // 发送通知 Set combinedUserSet = new LinkedHashSet<>(); // 找到班上所有的学生 MPJLambdaWrapper stuMPJLambdaWrapper = new MPJLambdaWrapper<>(); stuMPJLambdaWrapper .distinct() .select(User::getId) .select(User.class, x -> VoToColumnUtil.fieldsToColumns(User.class).contains(x.getProperty())) .innerJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, User::getId) .isNotNull(User::getOpenId) .in(BaseStudentSchoolRoll::getClassId, dto.getClassIds()); List stuList = userMapper.selectJoinList(User.class, stuMPJLambdaWrapper); // 找到班上所有的学生的家长 MPJLambdaWrapper parentMPJLambdaWrapper = new MPJLambdaWrapper<>(); parentMPJLambdaWrapper .distinct() .disableSubLogicDel() .select(User::getId) .select(User.class, x -> VoToColumnUtil.fieldsToColumns(User.class).contains(x.getProperty())) .innerJoin(UserStudent.class, UserStudent::getUserId, User::getId) .innerJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, UserStudent::getStudentId) .innerJoin(WorkflowFormRelation.class, WorkflowFormRelation::getFormKeyValue, UserStudent::getId) .in(BaseStudentSchoolRoll::getClassId, dto.getClassIds()) .eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_COMPLETED) .isNotNull(User::getOpenId) ; List parentList = userMapper.selectJoinList(User.class, parentMPJLambdaWrapper); // 根据 roleType 添加对应的角色对象到集合中 if (ObjectUtils.isNotEmpty(dto.getRoleType())) { int roleType = dto.getRoleType(); if (roleType == 1 || roleType == 3) { combinedUserSet.addAll(stuList); } if (roleType == 2 || roleType == 3) { combinedUserSet.addAll(parentList); } } // 发布作业的教师 User releaseUser = userMapper.selectById(loginId); for (User user : combinedUserSet) { try { WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto(); weChatSendMessageDto.setUserId(user.getOpenId()); weChatSendMessageDto.setTemplateId("qmpXORPM1Cocqn503Qa4On6BJhR92UZ00eod2-6IcGo"); weChatSendMessageDto.setUrl(StrUtil.format("{}/pages/student/practice/detail?id={}", commonPropertiesConfig.getDomainApp(), classInternshipDynamic.getId())); weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + ""); JSONObject paramJson = new JSONObject(); JSONObject thing23 = new JSONObject(); thing23.put("value", dto.getTitle()); paramJson.put("thing23", thing23); JSONObject thing29 = new JSONObject(); thing29.put("value", releaseUser.getName()); paramJson.put("thing29", thing29); JSONObject time17Json = new JSONObject(); time17Json.put("value", LocalDateTimeUtil.format(nowLocalDateTime, "yyyy-MM-dd HH:mm:ss")); paramJson.put("time17", time17Json); weChatSendMessageDto.setContent(paramJson); weChatService.sendTemplateMessage(weChatSendMessageDto); } catch (Exception e) { log.error("发送消息错误,Error processing event data", e); } } return true; } @Override public List listClassInternshipDynamic(ClassInternshipDynamicReadListDto dto) { ClassInternshipDynamic classInternshipDynamic = this.getById(dto.getClassInternshipDynamicId()); if (ObjectUtils.isEmpty(classInternshipDynamic)) { throw new MyException("当前作业被修改,请刷新重试"); } // 获取当前所有班级所有的学生 MPJLambdaWrapper xjrUserMPJLambdaWrapper = new MPJLambdaWrapper<>(); xjrUserMPJLambdaWrapper .selectAs(XjrUser::getId, ClassInternshipDynamicReadListVo::getUserId) .selectAs(XjrUser::getName, ClassInternshipDynamicReadListVo::getUserIdCn) .select("0 as is_read") .innerJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, XjrUser::getId) ; if (ObjectUtils.isEmpty(dto.getClassId())) { LambdaQueryWrapper classLambdaQueryWrapper = new LambdaQueryWrapper<>(); classLambdaQueryWrapper .eq(ClassInternshipDynamicClass::getClassInternshipDynamicId, dto.getClassInternshipDynamicId()) .eq(ClassInternshipDynamicClass::getDeleteMark, DeleteMark.NODELETE.getCode()) ; List classeList = classInternshipDynamicClassMapper.selectList(classLambdaQueryWrapper); if (CollectionUtils.isEmpty(classeList)) { return new ArrayList<>(); } // 提取 classId 并去重 List uniqueClassIds = classeList.stream() .map(ClassInternshipDynamicClass::getClassId) // 提取 classId .distinct() // 去重 .collect(Collectors.toList()); // 收集为 List xjrUserMPJLambdaWrapper .in(BaseStudentSchoolRoll::getClassId, uniqueClassIds); } else { xjrUserMPJLambdaWrapper .eq(BaseStudentSchoolRoll::getClassId, dto.getClassId()); } List list = xjrUserMapper.selectJoinList(ClassInternshipDynamicReadListVo.class, xjrUserMPJLambdaWrapper); // 获取当前作业已经阅读情况 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper .select(ClassInternshipDynamicRead.class, x -> VoToColumnUtil.fieldsToColumns(ClassInternshipDynamicRead.class).contains(x.getProperty())) .eq(ClassInternshipDynamicRead::getClassInternshipDynamicId, dto.getClassInternshipDynamicId()) .orderByDesc(ClassInternshipDynamicRead::getId) ; List readList = classInternshipDynamicReadMapper.selectList(queryWrapper); Map readMap = readList.stream() .collect(Collectors.toMap(ClassInternshipDynamicRead::getUserId, ClassInternshipDynamicRead::getCreateDate, (l1, l2) -> l2)); if (MapUtils.isNotEmpty(readMap)) { for (ClassInternshipDynamicReadListVo vo : list) { if (readMap.containsKey(vo.getUserId())) { vo.setCreateDate(readMap.get(vo.getUserId())); vo.setIsRead(1); } } } List result = new ArrayList<>(); if (ObjectUtils.isNotEmpty(dto.getIsRead())) { for (ClassInternshipDynamicReadListVo vo : list) { if (Objects.equals(vo.getIsRead(), dto.getIsRead())) { result.add(vo); } } } else { return list; } return result; } @Override @Transactional(rollbackFor = Exception.class) public Boolean readClassInternshipDynamic(AddClassInternshipDynamicReadDto dto) { Long loginId = StpUtil.getLoginIdAsLong(); // 查询用户是否已经阅读当前作业 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper .select(ClassInternshipDynamicRead.class, x -> VoToColumnUtil.fieldsToColumns(ClassInternshipDynamicRead.class).contains(x.getProperty())) .eq(ClassInternshipDynamicRead::getClassInternshipDynamicId, dto.getClassInternshipDynamicId()) .eq(ClassInternshipDynamicRead::getUserId, loginId) ; ClassInternshipDynamicRead classInternshipDynamicRead = classInternshipDynamicReadMapper.selectOne(queryWrapper); if (ObjectUtils.isEmpty(classInternshipDynamicRead)) { ClassInternshipDynamicRead insert = BeanUtil.toBean(dto, ClassInternshipDynamicRead.class); insert.setUserId(loginId); insert.setCreateDate(LocalDateTime.now()); insert.setCreateUserId(loginId); classInternshipDynamicReadMapper.insert(insert); } return true; } }