浏览代码

Merge branch 'master' of git.proginn.com:zaixianjiaoyu/sourcecode

Go 5 年之前
父节点
当前提交
b01e264269

+ 42 - 0
front/project/h5/routes/product/dataDetail/index.less

@@ -57,6 +57,48 @@
     border-top: 1px solid #eee;
     background: #fff;
 
+    .action {
+      display: inline-block;
+      margin-right: 10px;
+
+      .minus {
+        display: inline-block;
+        width: 20px;
+        height: 20px;
+        border: 1px solid #dfdfdf;
+        border-radius: 50%;
+        text-align: center;
+        line-height: 20px;
+        font-size: 10px;
+
+        i {
+          vertical-align: none;
+        }
+      }
+
+      .num {
+        display: inline-block;
+        color: #686872;
+        margin: 0 15px;
+      }
+
+      .add {
+        display: inline-block;
+        width: 20px;
+        height: 20px;
+        background: #41a6f3;
+        border-radius: 50%;
+        color: #fff;
+        text-align: center;
+        line-height: 20px;
+        font-size: 10px;
+
+        i {
+          vertical-align: none;
+        }
+      }
+    }
+
     .fee {
       display: inline-block;
     }

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

@@ -11,6 +11,7 @@ import { Course } from '../../../stores/course';
 import { Order } from '../../../stores/order';
 import { DataType } from '../../../../Constant';
 import { FAQItem, CommentItem } from '../../../components/Item';
+import Icon from '../../../components/Icon';
 
 const DataTypeMap = getMap(DataType, 'value', 'label');
 
