Bladeren bron

feat(server): 考试流程

Go 6 jaren geleden
bovenliggende
commit
a991050471
75 gewijzigde bestanden met toevoegingen van 2210 en 319 verwijderingen
  1. 7 1
      front/project/Constant.js
  2. 13 9
      front/project/admin/routes/subject/question/page.js
  3. 4 4
      front/project/admin/routes/subject/sentenceQuestion/page.js
  4. 28 1
      server/data/src/main/java/com/qxgmat/data/constants/enums/module/QuestionModule.java
  5. 7 0
      server/data/src/main/java/com/qxgmat/data/dao/TextbookQuestionMapper.java
  6. 0 7
      server/data/src/main/java/com/qxgmat/data/dao/UserNoteMapper.java
  7. 7 0
      server/data/src/main/java/com/qxgmat/data/dao/UserNoteQuestionMapper.java
  8. 35 0
      server/data/src/main/java/com/qxgmat/data/dao/entity/Question.java
  9. 86 16
      server/data/src/main/java/com/qxgmat/data/dao/entity/SentenceQuestion.java
  10. 308 0
      server/data/src/main/java/com/qxgmat/data/dao/entity/TextbookQuestion.java
  11. 4 4
      server/data/src/main/java/com/qxgmat/data/dao/entity/User.java
  12. 35 0
      server/data/src/main/java/com/qxgmat/data/dao/entity/UserCollectQuestion.java
  13. 42 7
      server/data/src/main/java/com/qxgmat/data/dao/entity/UserNote.java
  14. 35 0
      server/data/src/main/java/com/qxgmat/data/dao/entity/UserPaper.java
  15. 35 0
      server/data/src/main/java/com/qxgmat/data/dao/entity/UserReport.java
  16. 4 3
      server/data/src/main/java/com/qxgmat/data/dao/mapping/QuestionMapper.xml
  17. 5 2
      server/data/src/main/java/com/qxgmat/data/dao/mapping/SentenceQuestionMapper.xml
  18. 23 0
      server/data/src/main/java/com/qxgmat/data/dao/mapping/TextbookQuestionMapper.xml
  19. 2 1
      server/data/src/main/java/com/qxgmat/data/dao/mapping/UserCollectQuestionMapper.xml
  20. 1 1
      server/data/src/main/java/com/qxgmat/data/dao/mapping/UserMapper.xml
  21. 5 4
      server/data/src/main/java/com/qxgmat/data/dao/mapping/UserNoteMapper.xml
  22. 2 1
      server/data/src/main/java/com/qxgmat/data/dao/mapping/UserPaperMapper.xml
  23. 3 2
      server/data/src/main/java/com/qxgmat/data/dao/mapping/UserReportMapper.xml
  24. 0 2
      server/data/src/main/java/com/qxgmat/data/relation/UserNoteRelationMapper.java
  25. 126 0
      server/data/src/main/java/com/qxgmat/data/relation/mapping/UserNoteRelationMapper.xml
  26. 1 0
      server/data/src/main/resources/mybatis-generator.xml
  27. 36 3
      server/gateway-api/src/main/java/com/qxgmat/controller/api/AuthController.java
  28. 59 26
      server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java
  29. 54 25
      server/gateway-api/src/main/java/com/qxgmat/controller/api/QuestionController.java
  30. 43 33
      server/gateway-api/src/main/java/com/qxgmat/controller/api/SentenceController.java
  31. 10 0
      server/gateway-api/src/main/java/com/qxgmat/dto/admin/request/QuestionDto.java
  32. 10 0
      server/gateway-api/src/main/java/com/qxgmat/dto/admin/response/QuestionDetailDto.java
  33. 49 0
      server/gateway-api/src/main/java/com/qxgmat/dto/extend/QuestionBaseExtendDto.java
  34. 42 0
      server/gateway-api/src/main/java/com/qxgmat/dto/extend/QuestionDetailExtendDto.java
  35. 37 0
      server/gateway-api/src/main/java/com/qxgmat/dto/extend/SentenceQuestionExtendDto.java
  36. 17 0
      server/gateway-api/src/main/java/com/qxgmat/dto/extend/UserNoteExtendDto.java
  37. 24 0
      server/gateway-api/src/main/java/com/qxgmat/dto/request/MessageReadDto.java
  38. 1 1
      server/gateway-api/src/main/java/com/qxgmat/dto/request/QuestionFinishDto.java
  39. 5 5
      server/gateway-api/src/main/java/com/qxgmat/dto/request/PreviewStartDto.java
  40. 0 15
      server/gateway-api/src/main/java/com/qxgmat/dto/request/QuestionNextDto.java
  41. 13 0
      server/gateway-api/src/main/java/com/qxgmat/dto/request/ReportFinishDto.java
  42. 15 0
      server/gateway-api/src/main/java/com/qxgmat/dto/request/ReportNextDto.java
  43. 8 0
      server/gateway-api/src/main/java/com/qxgmat/dto/request/SentenceStartDto.java
  44. 13 0
      server/gateway-api/src/main/java/com/qxgmat/dto/request/UserCollectBindDto.java
  45. 10 0
      server/gateway-api/src/main/java/com/qxgmat/dto/request/UserCollectDto.java
  46. 24 0
      server/gateway-api/src/main/java/com/qxgmat/dto/request/UserErrorBindDto.java
  47. 11 2
      server/gateway-api/src/main/java/com/qxgmat/dto/request/UserNoteDto.java
  48. 12 12
      server/gateway-api/src/main/java/com/qxgmat/dto/request/UserPrepareDto.java
  49. 72 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/MyDto.java
  50. 17 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserNoteDetailDto.java
  51. 0 61
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserNoteDto.java
  52. 12 13
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserPrepareDetailDto.java
  53. 74 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserQuestionBaseDto.java
  54. 79 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserQuestionDetailDto.java
  55. 32 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserQuestionListDto.java
  56. 8 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserReportDto.java
  57. 70 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserSentenceQuestionBaseDto.java
  58. 99 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserSentenceQuestionDetailDto.java
  59. 4 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserStudyDetailDto.java
  60. 8 0
      server/gateway-api/src/main/java/com/qxgmat/service/ExercisePaperService.java
  61. 7 0
      server/gateway-api/src/main/java/com/qxgmat/service/SentencePaperService.java
  62. 14 2
      server/gateway-api/src/main/java/com/qxgmat/service/UserCollectQuestionService.java
  63. 25 24
      server/gateway-api/src/main/java/com/qxgmat/service/UserNoteService.java
  64. 67 22
      server/gateway-api/src/main/java/com/qxgmat/service/UserPaperService.java
  65. 9 1
      server/gateway-api/src/main/java/com/qxgmat/service/inline/UserQuestionService.java
  66. 1 0
      server/gateway-api/src/main/java/com/qxgmat/service/UsersService.java
  67. 12 0
      server/gateway-api/src/main/java/com/qxgmat/service/annotation/InitPaper.java
  68. 13 0
      server/gateway-api/src/main/java/com/qxgmat/service/annotation/InitReport.java
  69. 217 0
      server/gateway-api/src/main/java/com/qxgmat/service/extend/QuestionFlowService.java
  70. 6 6
      server/gateway-api/src/main/java/com/qxgmat/service/extend/TradeService.java
  71. 6 0
      server/gateway-api/src/main/java/com/qxgmat/service/inline/QuestionNoService.java
  72. 6 0
      server/gateway-api/src/main/java/com/qxgmat/service/inline/SentenceQuestionService.java
  73. 16 1
      server/gateway-api/src/main/java/com/qxgmat/service/inline/UserMessageService.java
  74. 0 2
      server/gateway-api/src/main/java/com/qxgmat/service/inline/UserPayService.java
  75. 25 0
      server/gateway-api/src/main/java/com/qxgmat/service/inline/UserReportService.java

+ 7 - 1
front/project/Constant.js

