ting.yin 3 tahun lalu
induk
melakukan
929fa644dc

+ 1 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/user/service/UserService.java

@@ -8,7 +8,7 @@ public interface UserService {
 
     User login(String loginName, String password, String ip);
 
-    User externalLogin(Integer schoolId, String account, String name, Role role);
+    User externalLogin(Integer schoolId, String account, String name, String password, Role role);
 
     User findByLoginName(String loginName);
 

+ 9 - 5
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/user/service/impl/UserServiceImpl.java

@@ -7,6 +7,7 @@ import cn.com.qmth.stmms.biz.user.service.query.UserSearchQuery;
 import cn.com.qmth.stmms.common.enums.Role;
 import cn.com.qmth.stmms.common.enums.UserSource;
 import cn.com.qmth.stmms.common.utils.EncryptUtils;
+
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -19,6 +20,7 @@ import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
+
 import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
@@ -130,9 +132,8 @@ public class UserServiceImpl implements UserService {
                         predicates.add(cb.equal(root.get("role"), role));
                     }
                 }
-                return predicates.isEmpty() ?
-                        cb.conjunction() :
-                        cb.and(predicates.toArray(new Predicate[predicates.size()]));
+                return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
+                        .size()]));
             }
         }, query);
         if (result != null) {
@@ -163,7 +164,7 @@ public class UserServiceImpl implements UserService {
 
     @Override
     @Transactional
-    public User externalLogin(Integer schoolId, String account, String name, Role role) {
+    public User externalLogin(Integer schoolId, String account, String name, String password, Role role) {
         User user = userDao.findFirstBySchoolIdAndRelatedAccount(schoolId, account);
         if (user == null) {
             user = new User();
@@ -178,9 +179,12 @@ public class UserServiceImpl implements UserService {
             user.setCreatedTime(new Date());
             user.setUpdatedTime(new Date());
         }
-        if (name != null) {
+        if (StringUtils.isNotBlank(name)) {
             user.setName(name);
         }
+        if (StringUtils.isNotBlank(password)) {
+            user.setPassword(EncryptUtils.md5(password));
+        }
         user.setLastLoginTime(new Date());
         user.refreshAccessToken();
         return userDao.save(user);

+ 186 - 19
stmms-web/src/main/java/cn/com/qmth/stmms/api/controller/CoreController.java

@@ -1,39 +1,52 @@
 package cn.com.qmth.stmms.api.controller;
 
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.servlet.http.HttpServletRequest;
+
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import cn.com.qmth.stmms.api.dto.PaperDTO;
+import cn.com.qmth.stmms.api.dto.QuestionDTO;
 import cn.com.qmth.stmms.api.exception.ApiException;
 import cn.com.qmth.stmms.biz.exam.model.Exam;
 import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
+import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.file.service.FileService;
+import cn.com.qmth.stmms.biz.user.model.User;
+import cn.com.qmth.stmms.biz.user.service.UserService;
 import cn.com.qmth.stmms.biz.utils.ScoreItem;
 import cn.com.qmth.stmms.common.annotation.RoleRequire;
 import cn.com.qmth.stmms.common.domain.ApiUser;
-import cn.com.qmth.stmms.common.enums.*;
+import cn.com.qmth.stmms.common.enums.ExamStatus;
+import cn.com.qmth.stmms.common.enums.ExamType;
+import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
+import cn.com.qmth.stmms.common.enums.Role;
+import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 import cn.com.qmth.stmms.common.utils.DateUtils;
 import cn.com.qmth.stmms.common.utils.RequestUtils;
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
-
-import org.apache.commons.lang.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import javax.servlet.http.HttpServletRequest;
-
-import java.text.DecimalFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.stream.Collectors;
 
 @Controller("coreApiController")
 @RequestMapping("/api")
@@ -62,6 +75,12 @@ public class CoreController extends BaseApiController {
     @Autowired
     private ExamSubjectService subjectService;
 
+    @Autowired
+    private UserService userService;
+
+    @Autowired
+    private MarkGroupService groupService;
+
     @RequestMapping(value = "/exam/save", method = RequestMethod.POST)
     @ResponseBody
     @RoleRequire({ Role.SCHOOL_ADMIN, Role.SCHOOL_DEV })
@@ -253,7 +272,7 @@ public class CoreController extends BaseApiController {
             @RequestParam(required = false) String examCode, @RequestParam(required = false) String examNumber,
             @RequestParam(required = false) String studentCode, @RequestParam(required = false) String subjectCode,
             @RequestParam(required = false) String college, @RequestParam(required = false) String className,
-            @RequestParam(required = false) String teacher,
+            @RequestParam(required = false) String teacher, @RequestParam(required = false) Boolean withMarkTrack,
             @RequestParam(required = false, defaultValue = "1") Integer pageNumber,
             @RequestParam(required = false, defaultValue = "20") Integer pageSize) {
         ApiUser user = RequestUtils.getApiUser(request);
@@ -357,6 +376,10 @@ public class CoreController extends BaseApiController {
             }
             obj.accumulate("objectiveScoreDetail", objective);
             obj.accumulate("subjectiveScoreDetail", subjective);
+            // 构造给分轨迹
+            if (withMarkTrack != null && withMarkTrack.booleanValue()) {
+                obj.accumulate("markTags", studentService.buildSheetTags(student, false));
+            }
             // 构造原图下载地址
             if (student.isUpload()) {
                 obj.accumulate(
@@ -455,4 +478,148 @@ public class CoreController extends BaseApiController {
         result.accumulate("updateTime", DateUtils.formatDateTime(new Date()));
         return result;
     }
+
+    @RequestMapping(value = "/user/save", method = RequestMethod.POST)
+    @ResponseBody
+    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SCHOOL_DEV })
+    public JSONObject subjectSave(HttpServletRequest request, @RequestParam String account,
+            @RequestParam(required = false) String name, @RequestParam(required = false) String password,
+            @RequestParam(required = false) Role role, @RequestParam boolean enable) {
+        ApiUser user = RequestUtils.getApiUser(request);
+        JSONObject result = new JSONObject();
+        // 输入字段预处理并初步校验
+        account = validate("account", account, true, 32);
+        name = validate("name", name, true, 32);
+        password = validate("password", password, false, 32);
+        User u = userService.externalLogin(user.getSchoolId(), account, name, password, role);
+        if (u.isEnable() != enable) {
+            u.setEnable(enable);
+            userService.save(u);
+        }
+        result.accumulate("updateTime", DateUtils.formatDateTime(new Date()));
+        return result;
+    }
+
+    @RequestMapping(value = "/exam/paper/save", method = RequestMethod.POST)
+    @ResponseBody
+    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SCHOOL_DEV })
+    public JSONObject paperSave(HttpServletRequest request, @RequestBody PaperDTO paper) {
+        ApiUser user = RequestUtils.getApiUser(request);
+        JSONObject result = new JSONObject();
+        // 输入字段预处理并初步校验
+        Exam exam = examService.findById(paper.getExamId());
+        if (exam == null) {
+            throw ApiException.QUERY_PARAM_ERROR.replaceMessage("examId invalid");
+        } else if (!exam.getSchoolId().equals(user.getSchoolId()) || exam.getStatus() != ExamStatus.START) {
+            throw ApiException.EXAM_NOT_ACCESSIBLED;
+        }
+        ExamSubject subject = subjectService.find(paper.getExamId(), paper.getSubjectCode());
+        if (subject == null) {
+            throw ApiException.QUERY_PARAM_ERROR.replaceMessage("subjectCode invalid");
+        }
+        validate("paperType", paper.getPaperType(), false, 16);
+        if (StringUtils.isNotBlank(paper.getPaperType()) && !paper.getPaperType().matches(PAPER_TYPES_REGEX)) {
+            throw ApiException.QUERY_PARAM_ERROR.replaceMessage("paperType invalid");
+        }
+        // 客观题更新
+        if (paper.getObjective()) {
+            if (0 != questionService.countByExamIdAndSubjectAndObjectiveAndGroupNumberIsNull(paper.getExamId(),
+                    subject.getCode(), true)) {
+                questionService.deleteByExamAndSubjectAndObjective(paper.getExamId(), subject.getCode(), true);
+            }
+            List<ExamQuestion> oList = parseQustionList(paper.getQuestions(), paper.getExamId(),
+                    paper.getSubjectCode(), paper.getPaperType(), paper.getObjective());
+            questionService.save(oList);
+            examService.updateObjectiveStatus(paper.getExamId(), ObjectiveStatus.WAITING);
+            subjectService.updateScore(paper.getExamId(), subject.getCode(), true,
+                    questionService.sumTotalScore(paper.getExamId(), subject.getCode(), true));
+        } else {
+            List<MarkGroup> groups = groupService.findByExamAndSubject(paper.getExamId(), subject.getCode());
+            if (groups == null || groups.size() == 0) {
+                if (0 != questionService.countByExamIdAndSubjectAndObjectiveAndGroupNumberIsNull(paper.getExamId(),
+                        subject.getCode(), false)) {
+                    questionService.deleteByExamAndSubjectAndObjective(paper.getExamId(), subject.getCode(), false);
+                }
+                List<ExamQuestion> sList = parseQustionList(paper.getQuestions(), paper.getExamId(),
+                        paper.getSubjectCode(), paper.getPaperType(), paper.getObjective());
+                questionService.save(sList);
+                subjectService.updateScore(paper.getExamId(), subject.getCode(), false,
+                        questionService.sumTotalScore(paper.getExamId(), subject.getCode(), false));
+            }
+        }
+        result.accumulate("updateTime", DateUtils.formatDateTime(new Date()));
+        return result;
+    }
+
+    private List<ExamQuestion> parseQustionList(QuestionDTO[] questions, Integer examId, String subjectCode,
+            String paperType, boolean objective) {
+        List<ExamQuestion> list = new ArrayList<ExamQuestion>();
+        for (QuestionDTO dto : questions) {
+            ExamQuestion q = dto.transform();
+            q.setExamId(examId);
+            q.setSubjectCode(subjectCode);
+            if (StringUtils.isNotBlank(paperType)) {
+                q.setPaperType(paperType);
+            } else {
+                q.setPaperType(NULL_PAPER_TYPE_PLACEHOLDER);
+            }
+            q.setObjective(objective);
+            list.add(q);
+        }
+        return list;
+    }
+
+    @RequestMapping(value = "/exam/paper/query", method = RequestMethod.POST)
+    @ResponseBody
+    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SCHOOL_DEV })
+    public JSONArray paperQuery(HttpServletRequest request, @RequestParam Integer examId,
+            @RequestParam String subjectCode, @RequestParam(required = false, defaultValue = "#") String paperType) {
+        ApiUser user = RequestUtils.getApiUser(request);
+        JSONArray result = new JSONArray();
+        // 输入字段预处理并初步校验
+        Exam exam = examService.findById(examId);
+        if (exam == null || !exam.getSchoolId().equals(user.getSchoolId()) || exam.getStatus() != ExamStatus.START) {
+            throw ApiException.EXAM_NOT_ACCESSIBLED;
+        }
+        subjectCode = validate("subjectCode", subjectCode, true, 64);
+        ExamSubject subject = subjectService.find(examId, subjectCode);
+        if (subject == null) {
+            throw ApiException.QUERY_PARAM_ERROR.appendMessage(": subjectCode error");
+        }
+        if (StringUtils.isNotBlank(paperType)) {
+            List<String> paperTypes = questionService.getPaperType(examId, subjectCode);
+            if (!contains(subject.getObjectiveScore() > 0, paperTypes, paperType)) {
+                throw ApiException.QUERY_PARAM_ERROR.appendMessage(": paperType error");
+            }
+        }
+        List<ExamQuestion> list = new ArrayList<ExamQuestion>();
+        list.addAll(questionService.findByExamAndSubjectAndObjectiveAndPaperType(examId, subjectCode, true, paperType));
+        list.addAll(questionService.findByExamAndSubjectAndObjective(examId, subjectCode, false));
+        for (ExamQuestion q : list) {
+            JSONObject value = new JSONObject();
+            value.accumulate("objective", q.isObjective());
+            value.accumulate("mainNumber", q.getMainNumber());
+            value.accumulate("subNumber", q.getSubNumber());
+            value.accumulate("mainTitle", q.getMainNumber());
+            value.accumulate("totalScore", q.getTotalScore());
+            value.accumulate("answer", q.getAnswer() == null ? "" : q.getAnswer());
+            result.add(value);
+        }
+        return result;
+    }
+
+    private boolean contains(boolean objective, List<String> paperTypes, String paperType) {
+        if (NULL_PAPER_TYPE_PLACEHOLDER.equals(paperType)) {
+            if (!objective) {
+                // 纯主观题
+                return true;
+            }
+        }
+        for (String s : paperTypes) {
+            if (paperType.equalsIgnoreCase(s)) {
+                return true;
+            }
+        }
+        return false;
+    }
 }

+ 58 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/api/dto/PaperDTO.java

@@ -0,0 +1,58 @@
+package cn.com.qmth.stmms.api.dto;
+
+public class PaperDTO {
+
+    private Integer examId;
+
+    private String subjectCode;
+
+    private String paperType;
+
+    private Boolean objective;
+
+    private QuestionDTO[] questions;
+
+    public PaperDTO() {
+    }
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public String getSubjectCode() {
+        return subjectCode;
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        this.subjectCode = subjectCode;
+    }
+
+    public String getPaperType() {
+        return paperType;
+    }
+
+    public void setPaperType(String paperType) {
+        this.paperType = paperType;
+    }
+
+    public Boolean getObjective() {
+        return objective;
+    }
+
+    public void setObjective(Boolean objective) {
+        this.objective = objective;
+    }
+
+    public QuestionDTO[] getQuestions() {
+        return questions;
+    }
+
+    public void setQuestions(QuestionDTO[] questions) {
+        this.questions = questions;
+    }
+
+}

+ 77 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/api/dto/QuestionDTO.java

@@ -0,0 +1,77 @@
+package cn.com.qmth.stmms.api.dto;
+
+import org.apache.commons.lang.StringUtils;
+
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+
+public class QuestionDTO {
+
+    private Integer mainNumber;
+
+    private String subNumber;
+
+    private String mainTitle;
+
+    private String answer;
+
+    private Double totalScore;
+
+    public ExamQuestion transform() {
+        ExamQuestion question = new ExamQuestion();
+        question.setMainNumber(mainNumber);
+        question.setSubNumber(subNumber);
+        question.setMainTitle(StringUtils.trimToNull(mainTitle));
+        question.setAnswer(StringUtils.trimToNull(answer));
+        question.setTotalScore(totalScore);
+        if (totalScore % 1 == 0) {
+            question.setIntervalScore(1d);
+        } else {
+            question.setIntervalScore(0.5);
+        }
+        return question;
+    }
+
+    public QuestionDTO() {
+    }
+
+    public Integer getMainNumber() {
+        return mainNumber;
+    }
+
+    public void setMainNumber(Integer mainNumber) {
+        this.mainNumber = mainNumber;
+    }
+
+    public String getSubNumber() {
+        return subNumber;
+    }
+
+    public void setSubNumber(String subNumber) {
+        this.subNumber = subNumber;
+    }
+
+    public String getMainTitle() {
+        return mainTitle;
+    }
+
+    public void setMainTitle(String mainTitle) {
+        this.mainTitle = mainTitle;
+    }
+
+    public String getAnswer() {
+        return answer;
+    }
+
+    public void setAnswer(String answer) {
+        this.answer = answer;
+    }
+
+    public Double getTotalScore() {
+        return totalScore;
+    }
+
+    public void setTotalScore(Double totalScore) {
+        this.totalScore = totalScore;
+    }
+
+}

+ 54 - 3
stmms-web/src/main/java/cn/com/qmth/stmms/open/controller/OpenUserController.java

@@ -63,8 +63,8 @@ public class OpenUserController {
         }
         // 签名验证,获取访问学校
         School school = null;
-        SignatureInfo info = authorizationService
-                .buildSignature(time, authorization, request.getMethod(), request.getServletPath());
+        SignatureInfo info = authorizationService.buildSignature(time, authorization, request.getMethod(),
+                request.getServletPath());
         if (info != null && info.getType() == SignatureType.SECRET) {
             school = schoolService.findByAccessKey(info.getInvoker());
         }
@@ -72,7 +72,7 @@ public class OpenUserController {
             return errorRedirect(redirect, returnUrl, "鉴权失败");
         }
         // 查找第三方账号并登陆
-        User user = userService.externalLogin(school.getId(), account, name, Role.MARKER);
+        User user = userService.externalLogin(school.getId(), account, name, null, Role.MARKER);
         if (user == null) {
             return errorRedirect(redirect, returnUrl, "第三方登录异常");
         }
@@ -109,4 +109,55 @@ public class OpenUserController {
         }
         return "redirect:/open/error";
     }
+
+    @RequestMapping(value = "/subject_header/login", method = RequestMethod.POST)
+    public String subjectHeaderLogin(HttpServletRequest request, HttpServletResponse response,
+            RedirectAttributes redirect, @RequestParam Long time, @RequestParam String authorization,
+            @RequestParam String account, @RequestParam String name, @RequestParam String returnUrl) {
+        // 请求参数验证
+        authorization = StringUtils.trimToEmpty(authorization);
+        name = StringUtils.trimToNull(name);
+        account = StringUtils.trimToEmpty(account);
+        returnUrl = StringUtils.trimToEmpty(returnUrl);
+        if (time == null) {
+            return errorRedirect(redirect, null, "time不能为空");
+        }
+        if (authorization.length() == 0) {
+            return errorRedirect(redirect, null, "authorization不能为空");
+        }
+        if (returnUrl.length() == 0) {
+            return errorRedirect(redirect, null, "returnUrl不能为空");
+        }
+        if (account.length() == 0) {
+            return errorRedirect(redirect, returnUrl, "account不能为空");
+        }
+        // 签名验证,获取访问学校
+        School school = null;
+        SignatureInfo info = authorizationService.buildSignature(time, authorization, request.getMethod(),
+                request.getServletPath());
+        if (info != null && info.getType() == SignatureType.SECRET) {
+            school = schoolService.findByAccessKey(info.getInvoker());
+        }
+        if (school == null || !school.isEnable() || !info.validate(school.getAccessSecret())) {
+            return errorRedirect(redirect, returnUrl, "鉴权失败");
+        }
+        // 查找第三方账号并登陆
+        User user = userService.externalLogin(school.getId(), account, name, null, Role.SUBJECT_HEADER);
+        if (user == null) {
+            return errorRedirect(redirect, returnUrl, "第三方登录异常");
+        }
+        if (!user.isEnable()) {
+            return errorRedirect(redirect, returnUrl, "第三方账号已禁用");
+        }
+        if (user.getRole() != Role.MARKER) {
+            return errorRedirect(redirect, returnUrl, "第三方账号没有评卷权限");
+        }
+        // 保存第三方账号到session
+        StmmsSession session = RequestUtils.getSession(request);
+        WebUser wu = new WebUser(user);
+        wu.setLogoutUrl(returnUrl);
+        session.saveWebUser(wu);
+        sessionService.put(request, response, session);
+        return "redirect:/mark/subject-select";
+    }
 }