Prechádzať zdrojové kódy

update content-service/exam

reghao 7 mesiacov pred
rodič
commit
b5fb670972
17 zmenil súbory, kde vykonal 224 pridanie a 309 odobranie
  1. 5 5
      content/content-service/src/main/java/cn/reghao/tnb/content/app/config/web/WebConfig.java
  2. 12 9
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/controller/ExamController.java
  3. 0 19
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/db/mapper/ExamUserMapper.java
  4. 0 54
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/constant/ExamRole.java
  5. 1 1
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/constant/PaperViewType.java
  6. 0 21
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/po/ExamUser.java
  7. 2 8
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/po/Paper.java
  8. 34 0
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/vo/EvalPaper.java
  9. 16 18
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/vo/PaperView.java
  10. 25 0
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/ExamAccountService.java
  11. 0 31
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/ExamUserService.java
  12. 33 21
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/PaperService.java
  13. 5 10
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/PaperViewService.java
  14. 0 74
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/web/AccessInterceptor.java
  15. 89 0
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/web/ExamAccountInterceptor.java
  16. 0 36
      content/content-service/src/main/resources/mapper/exam/ExamUserMapper.xml
  17. 2 2
      content/content-service/src/main/resources/mapper/exam/PaperMapper.xml

+ 5 - 5
content/content-service/src/main/java/cn/reghao/tnb/content/app/config/web/WebConfig.java

@@ -1,6 +1,6 @@
 package cn.reghao.tnb.content.app.config.web;
 