@@ -40,10 +41,22 @@ export default class extends Page {
         content = <div dangerouslySetInnerHTML={{ __html: data[tab] }} />;
         break;
       case 'faq':
-        content = <div>{(data.faqs || []).map(row => <FAQItem data={row} />)}</div>;
+        content = (
+          <div>
+            {(data.faqs || []).map(row => (
+              <FAQItem data={row} />
+            ))}
+          </div>
+        );
         break;
       case 'comment':
-        content = <div>{(data.comments || []).map(row => <CommentItem data={row} />)}</div>;
+        content = (
+          <div>
+            {(data.comments || []).map(row => (
+              <CommentItem data={row} />
+            ))}
+          </div>
+        );
         break;
       default:
         break;
@@ -85,6 +98,15 @@ export default class extends Page {
         />
         {this.renderText()}
         <div className="fixed">
+          <div className="action">
+            <div className="minus">
+              <Icon type="minus" />
+            </div>
+            <div className="num">10</div>
+            <div className="add">
+              <Icon type="plus" />
+            </div>
+          </div>
           <div className="fee">
             总额: <Money value={data.price} size="lager" />
           </div>

二进制
front/project/www/assets/email_gray.png


front/project/www/assets/information.png → front/project/www/assets/info.png


二进制
front/project/www/assets/info_gray.png


二进制
front/project/www/assets/phone_1_gray.png


二进制
front/project/www/assets/realname_gray.png


二进制
front/project/www/assets/wechat_gray.png


+ 93 - 70
front/project/www/components/Icon/index.less

@@ -121,16 +121,13 @@
   background-image: url('/assets/header_question_highlight.png');
 }
 
-.icon.star {
+.icon.star,
+.icon.star.no:hover {
   width: 16px;
   height: 16px;
   background: url('/assets/header_star_normal.png') no-repeat center;
 }
 
-.icon.star.no:hover {
-  background-image: url('/assets/header_star_normal.png');
-}
-
 .icon.star.active,
 .icon.star.no.active,
 .icon.star:hover {
@@ -238,210 +235,236 @@
   background-image: url('/assets/down_hover.png');
 }
 
-.icon.note {
+.icon.note,
+.icon.note.no:hover {
   width: 20px;
   height: 20px;
   background: url('/assets/note_normal.png') no-repeat center;
 }
 
-.icon.note.no:hover {
-  background-image: url('/assets/note_normal.png');
-}
-
 .icon.note.active,
 .icon.note.no.active,
 .icon.note:hover {
   background-image: url('/assets/note_highlight.png');
 }
 
-.icon.speed-block {
+.icon.speed-block,
+.icon.speed-block.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/speed_block.png') no-repeat center;
 }
 
-.icon.speed-block.no:hover {
-  background-image: url('/assets/speed_block.png');
-}
-
 .icon.speed-block.active,
 .icon.speed-block.no.active,
 .icon.speed-block:hover {
   background-image: url('/assets/speed_normal.png');
 }
 
-.icon.question-block {
+.icon.question-block,
+.icon.question-block.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/question_block.png') no-repeat center;
 }
 
-.icon.question-block.no:hover {
-  background-image: url('/assets/question_block.png');
-}
-
 .icon.question-block.active,
 .icon.question-block.no.active,
 .icon.question-block:hover {
   background-image: url('/assets/question_normal.png');
 }
 
-.icon.clockin-block {
+.icon.clockin-block,
+.icon.clockin-block.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/clockin_block.png') no-repeat center;
 }
 
-.icon.clockin-block.no:hover {
-  background-image: url('/assets/clockin_block.png');
-}
-
 .icon.clockin-block.active,
 .icon.clockin-block.no.active,
 .icon.clockin-block:hover {
   background-image: url('/assets/clockin_normal.png');
 }
 
-.icon.note-block {
+.icon.note-block,
+.icon.note-block.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/note_block_normal.png') no-repeat center;
 }
 
-.icon.note-block.no:hover {
-  background-image: url('/assets/note_block_normal.png');
-}
-
 .icon.note-block.active,
 .icon.note-block.no.active,
 .icon.note-block:hover {
   background-image: url('/assets/note_block_highlight.png');
 }
 
-.icon.gift-block {
+.icon.gift-block,
+.icon.gift-block.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/gift2.png') no-repeat center;
 }
 
-.icon.gift-block.no:hover {
-  background-image: url('/assets/gift2.png');
-}
-
 .icon.gift-block.active,
 .icon.gift-block.no.active,
 .icon.gift-block:hover {
   background-image: url('/assets/gift2.png');
 }
 
-.icon.time-icon {
+.icon.time-icon,
+.icon.time-icon.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/time_gray.png') no-repeat center;
 }
 
-.icon.time-icon.no:hover {
-  background-image: url('/assets/time_gray.png');
-}
-
 .icon.time-icon.active,
 .icon.time-icon.no.active,
 .icon.time-icon:hover {
   background-image: url('/assets/time_normal.png');
 }
 
-.icon.QA-icon {
+.icon.QA-icon,
+.icon.QA-icon.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/QA_gary.png') no-repeat center;
 }
 
-.icon.QA-icon.no:hover {
-  background-image: url('/assets/QA_gary.png');
-}
-
 .icon.QA-icon.active,
 .icon.QA-icon.no.active,
 .icon.QA-icon:hover {
   background-image: url('/assets/QA_normal.png');
 }
 
-.icon.class-icon {
+.icon.class-icon,
+.icon.class-icon.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/class_gray.png') no-repeat center;
 }
 
-.icon.class-icon.no:hover {
-  background-image: url('/assets/class_gray.png');
-}
-
 .icon.class-icon.active,
 .icon.class-icon.no.active,
 .icon.class-icon:hover {
   background-image: url('/assets/class_normal.png');
 }
 
-.icon.note-icon {
+.icon.note-icon,
+.icon.note-icon.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/note_gray.png') no-repeat center;
 }
 
-.icon.note-icon.no:hover {
-  background-image: url('/assets/note_gray.png');
-}
-
 .icon.note-icon.active,
 .icon.note-icon.no.active,
 .icon.note-icon:hover {
   background-image: url('/assets/page_normal.png');
 }
 
-.icon.supplement-icon {
+.icon.supplement-icon,
+.icon.supplement-icon.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/supplement_gray.png') no-repeat center;
 }
 
-.icon.supplement-icon.no:hover {
-  background-image: url('/assets/supplement_gray.png');
-}
-
 .icon.supplement-icon.active,
 .icon.supplement-icon.no.active,
 .icon.supplement-icon:hover {
   background-image: url('/assets/supplement_normal.png');
 }
 
-.icon.information-icon {
+.icon.information-icon,
+.icon.information-icon.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/information_gray.png') no-repeat center;
 }
 
-.icon.information-icon.no:hover {
-  background-image: url('/assets/information_gray.png');
-}
-
 .icon.information-icon.active,
 .icon.information-icon.no.active,
 .icon.information-icon:hover {
   background-image: url('/assets/information_normal.png');
 }
 
-.icon.homework-icon {
+.icon.homework-icon,
+.icon.homework-icon.no:hover {
   width: 40px;
   height: 40px;
   background: url('/assets/homework_gray.png') no-repeat center;
 }
 
-.icon.homework-icon.no:hover {
-  background-image: url('/assets/homework_gray.png');
-}
-
 .icon.homework-icon.active,
 .icon.homework-icon.no.active,
 .icon.homework-icon:hover {
   background-image: url('/assets/homework_normal.png');
+}
+
+.icon.user-wechat,
+.icon.user-wechat.no:hover {
+  width: 20px;
+  height: 20px;
+  background: url('/assets/wechat_gray.png') no-repeat center;
+}
+
+.icon.user-wechat.active,
+.icon.user-wechat.no.active,
+.icon.user-wechat:hover {
+  background-image: url('/assets/wechat.png');
+}
+
+.icon.user-phone,
+.icon.user-phone.no:hover {
+  width: 20px;
+  height: 20px;
+  background: url('/assets/phone_1_gray.png') no-repeat center;
+}
+
+.icon.user-phone.active,
+.icon.user-phone.no.active,
+.icon.user-phone:hover {
+  background-image: url('/assets/phone_1.png');
+}
+
+.icon.user-realname,
+.icon.user-realname.no:hover {
+  width: 20px;
+  height: 20px;
+  background: url('/assets/realname_gray.png') no-repeat center;
+}
+
+.icon.user-realname.active,
+.icon.user-realname.no.active,
+.icon.user-realname:hover {
+  background-image: url('/assets/realname.png');
+}
+
+.icon.user-email,
+.icon.user-email.no:hover {
+  width: 20px;
+  height: 20px;
+  background: url('/assets/email_gray.png') no-repeat center;
+}
+
+.icon.user-email.active,
+.icon.user-email.no.active,
+.icon.user-email:hover {
+  background-image: url('/assets/email.png');
+}
+
+.icon.user-info,
+.icon.user-info.no:hover {
+  width: 20px;
+  height: 20px;
+  background: url('/assets/info_gray.png') no-repeat center;
+}
+
+.icon.user-info.active,
+.icon.user-info.no.active,
+.icon.user-info:hover {
+  background-image: url('/assets/info.png');
 }

+ 10 - 1
front/project/www/components/Modal/index.js

@@ -20,6 +20,8 @@ export default class extends Component {
       close = true,
       maskClosable = false,
       body = true,
+      center,
+      height,
     } = this.props;
     return (
       <Modal
@@ -30,11 +32,18 @@ export default class extends Component {
         footer={false}
         width={width}
         onCancel={onClose}
+        centered={center}
       >
         <div className="g-modal-wrapper">
           {close && onClose && <Icon className="close" type="close-circle" theme="filled" onClick={() => onClose()} />}
           <div className="g-modal-title">{title}</div>
-          {body ? <div className="g-modal-body">{children}</div> : children}
+          {body ? (
+            <div className="g-modal-body" style={{ maxHeight: height }}>
+              {children}
+            </div>
+          ) : (
+            children
+          )}
           <div className={`g-modal-btns ${btnAlign}`}>
             {onCancel && (
               <Button size="lager" theme="link" onClick={() => onCancel()}>

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

@@ -19,6 +19,7 @@
 
     .g-modal-body {
       padding: 30px 0;
+      overflow-y: auto;
     }
 
     .g-modal-btns {

+ 2 - 4
front/project/www/components/More/index.js

@@ -3,7 +3,7 @@ import './index.less';
 import { Icon, Dropdown, Menu } from 'antd';
 
 function More(props) {
-  const { menu = [], onClick } = props;
+  const { menu = [], node, onClick } = props;
   return (
     <Dropdown
       overlay={
@@ -15,9 +15,7 @@ function More(props) {
       }
       trigger={['click']}
     >
-      <div className="more">
-        <Icon type="more" />
-      </div>
+      <div className="more">{node || <Icon type="more" />}</div>
     </Dropdown>
   );
 }

+ 25 - 0
front/project/www/components/Note/index.js

@@ -0,0 +1,25 @@
+import React, { Component } from 'react';
+import './index.less';
+import Assets from '@src/components/Assets';
+import More from '../More';
+
+export default class Note extends Component {
+  render() {
+    const { data = { file: true }, theme = 'default', actionList, onAction } = this.props;
+    return (
+      <div className={`note-detail ${theme}`}>
+        <Assets className="note-avatar" name="sun_blue" src={data.avatar} />
+        {onAction && actionList && <More menu={actionList} onClick={onAction} />}
+        <div className="t-2 t-s-12 m-b-1">
+          学生ID <span className="t-3">2019-07-02 19:00</span>
+        </div>
+        <div className="t-1 t-s-12 m-b-1">
+          学生留言内容学生留言内容学生留言内容学,生留言内容学生留言。内容学生 留言内容学生留言内容学生留言内容。
+        </div>
+        <a hidden={!data.file} className="link t-s-12">
+          学生上传文档1.doc
+        </a>
+      </div>
+    );
+  }
+}

+ 20 - 0
front/project/www/components/Note/index.less

@@ -0,0 +1,20 @@
+@import '../../app.less';
+
+.note-detail {
+  padding-left: 42px;
+  padding-bottom: 20px;
+  position: relative;
+
+  .note-avatar {
+    position: absolute;
+    left: 0;
+    border-radius: 50%;
+    width: 32px;
+    height: 32px;
+  }
+
+  .more {
+    position: absolute;
+    right: 0;
+  }
+}

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

@@ -95,7 +95,6 @@
     .select {
       margin-left: 12px;
       display: inline-block;
-      transform: translateY(-2px);
 
       .button {
         line-height: 20px;

+ 24 - 0
front/project/www/components/UserPagination/index.js

@@ -0,0 +1,24 @@
+import React, { Component } from 'react';
+import './index.less';
+import Icon from '../Icon';
+
+export default class extends Component {
+  onChangePage(page) {
+    const { current, total, onChange } = this.props;
+    if (page < current || page > total) return;
+    if (onChange) onChange(page);
+  }
+
+  render() {
+    const { current, total } = this.props;
+    return (
+      <div className="user-pagination">
+        <Icon name="arrow-left-small" onClick={() => this.onChangePage(current - 1)} />
+        <span>
+          <b>{current}</b>/{total}
+        </span>
+        <Icon name="arrow-right-small" onClick={() => this.onChangePage(current + 1)} />
+      </div>
+    );
+  }
+}

+ 17 - 0
front/project/www/components/UserPagination/index.less

@@ -0,0 +1,17 @@
+@import '../../app.less';
+
+.user-pagination {
+  padding-top: 20px;
+  text-align: center;
+
+  span {
+    margin: 0 15px;
+    display: inline-block;
+    color: #303139;
+
+    b {
+      color: #4299FF;
+      font-weight: 500;
+    }
+  }
+}

+ 3 - 15
front/project/www/components/UserTable/index.js

@@ -3,14 +3,9 @@ import './index.less';
 import Assets from '@src/components/Assets';
 import CheckboxItem from '../CheckboxItem';
 import Icon from '../Icon';
+import UserPagination from '../UserPagination';
 
 export default class UserTable extends Component {
-  onChangePage(page) {
-    const { current, total, onChange } = this.props;
-    if (page < current || page > total) return;
-    if (onChange) onChange(page);
-  }
-
   onSort(key, value) {
     const { sortMap = {}, onSort } = this.props;
     sortMap[key] = value;
@@ -43,6 +38,7 @@ export default class UserTable extends Component {
       header = true,
       sortMap = {},
       maxHeight,
+      onChange,
     } = this.props;
     return (
       <div className={`user-table ${size} ${even} ${theme} ${border ? 'border' : ''}`}>
@@ -109,15 +105,7 @@ export default class UserTable extends Component {
           </tbody>
         </table>
         {data.length === 0 && <div className="empty">暂无数据</div>}
-        {total && data.length > 0 && (
-          <div className="page">
-            <Icon name="arrow-left-small" onClick={() => this.onChangePage(current - 1)} />
-            <span>
-              <b>{current}</b>/{total}
-            </span>
-            <Icon name="arrow-right-small" onClick={() => this.onChangePage(current + 1)} />
-          </div>
-        )}
+        {total && data.length > 0 && <UserPagination total={total} current={current} onChange={onChange} />}
       </div>
     );
   }

+ 64 - 1
front/project/www/routes/my/collect/index.less

@@ -1,3 +1,66 @@
 @charset "utf-8";
 
-#my-sollect {}
+#my-collect {
+  .user-action {
+    .tip {
+      font-size: 12px;
+      color: #A7A7B7;
+
+      span {
+        color: #4299FF;
+        cursor: pointer;
+        margin: 0 5px;
+      }
+
+      i {
+        font-size: 14px;
+        cursor: pointer;
+      }
+    }
+  }
+
+  .table-layout {
+    padding: 20px 30px;
+
+    .user-table {
+      font-size: 12px;
+    }
+
+    .article-item {
+      .detail {
+        max-height: 140px;
+        overflow: hidden;
+        background: linear-gradient(360deg, rgba(161, 161, 171, 0) 0%, rgba(104, 104, 114, 1) 100%);
+        -webkit-background-clip: text;
+        -webkit-text-fill-color: transparent;
+      }
+    }
+  }
+}
+
+.g-modal.article-detail-modal {
+  .ant-modal-body {
+    .detail {
+      height: 600px;
+      overflow-y: auto;
+    }
+
+    .prev {
+      position: absolute;
+      left: -100px;
+      top: 300px;
+      color: #fff;
+      font-size: 37px;
+      cursor: pointer;
+    }
+
+    .next {
+      position: absolute;
+      right: -100px;
+      top: 300px;
+      color: #fff;
+      font-size: 37px;
+      cursor: pointer;
+    }
+  }
+}

文件差异内容过多而无法显示
+ 98 - 60
front/project/www/routes/my/collect/page.js


+ 8 - 0
front/project/www/routes/my/course/index.less

@@ -360,6 +360,14 @@
               border-bottom: 1px solid #4299FF;
               cursor: pointer;
             }
+
+            .note-list {
+              margin-top: 10px;
+              background: #FBFBFB;
+              width: 480px;
+              padding: 20px;
+              margin-left: -70px;
+            }
           }
         }
 

+ 26 - 7
front/project/www/routes/my/course/page.js

@@ -15,6 +15,7 @@ import UserTable from '../../../components/UserTable';
 import More from '../../../components/More';
 import Modal from '../../../components/Modal';
 import Date from '../../../components/Date';
+import Note from '../../../components/Note';
 
 export default class extends Page {
   initState() {
@@ -53,7 +54,7 @@ export default class extends Page {
     };
   }
 
-  onAction() { }
+  onAction() {}
 
   refresh(tab1, tab2) {
     this.setState({ tab1, tab2 });
@@ -99,7 +100,7 @@ export default class extends Page {
           onChange={key => this.refresh(tab1, key)}
         />
         {this[`renderTab${tab1}`]()}
-        <Modal className="clock-modal" title="打卡表" width={460} onClose={() => { }}>
+        <Modal className="clock-modal" title="打卡表" width={460} onClose={() => {}}>
           <div>
             <div className="d-i-b w-3">
               <div className="t-2 t-s-14">听课频率</div>
@@ -147,10 +148,10 @@ export default class extends Page {
           />
           <div className="t-2 t-s-12">*听课频率≤2天/课时,作业完成度≥90%,课程有效期可延长7-10天。</div>
         </Modal>
-        <Modal title="恢复学习" onConfirm={() => { }} onCancel={() => { }}>
+        <Modal title="恢复学习" onConfirm={() => {}} onCancel={() => {}}>
           <div className="t-2 t-s-18">恢复学习后,本课程的停课功能将无法使用。是否恢复学习?</div>
         </Modal>
-        <Modal title="上传笔记" width={630} confirmText="提交" onConfirm={() => { }} onCancel={() => { }}>
+        <Modal title="上传笔记" width={630} confirmText="提交" onConfirm={() => {}} onCancel={() => {}}>
           <textarea
             className="b-c-1 w-10 p-10 m-b-1"
             rows={6}
@@ -162,6 +163,12 @@ export default class extends Page {
           </div>
           <div className="b-b m-t-2" />
         </Modal>
+        <Modal title="课后笔记" width={500} height={500} onClose={() => {}}>
+          <Note />
+          <Note />
+          <Note />
+          <Note />
+        </Modal>
       </div>
     );
   }
@@ -401,10 +408,10 @@ class Education extends Component {
         <div className="class-hour">
           <div className="text">课时 5:解读句子属性</div>
           <div className="right">
-            <GIcon name="prev" onClick={() => { }} />
+            <GIcon name="prev" onClick={() => {}} />
             <span>上一课时</span>
             <span>下一课时</span>
-            <GIcon name="next" onClick={() => { }} />
+            <GIcon name="next" onClick={() => {}} />
           </div>
         </div>
         {tab === '1' ? this.renderTimeLine() : this.renderTable()}
@@ -569,7 +576,19 @@ class TimeLineItem extends Component {
           <input placeholder="请输入CCtalk用户名查看授课频道" />
         );
       case '4':
-        return <span className="link">点此上传</span>;
+        return (
+          <div>
+            <div>
+              <span className="link">点此上传</span>
+            </div>
+            <div className="note-list">
+              <Note onAction={() => {}} actionList={[{ key: '123', label: '123' }]} />
+              <Note />
+              <Note />
+              <Note />
+            </div>
+          </div>
+        );
       case '5':
         return <span className="link">写留言</span>;
       case '6':

+ 4 - 0
front/project/www/routes/my/error/index.less

@@ -21,5 +21,9 @@
 
   .table-layout {
     padding: 20px 30px;
+
+    .user-table {
+      font-size: 12px;
+    }
   }
 }

+ 38 - 14
front/project/www/routes/my/main/page.js

@@ -202,7 +202,7 @@ export default class extends Page {
     // 获取学习数据
     My.getStudyTotal().then((total, index) => {
       total.categorys = total.categorys.map(row => {
-        row.ratio = row.time * 100 / total.time;
+        row.ratio = (row.time * 100) / total.time;
         row.time = formatSeconds(row.time);
         row.color = this.colors[index];
         return row;
@@ -311,9 +311,20 @@ export default class extends Page {
         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: 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>的用户` },
+          {
+            title: `超过了<b>${
+              result.examinationExceed
+                ? formatPercent(result.examinationExceed.rank, result.examinationExceed.total)
+                : '-%'
+            }</b>的用户`,
+          },
         ],
         detail: result.examinationList.map(row => {
           return {
@@ -328,9 +339,18 @@ export default class extends Page {
         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: 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>的用户` },
+          {
+            title: `超过了<b>${
+              result.courseExceed ? formatPercent(result.courseExceed.rank, result.courseExceed.total) : '-%'
+            }</b>的用户`,
+          },
         ],
         detail: result.courseList.map(row => {
           return {
@@ -529,30 +549,34 @@ export default class extends Page {
                 邀请
               </Button>
             </span>
-            <Assets name="wechat" active={info.bindWechat} />
-            <Assets
-              name="phone_1"
+            <GIcon name="user-wechat" noHover active={info.bindWechat} />
+            <GIcon
+              name="user-phone"
+              noHover
               active={info.bindMobile}
               onClick={() => {
                 this.setState({ showPhone: true });
               }}
             />
-            <Assets
-              name="realname"
+            <GIcon
+              name="user-realname"
+              noHover
               active={info.bindReal}
               onClick={() => {
                 this.setState({ showReal: true });
               }}
             />
-            <Assets
-              name="email"
+            <GIcon
+              name="user-email"
+              noHover
               active={!!info.email}
               onClick={() => {
                 this.setState({ showEmail: true });
               }}
             />
-            <Assets
-              name="information"
+            <GIcon
+              name="user-info"
+              noHover
               active={info.bindPrepare}
               onClick={() => {
                 this.setState({ showExamination: true });