瀏覽代碼

feat(server): 修正逻辑

Go 6 年之前
父節點
當前提交
b406ae3e0e
共有 76 個文件被更改,包括 2152 次插入549 次删除
  1. 5 1
      front/project/Constant.js
  2. 15 0
      front/project/admin/routes/show/deploy/index.js
  3. 3 0
      front/project/admin/routes/show/deploy/index.less
  4. 418 0
      front/project/admin/routes/show/deploy/page.js
  5. 2 1
      front/project/admin/routes/show/index.js
  6. 8 0
      front/project/admin/stores/system.js
  7. 3 2
      front/project/h5/routes/page/identity/page.js
  8. 16 11
      front/project/h5/routes/page/study/page.js
  9. 7 0
      front/project/h5/stores/main.js
  10. 4 3
      front/project/h5/stores/my.js
  11. 1 1
      front/project/www/components/Login/index.js
  12. 7 3
      front/project/www/local.json
  13. 99 141
      front/project/www/routes/paper/process/base/index.js
  14. 1 1
      server/data/src/main/java/com/qxgmat/data/constants/enums/ServiceKey.java
  15. 1 0
      server/data/src/main/java/com/qxgmat/data/constants/enums/SettingKey.java
  16. 17 0
      server/data/src/main/java/com/qxgmat/data/constants/enums/logic/TextbookLogic.java
  17. 7 7
      server/data/src/main/java/com/qxgmat/data/dao/entity/ExaminationPaper.java
  18. 92 22
      server/data/src/main/java/com/qxgmat/data/dao/entity/TextbookLibraryHistory.java
  19. 35 35
      server/data/src/main/java/com/qxgmat/data/dao/entity/TextbookPaper.java
  20. 16 16
      server/data/src/main/java/com/qxgmat/data/dao/entity/TextbookQuestion.java
  21. 35 0
      server/data/src/main/java/com/qxgmat/data/dao/entity/UserPaper.java
  22. 35 0
      server/data/src/main/java/com/qxgmat/data/dao/entity/UserReport.java
  23. 0 20
      server/data/src/main/java/com/qxgmat/data/dao/mapping/CourseStudentOnlineMapper.xml
  24. 4 2
      server/data/src/main/java/com/qxgmat/data/dao/mapping/TextbookLibraryHistoryMapper.xml
  25. 3 3
      server/data/src/main/java/com/qxgmat/data/dao/mapping/TextbookPaperMapper.xml
  26. 2 2
      server/data/src/main/java/com/qxgmat/data/dao/mapping/TextbookQuestionMapper.xml
  27. 4 3
      server/data/src/main/java/com/qxgmat/data/dao/mapping/UserPaperMapper.xml
  28. 2 1
      server/data/src/main/java/com/qxgmat/data/dao/mapping/UserReportMapper.xml
  29. 36 0
      server/data/src/main/java/com/qxgmat/data/relation/PreviewAssignRelationMapper.java
  30. 19 0
      server/data/src/main/java/com/qxgmat/data/relation/TextbookPaperRelationMapper.java
  31. 14 6
      server/data/src/main/java/com/qxgmat/data/relation/UserCourseRecordRelationMapper.java
  32. 8 0
      server/data/src/main/java/com/qxgmat/data/relation/UserOrderRecordRelationMapper.java
  33. 22 0
      server/data/src/main/java/com/qxgmat/data/relation/UserQuestionRelationMapper.java
  34. 7 2
      server/data/src/main/java/com/qxgmat/data/relation/UserSentenceRecordRelationMapper.java
  35. 1 1
      server/data/src/main/java/com/qxgmat/data/relation/entity/UserCourseStatRelation.java
  36. 1 1
      server/data/src/main/java/com/qxgmat/data/relation/entity/UserSentenceStatRelation.java
  37. 2 2
      server/data/src/main/java/com/qxgmat/data/relation/mapping/ExaminationPaperRelationMapper.xml
  38. 1 1
      server/data/src/main/java/com/qxgmat/data/relation/mapping/ExercisePaperRelationMapper.xml
  39. 97 0
      server/data/src/main/java/com/qxgmat/data/relation/mapping/PreviewAssignRelationMapper.xml
  40. 40 0
      server/data/src/main/java/com/qxgmat/data/relation/mapping/TextbookPaperRelationMapper.xml
  41. 1 1
      server/data/src/main/java/com/qxgmat/data/relation/mapping/TextbookQuestionRelationMapper.xml
  42. 41 1
      server/data/src/main/java/com/qxgmat/data/relation/mapping/UserCourseRecordRelationMapper.xml
  43. 38 18
      server/data/src/main/java/com/qxgmat/data/relation/mapping/UserOrderRecordRelationMapper.xml
  44. 56 0
      server/data/src/main/java/com/qxgmat/data/relation/mapping/UserQuestionRelationMapper.xml
  45. 21 4
      server/data/src/main/java/com/qxgmat/data/relation/mapping/UserSentenceRecordRelationMapper.xml
  46. 17 0
      server/gateway-api/src/main/java/com/qxgmat/controller/admin/SettingController.java
  47. 3 3
      server/gateway-api/src/main/java/com/qxgmat/controller/admin/UserController.java
  48. 1 1
      server/gateway-api/src/main/java/com/qxgmat/controller/api/AuthController.java
  49. 7 0
      server/gateway-api/src/main/java/com/qxgmat/controller/api/BaseController.java
  50. 16 4
      server/gateway-api/src/main/java/com/qxgmat/controller/api/CourseController.java
  51. 28 81
      server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java
  52. 5 5
      server/gateway-api/src/main/java/com/qxgmat/controller/api/QuestionController.java
  53. 1 5
      server/gateway-api/src/main/java/com/qxgmat/controller/api/SentenceController.java
  54. 158 2
      server/gateway-api/src/main/java/com/qxgmat/controller/api/TextbookController.java
  55. 30 10
      server/gateway-api/src/main/java/com/qxgmat/dto/admin/request/TextbookLibraryHistoryDto.java
  56. 73 0
      server/gateway-api/src/main/java/com/qxgmat/dto/extend/UserTextbookGroupExtendDto.java
  57. 18 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/PaperBaseDto.java
  58. 11 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserStudyDetailDto.java
  59. 118 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserTextbookGroupDto.java
  60. 70 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserTextbookPaperDto.java
  61. 6 2
      server/gateway-api/src/main/java/com/qxgmat/help/AiHelp.java
  62. 35 0
      server/gateway-api/src/main/java/com/qxgmat/service/UserQuestionService.java
  63. 17 2
      server/gateway-api/src/main/java/com/qxgmat/service/extend/CourseExtendService.java
  64. 64 4
      server/gateway-api/src/main/java/com/qxgmat/service/extend/ExaminationService.java
  65. 16 10
      server/gateway-api/src/main/java/com/qxgmat/service/extend/OrderFlowService.java
  66. 13 9
      server/gateway-api/src/main/java/com/qxgmat/service/extend/PreviewService.java
  67. 11 22
      server/gateway-api/src/main/java/com/qxgmat/service/extend/QuestionFlowService.java
  68. 32 6
      server/gateway-api/src/main/java/com/qxgmat/service/extend/SentenceService.java
  69. 2 2
      server/gateway-api/src/main/java/com/qxgmat/service/extend/TextbookService.java
  70. 27 42
      server/gateway-api/src/main/java/com/qxgmat/service/inline/PreviewAssignService.java
  71. 28 16
      server/gateway-api/src/main/java/com/qxgmat/service/inline/TextbookPaperService.java
  72. 16 2
      server/gateway-api/src/main/java/com/qxgmat/service/inline/TextbookQuestionService.java
  73. 33 3
      server/gateway-api/src/main/java/com/qxgmat/service/inline/UserCourseRecordService.java
  74. 27 0
      server/gateway-api/src/main/java/com/qxgmat/service/inline/UserOrderRecordService.java
  75. 16 6
      server/gateway-api/src/main/java/com/qxgmat/service/inline/UserSentenceRecordService.java
  76. 6 0
      server/tools/src/main/java/com/nuliji/tools/Tools.java

+ 5 - 1
front/project/Constant.js

