Przeglądaj źródła

fix(front): 交互

Go 4 lat temu
rodzic
commit
6847240819
73 zmienionych plików z 512 dodań i 197 usunięć
  1. 1 1
      front/project/Constant.js
  2. 1 1
      front/project/admin/routes/course/data/page.js
  3. 1 1
      front/project/admin/routes/course/dataHistory/page.js
  4. 1 1
      front/project/admin/routes/course/experience/page.js
  5. 1 1
      front/project/admin/routes/course/invoice/page.js
  6. 2 2
      front/project/admin/routes/interaction/askQuestion/page.js
  7. 6 5
      front/project/admin/routes/interaction/askQuestionDetail/page.js
  8. 1 1
      front/project/admin/routes/interaction/comment/page.js
  9. 2 2
      front/project/admin/routes/interaction/faq/page.js
  10. 3 3
      front/project/admin/routes/interaction/feedback/page.js
  11. 1 1
      front/project/admin/routes/ready/article/page.js
  12. 1 1
      front/project/admin/routes/ready/feedback/page.js
  13. 1 1
      front/project/admin/routes/ready/read/page.js
  14. 2 2
      front/project/admin/routes/show/comment/page.js
  15. 3 3
      front/project/admin/routes/show/faq/page.js
  16. 1 1
      front/project/admin/routes/show/message/page.js
  17. 2 2
      front/project/admin/routes/student/askCourse/page.js
  18. 4 3
      front/project/admin/routes/student/askCourseDetail/page.js
  19. 2 2
      front/project/admin/routes/student/askQuestion/page.js
  20. 6 5
      front/project/admin/routes/student/askQuestionDetail/page.js
  21. 1 1
      front/project/admin/routes/student/study/page.js
  22. 1 1
      front/project/admin/routes/subject/examination/page.js
  23. 1 1
      front/project/admin/routes/subject/exercise/page.js
  24. 30 16
      front/project/admin/routes/subject/question/page.js
  25. 1 1
      front/project/admin/routes/subject/textbook/page.js
  26. 1 1
      front/project/admin/routes/textbook/feedback/page.js
  27. 2 2
      front/project/admin/routes/user/abnormal/page.js
  28. 4 4
      front/project/admin/routes/user/detail/page.js
  29. 2 2
      front/project/admin/routes/user/list/page.js
  30. 2 2
      front/project/admin/routes/user/order/page.js
  31. 2 2
      front/project/admin/routes/user/orderDetail/page.js
  32. 5 5
      front/project/admin/routes/user/recordAll/page.js
  33. 2 2
      front/project/admin/routes/user/recordBuy/page.js
  34. 2 2
      front/project/admin/routes/user/student/page.js
  35. 1 1
      front/project/h5/components/Item/index.js
  36. 1 1
      front/project/h5/routes/page/identity/page.js
  37. 3 3
      front/project/h5/routes/page/open/page.js
  38. 1 1
      front/project/h5/routes/page/study/page.js
  39. 1 1
      front/project/h5/routes/product/dataDetail/page.js
  40. 1 1
      front/project/h5/routes/product/dataHistory/page.js
  41. 1 1
      front/project/h5/routes/textbook/main/page.js
  42. 1 1
      front/project/www/components/Answer/index.js
  43. 1 1
      front/project/www/components/Continue/index.js
  44. 1 1
      front/project/www/components/Item/index.js
  45. 2 2
      front/project/www/components/Other/index.js
  46. 4 3
      front/project/www/routes/course/data/page.js
  47. 10 10
      front/project/www/routes/my/collect/page.js
  48. 5 5
      front/project/www/routes/my/error/page.js
  49. 2 2
      front/project/www/routes/my/note/page.js
  50. 2 2
      front/project/www/routes/my/tools/page.js
  51. 2 3
      front/project/www/routes/paper/process/base/index.js
  52. 82 36
      front/project/www/routes/paper/question/detail/index.js
  53. 54 6
      front/project/www/routes/paper/question/detail/index.less
  54. 3 3
      front/project/www/routes/paper/report/page.js
  55. 2 0
      server/data/src/main/java/com/qxgmat/data/constants/enums/status/AnswerStatus.java
  56. 5 7
      server/data/src/main/java/com/qxgmat/data/relation/mapping/CourseDataHistoryRelationMapper.xml
  57. 2 2
      server/data/src/main/java/com/qxgmat/data/relation/mapping/UserPaperQuestionRelationMapper.xml
  58. 1 1
      server/data/src/main/resources/db/migration/V1__init_table.sql
  59. 3 1
      server/gateway-api/src/main/java/com/qxgmat/controller/admin/CourseController.java
  60. 1 1
      server/gateway-api/src/main/java/com/qxgmat/controller/admin/QuestionController.java
  61. 1 0
      server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java
  62. 10 0
      server/gateway-api/src/main/java/com/qxgmat/dto/admin/request/ExerciseStructDto.java
  63. 51 0
      server/gateway-api/src/main/java/com/qxgmat/dto/admin/response/UserAskQuestionDetailDto.java
  64. 60 0
      server/gateway-api/src/main/java/com/qxgmat/dto/admin/response/UserAskQuestionListDto.java
  65. 20 0
      server/gateway-api/src/main/java/com/qxgmat/dto/admin/response/UserFeedbackErrorInfoDto.java
  66. 1 1
      server/gateway-api/src/main/java/com/qxgmat/dto/extend/QuestionBaseExtendDto.java
  67. 21 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/CourseDataListDto.java
  68. 19 8
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserQuestionBaseDto.java
  69. 10 0
      server/gateway-api/src/main/java/com/qxgmat/service/UserPaperService.java
  70. 2 2
      server/gateway-api/src/main/java/com/qxgmat/service/extend/OrderFlowService.java
  71. 25 8
      server/gateway-api/src/main/java/com/qxgmat/service/extend/QuestionFlowService.java
  72. 1 0
      server/gateway-api/src/main/java/com/qxgmat/service/inline/CourseDataHistoryService.java
  73. 1 1
      server/gateway-api/src/main/java/com/qxgmat/service/inline/UserAskQuestionService.java

+ 1 - 1
front/project/Constant.js

