diff --git a/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourseStudentSigninSetting.java b/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourseStudentSigninSetting.java index 7803491b..b7f212b0 100644 --- a/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourseStudentSigninSetting.java +++ b/web/src/main/java/com/ibeetl/jlw/entity/TeacherOpenCourseStudentSigninSetting.java @@ -30,6 +30,9 @@ public class TeacherOpenCourseStudentSigninSetting extends BaseEntity{ @Dict(type="school_class.class_name.class_status=1") private String schoolClassIds ; + + // 所有班级标识 + public static String ALL_SCHOOL_CLASS_IDS_SIGN = "ALL"; //签到方式 (数据字典 student_signin_type) @Dict(type="student_signin_type") diff --git a/web/src/main/java/com/ibeetl/jlw/entity/dto/TeacherOpenCourseStudentSigninLogSigninDTO.java b/web/src/main/java/com/ibeetl/jlw/entity/dto/TeacherOpenCourseStudentSigninLogSigninDTO.java index 15d7be62..6a587202 100644 --- a/web/src/main/java/com/ibeetl/jlw/entity/dto/TeacherOpenCourseStudentSigninLogSigninDTO.java +++ b/web/src/main/java/com/ibeetl/jlw/entity/dto/TeacherOpenCourseStudentSigninLogSigninDTO.java @@ -32,13 +32,12 @@ public class TeacherOpenCourseStudentSigninLogSigninDTO { private TeacherOpenCourseStudentSigninLogTypeEnum teacherOpenCourseStudentSigninLogType; @NotEmpty(message = "签到验证码不能为空", groups = { CodeClass.class }) - private String code; + private String verificationCode; @NotEmpty(message = "签到备注不能为空", groups = { ManualClass.class }) private String teacherOpenCourseStudentSigninLogRemark; - // 是否缺席 - + @NotNull(message = "是否缺席不能为空", groups = { ManualClass.class }) private Boolean isAbsent; diff --git a/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseStudentSigninLogService.java b/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseStudentSigninLogService.java index e18efbda..abbfc4fe 100644 --- a/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseStudentSigninLogService.java +++ b/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseStudentSigninLogService.java @@ -8,12 +8,16 @@ import cn.hutool.json.JSONUtil; import cn.jlw.util.ToolUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.ibeetl.admin.core.entity.CoreUser; import com.ibeetl.admin.core.service.CoreBaseService; import com.ibeetl.admin.core.util.PlatformException; import com.ibeetl.admin.core.web.JsonResult; import com.ibeetl.admin.core.web.JsonReturnCode; +import com.ibeetl.jlw.dao.StudentDao; import com.ibeetl.jlw.dao.TeacherOpenCourseStudentSigninLogDao; import com.ibeetl.jlw.dao.TeacherOpenCourseStudentSigninSettingDao; +import com.ibeetl.jlw.entity.Student; +import com.ibeetl.jlw.entity.TeacherOpenCourseMergeStudent; import com.ibeetl.jlw.entity.TeacherOpenCourseStudentSigninLog; import com.ibeetl.jlw.entity.TeacherOpenCourseStudentSigninSetting; import com.ibeetl.jlw.entity.dto.TeacherOpenCourseStudentSigninLogSigninDTO; @@ -28,13 +32,18 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import javax.validation.constraints.NotNull; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.List; +import static cn.hutool.core.net.Ipv4Util.IP_SPLIT_MARK; +import static cn.hutool.core.net.NetUtil.ipv4ToLong; import static cn.jlw.util.IpUtils.getIpAddr; import static com.ibeetl.admin.core.util.servlet.ServletUtils.getRequest; import static com.ibeetl.admin.core.util.user.CacheUserUtil.getUser; +import static com.ibeetl.jlw.entity.TeacherOpenCourseStudentSigninSetting.ALL_SCHOOL_CLASS_IDS_SIGN; /** * 学生签到记录 Service @@ -49,6 +58,9 @@ public class TeacherOpenCourseStudentSigninLogService extends CoreBaseServicequeryByCondition(PageQuery query){ PageQuery ret = teacherOpenCourseStudentSigninLogDao.queryByCondition(query); queryListAfter(ret.getList()); @@ -168,20 +180,12 @@ public class TeacherOpenCourseStudentSigninLogService extends CoreBaseService signinSettingList = teacherOpenCourseStudentSigninSettingDao.getByIds(signinDTO.getTeacherOpenCourseStudentSigninSettingId()); @@ -190,28 +194,195 @@ public class TeacherOpenCourseStudentSigninLogService extends CoreBaseService item.getTeacherOpenCourseId().equals(signinSetting.getTeacherOpenCourseId())); + + Assert.isTrue(isMatchCourse, "未加入到该课程中,开课ID或学生ID有误!"); + + switch (signinDTO.getTeacherOpenCourseStudentSigninLogType()) { + case ip_signin: { // IP签到 + ipSignInHandler(signinDTO, signinSetting); + }break; + case manual_signin: { // 手动签到。教师端操作 + manualSignInHandler(signinDTO, signinSetting); + }break; + case code_signin: { // 验证码签到 + codeSignInHandler(signinDTO, signinSetting); + }break; + } + } + + /** + * 判断班级ID是否在集合中 + * + * @param schoolClassId + * @param signinSetting + * @return + */ + private boolean schoolClassIdJudgment(@NotNull(message = "班级ID不能为空!") Long schoolClassId, + @NotNull(message = "签到配置不能为空!") TeacherOpenCourseStudentSigninSetting signinSetting) { + Assert.notEmpty(signinSetting.getSchoolClassIds(), "班级ID集合不能为空!"); + + if(signinSetting.getSchoolClassIds().equals(ALL_SCHOOL_CLASS_IDS_SIGN)) { + return true; + } + + // 分割班级ID,逐一比对,只要有一个符合要求,就返回true + return Arrays.stream(signinSetting.getSchoolClassIds().split(",")) + .anyMatch(item -> item.equals(schoolClassId)); + } + + /** + * IP签到 + * + * @param signinDTO + * @param signinSetting + */ + public void ipSignInHandler(@Validated TeacherOpenCourseStudentSigninLogSigninDTO signinDTO, + @NotNull(message = "签到配置不能为空!") TeacherOpenCourseStudentSigninSetting signinSetting) { + + // 获取登录用户,教师身份不支持IP签到,教师只能手动签到 + CoreUser user = getUser(); + Assert.isTrue(user.isStudent(), "IP签到方式,只允许学生进行操作!"); + + // 获取学生信息 + Student student = studentDao.getByUserId(user.getId()); + Assert.isTrue(schoolClassIdJudgment(student.getClassId(), signinSetting), "该学生所在的班级不符合签到要求!"); + + // 传入的签到类型 + TeacherOpenCourseStudentSigninLogTypeEnum signinLogTypeEnum = signinDTO.getTeacherOpenCourseStudentSigninLogType(); + String inputSignInType = signinLogTypeEnum.name(); + + // 根据type类型 验证Bean + BeanValidationResult beanValidationResult = ValidationUtil.warpValidate(signinDTO, signinLogTypeEnum.getClazz()); + Assert.isTrue(beanValidationResult.isSuccess(), JSONUtil.toJsonStr(beanValidationResult.getErrorMessages())); // 通过签到配置ID查询到的类型,是否与传入的参数一致 Assert.isTrue(signinSetting.getTeacherOpenCourseStudentSigninSettingType().equalsIgnoreCase(inputSignInType), "签到类型不匹配!"); + // 获取到真实的IP + String myIpAddress = getIpAddr(getRequest()); + // 我的IPv4转long类型 + long myIpLong = ipv4ToLong(myIpAddress); + + // 是否在IP段区间 + Boolean isRangeInner = false; + // 处理IP段,判断IP是否在这个区间内 192.168.1.1-192.168.1.100,192.168.2.1-192.168.2.100 + for (String range : signinSetting.getTeacherOpenCourseStudentSigninSettingValue().split(",")) { + // 两个IP段。开始IP-结束IP + String[] ips = range.split(IP_SPLIT_MARK); + long startIpLong = ipv4ToLong(ips[0]); + long endIpLong = ipv4ToLong(ips[1]); + // 在区间内,则打标记 + if((startIpLong >= myIpLong) && (myIpLong <= endIpLong)) { + isRangeInner = true; + } + } + + // 断言,如果IP不在指定的IP段内,则添加失败,异常信息丢给前台 + Assert.isTrue(isRangeInner, "您的IP地址:{},不在指定的IP段内!"); + // 构建实体 TeacherOpenCourseStudentSigninLogQuery signinLogQuery = new TeacherOpenCourseStudentSigninLogQuery(); signinLogQuery.setTeacherOpenCourseId(signinSetting.getTeacherOpenCourseId()); signinLogQuery.setTeacherOpenCourseStudentSigninLogType(inputSignInType); signinLogQuery.setTeacherOpenCourseStudentSigninLogIp(myIpAddress); signinLogQuery.setStudentId(signinDTO.getStudentId()); + // 学生签到记录添加 + add(signinLogQuery); + } + + /** + * 手动签到 + * + * @param signinDTO + * @param signinSetting + */ + public void manualSignInHandler(@Validated TeacherOpenCourseStudentSigninLogSigninDTO signinDTO, + @NotNull(message = "签到配置不能为空!") TeacherOpenCourseStudentSigninSetting signinSetting) { + + TeacherOpenCourseStudentSigninLogTypeEnum signinLogTypeEnum = signinDTO.getTeacherOpenCourseStudentSigninLogType(); + // 传入的签到类型 + String inputSignInType = signinLogTypeEnum.name(); + + // 根据type类型 验证Bean + BeanValidationResult beanValidationResult = ValidationUtil.warpValidate(signinDTO, signinLogTypeEnum.getClazz()); + Assert.isTrue(beanValidationResult.isSuccess(), JSONUtil.toJsonStr(beanValidationResult.getErrorMessages())); + + // 通过签到配置ID查询到的类型,是否与传入的参数一致 + Assert.isTrue(signinSetting.getTeacherOpenCourseStudentSigninSettingType().equalsIgnoreCase(inputSignInType), "签到类型不匹配!"); + + // 构建实体 + TeacherOpenCourseStudentSigninLogQuery signinLogQuery = new TeacherOpenCourseStudentSigninLogQuery(); + signinLogQuery.setTeacherOpenCourseId(signinSetting.getTeacherOpenCourseId()); + signinLogQuery.setTeacherOpenCourseStudentSigninLogType(inputSignInType); + signinLogQuery.setTeacherOpenCourseStudentSigninLogIp(getIpAddr(getRequest())); + signinLogQuery.setStudentId(signinDTO.getStudentId()); // 是否缺席 if(BooleanUtil.isTrue(signinDTO.getIsAbsent())) { + // 断言验证缺席时候,必传的字段 BeanValidationResult isAbsentValidationResult = ValidationUtil.warpValidate(signinDTO, ManualClass.class); Assert.isTrue(isAbsentValidationResult.isSuccess(), JSONUtil.toJsonStr(isAbsentValidationResult.getErrorMessages())); signinLogQuery.setTeacherOpenCourseStudentSigninLogRemark(signinDTO.getTeacherOpenCourseStudentSigninLogRemark()); } + // 学生签到记录添加 + add(signinLogQuery); + } + + /** + * 验证码签到 + * + * @param signinDTO + * @param signinSetting + */ + public void codeSignInHandler(@Validated TeacherOpenCourseStudentSigninLogSigninDTO signinDTO, + @NotNull(message = "签到配置不能为空!") TeacherOpenCourseStudentSigninSetting signinSetting) { + + // 获取登录用户,教师身份不支持IP签到,教师只能手动签到 + CoreUser user = getUser(); + Assert.isTrue(user.isStudent(), "验证码签到方式,只允许学生进行操作!"); + + // 获取学生信息 + Student student = studentDao.getByUserId(user.getId()); + Assert.isTrue(schoolClassIdJudgment(student.getClassId(), signinSetting), "该学生所在的班级不符合签到要求!"); + + TeacherOpenCourseStudentSigninLogTypeEnum signinLogTypeEnum = signinDTO.getTeacherOpenCourseStudentSigninLogType(); + // 传入的签到类型 + String inputSignInType = signinLogTypeEnum.name(); + + // 根据type类型 验证Bean + BeanValidationResult beanValidationResult = ValidationUtil.warpValidate(signinDTO, signinLogTypeEnum.getClazz()); + Assert.isTrue(beanValidationResult.isSuccess(), JSONUtil.toJsonStr(beanValidationResult.getErrorMessages())); + + // 通过签到配置ID查询到的类型,是否与传入的参数一致 + Assert.isTrue(signinSetting.getTeacherOpenCourseStudentSigninSettingType().equalsIgnoreCase(inputSignInType), "签到类型不匹配!"); + + // 断言,验证码验证 + boolean verificationSuccess = signinSetting.getTeacherOpenCourseStudentSigninSettingValue().equals(signinDTO.getVerificationCode()); + Assert.isTrue(verificationSuccess, "错误的验证码,签到失败!"); + + // 构建实体 + TeacherOpenCourseStudentSigninLogQuery signinLogQuery = new TeacherOpenCourseStudentSigninLogQuery(); + signinLogQuery.setTeacherOpenCourseId(signinSetting.getTeacherOpenCourseId()); + signinLogQuery.setTeacherOpenCourseStudentSigninLogType(inputSignInType); + signinLogQuery.setTeacherOpenCourseStudentSigninLogIp(getIpAddr(getRequest())); + signinLogQuery.setStudentId(signinDTO.getStudentId()); // 学生签到记录添加 add(signinLogQuery); } + + /** + * 签到日志查询 + * TODO mlx 签到日志查询 + * @param signinDTO + * @return + */ + public Object signinLog(TeacherOpenCourseStudentSigninLogSigninDTO signinDTO) { + throw new PlatformException("签到日志接口未实现!"); + } } diff --git a/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseStudentSigninLogController.java b/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseStudentSigninLogController.java index 9fc9e2bc..31227f37 100644 --- a/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseStudentSigninLogController.java +++ b/web/src/main/java/com/ibeetl/jlw/web/TeacherOpenCourseStudentSigninLogController.java @@ -192,7 +192,7 @@ public class TeacherOpenCourseStudentSigninLogController{ } /** - * 学生端-开始签到(签到统一接口) + * 学生端-教师端-开始签到(签到统一接口) * @param signinDTO 签到DTO * @return */ @@ -201,7 +201,19 @@ public class TeacherOpenCourseStudentSigninLogController{ @ResponseBody public JsonResult signin(TeacherOpenCourseStudentSigninLogSigninDTO signinDTO) { teacherOpenCourseStudentSigninLogService.signin(signinDTO); - return JsonResult.successMessage("签到成功!"); + return JsonResult.success(); + } + + /** + * 教师端-签到日志 + * @param signinDTO 签到DTO + * @return + */ + @PostMapping(MODEL + "/signinLog.json") + @Function("teacherOpenCourseStudentSigninLog.add") + @ResponseBody + public JsonResult signinLog(TeacherOpenCourseStudentSigninLogSigninDTO signinDTO) { + return JsonResult.success(teacherOpenCourseStudentSigninLogService.signinLog(signinDTO)); } }