-import cn.reghao.tnb.content.app.exam.web.AccessInterceptor;
+import cn.reghao.tnb.content.app.exam.web.ExamAccountInterceptor;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -15,15 +15,15 @@ import javax.servlet.Filter;
  */
 @Configuration
 public class WebConfig implements WebMvcConfigurer {
-    private final AccessInterceptor accessInterceptor;
+    private final ExamAccountInterceptor examAccountInterceptor;
 
-    public WebConfig(AccessInterceptor accessInterceptor) {
-        this.accessInterceptor = accessInterceptor;
+    public WebConfig(ExamAccountInterceptor examAccountInterceptor) {
+        this.examAccountInterceptor = examAccountInterceptor;
     }
 
     @Override
     public void addInterceptors(InterceptorRegistry registry) {
-        registry.addInterceptor(accessInterceptor);
+        registry.addInterceptor(examAccountInterceptor);
     }
 
     @Bean

+ 12 - 9
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/controller/ExamController.java

@@ -8,7 +8,7 @@ import cn.reghao.tnb.content.app.exam.model.dto.UserResult;
 import cn.reghao.tnb.content.app.exam.model.query.PaperQuery;
 import cn.reghao.tnb.content.app.exam.model.vo.*;
 import cn.reghao.tnb.content.app.exam.service.ExamService;
-import cn.reghao.tnb.content.app.exam.service.ExamUserService;
+import cn.reghao.tnb.content.app.exam.service.ExamAccountService;
 import cn.reghao.tnb.content.app.exam.service.PaperService;
 import cn.reghao.tnb.content.app.exam.service.PaperViewService;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -23,32 +23,35 @@ import java.util.List;
  * @author reghao
  * @date 2024-08-24 13:29:10
  */
-@Tag(name = "考试接口")
+@Tag(name = "测评接口")
 @RestController
 @RequestMapping("/api/content/exam/eval")
 public class ExamController {
-    private final ExamUserService examUserService;
+    private final ExamAccountService examAccountService;
     private final ExamService examService;
     private final PaperService paperService;
     private final PaperViewService paperViewService;
 
-    public ExamController(ExamUserService examUserService, ExamService examService,
+    public ExamController(ExamAccountService examAccountService, ExamService examService,
                           PaperService paperService, PaperViewService paperViewService) {
-        this.examUserService = examUserService;
+        this.examAccountService = examAccountService;
         this.examService = examService;
         this.paperService = paperService;
         this.paperViewService = paperViewService;
     }
 
-    @Operation(summary = "获取考试列表", description = "N")
+    @Operation(summary = "获取测评试卷列表", description = "N")
     @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE)
     public String getExams(PaperQuery paperQuery) {
-        paperQuery.setScope(examUserService.getRole());
-        PageList<PaperView> pageList1 = paperService.getExamPapers(paperQuery);
+        long loginUser = UserContext.getUser();
+        int role = examAccountService.getExamRole(loginUser);
+
+        paperQuery.setScope(role);
+        PageList<EvalPaper> pageList1 = paperService.getEvalPapers(paperQuery);
         return WebResult.success(pageList1);
     }
 
-    @Operation(summary = "获取考试使用的试卷", description = "N")
+    @Operation(summary = "获取试卷开始测评", description = "N")
     @GetMapping(value = "/start/{paperId}", produces = MediaType.APPLICATION_JSON_VALUE)
     public String getExamPaperView(@PathVariable("paperId") int paperId) {
         int viewType = PaperViewType.PaperExam.getCode();

+ 0 - 19
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/db/mapper/ExamUserMapper.java

@@ -1,19 +0,0 @@
-package cn.reghao.tnb.content.app.exam.db.mapper;
-
-import cn.reghao.jutil.jdk.db.BaseMapper;
-import cn.reghao.tnb.content.app.exam.model.po.ExamUser;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-
-/**
- * @author reghao
- * @date 2025-08-10 19:22:51
- */
-@Mapper
-public interface ExamUserMapper extends BaseMapper<ExamUser> {
-    List<ExamUser> findByPaperId(int paperId);
-    ExamUser findByUserId(long userId);
-    ExamUser findExamUser(@Param("paperId") int paperId, @Param("userId") long userId);
-}

+ 0 - 54
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/constant/ExamRole.java

@@ -1,54 +0,0 @@
-package cn.reghao.tnb.content.app.exam.model.constant;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author reghao
- * @date 2024-09-14 15:49:02
- */
-public enum ExamRole {
-    TEACHER(1, "教师"),
-    STUDENT(2, "学生");
-
-    private final int code;
-    private final String desc;
-    private static Map<Integer, ExamRole> map = new HashMap<>();
-    static {
-        for (ExamRole role : ExamRole.values()) {
-            map.put(role.code, role);
-        }
-    }
-
-    ExamRole(Integer code, String desc) {
-        this.code = code;
-        this.desc = desc;
-    }
-
-    public String getName() {
-        return this.name();
-    }
-
-    /**
-     * 提供给 @ValidEnum 调用
-     *
-     * @param
-     * @return
-     * @date 2023-10-11 14:44:42
-     */
-    public int getValue() {
-        return this.code;
-    }
-
-    public Integer getCode() {
-        return code;
-    }
-
-    public String getDesc() {
-        return desc;
-    }
-
-    public static ExamRole getByCode(int code) {
-        return map.get(code);
-    }
-}

+ 1 - 1
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/constant/PaperViewType.java

@@ -9,7 +9,7 @@ import java.util.Map;
  */
 public enum PaperViewType {
     PaperPreview(1, "试卷预览"),
-    PaperExam(2, "考试预览"),
+    PaperExam(2, "测评预览"),
     PaperMark(3, "阅卷预览"),
     PaperResult(4, "结果预览");
 

+ 0 - 21
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/po/ExamUser.java

@@ -1,21 +0,0 @@
-package cn.reghao.tnb.content.app.exam.model.po;
-
-import cn.reghao.jutil.jdk.db.BaseObject;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * @author reghao
- * @date 2025-08-10 19:22:05
- */
-@NoArgsConstructor
-@AllArgsConstructor
-@Getter
-@Setter
-public class ExamUser extends BaseObject<Integer> {
-    private Integer paperId;
-    private Long userId;
-    private Integer role;
-}

+ 2 - 8
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/po/Paper.java

@@ -22,14 +22,11 @@ public class Paper extends BaseObject<Integer> {
     private Integer subjectId;
     private String name;
     private Integer markType;
-    private String description;
+    private Integer scope;
     private Integer duration;
     private Integer totalScore;
-    private Integer passScore;
     private LocalDateTime startTime;
-    private LocalDateTime endTime;
     private String passcode;
-    //private Integer status;
     private Boolean hasSubjective;
     private LocalDateTime createAt;
     private Long createBy;
@@ -39,14 +36,11 @@ public class Paper extends BaseObject<Integer> {
         this.subjectId = 1;
         this.name = paperAddDto.getExamName();
         this.markType = 1;
-        this.description = paperAddDto.getExamDesc();
+        this.scope = 1;
         this.duration = paperAddDto.getExamDuration();
         this.totalScore = paperAddDto.getTotalScore();
-        this.passScore = paperAddDto.getPassScore();
         this.startTime = LocalDateTime.ofInstant(paperAddDto.getStartTime().toInstant(), ZoneId.systemDefault());
-        this.endTime = LocalDateTime.ofInstant(paperAddDto.getEndTime().toInstant(), ZoneId.systemDefault());
         this.passcode = paperAddDto.getExamPassword();
-        //this.status = 1;
         this.hasSubjective = false;
         this.createAt = LocalDateTime.now();
         this.createBy = UserContext.getUser();

+ 34 - 0
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/vo/EvalPaper.java

@@ -0,0 +1,34 @@
+package cn.reghao.tnb.content.app.exam.model.vo;
+
+import cn.reghao.jutil.jdk.converter.DateTimeConverter;
+import cn.reghao.tnb.content.app.exam.model.po.Paper;
+import lombok.Getter;
+
+/**
+ * @author reghao
+ * @date 2024-08-28 09:02:59
+ */
+@Getter
+public class EvalPaper {
+    private Integer examId;
+    private String examName;
+    private Boolean needPasscode;
+    private String password;
+    private Integer duration;
+    private String startTime;
+    private Integer totalScore;
+    private String myScore;
+    private Integer evalStatus;
+
+    public EvalPaper(Paper paper, int status, int userScore) {
+        this.needPasscode = false;
+        this.examId = paper.getId();
+        this.examName = paper.getName();
+        this.password = paper.getPasscode();
+        this.duration = paper.getDuration();
+        this.startTime = paper.getStartTime() != null ? DateTimeConverter.format(paper.getStartTime()) : "Anytime";
+        this.totalScore = paper.getTotalScore();
+        this.myScore = userScore != 0 ? ""+userScore : "N/A";
+        this.evalStatus = status;
+    }
+}

+ 16 - 18
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/vo/PaperView.java

@@ -8,29 +8,27 @@ import cn.reghao.tnb.content.app.exam.model.po.Paper;
  * @date 2024-08-28 09:02:59
  */
 public class PaperView {
-    private Integer examId;
-    private String examName;
-    private String examDesc;
-    private Integer type;
-    private String password;
+    private Integer paperId;
+    private String paperName;
+    private String subject;
+    private Integer markType;
+    private Integer scope;
+    private String passcode;
     private Integer duration;
     private String startTime;
-    private String endTime;
     private Integer totalScore;
-    private Integer passScore;
-    private Integer status;
+    private Boolean expired;
 
-    public PaperView(Paper paper, int status) {
-        this.type = 1;
-        this.examId = paper.getId();
-        this.examName = paper.getName();
-        this.examDesc = paper.getDescription();
-        this.password = paper.getPasscode();
+    public PaperView(String subject, Paper paper, boolean expired) {
+        this.subject = subject;
+        this.paperId = paper.getId();
+        this.paperName = paper.getName();
+        this.markType = paper.getMarkType();
+        this.scope = paper.getScope();
+        this.passcode = paper.getPasscode();
         this.duration = paper.getDuration();
-        this.startTime = DateTimeConverter.format(paper.getStartTime());
-        this.endTime = DateTimeConverter.format(paper.getEndTime());
+        this.startTime = paper.getStartTime() != null ? DateTimeConverter.format(paper.getStartTime()) : "Anytime";
         this.totalScore = paper.getTotalScore();
-        this.passScore = paper.getPassScore();
-        this.status = status;
+        this.expired = expired;
     }
 }

+ 25 - 0
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/ExamAccountService.java

@@ -0,0 +1,25 @@
+package cn.reghao.tnb.content.app.exam.service;
+
+import cn.reghao.tnb.account.api.dto.ExamAccount;
+import cn.reghao.tnb.account.api.iface.AccountQuery;
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author reghao
+ * @date 2025-08-11 15:14:56
+ */
+@Service
+public class ExamAccountService {
+    @DubboReference(check = false, retries = 0, timeout = 10_000)
+    private AccountQuery accountQuery;
+
+    public ExamAccount getExamAccount(long userId) {
+        return accountQuery.getExamAccount(userId);
+    }
+
+    public int getExamRole(long userId) {
+        ExamAccount examAccount = accountQuery.getExamAccount(userId);
+        return examAccount.isExamAdmin() ? 1 : 2;
+    }
+}

+ 0 - 31
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/ExamUserService.java

@@ -1,31 +0,0 @@
-package cn.reghao.tnb.content.app.exam.service;
-
-import cn.reghao.tnb.common.auth.UserContext;
-import cn.reghao.tnb.content.app.exam.db.mapper.ExamUserMapper;
-import cn.reghao.tnb.content.app.exam.model.po.ExamUser;
-import org.springframework.stereotype.Service;
-
-/**
- * @author reghao
- * @date 2025-08-11 15:14:56
- */
-@Service
-public class ExamUserService {
-    private final ExamUserMapper examUserMapper;
-
-    public ExamUserService(ExamUserMapper examUserMapper) {
-        this.examUserMapper = examUserMapper;
-    }
-
-    public boolean isAdminUser() {
-        long loginUser = UserContext.getUser();
-        ExamUser examUser = examUserMapper.findByUserId(loginUser);
-        return examUser != null && examUser.getRole() == 1;
-    }
-
-    public int getRole() {
-        long loginUser = UserContext.getUser();
-        ExamUser examUser = examUserMapper.findByUserId(loginUser);
-        return examUser != null ? examUser.getRole() : -1;
-    }
-}

+ 33 - 21
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/PaperService.java

@@ -1,5 +1,6 @@
 package cn.reghao.tnb.content.app.exam.service;
 
+import cn.reghao.jutil.jdk.converter.DateTimeConverter;
 import cn.reghao.jutil.jdk.db.Page;
 import cn.reghao.jutil.jdk.db.PageList;
 import cn.reghao.jutil.jdk.result.Result;
@@ -15,6 +16,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -25,22 +27,22 @@ import java.util.stream.Collectors;
 @Slf4j
 @Service
 public class PaperService {
+    private final SubjectMapper subjectMapper;
     private final PaperMapper paperMapper;
     private final PaperQuestionMapper paperQuestionMapper;
     private final QuestionMapper questionMapper;
     private final QuestionOptionMapper questionOptionMapper;
     private final PaperResultMapper paperResultMapper;
-    private final ExamUserMapper examUserMapper;
 
-    public PaperService(PaperMapper paperMapper, PaperQuestionMapper paperQuestionMapper,
+    public PaperService(SubjectMapper subjectMapper, PaperMapper paperMapper, PaperQuestionMapper paperQuestionMapper,
                         QuestionMapper questionMapper, QuestionOptionMapper questionOptionMapper,
-                        PaperResultMapper paperResultMapper, ExamUserMapper examUserMapper) {
+                        PaperResultMapper paperResultMapper) {
+        this.subjectMapper = subjectMapper;
         this.paperMapper = paperMapper;
         this.paperQuestionMapper = paperQuestionMapper;
         this.questionMapper = questionMapper;
         this.questionOptionMapper = questionOptionMapper;
         this.paperResultMapper = paperResultMapper;
-        this.examUserMapper = examUserMapper;
     }
 
     public Result createExamPaper(PaperAddDto paperAddDto) {
@@ -57,8 +59,6 @@ public class PaperService {
         list.forEach(paperQuestion -> {
             paperQuestion.setPaperId(paperId);
         });
-
-        examUserMapper.saveAll(getExamUsers(paperId));
         /*List<PaperQuestion> list1 = list.stream()
                 .map(paperQuestion -> {
                     if (paperQuestion.getChildren().isEmpty()) {
@@ -81,29 +81,17 @@ public class PaperService {
         }*/
     }
 
-    private List<ExamUser> getExamUsers(int paperId) {
-        List<ExamUser> list = new ArrayList<>();
-        long start = 10001L;
-        long total = 100;
-        while (start < start + total) {
-            ExamUser examUser = new ExamUser(paperId, start, 1);
-            list.add(examUser);
-            start++;
-        }
-        return list;
-    }
-
     public Result deleteExamPaper(int paperId) {
         paperMapper.deleteById(paperId);
         return Result.success();
     }
 
-    public PageList<PaperView> getExamPapers(PaperQuery paperQuery) {
+    public PageList<EvalPaper> getEvalPapers(PaperQuery paperQuery) {
         long loginUser = UserContext.getUser();
         int total = paperMapper.countByCriteria(paperQuery);
         Page page = paperQuery.getPage();
         List<Paper> list = paperMapper.findPaperByPage(page, paperQuery);
-        List<PaperView> list1 = list.stream()
+        List<EvalPaper> list1 = list.stream()
                 .map(paper -> {
                     int paperId = paper.getId();
                     int markType = paper.getMarkType();
@@ -113,17 +101,41 @@ public class PaperService {
                     // 2. 试卷已完成, 自己批改
                     // 3. 试卷已完成, 他人批改
                     // 4. 试卷已完成, 已批改
+                    int userScore = 0;
                     if (paperResult == null) {
                         status = 1;
                     } else if (paperResult.getMarked()) {
                         status = 4;
+                        userScore = paperResult.getUserScore();
                     } else if (markType == 2) {
                         status = 2;
                     } else {
                         status = 3;
                     }
 
-                    return new PaperView(paper, status);
+                    return new EvalPaper(paper, status, userScore);
+                })
+                .collect(Collectors.toList());
+
+        return PageList.pageList(page, total, list1);
+    }
+
+    public PageList<PaperView> getExamPapers(PaperQuery paperQuery) {
+        int total = paperMapper.countByCriteria(paperQuery);
+        Page page = paperQuery.getPage();
+        List<Paper> list = paperMapper.findPaperByPage(page, paperQuery);
+        List<PaperView> list1 = list.stream()
+                .map(paper -> {
+                    int subjectId = paper.getSubjectId();
+                    String subject = subjectMapper.findById(subjectId).getName();
+
+                    boolean expired = false;
+                    LocalDateTime startTime = paper.getStartTime();
+                    if (startTime != null) {
+                        long expireAt = DateTimeConverter.msTimestamp(startTime) + paper.getDuration()*60*1000L;
+                        expired = expireAt < System.currentTimeMillis();
+                    }
+                    return new PaperView(subject, paper, expired);
                 })
                 .collect(Collectors.toList());
 

+ 5 - 10
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/PaperViewService.java

@@ -28,31 +28,26 @@ public class PaperViewService {
     private final QuestionOptionMapper questionOptionMapper;
     private final RedisHash redisHash;
     private PaperAnswerMapper paperAnswerMapper;
-    private ExamUserMapper examUserMapper;
+    private ExamAccountService examAccountService;
 
     public PaperViewService(PaperMapper paperMapper, PaperQuestionMapper paperQuestionMapper,
                             QuestionMapper questionMapper, QuestionOptionMapper questionOptionMapper,
-                            RedisHash redisHash, PaperAnswerMapper paperAnswerMapper, ExamUserMapper examUserMapper) {
+                            RedisHash redisHash, PaperAnswerMapper paperAnswerMapper,
+                            ExamAccountService examAccountService) {
         this.paperMapper = paperMapper;
         this.paperQuestionMapper = paperQuestionMapper;
         this.questionMapper = questionMapper;
         this.questionOptionMapper = questionOptionMapper;
         this.redisHash = redisHash;
         this.paperAnswerMapper = paperAnswerMapper;
-        this.examUserMapper = examUserMapper;
+        this.examAccountService = examAccountService;
     }
 
     public PaperDetail getPaperDetail(int paperId, int viewType, int resultId) {
         long loginUser = UserContext.getUser();
-        ExamUser examUser = examUserMapper.findExamUser(paperId, loginUser);
-        if (examUser == null) {
-            // 用户没有访问试卷的权限
-            return new PaperDetail(paperId, 1);
-        }
+        int role = examAccountService.getExamRole(loginUser);
 
         Paper paper = paperMapper.findById(paperId);
-        int role = examUser.getRole();
-
         Map<Long, QuestionAnswer> paperAnswers;
         if (viewType == PaperViewType.PaperPreview.getCode()) {
             if (role > 1) {

+ 0 - 74
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/web/AccessInterceptor.java

@@ -1,74 +0,0 @@
-package cn.reghao.tnb.content.app.exam.web;
-
-import cn.reghao.jutil.web.WebResult;
-import cn.reghao.tnb.content.app.exam.service.ExamService;
-import cn.reghao.tnb.content.app.exam.service.ExamUserService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.lang.Nullable;
-import org.springframework.stereotype.Component;
-import org.springframework.web.servlet.HandlerInterceptor;
-import org.springframework.web.servlet.ModelAndView;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.PrintWriter;
-
-/**
- * HTTP 请求拦截器
- *
- * @author reghao
- * @date 2025-07-18 09:18:16
- */
-@Slf4j
-@Component
-public class AccessInterceptor implements HandlerInterceptor {
-    private final ExamUserService examUserService;
-
-    public AccessInterceptor(ExamUserService examUserService) {
-        this.examUserService = examUserService;
-    }
-
-    @Override
-    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
-            throws Exception {
-        String uri = request.getRequestURI();
-        String method = request.getMethod();
-        String userAgent = request.getHeader("user-agent");
-        String ipv4 = request.getRemoteAddr();
-        if (uri.startsWith("/api/content/exam/question")
-                || uri.startsWith("/api/content/exam/paper")) {
-            if (!examUserService.isAdminUser()) {
-                String retJson = WebResult.failWithMsg("非管理员");
-                response.setStatus(HttpServletResponse.SC_OK);
-                response.setContentType("application/json; charset=utf-8");
-                PrintWriter printWriter = response.getWriter();
-                printWriter.write(retJson);
-                return false;
-            }
-        }
-
-        if (uri.startsWith("/api/content/exam/eval")) {
-            if (examUserService.isAdminUser()) {
-                String retJson = WebResult.failWithMsg("非普通用户");
-                response.setStatus(HttpServletResponse.SC_OK);
-                response.setContentType("application/json; charset=utf-8");
-                PrintWriter printWriter = response.getWriter();
-                printWriter.write(retJson);
-                return false;
-            }
-        }
-
-        //log.info("{} {}", uri, method);
-        return true;
-    }
-
-    @Override
-    public void postHandle(HttpServletRequest request, HttpServletResponse response,
-                           Object handler, @Nullable ModelAndView modelAndView) throws Exception {
-    }
-
-    @Override
-    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
-                                Object handler, @Nullable Exception ex) throws Exception {
-    }
-}

+ 89 - 0
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/web/ExamAccountInterceptor.java

@@ -0,0 +1,89 @@
+package cn.reghao.tnb.content.app.exam.web;
+
+import cn.reghao.jutil.web.WebResult;
+import cn.reghao.tnb.account.api.dto.ExamAccount;
+import cn.reghao.tnb.common.auth.UserContext;
+import cn.reghao.tnb.content.app.exam.service.ExamAccountService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * 只放行具有 ExamAccount 的请求
+ *
+ * @author reghao
+ * @date 2025-07-18 09:18:16
+ */
+@Slf4j
+@Component
+public class ExamAccountInterceptor implements HandlerInterceptor {
+    private final ExamAccountService examAccountService;
+
+    public ExamAccountInterceptor(ExamAccountService examAccountService) {
+        this.examAccountService = examAccountService;
+    }
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+            throws Exception {
+        String uri = request.getRequestURI();
+        String method = request.getMethod();
+        String userAgent = request.getHeader("user-agent");
+        String ipv4 = request.getRemoteAddr();
+        if (uri.startsWith("/api/content/exam")) {
+            long loginUser = UserContext.getUser();
+            ExamAccount examAccount = examAccountService.getExamAccount(loginUser);
+            if (!examAccount.isExist()) {
+                String msg = "Current user not ExamAccount";
+                writeResponse(response, msg);
+                return false;
+            }
+
+            if (uri.startsWith("/api/content/exam/subject")
+                    || uri.startsWith("/api/content/exam/question")
+                    || uri.startsWith("/api/content/exam/paper")) {
+                if (!examAccount.isExamAdmin()) {
+                    String msg = "Current user not ExamAdmin";
+                    writeResponse(response, msg);
+                    return false;
+                }
+            }
+
+            if (uri.startsWith("/api/content/exam/eval")) {
+                if (examAccount.isExamAdmin()) {
+                    String msg = "Current user not ExamUser";
+                    writeResponse(response, msg);
+                    return false;
+                }
+            }
+        }
+
+        //log.info("{} {}", uri, method);
+        return true;
+    }
+
+    private void writeResponse(HttpServletResponse response, String msg) throws IOException {
+        String retJson = WebResult.failWithMsg(msg);
+        response.setStatus(HttpServletResponse.SC_OK);
+        response.setContentType("application/json; charset=utf-8");
+        PrintWriter printWriter = response.getWriter();
+        printWriter.write(retJson);
+    }
+
+    @Override
+    public void postHandle(HttpServletRequest request, HttpServletResponse response,
+                           Object handler, @Nullable ModelAndView modelAndView) throws Exception {
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
+                                Object handler, @Nullable Exception ex) throws Exception {
+    }
+}

+ 0 - 36
content/content-service/src/main/resources/mapper/exam/ExamUserMapper.xml

@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
-<mapper namespace="cn.reghao.tnb.content.app.exam.db.mapper.ExamUserMapper">
-    <insert id="save" useGeneratedKeys="true" keyProperty="id">
-        insert into exam_user
-        (`paper_id`,`user_id`,`role`)
-        values
-        (#{paperId},#{userId},#{role})
-    </insert>
-    <insert id="saveAll" useGeneratedKeys="true" keyProperty="id">
-        insert ignore into exam_user
-        (`paper_id`,`user_id`,`role`)
-        values
-        <foreach collection="list" item="item" index="index" separator=",">
-            (#{item.paperId},#{item.userId},#{item.role})
-        </foreach>
-    </insert>
-
-    <select id="findByPaperId" resultType="cn.reghao.tnb.content.app.exam.model.po.ExamUser">
-        select *
-        from exam_user
-        where paper_id=#{paperId}
-    </select>
-    <select id="findByUserId" resultType="cn.reghao.tnb.content.app.exam.model.po.ExamUser">
-        select *
-        from exam_user
-        where user_id=#{userId}
-        limit 1
-    </select>
-    <select id="findExamUser" resultType="cn.reghao.tnb.content.app.exam.model.po.ExamUser">
-        select *
-        from exam_user
-        where paper_id=#{paperId} and user_id=#{userId}
-    </select>
-</mapper>

+ 2 - 2
content/content-service/src/main/resources/mapper/exam/PaperMapper.xml

@@ -4,9 +4,9 @@
 <mapper namespace="cn.reghao.tnb.content.app.exam.db.mapper.PaperMapper">
     <insert id="save" useGeneratedKeys="true" keyProperty="id">
         insert into exam_paper
-        (`subject_id`,`name`,`mark_type`,`description`,`duration`,`total_score`,`pass_score`,`start_time`,`end_time`,`passcode`,`status`,`has_subjective`,`create_at`,`create_by`)
+        (`subject_id`,`name`,`mark_type`,`scope`,`duration`,`total_score`,`start_time`,`passcode`,`has_subjective`,`create_at`,`create_by`)
         values 
-        (#{subjectId},#{name},#{markType},#{description},#{duration},#{totalScore},#{passScore},#{endTime},#{startTime},#{passcode},#{status},#{hasSubjective},#{createAt},#{createBy})
+        (#{subjectId},#{name},#{markType},#{scope},#{duration},#{totalScore},#{startTime},#{passcode},#{hasSubjective},#{createAt},#{createBy})
     </insert>
 
     <delete id="deleteById">