@@ -30,7 +30,7 @@ export const AskModule = [{ label: '练习', value: 'exercise' }, { label: '模
 
 export const PaperModule = [{ label: '练习', value: 'exercise' }, { label: '模考', value: 'examination' }, { label: '长难句', value: 'sentence' }, { label: '机经', value: 'textbook' }];
 
-export const RecordSource = [{ label: '银行转账', value: 'bank' }, { label: '微信', value: 'wechat' }, { label: '支付宝', value: 'alipay' }, { label: '实名认证', value: 'real' }, { label: '邀请好友', value: 'invite' }, { label: '备考设置', value: 'prepare' }, { label: '课程赠送', value: 'gift_course' }, { label: '活动赠送', value: 'gift_activity' }, { label: '线下报名', value: 'backend' }];
+export const RecordSource = [{ label: '银行转账', value: 'bank' }, { label: '微信', value: 'wechat' }, { label: '支付宝', value: 'alipay' }, { label: '实名认证', value: 'real' }, { label: '邀请好友', value: 'invite' }, { label: '备考设置', value: 'prepare' }, { label: '课程赠送', value: 'gift_course' }, { label: '活动赠送', value: 'gift_activity' }, { label: '操作赠送', value: 'gift_action' }, { label: '线下报名', value: 'backend' }];
 
 export const RecordBuySource = [{ label: '银行转账', value: 'bank' }, { label: '微信', value: 'wechat' }, { label: '支付宝', value: 'alipay' }];
 

+ 1 - 1
front/project/admin/routes/course/data/page.js

@@ -90,7 +90,7 @@ export default class extends Page {
       sorter: true,
       dataIndex: 'updateTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '操作',

+ 1 - 1
front/project/admin/routes/course/dataHistory/page.js

@@ -60,7 +60,7 @@ export default class extends Page {
       title: '更新时间',
       dataIndex: 'time',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '版本名称',

+ 1 - 1
front/project/admin/routes/course/experience/page.js

@@ -86,7 +86,7 @@ export default class extends Page {
       title: '更新时间',
       dataIndex: 'updateTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '身份',

+ 1 - 1
front/project/admin/routes/course/invoice/page.js

@@ -51,7 +51,7 @@ export default class extends Page {
       title: '申请时间',
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '申请用户',

+ 2 - 2
front/project/admin/routes/interaction/askQuestion/page.js

@@ -111,7 +111,7 @@ export default class extends Page {
       title: '提问时间',
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '回答者',
@@ -121,7 +121,7 @@ export default class extends Page {
       sorter: true,
       dataIndex: 'answerTime',
       render: (text) => {
-        return text ? formatDate(text) : '';
+        return text ? formatDate(text, 'YYYY-MM-DD HH:mm:ss') : '';
       },
     }, {
       title: '回答状态',

+ 6 - 5
front/project/admin/routes/interaction/askQuestionDetail/page.js

@@ -38,7 +38,8 @@ export default class extends Page {
         getFieldDecorator('id');
         getFieldDecorator('answer');
         getFieldDecorator('showStatus');
-        setFieldsValue({ id: result.id, answer: result.answer, showStatus: result.showStatus });
+        getFieldDecorator('content');
+        setFieldsValue({ id: result.id, content: result.content, answer: result.answer, showStatus: result.showStatus });
         this.setState({ data: result });
       });
   }
@@ -106,7 +107,7 @@ export default class extends Page {
           {QuestionTypeMap[question.questionType]}
         </Form.Item>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='题目id'>
-          <a href='' target='_blank'>{questionNo.no}</a>
+          <a href={`/subject/question/${question.id}`} target='_blank'>{questionNo.title}</a>
         </Form.Item>
       </Form>
     </Block>;
@@ -120,10 +121,10 @@ export default class extends Page {
       <h1>提问信息</h1>
       <Form>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='用户姓名'>
-          {user.realName}
+          {user.nickname}
         </Form.Item>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='提问时间'>
-          {formatDate(createTime)}
+          {formatDate(createTime, 'YYYY-MM-DD HH:mm:ss')}
         </Form.Item>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='提问模块'>
           {AskTargetMap[target]}
@@ -157,7 +158,7 @@ export default class extends Page {
           this.orderQuestion(oldIndex, newIndex);
         }}
         renderItem={(item) => (
-          <List.Item actions={[<Icon type='bars' className='icon' />, <Typography.Text copyable={{ text: `${PcUrl}/paper/question/${this.state.data.userQuestionId}?askId=${item.id}` }} />]}>
+          <List.Item actions={[<Icon type='bars' className='icon' />, <Typography.Text copyable={{ text: this.state.data.userQuestionId ? `${PcUrl}/paper/question/${this.state.data.userQuestionId}?askId=${item.id}` : `${PcUrl}/question/detail/${this.state.data.questionNoId}?askId=${item.id}` }} />]}>
             <Row style={{ width: '100%' }}>
               <Col span={11}>问题:<span dangerouslySetInnerHTML={{ __html: item.content }} /></Col>
               <Col span={11} offset={1}>答复:<span dangerouslySetInnerHTML={{ __html: item.answer }} /></Col>

+ 1 - 1
front/project/admin/routes/interaction/comment/page.js

@@ -95,7 +95,7 @@ export default class extends Page {
       sorter: true,
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '展示',

+ 2 - 2
front/project/admin/routes/interaction/faq/page.js

@@ -120,7 +120,7 @@ export default class extends Page {
       sorter: true,
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '提问者',
@@ -139,7 +139,7 @@ export default class extends Page {
       sorter: true,
       dataIndex: 'answerTime',
       render: (text) => {
-        return text ? formatDate(text) : '';
+        return text ? formatDate(text, 'YYYY-MM-DD HH:mm:ss') : '';
       },
     }, {
       title: '展示',

+ 3 - 3
front/project/admin/routes/interaction/feedback/page.js

@@ -118,15 +118,15 @@ export default class extends Page {
       dataIndex: 'title',
     }, {
       title: '勘误区域',
-      dataIndex: 'target',
+      dataIndex: 'position',
       render: (text) => {
-        return AskTargetMap[text] || '';
+        return AskTargetMap[text[0]] || '';
       },
     }, {
       title: '提交时间',
       dataIndex: 'createTime',
       render: (text) => {
-        return text ? formatDate(text) : '-';
+        return text ? formatDate(text, 'YYYY-MM-DD HH:mm:ss') : '-';
       },
     }, {
       title: '用户',

+ 1 - 1
front/project/admin/routes/ready/article/page.js

@@ -108,7 +108,7 @@ export default class extends Page {
       title: '更新时间',
       dataIndex: 'updateTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '操作',

+ 1 - 1
front/project/admin/routes/ready/feedback/page.js

@@ -46,7 +46,7 @@ export default class extends Page {
       title: '提交时间',
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '提交人',

+ 1 - 1
front/project/admin/routes/ready/read/page.js

@@ -40,7 +40,7 @@ export default class extends Page {
       title: '更新时间',
       dataIndex: 'updateTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '操作',

+ 2 - 2
front/project/admin/routes/show/comment/page.js

@@ -129,7 +129,7 @@ export default class extends Page {
       sorter: true,
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '来源',
@@ -191,7 +191,7 @@ export default class extends Page {
     const { search, page } = this.state;
     if (value) {
       search.size = page.total;
-      search.order = 'order';
+      search.order = 'sort';
       search.direction = 'desc';
       search.isSystem = null;
       this.setState({ mode: 'order', search });

+ 3 - 3
front/project/admin/routes/show/faq/page.js

@@ -114,7 +114,7 @@ export default class extends Page {
       sorter: true,
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '来源',
@@ -176,7 +176,7 @@ export default class extends Page {
   changeModel(value) {
     const { search, page } = this.state;
     if (value) {
-      search.order = 'order';
+      search.order = 'sort';
       search.direction = 'desc';
       search.size = page.total;
       search.isSystem = null;
@@ -244,7 +244,7 @@ export default class extends Page {
 
   submit() {
     const { list } = this.state;
-    System.orderComment({ ids: list.map(row => row.id) }).then(() => {
+    System.orderFAQ({ ids: list.map(row => row.id) }).then(() => {
       asyncSMessage('操作成功!');
       this.refresh();
     });

+ 1 - 1
front/project/admin/routes/show/message/page.js

@@ -48,7 +48,7 @@ export default class extends Page {
       title: '发送时间',
       dataIndex: 'sendTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '状态',

+ 2 - 2
front/project/admin/routes/student/askCourse/page.js

@@ -101,7 +101,7 @@ export default class extends Page {
       title: '提问时间',
       dataIndex: 'createTime',
       render: (text) => {
-        return text ? formatDate(text) : '';
+        return text ? formatDate(text, 'YYYY-MM-DD HH:mm:ss') : '';
       },
     }, {
       title: '倒计时',
@@ -124,7 +124,7 @@ export default class extends Page {
       sorter: true,
       dataIndex: 'answerTime',
       render: (text) => {
-        return text ? formatDate(text) : '';
+        return text ? formatDate(text, 'YYYY-MM-DD HH:mm:ss') : '';
       },
     }, {
       title: '回答状态',

+ 4 - 3
front/project/admin/routes/student/askCourseDetail/page.js

@@ -42,7 +42,8 @@ export default class extends Page {
         getFieldDecorator('id');
         getFieldDecorator('answer');
         getFieldDecorator('showStatus');
-        setFieldsValue({ id: result.id, answer: result.answer });
+        getFieldDecorator('content');
+        setFieldsValue({ id: result.id, content: result.content, answer: result.answer });
         this.setState({ data: result });
       });
   }
@@ -121,10 +122,10 @@ export default class extends Page {
       <h1>提问信息</h1>
       <Form>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='用户姓名'>
-          {user.realName}
+          {user.nickname}
         </Form.Item>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='提问时间'>
-          {formatDate(createTime)}
+          {formatDate(createTime, 'YYYY-MM-DD HH:mm:ss')}
         </Form.Item>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='提问位置'>
           {`P${courseNo.no}:${position}-${position + 5}min`}

+ 2 - 2
front/project/admin/routes/student/askQuestion/page.js

@@ -111,7 +111,7 @@ export default class extends Page {
       title: '提问时间',
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '倒计时',
@@ -134,7 +134,7 @@ export default class extends Page {
       sorter: true,
       dataIndex: 'answerTime',
       render: (text) => {
-        return text ? formatDate(text) : '';
+        return text ? formatDate(text, 'YYYY-MM-DD HH:mm:ss') : '';
       },
     }, {
       title: '回答状态',

+ 6 - 5
front/project/admin/routes/student/askQuestionDetail/page.js

@@ -38,7 +38,8 @@ export default class extends Page {
         getFieldDecorator('id');
         getFieldDecorator('answer');
         getFieldDecorator('showStatus');
-        setFieldsValue({ id: result.id, answer: result.answer, showStatus: result.showStatus });
+        getFieldDecorator('content');
+        setFieldsValue({ id: result.id, content: result.content, answer: result.answer, showStatus: result.showStatus });
         this.setState({ data: result });
       });
   }
@@ -103,7 +104,7 @@ export default class extends Page {
           {QuestionTypeMap[question.questionType]}
         </Form.Item>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='题目id'>
-          <a href='' target='_blank'>{questionNo.no}</a>
+          <a href={`/subject/question/${question.id}`} target='_blank'>{questionNo.title}</a>
         </Form.Item>
       </Form>
     </Block>;
@@ -117,10 +118,10 @@ export default class extends Page {
       <h1>提问信息</h1>
       <Form>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='用户姓名'>
-          {user.realName}
+          {user.nickname}
         </Form.Item>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='提问时间'>
-          {formatDate(createTime)}
+          {formatDate(createTime, 'YYYY-MM-DD HH:mm:ss')}
         </Form.Item>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='提问模块'>
           {AskTargetMap[target]}
@@ -154,7 +155,7 @@ export default class extends Page {
           this.orderQuestion(oldIndex, newIndex);
         }}
         renderItem={(item) => (
-          <List.Item actions={[<Icon type='bars' className='icon' />, <Typography.Text copyable={{ text: `${PcUrl}/paper/question/${this.state.data.userQuestionId}?askId=${item.id}` }} />]}>
+          <List.Item actions={[<Icon type='bars' className='icon' />, <Typography.Text copyable={{ text: this.state.data.userQuestionId ? `${PcUrl}/paper/question/${this.state.data.userQuestionId}?askId=${item.id}` : `${PcUrl}/question/detail/${this.state.data.questionNoId}?askId=${item.id}` }} />]}>
             <Row style={{ width: '100%' }}>
               <Col span={11}>问题:<span dangerouslySetInnerHTML={{ __html: item.content }} /></Col>
               <Col span={11} offset={1}>答复:<span dangerouslySetInnerHTML={{ __html: item.answer }} /></Col>

+ 1 - 1
front/project/admin/routes/student/study/page.js

@@ -86,7 +86,7 @@ export default class extends Page {
       title: '上次学习时间',
       dataIndex: 'lastTime',
       render: (text) => {
-        return text ? `${formatDate(text)}` : '';
+        return text ? `${formatDate(text, 'YYYY-MM-DD HH:mm:ss')}` : '';
       },
     }, {
       title: '状态',

+ 1 - 1
front/project/admin/routes/subject/examination/page.js

@@ -120,7 +120,7 @@ export default class extends Page {
       sorter: true,
       dataIndex: 'updateTime',
       render: (text, record) => {
-        return formatDate(record.question.updateTime);
+        return formatDate(record.question.updateTime, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '操作',

+ 1 - 1
front/project/admin/routes/subject/exercise/page.js

@@ -155,7 +155,7 @@ export default class extends Page {
       sorter: true,
       dataIndex: 'updateTime',
       render: (text, record) => {
-        return formatDate(record.question.updateTime);
+        return formatDate(record.question.updateTime, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '操作',

+ 30 - 16
front/project/admin/routes/subject/question/page.js

@@ -56,6 +56,7 @@ export default class extends Page {
         return { value: 'examination', key: 'examination', label: '模考', title: '模考', children: formatTreeData(result.map(row => { row.title = `${row.titleZh}/${row.titleEn}`; return row; }), 'id', 'title', 'parentId') };
       }),
     ]).then(result => {
+      console.log(result);
       this.setState({ moduleStructData: result });
     });
   }
@@ -83,8 +84,16 @@ export default class extends Page {
         if (row.select && row.select.length > 0) {
           for (; this.uuid[index] < row.select.length; this.uuid[index] += 1) {
             keys.push(this.uuid[index]);
-            form.getFieldDecorator(`content.questions[${index}].select[${this.uuid}]`);
-            form.getFieldDecorator(`answer.questions[${index}].${type}[${this.uuid}]`);
+            form.getFieldDecorator(`content.questions[${index}].select[${this.uuid[index]}]`);
+            form.getFieldDecorator(`content.questions[${index}].direction`);
+            form.getFieldDecorator(`content.questions[${index}].first`);
+            form.getFieldDecorator(`content.questions[${index}].second`);
+            if (type === 'double') {
+              form.getFieldDecorator(`answer.questions[${index}].${type}[${this.uuid[index]}][0]`);
+              form.getFieldDecorator(`answer.questions[${index}].${type}[${this.uuid[index]}][1]`);
+            } else {
+              form.getFieldDecorator(`answer.questions[${index}].${type}[${this.uuid[index]}]`);
+            }
           }
         }
         form.getFieldDecorator(`content.questions[${index}].keys`);
@@ -824,38 +833,43 @@ export default class extends Page {
       </Row></List.Item>,
       <DragList
         loading={false}
-        dataSource={keys || []}
+        dataSource={keys.map(key => {
+          return {
+            key,
+          };
+        }) || []}
+        rowKey={'key'}
         handle={'.icon'}
         onMove={(oldIndex, newIndex) => {
           this.orderQuestion(index, oldIndex, newIndex);
         }}
-        renderItem={(k) => (
-          <List.Item actions={[<Icon type='bars' className='icon' />]}>
-            <Row key={k} style={{ width: '100%' }}>
+        renderItem={({ key }) => {
+          return <List.Item actions={[<Icon type='bars' className='icon' />]}>
+            <Row style={{ width: '100%' }}>
               <Col span={4}>
-                {getFieldDecorator(`answer.questions[${index}].double[${k}][0]`, {
+                {getFieldDecorator(`answer.questions[${index}].double[${key}][0]`, {
                   valuePropName: 'checked',
                 })(
                   <Checkbox onChange={(e) => {
-                    this.changeDouble(index, k, 0, e.target.checkedue);
+                    this.changeDouble(index, key, 0, e.target.checked);
                   }} />,
                 )}
               </Col>
               <Col span={4} offset={1}>
-                {getFieldDecorator(`answer.questions[${index}].double[${k}][1]`, {
+                {getFieldDecorator(`answer.questions[${index}].double[${key}][1]`, {
                   valuePropName: 'checked',
                 })(
                   <Checkbox onChange={(e) => {
-                    this.changeDouble(index, k, 1, e.target.checked);
+                    this.changeDouble(index, key, 1, e.target.checked);
                   }} />,
                 )}
               </Col>
               <Col span={14} offset={1}>
                 <Form.Item
-                  key={k}
+                  key={key}
                   hidden
                 >
-                  {getFieldDecorator(`content.questions[${index}].select[${k}]`, {
+                  {getFieldDecorator(`content.questions[${index}].select[${key}]`, {
                     rules: [{
                       required: true,
                       whitespace: true,
@@ -868,14 +882,14 @@ export default class extends Page {
                     <Icon
                       type='minus-circle-o'
                       disabled={keys.length === 1}
-                      onClick={() => this.removeQuestion(index, k)}
+                      onClick={() => this.removeQuestion(index, key)}
                     />
                   ) : null}
                 </Form.Item>
               </Col>
             </Row>
-          </List.Item>
-        )}
+          </List.Item>;
+        }}
       />,
       <Form.Item>
         <Button type='dashed' onClick={() => this.addQuestion(index)} >
@@ -894,7 +908,7 @@ export default class extends Page {
     return <Block flex>
       <Form>
         <Form.Item label='官方解析'>
-          {getFieldDecorator('officalContent', {
+          {getFieldDecorator('officialContent', {
           })(
             <Editor placeholder='输入内容' />,
           )}

+ 1 - 1
front/project/admin/routes/subject/textbook/page.js

@@ -74,7 +74,7 @@ export default class extends Page {
       title: '修改时间',
       dataIndex: 'updateTime',
       render: (text, record) => {
-        return formatDate(record.question.updateTime);
+        return formatDate(record.question.updateTime, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '操作',

+ 1 - 1
front/project/admin/routes/textbook/feedback/page.js

@@ -90,7 +90,7 @@ export default class extends Page {
       title: '提交时间',
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '提交人',

+ 2 - 2
front/project/admin/routes/user/abnormal/page.js

@@ -35,7 +35,7 @@ export default class extends Page {
       title: '登录时间',
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '用户id',
@@ -50,7 +50,7 @@ export default class extends Page {
       title: '注册时间',
       dataIndex: 'user.createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '注册ip',

+ 4 - 4
front/project/admin/routes/user/detail/page.js

@@ -30,7 +30,7 @@ export default class extends Page {
       title: '订单时间',
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }, {
       title: '购买',
@@ -158,7 +158,7 @@ export default class extends Page {
             </Col>
             <Col span={12}>
               <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='注册时间'>
-                {data.createTime && formatDate(data.createTime)}
+                {data.createTime && formatDate(data.createTime, 'YYYY-MM-DD HH:mm:ss')}
               </Form.Item>
             </Col>
             <Col span={12}>
@@ -213,7 +213,7 @@ export default class extends Page {
             </Col>
             <Col span={12}>
               <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='出分时间'>
-                {data.prepareScoreTime ? formatDate(data.prepareScoreTime) : ''}
+                {data.prepareScoreTime ? formatDate(data.prepareScoreTime, 'YYYY-MM-DD HH:mm:ss') : ''}
               </Form.Item>
             </Col>
             <Col span={12}>
@@ -241,7 +241,7 @@ export default class extends Page {
       <div className="group">
         <h2>已开通服务</h2>
         {(data.services || []).map(service => {
-          return <p>{ServiceKeyMap[service.service]}: {formatDate(service.startTime)} - {formatDate(service.expireTime)}</p>;
+          return <p>{ServiceKeyMap[service.service]}: {formatDate(service.startTime, 'YYYY-MM-DD HH:mm:ss')} - {formatDate(service.expireTime, 'YYYY-MM-DD HH:mm:ss')}</p>;
         })}
       </div>
       <div className="group">

+ 2 - 2
front/project/admin/routes/user/list/page.js

@@ -50,9 +50,9 @@ export default class extends Page {
             this.timeout = null;
           }
           this.timeout = setTimeout(() => {
-            User.validMobile({ area: this.formF.getFieldValue(), mobile: value }).then(result => {
+            User.validMobile({ area: this.formF.getFieldValue('area'), mobile: value }).then(result => {
               this.mobile = value;
-              this.itemList[1].suffix = !result ? '已注册' : '未注册';
+              this.itemList[2].suffix = !result ? '已注册' : '未注册';
               this.formF.setFieldsValue({ load: true });
             });
           }, 1500);

+ 2 - 2
front/project/admin/routes/user/order/page.js

@@ -58,7 +58,7 @@ export default class extends Page {
       title: '下单时间',
       dataIndex: 'createTime',
       render: (text) => {
-        return text ? formatDate(text) : '';
+        return text ? formatDate(text, 'YYYY-MM-DD HH:mm:ss') : '';
       },
     }, {
       title: '用户姓名',
@@ -85,7 +85,7 @@ export default class extends Page {
       title: '支付时间',
       dataIndex: 'payTime',
       render: (text) => {
-        return text ? formatDate(text) : '';
+        return text ? formatDate(text, 'YYYY-MM-DD HH:mm:ss') : '';
       },
     }, {
       title: '操作',

+ 2 - 2
front/project/admin/routes/user/orderDetail/page.js

@@ -117,10 +117,10 @@ export default class extends Page {
       <h1>订单时间</h1>
       <Form>
         <Form.Item labelCol={{ span: 3 }} wrapperCol={{ span: 16 }} label='提交时间'>
-          {data.createTime ? formatDate(data.createTime) : ''}
+          {data.createTime ? formatDate(data.createTime, 'YYYY-MM-DD HH:mm:ss') : ''}
         </Form.Item>
         <Form.Item labelCol={{ span: 3 }} wrapperCol={{ span: 16 }} label='支付时间'>
-          {data.payTime ? formatDate(data.payTime) : ''}
+          {data.payTime ? formatDate(data.payTime, 'YYYY-MM-DD HH:mm:ss') : ''}
         </Form.Item>
         <Form.Item labelCol={{ span: 3 }} wrapperCol={{ span: 16 }} label='支付方式'>
           {RecordBuySourceMap[data.payMethod] || ''}

+ 5 - 5
front/project/admin/routes/user/recordAll/page.js

@@ -59,9 +59,9 @@ export default class extends Page {
             this.timeout = null;
           }
           this.timeout = setTimeout(() => {
-            User.validMobile({ area: this.formF.getFieldValue(), mobile: value }).then(result => {
+            User.validMobile({ area: this.formF.getFieldValue('area'), mobile: value }).then(result => {
               this.mobile = value;
-              this.serviceList[1].suffix = !result ? '已注册' : '未注册';
+              this.serviceList[2].suffix = !result ? '已注册' : '未注册';
               this.formF.setFieldsValue({ load: true });
             });
           }, 1500);
@@ -110,9 +110,9 @@ export default class extends Page {
             this.timeout = null;
           }
           this.timeout = setTimeout(() => {
-            User.validMobile({ area: this.formF.getFieldValue(), mobile: value }).then(result => {
+            User.validMobile({ area: this.formF.getFieldValue('area'), mobile: value }).then(result => {
               this.mobile = value;
-              this.dataList[1].suffix = !result ? '已注册' : '未注册';
+              this.dataList[2].suffix = !result ? '已注册' : '未注册';
               this.formF.setFieldsValue({ load: true });
             });
           }, 1500);
@@ -201,7 +201,7 @@ export default class extends Page {
       title: '开通时间',
       dataIndex: 'time',
       render: (text, record) => {
-        return `${record.startTime ? formatDate(record.startTime) : ''} - ${record.endTime ? formatDate(record.endTime) : ''} `;
+        return `${record.startTime ? formatDate(record.startTime, 'YYYY-MM-DD HH:mm:ss') : ''} - ${record.endTime ? formatDate(record.endTime, 'YYYY-MM-DD HH:mm:ss') : ''} `;
       },
     }, {
       title: '开通方式',

+ 2 - 2
front/project/admin/routes/user/recordBuy/page.js

@@ -100,7 +100,7 @@ export default class extends Page {
       title: '开通时间',
       dataIndex: 'time',
       render: (text, record) => {
-        return `${record.startTime ? formatDate(record.startTime) : ''} - ${record.endTime ? formatDate(record.endTime) : ''}`;
+        return `${record.startTime ? formatDate(record.startTime, 'YYYY-MM-DD HH:mm:ss') : ''} - ${record.endTime ? formatDate(record.endTime, 'YYYY-MM-DD HH:mm:ss') : ''}`;
       },
     }, {
       title: '开通方式',
@@ -118,7 +118,7 @@ export default class extends Page {
       title: '购买时间',
       dataIndex: 'createTime',
       render: (text) => {
-        return formatDate(text);
+        return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
       },
     }];
     bindSearch(this.filterForm, 'userId', this, (search) => {

+ 2 - 2
front/project/admin/routes/user/student/page.js

@@ -59,7 +59,7 @@ export default class extends Page {
         dataIndex: 'time',
         render: (text, record) => {
           return (record.classes || []).map(row => {
-            return `${formatDate(row.startTime)} - ${formatDate(row.expireTime)}`;
+            return `${formatDate(row.startTime, 'YYYY-MM-DD HH:mm:ss')} - ${formatDate(row.expireTime, 'YYYY-MM-DD HH:mm:ss')}`;
           }).join(<br />);
         },
       },
@@ -67,7 +67,7 @@ export default class extends Page {
         title: '创建时间',
         dataIndex: 'createTime',
         render: (text) => {
-          return formatDate(text);
+          return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
         },
       }, {
         title: '操作',

+ 1 - 1
front/project/h5/components/Item/index.js

@@ -25,7 +25,7 @@ export class CommentItem extends Component {
         <div className="g-comment-item-right">
           <div className="g-comment-item-right-info">
             <div className="g-comment-item-right-info-name">{data.nickname}</div>
-            <div className="g-comment-item-right-info-date">{formatDate(data.createTime, 'YYYY-MM-DD')}</div>
+            <div className="g-comment-item-right-info-date">{data.createTime && formatDate(data.createTime, 'YYYY-MM-DD')}</div>
           </div>
           <div className="g-comment-item-right-desc">{data.content}</div>
         </div>

+ 1 - 1
front/project/h5/routes/page/identity/page.js

@@ -147,7 +147,7 @@ export default class extends Page {
         </div>
         <div className="title">认证完成!</div>
         <div className="desc">90天VIP权限已赠送至您的账户</div>
-        <div className="desc">生效时间:{formatDate(data.useStartTime, 'YYYY-MM-DD')}</div>
+        <div className="desc">生效时间:{data.useStartTime && formatDate(data.useStartTime, 'YYYY-MM-DD')}</div>
       </div>
     );
   }

+ 3 - 3
front/project/h5/routes/page/open/page.js

@@ -62,7 +62,7 @@ export default class extends Page {
           <Assets name="img3" />
         </div>
         <div className="title">您正在开通“{course.data}”</div>
-        <div className="tip">有效期至:{formatDate(endTime, 'YYYY-MM-DD')}</div>
+        <div className="tip">有效期至:{endTime && formatDate(endTime, 'YYYY-MM-DD')}</div>
         <Button block radius onClick={() => {
           this.submit();
         }}>
@@ -84,7 +84,7 @@ export default class extends Page {
           <Assets name="img3" />
         </div>
         <div className="title">您正在开通“{ServiceKeyMap[service]}”服务</div>
-        <div className="tip">有效期至:{formatDate(endTime, 'YYYY-MM-DD')}</div>
+        <div className="tip">有效期至:{endTime && formatDate(endTime, 'YYYY-MM-DD')}</div>
         {service === 'textbook' && <div className="check">
           <Checkbox checked={!!this.state.checked} onClick={() => {
             this.setState({ checked: !this.state.checked });
@@ -112,7 +112,7 @@ export default class extends Page {
           <Icon type="check-circle" />
         </div>
         <div className="title">开通成功!</div>
-        <div className="desc">生效时间:{formatDate(data.useStartTime, 'YYYY-MM-DD')}</div>
+        <div className="desc">生效时间:{data.useStartTime && formatDate(data.useStartTime, 'YYYY-MM-DD')}</div>
       </div>
     );
   }

+ 1 - 1
front/project/h5/routes/page/study/page.js

@@ -30,7 +30,7 @@ export default class extends Page {
       <div>
         <div className="block">
           <div className="text">
-            自{formatDate(total.createTime, 'YYYY-MM-DD')},您已在千行学习<span>{total.days}</span>天
+            自{total.createTime && formatDate(total.createTime, 'YYYY-MM-DD')},您已在千行学习<span>{total.days}</span>天
           </div>
           <div className="text">
             累积<span dangerouslySetInnerHTML={{ __html: formatSeconds(total.time).replace(/([0-9]+)(m|min|h|hour|s)/g, '<span class="s">$1</span>$2') }} />

+ 1 - 1
front/project/h5/routes/product/dataDetail/page.js

@@ -80,7 +80,7 @@ export default class extends Page {
             </div>
             <div className="data">页数: {data.pages}页</div>
             <div className="data">格式: {DataTypeMap[data.dataType]}</div>
-            <div className="data">{formatDate(data.updateTime, 'YYYY-MM-DD HH:mm')} 更新</div>
+            <div className="data">{data.updateTime && formatDate(data.updateTime, 'YYYY-MM-DD HH:mm')} 更新</div>
             <Money value={data.price} size="lager" theme="sell" />
           </div>
         </div>

+ 1 - 1
front/project/h5/routes/product/dataHistory/page.js

@@ -20,7 +20,7 @@ class Item extends Component {
     return (
       <div className="item">
         <div className="title">
-          {data.data.title}<span className="date">{formatDate(data.time, 'YYYY-MM-DD')}</span>
+          {data.data.title}<span className="date">{data.time && formatDate(data.time, 'YYYY-MM-DD')}</span>
         </div>
         <div className="tip">
           变更点:{data.version}

+ 1 - 1
front/project/h5/routes/textbook/main/page.js

@@ -66,7 +66,7 @@ export default class extends Page {
         {list.map(row => {
           return <div className="item">
             <div className="title">
-              版本{row.version}<span className="date">{formatDate(row.createTime)}</span>
+              版本{row.version}<span className="date">{row.createTime && formatDate(row.createTime)}</span>
             </div>
             <div className="desc" dangerouslySetInnerHTML={{ __html: row.content }} />
           </div>;

+ 1 - 1
front/project/www/components/Answer/index.js

@@ -43,7 +43,7 @@ export default class Answer extends Component {
         break;
       case 'portrait':
         double = double.map(row => {
-          row[index] = false;
+          row[column] = false;
           return row;
         });
         break;

+ 1 - 1
front/project/www/components/Continue/index.js

@@ -12,7 +12,7 @@ function Continue(props) {
       <div className="body">
         <div className="left">
           <div className="text">上次做题</div>
-          <div className="date">{formatDate(date)}</div>
+          <div className="date">{date && formatDate(date)}</div>
         </div>
         <div className="center">
           <div className="text">{paper.title} {questionNumber > 0 ? userNumber * 100 / questionNumber : 0}%</div>

+ 1 - 1
front/project/www/components/Item/index.js

@@ -300,7 +300,7 @@ export class TextbookItem extends Component {
           已更新至 <span className="t-4">{data.number}</span> 题
         </div>
         <div className="t-6 t-s-12 m-b-1">
-          {formatDate(data.time, 'YYYY-MM-DD HH:mm:ss')}
+          {data.time && formatDate(data.time, 'YYYY-MM-DD HH:mm:ss')}
           <div className="f-r">
             <More menu={menu} onClick={onMenuClick} />
           </div>

+ 2 - 2
front/project/www/components/Other/index.js

@@ -95,8 +95,8 @@ export class AnswerCarousel extends Component {
             </Carousel>
           )}
           {!tabs && <div className="fixed" />}
-          <Assets name="footer_next_highlight_1" className="next" onClick={() => this.onNext()} />
-          <Assets name="footer_previous_highlight_1" className="prev" onClick={() => this.onPrev()} />
+          <Assets name="footer_next_highlight_1 c-p" className="next" onClick={() => this.onNext()} />
+          <Assets name="footer_previous_highlight_1 c-p" className="prev" onClick={() => this.onPrev()} />
         </div>
         {!hideBtn && (
           <Button size="lager" radius onClick={() => User.needLogin().then(() => onFaq())}>

+ 4 - 3
front/project/www/routes/course/data/page.js

@@ -10,7 +10,7 @@ import Icon from '../../../components/Icon';
 import { DataItem } from '../../../components/Item';
 import UserTable from '../../../components/UserTable';
 import UserPagination from '../../../components/UserPagination';
-import { FeedbackErrorDataModal } from '../../../components/OtherModal';
+import { FeedbackErrorDataModal, FinishModal } from '../../../components/OtherModal';
 import { DataType } from '../../../../Constant';
 import { Main } from '../../../stores/main';
 import { Course } from '../../../stores/course';
@@ -250,7 +250,7 @@ export default class extends Page {
   }
 
   renderTabhistory() {
-    const { all = [], dataId, item = {}, list = [], dataStructMap = {}, showFeedbackError, feedbackError } = this.state;
+    const { all = [], dataId, item = {}, list = [], dataStructMap = {}, showFeedbackError, feedbackError, showFinish } = this.state;
     return [
       <div className="update-search">
         {/* <UserAction search defaultSearch={filterMap.keyword} /> */}
@@ -295,9 +295,10 @@ export default class extends Page {
       <FeedbackErrorDataModal
         show={showFeedbackError}
         defaultData={feedbackError}
-        onConfirm={() => this.setState({ showFeedbackError: false, feedbackError: {} })}
+        onConfirm={() => this.setState({ showFeedbackError: false, feedbackError: {}, showFinish: true })}
         onCancel={() => this.setState({ showFeedbackError: false, feedbackError: {} })}
       />,
+      <FinishModal show={showFinish} onConfirm={() => this.setState({ showFinish: false })} />,
     ];
   }
 }

+ 10 - 10
front/project/www/routes/my/collect/page.js

@@ -244,10 +244,10 @@ export default class extends Page {
           this.setState({ showVip: true });
           return;
         }
-        if (selectList.length < 10) {
-          this.setState({ showWarn: true, warn: { title: '组卷练习', content: '不可小于10题,请重新选择' } });
-          return;
-        }
+        // if (selectList.length < 10) {
+        //   this.setState({ showWarn: true, warn: { title: '组卷练习', content: '不可小于10题,请重新选择' } });
+        //   return;
+        // }
         if (selectList.length > 50) {
           this.setState({ showWarn: true, warn: { title: '组卷练习', content: '不可多余50题,请重新选择' } });
           return;
@@ -256,7 +256,7 @@ export default class extends Page {
           this.setState({ showWarn: true, warn: { title: '组卷练习', content: '不可同时选中语文题和数学题,请重新选择。' } });
           return;
         }
-        this.setState({ showGroupConfirm: true, groupInfo: { questionNoIds: selectList } });
+        this.setState({ showGroupConfirm: true, groupInfo: { questionNoIds: selectList, filterTimes: 2 } });
         break;
       case 'export':
         if (!info.vip) {
@@ -288,7 +288,7 @@ export default class extends Page {
         this.refresh();
       })
       .then(e => {
-        this.setState({ warn: { title: '移除', content: e.message }, showClearConfirm: false });
+        this.setState({ showWarn: true, warn: { title: '移除', content: e.message }, showClearConfirm: false });
       });
   }
 
@@ -300,7 +300,7 @@ export default class extends Page {
         this.setState({ showGroupConfirm: false });
       })
       .catch(e => {
-        this.setState({ warn: { title: '组卷练习', content: e.message }, showGroupConfirm: false });
+        this.setState({ showWarn: true, warn: { title: '组卷练习', content: e.message }, showGroupConfirm: false });
       });
   }
 
@@ -313,7 +313,7 @@ export default class extends Page {
         this.setState({ showExportWait: false });
       })
       .catch(e => {
-        this.setState({ warn: { title: '导出', content: e.message }, showExportWait: false });
+        this.setState({ showWarn: true, warn: { title: '导出', content: e.message }, showExportWait: false });
       });
   }
 
@@ -520,12 +520,12 @@ export default class extends Page {
             theme="white"
             value={groupInfo.filterTimes}
             list={[{ key: 2, title: '2' }, { key: 3, title: '3' }]}
-            onChange={(key) => {
+            onChange={({ key }) => {
               groupInfo.filterTimes = key;
               this.setState({ groupInfo });
             }}
           />{' '}
-          次以上的
+          次以上的题
         </div>
       </Modal>,
       <Modal show={showClearConfirm} title="移出" onConfirm={() => this.clearCollectQuestion()} onCancel={() => this.setState({ showClearConfirm: false })}>

+ 5 - 5
front/project/www/routes/my/error/page.js

@@ -242,7 +242,7 @@ export default class extends Page {
           this.setState({ showWarn: true, warn: { title: '组卷练习', content: '不可同时选中语文题和数学题,请重新选择。' } });
           return;
         }
-        this.setState({ showGroupConfirm: true, groupInfo: { questionNoIds: selectList } });
+        this.setState({ showGroupConfirm: true, groupInfo: { questionNoIds: selectList, filterTimes: 2 } });
         break;
       case 'export':
         if (!info.vip) {
@@ -274,7 +274,7 @@ export default class extends Page {
         this.refresh();
       })
       .catch(e => {
-        this.setState({ warn: { title: '移除', content: e.message }, showClearConfirm: false });
+        this.setState({ showWarn: true, warn: { title: '移除', content: e.message }, showClearConfirm: false });
       });
   }
 
@@ -286,7 +286,7 @@ export default class extends Page {
         this.setState({ showGroupConfirm: false });
       })
       .catch(e => {
-        this.setState({ warn: { title: '组卷练习', content: e.message }, showGroupConfirm: false });
+        this.setState({ showWarn: true, warn: { title: '组卷练习', content: e.message }, showGroupConfirm: false });
       });
   }
 
@@ -299,7 +299,7 @@ export default class extends Page {
         this.setState({ showExportWait: false });
       })
       .catch(e => {
-        this.setState({ warn: { title: '导出', content: e.message }, showExportWait: false });
+        this.setState({ showWarn: true, warn: { title: '导出', content: e.message }, showExportWait: false });
       });
   }
 
@@ -470,7 +470,7 @@ export default class extends Page {
             theme="white"
             value={groupInfo.filterTimes}
             list={[{ key: 2, title: '2' }, { key: 3, title: '3' }]}
-            onChange={(key) => {
+            onChange={({ key }) => {
               groupInfo.filterTimes = key;
               this.setState({ groupInfo });
             }}

+ 2 - 2
front/project/www/routes/my/note/page.js

@@ -336,7 +336,7 @@ export default class extends Page {
         this.refresh();
       })
       .catch(e => {
-        this.setState({ warn: { title: '移除', content: e.message }, showClearConfirm: false });
+        this.setState({ showWarn: true, warn: { title: '移除', content: e.message }, showClearConfirm: false });
       });
   }
 
@@ -349,7 +349,7 @@ export default class extends Page {
         this.setState({ showExportWait: false });
       })
       .catch(e => {
-        this.setState({ warn: { title: '导出', content: e.message }, showExportWait: false });
+        this.setState({ showWarn: true, warn: { title: '导出', content: e.message }, showExportWait: false });
       });
   }
 

+ 2 - 2
front/project/www/routes/my/tools/page.js

@@ -473,7 +473,7 @@ export default class extends Page {
               <Switch
                 checked={info.dataEmailSubscribe}
                 onChange={() => {
-                  this.subscribeEmail(!info.dataEmailSubscribe);
+                  this.subscribeDataEmail(!info.dataEmailSubscribe);
                 }}
               />
             </div>
@@ -510,7 +510,7 @@ export default class extends Page {
                   <span>版本{item.version}</span>
                   {item.title}
                 </div>
-                <div className="date">{formatDate(item.latestTime, 'YYYY-MM-DD HH:mm:ss')}</div>
+                <div className="date">最新更新: {formatDate(item.latestTime, 'YYYY-MM-DD HH:mm:ss')}</div>
                 <More
                   menu={[
                     { label: '纠错', key: 'feedback' },

+ 2 - 3
front/project/www/routes/paper/process/base/index.js

@@ -323,7 +323,7 @@ export default class extends Component {
                 <Assets name="subject_icon" />
                 题目总数
               </div>
-              <div className="desc-info">{paper.questionNumer}</div>
+              <div className="desc-info">{paper.questionNumber}</div>
             </div>
             <div className="block">
               <div className="desc-title">
@@ -521,8 +521,7 @@ export default class extends Component {
             <div className="btn" onClick={() => this.hideModal(true)}>
               <span className="t-d-l">O</span>k
               </div>
-          </div>
-          )}
+          </div>)}
         </div>
       </div>
     );

+ 82 - 36
front/project/www/routes/paper/question/detail/index.js

@@ -54,18 +54,18 @@ export default class extends Component {
   submitAsk() {
     const { userQuestion, questionNo = {} } = this.props;
     const { ask = {} } = this.state;
-    if (ask.originContent === '' || ask.content === '' || ask.target === '') return;
+    if (!ask.originContent || !ask.content || !ask.target) return;
     My.addQuestionAsk(userQuestion.id, ask.target, questionNo.id, ask.originContent, ask.content).then(() => {
-      this.setState({ askModal: false, askOkModal: true });
+      this.setState({ askModal: false, askOkModal: true, ask: {} });
     }).catch(err => {
-      this.setState({ askError: err.message });
+      this.setState({ askError: err.message, ask: {} });
     });
   }
 
   submitFeedbackError() {
     const { questionNo = {} } = this.props;
     const { feedback = {} } = this.state;
-    if (feedback.originContent === '' || feedback.content === '' || feedback.target === '') return;
+    if (!feedback.originContent || !feedback.content || !feedback.target) return;
     My.addFeedbackErrorQuestion(
       questionNo.id,
       questionNo.title,
@@ -74,10 +74,10 @@ export default class extends Component {
       feedback.content,
     )
       .then(() => {
-        this.setState({ feedbackModal: false, feedbackOkModal: true });
+        this.setState({ feedbackModal: false, feedbackOkModal: true, feedback: {} });
       })
       .catch(err => {
-        this.setState({ feedbackError: err.message });
+        this.setState({ feedbackError: err.message, feedback: {} });
       });
   }
 
@@ -152,6 +152,41 @@ export default class extends Component {
     return text;
   }
 
+  formatOtherStem(question) {
+    if (!question.stem) return '';
+    const { content = {}, stem } = question;
+    const { table = {}, questions = [] } = content;
+    let text = stem.replace(/#select#/g, `<span class='#select#${question.id}' />`);
+    text = text.replace(/#table#/g, `<span class='#table#${question.id}' />`);
+    setTimeout(() => {
+      const selectList = document.getElementsByClassName(`#select#${question.id}`);
+      const tableList = document.getElementsByClassName(`#table#${question.id}`);
+      for (let i = 0; i < selectList.length; i += 1) {
+        if (!questions[i]) break;
+        ReactDOM.render(
+          <AnswerSelect
+            list={questions[i].select}
+            type={'single'}
+            // selected={(userQuestion.userAnswer || { questions: [] }).questions[i]}
+            // answer={(question.answer || { questions: [] }).questions[i]}
+            fix
+          // show={showAnswer}
+          />,
+          selectList[i],
+        );
+      }
+      if (table.row && table.col && table.header) {
+        const columns = table.header.map((title, index) => {
+          return { title, key: index };
+        });
+        for (let i = 0; i < tableList.length; i += 1) {
+          ReactDOM.render(<AnswerTable list={columns} columns={columns} data={table.data} />, tableList[i]);
+        }
+      }
+    }, 1);
+    return text;
+  }
+
   render() {
     return (
       <Fullscreen
@@ -271,7 +306,7 @@ export default class extends Component {
           <span className="b">
             <span className="s">{formatPercent(questionNo.totalCorrect, questionNo.totalNumber)}</span>%
           </span>
-          <Icon name="question" />
+          <Icon name="question c-p" />
           <Icon name="star" active={userQuestion.collect} onClick={() => this.toggleCollect()} />
         </div>
       </div>
@@ -319,7 +354,7 @@ export default class extends Component {
                 提问
               </AnswerButton>
             )}
-            <AnswerButton className="item" onClick={() => this.setState({ feedbackModal: true })}>
+            <AnswerButton className="item" onClick={() => this.setState({ feedbackModal: true, feedback: { position: AskTarget[0].value } })}>
               纠错
             </AnswerButton>
           </div>
@@ -369,8 +404,8 @@ export default class extends Component {
     const { typeset = 'one' } = question.content;
     const { hideAnalysis, analysisTab } = this.state;
     const show = typeset === 'one' ? true : !hideAnalysis;
-    return (
-      <div className={`block block-analysis two-analysis ${show ? 'show' : ''}`}>
+    return (<div className="block">
+      <div className={`block-analysis two-analysis ${show ? 'show' : ''}`}>
         <Tabs
           type="division"
           active={analysisTab}
@@ -389,7 +424,7 @@ export default class extends Component {
           {typeset === 'two' && this.renderAnswer()}
           {this.renderText()}
         </div>
-      </div>
+      </div></div>
     );
   }
 
@@ -401,18 +436,18 @@ export default class extends Component {
     switch (analysisTab) {
       case 'official':
         content = (
-          <div className="detail-block text-block" dangerouslySetInnerHTML={{ __html: question.officialContent }} />
+          <div className="detail-block "><div className="block-text" dangerouslySetInnerHTML={{ __html: question.officialContent }} /></div>
         );
         break;
       case 'qx':
-        content = <div className="detail-block text-block" dangerouslySetInnerHTML={{ __html: question.qxContent }} />;
+        content = <div className="detail-block "><div className="block-text" dangerouslySetInnerHTML={{ __html: question.qxContent }} /></div>;
         break;
       case 'association':
         content = (
           <div className="detail-block">
             <Carousel>
               {associations.map(association => {
-                return <div className="text-block" dangerouslySetInnerHTML={{ __html: association.stem }} />;
+                return <div className="block-text" dangerouslySetInnerHTML={{ __html: this.formatOtherStem(association) }} />;
               })}
             </Carousel>
           </div>
@@ -420,10 +455,12 @@ export default class extends Component {
         break;
       case 'qa':
         content = (
-          <div className="detail-block answer-block">
-            {asks.map((ask, index) => {
-              return <OtherAnswer key={index} data={ask} />;
-            })}
+          <div className="detail-block ">
+            <div className="block-answer">
+              {asks.map((ask, index) => {
+                return <OtherAnswer key={index} data={ask} />;
+              })}
+            </div>
           </div>
         );
         break;
@@ -437,9 +474,9 @@ export default class extends Component {
     const { question = { content: {} }, userQuestion = {}, detail } = this.props;
     const { questions = [], type, typeset = 'one' } = question.content;
     const { showAnswer } = this.state;
-    return (
-      <div className="block block-answer">
-        {detail && typeset === 'two' ? (
+    return (<div className="block">
+      <div className="block-answer">
+        {detail && typeset === 'two' && (
           <Switch
             checked={showAnswer}
             onChange={value => {
@@ -448,8 +485,6 @@ export default class extends Component {
           >
             {showAnswer ? '显示答案' : '关闭答案'}
           </Switch>
-        ) : (
-          ''
         )}
         {questions.map((item, index) => {
           return (
@@ -469,7 +504,7 @@ export default class extends Component {
             </div>
           );
         })}
-      </div>
+      </div></div>
     );
   }
 
@@ -478,9 +513,9 @@ export default class extends Component {
     const { typeset = 'one' } = question.content;
     const { steps = [] } = question.content;
     const { showAnswer, step } = this.state;
-    return (
-      <div className="block block-content">
-        {detail && typeset === 'one' && question.questionType !== 'awa' ? (
+    return (<div className="block">
+      <div className="block-content">
+        {detail && typeset === 'one' && question.questionType !== 'awa' && (
           <Switch
             checked={showAnswer}
             onChange={value => {
@@ -489,8 +524,6 @@ export default class extends Component {
           >
             {showAnswer ? '显示答案' : '关闭答案'}
           </Switch>
-        ) : (
-          ''
         )}
         {question.questionType === 'awa' && <h2>Analytical Writing Assessment</h2>}
         {steps.length > 0 && (
@@ -503,18 +536,17 @@ export default class extends Component {
         )}
         <div
           className="text"
-          style={{ height: 2000 }}
           dangerouslySetInnerHTML={{ __html: this.formatStem(steps.length > 0 ? steps[step].stem : question.stem) }}
         />
-      </div>
+      </div></div>
     );
   }
 
   renderAWA() {
     const { userQuestion = { detail: {}, userAnswer: {} } } = this.state;
     const { showAnswer } = this.state;
-    return (
-      <div className="block block-awa">
+    return (<div className="block">
+      <div className="block-awa">
         <Switch
           checked={showAnswer}
           onChange={value => {
@@ -549,7 +581,7 @@ export default class extends Component {
           )}
           {!showAnswer && <div className="show-awa">选择「显示答案」查看自己的作文</div>}
         </div>
-      </div>
+      </div></div>
     );
   }
 
@@ -622,10 +654,11 @@ export default class extends Component {
               <div className="text">关注公众号,老师回答后会立即收到通知。</div>
               <div className="text">我们也会通过站内信的方式通知你。</div>
               <div className="small">
-                成为学员享受极速答疑特权。<Link>了解更多</Link>
+                成为学员享受极速答疑特权。<Link to="">了解更多</Link>
               </div>
             </div>
             <div className="right">
+              <Assets name="qrcode" />
               <div className="text">扫码关注公众号</div>
               <div className="text">千行GMAT</div>
             </div>
@@ -659,6 +692,7 @@ export default class extends Component {
               <Link to="/">了解更多></Link>
             </div>
             <div className="right">
+              <Assets name="qrcode" />
               <div className="text">扫码关注公众号</div>
               <div className="text">千行GMAT</div>
             </div>
@@ -707,9 +741,20 @@ export default class extends Component {
               className="textarea"
               value={feedback.originContent}
               placeholder="你可以适当扩大复制范围以使我们准确定位,感谢。"
+              onChange={(e) => {
+                feedback.originContent = e.target.value;
+                this.setState({ feedback });
+              }}
             />
             <div className="label">应该改为:</div>
-            <textarea className="textarea" placeholder="只需提供正确内容即可" />
+            <textarea
+              className="textarea"
+              value={feedback.content}
+              placeholder="只需提供正确内容即可"
+              onChange={(e) => {
+                feedback.content = e.target.value;
+                this.setState({ feedback });
+              }} />
           </div>
           <div className="bottom">
             <AnswerButton
@@ -751,6 +796,7 @@ export default class extends Component {
               <div className="text">您也可以关注公众号及时获取结果。</div>
             </div>
             <div className="right">
+              <Assets name="qrcode" />
               <div className="text">扫码关注公众号</div>
               <div className="text">千行GMAT</div>
             </div>

+ 54 - 6
front/project/www/routes/paper/question/detail/index.less

@@ -13,10 +13,16 @@
       display: flex;
       flex-direction: row;
 
-      // &.exercise {
-      //   border-top: 20px solid #7775CA;
-      //   background: #fff;
-      // }
+      &.exercise {
+        // border-top: 20px solid #7775CA;
+        // background: #fff;
+
+        // .layout-header {
+        //   height: 60px;
+        //   top: 20px;
+        // }
+        border-top: none;
+      }
 
       // &.sentence {
       //   border-top: 20px solid #435C96;
@@ -197,7 +203,9 @@
 
         .block-content,
         .block-answer,
+        .block-text,
         .block-awa {
+          box-sizing: border-box;
           padding: 30px 60px;
           color: #303036;
           height: 100%;
@@ -268,17 +276,18 @@
 
           .block {
             background: #fff;
+            margin-bottom: 5px;
           }
 
           .detail {
             flex: 1;
             display: flex;
             flex-direction: column;
+            height: 100%;
 
             .detail-block {
-              margin-top: 5px;
+              box-sizing: border-box;
               flex: 1;
-              padding: 30px 50px;
               overflow: hidden;
               overflow-y: auto;
               font-size: 16px;
@@ -286,6 +295,44 @@
               background: #fff;
             }
 
+            .ant-carousel {
+              height: 100%;
+
+              .slick-slider {
+                height: 100%;
+              }
+
+              .slick-list {
+                height: 100%;
+              }
+
+              .slick-track {
+                height: 100%;
+              }
+
+              .slick-slide {
+                height: 100%;
+                overflow: hidden;
+                overflow-y: auto;
+              }
+
+              .slick-dots {
+                li {
+                  button {
+                    background: #D0D8E2;
+                    width: 4px;
+                  }
+                }
+
+                .slick-active {
+                  button {
+                    background: #4299FF;
+                    width: 24px;
+                  }
+                }
+              }
+            }
+
             // .answer-block {
             //   margin-bottom: 5px;
             // }
@@ -367,6 +414,7 @@
           color: #303036;
           font-size: 20px;
           font-weight: 600;
+          border: none;
         }
 
         .desc {

+ 3 - 3
front/project/www/routes/paper/report/page.js

@@ -668,7 +668,7 @@ export default class extends Page {
             </div>
             <div className="right">
               <div className="text">{user.info.nickname}</div>
-              <div className="desc">练习次数{paper.times}</div>
+              <div className="desc">练习次数{paper.times + 1}</div>
               <div className="desc">{formatDate(report.updateTime, 'YYYY-MM-DD HH:mm:ss')}</div>
             </div>
           </div>
@@ -705,7 +705,7 @@ export default class extends Page {
             </div>
             <div className="right">
               <div className="text">{user.info.nickname}</div>
-              <div className="desc">练习次数{paper.times}</div>
+              <div className="desc">练习次数{paper.times + 1}</div>
               <div className="desc">{formatDate(report.updateTime, 'YYYY-MM-DD HH:mm:ss')}</div>
             </div>
           </div>
@@ -738,7 +738,7 @@ export default class extends Page {
             </div>
             <div className="right">
               <div className="text">{user.info.nickname}</div>
-              <div className="desc">练习次数{paper.times}</div>
+              <div className="desc">练习次数{paper.times + 1}</div>
               <div className="desc">{formatDate(report.updateTime, 'YYYY-MM-DD HH:mm:ss')}</div>
             </div>
           </div>

+ 2 - 0
server/data/src/main/java/com/qxgmat/data/constants/enums/status/AnswerStatus.java

@@ -22,6 +22,8 @@ public enum AnswerStatus {
                 return ANSWER;
             case 2:
                 return IGNORE;
+            case 3:
+                return NOHANDLE;
             default:
                 return null;
         }

+ 5 - 7
server/data/src/main/java/com/qxgmat/data/relation/mapping/CourseDataHistoryRelationMapper.xml

@@ -22,18 +22,16 @@
     select
     <include refid="Id_Column_List" />
     from `course_data_history` cdh
+    left join `user_course_data_subscribe` ucds on `ucds`.`data_id`= cdh.`data_id`
     <if test="userId != null">
-    left join `user_order_record` uor on `uor`.`product_type`='data' and `uor`.`product_id` = cdh.`data_id`
-      and `uor`.user_id = #{userId,jdbcType=VARCHAR}
+      and `ucds`.user_id = #{userId,jdbcType=VARCHAR}
     </if>
     <!--and `uo`.create_time &lt; cd.create_time-->
-    where 1
-    <if test="userId != null">
-    and `uor`.`id` > 0
-    </if>
+    where
+    `ucds`.`id` > 0
     <if test="dataId != null">
       and `cdh`.`data_id` = #{dataId,jdbcType=VARCHAR}
     </if>
-
+    order by cdh.`id` desc
   </select>
 </mapper>

+ 2 - 2
server/data/src/main/java/com/qxgmat/data/relation/mapping/UserPaperQuestionRelationMapper.xml

@@ -21,7 +21,7 @@
   -->
   <select id="filterTimes" resultMap="IdMap">
     select
-    <include refid="Id_Column_List" />
+    upq.`question_no_id`
     from `user_paper_question` upq
     where 1
     <if test="userId != null">
@@ -37,6 +37,6 @@
     <foreach collection="questionNoIds" item="item" index="index" open="(" separator="," close=")">
       #{item}
     </foreach>
-    group by upq.`question_no_id` having count(*) &gt; #{fiterTimes,jdbcType=VARCHAR}
+    group by upq.`question_no_id` having count(*) &gt; #{filterTimes,jdbcType=VARCHAR}
   </select>
 </mapper>

+ 1 - 1
server/data/src/main/resources/db/migration/V1__init_table.sql

@@ -527,7 +527,7 @@ CREATE TABLE question (
   difficult varchar(20) NOT NULL DEFAULT '' COMMENT '难度',
   difficult_score float(11,2) DEFAULT '0.00' COMMENT '难度分',
   stem text COMMENT '题干',
-  description varchar(255) DEFAULT NULL COMMENT '简介:自动从题干提取',
+  description varchar(1000) DEFAULT NULL COMMENT '简介:自动从题干提取',
   content text COMMENT '内容:json',
   answer text COMMENT '答案:json',
   question_time datetime DEFAULT NULL,

+ 3 - 1
server/gateway-api/src/main/java/com/qxgmat/controller/admin/CourseController.java

@@ -275,9 +275,11 @@ public class CourseController {
                 .build();
         if(in.getLatestTime() == null){
             tmp.setLatestTime(entity.getTime());
+            tmp.setVersion(entity.getVersion());
             courseDataService.edit(tmp);
         }else if(entity.getTime().after(in.getLatestTime())){
             tmp.setLatestTime(entity.getTime());
+            tmp.setVersion(entity.getVersion());
             courseDataService.edit(tmp);
         }
         asyncTask.postDataUpdate(entity.getId());
@@ -759,7 +761,7 @@ public class CourseController {
         UserAskCourse entity = Transform.dtoToEntity(dto);
         UserAskCourse in = userAskCourseService.get(entity.getId());
         // 调整回答
-        if(in.getAnswerStatus() == 0 && dto.getAnswer() != null || dto.getIgnoreStatus() > 0){
+        if(in.getAnswerStatus() == 0 && (dto.getAnswer() != null || (dto.getIgnoreStatus() !=null && dto.getIgnoreStatus() > 0))){
             entity.setAnswerTime(new Date());
 
             if (dto.getIgnoreStatus() != null && dto.getIgnoreStatus() > 0){

+ 1 - 1
server/gateway-api/src/main/java/com/qxgmat/controller/admin/QuestionController.java

@@ -183,7 +183,7 @@ public class QuestionController {
         UserAskQuestion in = userAskQuestionService.get(entity.getId());
 
         // 调整回答
-        if(in.getAnswerStatus() == 0 && dto.getAnswer() != null || dto.getIgnoreStatus() > 0){
+        if(in.getAnswerStatus() == 0 && (dto.getAnswer() != null || (dto.getIgnoreStatus() !=null && dto.getIgnoreStatus() > 0))){
             entity.setAnswerTime(new Date());
 
             if (dto.getIgnoreStatus() != null && dto.getIgnoreStatus() > 0){

+ 1 - 0
server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java

@@ -1490,6 +1490,7 @@ public class MyController {
         User user = (User) shiroHelp.getLoginUser();
         entity.setUserId(user.getId());
         entity.setStatus(0);
+        entity.setModule(FeedbackModule.QUESTION.key);
 
         QuestionNo questionNo = questionNoService.get(dto.getQuestionNoId());
         QuestionNoModule questionNoModule = QuestionNoModule.ValueOf(questionNo.getModule());

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

@@ -28,6 +28,8 @@ public class ExerciseStructDto {
 
     private Integer isData;
 
+    private Integer isExamination;
+
     public Integer getId() {
         return id;
     }
@@ -98,4 +100,12 @@ public class ExerciseStructDto {
     public void setIsData(Integer isData) {
         this.isData = isData;
     }
+
+    public Integer getIsExamination() {
+        return isExamination;
+    }
+
+    public void setIsExamination(Integer isExamination) {
+        this.isExamination = isExamination;
+    }
 }

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

@@ -5,12 +5,15 @@ import com.qxgmat.data.dao.entity.UserAskQuestion;
 import com.qxgmat.dto.admin.extend.*;
 
 import java.util.Collection;
+import java.util.Date;
 
 @Dto(entity = UserAskQuestion.class)
 public class UserAskQuestionDetailDto {
 
     private Integer id;
 
+    private String askModule;
+
     private Integer userQuestionId;
 
     private String questionModule;
@@ -37,6 +40,14 @@ public class UserAskQuestionDetailDto {
 
     private String answer;
 
+    private Integer answerStatus;
+
+    private Integer showStatus;
+
+    private Date answerTime;
+
+    private Date createTime;
+
     public Integer getId() {
         return id;
     }
@@ -148,4 +159,44 @@ public class UserAskQuestionDetailDto {
     public void setPaperModule(String paperModule) {
         this.paperModule = paperModule;
     }
+
+    public String getAskModule() {
+        return askModule;
+    }
+
+    public void setAskModule(String askModule) {
+        this.askModule = askModule;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getAnswerTime() {
+        return answerTime;
+    }
+
+    public void setAnswerTime(Date answerTime) {
+        this.answerTime = answerTime;
+    }
+
+    public Integer getAnswerStatus() {
+        return answerStatus;
+    }
+
+    public void setAnswerStatus(Integer answerStatus) {
+        this.answerStatus = answerStatus;
+    }
+
+    public Integer getShowStatus() {
+        return showStatus;
+    }
+
+    public void setShowStatus(Integer showStatus) {
+        this.showStatus = showStatus;
+    }
 }

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

@@ -13,6 +13,8 @@ import java.util.Date;
 public class UserAskQuestionListDto {
     private Integer id;
 
+    private String askModule;
+
     private String content;
 
     private String originContent;
@@ -23,12 +25,20 @@ public class UserAskQuestionListDto {
 
     private String paperModule;
 
+    private Integer questionId;
+
     private QuestionExtendDto question;
 
+    private Integer questionNoId;
+
     private QuestionNoExtendDto questionNo;
 
+    private Integer userId;
+
     private UserExtendDto user;
 
+    private Integer managerId;
+
     private ManagerExtendDto manager;
 
     private Integer askTime;
@@ -41,6 +51,8 @@ public class UserAskQuestionListDto {
 
     private Date answerTime;
 
+    private Date createTime;
+
     public Integer getId() {
         return id;
     }
@@ -160,4 +172,52 @@ public class UserAskQuestionListDto {
     public void setExpireTime(Date expireTime) {
         this.expireTime = expireTime;
     }
+
+    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 Integer getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Integer userId) {
+        this.userId = userId;
+    }
+
+    public Integer getManagerId() {
+        return managerId;
+    }
+
+    public void setManagerId(Integer managerId) {
+        this.managerId = managerId;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getAskModule() {
+        return askModule;
+    }
+
+    public void setAskModule(String askModule) {
+        this.askModule = askModule;
+    }
 }

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

@@ -17,6 +17,10 @@ public class UserFeedbackErrorInfoDto {
 
     private String module;
 
+    private Integer moduleId;
+
+    private String questionType;
+
     private String title;
 
     private Integer status;
@@ -118,4 +122,20 @@ public class UserFeedbackErrorInfoDto {
     public void setHandleTime(Date handleTime) {
         this.handleTime = handleTime;
     }
+
+    public Integer getModuleId() {
+        return moduleId;
+    }
+
+    public void setModuleId(Integer moduleId) {
+        this.moduleId = moduleId;
+    }
+
+    public String getQuestionType() {
+        return questionType;
+    }
+
+    public void setQuestionType(String questionType) {
+        this.questionType = questionType;
+    }
 }

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

@@ -5,7 +5,7 @@ import com.nuliji.tools.annotation.Dto;
 import com.qxgmat.data.dao.entity.Question;
 
 @Dto(entity = Question.class)
-public class QuestionBaseExtendDto  {
+public class QuestionBaseExtendDto extends QuestionExtendDto {
 
     private Integer id;
 

+ 21 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/CourseDataListDto.java

@@ -6,6 +6,7 @@ import com.qxgmat.dto.extend.CommentExtendDto;
 
 import java.math.BigDecimal;
 import java.util.Collection;
+import java.util.Date;
 
 @Dto(entity = CourseData.class)
 public class CourseDataListDto {
@@ -35,6 +36,10 @@ public class CourseDataListDto {
 
     private Integer saleNumber;
 
+    private Date latestTime;
+
+    private String version;
+
     private Boolean subscribe;
 
     private Boolean have;
@@ -178,4 +183,20 @@ public class CourseDataListDto {
     public void setSubscribe(Boolean subscribe) {
         this.subscribe = subscribe;
     }
+
+    public Date getLatestTime() {
+        return latestTime;
+    }
+
+    public void setLatestTime(Date latestTime) {
+        this.latestTime = latestTime;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
 }

+ 19 - 8
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserQuestionBaseDto.java

@@ -3,6 +3,7 @@ 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.QuestionExtendDto;
 import com.qxgmat.dto.extend.QuestionNoExtendDto;
 
@@ -28,6 +29,8 @@ public class UserQuestionBaseDto {
 
     private Integer isCorrect;
 
+    private Integer userTime;
+
     private JSONObject setting;
 
     private JSONObject detail;
@@ -62,14 +65,6 @@ public class UserQuestionBaseDto {
         this.questionNoId = questionNoId;
     }
 
-    public QuestionExtendDto getQuestion() {
-        return question;
-    }
-
-    public void setQuestion(QuestionExtendDto question) {
-        this.question = question;
-    }
-
     public Boolean getCollect() {
         return collect;
     }
@@ -149,4 +144,20 @@ public class UserQuestionBaseDto {
     public void setNote(Boolean note) {
         this.note = note;
     }
+
+    public QuestionExtendDto getQuestion() {
+        return question;
+    }
+
+    public void setQuestion(QuestionExtendDto question) {
+        this.question = question;
+    }
+
+    public Integer getUserTime() {
+        return userTime;
+    }
+
+    public void setUserTime(Integer userTime) {
+        this.userTime = userTime;
+    }
 }

+ 10 - 0
server/gateway-api/src/main/java/com/qxgmat/service/UserPaperService.java

@@ -292,6 +292,16 @@ public class UserPaperService extends AbstractService {
         userPaperRelationMapper.accumulation(report.getPaperId(), report.getUserNumber(), report.getUserTime(), report.getUserCorrect(), 1, report.getFinishTime(), report.getId());
     }
 
+    public int countByUser(Integer userId, PaperOrigin origin){
+        Example example = new Example(UserPaper.class);
+        example.and(
+                example.createCriteria()
+                        .andEqualTo("userId", userId)
+                        .andEqualTo("paperOrigin", origin.key)
+        );
+        return count(userPaperMapper, example);
+    }
+
     /**
      * 批量删除用户记录:preview切换可用学生
      * @param userIds

+ 2 - 2
server/gateway-api/src/main/java/com/qxgmat/service/extend/OrderFlowService.java

@@ -330,8 +330,8 @@ public class OrderFlowService {
                     // 是否存在半价机经券
                     if (!checkout.getMoney().equals(checkout.getOriginMoney())){
                         JSONObject info = new JSONObject();
-                        info.put("originMoney", originMoney);
-                        info.put("money", money);
+                        info.put("originMoney", checkout.getOriginMoney());
+                        info.put("money", checkout.getMoney());
                         info.put("key", "textbook-half");
                         info.put("message", "半价机经券");
                         JSONArray promote = order.getPromote();

+ 25 - 8
server/gateway-api/src/main/java/com/qxgmat/service/extend/QuestionFlowService.java

@@ -436,7 +436,7 @@ public class QuestionFlowService {
             throw new ParameterException("题目数为空");
         }
         QuestionOrigin questionOrigin = QuestionOrigin.WithPaper(origin);
-        if (filterTimes > 0){
+        if (filterTimes != null && filterTimes > 0){
             // 过滤重复多次的题目
             questionNoIds = userPaperQuestionService.filterTimesQuestion(userId, questionOrigin, module, questionNoIds, filterTimes);
             if (questionNoIds.size() == 0){
@@ -444,7 +444,16 @@ public class QuestionFlowService {
             }
         }
 
+        int count = userPaperService.countByUser(userId, origin);
+
         UserPaper paper = userPaperService.newByPaper(userId, origin, PaperModule.WithQuestion(module), 0);
+        switch(origin){
+            case ERROR:
+                paper.setTitle(String.format("错题组卷%02d", count+1));
+                break;
+            case COLLECT:
+                paper.setTitle(String.format("收藏组卷%02d", count+1));
+        }
         paper.setQuestionNumber(questionNoIds.size());
         paper.setQuestionNoIds(questionNoIds.toArray(new Integer[0]));
 
@@ -458,9 +467,9 @@ public class QuestionFlowService {
     }
 
     public QuestionModule validGroup(Integer[] questionNoIds){
-        if (questionNoIds == null || questionNoIds.length < 10) {
-            throw new ParameterException("不可小于10题,请重新选择");
-        }
+//        if (questionNoIds == null || questionNoIds.length < 10) {
+//            throw new ParameterException("不可小于10题,请重新选择");
+//        }
         if (questionNoIds.length > 50){
             throw new ParameterException("不可多余50题,请重新选择");
         }
@@ -604,8 +613,11 @@ public class QuestionFlowService {
             UserQuestion lastQuestion = userQuestion;
             userQuestion = userQuestionService.newByReport(userReport, lastQuestion);
             InitQuestion callback = nextCallback.get(PaperModule.ValueOf(userReport.getPaperModule()));
-            callback.callback(userQuestion, userReport, lastQuestion);
-            userQuestion = userQuestionService.add(userQuestion);
+            if (callback.callback(userQuestion, userReport, lastQuestion)){
+                userQuestion = userQuestionService.add(userQuestion);
+            }else{
+                return null;
+            }
         }
 
         return userQuestion;
@@ -1298,8 +1310,13 @@ public class QuestionFlowService {
      */
     private JSONObject statExerciseReport(UserReport report, List<UserQuestion> questionList){
         UserPaper paper = userPaperService.get(report.getPaperId());
-        Collection questionNoIds = Transform.getIds(questionList, UserQuestion.class, "questionNoId");
-        Map<Number, QuestionNoRelation> relationMap = questionNoService.mapWithRelationByIds((Integer[])questionNoIds.toArray());
+        Integer[] questionNoIds = new Integer[questionList.size()];
+        int index = 0;
+        for(UserQuestion userQuestion : questionList){
+            questionNoIds[index] = userQuestion.getQuestionNoId();
+            index += 1;
+        }
+        Map<Number, QuestionNoRelation> relationMap = questionNoService.mapWithRelationByIds(questionNoIds);
 
         // report
         JSONObject detail = new JSONObject();

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

@@ -48,6 +48,7 @@ public class CourseDataHistoryService extends AbstractService {
         Transform.replace(p, list, CourseDataHistory.class, "id");
         return p;
     }
+
     /**
      * 根据资料获取更新记录
      * @param page

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

@@ -80,7 +80,7 @@ public class UserAskQuestionService extends AbstractService {
     }};
 
     public Page<UserAskQuestion> listAdmin(int page, int size, String askModule, String questionType, String questionModule, Number userId, Number questionNoId, AskTarget target, AnswerStatus status, Integer showStatus, MoneyRange moneyRange, Boolean hasRecord, Date startTime, Date endTime, String order, DirectionStatus direction){
-        String tk = target != null ? target.key : "";
+        String tk = target != null ? target.key : null;
         Integer statusIndex = status != null ? status.index : null;
         Integer max = moneyRange != null ? moneyRange.max == Integer.MAX_VALUE ? null : moneyRange.max : null;
         Integer min = moneyRange != null ? moneyRange.min : null;