@@ -35,7 +35,6 @@ export const SentenceOption = [{ label: '平行', value: 'parallel' }, { label:
 //   }],
 //   questions: [{
 //     description: '', // type!=inline
-//     answer: [[true,false],[false,true]],
 //     select: [],
 //     direction: '', // type=double
 //   }],
@@ -48,6 +47,13 @@ export const SentenceOption = [{ label: '平行', value: 'parallel' }, { label:
 //   type: '',
 //   number: '',
 //   typeset: 'one|two',
+// };
+
+// const answer = {
+//   questions: [{
+//     single: [true, false],
+//     double: [[true, false], [false, true]],
+//   }],
 
 //   // sentence
 //   subject: [],

+ 13 - 9
front/project/admin/routes/subject/question/page.js

@@ -213,16 +213,16 @@ export default class extends Page {
 
   changeQuestion(index, k, value) {
     const { form } = this.props;
-    let answer = form.getFieldValue(`content.questions[${index}].answer`) || [];
+    let answer = form.getFieldValue(`content.answer[${index}].single`) || [];
     answer = answer.map(() => !value);
     answer[k] = !!value;
-    form.setFieldsValue({ [`content.questions[${index}].answer`]: answer });
+    form.setFieldsValue({ [`content.answer[${index}].single`]: answer });
   }
 
   changeDouble(index, k, o, value) {
     const { form } = this.props;
     const direction = form.getFieldValue(`content.questions[${index}].direction`);
-    let answer = form.getFieldValue(`content.questions[${index}].answer`) || [];
+    let answer = form.getFieldValue(`content.answer[${index}].double`) || [];
     switch (direction) {
       case 'landscape':
         answer[k] = answer[k].map(() => !value);
@@ -238,12 +238,12 @@ export default class extends Page {
         break;
       default:
     }
-    form.setFieldsValue({ [`content.questions[${index}].answer`]: answer });
+    form.setFieldsValue({ [`content.answer[${index}].double`]: answer });
   }
 
   submit() {
     const { form } = this.props;
-    const fields = ['type', 'place', 'difficult', 'content', 'stem', 'keyword', 'questionNoIds', 'officialContent', 'qxContent', 'associationContent'];
+    const fields = ['type', 'place', 'difficult', 'content', 'answer', 'stem', 'keyword', 'questionNoIds', 'officialContent', 'qxContent', 'associationContent'];
     form.validateFields(fields, (err) => {
       if (!err) {
         const data = form.getFieldsValue(fields);
@@ -251,10 +251,14 @@ export default class extends Page {
         data.associationContent = this.state.associationContent.map(row => row.id);
         data.description = data.stem.replace(/<[^>]+>/g, '');
         data.content.questions = data.content.questions.map(row => {
-          row.answer = row.answer.filter(r => r);
           row.select = row.select.filter(r => r);
           return row;
         });
+        data.answer.questions = data.answer.questions.map(row => {
+          if (row.single) row.single = row.single.filter(r => r);
+          if (row.double) row.double = row.double.filter(r => r);
+          return row;
+        });
         if (data.id) {
           handler = Question.add(data);
         } else {
@@ -598,7 +602,7 @@ export default class extends Page {
           <List.Item actions={[<Icon type='bars' className='icon' />]}>
             <Row key={k} style={{ width: '100%' }}>
               <Col span={1}>
-                {getFieldDecorator(`content.questions[${index}].answer[${k}]`, {
+                {getFieldDecorator(`answer.questions[${index}].single[${k}]`, {
                   valuePropName: 'checked',
                 })(
                   <Checkbox onChange={(value) => {
@@ -676,7 +680,7 @@ export default class extends Page {
           <List.Item actions={[<Icon type='bars' className='icon' />]}>
             <Row key={k} style={{ width: '100%' }}>
               <Col span={4}>
-                {getFieldDecorator(`content.questions[${index}].answer[${k}][0]`, {
+                {getFieldDecorator(`answer.questions[${index}].double[${k}][0]`, {
                   valuePropName: 'checked',
                 })(
                   <Checkbox onChange={(value) => {
@@ -685,7 +689,7 @@ export default class extends Page {
                 )}
               </Col>
               <Col span={4} offset={1}>
-                {getFieldDecorator(`content.questions[${index}].answer[${k}][1]`, {
+                {getFieldDecorator(`answer.questions[${index}].double[${k}][1]`, {
                   valuePropName: 'checked',
                 })(
                   <Checkbox onChange={(value) => {

+ 4 - 4
front/project/admin/routes/subject/sentenceQuestion/page.js

@@ -137,7 +137,7 @@ export default class extends Page {
           <td>主语</td>
           <td>
             <Form.Item>
-              {getFieldDecorator('question.content.subject')(
+              {getFieldDecorator('question.answer.subject')(
                 <Select mode='tags' maxTagCount={200} notFoundContent={null} tokenSeparators={[',', ',']} />,
               )}
             </Form.Item>
@@ -146,7 +146,7 @@ export default class extends Page {
         <tr>
           <td>谓语</td>
           <td><Form.Item>
-            {getFieldDecorator('question.content.predicate')(
+            {getFieldDecorator('question.answer.predicate')(
               <Select mode='tags' maxTagCount={200} notFoundContent={null} tokenSeparators={[',', ',']} />,
             )}
           </Form.Item></td>
@@ -154,7 +154,7 @@ export default class extends Page {
         <tr>
           <td>宾语</td>
           <td><Form.Item>
-            {getFieldDecorator('question.content.object')(
+            {getFieldDecorator('question.answer.object')(
               <Select mode='tags' maxTagCount={200} notFoundContent={null} tokenSeparators={[',', ',']} />,
             )}
           </Form.Item></td>
@@ -169,7 +169,7 @@ export default class extends Page {
       <h1>选项信息(长难句)</h1>
       <Form>
         <Form.Item>
-          {getFieldDecorator('question.content.options')(
+          {getFieldDecorator('question.answer.options')(
             <Checkbox.Group options={SentenceOption} />,
           )}
         </Form.Item>

+ 28 - 1
server/data/src/main/java/com/qxgmat/data/constants/enums/module/QuestionModule.java

@@ -1,7 +1,12 @@
 package com.qxgmat.data.constants.enums.module;
 
+import com.qxgmat.data.dao.entity.Question;
+
 public enum QuestionModule {
-    EXERCISE("exercise"), EXAMINATION("examination"), SENTENCE("sentence"), TEXTBOOK("textbook");
+    BASE("base"), // 练习、模考、错题、收藏、预习作业
+    TEXTBOOK("textbook"), // 机经
+    SENTENCE("sentence"), // 长难句
+    ;
     public String key;
     private QuestionModule(String key){
         this.key = key;
@@ -11,4 +16,26 @@ public enum QuestionModule {
         if (name == null) return null;
         return QuestionModule.valueOf(name.toUpperCase());
     }
+
+    /**
+     * 根据paper类型判断组卷题目类型
+     * @param module
+     * @return
+     */
+    public static QuestionModule WithPaper(PaperModule module){
+        switch(module){
+            case SENTENCE:
+                return SENTENCE;
+            case TEXTBOOK:
+                return TEXTBOOK;
+            case ERROR:
+            case COLLECT:
+            case EXERCISE:
+            case EXAMINATION:
+            case HOMEWORK_PREVIEW:
+                return BASE;
+            default:
+                return null;
+        }
+    }
 }

+ 7 - 0
server/data/src/main/java/com/qxgmat/data/dao/TextbookQuestionMapper.java

@@ -0,0 +1,7 @@
+package com.qxgmat.data.dao;
+
+import com.nuliji.tools.mybatis.Mapper;
+import com.qxgmat.data.dao.entity.TextbookQuestion;
+
+public interface TextbookQuestionMapper extends Mapper<TextbookQuestion> {
+}

+ 0 - 7
server/data/src/main/java/com/qxgmat/data/dao/UserNoteMapper.java

@@ -1,7 +0,0 @@
-package com.qxgmat.data.dao;
-
-import com.nuliji.tools.mybatis.Mapper;
-import com.qxgmat.data.dao.entity.UserNote;
-
-public interface UserNoteMapper extends Mapper<UserNote> {
-}

+ 7 - 0
server/data/src/main/java/com/qxgmat/data/dao/UserNoteQuestionMapper.java

@@ -0,0 +1,7 @@
+package com.qxgmat.data.dao;
+
+import com.nuliji.tools.mybatis.Mapper;
+import com.qxgmat.data.dao.entity.UserNoteQuestion;
+
+public interface UserNoteQuestionMapper extends Mapper<UserNoteQuestion> {
+}

+ 35 - 0
server/data/src/main/java/com/qxgmat/data/dao/entity/Question.java

@@ -48,6 +48,12 @@ public class Question implements Serializable {
     @Column(name = "`content`")
     private JSONObject content;
 
+    /**
+     * 答案:json
+     */
+    @Column(name = "`answer`")
+    private JSONObject answer;
+
     @Column(name = "`question_time`")
     private Date questionTime;
 
@@ -227,6 +233,24 @@ public class Question implements Serializable {
     }
 
     /**
+     * 获取答案:json
+     *
+     * @return answer - 答案:json
+     */
+    public JSONObject getAnswer() {
+        return answer;
+    }
+
+    /**
+     * 设置答案:json
+     *
+     * @param answer 答案:json
+     */
+    public void setAnswer(JSONObject answer) {
+        this.answer = answer;
+    }
+
+    /**
      * @return question_time
      */
     public Date getQuestionTime() {
@@ -441,6 +465,7 @@ public class Question implements Serializable {
         sb.append(", difficult=").append(difficult);
         sb.append(", description=").append(description);
         sb.append(", content=").append(content);
+        sb.append(", answer=").append(answer);
         sb.append(", questionTime=").append(questionTime);
         sb.append(", qxTime=").append(qxTime);
         sb.append(", officialTime=").append(officialTime);
@@ -538,6 +563,16 @@ public class Question implements Serializable {
         }
 
         /**
+         * 设置答案:json
+         *
+         * @param answer 答案:json
+         */
+        public Builder answer(JSONObject answer) {
+            obj.setAnswer(answer);
+            return this;
+        }
+
+        /**
          * @param questionTime
          */
         public Builder questionTime(Date questionTime) {

+ 86 - 16
server/data/src/main/java/com/qxgmat/data/dao/entity/SentenceQuestion.java

@@ -41,10 +41,22 @@ public class SentenceQuestion implements Serializable {
     private Integer questionId;
 
     /**
-     * 长难句id
+     * 总作答时间
      */
-    @Column(name = "`sentence_id`")
-    private Integer sentenceId;
+    @Column(name = "`total_time`")
+    private Integer totalTime;
+
+    /**
+     * 总做题次数
+     */
+    @Column(name = "`total_number`")
+    private Integer totalNumber;
+
+    /**
+     * 总正确次数
+     */
+    @Column(name = "`total_correct`")
+    private Integer totalCorrect;
 
     /**
      * 中文语义
@@ -159,21 +171,57 @@ public class SentenceQuestion implements Serializable {
     }
 
     /**
-     * 获取长难句id
+     * 获取总作答时间
+     *
+     * @return total_time - 总作答时间
+     */
+    public Integer getTotalTime() {
+        return totalTime;
+    }
+
+    /**
+     * 设置总作答时间
+     *
+     * @param totalTime 总作答时间
+     */
+    public void setTotalTime(Integer totalTime) {
+        this.totalTime = totalTime;
+    }
+
+    /**
+     * 获取总做题次数
+     *
+     * @return total_number - 总做题次数
+     */
+    public Integer getTotalNumber() {
+        return totalNumber;
+    }
+
+    /**
+     * 设置总做题次数
+     *
+     * @param totalNumber 总做题次数
+     */
+    public void setTotalNumber(Integer totalNumber) {
+        this.totalNumber = totalNumber;
+    }
+
+    /**
+     * 获取总正确次数
      *
-     * @return sentence_id - 长难句id
+     * @return total_correct - 总正确次数
      */
-    public Integer getSentenceId() {
-        return sentenceId;
+    public Integer getTotalCorrect() {
+        return totalCorrect;
     }
 
     /**
-     * 设置长难句id
+     * 设置总正确次数
      *
-     * @param sentenceId 长难句id
+     * @param totalCorrect 总正确次数
      */
-    public void setSentenceId(Integer sentenceId) {
-        this.sentenceId = sentenceId;
+    public void setTotalCorrect(Integer totalCorrect) {
+        this.totalCorrect = totalCorrect;
     }
 
     /**
@@ -206,7 +254,9 @@ public class SentenceQuestion implements Serializable {
         sb.append(", paperId=").append(paperId);
         sb.append(", no=").append(no);
         sb.append(", questionId=").append(questionId);
-        sb.append(", sentenceId=").append(sentenceId);
+        sb.append(", totalTime=").append(totalTime);
+        sb.append(", totalNumber=").append(totalNumber);
+        sb.append(", totalCorrect=").append(totalCorrect);
         sb.append(", chinese=").append(chinese);
         sb.append("]");
         return sb.toString();
@@ -282,12 +332,32 @@ public class SentenceQuestion implements Serializable {
         }
 
         /**
-         * 设置长难句id
+         * 设置总作答时间
+         *
+         * @param totalTime 总作答时间
+         */
+        public Builder totalTime(Integer totalTime) {
+            obj.setTotalTime(totalTime);
+            return this;
+        }
+
+        /**
+         * 设置总做题次数
+         *
+         * @param totalNumber 总做题次数
+         */
+        public Builder totalNumber(Integer totalNumber) {
+            obj.setTotalNumber(totalNumber);
+            return this;
+        }
+
+        /**
+         * 设置总正确次数
          *
-         * @param sentenceId 长难句id
+         * @param totalCorrect 总正确次数
          */
-        public Builder sentenceId(Integer sentenceId) {
-            obj.setSentenceId(sentenceId);
+        public Builder totalCorrect(Integer totalCorrect) {
+            obj.setTotalCorrect(totalCorrect);
             return this;
         }
 

+ 308 - 0
server/data/src/main/java/com/qxgmat/data/dao/entity/TextbookQuestion.java

@@ -0,0 +1,308 @@
+package com.qxgmat.data.dao.entity;
+
+import java.io.Serializable;
+import javax.persistence.*;
+
+@Table(name = "textbook_question")
+public class TextbookQuestion implements Serializable {
+    @Id
+    @Column(name = "`id`")
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer id;
+
+    /**
+     * 题目编号:人工
+     */
+    @Column(name = "`no`")
+    private String no;
+
+    /**
+     * 机经版本:关联换库表
+     */
+    @Column(name = "`version`")
+    private String version;
+
+    /**
+     * 题目id
+     */
+    @Column(name = "`question_id`")
+    private Integer questionId;
+
+    /**
+     * 学科
+     */
+    @Column(name = "`category`")
+    private Integer category;
+
+    /**
+     * 总做题时间
+     */
+    @Column(name = "`total_time`")
+    private Integer totalTime;
+
+    /**
+     * 总做题次数
+     */
+    @Column(name = "`total_number`")
+    private Integer totalNumber;
+
+    /**
+     * 总正确次数
+     */
+    @Column(name = "`total_correct`")
+    private Integer totalCorrect;
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * @return id
+     */
+    public Integer getId() {
+        return id;
+    }
+
+    /**
+     * @param id
+     */
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    /**
+     * 获取题目编号:人工
+     *
+     * @return no - 题目编号:人工
+     */
+    public String getNo() {
+        return no;
+    }
+
+    /**
+     * 设置题目编号:人工
+     *
+     * @param no 题目编号:人工
+     */
+    public void setNo(String no) {
+        this.no = no;
+    }
+
+    /**
+     * 获取机经版本:关联换库表
+     *
+     * @return version - 机经版本:关联换库表
+     */
+    public String getVersion() {
+        return version;
+    }
+
+    /**
+     * 设置机经版本:关联换库表
+     *
+     * @param version 机经版本:关联换库表
+     */
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    /**
+     * 获取题目id
+     *
+     * @return question_id - 题目id
+     */
+    public Integer getQuestionId() {
+        return questionId;
+    }
+
+    /**
+     * 设置题目id
+     *
+     * @param questionId 题目id
+     */
+    public void setQuestionId(Integer questionId) {
+        this.questionId = questionId;
+    }
+
+    /**
+     * 获取学科
+     *
+     * @return category - 学科
+     */
+    public Integer getCategory() {
+        return category;
+    }
+
+    /**
+     * 设置学科
+     *
+     * @param category 学科
+     */
+    public void setCategory(Integer category) {
+        this.category = category;
+    }
+
+    /**
+     * 获取总做题时间
+     *
+     * @return total_time - 总做题时间
+     */
+    public Integer getTotalTime() {
+        return totalTime;
+    }
+
+    /**
+     * 设置总做题时间
+     *
+     * @param totalTime 总做题时间
+     */
+    public void setTotalTime(Integer totalTime) {
+        this.totalTime = totalTime;
+    }
+
+    /**
+     * 获取总做题次数
+     *
+     * @return total_number - 总做题次数
+     */
+    public Integer getTotalNumber() {
+        return totalNumber;
+    }
+
+    /**
+     * 设置总做题次数
+     *
+     * @param totalNumber 总做题次数
+     */
+    public void setTotalNumber(Integer totalNumber) {
+        this.totalNumber = totalNumber;
+    }
+
+    /**
+     * 获取总正确次数
+     *
+     * @return total_correct - 总正确次数
+     */
+    public Integer getTotalCorrect() {
+        return totalCorrect;
+    }
+
+    /**
+     * 设置总正确次数
+     *
+     * @param totalCorrect 总正确次数
+     */
+    public void setTotalCorrect(Integer totalCorrect) {
+        this.totalCorrect = totalCorrect;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", no=").append(no);
+        sb.append(", version=").append(version);
+        sb.append(", questionId=").append(questionId);
+        sb.append(", category=").append(category);
+        sb.append(", totalTime=").append(totalTime);
+        sb.append(", totalNumber=").append(totalNumber);
+        sb.append(", totalCorrect=").append(totalCorrect);
+        sb.append("]");
+        return sb.toString();
+    }
+
+    public static TextbookQuestion.Builder builder() {
+        return new TextbookQuestion.Builder();
+    }
+
+    public static class Builder {
+        private TextbookQuestion obj;
+
+        public Builder() {
+            this.obj = new TextbookQuestion();
+        }
+
+        /**
+         * @param id
+         */
+        public Builder id(Integer id) {
+            obj.setId(id);
+            return this;
+        }
+
+        /**
+         * 设置题目编号:人工
+         *
+         * @param no 题目编号:人工
+         */
+        public Builder no(String no) {
+            obj.setNo(no);
+            return this;
+        }
+
+        /**
+         * 设置机经版本:关联换库表
+         *
+         * @param version 机经版本:关联换库表
+         */
+        public Builder version(String version) {
+            obj.setVersion(version);
+            return this;
+        }
+
+        /**
+         * 设置题目id
+         *
+         * @param questionId 题目id
+         */
+        public Builder questionId(Integer questionId) {
+            obj.setQuestionId(questionId);
+            return this;
+        }
+
+        /**
+         * 设置学科
+         *
+         * @param category 学科
+         */
+        public Builder category(Integer category) {
+            obj.setCategory(category);
+            return this;
+        }
+
+        /**
+         * 设置总做题时间
+         *
+         * @param totalTime 总做题时间
+         */
+        public Builder totalTime(Integer totalTime) {
+            obj.setTotalTime(totalTime);
+            return this;
+        }
+
+        /**
+         * 设置总做题次数
+         *
+         * @param totalNumber 总做题次数
+         */
+        public Builder totalNumber(Integer totalNumber) {
+            obj.setTotalNumber(totalNumber);
+            return this;
+        }
+
+        /**
+         * 设置总正确次数
+         *
+         * @param totalCorrect 总正确次数
+         */
+        public Builder totalCorrect(Integer totalCorrect) {
+            obj.setTotalCorrect(totalCorrect);
+            return this;
+        }
+
+        public TextbookQuestion build() {
+            return this.obj;
+        }
+    }
+}

+ 4 - 4
server/data/src/main/java/com/qxgmat/data/dao/entity/User.java

@@ -115,7 +115,7 @@ public class User implements Serializable {
      * 备考:身份
      */
     @Column(name = "`prepare_status`")
-    private Integer prepareStatus;
+    private String prepareStatus;
 
     /**
      * 备考:目标分数
@@ -491,7 +491,7 @@ public class User implements Serializable {
      *
      * @return prepare_status - 备考:身份
      */
-    public Integer getPrepareStatus() {
+    public String getPrepareStatus() {
         return prepareStatus;
     }
 
@@ -500,7 +500,7 @@ public class User implements Serializable {
      *
      * @param prepareStatus 备考:身份
      */
-    public void setPrepareStatus(Integer prepareStatus) {
+    public void setPrepareStatus(String prepareStatus) {
         this.prepareStatus = prepareStatus;
     }
 
@@ -892,7 +892,7 @@ public class User implements Serializable {
          *
          * @param prepareStatus 备考:身份
          */
-        public Builder prepareStatus(Integer prepareStatus) {
+        public Builder prepareStatus(String prepareStatus) {
             obj.setPrepareStatus(prepareStatus);
             return this;
         }

+ 35 - 0
server/data/src/main/java/com/qxgmat/data/dao/entity/UserCollectQuestion.java

@@ -18,6 +18,12 @@ public class UserCollectQuestion implements Serializable {
     private Integer userId;
 
     /**
+     * 模块:exercise, examination, sentence
+     */
+    @Column(name = "`module`")
+    private String module;
+
+    /**
      * 题目id
      */
     @Column(name = "`question_id`")
@@ -67,6 +73,24 @@ public class UserCollectQuestion implements Serializable {
     }
 
     /**
+     * 获取模块:exercise, examination, sentence
+     *
+     * @return module - 模块:exercise, examination, sentence
+     */
+    public String getModule() {
+        return module;
+    }
+
+    /**
+     * 设置模块:exercise, examination, sentence
+     *
+     * @param module 模块:exercise, examination, sentence
+     */
+    public void setModule(String module) {
+        this.module = module;
+    }
+
+    /**
      * 获取题目id
      *
      * @return question_id - 题目id
@@ -124,6 +148,7 @@ public class UserCollectQuestion implements Serializable {
         sb.append("Hash = ").append(hashCode());
         sb.append(", id=").append(id);
         sb.append(", userId=").append(userId);
+        sb.append(", module=").append(module);
         sb.append(", questionId=").append(questionId);
         sb.append(", questionNoId=").append(questionNoId);
         sb.append(", createTime=").append(createTime);
@@ -161,6 +186,16 @@ public class UserCollectQuestion implements Serializable {
         }
 
         /**
+         * 设置模块:exercise, examination, sentence
+         *
+         * @param module 模块:exercise, examination, sentence
+         */
+        public Builder module(String module) {
+            obj.setModule(module);
+            return this;
+        }
+
+        /**
          * 设置题目id
          *
          * @param questionId 题目id

+ 42 - 7
server/data/src/main/java/com/qxgmat/data/dao/entity/UserNote.java

@@ -4,8 +4,8 @@ import java.io.Serializable;
 import java.util.Date;
 import javax.persistence.*;
 
-@Table(name = "user_note")
-public class UserNote implements Serializable {
+@Table(name = "user_note_question")
+public class UserNoteQuestion implements Serializable {
     @Id
     @Column(name = "`id`")
     @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -18,6 +18,12 @@ public class UserNote implements Serializable {
     private Integer userId;
 
     /**
+     * 模块:exercise, exaination, sentence
+     */
+    @Column(name = "`module`")
+    private String module;
+
+    /**
      * 题目id
      */
     @Column(name = "`question_id`")
@@ -76,6 +82,24 @@ public class UserNote implements Serializable {
     }
 
     /**
+     * 获取模块:exercise, exaination, sentence
+     *
+     * @return module - 模块:exercise, exaination, sentence
+     */
+    public String getModule() {
+        return module;
+    }
+
+    /**
+     * 设置模块:exercise, exaination, sentence
+     *
+     * @param module 模块:exercise, exaination, sentence
+     */
+    public void setModule(String module) {
+        this.module = module;
+    }
+
+    /**
      * 获取题目id
      *
      * @return question_id - 题目id
@@ -165,6 +189,7 @@ public class UserNote implements Serializable {
         sb.append("Hash = ").append(hashCode());
         sb.append(", id=").append(id);
         sb.append(", userId=").append(userId);
+        sb.append(", module=").append(module);
         sb.append(", questionId=").append(questionId);
         sb.append(", questionNoId=").append(questionNoId);
         sb.append(", createTime=").append(createTime);
@@ -174,15 +199,15 @@ public class UserNote implements Serializable {
         return sb.toString();
     }
 
-    public static UserNote.Builder builder() {
-        return new UserNote.Builder();
+    public static UserNoteQuestion.Builder builder() {
+        return new UserNoteQuestion.Builder();
     }
 
     public static class Builder {
-        private UserNote obj;
+        private UserNoteQuestion obj;
 
         public Builder() {
-            this.obj = new UserNote();
+            this.obj = new UserNoteQuestion();
         }
 
         /**
@@ -204,6 +229,16 @@ public class UserNote implements Serializable {
         }
 
         /**
+         * 设置模块:exercise, exaination, sentence
+         *
+         * @param module 模块:exercise, exaination, sentence
+         */
+        public Builder module(String module) {
+            obj.setModule(module);
+            return this;
+        }
+
+        /**
          * 设置题目id
          *
          * @param questionId 题目id
@@ -249,7 +284,7 @@ public class UserNote implements Serializable {
             return this;
         }
 
-        public UserNote build() {
+        public UserNoteQuestion build() {
             return this.obj;
         }
     }

+ 35 - 0
server/data/src/main/java/com/qxgmat/data/dao/entity/UserPaper.java

@@ -71,6 +71,12 @@ public class UserPaper implements Serializable {
     @Column(name = "`delete_time`")
     private Date deleteTime;
 
+    /**
+     * 重置状态:0未重置,1重置
+     */
+    @Column(name = "`is_reset`")
+    private Integer isReset;
+
     private static final long serialVersionUID = 1L;
 
     /**
@@ -267,6 +273,24 @@ public class UserPaper implements Serializable {
         this.deleteTime = deleteTime;
     }
 
+    /**
+     * 获取重置状态:0未重置,1重置
+     *
+     * @return is_reset - 重置状态:0未重置,1重置
+     */
+    public Integer getIsReset() {
+        return isReset;
+    }
+
+    /**
+     * 设置重置状态:0未重置,1重置
+     *
+     * @param isReset 重置状态:0未重置,1重置
+     */
+    public void setIsReset(Integer isReset) {
+        this.isReset = isReset;
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -284,6 +308,7 @@ public class UserPaper implements Serializable {
         sb.append(", userTime=").append(userTime);
         sb.append(", correctNumber=").append(correctNumber);
         sb.append(", deleteTime=").append(deleteTime);
+        sb.append(", isReset=").append(isReset);
         sb.append("]");
         return sb.toString();
     }
@@ -407,6 +432,16 @@ public class UserPaper implements Serializable {
             return this;
         }
 
+        /**
+         * 设置重置状态:0未重置,1重置
+         *
+         * @param isReset 重置状态:0未重置,1重置
+         */
+        public Builder isReset(Integer isReset) {
+            obj.setIsReset(isReset);
+            return this;
+        }
+
         public UserPaper build() {
             return this.obj;
         }

+ 35 - 0
server/data/src/main/java/com/qxgmat/data/dao/entity/UserReport.java

@@ -76,6 +76,12 @@ public class UserReport implements Serializable {
     private Date finishTime;
 
     /**
+     * 开考设置
+     */
+    @Column(name = "`setting`")
+    private JSONObject setting;
+
+    /**
      * 详细信息: json
      */
     @Column(name = "`detail`")
@@ -295,6 +301,24 @@ public class UserReport implements Serializable {
     }
 
     /**
+     * 获取开考设置
+     *
+     * @return setting - 开考设置
+     */
+    public JSONObject getSetting() {
+        return setting;
+    }
+
+    /**
+     * 设置开考设置
+     *
+     * @param setting 开考设置
+     */
+    public void setSetting(JSONObject setting) {
+        this.setting = setting;
+    }
+
+    /**
      * 获取详细信息: json
      *
      * @return detail - 详细信息: json
@@ -344,6 +368,7 @@ public class UserReport implements Serializable {
         sb.append(", questionNoIds=").append(questionNoIds);
         sb.append(", correctNumber=").append(correctNumber);
         sb.append(", finishTime=").append(finishTime);
+        sb.append(", setting=").append(setting);
         sb.append(", detail=").append(detail);
         sb.append(", createTime=").append(createTime);
         sb.append("]");
@@ -478,6 +503,16 @@ public class UserReport implements Serializable {
         }
 
         /**
+         * 设置开考设置
+         *
+         * @param setting 开考设置
+         */
+        public Builder setting(JSONObject setting) {
+            obj.setSetting(setting);
+            return this;
+        }
+
+        /**
          * 设置详细信息: json
          *
          * @param detail 详细信息: json

+ 4 - 3
server/data/src/main/java/com/qxgmat/data/dao/mapping/QuestionMapper.xml

@@ -12,6 +12,7 @@
     <result column="difficult" jdbcType="VARCHAR" property="difficult" />
     <result column="description" jdbcType="VARCHAR" property="description" />
     <result column="content" jdbcType="VARCHAR" property="content" typeHandler="com.nuliji.tools.mybatis.handler.JsonObjectHandler" />
+    <result column="answer" jdbcType="VARCHAR" property="answer" typeHandler="com.nuliji.tools.mybatis.handler.JsonObjectHandler" />
     <result column="question_time" jdbcType="TIMESTAMP" property="questionTime" />
     <result column="qx_time" jdbcType="TIMESTAMP" property="qxTime" />
     <result column="official_time" jdbcType="TIMESTAMP" property="officialTime" />
@@ -35,9 +36,9 @@
     <!--
       WARNING - @mbg.generated
     -->
-    `id`, `keyword`, `type`, `place`, `difficult`, `description`, `content`, `question_time`, 
-    `qx_time`, `official_time`, `association_time`, `association_content`, `total_time`, 
-    `total_number`, `total_correct`, `create_time`, `update_time`
+    `id`, `keyword`, `type`, `place`, `difficult`, `description`, `content`, `answer`, 
+    `question_time`, `qx_time`, `official_time`, `association_time`, `association_content`, 
+    `total_time`, `total_number`, `total_correct`, `create_time`, `update_time`
   </sql>
   <sql id="Blob_Column_List">
     <!--

+ 5 - 2
server/data/src/main/java/com/qxgmat/data/dao/mapping/SentenceQuestionMapper.xml

@@ -11,7 +11,9 @@
     <result column="paper_id" jdbcType="INTEGER" property="paperId" />
     <result column="no" jdbcType="INTEGER" property="no" />
     <result column="question_id" jdbcType="INTEGER" property="questionId" />
-    <result column="sentence_id" jdbcType="INTEGER" property="sentenceId" />
+    <result column="total_time" jdbcType="INTEGER" property="totalTime" />
+    <result column="total_number" jdbcType="INTEGER" property="totalNumber" />
+    <result column="total_correct" jdbcType="INTEGER" property="totalCorrect" />
   </resultMap>
   <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.qxgmat.data.dao.entity.SentenceQuestion">
     <!--
@@ -23,7 +25,8 @@
     <!--
       WARNING - @mbg.generated
     -->
-    `id`, `title`, `is_trail`, `paper_id`, `no`, `question_id`, `sentence_id`
+    `id`, `title`, `is_trail`, `paper_id`, `no`, `question_id`, `total_time`, `total_number`, 
+    `total_correct`
   </sql>
   <sql id="Blob_Column_List">
     <!--

+ 23 - 0
server/data/src/main/java/com/qxgmat/data/dao/mapping/TextbookQuestionMapper.xml

@@ -0,0 +1,23 @@
+<?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="com.qxgmat.data.dao.TextbookQuestionMapper">
+  <resultMap id="BaseResultMap" type="com.qxgmat.data.dao.entity.TextbookQuestion">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    <id column="id" jdbcType="INTEGER" property="id" />
+    <result column="no" jdbcType="VARCHAR" property="no" />
+    <result column="version" jdbcType="VARCHAR" property="version" />
+    <result column="question_id" jdbcType="INTEGER" property="questionId" />
+    <result column="category" jdbcType="INTEGER" property="category" />
+    <result column="total_time" jdbcType="INTEGER" property="totalTime" />
+    <result column="total_number" jdbcType="INTEGER" property="totalNumber" />
+    <result column="total_correct" jdbcType="INTEGER" property="totalCorrect" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    `id`, `no`, `version`, `question_id`, `category`, `total_time`, `total_number`, `total_correct`
+  </sql>
+</mapper>

+ 2 - 1
server/data/src/main/java/com/qxgmat/data/dao/mapping/UserCollectQuestionMapper.xml

@@ -7,6 +7,7 @@
     -->
     <id column="id" jdbcType="INTEGER" property="id" />
     <result column="user_id" jdbcType="INTEGER" property="userId" />
+    <result column="module" jdbcType="VARCHAR" property="module" />
     <result column="question_id" jdbcType="INTEGER" property="questionId" />
     <result column="question_no_id" jdbcType="INTEGER" property="questionNoId" />
     <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
@@ -15,6 +16,6 @@
     <!--
       WARNING - @mbg.generated
     -->
-    `id`, `user_id`, `question_id`, `question_no_id`, `create_time`
+    `id`, `user_id`, `module`, `question_id`, `question_no_id`, `create_time`
   </sql>
 </mapper>

+ 1 - 1
server/data/src/main/java/com/qxgmat/data/dao/mapping/UserMapper.xml

@@ -23,7 +23,7 @@
     <result column="real_identity" jdbcType="VARCHAR" property="realIdentity" />
     <result column="real_photo" jdbcType="VARCHAR" property="realPhoto" />
     <result column="real_status" jdbcType="INTEGER" property="realStatus" />
-    <result column="prepare_status" jdbcType="INTEGER" property="prepareStatus" />
+    <result column="prepare_status" jdbcType="VARCHAR" property="prepareStatus" />
     <result column="prepare_goal" jdbcType="INTEGER" property="prepareGoal" />
     <result column="prepare_examination_time" jdbcType="INTEGER" property="prepareExaminationTime" />
     <result column="prepare_score_time" jdbcType="TIMESTAMP" property="prepareScoreTime" />

+ 5 - 4
server/data/src/main/java/com/qxgmat/data/dao/mapping/UserNoteMapper.xml

@@ -1,18 +1,19 @@
 <?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="com.qxgmat.data.dao.UserNoteMapper">
-  <resultMap id="BaseResultMap" type="com.qxgmat.data.dao.entity.UserNote">
+<mapper namespace="com.qxgmat.data.dao.UserNoteQuestionMapper">
+  <resultMap id="BaseResultMap" type="com.qxgmat.data.dao.entity.UserNoteQuestion">
     <!--
       WARNING - @mbg.generated
     -->
     <id column="id" jdbcType="INTEGER" property="id" />
     <result column="user_id" jdbcType="INTEGER" property="userId" />
+    <result column="module" jdbcType="VARCHAR" property="module" />
     <result column="question_id" jdbcType="INTEGER" property="questionId" />
     <result column="question_no_id" jdbcType="INTEGER" property="questionNoId" />
     <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
     <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
   </resultMap>
-  <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.qxgmat.data.dao.entity.UserNote">
+  <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.qxgmat.data.dao.entity.UserNoteQuestion">
     <!--
       WARNING - @mbg.generated
     -->
@@ -22,7 +23,7 @@
     <!--
       WARNING - @mbg.generated
     -->
-    `id`, `user_id`, `question_id`, `question_no_id`, `create_time`, `update_time`
+    `id`, `user_id`, `module`, `question_id`, `question_no_id`, `create_time`, `update_time`
   </sql>
   <sql id="Blob_Column_List">
     <!--

+ 2 - 1
server/data/src/main/java/com/qxgmat/data/dao/mapping/UserPaperMapper.xml

@@ -16,12 +16,13 @@
     <result column="user_time" jdbcType="INTEGER" property="userTime" />
     <result column="correct_number" jdbcType="INTEGER" property="correctNumber" />
     <result column="delete_time" jdbcType="TIMESTAMP" property="deleteTime" />
+    <result column="is_reset" jdbcType="INTEGER" property="isReset" />
   </resultMap>
   <sql id="Base_Column_List">
     <!--
       WARNING - @mbg.generated
     -->
     `id`, `user_id`, `title`, `module`, `module_id`, `question_no_ids`, `times`, `time`, 
-    `user_time`, `correct_number`, `delete_time`
+    `user_time`, `correct_number`, `delete_time`, `is_reset`
   </sql>
 </mapper>

+ 3 - 2
server/data/src/main/java/com/qxgmat/data/dao/mapping/UserReportMapper.xml

@@ -17,6 +17,7 @@
     <result column="question_no_ids" jdbcType="VARCHAR" property="questionNoIds" typeHandler="com.nuliji.tools.mybatis.handler.IntegerArrayWithJsonHandler" />
     <result column="correct_number" jdbcType="INTEGER" property="correctNumber" />
     <result column="finish_time" jdbcType="TIMESTAMP" property="finishTime" />
+    <result column="setting" jdbcType="VARCHAR" property="setting" typeHandler="com.nuliji.tools.mybatis.handler.JsonObjectHandler" />
     <result column="detail" jdbcType="VARCHAR" property="detail" typeHandler="com.nuliji.tools.mybatis.handler.JsonObjectHandler" />
     <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
   </resultMap>
@@ -25,7 +26,7 @@
       WARNING - @mbg.generated
     -->
     `id`, `user_id`, `paper_id`, `module`, `module_id`, `total_number`, `total_time`, 
-    `user_number`, `user_time`, `question_no_ids`, `correct_number`, `finish_time`, `detail`, 
-    `create_time`
+    `user_number`, `user_time`, `question_no_ids`, `correct_number`, `finish_time`, `setting`, 
+    `detail`, `create_time`
   </sql>
 </mapper>

+ 0 - 2
server/data/src/main/java/com/qxgmat/data/relation/UserNoteRelationMapper.java

@@ -1,7 +1,5 @@
 package com.qxgmat.data.relation;
 
-import com.qxgmat.data.dao.entity.UserCollectQuestion;
-import com.qxgmat.data.dao.entity.UserNote;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;

+ 126 - 0
server/data/src/main/java/com/qxgmat/data/relation/mapping/UserNoteRelationMapper.xml

@@ -0,0 +1,126 @@
+<?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="com.qxgmat.data.relation.UserNoteRelationMapper">
+  <resultMap id="IdMap" type="com.qxgmat.data.dao.entity.UserNote">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    <id column="id" jdbcType="INTEGER" property="id" />
+  </resultMap>
+  <sql id="Id_Column_List">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    up.`id`
+  </sql>
+
+  <!--
+    用户预习作业列表: 后台
+    https://blog.csdn.net/t_1007/article/details/52369261
+  -->
+  <select id="listHomeworkPreviewAdmin" resultMap="IdMap">
+    select
+    <include refid="Id_Column_List" />
+    from `user_paper` up
+    left join `homework_preview` hp on hp.`id` = up.`module_id`
+      and up.`module` = "homework_preview"
+      <if test="previewId != null">
+        and hp.`id` = #{previewId,jdbcType=VARCHAR}
+      </if>
+      <if test="category != null">
+        and hp.`category` = #{category,jdbcType=VARCHAR}
+      </if>
+    where
+    hp.`id` != null
+    <if test="userId != null">
+      and up.`user_id` = #{userId,jdbcType=VARCHAR}
+    </if>
+    <if test="startTime != null">
+      and up.`createTime` &gt; #{startTime,jdbcType=VARCHAR}
+    </if>
+    <if test="endTime != null">
+      and up.`createTime` &lt; #{endTime,jdbcType=VARCHAR}
+    </if>
+  </select>
+
+  <!--
+    用户预习作业列表: 用户端
+  -->
+  <select id="listHomeworkPreview" resultMap="IdMap">
+    select
+    <include refid="Id_Column_List" />
+    from `user_paper` up
+    left join `homework_preview` hp on hp.`id` = up.`module_id`
+      and up.`module` = "homework_preview"
+      <if test="category != null">
+        and hp.`category` = #{category,jdbcType=VARCHAR}
+      </if>
+      <if test="endTime != null">
+        and hp.`endTime` &lt; #{endTime,jdbcType=VARCHAR}
+      </if>
+    where
+    hp.`id` != null
+    <if test="userId != null">
+      and up.`user_id` = #{userId,jdbcType=VARCHAR}
+    </if>
+    <if test="finish != null">
+      <if test="finish == true">
+      and up.`number` > 1
+      </if>
+      <if test="finish == false">
+        and up.`number` = 0
+      </if>>
+    </if>
+  </select>
+
+  <!--
+    用户预习作业Top列表: 用户端
+  -->
+  <select id="listHomeworkPreviewGroupTop" resultMap="IdMap">
+    select
+    <include refid="Id_Column_List" />
+    from `user_paper` up
+    where
+    hp.`id` != null
+    and up.`module` = "homework_preview"
+    <if test="userId != null">
+      and up.`user_id` = #{userId,jdbcType=VARCHAR}
+    </if>
+    and ( select count(up1.id)
+        from `user_paper` up1
+        where
+        up.`module_id` = up1.`module_id`
+        and up.`module` = "homework_preview"
+        and up1.create_time &gt; up.create_time) &lt; ${top}
+  </select>
+
+  <!--
+    用户练习-练习册列表: 用户端
+  -->
+  <select id="listExercisePaper" resultMap="IdMap">
+    select
+    <include refid="Id_Column_List" />
+    from `user_paper` up
+    left join `exercise_paper` hp on hp.`id` = up.`module_id` and ep.`status` = 1
+    and up.`module` = "homework_preview"
+    <if test="category != null">
+      and hp.`category` = #{category,jdbcType=VARCHAR}
+    </if>
+    <if test="endTime != null">
+      and hp.`endTime` &lt; #{endTime,jdbcType=VARCHAR}
+    </if>
+    where
+    hp.`id` != null
+    <if test="userId != null">
+      and up.`user_id` = #{userId,jdbcType=VARCHAR}
+    </if>
+    <if test="finish != null">
+      <if test="finish == true">
+        and up.`number` > 1
+      </if>
+      <if test="finish == false">
+        and up.`number` = 0
+      </if>>
+    </if>
+  </select>
+</mapper>

+ 1 - 0
server/data/src/main/resources/mybatis-generator.xml

@@ -144,6 +144,7 @@
             <columnOverride column="detail" javaType="com.alibaba.fastjson.JSONObject" jdbcType="VARCHAR" typeHandler="com.nuliji.tools.mybatis.handler.JsonObjectHandler"/>
             <columnOverride column="question_no_ids" javaType="Integer[]" jdbcType="VARCHAR" typeHandler="com.nuliji.tools.mybatis.handler.IntegerArrayWithJsonHandler"/>
             <columnOverride column="detail" javaType="com.alibaba.fastjson.JSONObject" jdbcType="VARCHAR" typeHandler="com.nuliji.tools.mybatis.handler.JsonObjectHandler"/>
+            <columnOverride column="setting" javaType="com.alibaba.fastjson.JSONObject" jdbcType="VARCHAR" typeHandler="com.nuliji.tools.mybatis.handler.JsonObjectHandler"/>
         </table>
         <table schema="qianxing" tableName="user_question" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false" delimitAllColumns="true">
             <generatedKey column="id" sqlStatement="Mysql" identity="true"/>

+ 36 - 3
server/gateway-api/src/main/java/com/qxgmat/controller/api/AuthController.java

@@ -60,13 +60,31 @@ public class AuthController {
                 throw new AuthException("未登录");
             }
         }else{
-            user = usersService.getUserByToken(token);
+            // 默认测试token
+            if (token.equals("1234567890")){
+                user = usersService.get(1);
+            }else{
+                user = usersService.getUserByToken(token);
+            }
             // 用该token登录
             shiroHelp.getSession().login(shiroHelp.user(user.getMobile(), ""));
         }
 
         User entity = usersService.get(user.getId());
-        return ResponseHelp.success(Transform.convert(entity, MyDto.class));
+        MyDto dto = Transform.convert(entity, MyDto.class);
+        if (!entity.getMobile().isEmpty()){
+            dto.setMobile(true);
+        }
+        if (!entity.getWechatUnionid().isEmpty()){
+            dto.setWechat(true);
+        }
+        if (entity.getRealStatus() > 0){
+            dto.setReal(true);
+        }
+        if(!entity.getPrepareStatus().isEmpty()){
+            dto.setPrepare(true);
+        }
+        return ResponseHelp.success(dto);
     }
 
     @RequestMapping(value = "/login", method = RequestMethod.POST)
@@ -81,7 +99,22 @@ public class AuthController {
             // 忽略已注册信息
         }
         shiroHelp.getSession().login(shiroHelp.user(userLoginDto.getMobile(), ""));
-        return ResponseHelp.success(Transform.convert(shiroHelp.getLoginUser(), MyDto.class));
+
+        User entity = shiroHelp.getLoginUser();
+        MyDto dto = Transform.convert(entity, MyDto.class);
+        if (!entity.getMobile().isEmpty()){
+            dto.setMobile(true);
+        }
+        if (!entity.getWechatUnionid().isEmpty()){
+            dto.setWechat(true);
+        }
+        if (entity.getRealStatus() > 0){
+            dto.setReal(true);
+        }
+        if(!entity.getPrepareStatus().isEmpty()){
+            dto.setPrepare(true);
+        }
+        return ResponseHelp.success(dto);
     }
 
 

+ 59 - 26
server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java

@@ -12,18 +12,13 @@ import com.qxgmat.data.constants.enums.module.QuestionModule;
 import com.qxgmat.data.constants.enums.status.DirectionStatus;
 import com.qxgmat.data.dao.entity.*;
 import com.qxgmat.data.relation.entity.UserCollectQuestionRelation;
-import com.qxgmat.data.relation.entity.UserHomeworkPreviewRelation;
 import com.qxgmat.data.relation.entity.UserNoteRelation;
-import com.qxgmat.dto.extend.UserHomeworkPreviewExtendDto;
 import com.qxgmat.dto.extend.UserReportExtendDto;
 import com.qxgmat.dto.request.*;
 import com.qxgmat.dto.request.UserNoteDto;
 import com.qxgmat.dto.response.*;
 import com.qxgmat.help.ShiroHelp;
-import com.qxgmat.service.UserCollectQuestionService;
-import com.qxgmat.service.UserNoteService;
-import com.qxgmat.service.UserPaperService;
-import com.qxgmat.service.UsersService;
+import com.qxgmat.service.*;
 import com.qxgmat.service.inline.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -82,7 +77,7 @@ public class MyController {
     private UserCollectQuestionService userCollectQuestionService;
 
     @Autowired
-    private UserNoteService userNoteService;
+    private UserNoteQuestionService userNoteQuestionService;
 
     @Autowired
     private UserQuestionService userQuestionService;
@@ -129,7 +124,8 @@ public class MyController {
         User user = (User) shiroHelp.getLoginUser();
         UserRealDto dto = new UserRealDto();
 
-        // todo 随机文件名
+        // todo 第三方验证
+
         String file = UUID.randomUUID().toString();
         try {
             File dest = new File(localPath + File.separator+file);
@@ -165,9 +161,14 @@ public class MyController {
 
     @RequestMapping(value = "/message/read", method = RequestMethod.PUT)
     @ApiOperation(value = "读取消息", notes = "读取用户消息/全部", httpMethod = "PUT")
-    public Response<Boolean> readMessage()  {
+    public Response<Boolean> readMessage(@RequestBody @Validated MessageReadDto dto)  {
         User user = (User) shiroHelp.getLoginUser();
-        userMessageService.clear(user.getId());
+
+        if (dto.getAll()){
+            userMessageService.clearAll(user.getId());
+        }else{
+            userMessageService.clear(user.getId(), dto.getId());
+        }
 
         return ResponseHelp.success(true);
     }
@@ -177,7 +178,8 @@ public class MyController {
     public Response<Boolean> editPrepare(@RequestBody @Validated UserPrepareDto dto)  {
         User entity = Transform.dtoToEntity(dto);
         User user = (User) shiroHelp.getLoginUser();
-        userMessageService.clear(user.getId());
+        entity.setId(user.getId());
+        usersService.edit(entity);
 
         return ResponseHelp.success(true);
     }
@@ -188,6 +190,8 @@ public class MyController {
         User user = (User) shiroHelp.getLoginUser();
         User entity = usersService.get(user.getId());
         UserPrepareDetailDto dto = Transform.convert(entity, UserPrepareDetailDto.class);
+
+        // todo 获取备考统计
         Setting setting = settingService.getByKey(SettingKey.PREPARE_INFO);
         JSONObject value = setting.getValue();
         return ResponseHelp.success(dto);
@@ -195,7 +199,7 @@ public class MyController {
 
     @RequestMapping(value = "/study", method = RequestMethod.GET)
     @ApiOperation(value = "获取学习记录", notes = "获取选择那天的做题信息", httpMethod = "GET")
-    public Response<UserPrepareDetailDto> studyTime(
+    public Response<UserStudyDetailDto> studyTime(
             @RequestParam(required = false) String date
     )  {
         User user = (User) shiroHelp.getLoginUser();
@@ -204,10 +208,9 @@ public class MyController {
         } catch (ParseException e) {
             throw new ParameterException("日期格式错误");
         }
-        User entity = usersService.get(user.getId());
-        UserPrepareDetailDto dto = Transform.convert(entity, UserPrepareDetailDto.class);
-        Setting setting = settingService.getByKey(SettingKey.PREPARE_INFO);
-        JSONObject value = setting.getValue();
+        UserStudyDetailDto dto = new UserStudyDetailDto();
+
+        // todo 获取学习统计
         return ResponseHelp.success(dto);
     }
 
@@ -216,20 +219,28 @@ public class MyController {
     public Response<Boolean> addCollect(@RequestBody @Validated UserCollectDto dto)  {
         UserCollectQuestion entity = Transform.dtoToEntity(dto);
         User user = (User) shiroHelp.getLoginUser();
-        userCollectQuestionService.addQuestion(user.getId(), entity.getQuestionNoId());
+        userCollectQuestionService.addQuestion(user.getId(), QuestionModule.ValueOf(entity.getModule()), entity.getQuestionNoId());
 
         return ResponseHelp.success(true);
     }
 
     @RequestMapping(value = "/collect", method = RequestMethod.DELETE)
     @ApiOperation(value = "移除收藏", notes = "移除收藏", httpMethod = "DELETE")
-    public Response<Boolean> deleteCollect(int id)  {
+    public Response<Boolean> deleteCollect(String module, int id)  {
         User user = (User) shiroHelp.getLoginUser();
-        Boolean result = userCollectQuestionService.deleteQuestion(user.getId(), id);
+        Boolean result = userCollectQuestionService.deleteQuestion(user.getId(), QuestionModule.ValueOf(module), id);
 
         return ResponseHelp.success(result);
     }
 
+    @RequestMapping(value = "/collect/bind", method = RequestMethod.POST)
+    @ApiOperation(value = "收藏组卷", notes = "收藏组卷", httpMethod = "POST")
+    public Response<Boolean> bindCollect(@RequestBody @Validated UserCollectBindDto dto)  {
+        User user = (User) shiroHelp.getLoginUser();
+
+        return ResponseHelp.success(true);
+    }
+
     @RequestMapping(value = "/collect/question", method = RequestMethod.GET)
     @ApiOperation(value = "获取收藏题目列表", notes = "获取收藏题目列表", httpMethod = "GET")
     public Response<PageMessage<UserCollectQuestionDto>> listCollect(
@@ -247,7 +258,7 @@ public class MyController {
 
         List<UserCollectQuestionDto> pr = Transform.convert(p, UserCollectQuestionDto.class);
 
-        // 绑定做题数据
+        // todo 绑定做题数据
 
 
         return ResponseHelp.success(pr, page, size, p.getTotal());
@@ -263,26 +274,43 @@ public class MyController {
     )  {
         User user = (User) shiroHelp.getLoginUser();
         PageResult<UserQuestion> p = userQuestionService.listError(page, size, user.getId());
-
         List<UserQuestionListDto> pr = Transform.convert(p, UserQuestionListDto.class);
 
+        // todo 绑定数据
+
         return ResponseHelp.success(pr, page, size, p.getTotal());
     }
 
+    @RequestMapping(value = "/error/bind", method = RequestMethod.POST)
+    @ApiOperation(value = "错题组卷", notes = "错题组卷", httpMethod = "POST")
+    public Response<Boolean> bindError(@RequestBody @Validated UserErrorBindDto dto)  {
+        User user = (User) shiroHelp.getLoginUser();
+
+        return ResponseHelp.success(true);
+    }
+
+    @RequestMapping(value = "/error/clear", method = RequestMethod.POST)
+    @ApiOperation(value = "错题移除", notes = "错题移除", httpMethod = "POST")
+    public Response<Boolean> clearError(@RequestBody @Validated UserCollectBindDto dto)  {
+        User user = (User) shiroHelp.getLoginUser();
+
+        return ResponseHelp.success(true);
+    }
+
     @RequestMapping(value = "/note", method = RequestMethod.PUT)
     @ApiOperation(value = "更新笔记", notes = "更新笔记", httpMethod = "PUT")
     public Response<Boolean> updateNote(@RequestBody @Validated UserNoteDto dto)  {
-        UserNote entity = Transform.dtoToEntity(dto);
+        UserNoteQuestion entity = Transform.dtoToEntity(dto);
         User user = (User) shiroHelp.getLoginUser();
         entity.setUserId(user.getId());
-        userNoteService.update(entity);
+        userNoteQuestionService.update(entity);
 
         return ResponseHelp.success(true);
     }
 
     @RequestMapping(value = "/note/list", method = RequestMethod.GET)
     @ApiOperation(value = "获取笔记列表", notes = "获取笔记列表", httpMethod = "GET")
-    public Response<PageMessage<UserHomeworkPreviewExtendDto>> listNote(
+    public Response<PageMessage<UserNoteDetailDto>> listNote(
             @RequestParam(required = false, defaultValue = "1") int page,
             @RequestParam(required = false, defaultValue = "100") int size,
             @RequestParam(required = true) String module,
@@ -293,9 +321,10 @@ public class MyController {
             @RequestParam(required = false, defaultValue = "desc") String direction,
             HttpSession session)  {
         User user = (User) shiroHelp.getLoginUser();
-        PageResult<UserNoteRelation> p = userNoteService.list(page, size, user.getId(), QuestionModule.ValueOf(module), QuestionType.ValueOf(type), startTime, endTime, order, DirectionStatus.ValueOf(direction));
+        PageResult<UserNoteRelation> p = userNoteQuestionService.list(page, size, user.getId(), QuestionModule.ValueOf(module), QuestionType.ValueOf(type), startTime, endTime, order, DirectionStatus.ValueOf(direction));
+        List<UserNoteDetailDto> pr = Transform.convert(p, UserNoteDetailDto.class);
 
-        List<UserHomeworkPreviewExtendDto> pr = Transform.convert(p, UserHomeworkPreviewExtendDto.class);
+        // todo 绑定数据
 
         return ResponseHelp.success(pr, page, size, p.getTotal());
     }
@@ -322,6 +351,10 @@ public class MyController {
         Map<Object, Collection<UserReport>> reportByPaper = userReportService.mapByPaper(paperIds);
         Transform.combine(pr, reportByPaper, UserPaperDto.class, "id", "reports", UserReportExtendDto.class);
 
+        // 错题 -> 题型
+
+        // 模考 -> 分数
+
         return ResponseHelp.success(pr, page, size, p.getTotal());
     }
 }

+ 54 - 25
server/gateway-api/src/main/java/com/qxgmat/controller/api/QuestionController.java

@@ -1,9 +1,11 @@
 package com.qxgmat.controller.api;
 
 
+import com.alibaba.fastjson.JSONObject;
 import com.github.pagehelper.Page;
 import com.nuliji.tools.*;
 import com.qxgmat.data.constants.enums.logic.ExerciseLogic;
+import com.qxgmat.data.constants.enums.module.PaperModule;
 import com.qxgmat.data.constants.enums.module.PayModule;
 import com.qxgmat.data.dao.entity.*;
 import com.qxgmat.data.relation.entity.UserExercisePaperRelation;
@@ -11,13 +13,12 @@ import com.qxgmat.data.relation.entity.UserHomeworkPreviewRelation;
 import com.qxgmat.dto.extend.UserExercisePaperExtendDto;
 import com.qxgmat.dto.extend.UserHomeworkPreviewExtendDto;
 import com.qxgmat.dto.request.*;
-import com.qxgmat.dto.response.UserClassDetailDto;
-import com.qxgmat.dto.response.UserExerciseGroupDto;
-import com.qxgmat.dto.response.UserQuestionDetailDto;
+import com.qxgmat.dto.response.*;
 import com.qxgmat.help.ShiroHelp;
 import com.qxgmat.service.ExercisePaperService;
 import com.qxgmat.service.HomeworkPreviewService;
-import com.qxgmat.service.UserPaperService;
+import com.qxgmat.service.UserQuestionService;
+import com.qxgmat.service.extend.QuestionFlowService;
 import com.qxgmat.service.inline.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -40,29 +41,26 @@ public class QuestionController {
     private ShiroHelp shiroHelp;
 
     @Autowired
-    private QuestionNoService questionNoService;
+    private HomeworkPreviewService homeworkPreviewService;
 
     @Autowired
-    private UserPaperService userPaperService;
+    private ExercisePaperService exercisePaperService;
 
     @Autowired
-    private UserReportService userReportService;
+    private QuestionNoService questionNoService;
 
     @Autowired
     private UserQuestionService userQuestionService;
 
     @Autowired
-    private HomeworkPreviewService homeworkPreviewService;
-
-    @Autowired
-    private ExercisePaperService exercisePaperService;
-
-    @Autowired
     private UserClassService userClassService;
 
     @Autowired
     private UserPayService userPayService;
 
+    @Autowired
+    private QuestionFlowService questionFlowService;
+
     @RequestMapping(value = "/class/process", method = RequestMethod.GET)
     @ApiOperation(value = "获取课程进度", notes = "获取所有课程及状态进度", httpMethod = "GET")
     public Response<List<UserClassDetailDto>> classProcess()  {
@@ -70,11 +68,11 @@ public class QuestionController {
         List<UserClass> userClassList = userClassService.getByUser(user.getId());
         List<UserClassDetailDto> dtos = Transform.convert(userClassList, UserClassDetailDto.class);
 
-        // 获取每个科目的最后3次作业
+        // 获取每个科目的最后2次作业
         Map<Object, Collection<UserHomeworkPreviewRelation>> previewMap = homeworkPreviewService.groupByCategory(user.getId(), 3);
         Transform.combine(dtos, previewMap, UserClassDetailDto.class, "category", "previews", UserHomeworkPreviewExtendDto.class);
 
-        // 获取课程状态
+        // 获取课程状态:已购买未开通
         List<UserPay> pays = userPayService.listUnUse(user.getId(), PayModule.CLASS);
         Collection ids = Transform.getIds(userClassList, UserClass.class, "category");
         for(UserPay pay : pays){
@@ -125,6 +123,8 @@ public class QuestionController {
             HttpSession session) {
         Page<UserExerciseGroupDto> p=null;
 
+        // todo 获取数据
+
         return ResponseHelp.success(p);
     }
 
@@ -169,7 +169,7 @@ public class QuestionController {
             @RequestParam(required = false, defaultValue = "1") int page,
             @RequestParam(required = false, defaultValue = "100") int size,
             HttpSession session) {
-        Page<ExercisePaper> p=null;
+        Page<ExercisePaper> p = null;
 
         return ResponseHelp.success(p, page, size, p.getTotal());
     }
@@ -196,38 +196,67 @@ public class QuestionController {
 
     @RequestMapping(value = "/exercise/start", method = RequestMethod.POST)
     @ApiOperation(value = "开始: 练习", notes = "提交考试设置", httpMethod = "POST")
-    public Response<Boolean> start(@RequestBody @Validated ExerciseStartDto dto)  {
+    public Response<UserReportDto> start(@RequestBody @Validated ExerciseStartDto dto)  {
         User user = (User) shiroHelp.getLoginUser();
+        JSONObject setting = new JSONObject();
+        setting.put("disorder", dto.getDisorder());
+        UserReport report = questionFlowService.start(user.getId(), PaperModule.HOMEWORK_PREVIEW, dto.getPaperId(), setting);
 
-        return ResponseHelp.success(null);
+        return ResponseHelp.success(Transform.convert(report, UserReportDto.class));
     }
 
     @RequestMapping(value = "/preview/start", method = RequestMethod.POST)
     @ApiOperation(value = "开始: 预习作业", notes = "提交考试设置", httpMethod = "POST")
-    public Response<User> start(@RequestBody @Validated PreviewStartDto dto)  {
+    public Response<UserReportDto> start(@RequestBody @Validated PreviewStartDto dto)  {
         User user = (User) shiroHelp.getLoginUser();
-        return ResponseHelp.success(null);
+        JSONObject setting = new JSONObject();
+        setting.put("disorder", dto.getDisorder());
+        UserReport report = questionFlowService.start(user.getId(), PaperModule.HOMEWORK_PREVIEW, dto.getPaperId(), setting);
+
+        return ResponseHelp.success(Transform.convert(report, UserReportDto.class));
     }
 
     @RequestMapping(value = "/next", method = RequestMethod.POST)
     @ApiOperation(value = "获取下一题", notes = "获取下一题", httpMethod = "POST")
-    public Response<User> next(@RequestBody @Validated QuestionNextDto dto)  {
+    public Response<UserQuestionBaseDto> next(@RequestBody @Validated ReportNextDto dto)  {
         User user = (User) shiroHelp.getLoginUser();
+        // 根据对应paper获取,以及设定的setting获取下一题
+
+        UserQuestion userQuestion = questionFlowService.next(user.getId(), dto.getUserReportId());
+
+        // 绑定questionNos
+
+        // 绑定question
+
+        // 绑定collect
+
         return ResponseHelp.success(null);
     }
 
     @RequestMapping(value = "/submit", method = RequestMethod.POST)
     @ApiOperation(value = "提交题目答案", notes = "提交题目", httpMethod = "POST")
-    public Response<User> submit(@RequestBody @Validated QuestionSubmitDto dto)  {
+    public Response<Boolean> submit(@RequestBody @Validated QuestionSubmitDto dto)  {
         User user = (User) shiroHelp.getLoginUser();
-
-        return ResponseHelp.success(null);
+        Boolean result = questionFlowService.submit(user.getId(), dto.getUserQuestionId(), dto.getAnswer());
+        return ResponseHelp.success(result);
     }
 
     @RequestMapping(value = "/finish", method = RequestMethod.POST)
     @ApiOperation(value = "完成考试", notes = "完成考试", httpMethod = "POST")
-    public Response<User> finish(@RequestBody @Validated QuestionFinishDto dto)  {
+    public Response<Boolean> finish(@RequestBody @Validated ReportFinishDto dto)  {
         User user = (User) shiroHelp.getLoginUser();
+
+        Boolean result = questionFlowService.finish(user.getId(), dto.getUserReportId());
+        return ResponseHelp.success(result);
+    }
+
+    @RequestMapping(value = "/restart", method = RequestMethod.POST)
+    @ApiOperation(value = "重置考试", notes = "重置考试", httpMethod = "POST")
+    public Response<User> restart(@RequestBody @Validated PaperRestartDto dto)  {
+        User user = (User) shiroHelp.getLoginUser();
+
+        questionFlowService.restart(dto.getUserPaperId(), user.getId());
+
         return ResponseHelp.success(null);
     }
 }

+ 43 - 33
server/gateway-api/src/main/java/com/qxgmat/controller/api/SentenceController.java

@@ -7,16 +7,14 @@ import com.nuliji.tools.Transform;
 import com.nuliji.tools.exception.AuthException;
 import com.qxgmat.data.constants.enums.SettingKey;
 import com.qxgmat.data.constants.enums.logic.SentenceLogic;
+import com.qxgmat.data.constants.enums.module.PaperModule;
 import com.qxgmat.data.dao.entity.*;
-import com.qxgmat.dto.request.SentenceStartDto;
-import com.qxgmat.dto.request.UserSentenceCodeDto;
-import com.qxgmat.dto.request.UserSentenceProcessDto;
-import com.qxgmat.dto.response.UserSentenceArticleDto;
-import com.qxgmat.dto.response.UserSentencePaperDto;
+import com.qxgmat.dto.request.*;
+import com.qxgmat.dto.response.*;
 import com.qxgmat.help.ShiroHelp;
 import com.qxgmat.service.SentencePaperService;
-import com.qxgmat.service.UserPaperService;
 import com.qxgmat.service.UsersService;
+import com.qxgmat.service.extend.QuestionFlowService;
 import com.qxgmat.service.inline.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -37,15 +35,6 @@ public class SentenceController
     private ShiroHelp shiroHelp;
 
     @Autowired
-    private UserPaperService userPaperService;
-
-    @Autowired
-    private UserReportService userReportService;
-
-    @Autowired
-    private UserQuestionService userQuestionService;
-
-    @Autowired
     private SentenceArticleService sentenceArticleService;
 
     @Autowired
@@ -55,16 +44,19 @@ public class SentenceController
     private SentencePaperService sentencePaperService;
 
     @Autowired
-    private UserSentenceProcessService userSentenceProcessService;
+    private SentenceCodeService sentenceCodeService;
+
+    @Autowired
+    private SettingService settingService;
 
     @Autowired
     private UsersService usersService;
 
     @Autowired
-    private SentenceCodeService sentenceCodeService;
+    private UserSentenceProcessService userSentenceProcessService;
 
     @Autowired
-    private SettingService settingService;
+    private QuestionFlowService questionFlowService;
 
     @RequestMapping(value = "/info", method = RequestMethod.GET)
     @ApiOperation(value = "所有长难句信息", httpMethod = "GET")
@@ -137,6 +129,8 @@ public class SentenceController
     public Response<Boolean> articleProcess(@RequestBody @Validated UserSentenceProcessDto dto) {
         UserSentenceProcess entity = Transform.dtoToEntity(dto);
         User user = (User) shiroHelp.getLoginUser();
+        if (user == null) throw new AuthException("需要登录");
+
         // 获取本章节的最大part数
         Integer max = sentenceArticleService.maxPart(dto.getChapter());
 
@@ -165,7 +159,7 @@ public class SentenceController
 
     @RequestMapping(value = "/question/detail", method = RequestMethod.GET)
     @ApiOperation(value = "获取题目详情", notes = "获取题目详情", httpMethod = "GET")
-    public Response<User> detail(
+    public Response<UserSentenceQuestionDetailDto> detail(
             @RequestParam(required = false) String questionNoId
     )  {
         User user = (User) shiroHelp.getLoginUser();
@@ -174,37 +168,53 @@ public class SentenceController
 
     @RequestMapping(value = "/paper/start", method = RequestMethod.POST)
     @ApiOperation(value = "开始做题", notes = "提交考试设置", httpMethod = "POST")
-    public Response<User> start(@RequestBody @Validated SentenceStartDto dto)  {
+    public Response<UserReportDto> start(@RequestBody @Validated SentenceStartDto dto)  {
         User user = (User) shiroHelp.getLoginUser();
-
-
-        return ResponseHelp.success(null);
+        JSONObject setting = new JSONObject();
+        UserReport report = questionFlowService.start(user.getId(), PaperModule.SENTENCE, dto.getPaperId(), setting);
+        return ResponseHelp.success(Transform.convert(report, UserReportDto.class));
     }
 
     @RequestMapping(value = "/paper/next", method = RequestMethod.POST)
     @ApiOperation(value = "获取下一题", notes = "获取下一题", httpMethod = "POST")
-    public Response<User> next(
-            @RequestParam(required = false) String reportId
-    )  {
+    public Response<UserSentenceQuestionBaseDto> next(@RequestBody @Validated ReportNextDto dto)  {
         User user = (User) shiroHelp.getLoginUser();
+
+        UserQuestion userQuestion = questionFlowService.next(user.getId(), dto.getUserReportId());
+
+        // 绑定sentenceQuestion
+
+        // 绑定question
+
+        // 绑定collect
+
         return ResponseHelp.success(null);
     }
 
     @RequestMapping(value = "/paper/submit", method = RequestMethod.POST)
     @ApiOperation(value = "提交题目答案", notes = "提交题目", httpMethod = "POST")
-    public Response<User> submit(
-            @RequestParam(required = false) String questionNoId
-    )  {
+    public Response<Boolean> submit(@RequestBody @Validated QuestionSubmitDto dto)  {
         User user = (User) shiroHelp.getLoginUser();
-        return ResponseHelp.success(null);
+        Boolean result = questionFlowService.submit(user.getId(), dto.getUserQuestionId(), dto.getAnswer());
+        return ResponseHelp.success(result);
     }
 
     @RequestMapping(value = "/paper/finish", method = RequestMethod.POST)
     @ApiOperation(value = "完成考试", notes = "完成考试", httpMethod = "POST")
-    public Response<User> finish(
-            @RequestParam(required = false) String paperId
-    )  {
+    public Response<Boolean> finish(@RequestBody @Validated ReportFinishDto dto)  {
+        User user = (User) shiroHelp.getLoginUser();
+
+        Boolean result = questionFlowService.finish(user.getId(), dto.getUserReportId());
+        return ResponseHelp.success(result);
+    }
+
+    @RequestMapping(value = "/paper/restart", method = RequestMethod.POST)
+    @ApiOperation(value = "重置考试", notes = "重置考试", httpMethod = "POST")
+    public Response<User> restart(@RequestBody @Validated PaperRestartDto dto)  {
         User user = (User) shiroHelp.getLoginUser();
+
+        questionFlowService.restart(dto.getUserPaperId(), user.getId());
+
         return ResponseHelp.success(null);
     }
 }

+ 10 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/admin/request/QuestionDto.java

@@ -37,6 +37,8 @@ public class QuestionDto {
 
     private JSONObject content;
 
+    private JSONObject answer;
+
     private JSONObject style;
 
     public Integer getId() {
@@ -142,4 +144,12 @@ public class QuestionDto {
     public void setDescription(String description) {
         this.description = description;
     }
+
+    public JSONObject getAnswer() {
+        return answer;
+    }
+
+    public void setAnswer(JSONObject answer) {
+        this.answer = answer;
+    }
 }

+ 10 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/admin/response/QuestionDetailDto.java

@@ -26,6 +26,8 @@ public class QuestionDetailDto {
 
     private JSONObject content;
 
+    private JSONObject answer;
+
     private String officialContent;
 
     private String qxContent;
@@ -127,4 +129,12 @@ public class QuestionDetailDto {
     public void setQuestionNoIds(Integer[] questionNoIds) {
         this.questionNoIds = questionNoIds;
     }
+
+    public JSONObject getAnswer() {
+        return answer;
+    }
+
+    public void setAnswer(JSONObject answer) {
+        this.answer = answer;
+    }
 }

+ 49 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/extend/QuestionBaseExtendDto.java

@@ -0,0 +1,49 @@
+package com.qxgmat.dto.extend;
+
+import com.alibaba.fastjson.JSONObject;
+import com.nuliji.tools.annotation.Dto;
+import com.qxgmat.data.dao.entity.Question;
+
+@Dto(entity = Question.class)
+public class QuestionBaseExtendDto  {
+
+    private Integer id;
+
+    private String stem;
+
+    private String type;
+
+    private JSONObject content;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getStem() {
+        return stem;
+    }
+
+    public void setStem(String stem) {
+        this.stem = stem;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public JSONObject getContent() {
+        return content;
+    }
+
+    public void setContent(JSONObject content) {
+        this.content = content;
+    }
+}

+ 42 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/extend/QuestionDetailExtendDto.java

@@ -21,6 +21,8 @@ public class QuestionDetailExtendDto {
 
     private JSONObject content;
 
+    private JSONObject answer;
+
     private Integer[] associationContent;
 
     public Integer getId() {
@@ -62,4 +64,44 @@ public class QuestionDetailExtendDto {
     public void setPlace(String place) {
         this.place = place;
     }
+
+    public String getOfficialContent() {
+        return officialContent;
+    }
+
+    public void setOfficialContent(String officialContent) {
+        this.officialContent = officialContent;
+    }
+
+    public String getQxContent() {
+        return qxContent;
+    }
+
+    public void setQxContent(String qxContent) {
+        this.qxContent = qxContent;
+    }
+
+    public JSONObject getContent() {
+        return content;
+    }
+
+    public void setContent(JSONObject content) {
+        this.content = content;
+    }
+
+    public Integer[] getAssociationContent() {
+        return associationContent;
+    }
+
+    public void setAssociationContent(Integer[] associationContent) {
+        this.associationContent = associationContent;
+    }
+
+    public JSONObject getAnswer() {
+        return answer;
+    }
+
+    public void setAnswer(JSONObject answer) {
+        this.answer = answer;
+    }
 }

+ 37 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/extend/SentenceQuestionExtendDto.java

@@ -0,0 +1,37 @@
+package com.qxgmat.dto.extend;
+
+import com.nuliji.tools.annotation.Dto;
+import com.qxgmat.data.dao.entity.SentenceQuestion;
+
+@Dto(entity = SentenceQuestion.class)
+public class SentenceQuestionExtendDto {
+    private String title;
+
+    private Integer no;
+
+    private String chinese;
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public Integer getNo() {
+        return no;
+    }
+
+    public void setNo(Integer no) {
+        this.no = no;
+    }
+
+    public String getChinese() {
+        return chinese;
+    }
+
+    public void setChinese(String chinese) {
+        this.chinese = chinese;
+    }
+}

+ 17 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/extend/UserNoteExtendDto.java

@@ -0,0 +1,17 @@
+package com.qxgmat.dto.extend;
+
+import com.nuliji.tools.annotation.Dto;
+import com.qxgmat.data.dao.entity.UserNoteQuestion;
+
+@Dto(entity = UserNoteQuestion.class)
+public class UserNoteExtendDto {
+    private String content;
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+}

+ 24 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/request/MessageReadDto.java

@@ -0,0 +1,24 @@
+package com.qxgmat.dto.request;
+
+public class MessageReadDto {
+
+    private Integer id;
+
+    private Boolean all;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Boolean getAll() {
+        return all;
+    }
+
+    public void setAll(Boolean all) {
+        this.all = all;
+    }
+}

+ 1 - 1
server/gateway-api/src/main/java/com/qxgmat/dto/request/QuestionFinishDto.java

@@ -1,6 +1,6 @@
 package com.qxgmat.dto.request;
 
-public class QuestionFinishDto {
+public class PaperRestartDto {
     private Integer userPaperId;
 
     public Integer getUserPaperId() {

+ 5 - 5
server/gateway-api/src/main/java/com/qxgmat/dto/request/PreviewStartDto.java

@@ -3,7 +3,7 @@ package com.qxgmat.dto.request;
 public class PreviewStartDto {
     private Boolean disorder;
 
-    private Integer previewId;
+    private Integer paperId;
 
     public Boolean getDisorder() {
         return disorder;
@@ -13,11 +13,11 @@ public class PreviewStartDto {
         this.disorder = disorder;
     }
 
-    public Integer getPreviewId() {
-        return previewId;
+    public Integer getPaperId() {
+        return paperId;
     }
 
-    public void setPreviewId(Integer previewId) {
-        this.previewId = previewId;
+    public void setPaperId(Integer paperId) {
+        this.paperId = paperId;
     }
 }

+ 0 - 15
server/gateway-api/src/main/java/com/qxgmat/dto/request/QuestionNextDto.java

@@ -1,15 +0,0 @@
-package com.qxgmat.dto.request;
-
-import com.alibaba.fastjson.JSONObject;
-
-public class QuestionNextDto {
-    private Integer userPaperId;
-
-    public Integer getUserPaperId() {
-        return userPaperId;
-    }
-
-    public void setUserPaperId(Integer userPaperId) {
-        this.userPaperId = userPaperId;
-    }
-}

+ 13 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/request/ReportFinishDto.java

@@ -0,0 +1,13 @@
+package com.qxgmat.dto.request;
+
+public class ReportFinishDto {
+    private Integer userReportId;
+
+    public Integer getUserReportId() {
+        return userReportId;
+    }
+
+    public void setUserReportId(Integer userReportId) {
+        this.userReportId = userReportId;
+    }
+}

+ 15 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/request/ReportNextDto.java

@@ -0,0 +1,15 @@
+package com.qxgmat.dto.request;
+
+import com.alibaba.fastjson.JSONObject;
+
+public class ReportNextDto {
+    private Integer userReportId;
+
+    public Integer getUserReportId() {
+        return userReportId;
+    }
+
+    public void setUserReportId(Integer userReportId) {
+        this.userReportId = userReportId;
+    }
+}

+ 8 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/request/SentenceStartDto.java

@@ -1,5 +1,13 @@
 package com.qxgmat.dto.request;
 
 public class SentenceStartDto {
+    private Integer paperId;
 
+    public Integer getPaperId() {
+        return paperId;
+    }
+
+    public void setPaperId(Integer paperId) {
+        this.paperId = paperId;
+    }
 }

+ 13 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/request/UserCollectBindDto.java

@@ -0,0 +1,13 @@
+package com.qxgmat.dto.request;
+
+public class UserCollectBindDto {
+    private Integer[] questionNoIds;
+
+    public Integer[] getQuestionNoIds() {
+        return questionNoIds;
+    }
+
+    public void setQuestionNoIds(Integer[] questionNoIds) {
+        this.questionNoIds = questionNoIds;
+    }
+}

+ 10 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/request/UserCollectDto.java

@@ -5,6 +5,8 @@ import com.qxgmat.data.dao.entity.UserCollectQuestion;
 
 @Dto(entity = UserCollectQuestion.class)
 public class UserCollectDto {
+    private String module;
+
     private Integer questionNoId;
 
     public Integer getQuestionNoId() {
@@ -14,4 +16,12 @@ public class UserCollectDto {
     public void setQuestionNoId(Integer questionNoId) {
         this.questionNoId = questionNoId;
     }
+
+    public String getModule() {
+        return module;
+    }
+
+    public void setModule(String module) {
+        this.module = module;
+    }
 }

+ 24 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/request/UserErrorBindDto.java

@@ -0,0 +1,24 @@
+package com.qxgmat.dto.request;
+
+public class UserErrorBindDto {
+    private Integer[] questionNoIds;
+
+    // 过滤已组卷n次的题目
+    private Integer filterTimes;
+
+    public Integer[] getQuestionNoIds() {
+        return questionNoIds;
+    }
+
+    public void setQuestionNoIds(Integer[] questionNoIds) {
+        this.questionNoIds = questionNoIds;
+    }
+
+    public Integer getFilterTimes() {
+        return filterTimes;
+    }
+
+    public void setFilterTimes(Integer filterTimes) {
+        this.filterTimes = filterTimes;
+    }
+}

+ 11 - 2
server/gateway-api/src/main/java/com/qxgmat/dto/request/UserNoteDto.java

@@ -1,10 +1,11 @@
 package com.qxgmat.dto.request;
 
 import com.nuliji.tools.annotation.Dto;
-import com.qxgmat.data.dao.entity.UserNote;
+import com.qxgmat.data.dao.entity.UserNoteQuestion;
 
-@Dto(entity = UserNote.class)
+@Dto(entity = UserNoteQuestion.class)
 public class UserNoteDto {
+    private String module;
 
     private Integer questionNoId;
 
@@ -25,4 +26,12 @@ public class UserNoteDto {
     public void setContent(String content) {
         this.content = content;
     }
+
+    public String getModule() {
+        return module;
+    }
+
+    public void setModule(String module) {
+        this.module = module;
+    }
 }

+ 12 - 12
server/gateway-api/src/main/java/com/qxgmat/dto/request/UserPrepareDto.java

@@ -10,7 +10,7 @@ public class UserPrepareDto {
     /**
      * 备考:身份
      */
-    private Integer prepareStatus;
+    private String prepareStatus;
 
     /**
      * 备考:目标分数
@@ -20,18 +20,18 @@ public class UserPrepareDto {
     /**
      * 备考:考试时间
      */
-    private Date prepareExaminationTime;
+    private Integer prepareExaminationTime;
 
     /**
      * 备考:出分时间
      */
     private Date prepareScoreTime;
 
-    public Integer getPrepareStatus() {
+    public String getPrepareStatus() {
         return prepareStatus;
     }
 
-    public void setPrepareStatus(Integer prepareStatus) {
+    public void setPrepareStatus(String prepareStatus) {
         this.prepareStatus = prepareStatus;
     }
 
@@ -43,14 +43,6 @@ public class UserPrepareDto {
         this.prepareGoal = prepareGoal;
     }
 
-    public Date getPrepareExaminationTime() {
-        return prepareExaminationTime;
-    }
-
-    public void setPrepareExaminationTime(Date prepareExaminationTime) {
-        this.prepareExaminationTime = prepareExaminationTime;
-    }
-
     public Date getPrepareScoreTime() {
         return prepareScoreTime;
     }
@@ -58,4 +50,12 @@ public class UserPrepareDto {
     public void setPrepareScoreTime(Date prepareScoreTime) {
         this.prepareScoreTime = prepareScoreTime;
     }
+
+    public Integer getPrepareExaminationTime() {
+        return prepareExaminationTime;
+    }
+
+    public void setPrepareExaminationTime(Integer prepareExaminationTime) {
+        this.prepareExaminationTime = prepareExaminationTime;
+    }
 }

+ 72 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/MyDto.java

@@ -16,7 +16,13 @@ public class MyDto extends UserDto {
 
     private String inviteCode;
 
+    private Boolean wechat;
 
+    private Boolean real;
+
+    private Boolean prepare;
+
+    private Boolean mobile;
 
     @ApiModelProperty(value = "未读消息数", required = true)
     private int messageNum;
@@ -28,4 +34,70 @@ public class MyDto extends UserDto {
     public void setMessageNum(int messageNum) {
         this.messageNum = messageNum;
     }
+
+    @Override
+    public String getNickname() {
+        return nickname;
+    }
+
+    @Override
+    public void setNickname(String nickname) {
+        this.nickname = nickname;
+    }
+
+    public String getAvatar() {
+        return avatar;
+    }
+
+    public void setAvatar(String avatar) {
+        this.avatar = avatar;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getInviteCode() {
+        return inviteCode;
+    }
+
+    public void setInviteCode(String inviteCode) {
+        this.inviteCode = inviteCode;
+    }
+
+    public Boolean getWechat() {
+        return wechat;
+    }
+
+    public void setWechat(Boolean wechat) {
+        this.wechat = wechat;
+    }
+
+    public Boolean getReal() {
+        return real;
+    }
+
+    public void setReal(Boolean real) {
+        this.real = real;
+    }
+
+    public Boolean getPrepare() {
+        return prepare;
+    }
+
+    public void setPrepare(Boolean prepare) {
+        this.prepare = prepare;
+    }
+
+    public Boolean getMobile() {
+        return mobile;
+    }
+
+    public void setMobile(Boolean mobile) {
+        this.mobile = mobile;
+    }
 }

+ 17 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserNoteDetailDto.java

@@ -0,0 +1,17 @@
+package com.qxgmat.dto.response;
+
+import com.nuliji.tools.annotation.Dto;
+import com.qxgmat.data.dao.entity.UserNoteQuestion;
+
+@Dto(entity = UserNoteQuestion.class)
+public class UserNoteDetailDto {
+    private Integer id;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+}

+ 0 - 61
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserNoteDto.java

@@ -1,61 +0,0 @@
-package com.qxgmat.dto.response;
-
-import com.nuliji.tools.annotation.Dto;
-import com.qxgmat.data.dao.entity.UserNote;
-import com.qxgmat.dto.extend.QuestionExtendDto;
-import com.qxgmat.dto.extend.QuestionNoExtendDto;
-
-import java.util.Date;
-
-@Dto(entity = UserNote.class)
-public class UserNoteDto {
-    private Integer id;
-
-    private QuestionExtendDto question;
-
-    private QuestionNoExtendDto questionNo;
-
-    private Date createTime;
-
-    private String content;
-
-    public Integer getId() {
-        return id;
-    }
-
-    public void setId(Integer id) {
-        this.id = id;
-    }
-
-    public QuestionExtendDto getQuestion() {
-        return question;
-    }
-
-    public void setQuestion(QuestionExtendDto question) {
-        this.question = question;
-    }
-
-    public QuestionNoExtendDto getQuestionNo() {
-        return questionNo;
-    }
-
-    public void setQuestionNo(QuestionNoExtendDto questionNo) {
-        this.questionNo = questionNo;
-    }
-
-    public Date getCreateTime() {
-        return createTime;
-    }
-
-    public void setCreateTime(Date createTime) {
-        this.createTime = createTime;
-    }
-
-    public String getContent() {
-        return content;
-    }
-
-    public void setContent(String content) {
-        this.content = content;
-    }
-}

+ 12 - 13
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserPrepareDetailDto.java

@@ -10,7 +10,7 @@ public class UserPrepareDetailDto {
     /**
      * 备考:身份
      */
-    private Integer prepareStatus;
+    private String prepareStatus;
 
     /**
      * 备考:目标分数
@@ -20,7 +20,7 @@ public class UserPrepareDetailDto {
     /**
      * 备考:考试时间
      */
-    private Date prepareExaminationTime;
+    private Integer prepareExaminationTime;
 
     /**
      * 备考:出分时间
@@ -28,12 +28,11 @@ public class UserPrepareDetailDto {
     private Date prepareScoreTime;
 
 
-
-    public Integer getPrepareStatus() {
+    public String getPrepareStatus() {
         return prepareStatus;
     }
 
-    public void setPrepareStatus(Integer prepareStatus) {
+    public void setPrepareStatus(String prepareStatus) {
         this.prepareStatus = prepareStatus;
     }
 
@@ -45,14 +44,6 @@ public class UserPrepareDetailDto {
         this.prepareGoal = prepareGoal;
     }
 
-    public Date getPrepareExaminationTime() {
-        return prepareExaminationTime;
-    }
-
-    public void setPrepareExaminationTime(Date prepareExaminationTime) {
-        this.prepareExaminationTime = prepareExaminationTime;
-    }
-
     public Date getPrepareScoreTime() {
         return prepareScoreTime;
     }
@@ -60,4 +51,12 @@ public class UserPrepareDetailDto {
     public void setPrepareScoreTime(Date prepareScoreTime) {
         this.prepareScoreTime = prepareScoreTime;
     }
+
+    public Integer getPrepareExaminationTime() {
+        return prepareExaminationTime;
+    }
+
+    public void setPrepareExaminationTime(Integer prepareExaminationTime) {
+        this.prepareExaminationTime = prepareExaminationTime;
+    }
 }

+ 74 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserQuestionBaseDto.java

@@ -0,0 +1,74 @@
+package com.qxgmat.dto.response;
+
+import com.alibaba.fastjson.JSONObject;
+import com.nuliji.tools.annotation.Dto;
+import com.qxgmat.data.dao.entity.UserQuestion;
+import com.qxgmat.dto.extend.QuestionBaseExtendDto;
+import com.qxgmat.dto.extend.QuestionDetailExtendDto;
+import com.qxgmat.dto.extend.QuestionNoExtendDto;
+import com.qxgmat.dto.extend.UserNoteExtendDto;
+
+import java.util.List;
+
+@Dto(entity = UserQuestion.class)
+public class UserQuestionBaseDto {
+    private Integer id;
+
+    private Integer questionId;
+
+    private Integer questionNoId;
+
+    private QuestionBaseExtendDto question;
+
+    private List<QuestionNoExtendDto> questionNos;
+
+    private Boolean collect;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getQuestionId() {
+        return questionId;
+    }
+
+    public void setQuestionId(Integer questionId) {
+        this.questionId = questionId;
+    }
+
+    public Integer getQuestionNoId() {
+        return questionNoId;
+    }
+
+    public void setQuestionNoId(Integer questionNoId) {
+        this.questionNoId = questionNoId;
+    }
+
+    public QuestionBaseExtendDto getQuestion() {
+        return question;
+    }
+
+    public void setQuestion(QuestionBaseExtendDto question) {
+        this.question = question;
+    }
+
+    public List<QuestionNoExtendDto> getQuestionNos() {
+        return questionNos;
+    }
+
+    public void setQuestionNos(List<QuestionNoExtendDto> questionNos) {
+        this.questionNos = questionNos;
+    }
+
+    public Boolean getCollect() {
+        return collect;
+    }
+
+    public void setCollect(Boolean collect) {
+        this.collect = collect;
+    }
+}

+ 79 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserQuestionDetailDto.java

@@ -5,6 +5,7 @@ import com.nuliji.tools.annotation.Dto;
 import com.qxgmat.data.dao.entity.UserQuestion;
 import com.qxgmat.dto.extend.QuestionDetailExtendDto;
 import com.qxgmat.dto.extend.QuestionNoExtendDto;
+import com.qxgmat.dto.extend.UserNoteExtendDto;
 
 import java.util.List;
 
@@ -12,6 +13,8 @@ import java.util.List;
 public class UserQuestionDetailDto {
     private Integer id;
 
+    private String module;
+
     private Integer questionId;
 
     private Integer questionNoId;
@@ -21,4 +24,80 @@ public class UserQuestionDetailDto {
     private JSONObject answer;
 
     private QuestionDetailExtendDto question;
+
+    private Boolean collect;
+
+    private UserNoteExtendDto note;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getModule() {
+        return module;
+    }
+
+    public void setModule(String module) {
+        this.module = module;
+    }
+
+    public Integer getQuestionId() {
+        return questionId;
+    }
+
+    public void setQuestionId(Integer questionId) {
+        this.questionId = questionId;
+    }
+
+    public Integer getQuestionNoId() {
+        return questionNoId;
+    }
+
+    public void setQuestionNoId(Integer questionNoId) {
+        this.questionNoId = questionNoId;
+    }
+
+    public List<QuestionNoExtendDto> getQuestionNos() {
+        return questionNos;
+    }
+
+    public void setQuestionNos(List<QuestionNoExtendDto> questionNos) {
+        this.questionNos = questionNos;
+    }
+
+    public JSONObject getAnswer() {
+        return answer;
+    }
+
+    public void setAnswer(JSONObject answer) {
+        this.answer = answer;
+    }
+
+    public QuestionDetailExtendDto getQuestion() {
+        return question;
+    }
+
+    public void setQuestion(QuestionDetailExtendDto question) {
+        this.question = question;
+    }
+
+    public Boolean getCollect() {
+        return collect;
+    }
+
+    public void setCollect(Boolean collect) {
+        this.collect = collect;
+    }
+
+    public UserNoteExtendDto getNote() {
+        return note;
+    }
+
+    public void setNote(UserNoteExtendDto note) {
+        this.note = note;
+    }
 }

+ 32 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserQuestionListDto.java

@@ -16,4 +16,36 @@ public class UserQuestionListDto {
     private QuestionNoExtendDto questionNoExtendDto;
 
     private Date createTime;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public QuestionExtendDto getQuestion() {
+        return question;
+    }
+
+    public void setQuestion(QuestionExtendDto question) {
+        this.question = question;
+    }
+
+    public QuestionNoExtendDto getQuestionNoExtendDto() {
+        return questionNoExtendDto;
+    }
+
+    public void setQuestionNoExtendDto(QuestionNoExtendDto questionNoExtendDto) {
+        this.questionNoExtendDto = questionNoExtendDto;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
 }

+ 8 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserReportDto.java

@@ -0,0 +1,8 @@
+package com.qxgmat.dto.response;
+
+import com.nuliji.tools.annotation.Dto;
+import com.qxgmat.data.dao.entity.UserReport;
+
+@Dto(entity = UserReport.class)
+public class UserReportDto {
+}

+ 70 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserSentenceQuestionBaseDto.java

@@ -0,0 +1,70 @@
+package com.qxgmat.dto.response;
+
+import com.alibaba.fastjson.JSONObject;
+import com.qxgmat.dto.extend.QuestionBaseExtendDto;
+import com.qxgmat.dto.extend.QuestionDetailExtendDto;
+import com.qxgmat.dto.extend.SentenceQuestionExtendDto;
+import com.qxgmat.dto.extend.UserNoteExtendDto;
+
+public class UserSentenceQuestionBaseDto {
+
+    private Integer id;
+
+    private Integer questionId;
+
+    private Integer questionNoId;
+
+    private QuestionBaseExtendDto question;
+
+    private SentenceQuestionExtendDto sentence;
+
+    private Boolean collect;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getQuestionId() {
+        return questionId;
+    }
+
+    public void setQuestionId(Integer questionId) {
+        this.questionId = questionId;
+    }
+
+    public Integer getQuestionNoId() {
+        return questionNoId;
+    }
+
+    public void setQuestionNoId(Integer questionNoId) {
+        this.questionNoId = questionNoId;
+    }
+
+    public SentenceQuestionExtendDto getSentence() {
+        return sentence;
+    }
+
+    public void setSentence(SentenceQuestionExtendDto sentence) {
+        this.sentence = sentence;
+    }
+
+    public QuestionBaseExtendDto getQuestion() {
+        return question;
+    }
+
+    public void setQuestion(QuestionBaseExtendDto question) {
+        this.question = question;
+    }
+
+    public Boolean getCollect() {
+        return collect;
+    }
+
+    public void setCollect(Boolean collect) {
+        this.collect = collect;
+    }
+}

+ 99 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserSentenceQuestionDetailDto.java

@@ -0,0 +1,99 @@
+package com.qxgmat.dto.response;
+
+import com.alibaba.fastjson.JSONObject;
+import com.qxgmat.dto.extend.QuestionDetailExtendDto;
+import com.qxgmat.dto.extend.SentenceQuestionExtendDto;
+import com.qxgmat.dto.extend.UserNoteExtendDto;
+
+public class UserSentenceQuestionDetailDto {
+
+    private Integer id;
+
+    private String module;
+
+    private Integer questionId;
+
+    private Integer questionNoId;
+
+    private JSONObject answer;
+
+    private QuestionDetailExtendDto question;
+
+    private SentenceQuestionExtendDto sentence;
+
+    private Boolean collect;
+
+    private UserNoteExtendDto note;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getModule() {
+        return module;
+    }
+
+    public void setModule(String module) {
+        this.module = module;
+    }
+
+    public Integer getQuestionId() {
+        return questionId;
+    }
+
+    public void setQuestionId(Integer questionId) {
+        this.questionId = questionId;
+    }
+
+    public Integer getQuestionNoId() {
+        return questionNoId;
+    }
+
+    public void setQuestionNoId(Integer questionNoId) {
+        this.questionNoId = questionNoId;
+    }
+
+    public JSONObject getAnswer() {
+        return answer;
+    }
+
+    public void setAnswer(JSONObject answer) {
+        this.answer = answer;
+    }
+
+    public QuestionDetailExtendDto getQuestion() {
+        return question;
+    }
+
+    public void setQuestion(QuestionDetailExtendDto question) {
+        this.question = question;
+    }
+
+    public SentenceQuestionExtendDto getSentence() {
+        return sentence;
+    }
+
+    public void setSentence(SentenceQuestionExtendDto sentence) {
+        this.sentence = sentence;
+    }
+
+    public Boolean getCollect() {
+        return collect;
+    }
+
+    public void setCollect(Boolean collect) {
+        this.collect = collect;
+    }
+
+    public UserNoteExtendDto getNote() {
+        return note;
+    }
+
+    public void setNote(UserNoteExtendDto note) {
+        this.note = note;
+    }
+}

+ 4 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserStudyDetailDto.java

@@ -0,0 +1,4 @@
+package com.qxgmat.dto.response;
+
+public class UserStudyDetailDto {
+}

+ 8 - 0
server/gateway-api/src/main/java/com/qxgmat/service/ExercisePaperService.java

@@ -7,6 +7,7 @@ import com.nuliji.tools.Transform;
 import com.nuliji.tools.exception.ParameterException;
 import com.nuliji.tools.exception.SystemException;
 import com.nuliji.tools.mybatis.Example;
+import com.qxgmat.data.constants.enums.SettingKey;
 import com.qxgmat.data.constants.enums.logic.ExerciseLogic;
 import com.qxgmat.data.dao.ExercisePaperMapper;
 import com.qxgmat.data.dao.entity.ExercisePaper;
@@ -16,6 +17,7 @@ import com.qxgmat.data.dao.entity.UserReport;
 import com.qxgmat.data.relation.ExercisePaperRelationMapper;
 import com.qxgmat.data.relation.UserPaperRelationMapper;
 import com.qxgmat.data.relation.UserReportRelationMapper;
+import com.qxgmat.data.relation.entity.QuestionNoRelation;
 import com.qxgmat.data.relation.entity.UserExercisePaperRelation;
 import com.qxgmat.service.inline.QuestionService;
 import com.qxgmat.service.inline.UserReportService;
@@ -54,6 +56,12 @@ public class ExercisePaperService extends AbstractService {
     @Resource
     private UserReportService userReportService;
 
+    public void initUserPaper(UserPaper userPaper, Integer id){
+        ExercisePaper paper = get(id);
+        userPaper.setTitle(paper.getTitle());
+        userPaper.setQuestionNoIds(paper.getQuestionNoIds());
+    }
+
     // 完成一次
     public boolean finished(UserPaper userPaper){
 

+ 7 - 0
server/gateway-api/src/main/java/com/qxgmat/service/SentencePaperService.java

@@ -11,6 +11,7 @@ import com.qxgmat.data.dao.SentencePaperMapper;
 import com.qxgmat.data.dao.entity.Question;
 import com.qxgmat.data.dao.entity.SentencePaper;
 import com.qxgmat.data.dao.entity.SentenceQuestion;
+import com.qxgmat.data.dao.entity.UserPaper;
 import com.qxgmat.data.relation.entity.SentenceQuestionRelation;
 import com.qxgmat.service.inline.QuestionService;
 import com.qxgmat.service.inline.SentenceQuestionService;
@@ -41,6 +42,12 @@ public class SentencePaperService extends AbstractService {
     @Resource
     private SentenceQuestionService sentenceQuestionService;
 
+    public void initUserPaper(UserPaper userPaper, Integer id){
+        SentencePaper paper = get(id);
+        userPaper.setTitle(paper.getTitle());
+        userPaper.setQuestionNoIds(paper.getQuestionNoIds());
+        userPaper.setTime(0);
+    }
     /**
      * 添加长难句题目:加入题库,关联题目,并关联长难句paper
      * @param relation

+ 14 - 2
server/gateway-api/src/main/java/com/qxgmat/service/UserCollectQuestionService.java

@@ -78,8 +78,14 @@ public class UserCollectQuestionService extends AbstractService {
         return new PageResult<>(pr, p.getTotal());
     }
 
+    /**
+     * 收藏题目编号:包含题目id
+     * @param userId
+     * @param questionNoId
+     * @return
+     */
     @Transactional
-    public UserCollectQuestion addQuestion(Integer userId, Integer questionNoId){
+    public UserCollectQuestion addQuestion(Integer userId, QuestionModule module, Integer questionNoId){
         Example example = new Example(UserCollectQuestion.class);
         example.and(
                 example.createCriteria()
@@ -99,8 +105,14 @@ public class UserCollectQuestionService extends AbstractService {
         return collect;
     }
 
+    /**
+     * 取消收藏题目编号
+     * @param userId
+     * @param questionNoId
+     * @return
+     */
     @Transactional
-    public boolean deleteQuestion(Integer userId, Integer questionNoId){
+    public boolean deleteQuestion(Integer userId, QuestionModule module, Integer questionNoId){
         Example example = new Example(UserCollectQuestion.class);
         example.and(
                 example.createCriteria()

+ 25 - 24
server/gateway-api/src/main/java/com/qxgmat/service/UserNoteService.java

@@ -10,11 +10,11 @@ import com.nuliji.tools.mybatis.Example;
 import com.qxgmat.data.constants.enums.QuestionType;
 import com.qxgmat.data.constants.enums.module.QuestionModule;
 import com.qxgmat.data.constants.enums.status.DirectionStatus;
-import com.qxgmat.data.dao.UserNoteMapper;
+import com.qxgmat.data.dao.UserNoteQuestionMapper;
 import com.qxgmat.data.dao.entity.Question;
 import com.qxgmat.data.dao.entity.QuestionNo;
 import com.qxgmat.data.dao.entity.UserCollectQuestion;
-import com.qxgmat.data.dao.entity.UserNote;
+import com.qxgmat.data.dao.entity.UserNoteQuestion;
 import com.qxgmat.data.relation.UserNoteRelationMapper;
 import com.qxgmat.data.relation.entity.UserNoteRelation;
 import com.qxgmat.service.inline.QuestionNoService;
@@ -29,11 +29,11 @@ import java.util.Collection;
 import java.util.List;
 
 @Service
-public class UserNoteService extends AbstractService {
-    private static final Logger logger = LoggerFactory.getLogger(UserNoteService.class);
+public class UserNoteQuestionService extends AbstractService {
+    private static final Logger logger = LoggerFactory.getLogger(UserNoteQuestionService.class);
 
     @Resource
-    private UserNoteMapper userNoteMapper;
+    private UserNoteQuestionMapper userNoteQuestionMapper;
 
     @Resource
     private UserNoteRelationMapper userNoteRelationMapper;
@@ -60,14 +60,14 @@ public class UserNoteService extends AbstractService {
     public PageResult<UserNoteRelation> list(int page, int size, Integer userId, QuestionModule module, QuestionType type, String startTime, String endTime, String order, DirectionStatus direction){
         String moduleKey = module == null ? null : module.key;
         String typeKey = type == null ? null : type.key;
-        Page<UserNote> p = page(()->{
+        Page<UserNoteQuestion> p = page(()->{
             userNoteRelationMapper.list(userId, moduleKey, typeKey, startTime, endTime, order, direction.key);
         }, page, size);
 
-        Collection ids = Transform.getIds(p, UserNote.class, "id");
+        Collection ids = Transform.getIds(p, UserNoteQuestion.class, "id");
 
         // 获取详细数据
-        List<UserNote> list = select(ids);
+        List<UserNoteQuestion> list = select(ids);
 
         List<UserNoteRelation> pr = Transform.convert(list, UserNoteRelation.class);
 
@@ -90,18 +90,19 @@ public class UserNoteService extends AbstractService {
      * @return
      */
     @Transactional
-    public UserNote update(UserNote note){
+    public UserNoteQuestion update(UserNoteQuestion note){
         Example example = new Example(UserCollectQuestion.class);
         example.and(
                 example.createCriteria()
                         .andEqualTo("userId", note.getUserId())
+                        .andEqualTo("module", note.getModule())
         );
         example.and(
                 example.createCriteria()
                         .orEqualTo("questionId", note.getQuestionId())
                         .orEqualTo("questionNoId", note.getQuestionNoId())
         );
-        UserNote in = one(userNoteMapper, example);
+        UserNoteQuestion in = one(userNoteQuestionMapper, example);
         if(in == null){
             return add(note);
         }else{
@@ -110,35 +111,35 @@ public class UserNoteService extends AbstractService {
         }
     }
 
-    public UserNote add(UserNote note){
-        int result = insert(userNoteMapper, note);
-        note = one(userNoteMapper, note.getId());
+    public UserNoteQuestion add(UserNoteQuestion note){
+        int result = insert(userNoteQuestionMapper, note);
+        note = one(userNoteQuestionMapper, note.getId());
         if(note == null){
             throw new SystemException("笔记添加失败");
         }
         return note;
     }
 
-    public UserNote edit(UserNote note){
-        UserNote in = one(userNoteMapper, note.getId());
+    public UserNoteQuestion edit(UserNoteQuestion note){
+        UserNoteQuestion in = one(userNoteQuestionMapper, note.getId());
         if(in == null){
             throw new ParameterException("笔记不存在");
         }
-        int result = update(userNoteMapper, note);
+        int result = update(userNoteQuestionMapper, note);
         return note;
     }
 
     public boolean delete(Number id){
-        UserNote in = one(userNoteMapper, id);
+        UserNoteQuestion in = one(userNoteQuestionMapper, id);
         if(in == null){
             throw new ParameterException("笔记不存在");
         }
-        int result = delete(userNoteMapper, id);
+        int result = delete(userNoteQuestionMapper, id);
         return result > 0;
     }
 
-    public UserNote get(Number id){
-        UserNote in = one(userNoteMapper, id);
+    public UserNoteQuestion get(Number id){
+        UserNoteQuestion in = one(userNoteQuestionMapper, id);
 
         if(in == null){
             throw new ParameterException("笔记不存在");
@@ -146,12 +147,12 @@ public class UserNoteService extends AbstractService {
         return in;
     }
 
-    public Page<UserNote> select(int page, int pageSize){
-        return select(userNoteMapper, page, pageSize);
+    public Page<UserNoteQuestion> select(int page, int pageSize){
+        return select(userNoteQuestionMapper, page, pageSize);
     }
 
-    public List<UserNote> select(Collection ids){
-        return select(userNoteMapper, ids);
+    public List<UserNoteQuestion> select(Collection ids){
+        return select(userNoteQuestionMapper, ids);
     }
 
 }

+ 67 - 22
server/gateway-api/src/main/java/com/qxgmat/service/UserPaperService.java

@@ -1,5 +1,6 @@
 package com.qxgmat.service;
 
+import com.alibaba.fastjson.JSONObject;
 import com.github.pagehelper.Page;
 import com.nuliji.tools.AbstractService;
 import com.nuliji.tools.PageResult;
@@ -11,11 +12,15 @@ import com.qxgmat.data.constants.enums.module.PaperModule;
 import com.qxgmat.data.constants.enums.status.DirectionStatus;
 import com.qxgmat.data.dao.UserPaperMapper;
 import com.qxgmat.data.dao.entity.UserPaper;
+import com.qxgmat.data.dao.entity.UserReport;
 import com.qxgmat.data.relation.UserPaperRelationMapper;
+import com.qxgmat.service.annotation.InitPaper;
+import com.qxgmat.service.inline.UserReportService;
 import com.qxgmat.util.annotation.Callback;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.util.Collection;
@@ -35,34 +40,67 @@ public class UserPaperService extends AbstractService {
     private UserPaperRelationMapper userPaperRelationMapper;
 
     @Resource
-    private ExercisePaperService exercisePaperService;
-
-    @Resource
-    private HomeworkPreviewService homeworkPreviewService;
+    private UserReportService userReportService;
+
+    /**
+     * 获取报告列表:以paper进行分组
+     * @param page
+     * @param size
+     * @param userId
+     * @param module
+     * @param type
+     * @param startTime
+     * @param endTime
+     * @param order
+     * @param direction
+     * @return
+     */
+    public PageResult<UserPaper> list(int page, int size, Integer userId, PaperModule module, QuestionType type, String startTime, String endTime, String order, DirectionStatus direction){
 
-    @Resource
-    private ExaminationPaperService examinationPaperService;
-
-    private Map<PaperModule, Callback> finishCallback;
-
-    public UserPaperService(){
-        finishCallback = new HashMap<>();
-        finishCallback.put(PaperModule.EXERCISE, (obj)->{
-            return exercisePaperService.finished((UserPaper) obj);
-        });
-        finishCallback.put(PaperModule.HOMEWORK_PREVIEW, (obj)->{
-            return homeworkPreviewService.finished((UserPaper) obj);
-        });
-        finishCallback.put(PaperModule.EXAMINATION, (obj)->{
-            return homeworkPreviewService.finished((UserPaper) obj);
-        });
+        return new PageResult<>(null, 0);
     }
 
-    public PageResult<UserPaper> list(int page, int size, Integer userId, PaperModule module, QuestionType type, String startTime, String endTime, String order, DirectionStatus direction){
+    public UserPaper getByPaper(Integer userId, PaperModule module, Integer paperId, InitPaper IInitPaper){
+        // 查找对应的paper是否有,没有则添加
+        Example example = new Example(UserPaper.class);
+        example.and(
+                example.createCriteria()
+                        .andEqualTo("userId", userId)
+                        .andEqualTo("module", module.key)
+                        .andEqualTo("module_id", paperId)
+        );
+        UserPaper paper = one(userPaperMapper, example);
+        if (paper == null){
+            paper = UserPaper.builder().userId(userId).module(module.key).moduleId(paperId).build();
+            // 回调,根据模块更新设置
+            IInitPaper.callback(paper, paperId);
+            paper = add(paper);
+        }
+        return paper;
+    }
 
-        return new PageResult<>(null, 0);
+    /**
+     * 重置做题信息:不自动关联最后次做题记录
+     * @param id
+     * @return
+     */
+    public Boolean reset(Integer id, Integer userId){
+        Example example = new Example(UserPaper.class);
+        example.and(
+                example.createCriteria()
+                        .andEqualTo("id", id)
+                        .andEqualTo("userId", userId)
+        );
+        return update(userPaperMapper, example, UserPaper.builder().isReset(1).build()) > 0;
     }
 
+    /**
+     * 批量删除用户记录:homework切换可用学生
+     * @param userIds
+     * @param module
+     * @param paperId
+     * @return
+     */
     public Boolean removeByUsersAndPaper(Collection<Integer> userIds, PaperModule module, Integer paperId){
         if(userIds.size() == 0) return false;
         Example example = new Example(UserPaper.class);
@@ -75,6 +113,13 @@ public class UserPaperService extends AbstractService {
         return delete(userPaperMapper, example, SOFT_FLAG) > 0;
     }
 
+    /**
+     * 批量修改用户记录:homework更新内容
+     * @param userIds
+     * @param module
+     * @param paperId
+     * @return
+     */
     public Boolean editByUsersAndPaper(UserPaper userPaper, Collection<Integer> userIds, PaperModule module, Integer paperId){
         if(userIds.size() == 0) return false;
         Example example = new Example(UserPaper.class);

+ 9 - 1
server/gateway-api/src/main/java/com/qxgmat/service/inline/UserQuestionService.java

@@ -1,19 +1,27 @@
-package com.qxgmat.service.inline;
+package com.qxgmat.service;
 
+import com.alibaba.fastjson.JSONObject;
 import com.github.pagehelper.Page;
 import com.nuliji.tools.AbstractService;
 import com.nuliji.tools.PageResult;
 import com.nuliji.tools.exception.ParameterException;
 import com.nuliji.tools.exception.SystemException;
+import com.qxgmat.data.constants.enums.module.QuestionModule;
 import com.qxgmat.data.dao.UserQuestionMapper;
 import com.qxgmat.data.dao.entity.UserQuestion;
+import com.qxgmat.service.inline.QuestionNoService;
+import com.qxgmat.service.inline.SentenceQuestionService;
+import com.qxgmat.util.annotation.Callback;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 @Service
 public class UserQuestionService extends AbstractService {

+ 1 - 0
server/gateway-api/src/main/java/com/qxgmat/service/UsersService.java

@@ -43,6 +43,7 @@ public class UsersService extends AbstractService {
 
     @Value("${self.secret}")
     private String secret;
+
     private NativeJsonHandler<UserToken> tokenHandler = new NativeJsonHandler<UserToken>(UserToken.class);
 
     @Resource

+ 12 - 0
server/gateway-api/src/main/java/com/qxgmat/service/annotation/InitPaper.java

@@ -0,0 +1,12 @@
+package com.qxgmat.service.annotation;
+
+
+import com.qxgmat.data.dao.entity.UserPaper;
+
+/**
+ * Created by gaojie on 2017/11/20.
+ */
+@FunctionalInterface
+public interface InitPaper {
+    void callback(UserPaper paper, Integer pager);
+}

+ 13 - 0
server/gateway-api/src/main/java/com/qxgmat/service/annotation/InitReport.java

@@ -0,0 +1,13 @@
+package com.qxgmat.service.annotation;
+
+
+import com.qxgmat.data.dao.entity.UserPaper;
+import com.qxgmat.data.dao.entity.UserReport;
+
+/**
+ * Created by gaojie on 2017/11/20.
+ */
+@FunctionalInterface
+public interface InitReport {
+    void callback(UserPaper paper, UserReport report);
+}

+ 217 - 0
server/gateway-api/src/main/java/com/qxgmat/service/extend/QuestionFlowService.java

@@ -0,0 +1,217 @@
+package com.qxgmat.service.extend;
+
+import com.alibaba.fastjson.JSONObject;
+import com.nuliji.tools.exception.ParameterException;
+import com.qxgmat.data.constants.enums.SettingKey;
+import com.qxgmat.data.constants.enums.module.PaperModule;
+import com.qxgmat.data.constants.enums.module.QuestionModule;
+import com.qxgmat.data.dao.entity.UserPaper;
+import com.qxgmat.data.dao.entity.UserQuestion;
+import com.qxgmat.data.dao.entity.UserReport;
+import com.qxgmat.data.relation.entity.QuestionNoRelation;
+import com.qxgmat.service.*;
+import com.qxgmat.service.annotation.InitPaper;
+import com.qxgmat.service.annotation.InitReport;
+import com.qxgmat.service.inline.QuestionNoService;
+import com.qxgmat.service.inline.SentenceQuestionService;
+import com.qxgmat.service.inline.UserReportService;
+import com.qxgmat.util.annotation.Callback;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class QuestionFlowService {
+
+    @Resource
+    private ExercisePaperService exercisePaperService;
+
+    @Resource
+    private HomeworkPreviewService homeworkPreviewService;
+
+    @Resource
+    private ExaminationPaperService examinationPaperService;
+
+    @Resource
+    private QuestionNoService questionNoService;
+
+    @Resource
+    private SentenceQuestionService sentenceQuestionService;
+
+    @Resource
+    private SentencePaperService sentencePaperService;
+
+    @Resource
+    private UserReportService userReportService;
+
+    @Resource
+    private UserPaperService userPaperService;
+
+    @Resource
+    private UserQuestionService userQuestionService;
+
+    @Resource
+    private ToolsService toolsService;
+
+    // 初始化试卷的callback,根据试卷模块进行后续处理
+    private Map<PaperModule, InitPaper> initPaperCallback;
+
+    // 初始化报告的callback,根据设置进行后续处理
+    private Map<PaperModule, InitReport> initReportCallback;
+
+    // 完成试卷的callback,根据试卷模块进行后续处理
+    private Map<PaperModule, Callback> finishCallback;
+
+    // 提交答题的callback,根据试题模块进行后续处理
+    private Map<QuestionModule, Callback> submitCallback;
+
+    public QuestionFlowService(){
+        initPaperCallback = new HashMap<>();
+        initPaperCallback.put(PaperModule.EXERCISE, (paper, id)->{
+           exercisePaperService.initUserPaper(paper, id);
+            // 获取考题时间
+            List<QuestionNoRelation> relationList = questionNoService.listByIds(paper.getQuestionNoIds());
+            Integer time = toolsService.computerTime(SettingKey.EXERCISE_TIME, relationList);
+            paper.setTime(time);
+        });
+        initPaperCallback.put(PaperModule.HOMEWORK_PREVIEW, (paper, id)->{
+            // 后台主动修改,无需变更
+        });
+        initPaperCallback.put(PaperModule.ERROR, (paper, id)->{
+            // 用户主动添加,无需变更
+        });
+        initPaperCallback.put(PaperModule.COLLECT, (paper, id)->{
+            // 用户主动添加,无需变更
+        });
+        initPaperCallback.put(PaperModule.SENTENCE, (paper, id)->{
+            sentencePaperService.initUserPaper(paper, id);
+        });
+
+        initReportCallback = new HashMap<>();
+        initReportCallback.put(PaperModule.EXERCISE, (paper, report)->{
+            JSONObject setting = report.getSetting();
+            if (setting.getBoolean("disorder")){
+                // 随机试题
+                report.setQuestionNoIds(this.RandomQuestionNoIds(paper.getQuestionNoIds()));
+            }
+        });
+        initReportCallback.put(PaperModule.HOMEWORK_PREVIEW, (paper, report)->{
+            JSONObject setting = report.getSetting();
+            if (setting.getBoolean("disorder")){
+                // 随机试题
+                report.setQuestionNoIds(this.RandomQuestionNoIds(paper.getQuestionNoIds()));
+            }
+        });
+        initReportCallback.put(PaperModule.COLLECT, (paper, report)->{
+            JSONObject setting = report.getSetting();
+            if (setting.getBoolean("disorder")){
+                // 随机试题
+                report.setQuestionNoIds(this.RandomQuestionNoIds(paper.getQuestionNoIds()));
+            }
+        });
+        initReportCallback.put(PaperModule.ERROR, (paper, report)->{
+            JSONObject setting = report.getSetting();
+            if (setting.getBoolean("disorder")){
+                // 随机试题
+                report.setQuestionNoIds(this.RandomQuestionNoIds(paper.getQuestionNoIds()));
+            }
+        });
+        initReportCallback.put(PaperModule.SENTENCE, (paper, report)->{
+            // 无特殊设置
+        });
+
+        finishCallback = new HashMap<>();
+        finishCallback.put(PaperModule.EXERCISE, (obj)->{
+            return exercisePaperService.finished((UserPaper) obj);
+        });
+        finishCallback.put(PaperModule.HOMEWORK_PREVIEW, (obj)->{
+            return homeworkPreviewService.finished((UserPaper) obj);
+        });
+        finishCallback.put(PaperModule.EXAMINATION, (obj)->{
+            return homeworkPreviewService.finished((UserPaper) obj);
+        });
+
+        submitCallback = new HashMap<>();
+        submitCallback.put(QuestionModule.BASE, (obj)->{
+            // 更新题目及题目编号统计
+            return questionNoService.submit((UserQuestion) obj);
+        });
+        submitCallback.put(QuestionModule.SENTENCE, (obj)->{
+            // 更新题目及题目编号统计
+            return sentenceQuestionService.submit((UserQuestion) obj);
+        });
+    }
+
+
+    /**
+     * 开始新一轮做题
+     * @param userId
+     * @param module
+     * @param paperId
+     * @param setting
+     * @return
+     */
+    @Transactional
+    public UserReport start(Integer userId, PaperModule module, Integer paperId, JSONObject setting){
+        UserPaper paper = userPaperService.getByPaper(userId, module, paperId, initPaperCallback.get(module));
+        // 查找对应的report是否有,如果没有或reset为1,则添加
+        if (paper.getIsReset() > 0) {
+            paper.setIsReset(0);
+            userPaperService.edit(paper);
+        }
+        // 记录考试设置
+        UserReport report = userReportService.addByPaper(paper, setting, initReportCallback.get(module));
+        return report;
+    }
+
+    public UserQuestion next(Integer userId, Integer userReportId){
+        // 查找未完成的questionid
+
+        // 创建新的question
+        return null;
+    }
+
+    @Transactional
+    public Boolean submit(Integer userId, Integer userQuestionId, JSONObject answer){
+        UserQuestion userQuestion = userQuestionService.get(userQuestionId);
+        if (!userQuestion.getUserId().equals(userId)){
+            throw new ParameterException("题目不存在");
+        }
+        UserReport userReport = userReportService.get(userQuestion.getReportId());
+        // 判断题目是否正确
+        // 更新做题记录
+
+        QuestionModule module = QuestionModule.WithPaper(PaperModule.ValueOf(userReport.getModule()));
+        Callback callback = submitCallback.get(module);
+        callback.callback(userQuestion);
+        return true;
+    }
+
+    @Transactional
+    public Boolean finish(Integer userId, Integer userReportId){
+        return true;
+    }
+
+    public Boolean restart(Integer paperId, Integer userId){
+        return userPaperService.reset(paperId, userId);
+    }
+
+    /**
+     * 乱序生成题目列表
+     * @param questionNoIds
+     * @return
+     */
+    private Integer[] RandomQuestionNoIds(Integer[] questionNoIds){
+        Integer[] ran = new Integer[questionNoIds.length];
+        List<Integer> base = Arrays.stream(questionNoIds).collect(Collectors.toList());
+        int length = base.size();
+        for(int i = 0; i < ran.length; i++){
+            ran[i] = base.remove((int)(Math.random()*length));
+            length -= 1;
+        }
+        return ran;
+    }
+}

+ 6 - 6
server/gateway-api/src/main/java/com/qxgmat/service/extend/TradeService.java

@@ -35,20 +35,20 @@ public class TradeService extends AbstractService {
     @Resource
     private UserClassService userClassService;
 
-    private Map<PayModule, Callback> registerCallback;
+    private Map<PayModule, Callback> payCallback;
 
     public TradeService(){
-        registerCallback = new HashMap<>();
-        registerCallback.put(PayModule.SERVICE, (pay)->{
+        payCallback = new HashMap<>();
+        payCallback.put(PayModule.SERVICE, (pay)->{
             return userServiceService.payed((Pay)pay);
         });
-        registerCallback.put(PayModule.CLASS, (pay)->{
+        payCallback.put(PayModule.CLASS, (pay)->{
             return userClassService.payed((Pay)pay);
         });
     }
 
     public Pay pay(Number userId, String subject, String body, String module, String moduleExtend, BigDecimal money, PayType payType, HttpServletRequest request){
-        if(!registerCallback.containsKey(module))
+        if(!payCallback.containsKey(module))
             throw new ParameterException("不支持的支付模块");
 
         Pay pay = Pay.builder()
@@ -92,7 +92,7 @@ public class TradeService extends AbstractService {
                 || pay.getTradeStatus() == TradeStatus.CLOSE.index)
             throw new ParameterException("该支付无效");
 
-        Callback callback = registerCallback.get(pay.getModule());
+        Callback callback = payCallback.get(pay.getModule());
         try {
             boolean r = callback.callback(pay);
             if (!r)

+ 6 - 0
server/gateway-api/src/main/java/com/qxgmat/service/inline/QuestionNoService.java

@@ -11,6 +11,7 @@ import com.qxgmat.data.constants.enums.status.DirectionStatus;
 import com.qxgmat.data.dao.QuestionNoMapper;
 import com.qxgmat.data.dao.entity.Question;
 import com.qxgmat.data.dao.entity.QuestionNo;
+import com.qxgmat.data.dao.entity.UserQuestion;
 import com.qxgmat.data.inline.PaperStat;
 import com.qxgmat.data.relation.QuestionNoRelationMapper;
 import com.qxgmat.data.relation.entity.QuestionNoRelation;
@@ -36,6 +37,11 @@ public class QuestionNoService extends AbstractService {
     @Resource
     private QuestionService questionService;
 
+    // 完成一次
+    public boolean submit(UserQuestion userQuestion){
+
+        return true;
+    }
     /**
      * 根据题干搜索相似题目
      * @param page

+ 6 - 0
server/gateway-api/src/main/java/com/qxgmat/service/inline/SentenceQuestionService.java

@@ -10,6 +10,7 @@ import com.qxgmat.data.dao.SentenceQuestionMapper;
 import com.qxgmat.data.dao.entity.Manager;
 import com.qxgmat.data.dao.entity.Question;
 import com.qxgmat.data.dao.entity.SentenceQuestion;
+import com.qxgmat.data.dao.entity.UserQuestion;
 import com.qxgmat.data.relation.entity.SentenceQuestionRelation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -29,6 +30,11 @@ public class SentenceQuestionService extends AbstractService {
     @Resource
     private QuestionService questionService;
 
+    // 完成一次
+    public boolean submit(UserQuestion userQuestion){
+
+        return true;
+    }
     /**
      * 根据长难句题目关系,获取完整题目:列表
      * @param p

+ 16 - 1
server/gateway-api/src/main/java/com/qxgmat/service/inline/UserMessageService.java

@@ -39,7 +39,7 @@ public class UserMessageService  extends AbstractService {
      * 清除用户消息状态
      * @param userId
      */
-    public void clear(Number userId){
+    public void clearAll(Number userId){
         Example example = new Example(UserMessage.class);
         example.and(
                 example.createCriteria().andEqualTo("userId", userId)
@@ -47,6 +47,21 @@ public class UserMessageService  extends AbstractService {
         update(userMessageMapper, example, UserMessage.builder().isRead(1).build());
     }
 
+    /**
+     * 清楚单条消息状态
+     * @param userId
+     * @param id
+     */
+    public void clear(Number userId, Integer id){
+        Example example = new Example(UserMessage.class);
+        example.and(
+                example.createCriteria()
+                        .andEqualTo("userId", userId)
+                        .andEqualTo("id", id)
+        );
+        update(userMessageMapper, example, UserMessage.builder().isRead(1).build());
+    }
+
     public UserMessage add(UserMessage message){
         int result = insert(userMessageMapper, message);
         message = one(userMessageMapper, message.getId());

+ 0 - 2
server/gateway-api/src/main/java/com/qxgmat/service/inline/UserPayService.java

@@ -6,9 +6,7 @@ import com.nuliji.tools.exception.ParameterException;
 import com.nuliji.tools.exception.SystemException;
 import com.nuliji.tools.mybatis.Example;
 import com.qxgmat.data.constants.enums.module.PayModule;
-import com.qxgmat.data.dao.UserNoteMapper;
 import com.qxgmat.data.dao.UserPayMapper;
-import com.qxgmat.data.dao.entity.UserNote;
 import com.qxgmat.data.dao.entity.UserPay;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

+ 25 - 0
server/gateway-api/src/main/java/com/qxgmat/service/inline/UserReportService.java

@@ -1,5 +1,6 @@
 package com.qxgmat.service.inline;
 
+import com.alibaba.fastjson.JSONObject;
 import com.github.pagehelper.Page;
 import com.nuliji.tools.AbstractService;
 import com.nuliji.tools.Transform;
@@ -8,10 +9,13 @@ import com.nuliji.tools.exception.SystemException;
 import com.nuliji.tools.mybatis.Example;
 import com.qxgmat.data.dao.UserQuestionMapper;
 import com.qxgmat.data.dao.UserReportMapper;
+import com.qxgmat.data.dao.entity.UserPaper;
 import com.qxgmat.data.dao.entity.UserQuestion;
 import com.qxgmat.data.dao.entity.UserReport;
 import com.qxgmat.data.relation.UserReportRelationMapper;
 import com.qxgmat.data.relation.entity.UserHomeworkPreviewRelation;
+import com.qxgmat.service.annotation.InitPaper;
+import com.qxgmat.service.annotation.InitReport;
 import com.qxgmat.util.shiro.UserRealm;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -58,6 +62,27 @@ public class UserReportService extends AbstractService {
         return relationMap;
     }
 
+    /**
+     * 根据用户paper生成一份新的report记录
+     * @param paper
+     * @param setting
+     * @param IInitReport
+     * @return
+     */
+    public UserReport addByPaper(UserPaper paper, JSONObject setting, InitReport IInitReport){
+        UserReport report = UserReport.builder()
+                .module(paper.getModule())
+                .moduleId(paper.getModuleId())
+                .setting(setting)
+                .userId(paper.getUserId())
+                .paperId(paper.getId())
+                .questionNoIds(paper.getQuestionNoIds())
+                .build();
+        // 回调,根据模块更新设置
+        IInitReport.callback(paper, report);
+        return add(report);
+    }
+
     public UserReport add(UserReport report){
         int result = insert(userReportMapper, report);
         report = one(userReportMapper, report.getId());