commit:同步2.2版本
@@ -14,6 +14,22 @@
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.anji-plus</groupId>
|
||||
<artifactId>spring-boot-starter-captcha</artifactId>
|
||||
<version>${ajcaptcha.version}</version>
|
||||
</dependency>
|
||||
<!-- aj-captcha 依赖data-redis作为缓存 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- 业务组件依赖 -->
|
||||
<dependency>
|
||||
<groupId>com.orangeforms</groupId>
|
||||
|
||||
@@ -132,18 +132,7 @@ public class CourseController {
|
||||
if (MyCommonUtil.existBlankArgument(courseId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
Course originalCourse = courseService.getById(courseId);
|
||||
if (originalCourse == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!courseService.remove(courseId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
return this.doDelete(courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,4 +298,20 @@ public class CourseController {
|
||||
return ResponseResult.success(BeanQuery.select(
|
||||
"courseId as id", "courseName as name").executeFrom(resultList));
|
||||
}
|
||||
|
||||
private ResponseResult<Void> doDelete(Long courseId) {
|
||||
String errorMessage;
|
||||
// 验证关联Id的数据合法性
|
||||
Course originalCourse = courseService.getById(courseId);
|
||||
if (originalCourse == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!courseService.remove(courseId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,18 +108,7 @@ public class StudentActionTransController {
|
||||
if (MyCommonUtil.existBlankArgument(transId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
StudentActionTrans originalStudentActionTrans = studentActionTransService.getById(transId);
|
||||
if (originalStudentActionTrans == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!studentActionTransService.remove(transId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
return this.doDelete(transId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,4 +152,20 @@ public class StudentActionTransController {
|
||||
StudentActionTransVo studentActionTransVo = StudentActionTrans.INSTANCE.fromModel(studentActionTrans);
|
||||
return ResponseResult.success(studentActionTransVo);
|
||||
}
|
||||
|
||||
private ResponseResult<Void> doDelete(Long transId) {
|
||||
String errorMessage;
|
||||
// 验证关联Id的数据合法性
|
||||
StudentActionTrans originalStudentActionTrans = studentActionTransService.getById(transId);
|
||||
if (originalStudentActionTrans == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!studentActionTransService.remove(transId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,18 +107,7 @@ public class StudentClassController {
|
||||
if (MyCommonUtil.existBlankArgument(classId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
StudentClass originalStudentClass = studentClassService.getById(classId);
|
||||
if (originalStudentClass == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!studentClassService.remove(classId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
return this.doDelete(classId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,13 +175,8 @@ public class StudentClassController {
|
||||
}
|
||||
Course filter = MyModelUtil.copyTo(courseDtoFilter, Course.class);
|
||||
String orderBy = MyOrderParam.buildOrderBy(orderParam, Course.class);
|
||||
List<Course> courseList;
|
||||
if (MyCommonUtil.isNotBlankOrNull(classId)) {
|
||||
courseList = courseService.getNotInCourseListByClassId(classId, filter, orderBy);
|
||||
} else {
|
||||
courseList = courseService.getCourseList(filter, orderBy);
|
||||
courseService.buildRelationForDataList(courseList, MyRelationParam.dictOnly());
|
||||
}
|
||||
List<Course> courseList =
|
||||
courseService.getNotInCourseListByClassId(classId, filter, orderBy);
|
||||
return ResponseResult.success(MyPageUtil.makeResponseData(courseList, Course.INSTANCE));
|
||||
}
|
||||
|
||||
@@ -340,13 +324,8 @@ public class StudentClassController {
|
||||
}
|
||||
Student filter = MyModelUtil.copyTo(studentDtoFilter, Student.class);
|
||||
String orderBy = MyOrderParam.buildOrderBy(orderParam, Student.class);
|
||||
List<Student> studentList;
|
||||
if (MyCommonUtil.isNotBlankOrNull(classId)) {
|
||||
studentList = studentService.getNotInStudentListByClassId(classId, filter, orderBy);
|
||||
} else {
|
||||
studentList = studentService.getStudentList(filter, orderBy);
|
||||
studentService.buildRelationForDataList(studentList, MyRelationParam.dictOnly());
|
||||
}
|
||||
List<Student> studentList =
|
||||
studentService.getNotInStudentListByClassId(classId, filter, orderBy);
|
||||
return ResponseResult.success(MyPageUtil.makeResponseData(studentList, Student.INSTANCE));
|
||||
}
|
||||
|
||||
@@ -428,4 +407,20 @@ public class StudentClassController {
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
private ResponseResult<Void> doDelete(Long classId) {
|
||||
String errorMessage;
|
||||
// 验证关联Id的数据合法性
|
||||
StudentClass originalStudentClass = studentClassService.getById(classId);
|
||||
if (originalStudentClass == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!studentClassService.remove(classId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,18 +115,7 @@ public class StudentController {
|
||||
if (MyCommonUtil.existBlankArgument(studentId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
Student originalStudent = studentService.getById(studentId);
|
||||
if (originalStudent == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!studentService.remove(studentId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
return this.doDelete(studentId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,4 +186,20 @@ public class StudentController {
|
||||
return ResponseResult.success(BeanQuery.select(
|
||||
"studentId as id", "studentName as name").executeFrom(resultList));
|
||||
}
|
||||
|
||||
private ResponseResult<Void> doDelete(Long studentId) {
|
||||
String errorMessage;
|
||||
// 验证关联Id的数据合法性
|
||||
Student originalStudent = studentService.getById(studentId);
|
||||
if (originalStudent == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!studentService.remove(studentId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
</if>
|
||||
<if test="studentFilter.searchString != null and studentFilter.searchString != ''">
|
||||
<bind name = "safeStudentSearchString" value = "'%' + studentFilter.searchString + '%'" />
|
||||
AND CONCAT(IFNULL(zz_student.login_mobile,''), IFNULL(zz_student.student_name,'')) LIKE #{safeStudentSearchString}
|
||||
AND CONCAT(COALESCE(zz_student.login_mobile,''), COALESCE(zz_student.student_name,'')) LIKE #{safeStudentSearchString}
|
||||
</if>
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.orangeforms.webadmin.app.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.*;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.orangeforms.webadmin.app.service.*;
|
||||
import com.orangeforms.webadmin.app.dao.*;
|
||||
@@ -155,8 +155,12 @@ public class CourseServiceImpl extends BaseService<Course, Long> implements Cour
|
||||
*/
|
||||
@Override
|
||||
public List<Course> getNotInCourseListByClassId(Long classId, Course filter, String orderBy) {
|
||||
List<Course> resultList =
|
||||
courseMapper.getNotInCourseListByClassId(classId, filter, orderBy);
|
||||
List<Course> resultList;
|
||||
if (classId != null) {
|
||||
resultList = courseMapper.getNotInCourseListByClassId(classId, filter, orderBy);
|
||||
} else {
|
||||
resultList = getCourseList(filter, orderBy);
|
||||
}
|
||||
this.buildRelationForDataList(resultList, MyRelationParam.dictOnly());
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.orangeforms.webadmin.app.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.*;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.orangeforms.webadmin.app.service.*;
|
||||
import com.orangeforms.webadmin.app.dao.*;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.orangeforms.webadmin.app.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.*;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.orangeforms.application.common.constant.StudentStatus;
|
||||
import com.orangeforms.webadmin.app.service.*;
|
||||
@@ -159,8 +159,12 @@ public class StudentServiceImpl extends BaseService<Student, Long> implements St
|
||||
*/
|
||||
@Override
|
||||
public List<Student> getNotInStudentListByClassId(Long classId, Student filter, String orderBy) {
|
||||
List<Student> resultList =
|
||||
studentMapper.getNotInStudentListByClassId(classId, filter, orderBy);
|
||||
List<Student> resultList;
|
||||
if (classId != null) {
|
||||
resultList = studentMapper.getNotInStudentListByClassId(classId, filter, orderBy);
|
||||
} else {
|
||||
resultList = getStudentList(filter, orderBy);
|
||||
}
|
||||
this.buildRelationForDataList(resultList, MyRelationParam.dictOnly());
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.orangeforms.webadmin.app.util;
|
||||
|
||||
import com.anji.captcha.service.CaptchaCacheService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 对于分布式部署的应用,我们建议应用自己实现CaptchaCacheService,比如用Redis,参考service/spring-boot代码示例。
|
||||
* 如果应用是单点的,也没有使用redis,那默认使用内存。
|
||||
* 内存缓存只适合单节点部署的应用,否则验证码生产与验证在节点之间信息不同步,导致失败。
|
||||
*
|
||||
* ☆☆☆ SPI: 在resources目录新建META-INF.services文件夹(两层),参考当前服务resources。
|
||||
* @author lide1202@hotmail.com
|
||||
* @date 2020-05-12
|
||||
*/
|
||||
public class CaptchaCacheServiceRedisImpl implements CaptchaCacheService {
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return "redis";
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
@Override
|
||||
public void set(String key, String value, long expiresInSeconds) {
|
||||
stringRedisTemplate.opsForValue().set(key, value, expiresInSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(String key) {
|
||||
return stringRedisTemplate.hasKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String key) {
|
||||
stringRedisTemplate.delete(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(String key) {
|
||||
return stringRedisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long increment(String key, long val) {
|
||||
return stringRedisTemplate.opsForValue().increment(key,val);
|
||||
}
|
||||
}
|
||||
@@ -62,15 +62,19 @@ public class AuthenticationInterceptor implements HandlerInterceptor {
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
String url = request.getRequestURI();
|
||||
String token = request.getHeader(appConfig.getTokenHeaderKey());
|
||||
boolean noLoginUrl = false;
|
||||
// 如果接口方法标记NoAuthInterface注解,可以直接跳过Token鉴权验证,这里主要为了测试接口方便
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod hm = (HandlerMethod) handler;
|
||||
if (hm.getBeanType().getAnnotation(NoAuthInterface.class) != null
|
||||
|| hm.getMethodAnnotation(NoAuthInterface.class) != null) {
|
||||
return true;
|
||||
noLoginUrl = true;
|
||||
if (StringUtils.isBlank(token)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
String token = request.getHeader(appConfig.getTokenHeaderKey());
|
||||
if (StringUtils.isBlank(token)) {
|
||||
token = request.getParameter(appConfig.getTokenHeaderKey());
|
||||
}
|
||||
@@ -95,8 +99,8 @@ public class AuthenticationInterceptor implements HandlerInterceptor {
|
||||
return false;
|
||||
}
|
||||
TokenData.addToRequest(tokenData);
|
||||
// 如果url在权限资源白名单中,则不需要进行鉴权操作
|
||||
if (Boolean.FALSE.equals(tokenData.getIsAdmin()) && !whitelistPermSet.contains(url)) {
|
||||
// 如果url是免登陆、白名单中,则不需要进行鉴权操作
|
||||
if (!noLoginUrl && Boolean.FALSE.equals(tokenData.getIsAdmin()) && !whitelistPermSet.contains(url)) {
|
||||
RSet<String> permSet = redissonClient.getSet(RedisKeyUtil.makeSessionPermIdKey(sessionId));
|
||||
if (!permSet.contains(url)) {
|
||||
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
package com.orangeforms.webadmin.upms.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.anji.captcha.model.common.ResponseModel;
|
||||
import com.anji.captcha.model.vo.CaptchaVO;
|
||||
import com.anji.captcha.service.CaptchaService;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
@@ -19,6 +25,7 @@ import com.orangeforms.common.core.constant.ApplicationConstant;
|
||||
import com.orangeforms.common.core.constant.ErrorCodeEnum;
|
||||
import com.orangeforms.common.core.object.*;
|
||||
import com.orangeforms.common.core.util.*;
|
||||
import com.orangeforms.common.core.upload.*;
|
||||
import com.orangeforms.common.redis.cache.SessionCacheHelper;
|
||||
import com.orangeforms.common.log.annotation.OperationLog;
|
||||
import com.orangeforms.common.log.model.constant.SysOperationLogType;
|
||||
@@ -29,7 +36,9 @@ import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
@@ -69,28 +78,52 @@ public class LoginController {
|
||||
private SessionCacheHelper cacheHelper;
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
@Autowired
|
||||
private CaptchaService captchaService;
|
||||
@Autowired
|
||||
private UpDownloaderFactory upDownloaderFactory;
|
||||
|
||||
/**
|
||||
* 登录接口。
|
||||
*
|
||||
* @param loginName 登录名。
|
||||
* @param password 密码。
|
||||
* @param loginName 登录名。
|
||||
* @param password 密码。
|
||||
* @param captchaVerification 验证码。
|
||||
* @return 应答结果对象,其中包括JWT的Token数据,以及菜单列表。
|
||||
*/
|
||||
@ApiImplicitParams({
|
||||
// 这里包含密码密文,仅用于方便开发期间的接口测试,集成测试和发布阶段,需要将当前注解去掉。
|
||||
// 如果您重新生成了公钥和私钥,请替换password的缺省值。
|
||||
@ApiImplicitParam(name = "loginName", defaultValue = "admin"),
|
||||
@ApiImplicitParam(name = "password", defaultValue = "IP3ccke3GhH45iGHB5qP9p7iZw6xUyj28Ju10rnBiPKOI35sc%2BjI7%2FdsjOkHWMfUwGYGfz8ik31HC2Ruk%2Fhkd9f6RPULTHj7VpFdNdde2P9M4mQQnFBAiPM7VT9iW3RyCtPlJexQ3nAiA09OqG%2F0sIf1kcyveSrulxembARDbDo%3D")
|
||||
@ApiImplicitParam(name = "password", defaultValue = "IP3ccke3GhH45iGHB5qP9p7iZw6xUyj28Ju10rnBiPKOI35sc%2BjI7%2FdsjOkHWMfUwGYGfz8ik31HC2Ruk%2Fhkd9f6RPULTHj7VpFdNdde2P9M4mQQnFBAiPM7VT9iW3RyCtPlJexQ3nAiA09OqG%2F0sIf1kcyveSrulxembARDbDo%3D"),
|
||||
@ApiImplicitParam(name = "captchaVerification", defaultValue = "为了方便测试,这里可以修改一下代码,hardcode一个每次都ok的验证码")
|
||||
})
|
||||
@NoAuthInterface
|
||||
@OperationLog(type = SysOperationLogType.LOGIN, saveResponse = false)
|
||||
@PostMapping("/doLogin")
|
||||
public ResponseResult<JSONObject> doLogin(
|
||||
@MyRequestBody String loginName, @MyRequestBody String password) throws Exception {
|
||||
if (MyCommonUtil.existBlankArgument(loginName, password)) {
|
||||
@MyRequestBody String loginName,
|
||||
@MyRequestBody String password,
|
||||
@MyRequestBody String captchaVerification) throws Exception {
|
||||
if (MyCommonUtil.existBlankArgument(loginName, password, captchaVerification)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
String errorMessage;
|
||||
CaptchaVO captchaVO = new CaptchaVO();
|
||||
captchaVO.setCaptchaVerification(captchaVerification);
|
||||
ResponseModel response = captchaService.verification(captchaVO);
|
||||
if (!response.isSuccess()) {
|
||||
//验证码校验失败,返回信息告诉前端
|
||||
//repCode 0000 无异常,代表成功
|
||||
//repCode 9999 服务器内部异常
|
||||
//repCode 0011 参数不能为空
|
||||
//repCode 6110 验证码已失效,请重新获取
|
||||
//repCode 6111 验证失败
|
||||
//repCode 6112 获取验证码失败,请联系管理员
|
||||
errorMessage = String.format("数据验证失败,验证码错误,错误码 [%s] 错误信息 [%s]",
|
||||
response.getRepCode(), response.getRepMsg());
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
|
||||
}
|
||||
SysUser user = sysUserService.getSysUserByLoginName(loginName);
|
||||
password = URLDecoder.decode(password, StandardCharsets.UTF_8.name());
|
||||
// NOTE: 第一次使用时,请务必阅读ApplicationConstant.PRIVATE_KEY的代码注释。
|
||||
@@ -99,7 +132,6 @@ public class LoginController {
|
||||
if (user == null || !passwordEncoder.matches(password, user.getPassword())) {
|
||||
return ResponseResult.error(ErrorCodeEnum.INVALID_USERNAME_PASSWORD);
|
||||
}
|
||||
String errorMessage;
|
||||
if (user.getUserStatus() == SysUserStatus.STATUS_LOCKED) {
|
||||
errorMessage = "登录失败,用户账号被锁定!";
|
||||
return ResponseResult.error(ErrorCodeEnum.INVALID_USER_STATUS, errorMessage);
|
||||
@@ -143,6 +175,9 @@ public class LoginController {
|
||||
JSONObject jsonData = new JSONObject();
|
||||
jsonData.put("showName", tokenData.getShowName());
|
||||
jsonData.put("isAdmin", tokenData.getIsAdmin());
|
||||
if (StrUtil.isNotBlank(tokenData.getHeadImageUrl())) {
|
||||
jsonData.put("headImageUrl", tokenData.getHeadImageUrl());
|
||||
}
|
||||
Collection<SysMenu> menuList;
|
||||
Collection<String> permCodeList;
|
||||
if (tokenData.getIsAdmin()) {
|
||||
@@ -186,10 +221,72 @@ public class LoginController {
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传并修改用户头像。
|
||||
*
|
||||
* @param uploadFile 上传的头像文件。
|
||||
*/
|
||||
@PostMapping("/changeHeadImage")
|
||||
public void changeHeadImage(
|
||||
@RequestParam("uploadFile") MultipartFile uploadFile) throws Exception {
|
||||
String fieldName = "headImageUrl";
|
||||
UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(SysUser.class, fieldName);
|
||||
BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
|
||||
UploadResponseInfo responseInfo = upDownloader.doUpload(null,
|
||||
appConfig.getUploadFileBaseDir(), SysUser.class.getSimpleName(), fieldName, true, uploadFile);
|
||||
if (responseInfo.getUploadFailed()) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
|
||||
ResponseResult.error(ErrorCodeEnum.UPLOAD_FAILED, responseInfo.getErrorMessage()));
|
||||
return;
|
||||
}
|
||||
responseInfo.setDownloadUri("/admin/upms/login/downloadHeadImage");
|
||||
String newHeadImage = JSONArray.toJSONString(CollUtil.newArrayList(responseInfo));
|
||||
if (!sysUserService.changeHeadImage(TokenData.takeFromRequest().getUserId(), newHeadImage)) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
|
||||
ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST));
|
||||
return;
|
||||
}
|
||||
ResponseResult.output(ResponseResult.success(responseInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载用户头像。
|
||||
*
|
||||
* @param filename 文件名。如果没有提供该参数,就从当前记录的指定字段中读取。
|
||||
* @param response Http 应答对象。
|
||||
*/
|
||||
@GetMapping("/downloadHeadImage")
|
||||
public void downloadHeadImage(String filename, HttpServletResponse response) {
|
||||
try {
|
||||
SysUser user = sysUserService.getById(TokenData.takeFromRequest().getUserId());
|
||||
if (user == null) {
|
||||
ResponseResult.output(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
if (StrUtil.isBlank(user.getHeadImageUrl())) {
|
||||
ResponseResult.output(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
if (!BaseUpDownloader.containFile(user.getHeadImageUrl(), filename)) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
String fieldName = "headImageUrl";
|
||||
UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(SysUser.class, fieldName);
|
||||
BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
|
||||
upDownloader.doDownload(appConfig.getUploadFileBaseDir(),
|
||||
SysUser.class.getSimpleName(), fieldName, filename, true, response);
|
||||
} catch (Exception e) {
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private JSONObject buildLoginData(SysUser user) {
|
||||
int deviceType = MyCommonUtil.getDeviceType();
|
||||
boolean isAdmin = user.getUserType() == SysUserType.TYPE_ADMIN;
|
||||
String headImageUrl = user.getHeadImageUrl();
|
||||
Map<String, Object> claims = new HashMap<>(3);
|
||||
String sessionId = user.getLoginName() + "_" + deviceType + "_" + MyCommonUtil.generateUuid();
|
||||
claims.put("sessionId", sessionId);
|
||||
@@ -198,6 +295,9 @@ public class LoginController {
|
||||
jsonData.put(TokenData.REQUEST_ATTRIBUTE_NAME, token);
|
||||
jsonData.put("showName", user.getShowName());
|
||||
jsonData.put("isAdmin", isAdmin);
|
||||
if (StrUtil.isNotBlank(headImageUrl)) {
|
||||
jsonData.put("headImageUrl", headImageUrl);
|
||||
}
|
||||
TokenData tokenData = new TokenData();
|
||||
tokenData.setSessionId(sessionId);
|
||||
tokenData.setUserId(user.getUserId());
|
||||
@@ -208,6 +308,9 @@ public class LoginController {
|
||||
tokenData.setLoginIp(IpUtil.getRemoteIpAddress(ContextUtil.getHttpRequest()));
|
||||
tokenData.setLoginTime(new Date());
|
||||
tokenData.setDeviceType(deviceType);
|
||||
if (StrUtil.isNotBlank(headImageUrl)) {
|
||||
tokenData.setHeadImageUrl(headImageUrl);
|
||||
}
|
||||
List<SysUserRole> userRoleList = sysRoleService.getSysUserRoleListByUserId(user.getUserId());
|
||||
if (CollectionUtils.isNotEmpty(userRoleList)) {
|
||||
Set<Long> userRoleIdSet = userRoleList.stream().map(SysUserRole::getRoleId).collect(Collectors.toSet());
|
||||
|
||||
@@ -113,27 +113,7 @@ public class SysDeptController {
|
||||
if (MyCommonUtil.existBlankArgument(deptId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
SysDept originalSysDept = sysDeptService.getById(deptId);
|
||||
if (originalSysDept == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (sysDeptService.hasChildren(deptId)) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象存在子对象] ,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage);
|
||||
}
|
||||
if (sysDeptService.hasChildrenUser(deptId)) {
|
||||
errorMessage = "数据验证失败,请先移除部门用户数据后,再删除当前部门!";
|
||||
return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage);
|
||||
}
|
||||
if (!sysDeptService.remove(deptId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
return this.doDelete(deptId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,4 +198,29 @@ public class SysDeptController {
|
||||
return ResponseResult.success(BeanQuery.select(
|
||||
"parentId as parentId", "deptId as id", "deptName as name").executeFrom(resultList));
|
||||
}
|
||||
|
||||
private ResponseResult<Void> doDelete(Long deptId) {
|
||||
String errorMessage;
|
||||
// 验证关联Id的数据合法性
|
||||
SysDept originalSysDept = sysDeptService.getById(deptId);
|
||||
if (originalSysDept == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (sysDeptService.hasChildren(deptId)) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象存在子对象] ,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage);
|
||||
}
|
||||
if (sysDeptService.hasChildrenUser(deptId)) {
|
||||
errorMessage = "数据验证失败,请先移除部门用户数据后,再删除当前部门!";
|
||||
return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage);
|
||||
}
|
||||
if (!sysDeptService.remove(deptId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package com.orangeforms.webadmin.upms.controller;
|
||||
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import com.orangeforms.common.core.upload.BaseUpDownloader;
|
||||
import com.orangeforms.common.core.upload.UpDownloaderFactory;
|
||||
import com.orangeforms.common.core.upload.UploadResponseInfo;
|
||||
import com.orangeforms.common.core.upload.UploadStoreInfo;
|
||||
import com.orangeforms.common.log.annotation.OperationLog;
|
||||
import com.orangeforms.common.log.model.constant.SysOperationLogType;
|
||||
import com.github.pagehelper.page.PageMethod;
|
||||
@@ -12,6 +17,7 @@ import com.orangeforms.common.core.object.*;
|
||||
import com.orangeforms.common.core.util.*;
|
||||
import com.orangeforms.common.core.constant.*;
|
||||
import com.orangeforms.common.core.annotation.MyRequestBody;
|
||||
import com.orangeforms.common.redis.cache.SessionCacheHelper;
|
||||
import com.orangeforms.webadmin.config.ApplicationConfig;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import io.swagger.annotations.Api;
|
||||
@@ -19,7 +25,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -40,6 +48,10 @@ public class SysUserController {
|
||||
private PasswordEncoder passwordEncoder;
|
||||
@Autowired
|
||||
private ApplicationConfig appConfig;
|
||||
@Autowired
|
||||
private SessionCacheHelper cacheHelper;
|
||||
@Autowired
|
||||
private UpDownloaderFactory upDownloaderFactory;
|
||||
|
||||
/**
|
||||
* 新增用户操作。
|
||||
@@ -144,18 +156,7 @@ public class SysUserController {
|
||||
if (MyCommonUtil.existBlankArgument(userId)) {
|
||||
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
|
||||
}
|
||||
// 验证关联Id的数据合法性
|
||||
SysUser originalSysUser = sysUserService.getById(userId);
|
||||
if (originalSysUser == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!sysUserService.remove(userId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
return this.doDelete(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,6 +201,101 @@ public class SysUserController {
|
||||
return ResponseResult.success(sysUserVo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 附件文件下载。
|
||||
* 这里将图片和其他类型的附件文件放到不同的父目录下,主要为了便于今后图片文件的迁移。
|
||||
*
|
||||
* @param userId 附件所在记录的主键Id。
|
||||
* @param fieldName 附件所属的字段名。
|
||||
* @param filename 文件名。如果没有提供该参数,就从当前记录的指定字段中读取。
|
||||
* @param asImage 下载文件是否为图片。
|
||||
* @param response Http 应答对象。
|
||||
*/
|
||||
@OperationLog(type = SysOperationLogType.DOWNLOAD, saveResponse = false)
|
||||
@GetMapping("/download")
|
||||
public void download(
|
||||
@RequestParam(required = false) Long userId,
|
||||
@RequestParam String fieldName,
|
||||
@RequestParam String filename,
|
||||
@RequestParam Boolean asImage,
|
||||
HttpServletResponse response) {
|
||||
if (MyCommonUtil.existBlankArgument(fieldName, filename, asImage)) {
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
// 使用try来捕获异常,是为了保证一旦出现异常可以返回500的错误状态,便于调试。
|
||||
// 否则有可能给前端返回的是200的错误码。
|
||||
try {
|
||||
// 如果请求参数中没有包含主键Id,就判断该文件是否为当前session上传的。
|
||||
if (userId == null) {
|
||||
if (!cacheHelper.existSessionUploadFile(filename)) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
SysUser sysUser = sysUserService.getById(userId);
|
||||
if (sysUser == null) {
|
||||
ResponseResult.output(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
String fieldJsonData = (String) ReflectUtil.getFieldValue(sysUser, fieldName);
|
||||
if (fieldJsonData == null) {
|
||||
ResponseResult.output(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
if (!BaseUpDownloader.containFile(fieldJsonData, filename)) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(SysUser.class, fieldName);
|
||||
if (!storeInfo.isSupportUpload()) {
|
||||
ResponseResult.output(HttpServletResponse.SC_NOT_IMPLEMENTED,
|
||||
ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
|
||||
return;
|
||||
}
|
||||
BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
|
||||
upDownloader.doDownload(appConfig.getUploadFileBaseDir(),
|
||||
SysUser.class.getSimpleName(), fieldName, filename, asImage, response);
|
||||
} catch (Exception e) {
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件上传操作。
|
||||
*
|
||||
* @param fieldName 上传文件名。
|
||||
* @param asImage 是否作为图片上传。如果是图片,今后下载的时候无需权限验证。否则就是附件上传,下载时需要权限验证。
|
||||
* @param uploadFile 上传文件对象。
|
||||
*/
|
||||
@OperationLog(type = SysOperationLogType.UPLOAD, saveResponse = false)
|
||||
@PostMapping("/upload")
|
||||
public void upload(
|
||||
@RequestParam String fieldName,
|
||||
@RequestParam Boolean asImage,
|
||||
@RequestParam("uploadFile") MultipartFile uploadFile) throws Exception {
|
||||
UploadStoreInfo storeInfo = MyModelUtil.getUploadStoreInfo(SysUser.class, fieldName);
|
||||
// 这里就会判断参数中指定的字段,是否支持上传操作。
|
||||
if (!storeInfo.isSupportUpload()) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
|
||||
ResponseResult.error(ErrorCodeEnum.INVALID_UPLOAD_FIELD));
|
||||
return;
|
||||
}
|
||||
// 根据字段注解中的存储类型,通过工厂方法获取匹配的上传下载实现类,从而解耦。
|
||||
BaseUpDownloader upDownloader = upDownloaderFactory.get(storeInfo.getStoreType());
|
||||
UploadResponseInfo responseInfo = upDownloader.doUpload(null,
|
||||
appConfig.getUploadFileBaseDir(), SysUser.class.getSimpleName(), fieldName, asImage, uploadFile);
|
||||
if (responseInfo.getUploadFailed()) {
|
||||
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
|
||||
ResponseResult.error(ErrorCodeEnum.UPLOAD_FAILED, responseInfo.getErrorMessage()));
|
||||
return;
|
||||
}
|
||||
cacheHelper.putSessionUploadFile(responseInfo.getFilename());
|
||||
ResponseResult.output(ResponseResult.success(responseInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户的权限资源地址列表。同时返回详细的分配路径。
|
||||
*
|
||||
@@ -244,4 +340,20 @@ public class SysUserController {
|
||||
}
|
||||
return ResponseResult.success(sysUserService.getSysMenuListWithDetail(userId, menuName));
|
||||
}
|
||||
|
||||
private ResponseResult<Void> doDelete(Long userId) {
|
||||
String errorMessage;
|
||||
// 验证关联Id的数据合法性
|
||||
SysUser originalSysUser = sysUserService.getById(userId);
|
||||
if (originalSysUser == null) {
|
||||
// NOTE: 修改下面方括号中的话述
|
||||
errorMessage = "数据验证失败,当前 [对象] 并不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
if (!sysUserService.remove(userId)) {
|
||||
errorMessage = "数据操作失败,删除的对象不存在,请刷新后重试!";
|
||||
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
|
||||
}
|
||||
return ResponseResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.orangeforms.webadmin.upms.model;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.orangeforms.webadmin.upms.model.constant.SysUserType;
|
||||
import com.orangeforms.webadmin.upms.model.constant.SysUserStatus;
|
||||
import com.orangeforms.common.core.upload.UploadStoreTypeEnum;
|
||||
import com.orangeforms.common.core.annotation.*;
|
||||
import com.orangeforms.common.core.base.mapper.BaseModelMapper;
|
||||
import com.orangeforms.webadmin.upms.vo.SysUserVo;
|
||||
@@ -62,6 +63,7 @@ public class SysUser {
|
||||
/**
|
||||
* 用户头像的Url。
|
||||
*/
|
||||
@UploadFlagColumn(storeType = UploadStoreTypeEnum.LOCAL_SYSTEM)
|
||||
@TableField(value = "head_image_url")
|
||||
private String headImageUrl;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orangeforms.webadmin.upms.service;
|
||||
|
||||
import com.orangeforms.common.core.base.service.IBaseService;
|
||||
import com.orangeforms.common.core.object.CallResult;
|
||||
import com.orangeforms.webadmin.upms.model.SysPerm;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -51,6 +51,15 @@ public interface SysUserService extends IBaseService<SysUser, Long> {
|
||||
*/
|
||||
boolean changePassword(Long userId, String newPass);
|
||||
|
||||
/**
|
||||
* 修改用户头像。
|
||||
*
|
||||
* @param userId 用户主键Id。
|
||||
* @param newHeadImage 新的头像信息。
|
||||
* @return 成功返回true,否则false。
|
||||
*/
|
||||
boolean changeHeadImage(Long userId, String newHeadImage);
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.orangeforms.webadmin.upms.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.*;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.orangeforms.webadmin.upms.service.*;
|
||||
import com.orangeforms.webadmin.upms.dao.*;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.orangeforms.webadmin.upms.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.*;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.orangeforms.webadmin.upms.service.*;
|
||||
import com.orangeforms.webadmin.upms.dao.*;
|
||||
import com.orangeforms.webadmin.upms.model.*;
|
||||
@@ -173,6 +173,15 @@ public class SysUserServiceImpl extends BaseService<SysUser, Long> implements Sy
|
||||
return sysUserMapper.updateById(updatedUser) == 1;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public boolean changeHeadImage(Long userId, String newHeadImage) {
|
||||
SysUser updatedUser = new SysUser();
|
||||
updatedUser.setUserId(userId);
|
||||
updatedUser.setHeadImageUrl(newHeadImage);
|
||||
return sysUserMapper.updateById(updatedUser) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定数据。
|
||||
*
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
com.orangeforms.webadmin.app.util.CaptchaCacheServiceRedisImpl
|
||||
@@ -1,7 +1,8 @@
|
||||
logging:
|
||||
level:
|
||||
# 这里设置的日志级别优先于log4j2.xml文件Loggers中的日志级别。
|
||||
# 这里设置的日志级别优先于logback-spring.xml文件Loggers中的日志级别。
|
||||
com.orangeforms: info
|
||||
config: classpath:logback-spring.xml
|
||||
|
||||
server:
|
||||
port: 8082
|
||||
@@ -137,10 +138,53 @@ common-log:
|
||||
operation-log:
|
||||
enabled: true
|
||||
|
||||
aj:
|
||||
captcha:
|
||||
# 缓存local/redis..
|
||||
cache-type: redis
|
||||
# 验证码类型default两种都实例化。
|
||||
type: default
|
||||
# 右下角水印文字(我的水印)
|
||||
water-mark: 我的水印
|
||||
#点选字体样式 默认Font.BOLD
|
||||
font-style: 1
|
||||
#点选字体字体大小
|
||||
font-size: 25
|
||||
# 支持项目路径,以classpath:开头,取resource目录下路径,例:classpath:images/jigsaw
|
||||
jigsaw: classpath:images/jigsaw
|
||||
# 支持项目路径,以classpath:开头,取resource目录下路径,例:classpath:images/pic-click
|
||||
pic-click: classpath:images/pic-click
|
||||
history-data-clear-enable: false
|
||||
# 接口请求次数一分钟限制是否开启 true|false
|
||||
req-frequency-limit-enable: false
|
||||
# 验证失败5次,get接口锁定
|
||||
req-get-lock-limit: 5
|
||||
# 验证失败后,锁定时间间隔,s
|
||||
req-get-lock-seconds: 360
|
||||
# get接口一分钟内请求数限制
|
||||
req-get-minute-limit: 30
|
||||
# check接口一分钟内请求数限制
|
||||
req-check-minute-limit: 30
|
||||
# verify接口一分钟内请求数限制
|
||||
req-verify-minute-limit: 60
|
||||
# 校验滑动拼图允许误差偏移量(默认5像素)
|
||||
slip-offset: 5
|
||||
# aes加密坐标开启或者禁用(true|false)
|
||||
aes-status: true
|
||||
# 滑动干扰项(0/1/2)
|
||||
interference-options: 2
|
||||
|
||||
# 开发数据库相关配置
|
||||
---
|
||||
spring:
|
||||
profiles: dev
|
||||
# aj-captcha 对redis缓存的依赖。
|
||||
redis:
|
||||
database: 2
|
||||
host: localhost
|
||||
port: 6379
|
||||
password: ''
|
||||
timeout: 60000
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
druid:
|
||||
@@ -200,6 +244,13 @@ sequence:
|
||||
---
|
||||
spring:
|
||||
profiles: product
|
||||
# aj-captcha 对redis缓存的依赖。
|
||||
redis:
|
||||
database: 2
|
||||
host: localhost
|
||||
port: 6379
|
||||
password: ''
|
||||
timeout: 60000
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
druid:
|
||||
|
||||
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 39 KiB |
@@ -1,77 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!-- 本项目全部使用log4j2性能上有很大提升 -->
|
||||
|
||||
<!--monitorInterval="60" 自动检测配置文件更改时间 单位为秒 最小值为5 -->
|
||||
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出。 -->
|
||||
<configuration monitorInterval="20" status="OFF">
|
||||
<!--日志变量 -->
|
||||
<properties>
|
||||
<!-- 日志主目录 ,需要保存到文件时请自己配置-->
|
||||
<property name="LOG_HOME">./zzlogs/application-webadmin</property>
|
||||
<!-- 日志备份目录 -->
|
||||
<property name="BACKUP_HOME">./zzlogs/application-webadmin/backup</property>
|
||||
<!-- 日志输出级别 -->
|
||||
<property name="OUTPUT_LOG_LEVEL">info</property>
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="LOG_PATTERN">
|
||||
<!-- 输出格式%d{HH:mm:ss}时间24小时制 -->
|
||||
<!-- %-5p日志级别 5位左对齐 [%t]线程名 [%c]类名 -->
|
||||
<!--%l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数。例如:test.TestLog4j.main(TestLog4j.java:10)。 -->
|
||||
<!-- 另一种输出风格<PatternLayout pattern="级别%-5p [%d{YYYY-MM-dd HH:mm:ss}] [%t] 位置[%l] - 信息:%msg%n" /> -->
|
||||
<!-- [%-5p][%d{yy-MM-dd HH:mm:ss}][%t]==>%m==>%c==>%L%n -->
|
||||
[%-5p] [%d{YYYY-MM-dd HH:mm:ss}] [%t] ==> %msg%n
|
||||
</property>
|
||||
<property name="LOG_PATTERN_EX">
|
||||
[%-5p] [%d{YYYY-MM-dd HH:mm:ss}] T:[%X{traceId}] S:[%X{sessionId}] U:[%X{userId}] [%t] ==> %msg%n
|
||||
</property>
|
||||
<!-- 日志保留天数 -->
|
||||
<property name="EVERY_FILE_COUNT">31</property>
|
||||
<!-- 日志切割的最小单位 -->
|
||||
<property name="EVERY_FILE_SIZE">20M</property>
|
||||
</properties>
|
||||
|
||||
<appenders>
|
||||
<!--控制台输出 -->
|
||||
<console name="console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="${LOG_PATTERN}"/>
|
||||
</console>
|
||||
<!-- console_log级别日志文件 -->
|
||||
<!--每次大小超过size,则这size大小的日志会自动进行压缩,作为存档 -->
|
||||
<rollingFile name="file_log" fileName="${LOG_HOME}/application-webadmin.log"
|
||||
filePattern="${LOG_HOME}/application-webadmin-%d{yyyy-MM-dd}-%i.log.gz">
|
||||
<PatternLayout charset="UTF-8" pattern="${LOG_PATTERN_EX}"/>
|
||||
<!-- 日志切割的最小单位 -->
|
||||
<SizeBasedTriggeringPolicy size="${EVERY_FILE_SIZE}"/>
|
||||
<!-- 默认的日志文件数量 -->
|
||||
<DefaultRolloverStrategy max="${EVERY_FILE_COUNT}"/>
|
||||
</rollingFile>
|
||||
</appenders>
|
||||
|
||||
<!-- 然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
|
||||
<!-- 这里我们把输出到控制台appender的日志级别设置为DEBUG,便于调试。但是输出文件我们缺省为INFO,两者均可随时修改。-->
|
||||
<Loggers>
|
||||
<root level="${OUTPUT_LOG_LEVEL}">
|
||||
<AppenderRef ref="console"/>
|
||||
</root>
|
||||
<Logger name="springfox.documentation" additivity="false" level="error">
|
||||
<AppenderRef ref="console"/>
|
||||
</Logger>
|
||||
<AsyncLogger name="com.orangeforms" additivity="false" level="info">
|
||||
<AppenderRef ref="console"/>
|
||||
<AppenderRef ref="file_log"/>
|
||||
</AsyncLogger>
|
||||
<!-- 这里将dao的日志级别设置为DEBUG,是为了SQL语句的输出 -->
|
||||
<AsyncLogger name="com.orangeforms.webadmin.app.dao" additivity="false" level="debug">
|
||||
<AppenderRef ref="console"/>
|
||||
<AppenderRef ref="file_log"/>
|
||||
</AsyncLogger>
|
||||
<AsyncLogger name="com.orangeforms.webadmin.upms.dao" additivity="false" level="debug">
|
||||
<AppenderRef ref="console"/>
|
||||
<AppenderRef ref="file_log"/>
|
||||
</AsyncLogger>
|
||||
<AsyncLogger name="com.orangeforms.common.log.dao" additivity="false" level="debug">
|
||||
<AppenderRef ref="console"/>
|
||||
<AppenderRef ref="file_log"/>
|
||||
</AsyncLogger>
|
||||
</Loggers>
|
||||
</configuration>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
|
||||
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
|
||||
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
|
||||
-->
|
||||
<configuration scan="false" scanPeriod="60 seconds" debug="false">
|
||||
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
|
||||
<springProperty scope="context" name="logging.level" source="logging.level" defaultValue="info"/>
|
||||
|
||||
<!-- 定义日志的根目录 -->
|
||||
<property name="LOG_HOME" value="./zzlogs/application-webadmin" />
|
||||
<!-- 定义日志文件名称 -->
|
||||
<property name="LOG_NAME" value="application-webadmin"></property>
|
||||
<property name="LOG_PATTERN_EX" value="[%-5level] [%d{yyyy-MM-dd HH:mm:ss}] T:[%X{traceId}] S:[%X{sessionId}] U:[%X{userId}] [%thread] ==> %msg%n" />
|
||||
|
||||
<!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!--
|
||||
日志输出格式:
|
||||
%-5level:级别从左显示5个字符宽度
|
||||
%d表示日期时间,
|
||||
%thread表示线程名,
|
||||
%msg:日志消息,
|
||||
%n是换行符
|
||||
-->
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<pattern>${LOG_PATTERN_EX}</pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
|
||||
<appender name="file_log" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 这里为缺省log文件命名配置。注意,如果需要支持基于flume的日志搬运,为了防止文件名滚动过程中,
|
||||
重复搬运数据,请将下面两行配置注释掉,从而保证每次生成的日志文件均包含日期信息且不会变化。-->
|
||||
<file>${LOG_HOME}/${LOG_NAME}.log</file>
|
||||
<append>true</append>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!--
|
||||
滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动
|
||||
%i:当文件大小超过maxFileSize时,按照i进行文件滚动
|
||||
-->
|
||||
<fileNamePattern>${LOG_HOME}/${LOG_NAME}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
|
||||
<!--
|
||||
可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
|
||||
且maxHistory是365,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,
|
||||
那些为了归档而创建的目录也会被删除。
|
||||
-->
|
||||
<!-- 保存31天数据 -->
|
||||
<MaxHistory>31</MaxHistory>
|
||||
<!--
|
||||
当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
|
||||
-->
|
||||
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||
<maxFileSize>20MB</maxFileSize>
|
||||
</timeBasedFileNamingAndTriggeringPolicy>
|
||||
</rollingPolicy>
|
||||
<!-- 日志输出格式: -->
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<pattern>${LOG_PATTERN_EX}</pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- 然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
|
||||
<!-- 这里我们把输出到控制台appender的日志级别设置为DEBUG,便于调试。但是输出文件我们缺省为INFO,两者均可随时修改。-->
|
||||
<root level="${logging.level}">
|
||||
<appender-ref ref="console" />
|
||||
<appender-ref ref="file_log" />
|
||||
</root>
|
||||
<logger name="springfox.documentation" additivity="false" level="error">
|
||||
<appender-ref ref="console" />
|
||||
</logger>
|
||||
<logger name="com.orangeforms" additivity="false" level="info">
|
||||
<appender-ref ref="console" />
|
||||
<appender-ref ref="file_log" />
|
||||
</logger>
|
||||
<!-- 这里将dao的日志级别设置为DEBUG,是为了SQL语句的输出 -->
|
||||
<logger name="com.orangeforms.webadmin.app.dao" additivity="false" level="debug">
|
||||
<appender-ref ref="console" />
|
||||
<appender-ref ref="file_log" />
|
||||
</logger>
|
||||
<logger name="com.orangeforms.webadmin.upms.dao" additivity="false" level="debug">
|
||||
<appender-ref ref="console" />
|
||||
<appender-ref ref="file_log" />
|
||||
</logger>
|
||||
<logger name="com.orangeforms.common.log.dao" additivity="false" level="debug">
|
||||
<appender-ref ref="console" />
|
||||
<appender-ref ref="file_log" />
|
||||
</logger>
|
||||
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/>
|
||||
</configuration>
|
||||
@@ -1,329 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<style type="text/css">
|
||||
.b1{white-space-collapsing:preserve;}
|
||||
.t1{border-collapse:collapse;border-spacing:0;}
|
||||
.r1{height:23.25pt;}
|
||||
.r2{height:18.75pt;}
|
||||
.r3{height:17.25pt;}
|
||||
.r4{height:15.0pt;}
|
||||
.r5{height:14.25pt;}
|
||||
.r6{height:21.0pt;}
|
||||
.r7{height:18.0pt;}
|
||||
.r8{height:15.75pt;}
|
||||
.r9{height:19.5pt;}
|
||||
.r10{height:17.0pt;}
|
||||
.r11{height:20.25pt;}
|
||||
.r12{height:28.5pt;}
|
||||
.c1{white-space:pre-wrap;text-align:center;border-bottom:thin solid black;font-weight:bold;color: #dd0806; font-size:18pt;}
|
||||
.c2{white-space:pre-wrap;text-align:center;background-color:#ffff00;border-top:thin solid black;border-left:thin solid black;color: #dd0806; font-size:12pt;}
|
||||
.c3{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-left:thin solid black;color: #dd0806; font-size:12pt;}
|
||||
.c4{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-bottom:thin solid black;border-left:thin solid black;color: #dd0806; font-size:12pt;}
|
||||
.c5{white-space:pre-wrap;text-align:center;color: #dd0806; font-size:10pt;}
|
||||
.c6{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-bottom:thin solid black;color: #dd0806; font-size:10pt;}
|
||||
.c7{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-bottom:thin solid black;border-left:thin solid black;color: #dd0806; font-size:10pt;}
|
||||
.c8{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-bottom:thin solid black;border-left:thin solid black;font-size:9pt;}
|
||||
.c9{white-space:pre-wrap;text-align:center;background-color:#ffff00;border-top:thin solid black;border-right:thin solid black;border-bottom:thin solid black;border-left:thin solid black;color: #dd0806; font-size:11pt;}
|
||||
.c10{white-space:pre-wrap;text-align:center;border-right:thin solid black;border-left:thin solid black;font-size:10pt;}
|
||||
.c11{white-space:pre-wrap;text-align:center;border-right:thin solid black;border-bottom:thin solid black;border-left:thin solid black;font-size:10pt;}
|
||||
.c12{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-left:thin solid black;font-size:10pt;}
|
||||
.c13{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-bottom:thin solid black;border-left:thin solid black;font-size:8pt;}
|
||||
.c14{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-left:thin solid black;font-size:8pt;}
|
||||
.c15{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-bottom:thin solid black;border-left:thin solid black;font-size:10pt;}
|
||||
.c16{white-space:pre-wrap;text-align:center;background-color:#ffff00;border-top:thin solid black;border-right:thin solid black;border-bottom:thin solid black;border-left:thin solid black;font-size:11pt;}
|
||||
.c17{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-bottom:thin solid black;border-left:thin solid black;font-size:11pt;}
|
||||
.c18{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-bottom:thin solid black;border-left:thin solid black;font-size:6pt;}
|
||||
.c19{white-space:pre-wrap;text-align:center;border-right:thin solid black;border-bottom:thin solid black;border-left:thin solid black;font-size:6pt;}
|
||||
.c20{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-left:thin solid black;font-weight:bold;font-size:6pt;}
|
||||
.c21{white-space:pre-wrap;text-align:center;border-top:thin solid black;border-right:thin solid black;border-left:thin solid black;font-weight:bold;font-size:8pt;}
|
||||
.c22{white-space:pre-wrap;text-align:left;border-top:thin solid black;font-weight:bold;font-size:9pt;}
|
||||
</style>
|
||||
</head>
|
||||
<body class="b1">
|
||||
<table class="t1">
|
||||
<colgroup>
|
||||
<col width="40">
|
||||
<col width="40">
|
||||
<col width="57">
|
||||
<col width="57">
|
||||
<col width="57">
|
||||
<col width="57">
|
||||
<col width="57">
|
||||
<col width="56">
|
||||
<col width="59">
|
||||
<col width="57">
|
||||
<col width="57">
|
||||
<col width="57">
|
||||
<col width="57">
|
||||
<col width="57">
|
||||
<col width="57">
|
||||
<col width="57">
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr class="r1">
|
||||
<td class="c1" colspan="16">天津公安警官职业学院2017—2018学年度第一学期课程表</td>
|
||||
</tr>
|
||||
<tr class="r1">
|
||||
<td class="c2" colspan="2" rowspan="2">班 级</td>
|
||||
<td class="c3" colspan="3">星期一</td>
|
||||
<td class="c4" colspan="3">星期二</td>
|
||||
<td class="c4" colspan="3">星期三</td>
|
||||
<td class="c4" colspan="3">星期四</td>
|
||||
<td class="c4" colspan="2">星期五</td>
|
||||
</tr>
|
||||
<tr class="r2">
|
||||
<td class="c5">第1节</td>
|
||||
<td class="c5">第2节</td>
|
||||
<td class="c5">第3节</td>
|
||||
<td class="c6">第1节</td>
|
||||
<td class="c7">第2节</td>
|
||||
<td class="c7">第3节</td>
|
||||
<td class="c7">第1节</td>
|
||||
<td class="c7">第2节</td>
|
||||
<td class="c7">第3节</td>
|
||||
<td class="c7">第1节</td>
|
||||
<td class="c7">第2节</td>
|
||||
<td class="c7">第3节</td>
|
||||
<td class="c7">第1节</td>
|
||||
<td class="c7">第2节</td>
|
||||
</tr>
|
||||
<tr class="r2">
|
||||
<td class="c8" rowspan="6">16 级 刑 事 技 术 班 </td>
|
||||
<td class="c9" rowspan="2">课程</td>
|
||||
<td class="c10" rowspan="2">刑法</td>
|
||||
<td class="c10" rowspan="6">自习</td>
|
||||
<td class="c11">刑事图像</td>
|
||||
<td class="c12" rowspan="2">民 法(选修)</td>
|
||||
<td class="c13">派出所工作</td>
|
||||
<td class="c12" rowspan="2">刑事图像</td>
|
||||
<td class="c12" rowspan="2">法医学</td>
|
||||
<td class="c14" rowspan="2">派出所工作</td>
|
||||
<td class="c15">法医学</td>
|
||||
<td class="c12" rowspan="2">国内安全保卫</td>
|
||||
<td class="c12" rowspan="2">体能</td>
|
||||
<td class="c12" rowspan="6">自习</td>
|
||||
<td class="c12" rowspan="2">刑事技术总论</td>
|
||||
<td class="c12" rowspan="2">刑法</td>
|
||||
</tr>
|
||||
<tr class="r3">
|
||||
<td class="c11">自习</td>
|
||||
<td class="c11">自习</td>
|
||||
<td class="c11">自习</td>
|
||||
</tr>
|
||||
<tr class="r3">
|
||||
<td class="c16" rowspan="2">教师</td>
|
||||
<td class="c12" rowspan="2">曾岚</td>
|
||||
<td class="c15">陈磊</td>
|
||||
<td class="c12" rowspan="2">邵刚</td>
|
||||
<td class="c15">杨丽伟</td>
|
||||
<td class="c12" rowspan="2">陈磊</td>
|
||||
<td class="c12" rowspan="2">于辉</td>
|
||||
<td class="c12" rowspan="2">杨丽伟</td>
|
||||
<td class="c15">于辉</td>
|
||||
<td class="c12" rowspan="2">朱学强</td>
|
||||
<td class="c12" rowspan="2">张付海</td>
|
||||
<td class="c12" rowspan="2">王 伟(刑技)</td>
|
||||
<td class="c12" rowspan="2">曾岚</td>
|
||||
</tr>
|
||||
<tr class="r3">
|
||||
<td class="c11"> </td>
|
||||
<td class="c11"> </td>
|
||||
<td class="c11"> </td>
|
||||
</tr>
|
||||
<tr class="r3">
|
||||
<td class="c16" rowspan="2">教室</td>
|
||||
<td class="c15" rowspan="2">206</td>
|
||||
<td class="c15">206</td>
|
||||
<td class="c15" rowspan="2">206</td>
|
||||
<td class="c15">206</td>
|
||||
<td class="c15" rowspan="2">206</td>
|
||||
<td class="c15" rowspan="2">206</td>
|
||||
<td class="c15" rowspan="2">206</td>
|
||||
<td class="c15">206</td>
|
||||
<td class="c15" rowspan="2">206</td>
|
||||
<td class="c15" rowspan="2">操场</td>
|
||||
<td class="c15" rowspan="2">206</td>
|
||||
<td class="c15" rowspan="2">206</td>
|
||||
</tr>
|
||||
<tr class="r4">
|
||||
<td class="c15"> </td>
|
||||
<td class="c11"> </td>
|
||||
<td class="c11"> </td>
|
||||
</tr>
|
||||
<tr class="r2">
|
||||
<td class="c8" rowspan="6">16 级 刑 事 侦 查 </td>
|
||||
<td class="c17" rowspan="2">课程</td>
|
||||
<td class="c12" rowspan="6">自习</td>
|
||||
<td class="c12" rowspan="2">侦查措施</td>
|
||||
<td class="c12" rowspan="2">经济案件侦查</td>
|
||||
<td class="c14" rowspan="2">公安信息化</td>
|
||||
<td class="c14" rowspan="2">公安信息化</td>
|
||||
<td class="c12" rowspan="2">刑法</td>
|
||||
<td class="c12" rowspan="2">体能</td>
|
||||
<td class="c12" rowspan="6">自习</td>
|
||||
<td class="c12" rowspan="2">痕迹检验</td>
|
||||
<td class="c12" rowspan="2">刑法</td>
|
||||
<td class="c12" rowspan="2">国内安全保卫</td>
|
||||
<td class="c18">经济案件侦查</td>
|
||||
<td class="c12" rowspan="2">痕迹检验</td>
|
||||
<td class="c12" rowspan="2">民 法(选修)</td>
|
||||
</tr>
|
||||
<tr class="r3">
|
||||
<td class="c11">侦查措施</td>
|
||||
</tr>
|
||||
<tr class="r3">
|
||||
<td class="c17" rowspan="2">教师</td>
|
||||
<td class="c12" rowspan="2">徐宏涛</td>
|
||||
<td class="c12" rowspan="2">张静</td>
|
||||
<td class="c12" rowspan="2">赵晓松</td>
|
||||
<td class="c12" rowspan="2">赵晓松</td>
|
||||
<td class="c12" rowspan="2">王骏强</td>
|
||||
<td class="c12" rowspan="2">张付海</td>
|
||||
<td class="c12" rowspan="2">郭海川</td>
|
||||
<td class="c12" rowspan="2">王骏强</td>
|
||||
<td class="c12" rowspan="2">朱学强</td>
|
||||
<td class="c15">张静</td>
|
||||
<td class="c12" rowspan="2">郭海川</td>
|
||||
<td class="c12" rowspan="2">邵刚</td>
|
||||
</tr>
|
||||
<tr class="r3">
|
||||
<td class="c11">徐宏涛</td>
|
||||
</tr>
|
||||
<tr class="r3">
|
||||
<td class="c17" rowspan="2">教室</td>
|
||||
<td class="c15" rowspan="2">202</td>
|
||||
<td class="c15" rowspan="2">202</td>
|
||||
<td class="c15" rowspan="2">3号机房</td>
|
||||
<td class="c15" rowspan="2">3号机房</td>
|
||||
<td class="c15" rowspan="2">202</td>
|
||||
<td class="c15" rowspan="2">操场</td>
|
||||
<td class="c15" rowspan="2">202</td>
|
||||
<td class="c15" rowspan="2">202</td>
|
||||
<td class="c15" rowspan="2">202</td>
|
||||
<td class="c15" rowspan="2">202</td>
|
||||
<td class="c15" rowspan="2">202</td>
|
||||
<td class="c15" rowspan="2">202</td>
|
||||
</tr>
|
||||
<tr class="r5">
|
||||
</tr>
|
||||
<tr class="r2">
|
||||
<td class="c8" rowspan="6">16 级 治 安 管 理 班 </td>
|
||||
<td class="c17" rowspan="2">课程</td>
|
||||
<td class="c12" rowspan="2">刑事技术</td>
|
||||
<td class="c12" rowspan="2">体能</td>
|
||||
<td class="c12" rowspan="2">刑事技术</td>
|
||||
<td class="c12" rowspan="2">治安秩序管理</td>
|
||||
<td class="c12" rowspan="2">刑事侦查概论</td>
|
||||
<td class="c12" rowspan="2">刑法</td>
|
||||
<td class="c18">群众工作与纠纷调解</td>
|
||||
<td class="c12" rowspan="2">群众工作与纠纷调解</td>
|
||||
<td class="c12" rowspan="2">公共关系(选修)</td>
|
||||
<td class="c12" rowspan="2">刑事侦查概论</td>
|
||||
<td class="c12" rowspan="2">刑法</td>
|
||||
<td class="c12" rowspan="6">自习</td>
|
||||
<td class="c12" rowspan="6">自习</td>
|
||||
<td class="c12" rowspan="6">自习</td>
|
||||
</tr>
|
||||
<tr class="r6">
|
||||
<td class="c19">q</td>
|
||||
</tr>
|
||||
<tr class="r7">
|
||||
<td class="c17" rowspan="2">教师</td>
|
||||
<td class="c12" rowspan="2">郭海川 韩易浦</td>
|
||||
<td class="c12" rowspan="2">张付海</td>
|
||||
<td class="c12" rowspan="2">郭海川 韩易浦</td>
|
||||
<td class="c12" rowspan="2">翟政亮</td>
|
||||
<td class="c12" rowspan="2">邵妍</td>
|
||||
<td class="c12" rowspan="2">薛强</td>
|
||||
<td class="c15">刘晓鹏</td>
|
||||
<td class="c12" rowspan="2">刘晓鹏</td>
|
||||
<td class="c12" rowspan="2">尚欣</td>
|
||||
<td class="c12" rowspan="2">邵妍</td>
|
||||
<td class="c12" rowspan="2">薛强</td>
|
||||
</tr>
|
||||
<tr class="r7">
|
||||
<td class="c11">翟政亮</td>
|
||||
</tr>
|
||||
<tr class="r3">
|
||||
<td class="c17" rowspan="2">教室</td>
|
||||
<td class="c15" rowspan="2">218</td>
|
||||
<td class="c15" rowspan="2">操场</td>
|
||||
<td class="c15" rowspan="2">218</td>
|
||||
<td class="c15" rowspan="2">218</td>
|
||||
<td class="c15" rowspan="2">218</td>
|
||||
<td class="c15" rowspan="2">218</td>
|
||||
<td class="c15" rowspan="2">218</td>
|
||||
<td class="c15" rowspan="2">218</td>
|
||||
<td class="c15" rowspan="2">218</td>
|
||||
<td class="c15" rowspan="2">218</td>
|
||||
<td class="c15" rowspan="2">218</td>
|
||||
</tr>
|
||||
<tr class="r8">
|
||||
</tr>
|
||||
<tr class="r2">
|
||||
<td class="c13" rowspan="6">16 网 络 安 全 监 察 1 班</td>
|
||||
<td class="c17" rowspan="2">课程</td>
|
||||
<td class="c12" rowspan="2">应用写作</td>
|
||||
<td class="c14" rowspan="2">数据库系统应用</td>
|
||||
<td class="c20" rowspan="2">周二中午:计算机安全管理及实用技术</td>
|
||||
<td class="c13">刑事诉讼法</td>
|
||||
<td class="c21" rowspan="2">周一中午:数据库系统应用</td>
|
||||
<td class="c12" rowspan="2">民法</td>
|
||||
<td class="c12" rowspan="2">体育</td>
|
||||
<td class="c12" rowspan="2">VB语言程序设计</td>
|
||||
<td class="c12" rowspan="6">选修</td>
|
||||
<td class="c12" rowspan="2">VB语言程序设计</td>
|
||||
<td class="c12" rowspan="2">刑事诉讼法</td>
|
||||
<td class="c12" rowspan="6">选修</td>
|
||||
<td class="c15">应用写作</td>
|
||||
<td class="c12" rowspan="2">犯罪心理</td>
|
||||
</tr>
|
||||
<tr class="r2">
|
||||
<td class="c11">民法</td>
|
||||
<td class="c11">犯罪心理</td>
|
||||
</tr>
|
||||
<tr class="r9">
|
||||
<td class="c17" rowspan="2">教师</td>
|
||||
<td class="c12" rowspan="2">关利</td>
|
||||
<td class="c12" rowspan="2">杨斌</td>
|
||||
<td class="c12" rowspan="2">赵晓松</td>
|
||||
<td class="c15">王伟</td>
|
||||
<td class="c12" rowspan="2">杨斌</td>
|
||||
<td class="c12" rowspan="2">李静</td>
|
||||
<td class="c12" rowspan="2">程军</td>
|
||||
<td class="c12" rowspan="2">赵伟</td>
|
||||
<td class="c12" rowspan="2">赵伟</td>
|
||||
<td class="c12" rowspan="2">王伟</td>
|
||||
<td class="c15">关利</td>
|
||||
<td class="c12" rowspan="2">张学林</td>
|
||||
</tr>
|
||||
<tr class="r10">
|
||||
<td class="c11">李静</td>
|
||||
<td class="c11">张学林</td>
|
||||
</tr>
|
||||
<tr class="r3">
|
||||
<td class="c17" rowspan="2">教室</td>
|
||||
<td class="c15" rowspan="2">东阶梯</td>
|
||||
<td class="c15" rowspan="2">2号机房</td>
|
||||
<td class="c15" rowspan="2">主楼201</td>
|
||||
<td class="c15" rowspan="2">101</td>
|
||||
<td class="c15" rowspan="2">2号机房</td>
|
||||
<td class="c15" rowspan="2">101</td>
|
||||
<td class="c15" rowspan="2">操场</td>
|
||||
<td class="c15" rowspan="2">3号机房</td>
|
||||
<td class="c15" rowspan="2">3号机房</td>
|
||||
<td class="c15" rowspan="2">101</td>
|
||||
<td class="c15">东阶梯</td>
|
||||
<td class="c15" rowspan="2">主楼201</td>
|
||||
</tr>
|
||||
<tr class="r11">
|
||||
<td class="c11">主楼201</td>
|
||||
</tr>
|
||||
<tr class="r12">
|
||||
<td class="c22" colspan="16">注:1、课程一栏中有两科次的,上面的课程单周上课,下面的课程双周上课。2、每天上课时间:上午第1节8:30至9:55;第2节10:15至11:40;中午上课时间12:30至13:55;下午第3节14:00至15:25。</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||