Procházet zdrojové kódy

feat(front): 个人中心-课程

Go před 5 roky
rodič
revize
a4676d338c
34 změnil soubory, kde provedl 1320 přidání a 217 odebrání
  1. 11 2
      front/project/admin/routes/course/detail/page.js
  2. 10 1
      front/project/admin/routes/course/vsDetail/page.js
  3. 10 18
      front/project/www/components/OtherModal/index.js
  4. 6 3
      front/project/www/components/VipRenew/index.js
  5. 564 130
      front/project/www/routes/my/course/page.js
  6. 12 0
      front/project/www/stores/my.js
  7. 19 19
      server/data/src/main/java/com/qxgmat/data/dao/entity/Course.java
  8. 140 0
      server/data/src/main/java/com/qxgmat/data/dao/entity/User.java
  9. 35 0
      server/data/src/main/java/com/qxgmat/data/dao/entity/UserOrderRecord.java
  10. 2 2
      server/data/src/main/java/com/qxgmat/data/dao/mapping/CourseMapper.xml
  11. 7 1
      server/data/src/main/java/com/qxgmat/data/dao/mapping/UserMapper.xml
  12. 2 1
      server/data/src/main/java/com/qxgmat/data/dao/mapping/UserOrderRecordMapper.xml
  13. 2 1
      server/data/src/main/java/com/qxgmat/data/relation/UserOrderRecordRelationMapper.java
  14. 8 2
      server/data/src/main/java/com/qxgmat/data/relation/mapping/UserOrderRecordRelationMapper.xml
  15. 6 1
      server/data/src/main/resources/db/migration/V1__init_table.sql
  16. 89 2
      server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java
  17. 69 0
      server/gateway-api/src/main/java/com/qxgmat/dto/extend/BasePaperExtendDto.java
  18. 10 0
      server/gateway-api/src/main/java/com/qxgmat/dto/extend/CourseExtendDto.java
  19. 10 0
      server/gateway-api/src/main/java/com/qxgmat/dto/extend/CourseNoExtendDto.java
  20. 48 0
      server/gateway-api/src/main/java/com/qxgmat/dto/extend/UserAskCourseExtendDto.java
  21. 49 0
      server/gateway-api/src/main/java/com/qxgmat/dto/extend/UserNoteCourseExtendDto.java
  22. 13 0
      server/gateway-api/src/main/java/com/qxgmat/dto/request/RecordCommentTipsDto.java
  23. 10 0
      server/gateway-api/src/main/java/com/qxgmat/dto/response/MyDto.java
  24. 43 3
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserCourseDetailDto.java
  25. 27 12
      server/gateway-api/src/main/java/com/qxgmat/service/UserNoteCourseService.java
  26. 31 8
      server/gateway-api/src/main/java/com/qxgmat/service/extend/CourseExtendService.java
  27. 2 1
      server/gateway-api/src/main/java/com/qxgmat/service/extend/PreviewService.java
  28. 1 1
      server/gateway-api/src/main/java/com/qxgmat/service/inline/CourseNoService.java
  29. 1 0
      server/gateway-api/src/main/java/com/qxgmat/service/inline/PreviewAssignService.java
  30. 27 4
      server/gateway-api/src/main/java/com/qxgmat/service/inline/UserAskCourseService.java
  31. 2 1
      server/gateway-api/src/main/java/com/qxgmat/service/inline/UserCourseAppointmentService.java
  32. 13 1
      server/gateway-api/src/main/java/com/qxgmat/service/inline/UserOrderRecordService.java
  33. 1 1
      server/gateway-api/src/main/java/com/qxgmat/task/ScheduledTask.java
  34. 40 2
      server/tools/src/main/java/com/nuliji/tools/Transform.java

+ 11 - 2
front/project/admin/routes/course/detail/page.js

@@ -167,7 +167,7 @@ export default class extends Page {
     if (id) {
       handler = Course.get({ id });
     } else {
-      handler = Promise.resolve({ structId: 0, courseModule: module });
+      handler = Promise.resolve({ structId: 0, courseModule: module, expireDays: 180 });
     }
 
     handler
@@ -311,7 +311,7 @@ export default class extends Page {
             <Input placeholder='请输入课程名称' />,
           )}
         </Form.Item>
-        <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='有效期'>
+        <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='开通有效期'>
           {getFieldDecorator('expireDays', {
             rules: [
               { required: true, message: '请输入有效期' },
@@ -320,6 +320,15 @@ export default class extends Page {
             <InputNumber placeholder='天' />,
           )}
         </Form.Item>
+        <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='使用有效期'>
+          {getFieldDecorator('useExpireDays', {
+            rules: [
+              { required: true, message: '请输入有效期' },
+            ],
+          })(
+            <InputNumber placeholder='天' />,
+          )}
+        </Form.Item>
         <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='教师'>
           {getFieldDecorator('teacher', {
             rules: [

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

@@ -37,7 +37,7 @@ export default class extends Page {
           });
         } else {
           form.resetFields();
-          this.setState({ data: {}, loading: false, teacher: false });
+          this.setState({ data: { expireDays: 7 }, loading: false, teacher: false });
         }
       });
   }
@@ -146,6 +146,15 @@ export default class extends Page {
             <InputNumber placeholder='天/10课时' />,
           )}
         </Form.Item>
+        <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='开通有效期'>
+          {getFieldDecorator('expireDays', {
+            rules: [
+              { required: true, message: '请输入有效期' },
+            ],
+          })(
+            <InputNumber placeholder='天' />,
+          )}
+        </Form.Item>
       </Form>
     </Block>;
   }

+ 10 - 18
front/project/www/components/OtherModal/index.js