@@ -56,7 +56,11 @@ export const SentenceOption = [{ label: '平行', value: 'parallel' }, { label:
 
 
 export const ExaminationSubject = [{ short: 'V', value: 'verbal', label: '语文', english: 'Verbal' }, { short: 'Q', value: 'quant', label: '数学', english: 'Quant' }, { short: 'IR', value: 'ir', label: '综合推理', english: 'LR' }, { short: 'AWA', value: 'awa', label: '作文', english: 'AWA' }];
 export const ExaminationSubject = [{ short: 'V', value: 'verbal', label: '语文', english: 'Verbal' }, { short: 'Q', value: 'quant', label: '数学', english: 'Quant' }, { short: 'IR', value: 'ir', label: '综合推理', english: 'LR' }, { short: 'AWA', value: 'awa', label: '作文', english: 'AWA' }];
 
 
-export const ExaminationOrder = [{ list: ['awa', 'ir', 'quant', 'verbal'] }, { list: ['quant', 'verbal', 'ir', 'awa'] }, { list: ['verbal', 'quant', 'ir', 'awa'] }];
+export const ExaminationOrder = [
+  { label: 'ARQV', value: ['awa', 'ir', 'quant', 'verbal'], list: [{ label: 'Analytical Writing Analysis', value: 'awa' }, { label: 'Integrated Reasoning', value: 'ir' }, { label: 'Quantitative', value: 'quant' }, { label: 'Verbal', value: 'verbal' }] },
+  { label: 'VQRA', value: ['verbal', 'quant', 'ir', 'awa'], list: [{ label: 'Verbal', value: 'verbal' }, { label: 'Quantitative', value: 'quant' }, { label: 'Integrated Reasoning', value: 'ir' }, { label: 'Analytical Writing Analysis', value: 'awa' }] },
+  { label: 'QVRA', value: ['quant', 'verbal', 'ir', 'awa'], list: [{ label: 'Quantitative', value: 'quant' }, { label: 'Verbal', value: 'verbal' }, { label: 'Integrated Reasoning', value: 'ir' }, { label: 'Analytical Writing Analysis', value: 'awa' }] },
+];
 
 
 export const DataType = [{ label: '电子', value: 'electron' }, { label: '纸质', value: 'paper' }];
 export const DataType = [{ label: '电子', value: 'electron' }, { label: '纸质', value: 'paper' }];
 
 

+ 15 - 0
front/project/admin/routes/show/deploy/index.js

@@ -0,0 +1,15 @@
+import module from '../../module';
+import group from '../group';
+
+export default {
+  path: '/show/deploy',
+  key: 'show-deploy',
+  title: '配置文案',
+  needLogin: true,
+  module,
+  group,
+  index: true,
+  component() {
+    return import('./page');
+  },
+};

+ 3 - 0
front/project/admin/routes/show/deploy/index.less

@@ -0,0 +1,3 @@
+@charset "utf-8";
+
+#show-deploy {}

+ 418 - 0
front/project/admin/routes/show/deploy/page.js

@@ -0,0 +1,418 @@
+import React from 'react';
+import { Tabs, Form, Row, Col, Input, InputNumber, Button, Upload, Icon } from 'antd';
+import './index.less';
+import Page from '@src/containers/Page';
+import Block from '@src/components/Block';
+import { flattenObject } from '@src/services/Tools';
+import { asyncSMessage } from '@src/services/AsyncTools';
+import { ServiceParamMap } from '../../../../Constant';
+import { System } from '../../../stores/system';
+
+export default class extends Page {
+  constructor(props) {
+    super(props);
+    this.state.tab = 'qx_cat';
+    this.vipList = ServiceParamMap.vip;
+  }
+
+  initData() {
+    this.refresh(this.state.tab);
+  }
+
+  refresh(tab) {
+    if (tab === 'qx_cat') {
+      return this.refreshQxCat();
+    }
+    if (tab === 'textbook') {
+      return this.refreshTextbook();
+    }
+    if (tab === 'vip') {
+      return this.refreshVip();
+    }
+    return Promise.reject();
+  }
+
+  refreshQxCat() {
+    return System.getServiceQxCat().then(result => {
+      this.setState({ qx_cat: result || {} });
+      const { form } = this.props;
+      form.setFieldsValue(flattenObject(result, 'qx_cat'));
+    });
+  }
+
+  refreshTextbook() {
+    return System.getServiceTextbook().then(result => {
+      this.setState({ textbook: result || {} });
+      const { form } = this.props;
+      form.setFieldsValue(flattenObject(result, 'textbook'));
+    });
+  }
+
+  refreshVip() {
+    return System.getServiceVip().then(result => {
+      this.setState({ vip: result || {} });
+      const { form } = this.props;
+      form.setFieldsValue(flattenObject(result, 'vip'));
+    });
+  }
+
+  changeMapValue(field, second, index, key, value) {
+    const data = this.state[field] || {};
+    data[second] = data[second] || [];
+    data[second][index] = data[second][index] || {};
+    data[second][index][key] = value;
+    this.setState({ [field]: data });
+  }
+
+  submit(tab) {
+    let handler;
+    if (tab === 'qx_cat') {
+      handler = this.submitQxCat();
+    }
+    if (tab === 'textbook') {
+      handler = this.submitTextbook();
+    }
+    if (tab === 'vip') {
+      handler = this.submitVip();
+    }
+    handler.then(() => {
+      asyncSMessage('保存成功');
+    });
+  }
+
+  submitQxCat() {
+    const { qx_cat } = this.state;
+    return System.setServiceQxCat(qx_cat);
+  }
+
+  submitTextbook() {
+    const { textbook } = this.state;
+    return System.setServiceTextbook(textbook);
+  }
+
+  submitVip() {
+    const { vip } = this.state;
+    return System.setServiceVip(vip);
+  }
+
+  renderQxCat() {
+    const { getFieldDecorator, setFieldsValue, getFieldValue } = this.props.form;
+    const image = getFieldValue('qx_cat.image') || null;
+    return <Form>
+      <Row>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='商品价格'>
+          {getFieldDecorator('qx_cat.package[0].price', {
+            rules: [
+              { required: true, message: '输入千行Cat价格' },
+            ],
+          })(
+            <InputNumber placeholder='请输入千行Cat价格' onChange={(value) => {
+              this.changeMapValue('qx_cat', 'package', 0, 'price', value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='服务名称'>
+          {getFieldDecorator('qx_cat.package[0].title', {
+            rules: [
+              { required: true, message: '输入千行Cat名称' },
+            ],
+          })(
+            <Input placeholder='请输入千行Cat名称' onChange={(e) => {
+              this.changeMapValue('qx_cat', 'package', 0, 'title', e.target.value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='服务简介'>
+          {getFieldDecorator('qx_cat.package[0].description', {
+            rules: [
+              { required: true, message: '输入千行Cat服务简介' },
+            ],
+          })(
+            <Input placeholder='请输入千行Cat服务简介' onChange={(e) => {
+              this.changeMapValue('qx_cat', 'package', 0, 'description', e.target.value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='有效期说明'>
+          {getFieldDecorator('qx_cat.package[0].expire_info', {
+            rules: [
+              { required: true, message: '输入千行Cat有效期说明' },
+            ],
+          })(
+            <Input placeholder='请输入千行Cat有效期说明' onChange={(e) => {
+              this.changeMapValue('qx_cat', 'package', 0, 'expire_info', e.target.value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='退款政策'>
+          {getFieldDecorator('qx_cat.package[0].refund_policy', {
+            rules: [
+              { required: true, message: '输入千行Cat退款政策' },
+            ],
+          })(
+            <Input placeholder='请输入千行Cat退款政策' onChange={(e) => {
+              this.changeMapValue('qx_cat', 'package', 0, 'refund_policy', e.target.value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='版权说明'>
+          {getFieldDecorator('qx_cat.package[0].copyright_notes', {
+            rules: [
+              { required: true, message: '输入千行Cat版权说明' },
+            ],
+          })(
+            <Input placeholder='请输入千行Cat版权说明' onChange={(e) => {
+              this.changeMapValue('qx_cat', 'package', 0, 'copyright_notes', e.target.value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='商品图片'>
+          {getFieldDecorator('qx_cat.image', {
+            rules: [
+              { required: true, message: '上传图片' },
+            ],
+          })(
+            <Upload
+              listType="picture-card"
+              showUploadList={false}
+              beforeUpload={(file) => System.uploadImage(file).then((result) => {
+                setFieldsValue({ 'qx_cat.image': result.url });
+                return Promise.reject();
+              })}
+            >
+              {image ? <img src={image} alt="avatar" /> : <div>
+                <Icon type={this.state.loading ? 'loading' : 'plus'} />
+                <div className="ant-upload-text">Upload</div>
+              </div>}
+            </Upload>,
+          )}
+        </Form.Item>
+      </Row>
+    </Form>;
+  }
+
+  renderTextbook() {
+    const { getFieldDecorator, setFieldsValue, getFieldValue } = this.props.form;
+    const image = getFieldValue('textbook.image') || null;
+    return <Form>
+      <Row>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='商品图片'>
+          {getFieldDecorator('textbook.image', {
+            rules: [
+              { required: true, message: '上传图片' },
+            ],
+          })(
+            <Upload
+              listType="picture-card"
+              showUploadList={false}
+              beforeUpload={(file) => System.uploadImage(file).then((result) => {
+                setFieldsValue({ 'textbook.image': result.url });
+                return Promise.reject();
+              })}
+            >
+              {image ? <img src={image} alt="avatar" /> : <div>
+                <Icon type={this.state.loading ? 'loading' : 'plus'} />
+                <div className="ant-upload-text">Upload</div>
+              </div>}
+            </Upload>,
+          )}
+        </Form.Item>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='商品价格'>
+          {getFieldDecorator('textbook.package[0].price', {
+            rules: [
+              { required: true, message: '输入数学机经价格' },
+            ],
+          })(
+            <InputNumber placeholder='请输入数学机经价格' onChange={(value) => {
+              this.changeMapValue('textbook', 'package', 0, 'price', value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='服务名称'>
+          {getFieldDecorator('textbook.package[0].title', {
+            rules: [
+              { required: true, message: '输入数学机经名称' },
+            ],
+          })(
+            <Input placeholder='请输入数学机经名称' onChange={(e) => {
+              this.changeMapValue('textbook', 'package', 0, 'title', e.target.value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='服务简介'>
+          {getFieldDecorator('textbook.package[0].description', {
+            rules: [
+              { required: true, message: '输入数学机经服务简介' },
+            ],
+          })(
+            <Input placeholder='请输入数学机经服务简介' onChange={(e) => {
+              this.changeMapValue('textbook', 'package', 0, 'description', e.target.value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='有效期说明'>
+          {getFieldDecorator('textbook.package[0].expire_info', {
+            rules: [
+              { required: true, message: '输入数学机经有效期说明' },
+            ],
+          })(
+            <Input placeholder='请输入数学机经有效期说明' onChange={(e) => {
+              this.changeMapValue('textbook', 'package', 0, 'expire_info', e.target.value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='退款政策'>
+          {getFieldDecorator('textbook.package[0].refund_policy', {
+            rules: [
+              { required: true, message: '输入数学机经退款政策' },
+            ],
+          })(
+            <Input placeholder='请输入数学机经退款政策' onChange={(e) => {
+              this.changeMapValue('textbook', 'package', 0, 'refund_policy', e.target.value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+        <Form.Item labelCol={{ span: 4 }} wrapperCol={{ span: 16 }} label='版权说明'>
+          {getFieldDecorator('textbook.package[0].copyright_notes', {
+            rules: [
+              { required: true, message: '输入数学机经版权说明' },
+            ],
+          })(
+            <Input placeholder='请输入数学机经版权说明' onChange={(e) => {
+              this.changeMapValue('textbook', 'package', 0, 'copyright_notes', e.target.value);
+            }} style={{ width: '200px' }} />,
+          )}
+        </Form.Item>
+      </Row>
+    </Form>;
+  }
+
+  renderVip() {
+    const { getFieldDecorator, setFieldsValue, getFieldValue } = this.props.form;
+    const image = getFieldValue('vip.image') || null;
+    return <Form>
+      <Form.Item labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} label='商品图片'>
+        {getFieldDecorator('vip.image', {
+          rules: [
+            { required: true, message: '上传图片' },
+          ],
+        })(
+          <Upload
+            listType="picture-card"
+            showUploadList={false}
+            beforeUpload={(file) => System.uploadImage(file).then((result) => {
+              setFieldsValue({ 'vip.image': result.url });
+              return Promise.reject();
+            })}
+          >
+            {image ? <img src={image} alt="avatar" /> : <div>
+              <Icon type={this.state.loading ? 'loading' : 'plus'} />
+              <div className="ant-upload-text">Upload</div>
+            </div>}
+          </Upload>,
+        )}
+      </Form.Item>
+      <Row>
+        {this.vipList.map((row, index) => {
+          return <Col span={12}>
+            <h1>{row.label}</h1>
+            <Form.Item labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} label='商品价格'>
+              {getFieldDecorator(`vip.package[${index}].price`, {
+                rules: [
+                  { required: true, message: '输入价格' },
+                ],
+              })(
+                <InputNumber placeholder={'输入价格'} onChange={(value) => {
+                  this.changeMapValue('vip', 'package', index, 'price', value);
+                }} style={{ width: '200px' }} />,
+              )}
+            </Form.Item>
+            <Form.Item labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} label='服务名称'>
+              {getFieldDecorator(`vip.package[${index}].title`, {
+                rules: [
+                  { required: true, message: '输入名称' },
+                ],
+              })(
+                <Input placeholder={'输入名称'} onChange={(e) => {
+                  this.changeMapValue('vip', 'package', index, 'title', e.target.value);
+                }} style={{ width: '200px' }} />,
+              )}
+            </Form.Item>
+            <Form.Item labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} label='服务简介'>
+              {getFieldDecorator(`vip.package[${index}].description`, {
+                rules: [
+                  { required: true, message: '输入服务简介' },
+                ],
+              })(
+                <Input placeholder='请输入服务简介' onChange={(e) => {
+                  this.changeMapValue('vip', 'package', index, 'description', e.target.value);
+                }} style={{ width: '200px' }} />,
+              )}
+            </Form.Item>
+            <Form.Item labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} label='有效期说明'>
+              {getFieldDecorator(`vip.package[${index}].expire_info`, {
+                rules: [
+                  { required: true, message: '输入有效期说明' },
+                ],
+              })(
+                <Input placeholder='请输入有效期说明' onChange={(e) => {
+                  this.changeMapValue('vip', 'package', index, 'expire_info', e.target.value);
+                }} style={{ width: '200px' }} />,
+              )}
+            </Form.Item>
+            <Form.Item labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} label='退款政策'>
+              {getFieldDecorator(`vip.package[${index}].refund_policy`, {
+                rules: [
+                  { required: true, message: '输入退款政策' },
+                ],
+              })(
+                <Input placeholder='请输入退款政策' onChange={(e) => {
+                  this.changeMapValue('vip', 'package', index, 'refund_policy', e.target.value);
+                }} style={{ width: '200px' }} />,
+              )}
+            </Form.Item>
+            <Form.Item labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} label='版权说明'>
+              {getFieldDecorator(`vip.package[${index}].copyright_notes`, {
+                rules: [
+                  { required: true, message: '输入版权说明' },
+                ],
+              })(
+                <Input placeholder='请输入版权说明' onChange={(e) => {
+                  this.changeMapValue('vip', 'package', index, 'copyright_notes', e.target.value);
+                }} style={{ width: '200px' }} />,
+              )}
+            </Form.Item>
+          </Col>;
+        })}
+
+      </Row>
+    </Form>;
+  }
+
+  renderView() {
+    const { tab } = this.state;
+    return <Block><Tabs activeKey={tab} onChange={(value) => {
+      this.setState({ tab: value, selectedKeys: [], checkedKeys: [] });
+      this.refresh(value);
+    }}>
+      <Tabs.TabPane tab="千行Cat" key="qx_cat">
+        {this.renderQxCat()}
+      </Tabs.TabPane>
+      <Tabs.TabPane tab="数学机经" key="textbook">
+        {this.renderTextbook()}
+      </Tabs.TabPane>
+      <Tabs.TabPane tab="Vip" key="vip">
+        {this.renderVip()}
+      </Tabs.TabPane>
+    </Tabs>
+      <Row type="flex" justify="center">
+        <Col>
+          <Button type="primary" onClick={() => {
+            this.submit(tab);
+          }}>保存</Button>
+        </Col>
+      </Row>
+    </Block>;
+  }
+}

+ 2 - 1
front/project/admin/routes/show/index.js

@@ -6,5 +6,6 @@ import articleDetail from './articleDetail';
 import comment from './comment';
 import comment from './comment';
 import ad from './ad';
 import ad from './ad';
 import message from './message';
 import message from './message';
+import deploy from './deploy';
 
 
-export default [tips, faq, article, articleDetail, comment, ad, message];
+export default [tips, faq, article, articleDetail, comment, ad, message, deploy];

+ 8 - 0
front/project/admin/stores/system.js

@@ -149,6 +149,14 @@ export default class SystemStore extends BaseStore {
     return this.apiPut('/setting/experience_info', params);
     return this.apiPut('/setting/experience_info', params);
   }
   }
 
 
+  getWechatInfo() {
+    return this.apiGet('/setting/wechat_info');
+  }
+
+  setWechatInfo(params) {
+    return this.apiPut('/setting/wechat_info', params);
+  }
+
   getTips() {
   getTips() {
     return this.apiGet('/setting/tips');
     return this.apiGet('/setting/tips');
   }
   }

+ 3 - 2
front/project/h5/routes/page/identity/page.js

@@ -6,6 +6,7 @@ import { asyncSMessage } from '@src/services/AsyncTools';
 import { dataURLtoBlob, formatDate } from '@src/services/Tools';
 import { dataURLtoBlob, formatDate } from '@src/services/Tools';
 import Icon from '../../../components/Icon';
 import Icon from '../../../components/Icon';
 import { Common } from '../../../stores/common';
 import { Common } from '../../../stores/common';
+// import { Main } from '../../../stores/main';
 import { My } from '../../../stores/my';
 import { My } from '../../../stores/my';
 
 
 export default class extends Page {
 export default class extends Page {
@@ -107,7 +108,7 @@ export default class extends Page {
     return (
     return (
       <div>
       <div>
         <div className="text">
         <div className="text">
-          请扫描您的居民身份证原件,领取6个月VIP权限。
+          请扫描您的居民身份证原件,领取90天VIP权限。
           <br />
           <br />
           千行将重视和保护您的隐私。
           千行将重视和保护您的隐私。
         </div>
         </div>
@@ -145,7 +146,7 @@ export default class extends Page {
           <Icon type="check-circle" />
           <Icon type="check-circle" />
         </div>
         </div>
         <div className="title">认证完成!</div>
         <div className="title">认证完成!</div>
-        <div className="desc">180天VIP权限已赠送至您的账户</div>
+        <div className="desc">90天VIP权限已赠送至您的账户</div>
         <div className="desc">生效时间:{formatDate(data.useStartTime, 'YYYY-MM-DD')}</div>
         <div className="desc">生效时间:{formatDate(data.useStartTime, 'YYYY-MM-DD')}</div>
       </div>
       </div>
     );
     );

+ 16 - 11
front/project/h5/routes/page/study/page.js

@@ -1,7 +1,7 @@
 import React from 'react';
 import React from 'react';
 import './index.less';
 import './index.less';
 import Page from '@src/containers/Page';
 import Page from '@src/containers/Page';
-import { formatDate, formatSeconds } from '@src/services/Tools';
+import { formatDate, formatSeconds, formatPercent } from '@src/services/Tools';
 import Icon from '../../../components/Icon';
 import Icon from '../../../components/Icon';
 import { My } from '../../../stores/my';
 import { My } from '../../../stores/my';
 
 
@@ -12,13 +12,20 @@ export default class extends Page {
     My.getStudyTotal().then(total => {
     My.getStudyTotal().then(total => {
       this.setState({ total });
       this.setState({ total });
     });
     });
-    My.getStudyWeek().then(week => {
-      this.setState({ week });
+    My.getStudyWeek(0).then(latest => {
+      const diff = latest.time - latest.avgTime;
+      const diffPercent = diff > 0 ? formatPercent(latest.time - latest.avgTime, latest.avgTime, true) : formatPercent(latest.avgTime - latest.time, latest.avgTime, true);
+      this.setState({ latest, diff, diffPercent });
+      My.getStudyWeek(1).then(last => {
+        const diffLast = latest.time - last.time;
+        const diffLastPercent = diffLast > 0 ? formatPercent(latest.time - last.time, last.time, true) : formatPercent(last.time - latest.time, last.time, true);
+        this.setState({ last, diffLast, diffLastPercent });
+      });
     });
     });
   }
   }
 
 
   renderView() {
   renderView() {
-    const { total } = this.state;
+    const { total, latest = {}, diff = 0, diffPercent = 0, diffLast = 0, diffLastPercent = 0 } = this.state;
     return (
     return (
       <div>
       <div>
         <div className="block">
         <div className="block">
@@ -33,22 +40,20 @@ export default class extends Page {
         <div className="t-c">
         <div className="t-c">
           <div className="item">
           <div className="item">
             <div className="text">学习时间</div>
             <div className="text">学习时间</div>
-            <div className="value">
-              <span>23</span>Hour
-            </div>
+            <div className="value" dangerouslySetInnerHTML={{ __html: formatSeconds(latest.time).replace(/([0-9]+)([msh])/g, '<span>$1</span>$2') }} />
           </div>
           </div>
           <div className="item">
           <div className="item">
             <div className="text">同比上周</div>
             <div className="text">同比上周</div>
             <div className="value">
             <div className="value">
-              <Icon type="caret-up" theme="filled" color="#6EC64B" />
-              <span>15</span>%
+              {diffLast > 0 ? <Icon type="caret-up" theme="filled" color="#6EC64B" /> : <Icon type="caret-down" theme="filled" color="#F36565" />}
+              <span>{diffLastPercent}</span>%
             </div>
             </div>
           </div>
           </div>
           <div className="item">
           <div className="item">
             <div className="text">同比全站</div>
             <div className="text">同比全站</div>
             <div className="value">
             <div className="value">
-              <Icon type="caret-down" theme="filled" color="#F36565" />
-              <span>15</span>%
+              {diff > 0 ? <Icon type="caret-up" theme="filled" color="#6EC64B" /> : <Icon type="caret-down" theme="filled" color="#F36565" />}
+              <span>{diffPercent}</span>%
             </div>
             </div>
           </div>
           </div>
         </div>
         </div>

+ 7 - 0
front/project/h5/stores/main.js

@@ -28,6 +28,13 @@ export default class MainStore extends BaseStore {
   }
   }
 
 
   /**
   /**
+   * 获取微信信息
+   */
+  getWechat() {
+    return this.apiGet('/base/wechat');
+  }
+
+  /**
    * 获取对应位置的提示tips
    * 获取对应位置的提示tips
    * @param {*} position
    * @param {*} position
    */
    */

+ 4 - 3
front/project/h5/stores/my.js

@@ -108,10 +108,11 @@ export default class MyStore extends BaseStore {
   }
   }
 
 
   /**
   /**
-   * 获取本周学习记录
+   * 获取每周学习记录
+   * @param {*} week 0本周,1上周
    */
    */
-  getStudyWeek() {
-    return this.apiGet('/my/study/week', {});
+  getStudyWeek(week) {
+    return this.apiGet('/my/study/week', { week });
   }
   }
 
 
   /**
   /**

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

@@ -19,7 +19,7 @@ const BIND_WX_ERROR = 'BIND_WX_ERROR';
 export default class Login extends Component {
 export default class Login extends Component {
   constructor(props) {
   constructor(props) {
     super(props);
     super(props);
-    this.state = { type: LOGIN_PHONE };
+    this.state = { type: LOGIN_PHONE, data: {} };
   }
   }
 
 
   close() {
   close() {

+ 7 - 3
front/project/www/local.json

@@ -14,9 +14,13 @@
     ]
     ]
   },
   },
   "test": {
   "test": {
-    "scripts": ["http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"]
+    "scripts": [
+      "http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"
+    ]
   },
   },
   "production": {
   "production": {
-    "scripts": ["http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"]
+    "scripts": [
+      "http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"
+    ]
   }
   }
-}
+}

+ 99 - 141
front/project/www/routes/paper/process/base/index.js

@@ -12,7 +12,7 @@ import Calculator from '../../../../components/Calculator';
 import AnswerSelect from '../../../../components/AnswerSelect';
 import AnswerSelect from '../../../../components/AnswerSelect';
 import AnswerTable from '../../../../components/AnswerTable';
 import AnswerTable from '../../../../components/AnswerTable';
 import Editor from '../../../../components/Editor';
 import Editor from '../../../../components/Editor';
-import { QuestionType } from '../../../../../Constant';
+import { QuestionType, ExaminationOrder } from '../../../../../Constant';
 
 
 const QuestionTypeMap = getMap(QuestionType, 'value');
 const QuestionTypeMap = getMap(QuestionType, 'value');
 
 
@@ -262,51 +262,15 @@ export default class extends Component {
   }
   }
 
 
   renderExaminationStart() {
   renderExaminationStart() {
-    const { disorder } = this.state;
+    // const { paper, userQuestion, singleTime, stageTime, flow } = this.props;
+    // const { showTime, showNo } = this.state;
     const { paper, flow } = this.props;
     const { paper, flow } = this.props;
     return (
     return (
-      <div className="start">
-        <div className="bg" />
-        <div className="fixed-content">
-          <div className="title">{paper.title}</div>
-          <div className="desc">
-            <div className="block">
-              <div className="desc-title">
-                <Assets name="subject_icon" />
-                题目总数
-              </div>
-              <div className="desc-info">{paper.questionNumer}</div>
-            </div>
-            <div className="block">
-              <div className="desc-title">
-                <Assets name="time_icon" />
-                建议用时
-              </div>
-              <div className="desc-info">{formatSeconds(paper.time)}</div>
-            </div>
-          </div>
-          <div className="tip">
-            <Checkbox className="m-r-1" checked={disorder} onChange={() => this.setState({ disorder: !disorder })} />
-            题目选项乱序显示
-          </div>
-          <div className="submit">
-            <Button size="lager" radius onClick={() => flow.start({ disorder })}>
-              开始练习
-            </Button>
-          </div>
-        </div>
-      </div>
-    );
-  }
-
-  renderExerciseStart() {
-    const { paper, userQuestion, singleTime, stageTime, flow } = this.props;
-    const { showTime, showNo } = this.state;
-    return (
       <div className="layout">
       <div className="layout">
+        <div className="fixed" />
         <div className="layout-header">
         <div className="layout-header">
           <div className="title">{paper.title}</div>
           <div className="title">{paper.title}</div>
-          <div className="right">
+          {/* <div className="right">
             <div
             <div
               className="block"
               className="block"
               onClick={() => {
               onClick={() => {
@@ -326,9 +290,9 @@ export default class extends Component {
               <Assets name="subjectnumber_icon" />
               <Assets name="subjectnumber_icon" />
               {showNo && `${userQuestion.no} of ${paper.questionNumber}`}
               {showNo && `${userQuestion.no} of ${paper.questionNumber}`}
             </div>
             </div>
-          </div>
+          </div> */}
         </div>
         </div>
-        <div className={'layout-body'}>{this.renderExerciseStartCAT()}</div>
+        <div className={'layout-body'}>{paper.isAdapt > 1 ? this.renderExaminationStartCAT() : this.renderExaminationStartDefault()}</div>
         <div className="layout-footer">
         <div className="layout-footer">
           <div className="help">
           <div className="help">
             <Assets name="help_icon" />
             <Assets name="help_icon" />
@@ -346,7 +310,47 @@ export default class extends Component {
     );
     );
   }
   }
 
 
-  renderExerciseStartDefault() {
+  renderExerciseStart() {
+    const { disorder } = this.state;
+    const { paper, flow } = this.props;
+    return (
+      <div className="start">
+        <div className="bg" />
+        <div className="fixed-content">
+          <div className="title">{paper.title}</div>
+          <div className="desc">
+            <div className="block">
+              <div className="desc-title">
+                <Assets name="subject_icon" />
+                题目总数
+              </div>
+              <div className="desc-info">{paper.questionNumer}</div>
+            </div>
+            <div className="block">
+              <div className="desc-title">
+                <Assets name="time_icon" />
+                建议用时
+              </div>
+              <div className="desc-info">{formatSeconds(paper.time)}</div>
+            </div>
+          </div>
+          {paper.times > 0 && <div className="tip">
+            <Checkbox className="m-r-1" checked={!disorder} onChange={() => this.setState({ disorder: !!disorder })} />
+            题目选项乱序显示
+          </div>}
+          <div className="submit">
+            <Button size="lager" radius onClick={() => flow.start({ disorder: paper.times > 0 ? !disorder : false })}>
+              开始练习
+            </Button>
+          </div>
+        </div>
+      </div>
+    );
+  }
+
+  renderExaminationStartCAT() {
+    const { disorder, order, orderIndex } = this.state;
+    const { paper, flow } = this.props;
     return (
     return (
       <div className="exercise-start default">
       <div className="exercise-start default">
         <div className="title">Section Ordering</div>
         <div className="title">Section Ordering</div>
@@ -361,50 +365,29 @@ export default class extends Component {
           selected, before moving on to the next section. You will NOT be able to return to this screen.
           selected, before moving on to the next section. You will NOT be able to return to this screen.
         </div>
         </div>
         <div className="block-list">
         <div className="block-list">
-          <div className="block-item">
-            <div className="block-title">
-              <div className="block-title-border">
-                <AntDIcon type="check" />
-                <span>ARQV</span>
+          {ExaminationOrder.map((row, index) => {
+            return <div className="block-item">
+              <div className="block-title" onClick={() => {
+                this.setState({ order: row.value, orderIndex: index });
+              }}>
+                <div className="block-title-border">
+                  {orderIndex === index && <AntDIcon type="check" />}
+                  <span>{row.label}</span>
+                </div>
               </div>
               </div>
-            </div>
-            <div className="block-text">1.Analytical Writing Analysis </div>
-            <div className="block-text">2.Integrated Reasoning </div>
-            <div className="block-text">3.Quantitative </div>
-            <div className="block-text">4.Verbal </div>
-          </div>
-          <div className="block-item">
-            <div className="block-title">
-              <div className="block-title-border">
-                <AntDIcon type="check" />
-                <span>VQRA </span>
-              </div>
-            </div>
-            <div className="block-text">1.Verbal </div>
-            <div className="block-text">2.Quantitative </div>
-            <div className="block-text">3.Integrated Reasoning </div>
-            <div className="block-text">4.Analytical Writing Analysis </div>
-          </div>
-          <div className="block-item">
-            <div className="block-title">
-              <div className="block-title-border">
-                <AntDIcon type="check" />
-                <span>QVRA</span>
-              </div>
-            </div>
-            <div className="block-text">1.Quantitative</div>
-            <div className="block-text">2.Verbal </div>
-            <div className="block-text">3.Integrated Reasoning </div>
-            <div className="block-text">4.Analytical Writing Analysis </div>
-          </div>
+              {row.list.map((r, i) => {
+                return <div className="block-text">{i + 1}.{r.label} </div>;
+              })}
+            </div>;
+          })}
         </div>
         </div>
         <div className="bottom">
         <div className="bottom">
-          <div className="text">
-            <Checkbox checked /> 题目选项乱序显示
-          </div>
+          {paper.times > 0 && <div className="text">
+            <Checkbox checked={!disorder} onChange={() => this.setState({ disorder: !!disorder })} /> 题目选项乱序显示
+          </div>}
           <div className="text">
           <div className="text">
             Click{' '}
             Click{' '}
-            <div className="next" onClick={() => this.next()}>
+            <div className="next" onClick={() => flow.start({ disorder: paper.times > 0 ? !disorder : false, order })}>
               Next
               Next
               <Assets name="next_icon" />
               <Assets name="next_icon" />
             </div>{' '}
             </div>{' '}
@@ -415,68 +398,44 @@ export default class extends Component {
     );
     );
   }
   }
 
 
-  renderExerciseStartCAT() {
+  renderExaminationStartDefault() {
+    const { disorder, order, orderIndex } = this.state;
+    const { paper, flow } = this.props;
     return (
     return (
       <div className="exercise-start cat">
       <div className="exercise-start cat">
         <div className="title">Section Ordering</div>
         <div className="title">Section Ordering</div>
         <div className="block-list">
         <div className="block-list">
-          <div className="block-item">
-            <div className="block-item-body active">
-              <AntDIcon type="check" style={{ color: '#fff' }} />
-              <div className="block-text">
-                <Checkbox checked /> Analytical Writing Analysis{' '}
-              </div>
-              <div className="block-text">
-                <Checkbox checked /> Integrated Reasoning{' '}
-              </div>
-              <div className="block-text">
-                <Checkbox checked /> Quantitative{' '}
-              </div>
-              <div className="block-text">
-                <Checkbox checked /> Verbal{' '}
-              </div>
-            </div>
-          </div>
-          <div className="block-item">
-            <div className="block-item-body">
-              <div className="block-text">
-                <Checkbox /> Quantitative
-              </div>
-              <div className="block-text">
-                <Checkbox /> Verbal{' '}
-              </div>
-              <div className="block-text">
-                <Checkbox /> Integrated Reasoning{' '}
-              </div>
-              <div className="block-text">
-                <Checkbox /> Analytical Writing Analysis{' '}
-              </div>
-            </div>
-          </div>
-          <div className="block-item">
-            <div className="block-item-body">
-              <div className="block-text">
-                <Checkbox /> Verbal{' '}
-              </div>
-              <div className="block-text">
-                <Checkbox /> Quantitative{' '}
-              </div>
-              <div className="block-text">
-                <Checkbox /> Integrated Reasoning{' '}
+          {ExaminationOrder.map((row, index) => {
+            return <div className="block-item" onClick={() => {
+              this.setState({ order: row.value, orderIndex: index });
+            }}>
+              <div className={orderIndex === index ? 'block-item-body active' : 'block-item-body'}>
+                {orderIndex === index && <AntDIcon type="check" style={{ color: '#fff' }} />}
+                {row.list.map((r, i) => {
+                  return <div className="block-text" onClick={() => {
+                    if (order.indexOf(r.value) > 0) {
+                      // 取消
+                      order[i] = '';
+                    } else {
+                      // 选中
+                      order[i] = r.value;
+                    }
+                    this.setState({ order });
+                  }}>
+                    <Checkbox checked={orderIndex === index ? order.indexOf(r.value) >= 0 : false} /> {r.label}{' '}
+                  </div>;
+                })}
               </div>
               </div>
-              <div className="block-text">
-                <Checkbox /> Analytical Writing Analysis{' '}
-              </div>
-            </div>
-          </div>
+            </div>;
+          })}
         </div>
         </div>
         <div className="bottom">
         <div className="bottom">
-          <div className="text">
-            <Checkbox checked /> 题目选项乱序显示
-          </div>
+          {paper.times > 0 && <div className="text">
+            <Checkbox checked={!disorder} onChange={() => this.setState({ disorder: !!disorder })} /> 题目选项乱序显示
+          </div>}
           <div className="text">
           <div className="text">
             Click{' '}
             Click{' '}
-            <div className="next" onClick={() => this.next()}>
+            <div className="next" onClick={() => flow.start({ disorder: paper.times > 0 ? !disorder : false, order: order.filter(row => row) })}>
               Next
               Next
               <Assets name="next_icon" />
               <Assets name="next_icon" />
             </div>{' '}
             </div>{' '}
@@ -565,12 +524,11 @@ export default class extends Component {
                 <span className="t-d-l">N</span>o
                 <span className="t-d-l">N</span>o
               </div>
               </div>
             </div>
             </div>
-          ) : (
-            <div className="btn-list">
-              <div className="btn" onClick={() => this.hideModal(true)}>
-                <span className="t-d-l">O</span>k
+          ) : (<div className="btn-list">
+            <div className="btn" onClick={() => this.hideModal(true)}>
+              <span className="t-d-l">O</span>k
               </div>
               </div>
-            </div>
+          </div>
           )}
           )}
         </div>
         </div>
       </div>
       </div>

+ 1 - 1
server/data/src/main/java/com/qxgmat/data/constants/enums/ServiceKey.java

@@ -3,7 +3,7 @@ package com.qxgmat.data.constants.enums;
 public enum ServiceKey {
 public enum ServiceKey {
     VIP("vip", 0, 0), // 收藏和错题处的组卷、导出;笔记导出功能;部分解析只有VIP可以看;下载模考报告; 解锁完整版模考报告;“提问开放”期间有提问权限
     VIP("vip", 0, 0), // 收藏和错题处的组卷、导出;笔记导出功能;部分解析只有VIP可以看;下载模考报告; 解锁完整版模考报告;“提问开放”期间有提问权限
     TEXTBOOK("textbook", 180, 30),
     TEXTBOOK("textbook", 180, 30),
-    QX_CAT("qx_cat", 180, 0), // 可以考2次
+    QX_CAT("qx_cat", 180, 180), // 可以考2次
 
 
     ;
     ;
     public String key;
     public String key;

+ 1 - 0
server/data/src/main/java/com/qxgmat/data/constants/enums/SettingKey.java

@@ -29,6 +29,7 @@ public enum SettingKey {
     PROMOTE("course_promote"), // 促销
     PROMOTE("course_promote"), // 促销
     EXPERIENCE_INFO("experience_info"), // 心经信息
     EXPERIENCE_INFO("experience_info"), // 心经信息
     SENTENCE_INFO("sentence_info"), // 长难句信息
     SENTENCE_INFO("sentence_info"), // 长难句信息
+    WECHAT_INFO("wechat_info"), // 微信公众号信息
 
 
     TIPS("tips"); // 页面提示信息
     TIPS("tips"); // 页面提示信息
 
 

+ 17 - 0
server/data/src/main/java/com/qxgmat/data/constants/enums/logic/TextbookLogic.java

@@ -1,5 +1,7 @@
 package com.qxgmat.data.constants.enums.logic;
 package com.qxgmat.data.constants.enums.logic;
 
 
+import com.qxgmat.data.constants.enums.QuestionType;
+
 public enum TextbookLogic {
 public enum TextbookLogic {
     DS("ds"), PS("ps"), DS_PS("ds+ps");
     DS("ds"), PS("ps"), DS_PS("ds+ps");
     public String key;
     public String key;
@@ -11,4 +13,19 @@ public enum TextbookLogic {
         if (name == null) return null;
         if (name == null) return null;
         return TextbookLogic.valueOf(name.toUpperCase());
         return TextbookLogic.valueOf(name.toUpperCase());
     }
     }
+
+    public static TextbookLogic[] all(){
+        return new TextbookLogic[]{DS, PS, DS_PS};
+    }
+
+    public boolean contain(QuestionType questionType){
+        switch(this){
+            case DS:
+                return questionType == QuestionType.DS;
+            case PS:
+                return questionType == QuestionType.PS;
+            default:
+                return questionType == QuestionType.DS || questionType == QuestionType.PS;
+        }
+    }
 }
 }

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

@@ -23,7 +23,7 @@ public class ExaminationPaper implements Serializable {
     private Integer structThree;
     private Integer structThree;
 
 
     /**
     /**
-     * 是否适应难度
+     * 是否适应难度: 0非适应性,1适应性,2千行
      */
      */
     @Column(name = "`is_adapt`")
     @Column(name = "`is_adapt`")
     private Integer isAdapt;
     private Integer isAdapt;
@@ -123,18 +123,18 @@ public class ExaminationPaper implements Serializable {
     }
     }
 
 
     /**
     /**
-     * 获取是否适应难度
+     * 获取是否适应难度: 0非适应性,1适应性,2千行
      *
      *
-     * @return is_adapt - 是否适应难度
+     * @return is_adapt - 是否适应难度: 0非适应性,1适应性,2千行
      */
      */
     public Integer getIsAdapt() {
     public Integer getIsAdapt() {
         return isAdapt;
         return isAdapt;
     }
     }
 
 
     /**
     /**
-     * 设置是否适应难度
+     * 设置是否适应难度: 0非适应性,1适应性,2千行
      *
      *
-     * @param isAdapt 是否适应难度
+     * @param isAdapt 是否适应难度: 0非适应性,1适应性,2千行
      */
      */
     public void setIsAdapt(Integer isAdapt) {
     public void setIsAdapt(Integer isAdapt) {
         this.isAdapt = isAdapt;
         this.isAdapt = isAdapt;
@@ -327,9 +327,9 @@ public class ExaminationPaper implements Serializable {
         }
         }
 
 
         /**
         /**
-         * 设置是否适应难度
+         * 设置是否适应难度: 0非适应性,1适应性,2千行
          *
          *
-         * @param isAdapt 是否适应难度
+         * @param isAdapt 是否适应难度: 0非适应性,1适应性,2千行
          */
          */
         public Builder isAdapt(Integer isAdapt) {
         public Builder isAdapt(Integer isAdapt) {
             obj.setIsAdapt(isAdapt);
             obj.setIsAdapt(isAdapt);

+ 92 - 22
server/data/src/main/java/com/qxgmat/data/dao/entity/TextbookLibraryHistory.java

@@ -57,10 +57,22 @@ public class TextbookLibraryHistory implements Serializable {
     private Date createTime;
     private Date createTime;
 
 
     /**
     /**
-     * 更新日志
+     * 数学更新日志
      */
      */
-    @Column(name = "`content`")
-    private String content;
+    @Column(name = "`quant_contennt`")
+    private String quantContennt;
+
+    /**
+     * 阅读更新日志
+     */
+    @Column(name = "`rc_content`")
+    private String rcContent;
+
+    /**
+     * 综合推理更新日志
+     */
+    @Column(name = "`ir_content`")
+    private String irContent;
 
 
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
 
 
@@ -219,21 +231,57 @@ public class TextbookLibraryHistory implements Serializable {
     }
     }
 
 
     /**
     /**
-     * 获取更新日志
+     * 获取数学更新日志
+     *
+     * @return quant_contennt - 数学更新日志
+     */
+    public String getQuantContennt() {
+        return quantContennt;
+    }
+
+    /**
+     * 设置数学更新日志
+     *
+     * @param quantContennt 数学更新日志
+     */
+    public void setQuantContennt(String quantContennt) {
+        this.quantContennt = quantContennt;
+    }
+
+    /**
+     * 获取阅读更新日志
+     *
+     * @return rc_content - 阅读更新日志
+     */
+    public String getRcContent() {
+        return rcContent;
+    }
+
+    /**
+     * 设置阅读更新日志
+     *
+     * @param rcContent 阅读更新日志
+     */
+    public void setRcContent(String rcContent) {
+        this.rcContent = rcContent;
+    }
+
+    /**
+     * 获取综合推理更新日志
      *
      *
-     * @return content - 更新日志
+     * @return ir_content - 综合推理更新日志
      */
      */
-    public String getContent() {
-        return content;
+    public String getIrContent() {
+        return irContent;
     }
     }
 
 
     /**
     /**
-     * 设置更新日志
+     * 设置综合推理更新日志
      *
      *
-     * @param content 更新日志
+     * @param irContent 综合推理更新日志
      */
      */
-    public void setContent(String content) {
-        this.content = content;
+    public void setIrContent(String irContent) {
+        this.irContent = irContent;
     }
     }
 
 
     @Override
     @Override
@@ -251,7 +299,9 @@ public class TextbookLibraryHistory implements Serializable {
         sb.append(", ir=").append(ir);
         sb.append(", ir=").append(ir);
         sb.append(", irVersion=").append(irVersion);
         sb.append(", irVersion=").append(irVersion);
         sb.append(", createTime=").append(createTime);
         sb.append(", createTime=").append(createTime);
-        sb.append(", content=").append(content);
+        sb.append(", quantContennt=").append(quantContennt);
+        sb.append(", rcContent=").append(rcContent);
+        sb.append(", irContent=").append(irContent);
         sb.append("]");
         sb.append("]");
         return sb.toString();
         return sb.toString();
     }
     }
@@ -296,6 +346,16 @@ public class TextbookLibraryHistory implements Serializable {
         }
         }
 
 
         /**
         /**
+         * 设置数学更新日志
+         *
+         * @param quantContennt 数学更新日志
+         */
+        public Builder quantContennt(String quantContennt) {
+            obj.setQuantContennt(quantContennt);
+            return this;
+        }
+
+        /**
          * 设置数学版本
          * 设置数学版本
          *
          *
          * @param quantVersion 数学版本
          * @param quantVersion 数学版本
@@ -316,6 +376,16 @@ public class TextbookLibraryHistory implements Serializable {
         }
         }
 
 
         /**
         /**
+         * 设置阅读更新日志
+         *
+         * @param rcContent 阅读更新日志
+         */
+        public Builder rcContent(String rcContent) {
+            obj.setRcContent(rcContent);
+            return this;
+        }
+
+        /**
          * 设置阅读版本
          * 设置阅读版本
          *
          *
          * @param rcVersion 阅读版本
          * @param rcVersion 阅读版本
@@ -336,6 +406,16 @@ public class TextbookLibraryHistory implements Serializable {
         }
         }
 
 
         /**
         /**
+         * 设置综合推理更新日志
+         *
+         * @param irContent 综合推理更新日志
+         */
+        public Builder irContent(String irContent) {
+            obj.setIrContent(irContent);
+            return this;
+        }
+
+        /**
          * 设置综合推理版本
          * 设置综合推理版本
          *
          *
          * @param irVersion 综合推理版本
          * @param irVersion 综合推理版本
@@ -353,16 +433,6 @@ public class TextbookLibraryHistory implements Serializable {
             return this;
             return this;
         }
         }
 
 
-        /**
-         * 设置更新日志
-         *
-         * @param content 更新日志
-         */
-        public Builder content(String content) {
-            obj.setContent(content);
-            return this;
-        }
-
         public TextbookLibraryHistory build() {
         public TextbookLibraryHistory build() {
             return this.obj;
             return this.obj;
         }
         }

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

@@ -12,12 +12,6 @@ public class TextbookPaper implements Serializable {
     private Integer id;
     private Integer id;
 
 
     /**
     /**
-     * 所属时间
-     */
-    @Column(name = "`time`")
-    private String time;
-
-    /**
      * 标题
      * 标题
      */
      */
     @Column(name = "`title`")
     @Column(name = "`title`")
@@ -59,6 +53,12 @@ public class TextbookPaper implements Serializable {
     @Column(name = "`status`")
     @Column(name = "`status`")
     private Integer status;
     private Integer status;
 
 
+    /**
+     * 所属年份
+     */
+    @Column(name = "`year`")
+    private String year;
+
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
 
 
     /**
     /**
@@ -76,24 +76,6 @@ public class TextbookPaper implements Serializable {
     }
     }
 
 
     /**
     /**
-     * 获取所属时间
-     *
-     * @return time - 所属时间
-     */
-    public String getTime() {
-        return time;
-    }
-
-    /**
-     * 设置所属时间
-     *
-     * @param time 所属时间
-     */
-    public void setTime(String time) {
-        this.time = time;
-    }
-
-    /**
      * 获取标题
      * 获取标题
      *
      *
      * @return title - 标题
      * @return title - 标题
@@ -229,6 +211,24 @@ public class TextbookPaper implements Serializable {
         this.status = status;
         this.status = status;
     }
     }
 
 
+    /**
+     * 获取所属年份
+     *
+     * @return year - 所属年份
+     */
+    public String getYear() {
+        return year;
+    }
+
+    /**
+     * 设置所属年份
+     *
+     * @param year 所属年份
+     */
+    public void setYear(String year) {
+        this.year = year;
+    }
+
     @Override
     @Override
     public String toString() {
     public String toString() {
         StringBuilder sb = new StringBuilder();
         StringBuilder sb = new StringBuilder();
@@ -236,7 +236,6 @@ public class TextbookPaper implements Serializable {
         sb.append(" [");
         sb.append(" [");
         sb.append("Hash = ").append(hashCode());
         sb.append("Hash = ").append(hashCode());
         sb.append(", id=").append(id);
         sb.append(", id=").append(id);
-        sb.append(", time=").append(time);
         sb.append(", title=").append(title);
         sb.append(", title=").append(title);
         sb.append(", logic=").append(logic);
         sb.append(", logic=").append(logic);
         sb.append(", no=").append(no);
         sb.append(", no=").append(no);
@@ -245,6 +244,7 @@ public class TextbookPaper implements Serializable {
         sb.append(", questionNumber=").append(questionNumber);
         sb.append(", questionNumber=").append(questionNumber);
         sb.append(", createTime=").append(createTime);
         sb.append(", createTime=").append(createTime);
         sb.append(", status=").append(status);
         sb.append(", status=").append(status);
+        sb.append(", year=").append(year);
         sb.append("]");
         sb.append("]");
         return sb.toString();
         return sb.toString();
     }
     }
@@ -269,16 +269,6 @@ public class TextbookPaper implements Serializable {
         }
         }
 
 
         /**
         /**
-         * 设置所属时间
-         *
-         * @param time 所属时间
-         */
-        public Builder time(String time) {
-            obj.setTime(time);
-            return this;
-        }
-
-        /**
          * 设置标题
          * 设置标题
          *
          *
          * @param title 标题
          * @param title 标题
@@ -354,6 +344,16 @@ public class TextbookPaper implements Serializable {
             return this;
             return this;
         }
         }
 
 
+        /**
+         * 设置所属年份
+         *
+         * @param year 所属年份
+         */
+        public Builder year(String year) {
+            obj.setYear(year);
+            return this;
+        }
+
         public TextbookPaper build() {
         public TextbookPaper build() {
             return this.obj;
             return this.obj;
         }
         }

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

@@ -53,10 +53,10 @@ public class TextbookQuestion implements Serializable {
     private Integer totalCorrect;
     private Integer totalCorrect;
 
 
     /**
     /**
-     * 所属时间
+     * 所属年份
      */
      */
-    @Column(name = "`time`")
-    private String time;
+    @Column(name = "`year`")
+    private String year;
 
 
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
 
 
@@ -201,21 +201,21 @@ public class TextbookQuestion implements Serializable {
     }
     }
 
 
     /**
     /**
-     * 获取所属时间
+     * 获取所属年份
      *
      *
-     * @return time - 所属时间
+     * @return year - 所属年份
      */
      */
-    public String getTime() {
-        return time;
+    public String getYear() {
+        return year;
     }
     }
 
 
     /**
     /**
-     * 设置所属时间
+     * 设置所属年份
      *
      *
-     * @param time 所属时间
+     * @param year 所属年份
      */
      */
-    public void setTime(String time) {
-        this.time = time;
+    public void setYear(String year) {
+        this.year = year;
     }
     }
 
 
     @Override
     @Override
@@ -232,7 +232,7 @@ public class TextbookQuestion implements Serializable {
         sb.append(", totalTime=").append(totalTime);
         sb.append(", totalTime=").append(totalTime);
         sb.append(", totalNumber=").append(totalNumber);
         sb.append(", totalNumber=").append(totalNumber);
         sb.append(", totalCorrect=").append(totalCorrect);
         sb.append(", totalCorrect=").append(totalCorrect);
-        sb.append(", time=").append(time);
+        sb.append(", year=").append(year);
         sb.append("]");
         sb.append("]");
         return sb.toString();
         return sb.toString();
     }
     }
@@ -327,12 +327,12 @@ public class TextbookQuestion implements Serializable {
         }
         }
 
 
         /**
         /**
-         * 设置所属时间
+         * 设置所属年份
          *
          *
-         * @param time 所属时间
+         * @param year 所属年份
          */
          */
-        public Builder time(String time) {
-            obj.setTime(time);
+        public Builder year(String year) {
+            obj.setYear(year);
             return this;
             return this;
         }
         }
 
 

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

@@ -36,6 +36,12 @@ public class UserPaper implements Serializable {
     private String paperOrigin;
     private String paperOrigin;
 
 
     /**
     /**
+     * 模考:是否适应难度: 0非适应性,1适应性,2千行
+     */
+    @Column(name = "`is_adapt`")
+    private Integer isAdapt;
+
+    /**
      * 对应来源id
      * 对应来源id
      */
      */
     @Column(name = "`origin_id`")
     @Column(name = "`origin_id`")
@@ -196,6 +202,24 @@ public class UserPaper implements Serializable {
     }
     }
 
 
     /**
     /**
+     * 获取模考:是否适应难度: 0非适应性,1适应性,2千行
+     *
+     * @return is_adapt - 模考:是否适应难度: 0非适应性,1适应性,2千行
+     */
+    public Integer getIsAdapt() {
+        return isAdapt;
+    }
+
+    /**
+     * 设置模考:是否适应难度: 0非适应性,1适应性,2千行
+     *
+     * @param isAdapt 模考:是否适应难度: 0非适应性,1适应性,2千行
+     */
+    public void setIsAdapt(Integer isAdapt) {
+        this.isAdapt = isAdapt;
+    }
+
+    /**
      * 获取对应来源id
      * 获取对应来源id
      *
      *
      * @return origin_id - 对应来源id
      * @return origin_id - 对应来源id
@@ -422,6 +446,7 @@ public class UserPaper implements Serializable {
         sb.append(", title=").append(title);
         sb.append(", title=").append(title);
         sb.append(", paperModule=").append(paperModule);
         sb.append(", paperModule=").append(paperModule);
         sb.append(", paperOrigin=").append(paperOrigin);
         sb.append(", paperOrigin=").append(paperOrigin);
+        sb.append(", isAdapt=").append(isAdapt);
         sb.append(", originId=").append(originId);
         sb.append(", originId=").append(originId);
         sb.append(", recordId=").append(recordId);
         sb.append(", recordId=").append(recordId);
         sb.append(", questionNoIds=").append(questionNoIds);
         sb.append(", questionNoIds=").append(questionNoIds);
@@ -498,6 +523,16 @@ public class UserPaper implements Serializable {
         }
         }
 
 
         /**
         /**
+         * 设置模考:是否适应难度: 0非适应性,1适应性,2千行
+         *
+         * @param isAdapt 模考:是否适应难度: 0非适应性,1适应性,2千行
+         */
+        public Builder isAdapt(Integer isAdapt) {
+            obj.setIsAdapt(isAdapt);
+            return this;
+        }
+
+        /**
          * 设置对应来源id
          * 设置对应来源id
          *
          *
          * @param originId 对应来源id
          * @param originId 对应来源id

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

@@ -105,6 +105,12 @@ public class UserReport implements Serializable {
     @Column(name = "`is_finish`")
     @Column(name = "`is_finish`")
     private Integer isFinish;
     private Integer isFinish;
 
 
+    /**
+     * 是否完成报告
+     */
+    @Column(name = "`is_stat`")
+    private Integer isStat;
+
     @Column(name = "`create_time`")
     @Column(name = "`create_time`")
     private Date createTime;
     private Date createTime;
 
 
@@ -412,6 +418,24 @@ public class UserReport implements Serializable {
     }
     }
 
 
     /**
     /**
+     * 获取是否完成报告
+     *
+     * @return is_stat - 是否完成报告
+     */
+    public Integer getIsStat() {
+        return isStat;
+    }
+
+    /**
+     * 设置是否完成报告
+     *
+     * @param isStat 是否完成报告
+     */
+    public void setIsStat(Integer isStat) {
+        this.isStat = isStat;
+    }
+
+    /**
      * @return create_time
      * @return create_time
      */
      */
     public Date getCreateTime() {
     public Date getCreateTime() {
@@ -462,6 +486,7 @@ public class UserReport implements Serializable {
         sb.append(", score=").append(score);
         sb.append(", score=").append(score);
         sb.append(", detail=").append(detail);
         sb.append(", detail=").append(detail);
         sb.append(", isFinish=").append(isFinish);
         sb.append(", isFinish=").append(isFinish);
+        sb.append(", isStat=").append(isStat);
         sb.append(", createTime=").append(createTime);
         sb.append(", createTime=").append(createTime);
         sb.append(", updateTime=").append(updateTime);
         sb.append(", updateTime=").append(updateTime);
         sb.append("]");
         sb.append("]");
@@ -646,6 +671,16 @@ public class UserReport implements Serializable {
         }
         }
 
 
         /**
         /**
+         * 设置是否完成报告
+         *
+         * @param isStat 是否完成报告
+         */
+        public Builder isStat(Integer isStat) {
+            obj.setIsStat(isStat);
+            return this;
+        }
+
+        /**
          * @param createTime
          * @param createTime
          */
          */
         public Builder createTime(Date createTime) {
         public Builder createTime(Date createTime) {

+ 0 - 20
server/data/src/main/java/com/qxgmat/data/dao/mapping/CourseStudentOnlineMapper.xml

@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.qxgmat.data.dao.CourseStudentOnlineMapper">
-  <resultMap id="BaseResultMap" type="com.qxgmat.data.dao.entity.CourseStudentOnline">
-    <!--
-      WARNING - @mbg.generated
-    -->
-    <id column="id" jdbcType="INTEGER" property="id" />
-    <result column="course_id" jdbcType="INTEGER" property="courseId" />
-    <result column="time_id" jdbcType="INTEGER" property="timeId" />
-    <result column="user_id" jdbcType="INTEGER" property="userId" />
-    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
-  </resultMap>
-  <sql id="Base_Column_List">
-    <!--
-      WARNING - @mbg.generated
-    -->
-    `id`, `course_id`, `time_id`, `user_id`, `create_time`
-  </sql>
-</mapper>

+ 4 - 2
server/data/src/main/java/com/qxgmat/data/dao/mapping/TextbookLibraryHistoryMapper.xml

@@ -19,7 +19,9 @@
     <!--
     <!--
       WARNING - @mbg.generated
       WARNING - @mbg.generated
     -->
     -->
-    <result column="content" jdbcType="LONGVARCHAR" property="content" />
+    <result column="quant_contennt" jdbcType="LONGVARCHAR" property="quantContennt" />
+    <result column="rc_content" jdbcType="LONGVARCHAR" property="rcContent" />
+    <result column="ir_content" jdbcType="LONGVARCHAR" property="irContent" />
   </resultMap>
   </resultMap>
   <sql id="Base_Column_List">
   <sql id="Base_Column_List">
     <!--
     <!--
@@ -32,6 +34,6 @@
     <!--
     <!--
       WARNING - @mbg.generated
       WARNING - @mbg.generated
     -->
     -->
-    `content`
+    `quant_contennt`, `rc_content`, `ir_content`
   </sql>
   </sql>
 </mapper>
 </mapper>

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

@@ -6,7 +6,6 @@
       WARNING - @mbg.generated
       WARNING - @mbg.generated
     -->
     -->
     <id column="id" jdbcType="INTEGER" property="id" />
     <id column="id" jdbcType="INTEGER" property="id" />
-    <result column="time" jdbcType="VARCHAR" property="time" />
     <result column="title" jdbcType="VARCHAR" property="title" />
     <result column="title" jdbcType="VARCHAR" property="title" />
     <result column="logic" jdbcType="VARCHAR" property="logic" />
     <result column="logic" jdbcType="VARCHAR" property="logic" />
     <result column="no" jdbcType="INTEGER" property="no" />
     <result column="no" jdbcType="INTEGER" property="no" />
@@ -15,12 +14,13 @@
     <result column="question_number" jdbcType="INTEGER" property="questionNumber" />
     <result column="question_number" jdbcType="INTEGER" property="questionNumber" />
     <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
     <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
     <result column="status" jdbcType="INTEGER" property="status" />
     <result column="status" jdbcType="INTEGER" property="status" />
+    <result column="year" jdbcType="VARCHAR" property="year" />
   </resultMap>
   </resultMap>
   <sql id="Base_Column_List">
   <sql id="Base_Column_List">
     <!--
     <!--
       WARNING - @mbg.generated
       WARNING - @mbg.generated
     -->
     -->
-    `id`, `time`, `title`, `logic`, `no`, `library_id`, `question_no_ids`, `question_number`, 
-    `create_time`, `status`
+    `id`, `title`, `logic`, `no`, `library_id`, `question_no_ids`, `question_number`, 
+    `create_time`, `status`, `year`
   </sql>
   </sql>
 </mapper>
 </mapper>

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

@@ -13,13 +13,13 @@
     <result column="total_time" jdbcType="INTEGER" property="totalTime" />
     <result column="total_time" jdbcType="INTEGER" property="totalTime" />
     <result column="total_number" jdbcType="INTEGER" property="totalNumber" />
     <result column="total_number" jdbcType="INTEGER" property="totalNumber" />
     <result column="total_correct" jdbcType="INTEGER" property="totalCorrect" />
     <result column="total_correct" jdbcType="INTEGER" property="totalCorrect" />
-    <result column="time" jdbcType="VARCHAR" property="time" />
+    <result column="year" jdbcType="VARCHAR" property="year" />
   </resultMap>
   </resultMap>
   <sql id="Base_Column_List">
   <sql id="Base_Column_List">
     <!--
     <!--
       WARNING - @mbg.generated
       WARNING - @mbg.generated
     -->
     -->
     `id`, `title`, `no`, `library_id`, `question_id`, `total_time`, `total_number`, `total_correct`, 
     `id`, `title`, `no`, `library_id`, `question_id`, `total_time`, `total_number`, `total_correct`, 
-    `time`
+    `year`
   </sql>
   </sql>
 </mapper>
 </mapper>

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

@@ -10,6 +10,7 @@
     <result column="title" jdbcType="VARCHAR" property="title" />
     <result column="title" jdbcType="VARCHAR" property="title" />
     <result column="paper_module" jdbcType="VARCHAR" property="paperModule" />
     <result column="paper_module" jdbcType="VARCHAR" property="paperModule" />
     <result column="paper_origin" jdbcType="VARCHAR" property="paperOrigin" />
     <result column="paper_origin" jdbcType="VARCHAR" property="paperOrigin" />
+    <result column="is_adapt" jdbcType="INTEGER" property="isAdapt" />
     <result column="origin_id" jdbcType="INTEGER" property="originId" />
     <result column="origin_id" jdbcType="INTEGER" property="originId" />
     <result column="record_id" jdbcType="INTEGER" property="recordId" />
     <result column="record_id" jdbcType="INTEGER" property="recordId" />
     <result column="question_no_ids" jdbcType="VARCHAR" property="questionNoIds" typeHandler="com.nuliji.tools.mybatis.handler.IntegerArrayWithJsonHandler" />
     <result column="question_no_ids" jdbcType="VARCHAR" property="questionNoIds" typeHandler="com.nuliji.tools.mybatis.handler.IntegerArrayWithJsonHandler" />
@@ -27,8 +28,8 @@
     <!--
     <!--
       WARNING - @mbg.generated
       WARNING - @mbg.generated
     -->
     -->
-    `id`, `user_id`, `title`, `paper_module`, `paper_origin`, `origin_id`, `record_id`, 
-    `question_no_ids`, `question_number`, `times`, `time`, `latest_time`, `total_time`, 
-    `total_number`, `total_correct`, `delete_time`, `is_reset`
+    `id`, `user_id`, `title`, `paper_module`, `paper_origin`, `is_adapt`, `origin_id`, 
+    `record_id`, `question_no_ids`, `question_number`, `times`, `time`, `latest_time`, 
+    `total_time`, `total_number`, `total_correct`, `delete_time`, `is_reset`
   </sql>
   </sql>
 </mapper>
 </mapper>

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

@@ -22,6 +22,7 @@
     <result column="score" jdbcType="VARCHAR" property="score" typeHandler="com.nuliji.tools.mybatis.handler.JsonObjectHandler" />
     <result column="score" jdbcType="VARCHAR" property="score" typeHandler="com.nuliji.tools.mybatis.handler.JsonObjectHandler" />
     <result column="detail" jdbcType="VARCHAR" property="detail" typeHandler="com.nuliji.tools.mybatis.handler.JsonObjectHandler" />
     <result column="detail" jdbcType="VARCHAR" property="detail" typeHandler="com.nuliji.tools.mybatis.handler.JsonObjectHandler" />
     <result column="is_finish" jdbcType="INTEGER" property="isFinish" />
     <result column="is_finish" jdbcType="INTEGER" property="isFinish" />
+    <result column="is_stat" jdbcType="INTEGER" property="isStat" />
     <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
     <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
     <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
     <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
   </resultMap>
   </resultMap>
@@ -31,6 +32,6 @@
     -->
     -->
     `id`, `user_id`, `paper_id`, `paper_module`, `paper_origin`, `origin_id`, `question_no_ids`, 
     `id`, `user_id`, `paper_id`, `paper_module`, `paper_origin`, `origin_id`, `question_no_ids`, 
     `question_number`, `time`, `user_number`, `user_time`, `user_correct`, `finish_time`, 
     `question_number`, `time`, `user_number`, `user_time`, `user_correct`, `finish_time`, 
-    `setting`, `score`, `detail`, `is_finish`, `create_time`, `update_time`
+    `setting`, `score`, `detail`, `is_finish`, `is_stat`, `create_time`, `update_time`
   </sql>
   </sql>
 </mapper>
 </mapper>

+ 36 - 0
server/data/src/main/java/com/qxgmat/data/relation/PreviewAssignRelationMapper.java

@@ -0,0 +1,36 @@
+package com.qxgmat.data.relation;
+
+import com.qxgmat.data.dao.entity.ExercisePaper;
+import com.qxgmat.data.dao.entity.PreviewAssign;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Created by gaojie on 2017/11/9.
+ */
+public interface PreviewAssignRelationMapper {
+
+    List<PreviewAssign> listByCourse(
+            @Param("courseId") Number courseId,
+            @Param("userId") Number userId,
+            @Param("times") Integer times
+    );
+
+    List<PreviewAssign> listByAppointment(
+            @Param("courseId") Number courseId,
+            @Param("appointmentIds") Collection appointmentIds,
+            @Param("userId") Number userId,
+            @Param("endTime") String endTime,
+            @Param("times") Integer times
+    );
+
+    List<PreviewAssign> listByTime(
+            @Param("courseId") Number courseId,
+            @Param("timeId") Number timeId,
+            @Param("userId") Number userId,
+            @Param("endTime") String endTime,
+            @Param("times") Integer times
+    );
+}

+ 19 - 0
server/data/src/main/java/com/qxgmat/data/relation/TextbookPaperRelationMapper.java

@@ -0,0 +1,19 @@
+package com.qxgmat.data.relation;
+
+import com.qxgmat.data.dao.entity.ExercisePaper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * Created by gaojie on 2017/11/9.
+ */
+public interface TextbookPaperRelationMapper {
+
+    List<ExercisePaper> listWithUser(
+            @Param("libraryId") Number libraryId,
+            @Param("userId") Number userId,
+            @Param("logic") String logic,
+            @Param("times") Integer times
+    );
+}

+ 14 - 6
server/data/src/main/java/com/qxgmat/data/relation/UserCourseRecordRelationMapper.java

@@ -1,20 +1,28 @@
 package com.qxgmat.data.relation;
 package com.qxgmat.data.relation;
 
 
-import com.qxgmat.data.dao.entity.UserReport;
-import com.qxgmat.data.relation.entity.UserCourseStatRelation;
+import com.qxgmat.data.relation.entity.UserModuleRecordStatRelation;
 import com.qxgmat.data.relation.entity.UserRankStatRelation;
 import com.qxgmat.data.relation.entity.UserRankStatRelation;
-import com.qxgmat.data.relation.entity.UserReportLimitRelation;
-import com.qxgmat.data.relation.entity.UserStudyStatRelation;
+import com.qxgmat.data.relation.entity.UserRecordStatRelation;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Param;
 
 
-import java.util.Collection;
 import java.util.List;
 import java.util.List;
 
 
 /**
 /**
  * Created by gaojie on 2017/11/9.
  * Created by gaojie on 2017/11/9.
  */
  */
 public interface UserCourseRecordRelationMapper {
 public interface UserCourseRecordRelationMapper {
-    List<UserCourseStatRelation> statGroupType(
+    List<UserRecordStatRelation> stat(
+            @Param("userId") Integer userId,
+            @Param("startTime") String startTime,
+            @Param("endTime") String endTime
+    );
+
+    List<UserRecordStatRelation> statAvg(
+            @Param("startTime") String startTime,
+            @Param("endTime") String endTime
+    );
+
+    List<UserModuleRecordStatRelation> statGroupType(
             @Param("userId") Integer userId,
             @Param("userId") Integer userId,
             @Param("startTime") String startTime,
             @Param("startTime") String startTime,
             @Param("endTime") String endTime
             @Param("endTime") String endTime

+ 8 - 0
server/data/src/main/java/com/qxgmat/data/relation/UserOrderRecordRelationMapper.java

@@ -22,6 +22,14 @@ public interface UserOrderRecordRelationMapper {
             @Param("direction") String direction
             @Param("direction") String direction
     );
     );
 
 
+    List<UserOrderRecord> listWithVs(
+            @Param("vsType") String vsType,
+            @Param("courseId") Integer courseId,
+            @Param("userId") Integer userId,
+            @Param("order") String order,
+            @Param("direction") String direction
+    );
+
     List<CourseStudentNumberRelation> groupByTime(
     List<CourseStudentNumberRelation> groupByTime(
             @Param("ids") Collection ids
             @Param("ids") Collection ids
     );
     );

+ 22 - 0
server/data/src/main/java/com/qxgmat/data/relation/UserQuestionRelationMapper.java

@@ -0,0 +1,22 @@
+package com.qxgmat.data.relation;
+
+import com.qxgmat.data.relation.entity.UserRecordStatRelation;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * Created by gaojie on 2017/11/9.
+ */
+public interface UserQuestionRelationMapper {
+    List<UserRecordStatRelation> stat(
+            @Param("userId") Integer userId,
+            @Param("startTime") String startTime,
+            @Param("endTime") String endTime
+    );
+
+    List<UserRecordStatRelation> statAvg(
+            @Param("startTime") String startTime,
+            @Param("endTime") String endTime
+    );
+}

+ 7 - 2
server/data/src/main/java/com/qxgmat/data/relation/UserSentenceRecordRelationMapper.java

@@ -1,6 +1,6 @@
 package com.qxgmat.data.relation;
 package com.qxgmat.data.relation;
 
 
-import com.qxgmat.data.relation.entity.UserSentenceStatRelation;
+import com.qxgmat.data.relation.entity.UserRecordStatRelation;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Param;
 
 
 import java.util.List;
 import java.util.List;
@@ -9,9 +9,14 @@ import java.util.List;
  * Created by gaojie on 2017/11/9.
  * Created by gaojie on 2017/11/9.
  */
  */
 public interface UserSentenceRecordRelationMapper {
 public interface UserSentenceRecordRelationMapper {
-    List<UserSentenceStatRelation> stat(
+    List<UserRecordStatRelation> stat(
             @Param("userId") Integer userId,
             @Param("userId") Integer userId,
             @Param("startTime") String startTime,
             @Param("startTime") String startTime,
             @Param("endTime") String endTime
             @Param("endTime") String endTime
     );
     );
+
+    List<UserRecordStatRelation> statAvg(
+            @Param("startTime") String startTime,
+            @Param("endTime") String endTime
+    );
 }
 }

+ 1 - 1
server/data/src/main/java/com/qxgmat/data/relation/entity/UserCourseStatRelation.java

@@ -2,7 +2,7 @@ package com.qxgmat.data.relation.entity;
 
 
 import javax.persistence.Column;
 import javax.persistence.Column;
 
 
-public class UserCourseStatRelation {
+public class UserModuleRecordStatRelation {
     /**
     /**
      * 对应模块或题型
      * 对应模块或题型
      */
      */

+ 1 - 1
server/data/src/main/java/com/qxgmat/data/relation/entity/UserSentenceStatRelation.java

@@ -2,7 +2,7 @@ package com.qxgmat.data.relation.entity;
 
 
 import javax.persistence.Column;
 import javax.persistence.Column;
 
 
-public class UserSentenceStatRelation {
+public class UserRecordStatRelation {
     /**
     /**
      * 用户做题时间
      * 用户做题时间
      */
      */

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

@@ -31,10 +31,10 @@
     </if>
     </if>
     where 1
     where 1
     <if test="structId != null">
     <if test="structId != null">
-      and ep.`struct_three` = #{structId,jdbcType=VARCHAR} or ep.`struct_four` = #{structId,jdbcType=VARCHAR}
+      and (ep.`struct_three` = #{structId,jdbcType=VARCHAR} or ep.`struct_four` = #{structId,jdbcType=VARCHAR})
     </if>
     </if>
     <if test="userId != null">
     <if test="userId != null">
-      and up.`id` != null
+      and up.`id` &gt; 0
     </if>
     </if>
   </select>
   </select>
 </mapper>
 </mapper>

+ 1 - 1
server/data/src/main/java/com/qxgmat/data/relation/mapping/ExercisePaperRelationMapper.xml

@@ -43,7 +43,7 @@
     </if>
     </if>
     where 1
     where 1
     <if test="structId != null">
     <if test="structId != null">
-      and ep.`struct_three` = #{structId,jdbcType=VARCHAR} or ep.`struct_four` = #{structId,jdbcType=VARCHAR}
+      and (ep.`struct_three` = #{structId,jdbcType=VARCHAR} or ep.`struct_four` = #{structId,jdbcType=VARCHAR})
     </if>
     </if>
     <if test="userId != null">
     <if test="userId != null">
       and up.`id` &gt; 0
       and up.`id` &gt; 0

+ 97 - 0
server/data/src/main/java/com/qxgmat/data/relation/mapping/PreviewAssignRelationMapper.xml

@@ -0,0 +1,97 @@
+<?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.PreviewAssignRelationMapper">
+  <resultMap id="IdMap" type="com.qxgmat.data.dao.entity.PreviewAssign">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    <id column="id" jdbcType="INTEGER" property="id" />
+  </resultMap>
+  <sql id="Id_Column_List">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    ep.`id`
+  </sql>
+
+  <!--
+   视频课程作业列表
+  -->
+  <select id="listByCourse" resultMap="IdMap">
+    select
+    <include refid="Id_Column_List" />
+    from `preview_assign` pa
+    <if test="userId != null">
+    left join `user_paper` up on ep.`id` = up.`origin_id`
+      and up.`paper_origin` = 'preview'
+      and up.`user_id` = #{userId,jdbcType=VARCHAR}
+      <if test="times != null">
+        and up.`times` >= #{times,jdbcType=VARCHAR}
+      </if>
+    </if>
+    where 1
+    <if test="courseId != null">
+      and pa.`course_id` = #{courseId,jdbcType=VARCHAR}
+    </if>
+    <if test="userId != null">
+      and up.`id` &gt; 0
+    </if>
+  </select>
+
+  <!--
+   1v1课程作业列表
+  -->
+  <select id="listByAppointment" resultMap="IdMap">
+    select
+    <include refid="Id_Column_List" />
+    from `preview_assign` pa
+    <if test="userId != null">
+      left join `user_paper` up on ep.`id` = up.`origin_id`
+      and up.`paper_origin` = 'preview'
+      and up.`user_id` = #{userId,jdbcType=VARCHAR}
+      <if test="times != null">
+        and up.`times` >= #{times,jdbcType=VARCHAR}
+      </if>
+    </if>
+    where 1
+    <if test="courseId != null">
+      and pa.`course_id` = #{courseId,jdbcType=VARCHAR}
+    </if>
+    <if test="appointmentIds != null">
+      pa.`course_appointment` IN
+      <foreach collection="appointmentIds" item="item" index="index" open="(" close=")" separator=",">
+        #{item}
+      </foreach>
+    </if>
+    <if test="userId != null">
+      and up.`id` &gt; 0
+    </if>
+  </select>
+
+  <!--
+   小班课程作业列表
+  -->
+  <select id="listByAppointment" resultMap="IdMap">
+    select
+    <include refid="Id_Column_List" />
+    from `preview_assign` pa
+    <if test="userId != null">
+      left join `user_paper` up on ep.`id` = up.`origin_id`
+      and up.`paper_origin` = 'preview'
+      and up.`user_id` = #{userId,jdbcType=VARCHAR}
+      <if test="times != null">
+        and up.`times` >= #{times,jdbcType=VARCHAR}
+      </if>
+    </if>
+    where 1
+    <if test="courseId != null">
+      and pa.`course_id` = #{courseId,jdbcType=VARCHAR}
+    </if>
+    <if test="timeId != null">
+      and pa.`course_time` = #{timeId,jdbcType=VARCHAR}
+    </if>
+    <if test="userId != null">
+      and up.`id` &gt; 0
+    </if>
+  </select>
+</mapper>

+ 40 - 0
server/data/src/main/java/com/qxgmat/data/relation/mapping/TextbookPaperRelationMapper.xml

@@ -0,0 +1,40 @@
+<?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.TextbookPaperRelationMapper">
+  <resultMap id="IdMap" type="com.qxgmat.data.dao.entity.TextbookPaper">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    <id column="id" jdbcType="INTEGER" property="id" />
+  </resultMap>
+  <sql id="Id_Column_List">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    ep.`id`
+  </sql>
+
+  <!--
+    用户机经-练习册列表: 用户端
+  -->
+  <select id="listWithUser" resultMap="IdMap">
+    select
+    <include refid="Id_Column_List" />
+    from `textbook_paper` tp
+    <if test="userId != null">
+    left join `user_paper` up on ep.`id` = up.`origin_id`
+      and up.`paper_origin` = 'textbook'
+      and up.`user_id` = #{userId,jdbcType=VARCHAR}
+      <if test="times != null">
+        and up.`times` >= #{times,jdbcType=VARCHAR}
+      </if>
+    </if>
+    where 1
+    <if test="libraryId != null">
+      and tp.`library_id` = #{libraryId,jdbcType=VARCHAR}
+    </if>
+    <if test="userId != null">
+      and up.`id` &gt; 0
+    </if>
+  </select>
+</mapper>

+ 1 - 1
server/data/src/main/java/com/qxgmat/data/relation/mapping/TextbookQuestionRelationMapper.xml

@@ -35,7 +35,7 @@
     </if>
     </if>
     where 1
     where 1
     <if test="paperId != null">
     <if test="paperId != null">
-      and tp.`id` != null
+      and tp.`id` &gt; 0
     </if>
     </if>
     <if test="questionNoId != null">
     <if test="questionNoId != null">
       and tq.`id` =#{questionNoId,jdbcType=VARCHAR}
       and tq.`id` =#{questionNoId,jdbcType=VARCHAR}

+ 41 - 1
server/data/src/main/java/com/qxgmat/data/relation/mapping/UserCourseRecordRelationMapper.xml

@@ -7,7 +7,13 @@
     -->
     -->
     <id column="id" jdbcType="INTEGER" property="id" />
     <id column="id" jdbcType="INTEGER" property="id" />
   </resultMap>
   </resultMap>
-  <resultMap id="studyMap" type="com.qxgmat.data.relation.entity.UserCourseStatRelation">
+  <resultMap id="studyMap" type="com.qxgmat.data.relation.entity.UserRecordStatRelation">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    <id column="user_time" jdbcType="INTEGER" property="user_time" />
+  </resultMap>
+  <resultMap id="studyModuleMap" type="com.qxgmat.data.relation.entity.UserModuleRecordStatRelation">
     <!--
     <!--
       WARNING - @mbg.generated
       WARNING - @mbg.generated
     -->
     -->
@@ -29,6 +35,40 @@
   </sql>
   </sql>
 
 
   <!--
   <!--
+    用户听课记录统计
+  -->
+  <select id="stat" resultMap="studyMap">
+    select
+    sum(ucr.`user_time`) as `user_time`
+    from `user_course_record` ucr
+    where
+    ucr.`user_id` = #{userId,jdbcType=VARCHAR}
+    <if test="startTime != null">
+      and ucr.`create_time` &gt; #{startTime,jdbcType=VARCHAR}
+    </if>
+    <if test="endTime != null">
+      and ucr.`create_time` &lt; #{endTime,jdbcType=VARCHAR}
+    </if>
+  </select>
+
+  <!--
+    全站听课记录统计
+  -->
+  <select id="statAvg" resultMap="studyMap">
+    select
+    sum(ucr.`user_time`) / count(distance(ucr.`user_id`)) as `user_time`
+    from `user_course_record` ucr
+    where
+    1
+    <if test="startTime != null">
+      and ucr.`create_time` &gt; #{startTime,jdbcType=VARCHAR}
+    </if>
+    <if test="endTime != null">
+      and ucr.`create_time` &lt; #{endTime,jdbcType=VARCHAR}
+    </if>
+  </select>
+
+  <!--
     用户听课记录统计,分题型
     用户听课记录统计,分题型
   -->
   -->
   <select id="statGroupType" resultMap="studyMap">
   <select id="statGroupType" resultMap="studyMap">

+ 38 - 18
server/data/src/main/java/com/qxgmat/data/relation/mapping/UserOrderRecordRelationMapper.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?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">
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.qxgmat.data.relation.UserNoteQuestionRelationMapper">
+<mapper namespace="com.qxgmat.data.relation.UserOrderRecordRelationMapper">
   <resultMap id="IdMap" type="com.qxgmat.data.dao.entity.UserNoteQuestion">
   <resultMap id="IdMap" type="com.qxgmat.data.dao.entity.UserNoteQuestion">
     <!--
     <!--
       WARNING - @mbg.generated
       WARNING - @mbg.generated
@@ -34,34 +34,54 @@
       #{item}
       #{item}
     </foreach>
     </foreach>
   </select>
   </select>
+
   <!--
   <!--
-    用户笔记题目列表
+    获取用户学习记录
   -->
   -->
-  <select id="list" resultMap="IdMap">
+  <select id="listWithStudyAdmin" resultMap="IdMap">
     select
     select
     <include refid="Id_Column_List" />
     <include refid="Id_Column_List" />
-    from `user_note_question` ucq
-    left join `question_no` qn on qn.`id` = ucq.`question_no_id`
-    <if test="module != null">
-      and qn.`module` = #{module,jdbcType=VARCHAR}
+    from `user_order_record` uor
+    left join `course` c on c.`id` = uor.`product_id` and uor.`product_type` = 'course'
+    <if test="courseModules != null">
+      c.`course_module` IN
+      <foreach collection="courseModules" item="item" index="index" open="(" close=")" separator=",">
+        #{item, jdbcType=VARCHAR}
+      </foreach>
     </if>
     </if>
-    left join `question` q on q.`id` = ucq.`question_id`
-    <if test="questionType != null">
-      and q.`question_type` = #{questionType,jdbcType=VARCHAR}
+    <if test="structId != null">
+      and (c.`struct_id` = #{structId,jdbcType=VARCHAR} or c.`parent_struct_id` = #{structId,jdbcType=VARCHAR})
+    </if>
+    <if test="courseId != null">
+      and c.`id` = #{courseId,jdbcType=VARCHAR}
     </if>
     </if>
     where
     where
-    qn.`id` &gt; 0
-    and q.`id` &gt; 0
+    c.`id` &gt; 0
     <if test="userId != null">
     <if test="userId != null">
-      and ucq.`user_id` = #{userId,jdbcType=VARCHAR}
+      and uor.`user_id` = #{userId,jdbcType=VARCHAR}
     </if>
     </if>
-    <if test="startTime != null">
-      and ucq.`createTime` &gt; #{startTime,jdbcType=VARCHAR}
+    order by ${order} ${direction}
+  </select>
+
+  <!--
+    获取用户VS学习记录
+  -->
+  <select id="listWithVs" resultMap="IdMap">
+    select
+    <include refid="Id_Column_List" />
+    from `user_order_record` uor
+    left join `course` c on c.`id` = uor.`product_id` and uor.`product_type` = 'course'
+    <if test="vsType != null">
+      and c.`vs_type` = #{vsType,jdbcType=VARCHAR}
     </if>
     </if>
-    <if test="endTime != null">
-      and ucq.`createTime` &lt; #{endTime,jdbcType=VARCHAR}
+    <if test="courseId != null">
+      and c.`id` = #{courseId,jdbcType=VARCHAR}
+    </if>
+    where
+    c.`id` &gt; 0
+    <if test="userId != null">
+      and uor.`user_id` = #{userId,jdbcType=VARCHAR}
     </if>
     </if>
-
     order by ${order} ${direction}
     order by ${order} ${direction}
   </select>
   </select>
 
 

+ 56 - 0
server/data/src/main/java/com/qxgmat/data/relation/mapping/UserQuestionRelationMapper.xml

@@ -0,0 +1,56 @@
+<?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.UserQuestionRelationMapper">
+  <resultMap id="IdMap" type="com.qxgmat.data.dao.entity.UserQuestion">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    <id column="id" jdbcType="INTEGER" property="id" />
+  </resultMap>
+  <resultMap id="studyMap" type="com.qxgmat.data.relation.entity.UserRecordStatRelation">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    <id column="user_time" jdbcType="INTEGER" property="user_time" />
+  </resultMap>
+  <sql id="Id_Column_List">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    ur.`id`
+  </sql>
+
+  <!--
+    用户做题记录统计
+  -->
+  <select id="stat" resultMap="studyMap">
+    select
+    sum(uq.`user_time`) as `user_time`
+    from `user_question` uq
+    where
+    uq.`user_id` = #{userId,jdbcType=VARCHAR}
+    <if test="startTime != null">
+      and uq.`create_time` &gt; #{startTime,jdbcType=VARCHAR}
+    </if>
+    <if test="endTime != null">
+      and uq.`create_time` &lt; #{endTime,jdbcType=VARCHAR}
+    </if>
+  </select>
+
+  <!--
+    全站做题记录统计
+  -->
+  <select id="statAvg" resultMap="studyMap">
+    select
+    sum(uq.`user_time`) /count(distance(uq.`user_id`)) as `user_time`
+    from `user_question` uq
+    where
+    1
+    <if test="startTime != null">
+      and uq.`create_time` &gt; #{startTime,jdbcType=VARCHAR}
+    </if>
+    <if test="endTime != null">
+      and uq.`create_time` &lt; #{endTime,jdbcType=VARCHAR}
+    </if>
+  </select>
+</mapper>

+ 21 - 4
server/data/src/main/java/com/qxgmat/data/relation/mapping/UserSentenceRecordRelationMapper.xml

@@ -7,7 +7,7 @@
     -->
     -->
     <id column="id" jdbcType="INTEGER" property="id" />
     <id column="id" jdbcType="INTEGER" property="id" />
   </resultMap>
   </resultMap>
-  <resultMap id="studyMap" type="com.qxgmat.data.relation.entity.UserSentenceStatRelation">
+  <resultMap id="studyMap" type="com.qxgmat.data.relation.entity.UserRecordStatRelation">
     <!--
     <!--
       WARNING - @mbg.generated
       WARNING - @mbg.generated
     -->
     -->
@@ -28,12 +28,29 @@
     sum(usr.`user_time`) as `user_time`
     sum(usr.`user_time`) as `user_time`
     from `user_sentence_record` usr
     from `user_sentence_record` usr
     where
     where
-    ucr.`user_id` = #{userId,jdbcType=VARCHAR}
+    usr.`user_id` = #{userId,jdbcType=VARCHAR}
     <if test="startTime != null">
     <if test="startTime != null">
-      and ur.`update_time` &gt; #{startTime,jdbcType=VARCHAR}
+      and usr.`create_time` &gt; #{startTime,jdbcType=VARCHAR}
     </if>
     </if>
     <if test="endTime != null">
     <if test="endTime != null">
-      and ur.`update_time` &lt; #{endTime,jdbcType=VARCHAR}
+      and usr.`create_time` &lt; #{endTime,jdbcType=VARCHAR}
+    </if>
+  </select>
+
+  <!--
+    全站阅读记录统计
+  -->
+  <select id="statAvg" resultMap="studyMap">
+    select
+    sum(usr.`user_time`) / count(distance(usr.`user_id`)) as `user_time`
+    from `user_sentence_record` usr
+    where
+    1
+    <if test="startTime != null">
+      and usr.`create_time` &gt; #{startTime,jdbcType=VARCHAR}
+    </if>
+    <if test="endTime != null">
+      and usr.`create_time` &lt; #{endTime,jdbcType=VARCHAR}
     </if>
     </if>
   </select>
   </select>
 </mapper>
 </mapper>

+ 17 - 0
server/gateway-api/src/main/java/com/qxgmat/controller/admin/SettingController.java

@@ -365,6 +365,23 @@ public class SettingController {
         return ResponseHelp.success(entity.getValue());
         return ResponseHelp.success(entity.getValue());
     }
     }
 
 
+    @RequestMapping(value = "/wechat_info", method = RequestMethod.PUT)
+    @ApiOperation(value = "修改长难句信息", httpMethod = "PUT")
+    private Response<Boolean> editWechatInfo(@RequestBody @Validated JSONObject dto){
+        Setting entity = settingService.getByKey(SettingKey.WECHAT_INFO);
+        entity.setValue(dto);
+        settingService.edit(entity);
+        return ResponseHelp.success(true);
+    }
+
+    @RequestMapping(value = "/wechat_info", method = RequestMethod.GET)
+    @ApiOperation(value = "获取长难句信息", httpMethod = "GET")
+    private Response<JSONObject> getWechatInfo(){
+        Setting entity = settingService.getByKey(SettingKey.WECHAT_INFO);
+
+        return ResponseHelp.success(entity.getValue());
+    }
+
     @RequestMapping(value = "/tips", method = RequestMethod.PUT)
     @RequestMapping(value = "/tips", method = RequestMethod.PUT)
     @ApiOperation(value = "修改结构说明", httpMethod = "PUT")
     @ApiOperation(value = "修改结构说明", httpMethod = "PUT")
     private Response<Boolean> editTips(@RequestBody @Validated JSONObject dto){
     private Response<Boolean> editTips(@RequestBody @Validated JSONObject dto){

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

@@ -158,9 +158,9 @@ public class UserController {
         UserDetailDto dto = Transform.convert(entity, UserDetailDto.class);
         UserDetailDto dto = Transform.convert(entity, UserDetailDto.class);
         Integer time = 0;
         Integer time = 0;
 
 
-        time += courseExtendService.studyTime(id);
-        time += sentenceService.studyTime(id);
-        time += questionFlowService.studyTime(id);
+        time += courseExtendService.studyTime(id, null, null);
+        time += sentenceService.studyTime(id, null, null);
+        time += questionFlowService.studyTime(id, null, null);
         dto.setTotalTime(time);
         dto.setTotalTime(time);
 
 
         return ResponseHelp.success(dto);
         return ResponseHelp.success(dto);

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

@@ -73,7 +73,7 @@ public class AuthController {
         }else{
         }else{
             user = usersService.getUserByToken(token);
             user = usersService.getUserByToken(token);
             // 用该token登录
             // 用该token登录
-            shiroHelp.getSession().login(shiroHelp.user(user.getMobile(), ""));
+            shiroHelp.getSession().login(shiroHelp.user(user.getArea()+":"+user.getMobile(), ""));
         }
         }
 
 
         User entity = usersService.get(user.getId());
         User entity = usersService.get(user.getId());

+ 7 - 0
server/gateway-api/src/main/java/com/qxgmat/controller/api/BaseController.java

@@ -101,6 +101,13 @@ public class BaseController {
         return ResponseHelp.success(entity.getValue());
         return ResponseHelp.success(entity.getValue());
     }
     }
 
 
+    @RequestMapping(value = "/wechat", method = RequestMethod.GET)
+    @ApiOperation(value = "获取心经信息", notes = "获取心经信息", httpMethod = "GET")
+    public Response<JSONObject> wechat()  {
+        Setting entity = settingService.getByKey(SettingKey.WECHAT_INFO);
+        return ResponseHelp.success(entity.getValue());
+    }
+
     @RequestMapping(value = "/score", method = RequestMethod.GET)
     @RequestMapping(value = "/score", method = RequestMethod.GET)
     @ApiOperation(value = "考分计算", notes = "获取考分排行信息", httpMethod = "GET")
     @ApiOperation(value = "考分计算", notes = "获取考分排行信息", httpMethod = "GET")
     public Response<Rank> score(
     public Response<Rank> score(

+ 16 - 4
server/gateway-api/src/main/java/com/qxgmat/controller/api/CourseController.java

@@ -7,6 +7,7 @@ import com.nuliji.tools.exception.ParameterException;
 import com.qxgmat.data.constants.enums.ExperienceDayRange;
 import com.qxgmat.data.constants.enums.ExperienceDayRange;
 import com.qxgmat.data.constants.enums.ExperienceScoreRange;
 import com.qxgmat.data.constants.enums.ExperienceScoreRange;
 import com.qxgmat.data.constants.enums.module.CourseModule;
 import com.qxgmat.data.constants.enums.module.CourseModule;
+import com.qxgmat.data.constants.enums.module.VsCourseType;
 import com.qxgmat.data.constants.enums.status.DirectionStatus;
 import com.qxgmat.data.constants.enums.status.DirectionStatus;
 import com.qxgmat.data.constants.enums.user.DataType;
 import com.qxgmat.data.constants.enums.user.DataType;
 import com.qxgmat.data.dao.entity.*;
 import com.qxgmat.data.dao.entity.*;
@@ -239,12 +240,22 @@ public class CourseController {
     @RequestMapping(value = "/progress", method = RequestMethod.GET)
     @RequestMapping(value = "/progress", method = RequestMethod.GET)
     @ApiOperation(value = "获取课程进度", notes = "获取所有课程及状态进度", httpMethod = "GET")
     @ApiOperation(value = "获取课程进度", notes = "获取所有课程及状态进度", httpMethod = "GET")
     public Response<List<UserCourseProgressDto>> progress(
     public Response<List<UserCourseProgressDto>> progress(
-            @RequestParam(required = false) String[] courseModules,
+            @RequestParam(required = false) String courseModule,
             @RequestParam(required = false) Integer structId,
             @RequestParam(required = false) Integer structId,
             @RequestParam(required = false) Integer courseId
             @RequestParam(required = false) Integer courseId
     )  {
     )  {
         User user = (User) shiroHelp.getLoginUser();
         User user = (User) shiroHelp.getLoginUser();
-        List<UserOrderRecord> userOrderRecordList = userOrderRecordService.listWithStudyAdmin(1, 1000, courseModules, structId, courseId, user.getId(), null,null, null);
+        List<UserOrderRecord> userOrderRecordList;
+        CourseModule module = CourseModule.ValueOf(courseModule);
+        if (module == CourseModule.VIDEO){
+            // 视频课程包含:小班课程
+            userOrderRecordList = userOrderRecordService.listWithStudyAdmin(1, 1000, new String[]{CourseModule.VIDEO.key, CourseModule.ONLINE.key}, structId, courseId, user.getId(), null,null, null);
+        } else if (module == CourseModule.VS){
+            // 1v1课程:只有系统授课有作业
+            userOrderRecordList = userOrderRecordService.listWithVs(1, 1000, VsCourseType.COACH, courseId, user.getId(), null, null);
+        }else{
+            throw new ParameterException("课程类型错误");
+        }
         List<UserCourseProgressDto> dtos = Transform.convert(userOrderRecordList, UserCourseProgressDto.class);
         List<UserCourseProgressDto> dtos = Transform.convert(userOrderRecordList, UserCourseProgressDto.class);
 
 
         // 绑定课程
         // 绑定课程
@@ -265,14 +276,15 @@ public class CourseController {
     @RequestMapping(value = "/preview/list", method = RequestMethod.GET)
     @RequestMapping(value = "/preview/list", method = RequestMethod.GET)
     @ApiOperation(value = "获取预习作业列表", notes = "获取预习作业列表", httpMethod = "GET")
     @ApiOperation(value = "获取预习作业列表", notes = "获取预习作业列表", httpMethod = "GET")
     public Response<List<UserExercisePaperDto>> listPreview(
     public Response<List<UserExercisePaperDto>> listPreview(
+            @RequestParam(required = false, defaultValue = "1") int page,
+            @RequestParam(required = false, defaultValue = "100") int size,
             @RequestParam(required = false) Integer recordId,
             @RequestParam(required = false) Integer recordId,
             @RequestParam(required = false) String endTime,
             @RequestParam(required = false) String endTime,
             @RequestParam(required = false) Integer times
             @RequestParam(required = false) Integer times
     )  {
     )  {
         User user = (User) shiroHelp.getLoginUser();
         User user = (User) shiroHelp.getLoginUser();
 
 
-        List<UserPreviewPaperRelation> p = previewService.list(recordId, user.getId(), endTime, times, null);
-
+        List<UserPreviewPaperRelation> p = previewService.list(page, size, recordId, user.getId(), endTime, times);
         List<UserExercisePaperDto> pr = Transform.convert(p, UserExercisePaperDto.class);
         List<UserExercisePaperDto> pr = Transform.convert(p, UserExercisePaperDto.class);
 
 
         // 获取试卷统计信息
         // 获取试卷统计信息

+ 28 - 81
server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java

@@ -25,8 +25,10 @@ import com.qxgmat.help.AiHelp;
 import com.qxgmat.help.MailHelp;
 import com.qxgmat.help.MailHelp;
 import com.qxgmat.help.ShiroHelp;
 import com.qxgmat.help.ShiroHelp;
 import com.qxgmat.service.*;
 import com.qxgmat.service.*;
+import com.qxgmat.service.extend.CourseExtendService;
 import com.qxgmat.service.extend.OrderFlowService;
 import com.qxgmat.service.extend.OrderFlowService;
 import com.qxgmat.service.extend.QuestionFlowService;
 import com.qxgmat.service.extend.QuestionFlowService;
+import com.qxgmat.service.extend.SentenceService;
 import com.qxgmat.service.inline.*;
 import com.qxgmat.service.inline.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
@@ -147,6 +149,12 @@ public class MyController {
     private QuestionFlowService questionFlowService;
     private QuestionFlowService questionFlowService;
 
 
     @Autowired
     @Autowired
+    private SentenceService sentenceService;
+
+    @Autowired
+    private CourseExtendService courseExtendService;
+
+    @Autowired
     private OrderFlowService orderFlowService;
     private OrderFlowService orderFlowService;
 
 
     @RequestMapping(value = "/email", method = RequestMethod.POST)
     @RequestMapping(value = "/email", method = RequestMethod.POST)
@@ -459,92 +467,31 @@ public class MyController {
 
 
     @RequestMapping(value = "/study/week", method = RequestMethod.GET)
     @RequestMapping(value = "/study/week", method = RequestMethod.GET)
     @ApiOperation(value = "获取本周记录", notes = "获取本周学习记录", httpMethod = "GET")
     @ApiOperation(value = "获取本周记录", notes = "获取本周学习记录", httpMethod = "GET")
-    public Response<UserStudyDetailDto> studyWeekTime()  {
+    public Response<UserStudyDetailDto> studyWeekTime(
+            @RequestParam(required = false) Integer week
+    )  {
         User user = (User) shiroHelp.getLoginUser();
         User user = (User) shiroHelp.getLoginUser();
         UserStudyDetailDto dto = new UserStudyDetailDto();
         UserStudyDetailDto dto = new UserStudyDetailDto();
         dto.setCreateTime(user.getCreateTime());
         dto.setCreateTime(user.getCreateTime());
         dto.setDays((int)((user.getCreateTime().getTime() - new Date().getTime()) / (1000*3600*24)));
         dto.setDays((int)((user.getCreateTime().getTime() - new Date().getTime()) / (1000*3600*24)));
-        Integer totalTime = 0;
-        Map<String, Integer> categoryMap = new HashMap<>();
-        // 按模块来源分组查询: module=> sentence, examination, collect+error, 忽略exercise,preview
-        List<UserStudyStatRelation> moduleList = userReportService.statGroupModule(user.getId());
-        for(UserStudyStatRelation module:moduleList){
-            // 练习时间过滤
-            if (module.getModule().equals(PaperModule.EXERCISE.key)){
-                continue;
-            }
-            Integer time = module.getUserTime();
-            String key = module.getModule();
-            totalTime += time;
-            // 收藏及错误组卷合并
-            if (module.getModule().equals(PaperOrigin.COLLECT.key)
-                    || module.getModule().equals(PaperOrigin.ERROR.key)){
-                key = "freedom";
-                time += categoryMap.getOrDefault(key, 0);
-            }else if (module.getModule().equals(PaperOrigin.PREVIEW.key)){
-                key = PaperOrigin.EXERCISE.key;
-            }
-            categoryMap.put(key, time);
-        }
-        // 按题型统计练习
-        List<UserStudyStatRelation> exerciseList = userReportService.statGroupExerciseType(user.getId(), null, null);
-        for(UserStudyStatRelation type:exerciseList){
-            totalTime += type.getUserTime();
-            categoryMap.put(type.getModule(), type.getUserTime());
-        }
-        // 按题型统计预习作业
-        List<UserStudyStatRelation> previewList = userReportService.statGroupExerciseType(user.getId(), null, null);
-        for(UserStudyStatRelation type:previewList){
-            totalTime += type.getUserTime();
-            categoryMap.put(type.getModule(), type.getUserTime());
-        }
-        // 按题型统计课程
-        List<UserCourseStatRelation> recordList = userCourseRecordService.statGroupType(user.getId(), null, null);
-        for (UserCourseStatRelation record : recordList){
-            totalTime += record.getUserTime();
-            // 累加同类型时间
-            Integer time = categoryMap.getOrDefault(record.getModule(), 0);
-            categoryMap.put(record.getModule(), time);
-        }
-        // 获取长难句阅读统计
-        UserSentenceStatRelation sentenceStatRelation = userSentenceRecordService.stat(user.getId(), null, null);
-        if (sentenceStatRelation != null){
-            Integer sentenceTime = categoryMap.getOrDefault(PaperModule.SENTENCE.key, 0);
-            categoryMap.put(PaperModule.SENTENCE.key, sentenceTime + sentenceStatRelation.getUserTime());
-        }
 
 
-        List<ExerciseStruct> p = exerciseStructService.main();
-        Map<String, String> m = new HashMap<>();
-        for (ExerciseStruct struct : p){
-            if (struct.getExtend() == null || struct.getExtend().isEmpty()) continue;
-            m.put(struct.getExtend(), struct.getTitleZh() + (struct.getTitleEn().isEmpty() ? "":" "+struct.getTitleEn()));
-        }
+        Date now = Tools.today();
+        int day = Tools.getDayOfWeek(now);
+        Date start = Tools.addDate(now, -1 * (day + week * 7));
+        Date end = Tools.addDate(start, 7);
 
 
-        // 组装数据
-        List<UserStudyExtendDto> categorys = new ArrayList<>();
-        if (categoryMap.containsKey(PaperModule.SENTENCE.key)) categorys.add(new UserStudyExtendDto(m.get(PaperModule.SENTENCE.key), categoryMap.get(PaperModule.SENTENCE.key)));
-        if (categoryMap.containsKey(QuestionType.SC.key)) categorys.add(new UserStudyExtendDto(m.get(QuestionType.SC.key), categoryMap.get(QuestionType.SC.key)));
-        if (categoryMap.containsKey(QuestionType.RC.key)) categorys.add(new UserStudyExtendDto(m.get(QuestionType.RC.key), categoryMap.get(QuestionType.RC.key)));
-        if (categoryMap.containsKey(QuestionType.CR.key)) categorys.add(new UserStudyExtendDto(m.get(QuestionType.CR.key), categoryMap.get(QuestionType.CR.key)));
-        if (categoryMap.containsKey(QuestionType.PS.key)){
-            // 累加数学
-            Integer time = categoryMap.getOrDefault(QuestionSubject.QUANT.key, 0);
-            categoryMap.put(QuestionSubject.QUANT.key, time + categoryMap.get(QuestionType.PS.key));
-        }
-        if (categoryMap.containsKey(QuestionType.DS.key)){
-            // 累加数学
-            Integer time = categoryMap.getOrDefault(QuestionSubject.QUANT.key, 0);
-            categoryMap.put(QuestionSubject.QUANT.key, time + categoryMap.get(QuestionType.DS.key));
-        }
-        if (categoryMap.containsKey(QuestionSubject.QUANT.key)) categorys.add(new UserStudyExtendDto(m.get(QuestionSubject.QUANT.key), categoryMap.get(QuestionSubject.QUANT.key)));
+        Integer time = 0;
+        time += courseExtendService.studyTime(user.getId(), start, end);
+        time += sentenceService.studyTime(user.getId(), start, end);
+        time += questionFlowService.studyTime(user.getId(), start, end);
+        dto.setTime(time);
 
 
-        if (categoryMap.containsKey(QuestionType.IR.key)) categorys.add(new UserStudyExtendDto(m.get(QuestionType.IR.key), categoryMap.get(QuestionType.IR.key)));
-        if (categoryMap.containsKey(QuestionType.AWA.key)) categorys.add(new UserStudyExtendDto(m.get(QuestionType.AWA.key), categoryMap.get(QuestionType.AWA.key)));
-        if (categoryMap.containsKey(PaperModule.EXAMINATION.key)) categorys.add(new UserStudyExtendDto("模考", categoryMap.get(PaperModule.EXAMINATION.key)));
-        if (categoryMap.containsKey("freedom")) categorys.add(new UserStudyExtendDto("自由组卷", categoryMap.get("freedom")));
+        Integer avgTime = 0;
+        avgTime += courseExtendService.studyAvgTime(start, end);
+        avgTime += sentenceService.studyAvgTime(start, end);
+        avgTime += questionFlowService.studyAvgTime(start, end);
+        dto.setAvgTime(avgTime);
 
 
-        dto.setTime(totalTime);
-        dto.setCategorys(categorys);
         return ResponseHelp.success(dto);
         return ResponseHelp.success(dto);
     }
     }
 
 
@@ -590,15 +537,15 @@ public class MyController {
             categoryMap.put(type.getModule(), type.getUserTime());
             categoryMap.put(type.getModule(), type.getUserTime());
         }
         }
         // 按题型统计课程
         // 按题型统计课程
-        List<UserCourseStatRelation> recordList = userCourseRecordService.statGroupType(user.getId(), null, null);
-        for (UserCourseStatRelation record : recordList){
+        List<UserModuleRecordStatRelation> recordList = userCourseRecordService.statGroupType(user.getId(), null, null);
+        for (UserModuleRecordStatRelation record : recordList){
             totalTime += record.getUserTime();
             totalTime += record.getUserTime();
             // 累加同类型时间
             // 累加同类型时间
             Integer time = categoryMap.getOrDefault(record.getModule(), 0);
             Integer time = categoryMap.getOrDefault(record.getModule(), 0);
             categoryMap.put(record.getModule(), time);
             categoryMap.put(record.getModule(), time);
         }
         }
         // 获取长难句阅读统计
         // 获取长难句阅读统计
-        UserSentenceStatRelation sentenceStatRelation = userSentenceRecordService.stat(user.getId(), null, null);
+        UserRecordStatRelation sentenceStatRelation = userSentenceRecordService.stat(user.getId(), null, null);
         if (sentenceStatRelation != null){
         if (sentenceStatRelation != null){
             Integer sentenceTime = categoryMap.getOrDefault(PaperModule.SENTENCE.key, 0);
             Integer sentenceTime = categoryMap.getOrDefault(PaperModule.SENTENCE.key, 0);
             categoryMap.put(PaperModule.SENTENCE.key, sentenceTime + sentenceStatRelation.getUserTime());
             categoryMap.put(PaperModule.SENTENCE.key, sentenceTime + sentenceStatRelation.getUserTime());

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

@@ -196,12 +196,12 @@ public class QuestionController {
                 List<UserPaper> userPaperList = userPaperService.listWithOrigin(user.getId(), PaperOrigin.EXERCISE, ids, null);
                 List<UserPaper> userPaperList = userPaperService.listWithOrigin(user.getId(), PaperOrigin.EXERCISE, ids, null);
                 // 绑定userPaperId,用于关联report
                 // 绑定userPaperId,用于关联report
                 Map userPaperMap = Transform.getMap(userPaperList, UserPaper.class, "originId", "id");
                 Map userPaperMap = Transform.getMap(userPaperList, UserPaper.class, "originId", "id");
-                Transform.combine(childrenDtos, userPaperMap, UserSentencePaperDto.class, "id", "userPaperId");
+                Transform.combine(childrenDtos, userPaperMap, UserExerciseGroupExtendDto.class, "id", "userPaperId");
 
 
                 // 获取最后一次作业结果
                 // 获取最后一次作业结果
                 Collection paperIds = Transform.getIds(userPaperList, UserPaper.class, "id");
                 Collection paperIds = Transform.getIds(userPaperList, UserPaper.class, "id");
                 List<UserReport> reportList = userReportService.listWithLater(paperIds);
                 List<UserReport> reportList = userReportService.listWithLater(paperIds);
-                Transform.combine(childrenDtos, reportList, UserSentencePaperDto.class, "userPaperId", "report", UserReport.class, "paperId", UserReportExtendDto.class);
+                Transform.combine(childrenDtos, reportList, UserExerciseGroupExtendDto.class, "userPaperId", "report", UserReport.class, "paperId", UserReportExtendDto.class);
 
 
                 dto.setChildren(childrenDtos);
                 dto.setChildren(childrenDtos);
             }else{
             }else{
@@ -747,9 +747,9 @@ public class QuestionController {
         return ResponseHelp.success(true);
         return ResponseHelp.success(true);
     }
     }
 
 
-    @RequestMapping(value = "/restart/examination", method = RequestMethod.POST)
+    @RequestMapping(value = "/reset/cat", method = RequestMethod.POST)
     @ApiOperation(value = "重置整套模拟卷", notes = "重置考试", httpMethod = "POST")
     @ApiOperation(value = "重置整套模拟卷", notes = "重置考试", httpMethod = "POST")
-    public Response<Boolean> restartExamination(@RequestBody @Validated ExaminationRestartDto dto)  {
+    public Response<Boolean> resetCat()  {
         User user = (User) shiroHelp.getLoginUser();
         User user = (User) shiroHelp.getLoginUser();
 
 
         UserService userService = userServiceService.getService(user.getId(), ServiceKey.QX_CAT);
         UserService userService = userServiceService.getService(user.getId(), ServiceKey.QX_CAT);
@@ -760,7 +760,7 @@ public class QuestionController {
             throw new ParameterException("已重置,请再次购买服务");
             throw new ParameterException("已重置,请再次购买服务");
         }
         }
         // reset当前考卷的所有状态
         // reset当前考卷的所有状态
-        questionFlowService.restart(dto.getStructId(), user.getId());
+        examinationService.resetCat(user.getId(), false);
         userServiceService.edit(UserService.builder().id(userService.getId()).isReset(1).build());
         userServiceService.edit(UserService.builder().id(userService.getId()).isReset(1).build());
         return ResponseHelp.success(true);
         return ResponseHelp.success(true);
     }
     }

+ 1 - 5
server/gateway-api/src/main/java/com/qxgmat/controller/api/SentenceController.java

@@ -114,11 +114,7 @@ public class SentenceController
     public Response<Boolean> active(@RequestBody @Validated UserSentenceCodeDto dto) {
     public Response<Boolean> active(@RequestBody @Validated UserSentenceCodeDto dto) {
         User user = (User) shiroHelp.getLoginUser();
         User user = (User) shiroHelp.getLoginUser();
         if (user == null) throw new AuthException("需要登录");
         if (user == null) throw new AuthException("需要登录");
-
-        if (sentenceCodeService.isActive(user.getId()) == null){
-            sentenceCodeService.active(user.getId(), dto.getCode());
-        }
-
+        sentenceService.active(user.getId(), dto.getCode());
         return ResponseHelp.success(true);
         return ResponseHelp.success(true);
     }
     }
 
 

+ 158 - 2
server/gateway-api/src/main/java/com/qxgmat/controller/api/TextbookController.java

@@ -5,12 +5,24 @@ import com.nuliji.tools.*;
 import com.nuliji.tools.exception.AuthException;
 import com.nuliji.tools.exception.AuthException;
 import com.nuliji.tools.exception.ParameterException;
 import com.nuliji.tools.exception.ParameterException;
 import com.qxgmat.data.constants.enums.QuestionSubject;
 import com.qxgmat.data.constants.enums.QuestionSubject;
+import com.qxgmat.data.constants.enums.QuestionType;
 import com.qxgmat.data.constants.enums.ServiceKey;
 import com.qxgmat.data.constants.enums.ServiceKey;
+import com.qxgmat.data.constants.enums.logic.TextbookLogic;
+import com.qxgmat.data.constants.enums.module.PaperOrigin;
 import com.qxgmat.data.constants.enums.status.DirectionStatus;
 import com.qxgmat.data.constants.enums.status.DirectionStatus;
 import com.qxgmat.data.dao.entity.*;
 import com.qxgmat.data.dao.entity.*;
+import com.qxgmat.data.inline.UserQuestionStat;
+import com.qxgmat.data.relation.entity.TextbookQuestionRelation;
+import com.qxgmat.dto.extend.UserPaperBaseExtendDto;
+import com.qxgmat.dto.extend.UserReportExtendDto;
 import com.qxgmat.dto.extend.UserServiceRecordExtendDto;
 import com.qxgmat.dto.extend.UserServiceRecordExtendDto;
+import com.qxgmat.dto.extend.UserTextbookGroupExtendDto;
+import com.qxgmat.dto.response.UserTextbookGroupDto;
 import com.qxgmat.dto.response.UserTextbookInfoDto;
 import com.qxgmat.dto.response.UserTextbookInfoDto;
+import com.qxgmat.dto.response.UserTextbookPaperDto;
 import com.qxgmat.help.ShiroHelp;
 import com.qxgmat.help.ShiroHelp;
+import com.qxgmat.service.UserPaperService;
+import com.qxgmat.service.UserQuestionService;
 import com.qxgmat.service.UserServiceService;
 import com.qxgmat.service.UserServiceService;
 import com.qxgmat.service.UsersService;
 import com.qxgmat.service.UsersService;
 import com.qxgmat.service.extend.QuestionFlowService;
 import com.qxgmat.service.extend.QuestionFlowService;
@@ -23,8 +35,8 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.HttpSession;
 import javax.servlet.http.HttpSession;
 import java.text.DateFormat;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.ParseException;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 
 @RestController
 @RestController
 @RequestMapping("/api/textbook")
 @RequestMapping("/api/textbook")
@@ -44,6 +56,15 @@ public class TextbookController
     private UsersService usersService;
     private UsersService usersService;
 
 
     @Autowired
     @Autowired
+    private UserPaperService userPaperService;
+
+    @Autowired
+    private UserQuestionService userQuestionService;
+
+    @Autowired
+    private UserReportService userReportService;
+
+    @Autowired
     private UserServiceService userServiceService;
     private UserServiceService userServiceService;
 
 
     @Autowired
     @Autowired
@@ -53,6 +74,12 @@ public class TextbookController
     private QuestionFlowService questionFlowService;
     private QuestionFlowService questionFlowService;
 
 
     @Autowired
     @Autowired
+    private TextbookPaperService textbookPaperService;
+
+    @Autowired
+    private TextbookQuestionService textbookQuestionService;
+
+    @Autowired
     private TextbookLibraryService textbookLibraryService;
     private TextbookLibraryService textbookLibraryService;
 
 
     @Autowired
     @Autowired
@@ -61,6 +88,82 @@ public class TextbookController
     @Autowired
     @Autowired
     private TextbookTopicService textbookTopicService;
     private TextbookTopicService textbookTopicService;
 
 
+    @RequestMapping(value = "/progress", method = RequestMethod.GET)
+    @ApiOperation(value = "练习进度", httpMethod = "GET")
+    public Response<List<UserTextbookGroupDto>> progress(HttpSession session) {
+        User user = (User) shiroHelp.getLoginUser();
+
+        TextbookLibrary latest = textbookLibraryService.getLatest();
+        TextbookLibrary second = textbookLibraryService.getSecond();
+        List<UserTextbookGroupDto> p = new ArrayList<>(2);
+
+        for(TextbookLibrary library : new ArrayList<TextbookLibrary>(2){{add(latest);add(second);}}){
+            UserTextbookGroupDto dto = Transform.convert(library, UserTextbookGroupDto.class);
+            // 获取第三层所有题目,并获取题目统计
+            List<TextbookQuestion> list = textbookQuestionService.listByLibrary(library.getId());
+            List<TextbookQuestionRelation> relations = textbookQuestionService.relation(list);
+            dto.setStat(textbookQuestionService.statPaper(list));
+            dto.setQuestionNumber(list.size());
+            Map<Object, UserQuestionStat> userQuestionStatMap = null;
+            if(user != null){
+                Collection questionNoIds = Transform.getIds(list, QuestionNo.class, "id");
+                List<UserQuestion> userQuestionList = userQuestionService.listByQuestionNo(user.getId(), questionNoIds);
+                userQuestionStatMap = userQuestionService.statQuestionNoMap(userQuestionList);
+
+                dto.setUserStat(userQuestionService.statQuestion(userQuestionList));
+
+                if (list.size() > userQuestionStatMap.size()){
+                    dto.setUserNumber(userQuestionStatMap.size());
+                    dto.setMinTimes(0);
+                }else{
+                    int minTimes = 0;
+                    // 统计最小轮的已做题数
+                    for(UserQuestionStat stat : userQuestionStatMap.values()){
+                        if(stat.getUserNumber() < minTimes || minTimes == 0) minTimes = stat.getUserNumber();
+                    }
+                    int userNumber = 0;
+                    for(UserQuestionStat stat : userQuestionStatMap.values()){
+                        if(stat.getUserNumber() > minTimes) userNumber += 1;
+                    }
+                    dto.setMinTimes(minTimes);
+                    dto.setUserNumber(userNumber);
+                }
+            }
+
+            List<UserTextbookGroupExtendDto> childrenDtos = new ArrayList<>(TextbookLogic.all().length);
+            for(TextbookLogic logic : TextbookLogic.all()){
+                UserTextbookGroupExtendDto extendDto = new UserTextbookGroupExtendDto();
+                extendDto.setLogic(logic.key);
+                List<TextbookQuestionRelation> childQuestionList = relations.stream().filter((q)-> logic.contain(QuestionType.ValueOf(q.getQuestion().getQuestionType()))).collect(Collectors.toList());
+                extendDto.setQuestionNumber(childQuestionList.size());
+                if (user != null){
+                    int minTimes = 0;
+                    int userQuestionNumber = 0;
+                    boolean flag = true;
+                    for(TextbookQuestion questionNo : childQuestionList){
+                        UserQuestionStat stat = userQuestionStatMap.get(questionNo.getId());
+                        if (stat == null) {
+                            flag = false;
+                            break;
+                        }
+                        if (stat.getUserNumber() < minTimes || minTimes == 0) minTimes = stat.getUserNumber();
+                    }
+                    if (!flag) minTimes = 0;
+                    for(TextbookQuestion questionNo : childQuestionList){
+                        UserQuestionStat stat = userQuestionStatMap.get(questionNo.getId());
+                        if (stat != null && stat.getUserNumber() > minTimes)  userQuestionNumber += 1;
+                    }
+                    extendDto.setUserNumber(userQuestionNumber);
+                    extendDto.setMinTimes(minTimes);
+                }
+                childrenDtos.add(extendDto);
+            }
+            dto.setChildren(childrenDtos);
+            p.add(dto);
+        }
+
+        return ResponseHelp.success(p);
+    }
 
 
     @RequestMapping(value = "/info", method = RequestMethod.GET)
     @RequestMapping(value = "/info", method = RequestMethod.GET)
     @ApiOperation(value = "机经信息", httpMethod = "GET")
     @ApiOperation(value = "机经信息", httpMethod = "GET")
@@ -150,4 +253,57 @@ public class TextbookController
 
 
         return ResponseHelp.success(p, page, size, p.getTotal());
         return ResponseHelp.success(p, page, size, p.getTotal());
     }
     }
+
+
+    @RequestMapping(value = "/paper/list", method = RequestMethod.GET)
+    @ApiOperation(value = "机经组卷列表", httpMethod = "GET")
+    public Response<List<UserTextbookPaperDto>> listPaper(
+            @RequestParam(required = false, defaultValue = "1") int page,
+            @RequestParam(required = false, defaultValue = "100") int size,
+            @RequestParam(required = true) boolean latest,
+            @RequestParam(required = true) String logic,
+            @RequestParam(required = false)  Integer times,
+            HttpSession session) {
+        User user = (User) shiroHelp.getLoginUser();
+        TextbookLibrary library;
+        if (latest){
+            if (user == null){
+                throw new AuthException("请先登录");
+            }
+            if (!userServiceService.hasService(user.getId(), ServiceKey.TEXTBOOK)){
+                throw new ParameterException("没有机经查看权限");
+            }
+            library = textbookLibraryService.getLatest();
+        }else{
+            // 获取往期:倒数第二
+            library = textbookLibraryService.getSecond();
+        }
+        List<TextbookPaper> p = textbookPaperService.list(page, size, library.getId(), user != null ? user.getId():null, TextbookLogic.ValueOf(logic), times);
+        List<UserTextbookPaperDto> pr = Transform.convert(p, UserTextbookPaperDto.class);
+
+        // 获取试卷统计信息
+        Map<Integer, Integer[]> questionNoIdsMap = new HashMap<>();
+        for(TextbookPaper paper : p){
+            questionNoIdsMap.put(paper.getId(), paper.getQuestionNoIds());
+        }
+        Map statMap = textbookQuestionService.statPaperMap(questionNoIdsMap);
+        Transform.combine(pr, statMap, UserTextbookPaperDto.class, "id", "stat");
+
+        if (user != null){
+            // 获取做题记录
+            Collection ids = Transform.getIds(p, TextbookPaper.class, "id");
+            List<UserPaper> userPaperList = userPaperService.listWithOrigin(user.getId(), PaperOrigin.TEXTBOOK, ids, null);
+            Transform.combine(pr, userPaperList, UserTextbookPaperDto.class, "id", "paper", UserPaper.class, "originId", UserPaperBaseExtendDto.class);
+            // 绑定userPaperId,用于关联report
+            Map userPaperMap = Transform.getMap(userPaperList, UserPaper.class, "originId", "id");
+            Transform.combine(pr, userPaperMap, UserTextbookPaperDto.class, "id", "userPaperId");
+
+            // 获取最后一次作业结果
+            Collection paperIds = Transform.getIds(userPaperList, UserPaper.class, "id");
+            List<UserReport> reportList = userReportService.listWithLater(paperIds);
+            Transform.combine(pr, reportList, UserTextbookPaperDto.class, "userPaperId", "report", UserReport.class, "paperId", UserReportExtendDto.class);
+        }
+
+        return ResponseHelp.success(pr);
+    }
 }
 }

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

@@ -7,14 +7,18 @@ import com.qxgmat.data.dao.entity.TextbookLibraryHistory;
 public class TextbookLibraryHistoryDto {
 public class TextbookLibraryHistoryDto {
     private Integer libraryId;
     private Integer libraryId;
 
 
-    private String content;
-
     private String quant = "";
     private String quant = "";
 
 
+    private String quantContent = "";
+
     private String ir = "";
     private String ir = "";
 
 
+    private String irContent = "";
+
     private String rc = "";
     private String rc = "";
 
 
+    private String rcContent = "";
+
     public Integer getLibraryId() {
     public Integer getLibraryId() {
         return libraryId;
         return libraryId;
     }
     }
@@ -23,14 +27,6 @@ public class TextbookLibraryHistoryDto {
         this.libraryId = libraryId;
         this.libraryId = libraryId;
     }
     }
 
 
-    public String getContent() {
-        return content;
-    }
-
-    public void setContent(String content) {
-        this.content = content;
-    }
-
     public String getQuant() {
     public String getQuant() {
         return quant;
         return quant;
     }
     }
@@ -54,4 +50,28 @@ public class TextbookLibraryHistoryDto {
     public void setRc(String rc) {
     public void setRc(String rc) {
         this.rc = rc;
         this.rc = rc;
     }
     }
+
+    public String getQuantContent() {
+        return quantContent;
+    }
+
+    public void setQuantContent(String quantContent) {
+        this.quantContent = quantContent;
+    }
+
+    public String getIrContent() {
+        return irContent;
+    }
+
+    public void setIrContent(String irContent) {
+        this.irContent = irContent;
+    }
+
+    public String getRcContent() {
+        return rcContent;
+    }
+
+    public void setRcContent(String rcContent) {
+        this.rcContent = rcContent;
+    }
 }
 }

+ 73 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/extend/UserTextbookGroupExtendDto.java

@@ -0,0 +1,73 @@
+package com.qxgmat.dto.extend;
+
+public class UserTextbookGroupExtendDto {
+    private String logic;
+
+    private String title;
+
+    private Integer questionNumber;
+
+    private Integer userNumber;
+
+    private Integer minTimes;
+
+    private Integer userPaperId;
+
+    private UserReportExtendDto report;
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public Integer getQuestionNumber() {
+        return questionNumber;
+    }
+
+    public void setQuestionNumber(Integer questionNumber) {
+        this.questionNumber = questionNumber;
+    }
+
+    public Integer getUserNumber() {
+        return userNumber;
+    }
+
+    public void setUserNumber(Integer userNumber) {
+        this.userNumber = userNumber;
+    }
+
+    public Integer getMinTimes() {
+        return minTimes;
+    }
+
+    public void setMinTimes(Integer minTimes) {
+        this.minTimes = minTimes;
+    }
+
+    public UserReportExtendDto getReport() {
+        return report;
+    }
+
+    public void setReport(UserReportExtendDto report) {
+        this.report = report;
+    }
+
+    public Integer getUserPaperId() {
+        return userPaperId;
+    }
+
+    public void setUserPaperId(Integer userPaperId) {
+        this.userPaperId = userPaperId;
+    }
+
+    public String getLogic() {
+        return logic;
+    }
+
+    public void setLogic(String logic) {
+        this.logic = logic;
+    }
+}

+ 18 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/PaperBaseDto.java

@@ -11,6 +11,8 @@ public class PaperBaseDto {
     private String title;
     private String title;
     private Integer time;
     private Integer time;
     private Integer questionNumber;
     private Integer questionNumber;
+    private Integer times;
+    private Integer isAdapt;
 
 
     public Integer getQuestionNumber() {
     public Integer getQuestionNumber() {
         return questionNumber;
         return questionNumber;
@@ -59,4 +61,20 @@ public class PaperBaseDto {
     public void setTime(Integer time) {
     public void setTime(Integer time) {
         this.time = time;
         this.time = time;
     }
     }
+
+    public Integer getIsAdapt() {
+        return isAdapt;
+    }
+
+    public void setIsAdapt(Integer isAdapt) {
+        this.isAdapt = isAdapt;
+    }
+
+    public Integer getTimes() {
+        return times;
+    }
+
+    public void setTimes(Integer times) {
+        this.times = times;
+    }
 }
 }

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

@@ -19,6 +19,9 @@ public class UserStudyDetailDto {
     // 各部分时长
     // 各部分时长
     private List<UserStudyExtendDto> categorys;
     private List<UserStudyExtendDto> categorys;
 
 
+    // 全站平均时长
+    private Integer avgTime;
+
     public Integer getDays() {
     public Integer getDays() {
         return days;
         return days;
     }
     }
@@ -50,4 +53,12 @@ public class UserStudyDetailDto {
     public void setCategorys(List<UserStudyExtendDto> categorys) {
     public void setCategorys(List<UserStudyExtendDto> categorys) {
         this.categorys = categorys;
         this.categorys = categorys;
     }
     }
+
+    public Integer getAvgTime() {
+        return avgTime;
+    }
+
+    public void setAvgTime(Integer avgTime) {
+        this.avgTime = avgTime;
+    }
 }
 }

+ 118 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserTextbookGroupDto.java

@@ -0,0 +1,118 @@
+package com.qxgmat.dto.response;
+
+import com.qxgmat.data.inline.PaperStat;
+import com.qxgmat.data.inline.UserQuestionStat;
+import com.qxgmat.dto.extend.UserTextbookGroupExtendDto;
+
+import java.util.List;
+public class UserTextbookGroupDto {
+    private Integer id;
+
+    private String titleZh;
+
+    private String titleEn;
+
+    private String description;
+
+    private String extend;
+
+    private Integer questionNumber;
+
+    private Integer minTimes;
+
+    private Integer userNumber;
+
+    private PaperStat stat;
+
+    private UserQuestionStat userStat;
+
+    private List<UserTextbookGroupExtendDto> children;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getTitleZh() {
+        return titleZh;
+    }
+
+    public void setTitleZh(String titleZh) {
+        this.titleZh = titleZh;
+    }
+
+    public String getTitleEn() {
+        return titleEn;
+    }
+
+    public void setTitleEn(String titleEn) {
+        this.titleEn = titleEn;
+    }
+
+    public String getExtend() {
+        return extend;
+    }
+
+    public void setExtend(String extend) {
+        this.extend = extend;
+    }
+
+    public Integer getQuestionNumber() {
+        return questionNumber;
+    }
+
+    public void setQuestionNumber(Integer questionNumber) {
+        this.questionNumber = questionNumber;
+    }
+
+    public Integer getUserNumber() {
+        return userNumber;
+    }
+
+    public void setUserNumber(Integer userNumber) {
+        this.userNumber = userNumber;
+    }
+
+    public PaperStat getStat() {
+        return stat;
+    }
+
+    public void setStat(PaperStat stat) {
+        this.stat = stat;
+    }
+
+    public UserQuestionStat getUserStat() {
+        return userStat;
+    }
+
+    public void setUserStat(UserQuestionStat userStat) {
+        this.userStat = userStat;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Integer getMinTimes() {
+        return minTimes;
+    }
+
+    public void setMinTimes(Integer minTimes) {
+        this.minTimes = minTimes;
+    }
+
+    public List<UserTextbookGroupExtendDto> getChildren() {
+        return children;
+    }
+
+    public void setChildren(List<UserTextbookGroupExtendDto> children) {
+        this.children = children;
+    }
+}

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

@@ -0,0 +1,70 @@
+package com.qxgmat.dto.response;
+
+import com.nuliji.tools.annotation.Dto;
+import com.qxgmat.data.dao.entity.TextbookPaper;
+import com.qxgmat.data.inline.PaperStat;
+import com.qxgmat.dto.extend.UserPaperBaseExtendDto;
+import com.qxgmat.dto.extend.UserReportExtendDto;
+
+@Dto(entity = TextbookPaper.class)
+public class UserTextbookPaperDto {
+    private Integer id;
+
+    private String title;
+
+    private PaperStat stat;
+
+    private UserPaperBaseExtendDto paper;
+
+    private UserReportExtendDto report;
+
+    private Integer userPaperId;
+
+    public PaperStat getStat() {
+        return stat;
+    }
+
+    public void setStat(PaperStat stat) {
+        this.stat = stat;
+    }
+
+    public UserPaperBaseExtendDto getPaper() {
+        return paper;
+    }
+
+    public void setPaper(UserPaperBaseExtendDto paper) {
+        this.paper = paper;
+    }
+
+    public UserReportExtendDto getReport() {
+        return report;
+    }
+
+    public void setReport(UserReportExtendDto report) {
+        this.report = report;
+    }
+
+    public Integer getUserPaperId() {
+        return userPaperId;
+    }
+
+    public void setUserPaperId(Integer userPaperId) {
+        this.userPaperId = userPaperId;
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+}

+ 6 - 2
server/gateway-api/src/main/java/com/qxgmat/help/AiHelp.java

@@ -32,8 +32,12 @@ public class AiHelp {
         // City类可用于IPDB格式的IPv4免费库,IPv4与IPv6的每周高级版、每日标准版、每日高级版、每日专业版、每日旗舰版
         // City类可用于IPDB格式的IPv4免费库,IPv4与IPv6的每周高级版、每日标准版、每日高级版、每日专业版、每日旗舰版
         if (path.startsWith(".")){
         if (path.startsWith(".")){
             // 相对路径,从resource中获取
             // 相对路径,从resource中获取
-            logger.debug(this.getClass().getClassLoader().getResource(path).toString());
-            cityDb = new City(this.getClass().getClassLoader().getResourceAsStream(path));
+            logger.debug("{}, {}", path, this.getClass().getClassLoader().getResource(path));
+            try {
+                cityDb = new City(this.getClass().getClassLoader().getResourceAsStream(path));
+            }catch (Exception e){
+                logger.error(e.getLocalizedMessage());
+            }
         }else{
         }else{
             cityDb = new City(path);
             cityDb = new City(path);
         }
         }

+ 35 - 0
server/gateway-api/src/main/java/com/qxgmat/service/UserQuestionService.java

@@ -14,6 +14,8 @@ import com.qxgmat.data.dao.UserQuestionMapper;
 import com.qxgmat.data.dao.entity.UserQuestion;
 import com.qxgmat.data.dao.entity.UserQuestion;
 import com.qxgmat.data.dao.entity.UserReport;
 import com.qxgmat.data.dao.entity.UserReport;
 import com.qxgmat.data.inline.UserQuestionStat;
 import com.qxgmat.data.inline.UserQuestionStat;
+import com.qxgmat.data.relation.UserQuestionRelationMapper;
+import com.qxgmat.data.relation.entity.UserRecordStatRelation;
 import com.qxgmat.service.annotation.InitQuestion;
 import com.qxgmat.service.annotation.InitQuestion;
 import com.qxgmat.service.inline.QuestionNoService;
 import com.qxgmat.service.inline.QuestionNoService;
 import com.qxgmat.service.inline.SentenceQuestionService;
 import com.qxgmat.service.inline.SentenceQuestionService;
@@ -34,6 +36,9 @@ public class UserQuestionService extends AbstractService {
     @Resource
     @Resource
     private UserQuestionMapper userQuestionMapper;
     private UserQuestionMapper userQuestionMapper;
 
 
+    @Resource
+    private UserQuestionRelationMapper userQuestionRelationMapper;
+
     /**
     /**
      * 用户错题记录:相同题目的最后一次做题记录及其编号
      * 用户错题记录:相同题目的最后一次做题记录及其编号
      * @param page
      * @param page
@@ -220,6 +225,36 @@ public class UserQuestionService extends AbstractService {
         return select(userQuestionMapper, example);
         return select(userQuestionMapper, example);
     }
     }
 
 
+
+    /**
+     * 统计用户的做题记录
+     * @param userId
+     * @param startTime
+     * @param endTime
+     * @return
+     */
+    public UserRecordStatRelation stat(Integer userId, String startTime, String endTime){
+        List<UserRecordStatRelation> list = userQuestionRelationMapper.stat(userId, startTime, endTime);
+        if (list!=null && list.size() > 0){
+            return list.get(1);
+        }
+        return null;
+    }
+
+    /**
+     * 统计全站的做题记录
+     * @param startTime
+     * @param endTime
+     * @return
+     */
+    public UserRecordStatRelation statAvg(String startTime, String endTime){
+        List<UserRecordStatRelation> list = userQuestionRelationMapper.statAvg(startTime, endTime);
+        if (list!=null && list.size() > 0){
+            return list.get(1);
+        }
+        return null;
+    }
+
     public UserQuestion add(UserQuestion question){
     public UserQuestion add(UserQuestion question){
         int result = insert(userQuestionMapper, question);
         int result = insert(userQuestionMapper, question);
         question = one(userQuestionMapper, question.getId());
         question = one(userQuestionMapper, question.getId());

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

@@ -4,7 +4,9 @@ import com.nuliji.tools.Tools;
 import com.qxgmat.data.constants.enums.module.ProductType;
 import com.qxgmat.data.constants.enums.module.ProductType;
 import com.qxgmat.data.dao.entity.Course;
 import com.qxgmat.data.dao.entity.Course;
 import com.qxgmat.data.dao.entity.UserOrderRecord;
 import com.qxgmat.data.dao.entity.UserOrderRecord;
+import com.qxgmat.data.relation.entity.UserRecordStatRelation;
 import com.qxgmat.service.inline.CourseService;
 import com.qxgmat.service.inline.CourseService;
+import com.qxgmat.service.inline.UserCourseRecordService;
 import com.qxgmat.service.inline.UserOrderRecordService;
 import com.qxgmat.service.inline.UserOrderRecordService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
@@ -20,6 +22,9 @@ public class CourseExtendService {
     @Autowired
     @Autowired
     private UserOrderRecordService userOrderRecordService;
     private UserOrderRecordService userOrderRecordService;
 
 
+    @Autowired
+    private UserCourseRecordService userCourseRecordService;
+
     /**
     /**
      * 计算vs课程有效期
      * 计算vs课程有效期
      * @param vsNumber
      * @param vsNumber
@@ -53,7 +58,17 @@ public class CourseExtendService {
      * @param userId
      * @param userId
      * @return
      * @return
      */
      */
-    public Integer studyTime(Integer userId){
-        return 0;
+    public Integer studyTime(Integer userId, Date startTime, Date endTime){
+        UserRecordStatRelation record = userCourseRecordService.stat(userId, startTime.toString(), endTime.toString());
+        return record == null ? record.getUserTime() : 0;
+    }
+
+    /**
+     * 全站平均听课时间
+     * @return
+     */
+    public Integer studyAvgTime(Date startTime, Date endTime){
+        UserRecordStatRelation record = userCourseRecordService.statAvg(startTime.toString(), endTime.toString());
+        return record == null ? record.getUserTime() : 0;
     }
     }
 }
 }

+ 64 - 4
server/gateway-api/src/main/java/com/qxgmat/service/extend/ExaminationService.java

@@ -5,13 +5,15 @@ import com.github.pagehelper.Page;
 import com.nuliji.tools.AbstractService;
 import com.nuliji.tools.AbstractService;
 import com.nuliji.tools.PageResult;
 import com.nuliji.tools.PageResult;
 import com.nuliji.tools.Transform;
 import com.nuliji.tools.Transform;
+import com.nuliji.tools.exception.ParameterException;
+import com.nuliji.tools.exception.SystemException;
 import com.qxgmat.data.constants.enums.QuestionDifficult;
 import com.qxgmat.data.constants.enums.QuestionDifficult;
 import com.qxgmat.data.constants.enums.QuestionSubject;
 import com.qxgmat.data.constants.enums.QuestionSubject;
 import com.qxgmat.data.constants.enums.QuestionType;
 import com.qxgmat.data.constants.enums.QuestionType;
+import com.qxgmat.data.constants.enums.ServiceKey;
+import com.qxgmat.data.constants.enums.module.PaperOrigin;
 import com.qxgmat.data.constants.enums.status.DirectionStatus;
 import com.qxgmat.data.constants.enums.status.DirectionStatus;
-import com.qxgmat.data.dao.entity.ExaminationPaper;
-import com.qxgmat.data.dao.entity.ExaminationStruct;
-import com.qxgmat.data.dao.entity.UserQuestion;
+import com.qxgmat.data.dao.entity.*;
 import com.qxgmat.data.relation.ExaminationPaperRelationMapper;
 import com.qxgmat.data.relation.ExaminationPaperRelationMapper;
 import com.qxgmat.data.relation.QuestionNoRelationMapper;
 import com.qxgmat.data.relation.QuestionNoRelationMapper;
 import com.qxgmat.data.relation.UserPaperRelationMapper;
 import com.qxgmat.data.relation.UserPaperRelationMapper;
@@ -178,7 +180,7 @@ public class ExaminationService extends AbstractService {
     }
     }
 
 
     /**
     /**
-     * 查找练习组卷
+     * 查找模考组卷
      * @param page
      * @param page
      * @param size
      * @param size
      * @param structId
      * @param structId
@@ -199,6 +201,64 @@ public class ExaminationService extends AbstractService {
     }
     }
 
 
     /**
     /**
+     * cat模考是否已经完成
+     * @param userId
+     * @return
+     */
+    public boolean isFinishCat(Integer userId){
+        ExaminationStruct struct = getCat();
+        List<ExaminationPaper> paperList = examinationPaperService.listByTwo(struct.getId());
+        Collection ids = Transform.getIds(paperList, ExaminationPaper.class, "id");
+        List<UserPaper> userPaperList = userPaperService.listWithOrigin(userId, PaperOrigin.EXAMINATION, ids, null);
+        if (paperList.size() != userPaperList.size()){
+            return false;
+        }
+        Collection paperIds = Transform.getIds(userPaperList, UserPaper.class, "id");
+        List<UserReport> reportList = userReportService.listWithLater(paperIds);
+        for(UserReport report: reportList){
+            if(report.getIsFinish() == 0){
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 重置Cat模考系列
+     * @param userId
+     * @return
+     */
+    @Transactional
+    public Boolean resetCat(Integer userId, boolean force){
+        ExaminationStruct struct = getCat();
+        List<ExaminationPaper> paperList = examinationPaperService.listByTwo(struct.getId());
+        Collection ids = Transform.getIds(paperList, ExaminationPaper.class, "id");
+        List<UserPaper> userPaperList = userPaperService.listWithOrigin(userId, PaperOrigin.EXAMINATION, ids, null);
+        if (!force && paperList.size() != userPaperList.size()){
+            throw new ParameterException("未完成所有");
+        }
+        Collection paperIds = Transform.getIds(userPaperList, UserPaper.class, "id");
+        if(!force){
+            List<UserReport> reportList = userReportService.listWithLater(paperIds);
+            for(UserReport report: reportList){
+                if(report.getIsFinish() == 0){
+                    throw new ParameterException("未完成所有");
+                }
+            }
+        }
+        return userPaperService.reset(paperIds, userId);
+    }
+
+    public ExaminationStruct getCat(){
+        List<ExaminationStruct> list = examinationStructService.main();
+        for (ExaminationStruct struct : list){
+            if (struct.getLevel() == 1) continue;
+            if (struct.getExtend().equals(ServiceKey.QX_CAT.key)) return struct;
+        }
+        throw new SystemException("没有找到cat模考节点");
+    }
+
+    /**
      * 获取下一阶段难度分
      * 获取下一阶段难度分
      * @param currentLevel
      * @param currentLevel
      * @param number
      * @param number

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

@@ -61,6 +61,9 @@ public class OrderFlowService {
     @Resource
     @Resource
     private UsersService usersService;
     private UsersService usersService;
 
 
+    @Resource
+    private ExaminationService examinationService;
+
     private TradeService tradeService;
     private TradeService tradeService;
 
 
     @Resource
     @Resource
@@ -449,19 +452,22 @@ public class OrderFlowService {
                         .build();
                         .build();
                 userService = userServiceService.add(userService);
                 userService = userServiceService.add(userService);
             }else{
             }else{
-                if (userService.getExpireTime() != null && userService.getExpireTime().before(time)){
+                if (serviceKey == ServiceKey.QX_CAT){
+                    // cat逻辑独立
+                    if (userService.getExpireTime().after(time)){
+                        // 有效期内
+                        if (userService.getIsReset() == 0) throw new ParameterException("已开通当前服务");
+                        // 第二次还未做完
+                        if (userService.getIsReset() == 1 && examinationService.isFinishCat(record.getUserId()))  throw new ParameterException("已开通当前服务");
+                    }
+                    // 重置
+                    userService.setIsReset(0);
+                    examinationService.resetCat(record.getUserId(), true);
+                }else if (userService.getExpireTime() != null && userService.getExpireTime().before(time)){
                     // 已到期 - 续期
                     // 已到期 - 续期
                     userService.setStartTime(startTime);
                     userService.setStartTime(startTime);
                     userService.setExpireTime(endTime);
                     userService.setExpireTime(endTime);
                 }else{
                 }else{
-                    if (serviceKey == ServiceKey.QX_CAT){
-                        if (userService.getIsReset() == 0){
-                            // 未到期 - 报错
-                            throw new ParameterException("已开通当前服务");
-                        }
-                        // 重置
-                        userService.setIsReset(0);
-                    }
                     // 未到期 - 延长有效期
                     // 未到期 - 延长有效期
                     startTime = userService.getExpireTime();
                     startTime = userService.getExpireTime();
                     if (expireDay > 0){
                     if (expireDay > 0){
@@ -850,7 +856,7 @@ public class OrderFlowService {
         UserOrderRecord record = UserOrderRecord.builder()
         UserOrderRecord record = UserOrderRecord.builder()
                 .userId(userId)
                 .userId(userId)
                 .service(ServiceKey.VIP.key)
                 .service(ServiceKey.VIP.key)
-                .param(ServiceVipKey.MONTH6.key)
+                .param(ServiceVipKey.MONTH3.key)
                 .source(RecordSource.REAL.key)
                 .source(RecordSource.REAL.key)
                 .build();
                 .build();
         // 虚拟order
         // 虚拟order

+ 13 - 9
server/gateway-api/src/main/java/com/qxgmat/service/extend/PreviewService.java

@@ -57,6 +57,9 @@ public class PreviewService extends AbstractService {
     @Resource
     @Resource
     private UserCourseProgressService userCourseProgressService;
     private UserCourseProgressService userCourseProgressService;
 
 
+    @Resource
+    private UserCourseService userCourseService;
+
     /**
     /**
      * 获取用户分组作业列表
      * 获取用户分组作业列表
      * @param userId
      * @param userId
@@ -67,7 +70,7 @@ public class PreviewService extends AbstractService {
         Map<Object, Collection<UserPreviewPaperRelation>> relationMap = new HashMap<>();
         Map<Object, Collection<UserPreviewPaperRelation>> relationMap = new HashMap<>();
         for(Object id : recordIds){
         for(Object id : recordIds){
             Integer recordId = (Integer)id;
             Integer recordId = (Integer)id;
-            relationMap.put(recordId, list(userId, recordId, null, 0, top));
+            relationMap.put(recordId, list(1, top, userId, recordId, null, 0));
         }
         }
         return relationMap;
         return relationMap;
     }
     }
@@ -80,7 +83,7 @@ public class PreviewService extends AbstractService {
      * @param times
      * @param times
      * @return
      * @return
      */
      */
-    public List<UserPreviewPaperRelation> list(Integer recordId, Integer userId, String endTime, Integer times, Integer top){
+    public List<UserPreviewPaperRelation> list(int page, int size, Integer recordId, Integer userId, String endTime, Integer times){
         // 根据不同的课程,执行不同的查询方案
         // 根据不同的课程,执行不同的查询方案
         UserOrderRecord record = userOrderRecordService.get(recordId);
         UserOrderRecord record = userOrderRecordService.get(recordId);
         if (record == null){
         if (record == null){
@@ -100,18 +103,19 @@ public class PreviewService extends AbstractService {
                 // 查询记录对应预约情况
                 // 查询记录对应预约情况
                 List<UserCourseAppointment> appointmentList = userCourseAppointmentService.listByRecord(recordId);
                 List<UserCourseAppointment> appointmentList = userCourseAppointmentService.listByRecord(recordId);
                 Collection appointmentIds = Transform.getIds(appointmentList, UserCourseAppointment.class, "id");
                 Collection appointmentIds = Transform.getIds(appointmentList, UserCourseAppointment.class, "id");
-                previewAssignList = previewAssignService.listByAppointment(appointmentIds, endTime, top);
+                previewAssignList = previewAssignService.listByAppointment(page, size, course.getId(), appointmentIds, userId, endTime, times);
                 break;
                 break;
             case ONLINE:
             case ONLINE:
                 // 查询记录对应时间段内
                 // 查询记录对应时间段内
-                previewAssignList = previewAssignService.listByTime(record.getTimeId(), endTime, top);
+                previewAssignList = previewAssignService.listByTime(page, size, course.getId(), record.getTimeId(), userId, endTime, times);
                 replaceTitle(previewAssignList);
                 replaceTitle(previewAssignList);
                 break;
                 break;
             case VIDEO:
             case VIDEO:
                 // 获取课时,并关联当前记录的paper
                 // 获取课时,并关联当前记录的paper
                 if (endTime != null){
                 if (endTime != null){
                     // 无论列表还是卡片,都只显示2条
                     // 无论列表还是卡片,都只显示2条
-                    top = 2;
+                    size = 2;
+                    page = 1;
                     List<CourseNo> courseNoList = courseNoService.allCourse(course.getId());
                     List<CourseNo> courseNoList = courseNoService.allCourse(course.getId());
                     // 查询课时进度
                     // 查询课时进度
                     List<UserCourseProgress> progressList =userCourseProgressService.listCourse(record.getId(), course.getId());
                     List<UserCourseProgress> progressList =userCourseProgressService.listCourse(record.getId(), course.getId());
@@ -131,12 +135,12 @@ public class PreviewService extends AbstractService {
                         }
                         }
                         break;
                         break;
                     }
                     }
-                    int max = min+top -1;
+                    int max = min+size -1;
                     int finalMin = min;
                     int finalMin = min;
                     List<CourseNo> select = courseNoList.stream().filter(row->row.getNo() >= finalMin && row.getNo()<=max).collect(Collectors.toList());
                     List<CourseNo> select = courseNoList.stream().filter(row->row.getNo() >= finalMin && row.getNo()<=max).collect(Collectors.toList());
                     previewAssignList = previewAssignService.listByCourseNos(course.getId(), getIds(select, CourseNo.class, "id"));
                     previewAssignList = previewAssignService.listByCourseNos(course.getId(), getIds(select, CourseNo.class, "id"));
                 }else{
                 }else{
-                    previewAssignList = previewAssignService.listByCourse(course.getId());
+                    previewAssignList = previewAssignService.listByCourse(page, size, course.getId(), userId, times);
                 }
                 }
                 replaceTitle(previewAssignList);
                 replaceTitle(previewAssignList);
                 break;
                 break;
@@ -176,8 +180,8 @@ public class PreviewService extends AbstractService {
                 return timeRecord.getId();
                 return timeRecord.getId();
             case VIDEO:
             case VIDEO:
                 // 获取当前该课程记录
                 // 获取当前该课程记录
-                UserOrderRecord record = userOrderRecordService.getByUserAndCourse(userId, assign.getCourseId(), true);
-                return record != null ? record.getId() : 0;
+                UserCourse record = userCourseService.getCourse(userId, assign.getCourseId());
+                return record != null ? record.getRecordId() : 0;
             default:
             default:
                 return 0;
                 return 0;
         }
         }

+ 11 - 22
server/gateway-api/src/main/java/com/qxgmat/service/extend/QuestionFlowService.java

@@ -187,6 +187,7 @@ public class QuestionFlowService {
         initPaperCallback.put(PaperModule.EXAMINATION, (userPaper, id)->{
         initPaperCallback.put(PaperModule.EXAMINATION, (userPaper, id)->{
             ExaminationPaper paper = examinationPaperService.get(id);
             ExaminationPaper paper = examinationPaperService.get(id);
             userPaper.setTitle(paper.getTitle());
             userPaper.setTitle(paper.getTitle());
+            userPaper.setIsAdapt(paper.getIsAdapt());
         });
         });
 
 
         initReportCallback.put(PaperModule.EXERCISE, (report, paper)->{
         initReportCallback.put(PaperModule.EXERCISE, (report, paper)->{
@@ -649,6 +650,7 @@ public class QuestionFlowService {
         // 分析做题结果
         // 分析做题结果
         StatReport callback = finishCallback.get(PaperModule.ValueOf(userReport.getPaperModule()));
         StatReport callback = finishCallback.get(PaperModule.ValueOf(userReport.getPaperModule()));
         callback.callback(userReport, userQuestionList);
         callback.callback(userReport, userQuestionList);
+        userReport.setIsStat(1);
         userReportService.edit(userReport);
         userReportService.edit(userReport);
 
 
         // 统计: 更新对应paper记录
         // 统计: 更新对应paper记录
@@ -671,42 +673,29 @@ public class QuestionFlowService {
         // 分析做题结果
         // 分析做题结果
         StatReport callback = finishCallback.get(PaperModule.ValueOf(userReport.getPaperModule()));
         StatReport callback = finishCallback.get(PaperModule.ValueOf(userReport.getPaperModule()));
         callback.callback(userReport, userQuestionList);
         callback.callback(userReport, userQuestionList);
+        userReport.setIsStat(1);
         userReportService.edit(userReport);
         userReportService.edit(userReport);
 
 
         return userPaperService.reset(userPaperId, userId);
         return userPaperService.reset(userPaperId, userId);
     }
     }
 
 
     /**
     /**
-     * 重置模考系列
-     * @param structId
+     * 累计考试学习时间
      * @param userId
      * @param userId
      * @return
      * @return
      */
      */
-    @Transactional
-    public Boolean restartExamination(Integer structId, Integer userId){
-        List<ExaminationPaper> paperList = examinationPaperService.listByTwo(structId);
-        Collection ids = Transform.getIds(paperList, ExaminationPaper.class, "id");
-        List<UserPaper> userPaperList = userPaperService.listWithOrigin(userId, PaperOrigin.EXAMINATION, ids, null);
-        if (paperList.size() != userPaperList.size()){
-            throw new ParameterException("未完成所有");
-        }
-        Collection paperIds = Transform.getIds(userPaperList, UserPaper.class, "id");
-        List<UserReport> reportList = userReportService.listWithLater(paperIds);
-        for(UserReport report: reportList){
-            if(report.getIsFinish() == 0){
-                throw new ParameterException("未完成所有");
-            }
-        }
-        return userPaperService.reset(paperIds, userId);
+    public Integer studyTime(Integer userId, Date startTime, Date endTime){
+        UserRecordStatRelation record = userQuestionService.stat(userId, startTime.toString(), endTime.toString());
+        return record == null ? record.getUserTime() : 0;
     }
     }
 
 
     /**
     /**
-     * 累计考试学习时间
-     * @param userId
+     * 平均考试时间
      * @return
      * @return
      */
      */
-    public Integer studyTime(Integer userId, Date startTime, Date endTime){
-        return 0;
+    public Integer studyAvgTime(Date startTime, Date endTime){
+        UserRecordStatRelation record = userQuestionService.statAvg(startTime.toString(), endTime.toString());
+        return record == null ? record.getUserTime() : 0;
     }
     }
 
 
     /**
     /**

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

@@ -7,12 +7,10 @@ import com.qxgmat.data.constants.enums.logic.SentenceLogic;
 import com.qxgmat.data.dao.entity.*;
 import com.qxgmat.data.dao.entity.*;
 import com.qxgmat.data.relation.UserReportRelationMapper;
 import com.qxgmat.data.relation.UserReportRelationMapper;
 import com.qxgmat.data.relation.entity.SentenceQuestionRelation;
 import com.qxgmat.data.relation.entity.SentenceQuestionRelation;
+import com.qxgmat.data.relation.entity.UserRecordStatRelation;
 import com.qxgmat.data.relation.entity.UserSentencePaperRelation;
 import com.qxgmat.data.relation.entity.UserSentencePaperRelation;
 import com.qxgmat.service.UserPaperService;
 import com.qxgmat.service.UserPaperService;
-import com.qxgmat.service.inline.SentencePaperService;
-import com.qxgmat.service.inline.QuestionService;
-import com.qxgmat.service.inline.SentenceQuestionService;
-import com.qxgmat.service.inline.UserReportService;
+import com.qxgmat.service.inline.*;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
@@ -20,6 +18,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import javax.annotation.Resource;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collection;
+import java.util.Date;
 import java.util.List;
 import java.util.List;
 
 
 @Service
 @Service
@@ -43,6 +42,12 @@ public class SentenceService {
     @Resource
     @Resource
     private UserPaperService userPaperService;
     private UserPaperService userPaperService;
 
 
+    @Resource
+    private UserSentenceRecordService userSentenceRecordService;
+
+    @Resource
+    private SentenceCodeService sentenceCodeService;
+
 
 
     /**
     /**
      * 添加长难句题目:加入题库,关联题目,并关联长难句paper
      * 添加长难句题目:加入题库,关联题目,并关联长难句paper
@@ -177,7 +182,28 @@ public class SentenceService {
      * @param userId
      * @param userId
      * @return
      * @return
      */
      */
-    public Integer studyTime(Integer userId){
-        return 0;
+    public Integer studyTime(Integer userId, Date startTime, Date endTime){
+        UserRecordStatRelation record = userSentenceRecordService.stat(userId, startTime.toString(), endTime.toString());
+        return record == null ? record.getUserTime() : 0;
+    }
+
+    /**
+     * 全站平均时间
+     * @return
+     */
+    public Integer studyAvgTime(Date startTime, Date endTime){
+        UserRecordStatRelation record = userSentenceRecordService.statAvg(startTime.toString(), endTime.toString());
+        return record == null ? record.getUserTime() : 0;
+    }
+
+    /**
+     * 激活长难句
+     * @param userId
+     * @param code
+     */
+    public void active(Integer userId, String code){
+        if (sentenceCodeService.isActive(userId) == null){
+            sentenceCodeService.active(userId, code);
+        }
     }
     }
 }
 }

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

@@ -83,7 +83,7 @@ public class TextbookService {
 
 
         relation.setTitle(textbookQuestionService.generateTitle(prefixTitle, relation.getNo()));
         relation.setTitle(textbookQuestionService.generateTitle(prefixTitle, relation.getNo()));
         // 保存年份
         // 保存年份
-        relation.setTime(String.valueOf(Tools.year(library.getStartDate())));
+        relation.setYear(String.valueOf(Tools.year(library.getStartDate())));
 
 
         TextbookQuestion textbookQuestion =  textbookQuestionService.add(relation);
         TextbookQuestion textbookQuestion =  textbookQuestionService.add(relation);
 
 
@@ -128,7 +128,7 @@ public class TextbookService {
             }
             }
             paper = textbookPaperService.add(TextbookPaper.builder()
             paper = textbookPaperService.add(TextbookPaper.builder()
                     .logic(SentenceLogic.NO.key)
                     .logic(SentenceLogic.NO.key)
-                    .time(question.getTime())
+                    .year(question.getYear())
                     .libraryId(question.getLibraryId())
                     .libraryId(question.getLibraryId())
                     .title(textbookPaperService.generateTitle(prefixTitle, paperLength, no, 1))
                     .title(textbookPaperService.generateTitle(prefixTitle, paperLength, no, 1))
                     .no(no+1)
                     .no(no+1)

+ 27 - 42
server/gateway-api/src/main/java/com/qxgmat/service/inline/PreviewAssignService.java

@@ -2,6 +2,7 @@ package com.qxgmat.service.inline;
 
 
 import com.github.pagehelper.Page;
 import com.github.pagehelper.Page;
 import com.nuliji.tools.AbstractService;
 import com.nuliji.tools.AbstractService;
+import com.nuliji.tools.Transform;
 import com.nuliji.tools.exception.ParameterException;
 import com.nuliji.tools.exception.ParameterException;
 import com.nuliji.tools.exception.SystemException;
 import com.nuliji.tools.exception.SystemException;
 import com.nuliji.tools.mybatis.Example;
 import com.nuliji.tools.mybatis.Example;
@@ -11,6 +12,7 @@ import com.qxgmat.data.dao.PreviewAssignMapper;
 import com.qxgmat.data.dao.PreviewPaperMapper;
 import com.qxgmat.data.dao.PreviewPaperMapper;
 import com.qxgmat.data.dao.entity.PreviewAssign;
 import com.qxgmat.data.dao.entity.PreviewAssign;
 import com.qxgmat.data.dao.entity.PreviewPaper;
 import com.qxgmat.data.dao.entity.PreviewPaper;
+import com.qxgmat.data.relation.PreviewAssignRelationMapper;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
@@ -27,6 +29,9 @@ public class PreviewAssignService extends AbstractService {
     @Resource
     @Resource
     private PreviewAssignMapper previewAssignMapper;
     private PreviewAssignMapper previewAssignMapper;
 
 
+    @Resource
+    private PreviewAssignRelationMapper previewAssignRelationMapper;
+
     public Page<PreviewAssign> listAdmin(int page, int size, Integer paperId, String order, DirectionStatus direction){
     public Page<PreviewAssign> listAdmin(int page, int size, Integer paperId, String order, DirectionStatus direction){
         Example example = new Example(PreviewAssign.class);
         Example example = new Example(PreviewAssign.class);
         if(paperId != null){
         if(paperId != null){
@@ -73,13 +78,13 @@ public class PreviewAssignService extends AbstractService {
      * @param courseId
      * @param courseId
      * @return
      * @return
      */
      */
-    public List<PreviewAssign> listByCourse(Integer courseId){
-        Example example = new Example(PreviewAssign.class);
-        example.and(
-                example.createCriteria()
-                        .andEqualTo("courseId", courseId)
-        );
-        return select(previewAssignMapper, example);
+    public List<PreviewAssign> listByCourse(int page, int size, Integer courseId, Integer userId, Integer times){
+        Page<PreviewAssign> p = page(()->previewAssignRelationMapper.listByCourse(courseId, userId, times), page, size);
+        Collection ids = Transform.getIds(p, PreviewAssign.class, "id");
+        // 获取详细数据
+        List<PreviewAssign> list = select(ids);
+        Transform.replace(p, list, PreviewAssign.class, "id");
+        return p;
     }
     }
 
 
     /**
     /**
@@ -99,26 +104,16 @@ public class PreviewAssignService extends AbstractService {
 
 
     /**
     /**
      * 用户查询1v1相对的预约作业
      * 用户查询1v1相对的预约作业
-     * @param ids
+     * @param appointmentIds
      * @return
      * @return
      */
      */
-    public List<PreviewAssign> listByAppointment(Collection ids, String endTime, Integer top){
-        Example example = new Example(PreviewAssign.class);
-        example.and(
-                example.createCriteria()
-                        .andIn("courseAppointment", ids)
-        );
-        if (endTime != null){
-            example.and(
-                    example.createCriteria()
-                        .andLessThanOrEqualTo("endTime", endTime)
-            );
-        }
-        example.orderBy("startTime").asc();
-        if (top != null){
-            return select(previewAssignMapper, example, 1, top);
-        }
-        return select(previewAssignMapper, example);
+    public List<PreviewAssign> listByAppointment(int page, int size, Integer courseId, Collection appointmentIds, Integer userId, String endTime, Integer times){
+        Page<PreviewAssign> p = page(()->previewAssignRelationMapper.listByAppointment(courseId, appointmentIds, userId, endTime, times), page, size);
+        Collection ids = Transform.getIds(p, PreviewAssign.class, "id");
+        // 获取详细数据
+        List<PreviewAssign> list = select(ids);
+        Transform.replace(p, list, PreviewAssign.class, "id");
+        return p;
     }
     }
 
 
     public boolean removeCourseAppointment(Integer courseId, Integer id){
     public boolean removeCourseAppointment(Integer courseId, Integer id){
@@ -136,23 +131,13 @@ public class PreviewAssignService extends AbstractService {
      * @param timeId
      * @param timeId
      * @return
      * @return
      */
      */
-    public List<PreviewAssign> listByTime(Integer timeId, String endTime, Integer top){
-        Example example = new Example(PreviewAssign.class);
-        example.and(
-                example.createCriteria()
-                        .andEqualTo("courseTime", timeId)
-        );
-        if (endTime != null){
-            example.and(
-                    example.createCriteria()
-                            .andLessThanOrEqualTo("endTime", endTime)
-            );
-        }
-        example.orderBy("startTime").asc();
-        if (top != null){
-            return select(previewAssignMapper, example, 1, top);
-        }
-        return select(previewAssignMapper, example);
+    public List<PreviewAssign> listByTime(int page, int size, Integer courseId, Integer timeId, Integer userId, String endTime, Integer times){
+        Page<PreviewAssign> p = page(()->previewAssignRelationMapper.listByTime(courseId, timeId, userId, endTime, times), page, size);
+        Collection ids = Transform.getIds(p, PreviewAssign.class, "id");
+        // 获取详细数据
+        List<PreviewAssign> list = select(ids);
+        Transform.replace(p, list, PreviewAssign.class, "id");
+        return p;
     }
     }
 
 
     public boolean removeCourseTime(Integer courseId, Integer timeId){
     public boolean removeCourseTime(Integer courseId, Integer timeId){

+ 28 - 16
server/gateway-api/src/main/java/com/qxgmat/service/inline/TextbookPaperService.java

@@ -2,12 +2,15 @@ package com.qxgmat.service.inline;
 
 
 import com.github.pagehelper.Page;
 import com.github.pagehelper.Page;
 import com.nuliji.tools.AbstractService;
 import com.nuliji.tools.AbstractService;
+import com.nuliji.tools.PageResult;
+import com.nuliji.tools.Transform;
 import com.nuliji.tools.exception.ParameterException;
 import com.nuliji.tools.exception.ParameterException;
 import com.nuliji.tools.exception.SystemException;
 import com.nuliji.tools.exception.SystemException;
 import com.nuliji.tools.mybatis.Example;
 import com.nuliji.tools.mybatis.Example;
 import com.qxgmat.data.constants.enums.logic.TextbookLogic;
 import com.qxgmat.data.constants.enums.logic.TextbookLogic;
 import com.qxgmat.data.dao.TextbookPaperMapper;
 import com.qxgmat.data.dao.TextbookPaperMapper;
 import com.qxgmat.data.dao.entity.*;
 import com.qxgmat.data.dao.entity.*;
+import com.qxgmat.data.relation.TextbookPaperRelationMapper;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
@@ -22,6 +25,31 @@ public class TextbookPaperService extends AbstractService {
     @Resource
     @Resource
     private TextbookPaperMapper textbookPaperMapper;
     private TextbookPaperMapper textbookPaperMapper;
 
 
+    @Resource
+    private TextbookPaperRelationMapper textbookPaperRelationMapper;
+
+    /**
+     * 查找组卷
+     * @param page
+     * @param size
+     * @param libraryId
+     * @param userId
+     * @param logic
+     * @param times
+     * @return
+     */
+    public Page<TextbookPaper> list(int page, int size, Number libraryId, Number userId, TextbookLogic logic, Integer times){
+        String logicKey = logic != null ? logic.key : "";
+        Page<TextbookPaper> p = page(()->{
+            textbookPaperRelationMapper.listWithUser(libraryId, userId, logicKey, times);
+        },page, size);
+
+        Collection ids = Transform.getIds(p, TextbookPaper.class, "id");
+        // 获取详细数据
+        List<TextbookPaper> list = select(ids);
+        Transform.replace(p, list, TextbookPaper.class, "id");
+        return p;
+    }
     /**
     /**
      * 更新所有组卷title
      * 更新所有组卷title
      * @param libraryId
      * @param libraryId
@@ -68,22 +96,6 @@ public class TextbookPaperService extends AbstractService {
         return page(()->select(textbookPaperMapper, example), page, size);
         return page(()->select(textbookPaperMapper, example), page, size);
     }
     }
 
 
-    /**
-     * 获取可用的试卷列表:单个分组逻辑
-     * @param logic
-     * @return
-     */
-    public List<TextbookPaper> listByLogic(TextbookLogic logic){
-        Example example = new Example(SentencePaper.class);
-        example.and(
-                example.createCriteria()
-                        .andEqualTo("logic", logic.key)
-                        .andEqualTo("status", 1)
-        );
-        example.orderBy("no").asc();
-        return select(textbookPaperMapper, example);
-    }
-
     public List<TextbookPaper> listByQuestion(TextbookQuestion question){
     public List<TextbookPaper> listByQuestion(TextbookQuestion question){
         Example example = new Example(SentencePaper.class);
         Example example = new Example(SentencePaper.class);
         example.and(
         example.and(

+ 16 - 2
server/gateway-api/src/main/java/com/qxgmat/service/inline/TextbookQuestionService.java

@@ -119,6 +119,20 @@ public class TextbookQuestionService extends AbstractService {
     }
     }
 
 
     /**
     /**
+     * 获取换库表中的题目
+     * @param libraryId
+     * @return
+     */
+    public List<TextbookQuestion> listByLibrary(Integer libraryId){
+        Example example = new Example(TextbookQuestion.class);
+        example.and(
+                example.createCriteria()
+                        .andEqualTo("libraryId", libraryId)
+        );
+        return select(textbookQuestionMapper, example);
+    }
+
+    /**
      * 获取换库表中的最后一题
      * 获取换库表中的最后一题
      * @param libraryId
      * @param libraryId
      * @return
      * @return
@@ -232,7 +246,7 @@ public class TextbookQuestionService extends AbstractService {
     }
     }
 
 
     /**
     /**
-     * 根据长难句题目关系,获取完整题目:列表
+     * 根据题目关系,获取完整题目:列表
      * @param p
      * @param p
      * @return
      * @return
      */
      */
@@ -246,7 +260,7 @@ public class TextbookQuestionService extends AbstractService {
     }
     }
 
 
     /**
     /**
-     * 根据长难句题目关系,获取完整题目:单个
+     * 根据题目关系,获取完整题目:单个
      * @param p
      * @param p
      * @return
      * @return
      */
      */

+ 33 - 3
server/gateway-api/src/main/java/com/qxgmat/service/inline/UserCourseRecordService.java

@@ -8,8 +8,9 @@ import com.nuliji.tools.mybatis.Example;
 import com.qxgmat.data.dao.UserCourseRecordMapper;
 import com.qxgmat.data.dao.UserCourseRecordMapper;
 import com.qxgmat.data.dao.entity.UserCourseRecord;
 import com.qxgmat.data.dao.entity.UserCourseRecord;
 import com.qxgmat.data.relation.UserCourseRecordRelationMapper;
 import com.qxgmat.data.relation.UserCourseRecordRelationMapper;
-import com.qxgmat.data.relation.entity.UserCourseStatRelation;
+import com.qxgmat.data.relation.entity.UserModuleRecordStatRelation;
 import com.qxgmat.data.relation.entity.UserRankStatRelation;
 import com.qxgmat.data.relation.entity.UserRankStatRelation;
+import com.qxgmat.data.relation.entity.UserRecordStatRelation;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
@@ -28,7 +29,6 @@ public class UserCourseRecordService extends AbstractService {
     @Resource
     @Resource
     private UserCourseRecordRelationMapper userCourseRecordRelationMapper;
     private UserCourseRecordRelationMapper userCourseRecordRelationMapper;
 
 
-
     /**
     /**
      * 获取指定时间内的听课记录
      * 获取指定时间内的听课记录
      * @param userId
      * @param userId
@@ -46,6 +46,36 @@ public class UserCourseRecordService extends AbstractService {
         );
         );
         return select(userCourseRecordMapper, example);
         return select(userCourseRecordMapper, example);
     }
     }
+
+    /**
+     * 统计用户的听课记录
+     * @param userId
+     * @param startTime
+     * @param endTime
+     * @return
+     */
+    public UserRecordStatRelation stat(Integer userId, String startTime, String endTime){
+        List<UserRecordStatRelation> list = userCourseRecordRelationMapper.stat(userId, startTime, endTime);
+        if (list!=null && list.size() > 0){
+            return list.get(1);
+        }
+        return null;
+    }
+
+    /**
+     * 统计全站的听课记录
+     * @param startTime
+     * @param endTime
+     * @return
+     */
+    public UserRecordStatRelation statAvg(String startTime, String endTime){
+        List<UserRecordStatRelation> list = userCourseRecordRelationMapper.statAvg(startTime, endTime);
+        if (list!=null && list.size() > 0){
+            return list.get(1);
+        }
+        return null;
+    }
+
     /**
     /**
      * 统计不同题型用户的听课记录
      * 统计不同题型用户的听课记录
      * @param userId
      * @param userId
@@ -53,7 +83,7 @@ public class UserCourseRecordService extends AbstractService {
      * @param endTime
      * @param endTime
      * @return
      * @return
      */
      */
-    public List<UserCourseStatRelation> statGroupType(Integer userId, String startTime, String endTime){
+    public List<UserModuleRecordStatRelation> statGroupType(Integer userId, String startTime, String endTime){
         return userCourseRecordRelationMapper.statGroupType(userId, startTime, endTime);
         return userCourseRecordRelationMapper.statGroupType(userId, startTime, endTime);
     }
     }
 
 

+ 27 - 0
server/gateway-api/src/main/java/com/qxgmat/service/inline/UserOrderRecordService.java

@@ -9,6 +9,7 @@ import com.nuliji.tools.mybatis.Example;
 import com.qxgmat.data.constants.enums.ServiceKey;
 import com.qxgmat.data.constants.enums.ServiceKey;
 import com.qxgmat.data.constants.enums.module.CourseModule;
 import com.qxgmat.data.constants.enums.module.CourseModule;
 import com.qxgmat.data.constants.enums.module.ProductType;
 import com.qxgmat.data.constants.enums.module.ProductType;
+import com.qxgmat.data.constants.enums.module.VsCourseType;
 import com.qxgmat.data.constants.enums.status.DirectionStatus;
 import com.qxgmat.data.constants.enums.status.DirectionStatus;
 import com.qxgmat.data.dao.UserOrderRecordMapper;
 import com.qxgmat.data.dao.UserOrderRecordMapper;
 import com.qxgmat.data.dao.entity.UserOrder;
 import com.qxgmat.data.dao.entity.UserOrder;
@@ -313,6 +314,32 @@ public class UserOrderRecordService extends AbstractService {
     }
     }
 
 
     /**
     /**
+     * 列出用户学习记录
+     * @param page
+     * @param size
+     * @param courseId
+     * @param userId
+     * @return
+     */
+    public Page<UserOrderRecord> listWithVs(int page, int size, VsCourseType vsType, Integer courseId, Integer userId, String order, DirectionStatus direction){
+        if(order == null || order.isEmpty()) order = "id";
+        if (direction == null){
+            direction = DirectionStatus.DESC;
+        }
+        String finalOrder = order;
+        DirectionStatus finalDirection = direction;
+        Page<UserOrderRecord> p = page(
+                ()-> userOrderRecordRelationMapper.listWithVs(vsType != null ? vsType.key : null, courseId, userId, finalOrder, finalDirection.key)
+                , page, size);
+
+        Collection ids = Transform.getIds(p, UserOrderRecord.class, "id");
+        Transform.replace(p, select(ids), UserOrderRecord.class, "id");
+
+        return p;
+    }
+
+
+    /**
      * 获取最大vs课程编号
      * 获取最大vs课程编号
      * @param userId
      * @param userId
      * @return
      * @return

+ 16 - 6
server/gateway-api/src/main/java/com/qxgmat/service/inline/UserSentenceRecordService.java

@@ -5,14 +5,11 @@ import com.nuliji.tools.AbstractService;
 import com.nuliji.tools.exception.ParameterException;
 import com.nuliji.tools.exception.ParameterException;
 import com.nuliji.tools.exception.SystemException;
 import com.nuliji.tools.exception.SystemException;
 import com.nuliji.tools.mybatis.Example;
 import com.nuliji.tools.mybatis.Example;
-import com.qxgmat.data.dao.UserCourseRecordMapper;
 import com.qxgmat.data.dao.UserSentenceRecordMapper;
 import com.qxgmat.data.dao.UserSentenceRecordMapper;
 import com.qxgmat.data.dao.entity.UserCourseRecord;
 import com.qxgmat.data.dao.entity.UserCourseRecord;
 import com.qxgmat.data.dao.entity.UserSentenceRecord;
 import com.qxgmat.data.dao.entity.UserSentenceRecord;
-import com.qxgmat.data.relation.UserCourseRecordRelationMapper;
 import com.qxgmat.data.relation.UserSentenceRecordRelationMapper;
 import com.qxgmat.data.relation.UserSentenceRecordRelationMapper;
-import com.qxgmat.data.relation.entity.UserCourseStatRelation;
-import com.qxgmat.data.relation.entity.UserSentenceStatRelation;
+import com.qxgmat.data.relation.entity.UserRecordStatRelation;
 import org.slf4j.Logger;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
@@ -38,8 +35,8 @@ public class UserSentenceRecordService extends AbstractService {
      * @param endTime
      * @param endTime
      * @return
      * @return
      */
      */
-    public UserSentenceStatRelation stat(Integer userId, String startTime, String endTime){
-        List<UserSentenceStatRelation> list = userSentenceRecordRelationMapper.stat(userId, startTime, endTime);
+    public UserRecordStatRelation stat(Integer userId, String startTime, String endTime){
+        List<UserRecordStatRelation> list = userSentenceRecordRelationMapper.stat(userId, startTime, endTime);
         if (list!=null && list.size() > 0){
         if (list!=null && list.size() > 0){
             return list.get(1);
             return list.get(1);
         }
         }
@@ -47,6 +44,19 @@ public class UserSentenceRecordService extends AbstractService {
     }
     }
 
 
     /**
     /**
+     * 统计全站的阅读记录
+     * @param startTime
+     * @param endTime
+     * @return
+     */
+    public UserRecordStatRelation statAvg(String startTime, String endTime){
+        List<UserRecordStatRelation> list = userSentenceRecordRelationMapper.statAvg(startTime, endTime);
+        if (list!=null && list.size() > 0){
+            return list.get(1);
+        }
+        return null;
+    }
+    /**
      * 获取指定时间内的阅读记录
      * 获取指定时间内的阅读记录
      * @param userId
      * @param userId
      * @param startTime
      * @param startTime

+ 6 - 0
server/tools/src/main/java/com/nuliji/tools/Tools.java

@@ -69,6 +69,12 @@ public class Tools {
         return calendar.get(Calendar.DAY_OF_MONTH);
         return calendar.get(Calendar.DAY_OF_MONTH);
     }
     }
 
 
+    public static int getDayOfWeek(Date date){
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        return calendar.get(Calendar.DAY_OF_WEEK);
+    }
+
     public static byte[] getMd5(String str) {
     public static byte[] getMd5(String str) {
         try {
         try {
             MessageDigest md = MessageDigest.getInstance("MD5");
             MessageDigest md = MessageDigest.getInstance("MD5");