Browse Source

Merge branch 'master' of www.gitinn.com:zaixianjiaoyu/sourcecode

# Conflicts:
#	front/project/www/components/Date/index.js
#	front/project/www/components/Examination/index.js
KaysonCui 5 years ago
parent
commit
6cc23368e8

+ 2 - 0
front/project/Constant.js

@@ -60,6 +60,8 @@ export const PrepareStatus = [
 
 export const PrepareExaminationTime = [{ label: '近1个月', value: 'one_month' }, { label: '近2个月', value: 'two_month' }, { label: '近3个月', value: 'three_month' }, { label: '半年内', value: 'six_month' }];
 
+export const PrepareScoreTime = [{ label: '近1个月', value: 'one_month' }, { label: '近2个月', value: 'two_month' }, { label: '近3个月', value: 'three_month' }, { label: '半年内', value: 'six_month' }, { label: '1年内', value: 'one_year' }, { label: '不清楚', value: 'other' }];
+
 export const ProductType = [{ label: '服务', value: 'service' }, { label: '课程', value: 'course' }, { label: '资料', value: 'data' }, { label: '课程-套餐', value: 'course-package' }];
 
 export const ProductTypeMain = [{ label: '服务', value: 'service' }, { label: '课程', value: 'course' }, { label: '资料', value: 'data' }];

+ 3 - 1
front/project/www/components/Date/index.js

@@ -29,14 +29,16 @@ export default class extends Component {
   }
 
   render() {
-    const { hideInput, disabledDate, theme = '' } = this.props;
+    const { hideInput, disabledDate, theme = '', value, onChange } = this.props;
     return (
       <div className={`g-date-block ${hideInput ? 'hide-input' : ''}`}>
         <DatePicker
           open
+          value={value}
           dropdownClassName={`g-date ${theme} ${hideInput ? 'hide-input' : ''}`}
           disabledDate={disabledDate}
           dateRender={date => this.dateRender(date)}
+          onChange={date => onChange(date)}
         />
       </div>
     );

+ 1 - 0
front/project/www/components/Date/index.less

@@ -27,6 +27,7 @@
     }
 
     .ant-calendar-body {
+      cursor: pointer;
       table {
         th {
           height: 64px;

+ 79 - 46
front/project/www/components/Examination/index.js

@@ -1,7 +1,8 @@
 import React, { Component } from 'react';
 import './index.less';
 import { Icon } from 'antd';
-import { getMap, formatDate } from '@src/services/Tools';
+import { getMap, formatDate, formatPercent } from '@src/services/Tools';
+import moment from 'moment';
 import { SpecialRadioGroup } from '../Radio';
 import Modal from '../Modal';
 import Button from '../Button';
@@ -9,14 +10,21 @@ import TotalSort from '../TotalSort';
 import Date from '../Date';
 import Ratio from '../Ratio';
 import { My } from '../../stores/my';
-import { PrepareStatus, PrepareExaminationTime } from '../../../Constant';
+import { PrepareStatus, PrepareExaminationTime, PrepareScoreTime } from '../../../Constant';
 
 const PrepareStatusMap = getMap(PrepareStatus, 'value', 'short');
 const PrepareExaminationTimeMap = getMap(PrepareExaminationTime, 'value', 'label');
+const PrepareScoreTimeMap = getMap(PrepareScoreTime, 'value', 'label');
 
 export default class extends Component {
   constructor(props) {
     super(props);
+
+    this.statusColors = ['#41A6F3', '#3F86EA', '#41A6F3', '#6DC0FF', '#9BD4FF'];
+    this.examinationTimeColors = ['#6865FD', '#322EF2', '#8F65FF', '#8C8AFF'];
+    this.goalColors = ['#2754E0', '#3F86EA', '#41A6F3', '#6DC0FF'];
+    this.scoreTimeColors = ['#6865FD', '#322EF2', '#8F65FF', '#8C8AFF', '#8F65FF', '#C3C1D1'];
+
     this.stepProp = {
       0: {
         title: '我的身份',
@@ -33,21 +41,63 @@ export default class extends Component {
       4: {
         title: '备考信息',
         onConfirm: props.onConfirm,
-        onCancel: props.onCancel,
+        onCancel: () => {
+          this.setState({ step: 0 });
+        },
         confirmText: '关闭',
         cancelText: '修改',
       },
     };
-    this.state = { step: 0, data: {} };
+    this.state = { step: 0, data: { prepareGoal: 650 } };
     My.getPrepare().then(result => {
-      this.setState({ data: result, first: !result.prepareStatus });
+      const statusTotal = result.stat.status.reduce((p, n) => {
+        return p + n.value;
+      }, 0);
+      const goalTotal = result.stat.goal.reduce((p, n) => {
+        return p + n.value;
+      }, 0);
+      const examinationTimeTotal = result.stat.examinationTime.reduce((p, n) => {
+        return p + n.value;
+      }, 0);
+      const scoreTimeTotal = result.stat.scoreTime.reduce((p, n) => {
+        return p + n.value;
+      }, 0);
+      const stat = {
+        status: result.stat.status.map((row, index) => {
+          row.value = formatPercent(row.value, statusTotal);
+          row.label = `${PrepareStatusMap[row.key]}; ${row.value}%`;
+          row.color = this.statusColors[index];
+          return row;
+        }),
+        goal: result.stat.goal.map((row, index) => {
+          row.value = formatPercent(row.value, goalTotal);
+          row.label = `${row.key}+; ${row.value}%`;
+          row.color = this.goalColors[index];
+          return row;
+        }),
+        examinationTime: result.stat.status.map((row, index) => {
+          row.value = formatPercent(row.value, examinationTimeTotal);
+          row.label = `${PrepareExaminationTimeMap[row.key]}; ${row.value}%`;
+          row.color = this.examinationTimeColors[index];
+          return row;
+        }),
+        scoreTime: result.stat.scoreTime.map((row, index) => {
+          row.value = formatPercent(row.value, scoreTimeTotal);
+          row.label = `${PrepareScoreTimeMap[row.key]}; ${row.value}%`;
+          row.color = this.scoreTimeColors[index];
+          return row;
+        }),
+      };
+      result.prepareGoal = result.prepareGoal || 650;
+      result.prepareScoreTime = result.prepareScoreTime ? moment(result.prepareScoreTime) : null;
+      this.setState({ data: result, stat, first: !result.prepareStatus, step: !result.prepareStatus ? 0 : 4 });
     });
   }
 
   onChange(type, key) {
-    const { data, step } = this.state;
+    const { data } = this.state;
     data[type] = key;
-    this.setState({ data, step: step + 1 });
+    this.setState({ data });
   }
 
   onPrev() {
@@ -133,9 +183,16 @@ export default class extends Component {
   }
 
   renderStep2() {
+    const { data } = this.state;
+    const { prepareGoal } = data;
     return (
       <div className="step-2-layout">
-        <TotalSort />
+        <TotalSort
+          value={prepareGoal}
+          onChange={goal => {
+            this.onChange('prepareGoal', goal);
+          }}
+        />
         <div className="action-layout">
           <div className="prev" onClick={() => this.onPrev()}>
             <Icon type="left-circle" theme="filled" />
@@ -151,9 +208,17 @@ export default class extends Component {
   }
 
   renderStep3() {
+    const { data } = this.state;
+    const { prepareScoreTime } = data;
     return (
       <div className="step-3-layout">
-        <Date theme="filled" />
+        <Date
+          theme="filled"
+          value={prepareScoreTime}
+          onChange={date => {
+            this.onChange('prepareScoreTime', date);
+          }}
+        />
         <div className="action-layout">
           <div className="prev" onClick={() => this.onPrev()}>
             <Icon type="left-circle" theme="filled" />
@@ -174,7 +239,7 @@ export default class extends Component {
   }
 
   renderStep4() {
-    const { first, data } = this.state;
+    const { first, data, stat = {} } = this.state;
     return (
       <div className="step-4-layout">
         {first && (
@@ -183,49 +248,17 @@ export default class extends Component {
             7天VIP权限已赠送至您的账户。
           </div>
         )}
-        <Ratio
-          text="身份"
-          subtext={PrepareStatusMap[data.prepareStatus]}
-          values={[
-            { label: '学生-D; 20%', value: 10, color: '#41A6F3' },
-            { label: '学生-O; 20%', value: 20, color: '#3F86EA' },
-            { label: '在职-D; 20%', value: 20, color: '#41A6F3' },
-            { label: '在职-O; 20%', value: 20, color: '#6DC0FF' },
-            { label: 'Gap Year; 20%', value: 20, color: '#9BD4FF' },
-          ]}
-        />
+        <Ratio text="身份" subtext={PrepareStatusMap[data.prepareStatus]} values={stat.status || []} />
         <Ratio
           text="考试时间"
           subtext={PrepareExaminationTimeMap[data.prepareExaminationTime]}
-          values={[
-            { label: '近1个月; 20%', value: 10, color: '#6865FD' },
-            { label: '近2个月; 20%', value: 20, color: '#322EF2' },
-            { label: '近3个月; 20%', value: 20, color: '#8F65FF' },
-            { label: '半年内; 20%', value: 20, color: '#8C8AFF' },
-          ]}
-        />
-        <Ratio
-          text="目标成绩"
-          subtext={`${data.prepareGoal}分`}
-          values={[
-            { label: '600+; 20%', value: 10, color: '#2754E0' },
-            { label: '650+; 20%', value: 20, color: '#3F86EA' },
-            { label: '700+; 20%', value: 20, color: '#41A6F3' },
-            { label: '700+; 20%', value: 20, color: '#6DC0FF' },
-          ]}
+          values={stat.examinationTime || []}
         />
+        <Ratio text="目标成绩" subtext={`${data.prepareGoal}分`} values={stat.goal || []} />
         <Ratio
           text="出分日期"
           subtext={`${formatDate(data.prepareScoreTime, 'YYYY-MM')}`}
-          values={[
-            { label: '近1个月; 20%', value: 10, color: '#6865FD' },
-            { label: '近2个月; 20%', value: 20, color: '#322EF2' },
-            { label: '近3个月; 20%', value: 20, color: '#8F65FF' },
-            { label: '半年内; 20%', value: 20, color: '#8C8AFF' },
-            { label: '半年内; 20%', value: 20, color: '#8C8AFF' },
-            { label: '1年内; 20%', value: 20, color: '#8F65FF' },
-            { label: '不清楚', value: 20, color: '#C3C1D1' },
-          ]}
+          values={stat.scoreTime || []}
         />
       </div>
     );

+ 49 - 14
front/project/www/components/TotalSort/index.js

@@ -1,45 +1,80 @@
 import React, { Component } from 'react';
 import './index.less';
 import { Icon } from 'antd';
+import { Main } from '../../stores/main';
 
 export default class extends Component {
   constructor(props) {
     super(props);
-    this.state = {};
+    this.state = { quant: 50 };
+    this.time = 0;
+    this.compute(props.value, 50);
+  }
+
+  componentWillReceiveProps(nextProps) {
+    if (this.props.value !== nextProps.value) {
+      this.compute(nextProps.value, this.state.quant || 50);
+    }
+  }
+
+  compute(value, quant) {
+    if (value === this.props.value && quant === this.state.quant) return;
+    console.log(quant);
+    this.time += 1;
+    const number = this.time;
+    this.setState({ quant });
+    Main.getScore(value, quant)
+      .then(result => {
+        if (number !== this.time) return;
+        this.setState({ data: result });
+      })
+      .catch(() => {
+
+      });
   }
 
   render() {
+    const { value, onChange } = this.props;
+    const { data = {} } = this.state;
     return (
       <div className="total-sort">
         <div className="total-sort-num">
-          <Icon className="plus" type="plus" />
-          <input />
-          <Icon className="minus" type="minus" />
+          <Icon className="minus" type="minus" onClick={() => {
+            onChange(Math.max(value - 10, 200));
+          }} />
+          <input value={value} />
+          <Icon className="plus" type="plus" onClick={() => {
+            onChange(Math.min(value + 10, 800));
+          }} />
         </div>
         <div className="total-sort-desc">
-          预计全球排名<b>94th</b>
+          预计全球排名<b>{data.totalRank || 0}th</b>
         </div>
         <div className="total-sort-list">
           <div className="item">
             <div className="sort-num">
               <div className="sort-text">Quant :</div>
-              <input />
-              <Icon className="up" type="caret-up" />
-              <Icon className="down" type="caret-down" />
+              <input value={this.state.quant} />
+              <Icon className="up" type="caret-up" onClick={() => {
+                this.compute(value, Math.min(this.state.quant + 1, 51));
+              }} />
+              <Icon className="down" type="caret-down" onClick={() => {
+                this.compute(value, Math.max(this.state.quant - 1, 6));
+              }} />
             </div>
             <div className="t2">
-              排名<b>94th</b>
+              排名<b>{data.quantRank || 0}th</b>
             </div>
           </div>
           <div className="item">
             <div className="sort-num">
-              <div className="sort-text">Quant :</div>
-              <input />
-              <Icon className="up" type="caret-up" />
-              <Icon className="down" type="caret-down" />
+              <div className="sort-text">Verbal :</div>
+              <input value={data.verbalScore} />
+              {/* <Icon className="up" type="caret-up" />
+              <Icon className="down" type="caret-down" /> */}
             </div>
             <div className="t2">
-              排名<b>94th</b>
+              排名<b>{data.verbalRank || 0}th</b>
             </div>
           </div>
         </div>

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

@@ -4,7 +4,7 @@ import './index.less';
 import { Tooltip, Icon, Calendar } from 'antd';
 import Page from '@src/containers/Page';
 import Assets from '@src/components/Assets';
-import { formatPercent, formatDate, formatSeconds } from '@src/services/Tools';
+import { formatPercent, formatDate, formatSeconds, getMap } from '@src/services/Tools';
 import { asyncSMessage } from '@src/services/AsyncTools';
 import moment from 'moment';
 import UserLayout from '../../../layouts/User';
@@ -18,6 +18,9 @@ import { BindPhone, BindEmail, EditInfo, RealAuth, EditAvatar, InviteModal } fro
 import VipRenew from '../../../components/VipRenew';
 import { My } from '../../../stores/my';
 import { Main } from '../../../stores/main';
+import { QuestionType } from '../../../../Constant';
+
+const QuestionTypeMap = getMap(QuestionType, 'value', 'label');
 
 class LogItem extends Component {
   constructor(props) {
@@ -130,6 +133,11 @@ class LogItem extends Component {
 }
 
 export default class extends Page {
+  constructor(props) {
+    super(props);
+    this.colors = ['#3C39CC', '#9E9CFF', '#4292F0', '#4374EC', '#6865FD', '#8D65FD', '#6BABF6', '#7BBEFF', '#6BABF6'];
+  }
+
   initState() {
     return {
       day: 'today',
@@ -191,7 +199,13 @@ export default class extends Page {
 
   initData() {
     // 获取学习数据
-    My.getStudyTotal().then(total => {
+    My.getStudyTotal().then((total, index) => {
+      total.categorys = total.categorys.map(row => {
+        row.ratio = row.time * 100 / total.time;
+        row.time = formatSeconds(row.time);
+        row.color = this.colors[index];
+        return row;
+      });
       this.setState({ total });
     });
     My.getStudyWeek(0).then(latest => {
@@ -291,6 +305,40 @@ export default class extends Page {
           },
         ],
       });
+
+      study.push({
+        type: 'examination',
+        total: [
+          { title: '<span>模考和订正</span>', width: 130 },
+          { title: result.examinationTime ? formatSeconds(result.examinationTime).replace(/([0-9]+)(m|min|h|hour|s)/g, '<b>$1</b>$2') : '<b>-</b>', width: 90 },
+          { title: `<b>${result.examinationPaper || '-'}</b>套卷`, width: 80 },
+          { title: `超过了<b>${result.examinationExceed ? formatPercent(result.examinationExceed.rank, result.examinationExceed.total) : '-%'}</b>的用户` },
+        ],
+        detail: result.examinationList.map(row => {
+          return {
+            title: row.title,
+            time: formatDate(row.report.createTime, 'YYYY-MM-DD HH:mm:ss'),
+            score: row.report.score,
+          };
+        }),
+      });
+
+      study.push({
+        type: 'course',
+        total: [
+          { title: '<span>课程学习</span>', width: 130 },
+          { title: result.courseTime ? formatSeconds(result.courseTime).replace(/([0-9]+)(m|min|h|hour|s)/g, '<b>$1</b>$2') : '<b>-</b>', width: 90 },
+          { title: `<b>${result.courseNumber || '-'}</b>课时`, width: 80 },
+          { title: `超过了<b>${result.courseExceed ? formatPercent(result.courseExceed.rank, result.courseExceed.total) : '-%'}</b>的用户` },
+        ],
+        detail: result.courseList.map(row => {
+          return {
+            type: QuestionTypeMap[row.extend],
+            title: `课时${row.no}: ${row.title}`,
+            time: formatDate(row.createTime, 'YYYY-MM-DD HH:mm:ss'),
+          };
+        }),
+      });
       this.setState({ study });
     });
     this.setState({ day: value, time, showCal: false });
@@ -394,7 +442,7 @@ export default class extends Page {
   }
 
   renderTime() {
-    const { timeList = [], total = {} } = this.state;
+    const { total = {} } = this.state;
     return (
       <div className="time-layout">
         <div className="header">
@@ -416,7 +464,7 @@ export default class extends Page {
         </div>
         <div className="body">
           <div className="line">
-            {timeList.map(item => {
+            {(total.categorys || []).map(item => {
               return (
                 <Tooltip overlayClassName="gray" title={`${item.title} ${item.time}`}>
                   <i style={{ background: item.color, width: `${item.ratio}%` }} />
@@ -425,7 +473,7 @@ export default class extends Page {
             })}
           </div>
           <div className="list">
-            {timeList.map(item => {
+            {(total.categorys || []).map(item => {
               return (
                 <div className="item">
                   <div className="color" style={{ background: item.color }} />

+ 5 - 5
server/data/src/main/java/com/qxgmat/data/constants/enums/QuestionType.java

@@ -9,13 +9,13 @@ import java.util.List;
  * Created by gaojie on 2017/11/19.
  */
 public enum QuestionType {
-    SC("sc", "语法"),
-    RC("rc", "阅读"),
-    CR("cr","逻辑"),
+    SC("sc", "语法SC"),
+    RC("rc", "阅读RC"),
+    CR("cr","逻辑CR"),
     PS("ps", "数学PS"),
     DS("ds", "数学DS"),
-    IR("ir", "综合推理"),
-    AWA("awa", "作文"),
+    IR("ir", "综合推理IR"),
+    AWA("awa", "作文AWA"),
 
     SENTENCE("sentence", "长难句"), // 特殊类型
     ;

+ 2 - 1
server/data/src/main/java/com/qxgmat/data/constants/enums/user/PrepareExaminationTime.java

@@ -5,7 +5,8 @@ public enum PrepareExaminationTime {
     TWO_MONTH("two_month"),
     THREE_MONTH("three_month"),
     SIX_MONTH("six_month"),
-    ONE_YEAR("one_year")
+    ONE_YEAR("one_year"),
+    OTHER("other"),
     ;
 
     public String key;

+ 7 - 1
server/data/src/main/java/com/qxgmat/data/relation/UserReportRelationMapper.java

@@ -40,7 +40,7 @@ public interface UserReportRelationMapper {
             @Param("originId") Integer originId
     );
 
-    List<UserStudyStatRelation> statGroupModule(
+    List<UserStudyStatRelation> statGroupOrigin(
             @Param("userId") Integer userId
     );
 
@@ -50,6 +50,12 @@ public interface UserReportRelationMapper {
             @Param("endTime") String endTime
     );
 
+    List<UserStudyStatRelation> statGroupPreviewType(
+            @Param("userId") Integer userId,
+            @Param("startTime") String startTime,
+            @Param("endTime") String endTime
+    );
+
     List<UserRankStatRelation> rankExerciseByTime(
         @Param("userId") Integer userId,
         @Param("startTime") String startTime,

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

@@ -140,7 +140,7 @@
   <!--
     用户不同来源记录统计
   -->
-  <select id="statGroupModule" resultMap="studyMap">
+  <select id="statGroupOrigin" resultMap="studyMap">
     select
     sum(`user_number`) as `user_number`, sum(`user_time`) as `user_time`, sum(`user_correct`) as `user_correct`, `paper_origin` as `module`
     from `user_report`
@@ -171,6 +171,28 @@
   </select>
 
   <!--
+    用户预习作业模块记录统计,分题型
+  -->
+  <select id="statGroupPreviewType" resultMap="studyMap">
+    select
+    sum(ur.`user_number`) as `user_number`, sum(ur.`user_time`) as `user_time`, sum(ur.`user_correct`) as `user_correct`, pp.`question_type` as `module`
+    from `user_report` ur
+    left join `preview_assign` pa on pa.`id` = ur.`origin_id`
+    left join `preview_paper` pp on pp.`id` = pa.`paper_id`
+    where
+    ur.`user_id` = #{userId,jdbcType=VARCHAR}
+    and ur.`paper_origin` = 'preview'
+    and pp.`id` &gt; 0
+    <if test="startTime != null">
+      and ur.`update_time` &gt; #{startTime,jdbcType=VARCHAR}
+    </if>
+    <if test="endTime != null">
+      and ur.`update_time` &lt; #{endTime,jdbcType=VARCHAR}
+    </if>
+    group by pp.`question_type`
+  </select>
+
+  <!--
     用户练习记录排名
   -->
   <select id="rankExerciseByTime" resultMap="studyMap">

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

@@ -136,6 +136,9 @@ public class BaseController {
             @RequestParam(required = true) Number quant
     )  {
         Rank rank = rankService.compute(total, quant);
+        if (rank == null){
+            throw new ParameterException("排名信息为空");
+        }
         return ResponseHelp.success(rank);
     }
 

+ 18 - 17
server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java

@@ -512,16 +512,17 @@ public class MyController {
         Collection courseIds = Transform.getIds(userCourseRecordList, UserCourseRecord.class, "courseId");
         Collection courseNoIds = Transform.getIds(userCourseRecordList, UserCourseRecord.class, "noId");
         List<Course> courseList = courseService.select(courseIds);
-        Map courseMap = Transform.getMap(courseList, Course.class, "id", "title");
+        Map courseMap = Transform.getMap(courseList, Course.class, "id");
         List<CourseNo> courseNoList = courseNoService.select(courseNoIds);
-        Map classCourseNoMap = Transform.getMap(courseNoList, CourseNo.class, "id", "content");
+        Map courseNoMap = Transform.getMap(courseNoList, CourseNo.class, "id");
         List<UserCourseResultExtendDto> courseResultList = new ArrayList<>(userCourseRecordList.size());
         for(UserCourseRecord record:userCourseRecordList){
             courseTime += record.getUserTime();
             courseNumber += 1;
             UserCourseResultExtendDto d = Transform.convert(record, UserCourseResultExtendDto.class);
-            d.setTitle((String)courseMap.get(record.getCourseId()));
-            d.setContent((String)classCourseNoMap.get(record.getCourseNoId()));
+            d.setExtend(((Course)courseMap.get(record.getCourseId())).getExtend());
+            d.setTitle(((CourseNo)courseNoMap.get(record.getCourseNoId())).getTitle());
+            d.setNo(((CourseNo)courseNoMap.get(record.getCourseNoId())).getNo());
             courseResultList.add(d);
         }
         // todo 听课统计排行
@@ -530,7 +531,8 @@ public class MyController {
             courseRank.setTotal(total);
 
         dto.setCourseTime(courseTime);
-        dto.setCourseNumber(courseNumber);
+        // 课时数量:不按学完的课时计算
+        dto.setCourseNumber(courseNoIds.size());
         dto.setCourseList(courseResultList);
         dto.setCourseExceed(courseRank);
 
@@ -545,7 +547,7 @@ public class MyController {
         User user = (User) shiroHelp.getLoginUser();
         UserStudyDetailDto dto = new UserStudyDetailDto();
         dto.setCreateTime(user.getCreateTime());
-        dto.setDays((int)((user.getCreateTime().getTime() - new Date().getTime()) / (1000*3600*24)));
+        dto.setDays((int)((new Date().getTime() - user.getCreateTime().getTime()) / (1000*3600*24)));
 
         Date now = Tools.today();
         int day = Tools.getDayOfWeek(now);
@@ -573,26 +575,24 @@ public class MyController {
         User user = (User) shiroHelp.getLoginUser();
         UserStudyDetailDto dto = new UserStudyDetailDto();
         dto.setCreateTime(user.getCreateTime());
-        dto.setDays((int)((user.getCreateTime().getTime() - new Date().getTime()) / (1000*3600*24)));
+        dto.setDays((int)((new Date().getTime() - user.getCreateTime().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){
+        List<UserStudyStatRelation> originList = userReportService.statGroupOrigin(user.getId());
+        for(UserStudyStatRelation relation:originList){
             // 练习时间过滤
-            if (module.getModule().equals(PaperModule.EXERCISE.key)){
+            if (relation.getModule().equals(PaperOrigin.EXERCISE.key) || relation.getModule().equals(PaperOrigin.PREVIEW.key)){
                 continue;
             }
-            Integer time = module.getUserTime();
-            String key = module.getModule();
+            Integer time = relation.getUserTime();
+            String key = relation.getModule();
             totalTime += time;
             // 收藏及错误组卷合并
-            if (module.getModule().equals(PaperOrigin.COLLECT.key)
-                    || module.getModule().equals(PaperOrigin.ERROR.key)){
+            if (relation.getModule().equals(PaperOrigin.COLLECT.key)
+                    || relation.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);
         }
@@ -603,7 +603,7 @@ public class MyController {
             categoryMap.put(type.getModule(), type.getUserTime());
         }
         // 按题型统计预习作业
-        List<UserStudyStatRelation> previewList = userReportService.statGroupExerciseType(user.getId(), null, null);
+        List<UserStudyStatRelation> previewList = userReportService.statGroupPreviewType(user.getId(), null, null);
         for(UserStudyStatRelation type:previewList){
             totalTime += type.getUserTime();
             categoryMap.put(type.getModule(), type.getUserTime());
@@ -620,6 +620,7 @@ public class MyController {
         UserRecordStatRelation sentenceStatRelation = userSentenceRecordService.stat(user.getId(), null, null);
         if (sentenceStatRelation != null){
             Integer sentenceTime = categoryMap.getOrDefault(PaperModule.SENTENCE.key, 0);
+            totalTime += sentenceTime;
             categoryMap.put(PaperModule.SENTENCE.key, sentenceTime + sentenceStatRelation.getUserTime());
         }
 

+ 19 - 9
server/gateway-api/src/main/java/com/qxgmat/dto/extend/UserCourseResultExtendDto.java

@@ -8,9 +8,11 @@ import java.util.Date;
 
 @Dto(entity = UserCourseRecord.class)
 public class UserCourseResultExtendDto {
+    private String extend;
+
     private String title;
 
-    private String content;
+    private Integer no;
 
     private Integer userTime;
 
@@ -24,14 +26,6 @@ public class UserCourseResultExtendDto {
         this.title = title;
     }
 
-    public String getContent() {
-        return content;
-    }
-
-    public void setContent(String content) {
-        this.content = content;
-    }
-
     public Date getCreateTime() {
         return createTime;
     }
@@ -47,4 +41,20 @@ public class UserCourseResultExtendDto {
     public void setUserTime(Integer userTime) {
         this.userTime = userTime;
     }
+
+    public Integer getNo() {
+        return no;
+    }
+
+    public void setNo(Integer no) {
+        this.no = no;
+    }
+
+    public String getExtend() {
+        return extend;
+    }
+
+    public void setExtend(String extend) {
+        this.extend = extend;
+    }
 }

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

@@ -350,7 +350,7 @@ public class UsersService extends AbstractService {
             if (goal > 0){
                 // 按层级归类
                 UserPrepareRelation real = userPrepareRelationList.get(goal);
-                real.setNumber(real.getNumber()+real.getNumber());
+                real.setNumber(real.getNumber()+relation.getNumber());
             }
         }
 
@@ -412,7 +412,7 @@ public class UsersService extends AbstractService {
         UserPrepareRelation threeMonth = new UserPrepareRelation();
         threeMonth.setS(PrepareExaminationTime.THREE_MONTH.key);
         threeMonth.setNumber(count(userMapper, example) - twoMonth.getNumber());
-        userPrepareRelationList.add(twoMonth);
+        userPrepareRelationList.add(threeMonth);
 
         // 半年
         calendar.setTime(new Date());
@@ -449,7 +449,7 @@ public class UsersService extends AbstractService {
                         .andIsNull("prepareScoreTime")
         );
         UserPrepareRelation other = new UserPrepareRelation();
-        other.setS(PrepareExaminationTime.ONE_YEAR.key);
+        other.setS(PrepareExaminationTime.OTHER.key);
         other.setNumber(count(userMapper, example));
         userPrepareRelationList.add(other);
 

+ 11 - 2
server/gateway-api/src/main/java/com/qxgmat/service/inline/UserReportService.java

@@ -143,8 +143,8 @@ public class UserReportService extends AbstractService {
      * @param userId
      * @return
      */
-    public List<UserStudyStatRelation> statGroupModule(Integer userId){
-       return userReportRelationMapper.statGroupModule(userId);
+    public List<UserStudyStatRelation> statGroupOrigin(Integer userId){
+       return userReportRelationMapper.statGroupOrigin(userId);
     }
 
     /**
@@ -157,6 +157,15 @@ public class UserReportService extends AbstractService {
     }
 
     /**
+     * 按report统计预习作业不同题型用户的做题记录
+     * @param userId
+     * @return
+     */
+    public List<UserStudyStatRelation> statGroupPreviewType(Integer userId, String startTime, String endTime){
+        return userReportRelationMapper.statGroupPreviewType(userId, startTime, endTime);
+    }
+
+    /**
      * 计算用户在指定时间内的练习排行
      * @param userId
      * @param startTime