@@ -18,7 +18,7 @@ export class BindPhone extends Component {
   constructor(props) {
     super(props);
     this.props.data = this.props.data || {};
-    this.state = this.initState(this.props);
+    this.state = Object.assign({ step: 0, data: {} }, this.initState(this.props));
     this.stepProp = {
       0: {
         title: '绑定手机',
@@ -36,7 +36,7 @@ export class BindPhone extends Component {
   }
 
   initState(props) {
-    if (this.wait) return {};
+    if (!props.show || this.props.show) return {};
     const data = Object.assign({}, props.data);
     if (!data.area) data.area = MobileArea[0].value;
     return { step: props.data.mobile ? 0 : 1, data };
@@ -77,10 +77,8 @@ export class BindPhone extends Component {
     const { data, error } = this.state;
     const { area, mobile } = data;
     if (!area || !mobile || error) return Promise.reject();
-    this.wait = true;
     return Common.sendSms(area, mobile)
       .then(result => {
-        this.wait = false;
         if (result) {
           asyncSMessage('发送成功');
           this.setState({ error: '', validError: '' });
@@ -89,7 +87,6 @@ export class BindPhone extends Component {
         }
       })
       .catch(err => {
-        this.wait = false;
         this.setState({ error: err.message });
         throw err;
       });
@@ -97,27 +94,23 @@ export class BindPhone extends Component {
 
   submit() {
     const { data, error } = this.state;
-    console.log(data, error);
     if (!data.mobile || !data.area || error) return;
     const { area, mobile } = data;
-    this.wait = true;
     My.bindMobile(area, mobile)
       .then(() => {
         asyncSMessage('操作成功');
         this.setState({ step: 0 });
         User.infoHandle(Object.assign(this.props.data, { area, mobile }));
         this.props.onConfirm();
-        this.wait = false;
       })
       .catch(e => {
         this.setState({ error: e.message });
-        this.wait = false;
       });
   }
 
   render() {
     const { show } = this.props;
-    const { step } = this.state;
+    const { step = 0 } = this.state;
     return (
       <Modal className="bind-phone-modal" show={show} width={630} {...this.stepProp[step]}>
         <div className="bind-phone-modal-wrapper">{this[`renderStep${step}`]()}</div>
@@ -176,7 +169,7 @@ export class BindEmail extends Component {
   constructor(props) {
     super(props);
     this.props.data = this.props.data || {};
-    this.state = this.initState(this.props);
+    this.state = Object.assign({ step: 0, data: {} }, this.initState(this.props));
     this.stepProp = {
       0: {
         title: '绑定邮箱',
@@ -194,7 +187,7 @@ export class BindEmail extends Component {
   }
 
   initState(props) {
-    if (this.wait) return {};
+    if (!props.show || this.props.show) return {};
     return { step: props.data.email ? 0 : 1, data: Object.assign({}, props.data) };
   }
 
@@ -217,24 +210,21 @@ export class BindEmail extends Component {
     const { data, error } = this.state;
     if (!data.email || error) return;
     const { email } = data;
-    this.wait = true;
     My.bindEmail(email)
       .then(() => {
         asyncSMessage('操作成功');
         this.setState({ step: 0 });
         User.infoHandle(Object.assign(this.props.data, { email }));
         this.props.onConfirm();
-        this.wait = false;
       })
       .catch(e => {
         this.setState({ error: e.message });
-        this.wait = false;
       });
   }
 
   render() {
     const { show } = this.props;
-    const { step } = this.state;
+    const { step = 0 } = this.state;
     return (
       <Modal className="bind-email-modal" show={show} width={630} {...this.stepProp[step]}>
         <div className="bind-email-modal-wrapper">{this[`renderStep${step}`]()}</div>
@@ -275,7 +265,7 @@ export class EditInfo extends Component {
   constructor(props) {
     super(props);
     this.props.data = this.props.data || {};
-    this.state = this.initState(this.props);
+    this.state = Object.assign({ data: {} }, this.initState(this.props));
   }
 
   initState(props) {
@@ -292,6 +282,7 @@ export class EditInfo extends Component {
       this.waitImage = false;
       return state;
     }
+    if (!props.show || this.props.show) return {};
     return { data: Object.assign({}, props.data) };
   }
 
@@ -405,11 +396,12 @@ export class RealAuth extends Component {
 export class EditAvatar extends Component {
   constructor(props) {
     super(props);
-    this.state = this.initState(props);
+    this.state = Object.assign({ data: {} }, this.initState(this.props));
   }
 
   initState(props) {
     if (props.image) this.loadImage(props.image);
+    if (!props.show || this.props.show) return {};
     return { data: {} };
   }
 

+ 6 - 3
front/project/www/components/VipRenew/index.js

@@ -88,6 +88,7 @@ export default class extends Component {
 
   renderTab2() {
     const { data, onReal, onPrepare } = this.props;
+    const { showInvite } = this.state;
     return (
       <div className="tab-2-layout">
         <div className="list">
@@ -108,9 +109,11 @@ export default class extends Component {
             <Assets className="icon" name="invite" />
             <div className="t">
               <Assets name="gift" />
-              7天/每位好友
+              {data.inviteNumber > 0 ? `7天 X ${data.inviteNumber}位好友` : '7天/每位好友'}
             </div>
-            <Button size="small" radius>
+            <Button size="small" radius onClick={() => {
+              this.setState({ showInvite: true });
+            }}>
               邀请好友
             </Button>
           </div>
@@ -128,7 +131,7 @@ export default class extends Component {
             </Button>
           </div>
         </div>
-        <Invite data={data} />
+        {showInvite && <Invite data={data} />}
       </div>
     );
   }

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 564 - 130
front/project/www/routes/my/course/page.js


+ 12 - 0
front/project/www/stores/my.js

@@ -429,6 +429,18 @@ export default class MyStore extends BaseStore {
   timeCourse(recordId) {
     return this.apiGet('/my/course/time', { recordId });
   }
+
+  exportQuestionError() {
+    return this.apiPost('/my/export/question/error', {});
+  }
+
+  exportTips() {
+    return this.apiPost('/my/export/tips', {});
+  }
+
+  courseCommentTips(recordId) {
+    return this.apiPost('/my/course/comment/tips', { recordId });
+  }
 }
 
 export const My = new MyStore({ key: 'my' });

+ 19 - 19
server/data/src/main/java/com/qxgmat/data/dao/entity/Course.java

@@ -109,7 +109,7 @@ public class Course implements Serializable {
     private Integer expirePreDays;
 
     /**
-     * 视频课程开通有效时长
+     * 视频课程有效时长
      */
     @Column(name = "`expire_days`")
     private Integer expireDays;
@@ -123,8 +123,8 @@ public class Course implements Serializable {
     /**
      * 使用有效时长
      */
-    @Column(name = "`use_expire_time`")
-    private Integer useExpireTime;
+    @Column(name = "`use_expire_days`")
+    private Integer useExpireDays;
 
     /**
      * 微信头像
@@ -527,18 +527,18 @@ public class Course implements Serializable {
     }
 
     /**
-     * 获取视频课程开通有效时长
+     * 获取视频课程有效时长
      *
-     * @return expire_days - 视频课程开通有效时长
+     * @return expire_days - 视频课程有效时长
      */
     public Integer getExpireDays() {
         return expireDays;
     }
 
     /**
-     * 设置视频课程开通有效时长
+     * 设置视频课程有效时长
      *
-     * @param expireDays 视频课程开通有效时长
+     * @param expireDays 视频课程有效时长
      */
     public void setExpireDays(Integer expireDays) {
         this.expireDays = expireDays;
@@ -565,19 +565,19 @@ public class Course implements Serializable {
     /**
      * 获取使用有效时长
      *
-     * @return use_expire_time - 使用有效时长
+     * @return use_expire_days - 使用有效时长
      */
-    public Integer getUseExpireTime() {
-        return useExpireTime;
+    public Integer getUseExpireDays() {
+        return useExpireDays;
     }
 
     /**
      * 设置使用有效时长
      *
-     * @param useExpireTime 使用有效时长
+     * @param useExpireDays 使用有效时长
      */
-    public void setUseExpireTime(Integer useExpireTime) {
-        this.useExpireTime = useExpireTime;
+    public void setUseExpireDays(Integer useExpireDays) {
+        this.useExpireDays = useExpireDays;
     }
 
     /**
@@ -903,7 +903,7 @@ public class Course implements Serializable {
         sb.append(", expirePreDays=").append(expirePreDays);
         sb.append(", expireDays=").append(expireDays);
         sb.append(", askExtendDays=").append(askExtendDays);
-        sb.append(", useExpireTime=").append(useExpireTime);
+        sb.append(", useExpireDays=").append(useExpireDays);
         sb.append(", wechatAvatar=").append(wechatAvatar);
         sb.append(", trailNumber=").append(trailNumber);
         sb.append(", saleNumber=").append(saleNumber);
@@ -1125,9 +1125,9 @@ public class Course implements Serializable {
         }
 
         /**
-         * 设置视频课程开通有效时长
+         * 设置视频课程有效时长
          *
-         * @param expireDays 视频课程开通有效时长
+         * @param expireDays 视频课程有效时长
          */
         public Builder expireDays(Integer expireDays) {
             obj.setExpireDays(expireDays);
@@ -1147,10 +1147,10 @@ public class Course implements Serializable {
         /**
          * 设置使用有效时长
          *
-         * @param useExpireTime 使用有效时长
+         * @param useExpireDays 使用有效时长
          */
-        public Builder useExpireTime(Integer useExpireTime) {
-            obj.setUseExpireTime(useExpireTime);
+        public Builder useExpireDays(Integer useExpireDays) {
+            obj.setUseExpireDays(useExpireDays);
             return this;
         }
 

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

@@ -258,6 +258,30 @@ public class User implements Serializable {
     @Column(name = "`total_alert`")
     private Integer totalAlert;
 
+    /**
+     * 导出错题次数
+     */
+    @Column(name = "`export_question_error_number`")
+    private Integer exportQuestionErrorNumber;
+
+    /**
+     * 导出笔记次数
+     */
+    @Column(name = "`export_question_note_number`")
+    private Integer exportQuestionNoteNumber;
+
+    /**
+     * 导出课时笔记次数
+     */
+    @Column(name = "`export_course_note_number`")
+    private Integer exportCourseNoteNumber;
+
+    /**
+     * 导出提示:0展示,1关闭
+     */
+    @Column(name = "`export_tips`")
+    private Integer exportTips;
+
     private static final long serialVersionUID = 1L;
 
     /**
@@ -1022,6 +1046,78 @@ public class User implements Serializable {
         this.totalAlert = totalAlert;
     }
 
+    /**
+     * 获取导出错题次数
+     *
+     * @return export_question_error_number - 导出错题次数
+     */
+    public Integer getExportQuestionErrorNumber() {
+        return exportQuestionErrorNumber;
+    }
+
+    /**
+     * 设置导出错题次数
+     *
+     * @param exportQuestionErrorNumber 导出错题次数
+     */
+    public void setExportQuestionErrorNumber(Integer exportQuestionErrorNumber) {
+        this.exportQuestionErrorNumber = exportQuestionErrorNumber;
+    }
+
+    /**
+     * 获取导出笔记次数
+     *
+     * @return export_question_note_number - 导出笔记次数
+     */
+    public Integer getExportQuestionNoteNumber() {
+        return exportQuestionNoteNumber;
+    }
+
+    /**
+     * 设置导出笔记次数
+     *
+     * @param exportQuestionNoteNumber 导出笔记次数
+     */
+    public void setExportQuestionNoteNumber(Integer exportQuestionNoteNumber) {
+        this.exportQuestionNoteNumber = exportQuestionNoteNumber;
+    }
+
+    /**
+     * 获取导出课时笔记次数
+     *
+     * @return export_course_note_number - 导出课时笔记次数
+     */
+    public Integer getExportCourseNoteNumber() {
+        return exportCourseNoteNumber;
+    }
+
+    /**
+     * 设置导出课时笔记次数
+     *
+     * @param exportCourseNoteNumber 导出课时笔记次数
+     */
+    public void setExportCourseNoteNumber(Integer exportCourseNoteNumber) {
+        this.exportCourseNoteNumber = exportCourseNoteNumber;
+    }
+
+    /**
+     * 获取导出提示:0展示,1关闭
+     *
+     * @return export_tips - 导出提示:0展示,1关闭
+     */
+    public Integer getExportTips() {
+        return exportTips;
+    }
+
+    /**
+     * 设置导出提示:0展示,1关闭
+     *
+     * @param exportTips 导出提示:0展示,1关闭
+     */
+    public void setExportTips(Integer exportTips) {
+        this.exportTips = exportTips;
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -1071,6 +1167,10 @@ public class User implements Serializable {
         sb.append(", dataEmailSubscribe=").append(dataEmailSubscribe);
         sb.append(", textbookEmailSubscribe=").append(textbookEmailSubscribe);
         sb.append(", totalAlert=").append(totalAlert);
+        sb.append(", exportQuestionErrorNumber=").append(exportQuestionErrorNumber);
+        sb.append(", exportQuestionNoteNumber=").append(exportQuestionNoteNumber);
+        sb.append(", exportCourseNoteNumber=").append(exportCourseNoteNumber);
+        sb.append(", exportTips=").append(exportTips);
         sb.append("]");
         return sb.toString();
     }
@@ -1510,6 +1610,46 @@ public class User implements Serializable {
             return this;
         }
 
+        /**
+         * 设置导出错题次数
+         *
+         * @param exportQuestionErrorNumber 导出错题次数
+         */
+        public Builder exportQuestionErrorNumber(Integer exportQuestionErrorNumber) {
+            obj.setExportQuestionErrorNumber(exportQuestionErrorNumber);
+            return this;
+        }
+
+        /**
+         * 设置导出笔记次数
+         *
+         * @param exportQuestionNoteNumber 导出笔记次数
+         */
+        public Builder exportQuestionNoteNumber(Integer exportQuestionNoteNumber) {
+            obj.setExportQuestionNoteNumber(exportQuestionNoteNumber);
+            return this;
+        }
+
+        /**
+         * 设置导出课时笔记次数
+         *
+         * @param exportCourseNoteNumber 导出课时笔记次数
+         */
+        public Builder exportCourseNoteNumber(Integer exportCourseNoteNumber) {
+            obj.setExportCourseNoteNumber(exportCourseNoteNumber);
+            return this;
+        }
+
+        /**
+         * 设置导出提示:0展示,1关闭
+         *
+         * @param exportTips 导出提示:0展示,1关闭
+         */
+        public Builder exportTips(Integer exportTips) {
+            obj.setExportTips(exportTips);
+            return this;
+        }
+
         public User build() {
             return this.obj;
         }

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

@@ -183,6 +183,12 @@ public class UserOrderRecord implements Serializable {
     @Column(name = "`course_award`")
     private Integer courseAward;
 
+    /**
+     * 评价题型:0显示,1关闭
+     */
+    @Column(name = "`comment_tips`")
+    private Integer commentTips;
+
     private static final long serialVersionUID = 1L;
 
     /**
@@ -727,6 +733,24 @@ public class UserOrderRecord implements Serializable {
         this.courseAward = courseAward;
     }
 
+    /**
+     * 获取评价题型:0显示,1关闭
+     *
+     * @return comment_tips - 评价题型:0显示,1关闭
+     */
+    public Integer getCommentTips() {
+        return commentTips;
+    }
+
+    /**
+     * 设置评价题型:0显示,1关闭
+     *
+     * @param commentTips 评价题型:0显示,1关闭
+     */
+    public void setCommentTips(Integer commentTips) {
+        this.commentTips = commentTips;
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
@@ -764,6 +788,7 @@ public class UserOrderRecord implements Serializable {
         sb.append(", money=").append(money);
         sb.append(", originMoney=").append(originMoney);
         sb.append(", courseAward=").append(courseAward);
+        sb.append(", commentTips=").append(commentTips);
         sb.append("]");
         return sb.toString();
     }
@@ -1081,6 +1106,16 @@ public class UserOrderRecord implements Serializable {
             return this;
         }
 
+        /**
+         * 设置评价题型:0显示,1关闭
+         *
+         * @param commentTips 评价题型:0显示,1关闭
+         */
+        public Builder commentTips(Integer commentTips) {
+            obj.setCommentTips(commentTips);
+            return this;
+        }
+
         public UserOrderRecord build() {
             return this.obj;
         }

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

@@ -24,7 +24,7 @@
     <result column="expire_pre_days" jdbcType="INTEGER" property="expirePreDays" />
     <result column="expire_days" jdbcType="INTEGER" property="expireDays" />
     <result column="ask_extend_days" jdbcType="INTEGER" property="askExtendDays" />
-    <result column="use_expire_time" jdbcType="INTEGER" property="useExpireTime" />
+    <result column="use_expire_days" jdbcType="INTEGER" property="useExpireDays" />
     <result column="wechat_avatar" jdbcType="VARCHAR" property="wechatAvatar" />
     <result column="trail_number" jdbcType="INTEGER" property="trailNumber" />
     <result column="sale_number" jdbcType="INTEGER" property="saleNumber" />
@@ -54,7 +54,7 @@
     -->
     `id`, `struct_id`, `parent_struct_id`, `course_module`, `no_number`, `vs_type`, `video_type`, 
     `extend`, `title`, `comment`, `crowd`, `price`, `teacher`, `cover`, `min_number`, 
-    `max_number`, `expire_pre_days`, `expire_days`, `ask_extend_days`, `use_expire_time`, 
+    `max_number`, `expire_pre_days`, `expire_days`, `ask_extend_days`, `use_expire_days`, 
     `wechat_avatar`, `trail_number`, `sale_number`, `package_sale_number`, `create_time`, 
     `update_time`
   </sql>

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

@@ -48,6 +48,10 @@
     <result column="data_email_subscribe" jdbcType="INTEGER" property="dataEmailSubscribe" />
     <result column="textbook_email_subscribe" jdbcType="INTEGER" property="textbookEmailSubscribe" />
     <result column="total_alert" jdbcType="INTEGER" property="totalAlert" />
+    <result column="export_question_error_number" jdbcType="INTEGER" property="exportQuestionErrorNumber" />
+    <result column="export_question_note_number" jdbcType="INTEGER" property="exportQuestionNoteNumber" />
+    <result column="export_course_note_number" jdbcType="INTEGER" property="exportCourseNoteNumber" />
+    <result column="export_tips" jdbcType="INTEGER" property="exportTips" />
   </resultMap>
   <sql id="Base_Column_List">
     <!--
@@ -60,6 +64,8 @@
     `prepare_goal`, `prepare_examination_time`, `prepare_score_time`, `latest_exercise`, 
     `latest_error`, `latest_collect`, `origin_id`, `invite_code`, `total_money`, `invite_number`, 
     `textbook_half`, `qx_cat`, `register_ip`, `register_city`, `latest_login_ip`, `latest_login_time`, 
-    `is_frozen`, `create_time`, `data_email_subscribe`, `textbook_email_subscribe`, `total_alert`
+    `is_frozen`, `create_time`, `data_email_subscribe`, `textbook_email_subscribe`, `total_alert`, 
+    `export_question_error_number`, `export_question_note_number`, `export_course_note_number`, 
+    `export_tips`
   </sql>
 </mapper>

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

@@ -36,6 +36,7 @@
     <result column="money" jdbcType="DECIMAL" property="money" />
     <result column="origin_money" jdbcType="DECIMAL" property="originMoney" />
     <result column="course_award" jdbcType="INTEGER" property="courseAward" />
+    <result column="comment_tips" jdbcType="INTEGER" property="commentTips" />
   </resultMap>
   <sql id="Base_Column_List">
     <!--
@@ -45,6 +46,6 @@
     `param`, `source`, `teacher_id`, `number`, `vs_no`, `time_id`, `ask_time`, `cctalk_name`, 
     `is_subscribe`, `start_time`, `end_time`, `use_start_time`, `use_end_time`, `is_used`, 
     `use_time`, `is_stop`, `stop_time`, `is_suspend`, `suspend_time`, `restore_time`, 
-    `create_time`, `money`, `origin_money`, `course_award`
+    `create_time`, `money`, `origin_money`, `course_award`, `comment_tips`
   </sql>
 </mapper>

+ 2 - 1
server/data/src/main/java/com/qxgmat/data/relation/UserOrderRecordRelationMapper.java

@@ -34,7 +34,8 @@ public interface UserOrderRecordRelationMapper {
             @Param("userId") Integer userId,
             @Param("courseModules") String[] modules,
             @Param("isUsed") Boolean isUsed,
-            @Param("isEnd") Boolean isEnd,
+            @Param("ltUseEndTime") String ltUseEndTime,
+            @Param("gtUseEndTime") String gtUseEndTime,
             @Param("order") String order,
             @Param("direction") String direction
     );

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

@@ -101,11 +101,17 @@
     </if>
     where
     c.`id` &gt; 0
+    <if test="userId != null">
+      and uor.`user_id` = #{userId,jdbcType=VARCHAR}
+    </if>
     <if test="isUsed != null">
       and uor.`isUsed` = #{userId,jdbcType=INTEGER}
     </if>
-    <if test="useEndTime != null">
-      and uor.`useEndTime` &lt; #{useEndTime,jdbcType=INTEGER}
+    <if test="ltUseEndTime != null">
+      and uor.`useEndTime` &lt; #{ltUseEndTime,jdbcType=INTEGER}
+    </if>
+    <if test="gtUseEndTime != null">
+      and uor.`useEndTime` &gt; #{gtUseEndTime,jdbcType=INTEGER}
     </if>
     order by ${order} ${direction}
   </select>

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

@@ -934,6 +934,10 @@ CREATE TABLE user (
   data_email_subscribe tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '资料订阅',
   textbook_email_subscribe tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '机经邮箱订阅',
   total_alert int(11) unsigned NOT NULL DEFAULT '0' COMMENT '累计告警字数',
+  export_question_error_number int(11) unsigned NOT NULL DEFAULT '0' COMMENT '导出错题次数',
+  export_question_note_number int(11) unsigned NOT NULL DEFAULT '0' COMMENT '导出题目笔记次数',
+  export_tips tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '导出提示:0展示,1关闭',
+  export_course_note_number int(11) unsigned NOT NULL COMMENT '导出课时笔记次数',
   PRIMARY KEY (id),
   KEY mobile (mobile),
   KEY wechat_unionid (wechat_unionid),
@@ -1238,6 +1242,7 @@ CREATE TABLE user_order_record (
   money decimal(10,2) unsigned NOT NULL DEFAULT '0.00',
   origin_money decimal(10,2) unsigned NOT NULL DEFAULT '0.00',
   course_award int(10) unsigned NOT NULL DEFAULT '0' COMMENT '奖励天数',
+  comment_tips tinyint(10) unsigned NOT NULL DEFAULT '0' COMMENT '评价提醒:0显示,1关闭',
   PRIMARY KEY (id),
   KEY user_id (user_id,product_type),
   KEY order_id (order_id),
@@ -1273,7 +1278,7 @@ CREATE TABLE user_paper_question (
   user_id int(11) unsigned NOT NULL COMMENT '用户id',
   paper_id int(11) unsigned NOT NULL COMMENT '分组id',
   question_module varchar(20) DEFAULT NULL COMMENT '题目模块:base, sentence, textbook',
-  question_no_id int(11) unsigned NOT NULL COMMENT '题目编号id',
+  question_no_id int(11) unsigned DEFAULT 0 NOT NULL COMMENT '题目编号id',
   question_origin varchar(20) NOT NULL DEFAULT '' COMMENT '题目来源:collect,error,remove_error',
   PRIMARY KEY (id),
   KEY user_id (user_id,question_module)

+ 89 - 2
server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java

@@ -1603,13 +1603,32 @@ public class MyController {
             throw new ParameterException("课程类型错误");
         }
         List<UserCourseDetailDto> pr = Transform.convert(p, UserCourseDetailDto.class);
+        Map<Integer, UserOrderRecord> map = new HashMap<>();
+        for(UserOrderRecord record : p){
+            map.put(record.getId(), record);
+        }
 
         Collection recordIds = Transform.getIds(p, UserOrderRecord.class,"id");
 
         // 绑定课程
         Collection courseIds = Transform.getIds(p, UserOrderRecord.class, "productId");
         List<Course> courseList = courseService.select(courseIds);
+        Map courseMap = Transform.getMap(courseList, Course.class, "id");
         Transform.combine(pr, courseList, UserCourseDetailDto.class, "productId", "course", Course.class, "id", CourseExtendDto.class);
+        for(UserCourseDetailDto dto : pr){
+            Course course = (Course)courseMap.get(dto.getProductId());
+            CourseExtendDto courseExtendDto = dto.getCourse();
+            if (course.getCourseModule().equals(CourseModule.VS.key)){
+                // 根据课时数进行计算
+                courseExtendDto.setExpireDays(courseExtendService.computeExpire(dto.getNumber(), course));
+            }else if(course.getCourseModule().equals(CourseModule.VIDEO.key)){
+                // 根据设置进行计算
+                courseExtendDto.setExpireDays(courseExtendService.computeExpire(course));
+            }else if(course.getCourseModule().equals(CourseModule.ONLINE.key)){
+                // 根据使用时长计算
+                courseExtendDto.setExpireDays((int)(dto.getUseEndTime().getTime() - dto.getUseStartTime().getTime() / 86400000));
+            }
+        }
 
         // 绑定课时、预约、进度
         Map<Object, Collection<CourseNo>> courseNoMap = courseNoService.groupByCourseId(courseIds);
@@ -1625,12 +1644,14 @@ public class MyController {
             if (list == null || list.size() == 0) continue;
             Collection<CourseNo> courseNos = courseNoMap.get(dto.getProductId());
             dto.setCurrentNo(courseExtendService.computeCourseNoCurrent(courseNos, list));
-            dto.setTotalDays(courseExtendService.computeCourseDay(recordMap.get(dto.getId())));
+            Collection<UserCourseRecord> userCourseRecords = recordMap.get(dto.getId());
+            dto.setTotalTime(courseExtendService.computeCourseTime(userCourseRecords));
+            dto.setTotalDays(courseExtendService.computeCourseDay(map.get(dto.getId()), userCourseRecords));
         }
 
         // 获取每个科目的所有作业
         Map<Object, Collection<UserPreviewPaperRelation>> previewMap = previewService.groupByCourseId(user.getId(), recordIds, 1000);
-        Transform.combine(pr, previewMap, UserCourseDetailDto.class, "productId", "papers", UserPaperBaseExtendDto.class);
+        Transform.combine(pr, previewMap, UserCourseDetailDto.class, "productId", "papers", BasePaperExtendDto.class);
         for(UserCourseDetailDto dto : pr){
             Collection<UserPreviewPaperRelation> list = previewMap.get(dto.getId());
             if (list == null || list.size() == 0) continue;
@@ -1650,6 +1671,39 @@ public class MyController {
         List<CourseTeacher> teacherList = courseTeacherService.select(teacherIds);
         Transform.combine(pr, teacherList, UserCourseDetailDto.class, "teacherId", "teacher", CourseTeacher.class, "id", CourseTeacherExtendDto.class);
 
+        // 提问数、笔记数
+        Map<Object, Collection<UserAskCourse>> askMap = userAskCourseService.groupByRecordId(recordIds);
+        Transform.combine(pr, appointmentMap, UserCourseDetailDto.class, "productId", "appointments", UserCourseAppointmentExtendDto.class);
+
+        Map<Object, Collection<UserNoteCourse>> noteMap = userNoteCourseService.groupByCourse(courseIds);
+        Transform.combine(pr, appointmentMap, UserCourseDetailDto.class, "productId", "notes", UserNoteCourseExtendDto.class);
+        for(UserCourseDetailDto dto : pr){
+            Collection<CourseNoExtendDto> courseNos = dto.getCourseNos();
+            if (courseNos == null) continue;
+            Collection<UserAskCourse> askList = askMap.get(dto.getId());
+            Map<Object, List<UserAskCourse>> askListMap = Transform.getMapList(askList, UserAskCourse.class, "courseNoId");
+            Collection<UserNoteCourse> noteList = noteMap.get(dto.getProductId());
+            Map notes = Transform.getMap(noteList, UserNoteCourse.class, "courseNoId");
+            int noteNumber = 0;
+            int askNumber = askList.size();
+            int answerNumber = (int)askList.stream().filter(r->r.getAnswerStatus()==AskStatus.ANSWER.index).count();
+            for(CourseNoExtendDto courseNo : courseNos){
+                if (notes.get(courseNo.getId()) != null){
+                    courseNo.setNote(true);
+                    noteNumber += 1;
+                }
+                List<UserAskCourse> askListNo = askListMap.get(courseNo.getId());
+                if (askListNo != null){
+                    courseNo.setAskNumber(askListNo.size());
+                    courseNo.setAnswerNumber((int)askListNo.stream().filter(r->r.getAnswerStatus()==AskStatus.ANSWER.index).count());
+                }
+            }
+            dto.setNoteNumber(noteNumber);
+            dto.setAskNumber(askNumber);
+            dto.setAnswerNumber(answerNumber);
+        }
+
+
         return ResponseHelp.success(pr, page, size, p.getTotal());
     }
 
@@ -1742,4 +1796,37 @@ public class MyController {
 
         return ResponseHelp.success(dtos);
     }
+
+    @RequestMapping(value = "/export/question/error", method = RequestMethod.POST)
+    @ApiOperation(value = "关闭提示", notes = "关闭提示", httpMethod = "POST")
+    public Response<List<UserQuestionDetailDto>> exportQuestionError()  {
+        User user = (User) shiroHelp.getLoginUser();
+
+        return ResponseHelp.success(null);
+    }
+
+    @RequestMapping(value = "/export/tips", method = RequestMethod.POST)
+    @ApiOperation(value = "关闭提示", notes = "关闭提示", httpMethod = "POST")
+    public Response<Boolean> exportTips()  {
+        User user = (User) shiroHelp.getLoginUser();
+
+        User in = usersService.get(user.getId());
+        usersService.edit(User.builder()
+                .id(user.getId())
+                .exportTips(1)
+                .build());
+        return ResponseHelp.success(true);
+    }
+
+    @RequestMapping(value = "/course/comment/tips", method = RequestMethod.POST)
+    @ApiOperation(value = "关闭评论提示提示", notes = "关闭评论提示提示", httpMethod = "POST")
+    public Response<Boolean> exportTips(@RequestBody @Validated RecordCommentTipsDto dto)  {
+        User user = (User) shiroHelp.getLoginUser();
+        UserOrderRecord record = userOrderRecordService.get(dto.getRecordId());
+        userOrderRecordService.edit(UserOrderRecord.builder()
+                .id(dto.getRecordId())
+                .commentTips(1)
+                .build());
+        return ResponseHelp.success(true);
+    }
 }

+ 69 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/extend/BasePaperExtendDto.java

@@ -0,0 +1,69 @@
+package com.qxgmat.dto.extend;
+
+import com.nuliji.tools.annotation.Dto;
+import com.qxgmat.data.dao.entity.UserPaper;
+
+import java.util.Date;
+
+@Dto(entity = UserPaper.class)
+public class BasePaperExtendDto {
+    private Integer id;
+
+    private String title;
+
+    private Integer courseId;
+
+    private Integer courseNo;
+
+    private UserPaperBaseExtendDto paper;
+
+    private UserReportExtendDto report;
+
+    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;
+    }
+
+    public UserReportExtendDto getReport() {
+        return report;
+    }
+
+    public void setReport(UserReportExtendDto report) {
+        this.report = report;
+    }
+
+    public UserPaperBaseExtendDto getPaper() {
+        return paper;
+    }
+
+    public void setPaper(UserPaperBaseExtendDto paper) {
+        this.paper = paper;
+    }
+
+    public Integer getCourseId() {
+        return courseId;
+    }
+
+    public void setCourseId(Integer courseId) {
+        this.courseId = courseId;
+    }
+
+    public Integer getCourseNo() {
+        return courseNo;
+    }
+
+    public void setCourseNo(Integer courseNo) {
+        this.courseNo = courseNo;
+    }
+}

+ 10 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/extend/CourseExtendDto.java

@@ -25,6 +25,8 @@ public class CourseExtendDto {
 
     private Integer noNumber;
 
+    private Integer expireDays;
+
     public Integer getId() {
         return id;
     }
@@ -96,4 +98,12 @@ public class CourseExtendDto {
     public void setCourseModule(String courseModule) {
         this.courseModule = courseModule;
     }
+
+    public Integer getExpireDays() {
+        return expireDays;
+    }
+
+    public void setExpireDays(Integer expireDays) {
+        this.expireDays = expireDays;
+    }
 }

+ 10 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/extend/CourseNoExtendDto.java

@@ -16,6 +16,8 @@ public class CourseNoExtendDto {
 
     private String title;
 
+    private Integer time;
+
     private Integer askNumber;
 
     private Integer answerNumber;
@@ -77,4 +79,12 @@ public class CourseNoExtendDto {
     public void setNote(Boolean note) {
         this.note = note;
     }
+
+    public Integer getTime() {
+        return time;
+    }
+
+    public void setTime(Integer time) {
+        this.time = time;
+    }
 }

+ 48 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/extend/UserAskCourseExtendDto.java

@@ -0,0 +1,48 @@
+package com.qxgmat.dto.extend;
+
+import com.nuliji.tools.annotation.Dto;
+import com.qxgmat.data.dao.entity.UserAskCourse;
+import java.util.Date;
+
+@Dto(entity = UserAskCourse.class)
+public class UserAskCourseExtendDto {
+    private Integer id;
+
+    private Integer courseId;
+
+    private Integer courseNoId;
+
+    private Date updateTime;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getCourseId() {
+        return courseId;
+    }
+
+    public void setCourseId(Integer courseId) {
+        this.courseId = courseId;
+    }
+
+    public Integer getCourseNoId() {
+        return courseNoId;
+    }
+
+    public void setCourseNoId(Integer courseNoId) {
+        this.courseNoId = courseNoId;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+}

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

@@ -0,0 +1,49 @@
+package com.qxgmat.dto.extend;
+
+import com.nuliji.tools.annotation.Dto;
+import com.qxgmat.data.dao.entity.UserNoteCourse;
+
+import java.util.Date;
+
+@Dto(entity = UserNoteCourse.class)
+public class UserNoteCourseExtendDto {
+    private Integer id;
+
+    private Integer courseId;
+
+    private Integer courseNoId;
+
+    private Date updateTime;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getCourseId() {
+        return courseId;
+    }
+
+    public void setCourseId(Integer courseId) {
+        this.courseId = courseId;
+    }
+
+    public Integer getCourseNoId() {
+        return courseNoId;
+    }
+
+    public void setCourseNoId(Integer courseNoId) {
+        this.courseNoId = courseNoId;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+}

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

@@ -0,0 +1,13 @@
+package com.qxgmat.dto.request;
+
+public class RecordCommentTipsDto {
+    private Integer recordId;
+
+    public Integer getRecordId() {
+        return recordId;
+    }
+
+    public void setRecordId(Integer recordId) {
+        this.recordId = recordId;
+    }
+}

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

@@ -19,6 +19,8 @@ public class MyDto extends UserDto {
 
     private String inviteCode;
 
+    private Integer inviteNumber;
+
     private Boolean bindWechat;
 
     private Boolean bindReal;
@@ -148,4 +150,12 @@ public class MyDto extends UserDto {
     public void setDataEmailSubscribe(Integer dataEmailSubscribe) {
         this.dataEmailSubscribe = dataEmailSubscribe;
     }
+
+    public Integer getInviteNumber() {
+        return inviteNumber;
+    }
+
+    public void setInviteNumber(Integer inviteNumber) {
+        this.inviteNumber = inviteNumber;
+    }
 }

+ 43 - 3
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserCourseDetailDto.java

@@ -18,6 +18,8 @@ public class UserCourseDetailDto {
 
     private Integer vsNo;
 
+    private Integer number;
+
     private Integer teacherId;
 
     private CourseTeacherExtendDto teacher;
@@ -40,10 +42,16 @@ public class UserCourseDetailDto {
 
     private Date restoreTime;
 
+    private Integer commentTips;
+
+    private Integer courseAward;
+
     private Collection<CourseNoExtendDto> courseNos;
 
     private Integer currentNo;
 
+    private Integer totalTime;
+
     private Integer totalDays;
 
     private Integer previewProgress;
@@ -56,7 +64,7 @@ public class UserCourseDetailDto {
 
     private Integer noteNumber;
 
-    private Collection<UserPaperBaseExtendDto> papers;
+    private Collection<BasePaperExtendDto> papers;
 
     public Date getStartTime() {
         return startTime;
@@ -194,11 +202,11 @@ public class UserCourseDetailDto {
         this.appointments = appointments;
     }
 
-    public Collection<UserPaperBaseExtendDto> getPapers() {
+    public Collection<BasePaperExtendDto> getPapers() {
         return papers;
     }
 
-    public void setPapers(Collection<UserPaperBaseExtendDto> papers) {
+    public void setPapers(Collection<BasePaperExtendDto> papers) {
         this.papers = papers;
     }
 
@@ -249,4 +257,36 @@ public class UserCourseDetailDto {
     public void setPreviewProgress(Integer previewProgress) {
         this.previewProgress = previewProgress;
     }
+
+    public Integer getTotalTime() {
+        return totalTime;
+    }
+
+    public void setTotalTime(Integer totalTime) {
+        this.totalTime = totalTime;
+    }
+
+    public Integer getNumber() {
+        return number;
+    }
+
+    public void setNumber(Integer number) {
+        this.number = number;
+    }
+
+    public Integer getCommentTips() {
+        return commentTips;
+    }
+
+    public void setCommentTips(Integer commentTips) {
+        this.commentTips = commentTips;
+    }
+
+    public Integer getCourseAward() {
+        return courseAward;
+    }
+
+    public void setCourseAward(Integer courseAward) {
+        this.courseAward = courseAward;
+    }
 }

+ 27 - 12
server/gateway-api/src/main/java/com/qxgmat/service/UserNoteCourseService.java

@@ -2,29 +2,18 @@ package com.qxgmat.service;
 
 import com.github.pagehelper.Page;
 import com.nuliji.tools.AbstractService;
-import com.nuliji.tools.Transform;
 import com.nuliji.tools.exception.ParameterException;
 import com.nuliji.tools.exception.SystemException;
 import com.nuliji.tools.mybatis.Example;
-import com.qxgmat.data.constants.enums.status.AskStatus;
-import com.qxgmat.data.constants.enums.status.DirectionStatus;
-import com.qxgmat.data.constants.enums.user.AskTarget;
-import com.qxgmat.data.constants.enums.user.MoneyRange;
-import com.qxgmat.data.dao.UserAskCourseMapper;
 import com.qxgmat.data.dao.UserNoteCourseMapper;
-import com.qxgmat.data.dao.entity.UserAskCourse;
 import com.qxgmat.data.dao.entity.UserNoteCourse;
-import com.qxgmat.data.relation.UserAskCourseRelationMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 @Service
 public class UserNoteCourseService extends AbstractService {
@@ -58,6 +47,32 @@ public class UserNoteCourseService extends AbstractService {
         }
     }
 
+    /**
+     * 获取课程记录分组列表
+     * @param courseIds
+     * @return
+     */
+    public Map<Object, Collection<UserNoteCourse>> groupByCourse(Collection courseIds){
+        Map<Object, Collection<UserNoteCourse>> relationMap = new HashMap<>();
+        Example example = new Example(UserNoteCourse.class);
+        example.and(
+                example.createCriteria()
+                        .andIn("courseIds", courseIds)
+        );
+        List<UserNoteCourse> nos =  select(userNoteCourseMapper, example);
+        Collection<UserNoteCourse> list;
+        for(UserNoteCourse no : nos){
+            if (!relationMap.containsKey(no.getCourseId())){
+                list = new ArrayList<>();
+                relationMap.put(no.getCourseId(), list);
+            }else{
+                list = relationMap.get(no.getCourseId());
+            }
+            list.add(no);
+        }
+        return relationMap;
+    }
+
     public UserNoteCourse add(UserNoteCourse message){
         int result = insert(userNoteCourseMapper, message);
         message = one(userNoteCourseMapper, message.getId());

+ 31 - 8
server/gateway-api/src/main/java/com/qxgmat/service/extend/CourseExtendService.java

@@ -51,7 +51,7 @@ public class CourseExtendService {
      * @return
      */
     public int computeExpire(Course course){
-        return course.getExpireDays();
+        return course.getUseExpireDays();
     }
 
     public void suspendCourse(Integer userId, Integer recordId){
@@ -215,23 +215,46 @@ public class CourseExtendService {
         return min;
     }
 
+
+    /**
+     * 计算用户该课程的总学习时长
+     * @param userCourseRecords
+     * @return
+     */
+    public int computeCourseTime(Collection<UserCourseRecord> userCourseRecords){
+        int time = 0;
+        for(UserCourseRecord userCourseRecord:userCourseRecords){
+            time += userCourseRecord.getUserTime();
+        }
+        return time;
+    }
+
     /**
      * 计算用户该课程的总学习天数
+     * @param  record
      * @param userCourseRecords
      * @return
      */
-    public int computeCourseDay(Collection<UserCourseRecord> userCourseRecords){
+    public int computeCourseDay(UserOrderRecord record, Collection<UserCourseRecord> userCourseRecords){
         Date min = null;
         Date max = null;
-        for(UserCourseRecord record:userCourseRecords){
-            if(min==null || min.after(record.getCreateTime())){
-                min = record.getCreateTime();
+        for(UserCourseRecord userCourseRecord:userCourseRecords){
+            if(min==null || min.after(userCourseRecord.getCreateTime())){
+                min = userCourseRecord.getCreateTime();
             }
-            if (max == null || max.before(record.getCreateTime())){
-                max = record.getCreateTime();
+            if (max == null || max.before(userCourseRecord.getCreateTime())){
+                max = userCourseRecord.getCreateTime();
             }
         }
-        return (int)(Tools.day(max).getTime() - Tools.day(min).getTime()/86400000);
+        int suspend = 0;
+//        if(record.getIsSuspend() > 0){
+//            if(record.getRestoreTime() != null){
+//
+//            }else{
+//                suspend = 0;
+//            }
+//        }
+        return (int)(Tools.day(max).getTime() - Tools.day(min).getTime()/86400000) - suspend;
     }
 
     /**

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

@@ -62,9 +62,10 @@ public class PreviewService extends AbstractService {
      */
     public Map<Object, Collection<UserPreviewPaperRelation>> groupByCourseId(Integer userId, Collection recordIds, Integer top){
         Map<Object, Collection<UserPreviewPaperRelation>> relationMap = new HashMap<>();
+        if(recordIds == null || recordIds.size() == 0) return relationMap;
         for(Object id : recordIds){
             Integer recordId = (Integer)id;
-            relationMap.put(recordId, list(1, top, userId, recordId, null, 0));
+            relationMap.put(recordId, list(1, top, recordId, userId,  null, 0));
         }
         return relationMap;
     }

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

@@ -45,7 +45,7 @@ public class CourseNoService extends AbstractService {
                 example.createCriteria()
                         .andIn("courseId", courseIds)
         );
-        example.setOrderByClause("courseId asc, no asc");
+        example.setOrderByClause("course_id asc, no asc");
         List<CourseNo> nos =  select(courseNoMapper, example);
         Collection<CourseNo> list;
         for(CourseNo no : nos){

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

@@ -137,6 +137,7 @@ public class PreviewAssignService extends AbstractService {
      * @return
      */
     public List<PreviewAssign> listByAppointment(int page, int size, Integer courseId, Collection appointmentIds, Integer userId, String endTime, Integer times){
+        if(appointmentIds==null || appointmentIds.size() == 0) return new ArrayList<>();
         Page<PreviewAssign> p = page(()->previewAssignRelationMapper.listByAppointment(courseId, appointmentIds, userId, endTime, times), page, size);
         Collection ids = Transform.getIds(p, PreviewAssign.class, "id");
         // 获取详细数据

+ 27 - 4
server/gateway-api/src/main/java/com/qxgmat/service/inline/UserAskCourseService.java

@@ -19,10 +19,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 @Service
 public class UserAskCourseService extends AbstractService {
@@ -106,6 +103,32 @@ public class UserAskCourseService extends AbstractService {
         }
     }
 
+    /**
+     * 获取课程记录分组列表
+     * @param recordIds
+     * @return
+     */
+    public Map<Object, Collection<UserAskCourse>> groupByRecordId(Collection recordIds){
+        Map<Object, Collection<UserAskCourse>> relationMap = new HashMap<>();
+        Example example = new Example(UserAskCourse.class);
+        example.and(
+                example.createCriteria()
+                        .andIn("recordId", recordIds)
+        );
+        List<UserAskCourse> nos =  select(userAskCourseMapper, example);
+        Collection<UserAskCourse> list;
+        for(UserAskCourse no : nos){
+            if (!relationMap.containsKey(no.getRecordId())){
+                list = new ArrayList<>();
+                relationMap.put(no.getRecordId(), list);
+            }else{
+                list = relationMap.get(no.getRecordId());
+            }
+            list.add(no);
+        }
+        return relationMap;
+    }
+
     public UserAskCourse add(UserAskCourse message){
         int result = insert(userAskCourseMapper, message);
         message = one(userAskCourseMapper, message.getId());

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

@@ -75,12 +75,13 @@ public class UserCourseAppointmentService extends AbstractService {
      */
     public Map<Object, Collection<UserCourseAppointment>> groupByRecordId(Collection recordIds){
         Map<Object, Collection<UserCourseAppointment>> relationMap = new HashMap<>();
+        if (recordIds == null || recordIds.size() == 0) return relationMap;
         Example example = new Example(UserCourseAppointment.class);
         example.and(
                 example.createCriteria()
                         .andIn("recordId", recordIds)
         );
-        example.setOrderByClause("recordId asc, no asc");
+        example.setOrderByClause("record_id asc, no asc");
         List<UserCourseAppointment> nos =  select(userCourseAppointmentMapper, example);
         Collection<UserCourseAppointment> list;
         for(UserCourseAppointment no : nos){

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

@@ -521,8 +521,20 @@ public class UserOrderRecordService extends AbstractService {
         }
         String finalOrder = order;
         DirectionStatus finalDirection = direction;
+        String ltUseEndTime = null;
+        String gtUseEndTime = null;
+        if (isEnd != null){
+            // 是否结束,根据当前时间进行sql处理
+            if (isEnd){
+                ltUseEndTime = new Date().toString();
+            }else{
+                gtUseEndTime = new Date().toString();
+            }
+        }
+        String finalLtUseEndTime = ltUseEndTime;
+        String finalGtUseEndTime = gtUseEndTime;
         Page<UserOrderRecord> p = page(
-                ()-> userOrderRecordRelationMapper.listWithCourse(userId, modules, isUsed, isEnd, finalOrder, finalDirection.key)
+                ()-> userOrderRecordRelationMapper.listWithCourse(userId, modules, isUsed, finalLtUseEndTime, finalGtUseEndTime, finalOrder, finalDirection.key)
                 , page, size);
 
         Collection ids = Transform.getIds(p, UserOrderRecord.class, "id");

+ 1 - 1
server/gateway-api/src/main/java/com/qxgmat/task/ScheduledTask.java

@@ -283,7 +283,7 @@ public class ScheduledTask {
             List<UserCourseProgress> progressList = userCourseProgressService.listCourse(record.getId(), course.getId());
             List<UserCourseRecord> records = userCourseRecordService.allWithRecord(record.getId());
             Integer currentNo = courseExtendService.computeCourseNoCurrent(courseNoList, progressList);
-            Integer days = courseExtendService.computeCourseDay(records);
+            Integer days = courseExtendService.computeCourseDay(record, records);
             if (days/currentNo > 2){
                 continue;
             }

+ 40 - 2
server/tools/src/main/java/com/nuliji/tools/Transform.java

@@ -197,6 +197,7 @@ public class Transform {
         try {
             for(T t: targetList){
                 Collection<S> o = objectMap.get(targetKeyField.get(t));
+                if (o == null) continue;
                 if (transform == null){
                     targetField.set(t, o);
                 }else{
@@ -287,7 +288,44 @@ public class Transform {
         }
     }
 
-    public static <T,S> Map<Object, List<T>> getMapList(List<S> list, List<T> targetList, Class<?> clazz, String keyProp, String targetProp, Class<?> targetClazz, String indexProp){
-        return new HashMap<Object, List<T>>();
+    public static <T> Map<Object, List<T>> getMapList(Collection<T> list, Class<?> clazz, String keyProp){
+        Map<Object, List<T>> map = new HashMap<>();
+        if(list == null || list.size() == 0) return map;
+        Field keyField = Transform.getField(clazz, keyProp);
+        try{
+            for(T item: list){
+                Object object = keyField.get(item);
+                if (!map.containsKey(object)){
+                    map.put(object, new ArrayList<>());
+                }
+                List t = map.get(object);
+                t.add(item);
+            }
+            return map;
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+            throw new RuntimeException("Class:"+clazz.getName()+" access "+keyProp+" exception");
+        }
+    }
+
+    public static <T> Map<Object, List<T>> getMapList(Collection<T> list, Class<?> clazz, String keyProp, String valueProp){
+        Map<Object, List<T>> map = new HashMap<>();
+        if(list == null || list.size() == 0) return map;
+        Field keyField = Transform.getField(clazz, keyProp);
+        Field valueField = Transform.getField(clazz, valueProp);
+        try{
+            for(T item: list){
+                Object object = keyField.get(item);
+                if (!map.containsKey(object)){
+                    map.put(object, new ArrayList<>());
+                }
+                List t = map.get(object);
+                t.add(valueField.get(item));
+            }
+            return map;
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+            throw new RuntimeException("Class:"+clazz.getName()+" access "+keyProp+","+valueProp+" exception");
+        }
     }
 }