소스 검색

fix layout

KaysonCui 4 년 전
부모
커밋
2eb89a9471

+ 25 - 0
front/project/www/app.less

@@ -338,6 +338,31 @@ body,
     width: @content_width;
     margin: 0 auto;
   }
+
+  .drag-upload {
+    padding: 30px;
+    border: 1px dashed #ddd;
+    position: relative;
+    text-align: center;
+
+    .fixed {
+      padding: 30px;
+      background: #00000066;
+      color: #fff;
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      display: none;
+    }
+  }
+
+  .drag-upload.draging {
+    .fixed {
+      display: block;
+    }
+  }
 }
 
 #root {}

+ 10 - 0
front/project/www/components/Button/index.less

@@ -65,6 +65,12 @@
   border: 1px solid @line_color;
 }
 
+.button.file {
+  background: linear-gradient(180deg, rgba(249, 249, 249, 1) 0%, rgba(241, 241, 241, 1) 100%);
+  border-radius: 3px;
+  border: 1px solid #d5d5d5;
+}
+
 .button.white {
   background: #fff;
   color: @theme_color;
@@ -109,6 +115,10 @@
   color: @theme_color_hover;
 }
 
+.button.file:hover {
+  background: #ececec;
+}
+
 .button.error:hover {
   background: darken(#f36565, 5);
 }

+ 16 - 1
front/project/www/components/UserAction/index.js

@@ -4,6 +4,7 @@ import { Icon } from 'antd';
 import Assets from '@src/components/Assets';
 import Select from '../Select';
 import CheckboxItem from '../CheckboxItem';
+import { Icon as GIcon } from '../Icon';
 import { Button } from '../Button';
 
 export default class UserAction extends Component {
@@ -22,6 +23,13 @@ export default class UserAction extends Component {
     if (onAll) onAll(checked);
   }
 
+  onSearchKey(e) {
+    if (e.keyCode === 13) {
+      const { onSearch } = this.props;
+      if (onSearch) onSearch(this.state.searchText);
+    }
+  }
+
   onSearch(value) {
     this.setState({ searchText: value });
   }
@@ -90,7 +98,13 @@ export default class UserAction extends Component {
             return (
               <div className={`item sort-item ${item.right ? 'right' : ''}`}>
                 {item.label}
-                {sortMap[item.key] ? (
+                {item.fixed ? (
+                  sortMap[item.key] ? (
+                    <GIcon active name="arrow-down" onClick={() => this.onSort(item.key, '')} />
+                  ) : (
+                    <GIcon name="arrow-up" onClick={() => this.onSort(item.key, 'desc')} />
+                  )
+                ) : sortMap[item.key] ? (
                   <Assets
                     name={sortMap[item.key] === 'asc' ? 'seqencing2_up_select' : 'seqencing2_down_select'}
                     onClick={() => this.onSort(item.key, sortMap[item.key] === 'asc' ? 'desc' : '')}
@@ -110,6 +124,7 @@ export default class UserAction extends Component {
                 placeholder="请输入您想搜索的内容"
                 value={searchText}
                 onChange={e => this.onSearch(e.target.value)}
+                onKeyUp={e => this.onSearchKey(e)}
               />
             )}
             {!showInput && <Icon type="search" onClick={() => this.setState({ showInput: true })} />}

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

@@ -17,6 +17,10 @@
         cursor: pointer;
       }
     }
+
+    .switch {
+      height: 100%;
+    }
   }
 
   .table-layout {

+ 134 - 89
front/project/www/routes/my/answer/page.js

@@ -13,48 +13,53 @@ import Tabs from '../../../components/Tabs';
 import { TimeRange } from '../../../../Constant';
 import { My } from '../../../stores/my';
 
-const columns = [{
-  key: 'title',
-  title: '笔记对象',
-  width: 140,
-  render(text, row) {
-    return row.group ? (
-      <div className="group">
-        <Link to="">{text}</Link>
-      </div>
-    ) : (
-      <div className="sub">{text}</div>
-    );
+const columns = [
+  {
+    key: 'title',
+    title: '笔记对象',
+    width: 140,
+    render(text, row) {
+      return row.group ? (
+        <div className="group">
+          <Link to="">{text}</Link>
+        </div>
+      ) : (
+        <div className="sub">{text}</div>
+      );
+    },
   },
-}, {
-  key: 'date',
-  title: '更新时间',
-  width: 100,
-  render(text, row) {
-    return row.group ? (
-      <div className="group">
-        <Link to="">{text}</Link>
-      </div>
-    ) : (<div className="sub">
-      <div className="date">{text.split(' ')[0]}</div>
-      <div className="date">{text.split(' ')[1]}</div>
-    </div>
-    );
+  {
+    key: 'date',
+    title: '更新时间',
+    width: 100,
+    render(text, row) {
+      return row.group ? (
+        <div className="group">
+          <Link to="">{text}</Link>
+        </div>
+      ) : (
+        <div className="sub">
+          <div className="date">{text.split(' ')[0]}</div>
+          <div className="date">{text.split(' ')[1]}</div>
+        </div>
+      );
+    },
   },
-}, {
-  key: 'content',
-  title: '内容',
-  width: 540,
-  render(text, row) {
-    return row.group ? (
-      <div className="group">
-        <Link to="">{text}</Link>
-      </div>
-    ) : (
-      <div className="sub">{text}</div>
-    );
+  {
+    key: 'content',
+    title: '内容',
+    width: 540,
+    render(text, row) {
+      return row.group ? (
+        <div className="group">
+          <Link to="">{text}</Link>
+        </div>
+      ) : (
+        <div className="sub">{text}</div>
+      );
+    },
   },
-}];
+];
 
 export default class extends Page {
   constructor(props) {
@@ -128,21 +133,33 @@ export default class extends Page {
       data.filterMap.timerange = data.timerange;
     }
     const [startTime, endTime] = timeRange(data.timerange);
-    refreshQuestionType(this, data.subject, data.questionType, { all: true, needSentence: false, allSubject: true })
-      .then(({ questionTypes }) => {
-        return refreshStruct(this, data.tab, data.one, data.two, {
-          all: true, needPreview: false, needTextbook: true,
-        })
-          .then(({ structIds, latest, year }) => {
-            My.listQuestionAsk(Object.assign({ module: data.tab, questionTypes, structIds, latest, year, startTime, endTime }, this.state.search, {
-              order: Object.keys(data.sortMap).map(key => {
-                return `${key} ${data.sortMap[key]}`;
-              }).join(','),
-            })).then(result => {
-              this.setState({ list: result.list, total: result.total, page: data.page });
-            });
-          });
+    refreshQuestionType(this, data.subject, data.questionType, {
+      all: true,
+      needSentence: false,
+      allSubject: true,
+    }).then(({ questionTypes }) => {
+      return refreshStruct(this, data.tab, data.one, data.two, {
+        all: true,
+        needPreview: false,
+        needTextbook: true,
+      }).then(({ structIds, latest, year }) => {
+        My.listQuestionAsk(
+          Object.assign(
+            { module: data.tab, questionTypes, structIds, latest, year, startTime, endTime },
+            this.state.search,
+            {
+              order: Object.keys(data.sortMap)
+                .map(key => {
+                  return `${key} ${data.sortMap[key]}`;
+                })
+                .join(','),
+            },
+          ),
+        ).then(result => {
+          this.setState({ list: result.list, total: result.total, page: data.page });
+        });
       });
+    });
   }
 
   onTabChange(tab) {
@@ -166,7 +183,7 @@ export default class extends Page {
     this.search({ page });
   }
 
-  onAction() { }
+  onAction() {}
 
   onSelect(selectList) {
     this.setState({ selectList });
@@ -178,7 +195,16 @@ export default class extends Page {
   }
 
   renderTable() {
-    const { tab, questionSubjectSelect, questionSubjectMap = {}, oneSelect, twoSelectMap = {}, filterMap = {}, sortMap = {}, list = [] } = this.state;
+    const {
+      tab,
+      questionSubjectSelect,
+      questionSubjectMap = {},
+      oneSelect,
+      twoSelectMap = {},
+      filterMap = {},
+      sortMap = {},
+      list = [],
+    } = this.state;
     const { total, page } = this.state;
     return (
       <div className="table-layout">
@@ -195,46 +221,63 @@ export default class extends Page {
         />
         <UserAction
           search
-          selectList={[{
-            children: [{
-              key: 'subject',
-              placeholder: '学科',
-              select: questionSubjectSelect,
-            }, {
-              placeholder: '题型',
-              key: 'questionType',
-              be: 'subject',
-              selectMap: questionSubjectMap,
-            }],
-          }, {
-            label: '范围',
-            children: [{
-              key: 'one',
-              placeholder: '全部',
-              select: oneSelect,
-            }, {
-              key: 'two',
-              be: 'one',
-              placeholder: '全部',
-              selectMap: twoSelectMap,
-            }],
-          }, {
-            right: true,
-            key: 'timerange',
-            select: TimeRange,
-          }]}
+          selectList={[
+            {
+              children: [
+                {
+                  key: 'subject',
+                  placeholder: '学科',
+                  select: questionSubjectSelect,
+                },
+                {
+                  placeholder: '题型',
+                  key: 'questionType',
+                  be: 'subject',
+                  selectMap: questionSubjectMap,
+                },
+              ],
+            },
+            {
+              label: '范围',
+              children: [
+                {
+                  key: 'one',
+                  placeholder: '全部',
+                  select: oneSelect,
+                },
+                {
+                  key: 'two',
+                  be: 'one',
+                  placeholder: '全部',
+                  selectMap: twoSelectMap,
+                },
+              ],
+            },
+            {
+              right: true,
+              key: 'timerange',
+              select: TimeRange,
+            },
+          ]}
           filterMap={filterMap}
           onFilter={value => this.onFilter(value)}
         />
         <UserAction
-          sortList={[{ right: true, label: '提问时间', key: 'create_time' }, { right: true, label: '回答时间', key: 'ask_time' }]}
+          sortList={[
+            { right: true, label: '提问时间', key: 'create_time', fixed: true },
+            { right: true, label: '回答时间', key: 'ask_time' },
+          ]}
           sortMap={sortMap}
           left={
             <div className="email">
-              只看已回答 <Switch checked={filterMap.askStatus} onChange={() => {
-              filterMap.askStatus = !filterMap.askStatus;
-              this.onFilter(filterMap);
-            }} />
+              只看已回答{' '}
+              <Switch
+                checked={filterMap.askStatus}
+                onChange={() => {
+                  filterMap.askStatus = !filterMap.askStatus;
+                  this.onFilter(filterMap);
+                }}
+              />
             </div>
           }
           onSort={value => this.onSort(value)}
@@ -255,7 +298,9 @@ export default class extends Page {
             </div>
           );
         })}
-        {total && list.length > 0 && <UserPagination total={total} current={page} onChange={(p) => this.onChangePage(p)} />}
+        {total && list.length > 0 && (
+          <UserPagination total={total} current={page} onChange={p => this.onChangePage(p)} />
+        )}
       </div>
     );
   }

+ 27 - 12
front/project/www/routes/my/course/page.js

@@ -81,7 +81,7 @@ export default class extends Page {
     });
   }
 
-  onAction() { }
+  onAction() {}
 
   onTabChange(tab) {
     const data = { tab };
@@ -102,7 +102,7 @@ export default class extends Page {
   }
 
   renderDetail() {
-    const { tab, status, showTime, showRestore, showUploadNote, showNote } = this.state;
+    const { tab, status, showTime, showRestore, showUploadNote = true, showNote } = this.state;
     return (
       <div className="detail-layout">
         <div className="tip">
@@ -136,7 +136,7 @@ export default class extends Page {
           onChange={key => this.onStatusChange(key)}
         />
         {this[`renderTab${tab}`]()}
-        <Modal show={showTime} className="clock-modal" title="打卡表" width={460} onClose={() => { }}>
+        <Modal show={showTime} className="clock-modal" title="打卡表" width={460} onClose={() => {}}>
           <div>
             <div className="d-i-b w-3">
               <div className="t-2 t-s-14">听课频率</div>
@@ -184,22 +184,37 @@ export default class extends Page {
           />
           <div className="t-2 t-s-12">*听课频率≤2天/课时,作业完成度≥90%,课程有效期可延长7-10天。</div>
         </Modal>
-        <Modal show={showRestore} title="恢复学习" onConfirm={() => { }} onCancel={() => { }}>
+        <Modal show={showRestore} title="恢复学习" onConfirm={() => {}} onCancel={() => {}}>
           <div className="t-2 t-s-18">恢复学习后,本课程的停课功能将无法使用。是否恢复学习?</div>
         </Modal>
-        <Modal show={showUploadNote} title="上传笔记" width={630} confirmText="提交" onConfirm={() => { }} onCancel={() => { }}>
+        <Modal
+          show={showUploadNote}
+          title="上传笔记"
+          width={630}
+          confirmText="提交"
+          onConfirm={() => {}}
+          onCancel={() => {}}
+        >
           <textarea
             className="b-c-1 w-10 p-10 m-b-1"
             rows={6}
             placeholder="请输入留言内容,也可将文件拖动到这里上传。"
           />
-          <div className="t-2 t-s-16 m-b-1">
-            上传文件 <FileUpload type="file" title="选择文件" />
-            <span className="t-3 t-s-14">支持 docx, xls, PDF, rar, zip, PNG, JPG 等类型的文件</span>
+          <div className={`t-c drag-upload ${this.state.draging ? 'draging' : ''}`}>
+            <Button theme="file">上传文件</Button>
+            <span className="m-l-1 t-3 t-s-14">支持 docx, xls, PDF, rar, zip, PNG, JPG 等类型的文件</span>
+            <div className="fixed">
+              <span className="f-w-b t-s-18">放开文件立刻上传</span>
+            </div>
+            <FileUpload
+              type="none"
+              onDragEnter={() => this.setState({ draging: true })}
+              onDragLeave={() => this.setState({ draging: false })}
+            />
           </div>
           <div className="b-b m-t-2" />
         </Modal>
-        <Modal show={showNote} title="课后笔记" width={500} height={500} onClose={() => { }}>
+        <Modal show={showNote} title="课后笔记" width={500} height={500} onClose={() => {}}>
           <Note />
           <Note />
           <Note />
@@ -444,10 +459,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()}
@@ -618,7 +633,7 @@ class TimeLineItem extends Component {
               <span className="link">点此上传</span>
             </div>
             <div className="note-list">
-              <Note onAction={() => { }} actionList={[{ key: '123', label: '123' }]} />
+              <Note onAction={() => {}} actionList={[{ key: '123', label: '123' }]} />
               <Note />
               <Note />
               <Note />

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

@@ -67,22 +67,34 @@ export default class extends Page {
       data.filterMap.timerange = data.timerange;
     }
     const [startTime, endTime] = timeRange(data.timerange);
-    refreshQuestionType(this, data.subject, data.questionType, { all: true, needSentence: true, allSubject: true })
-      .then(({ questionTypes }) => {
-        return refreshStruct(this, data.tab, data.one, data.two, {
-          all: true, needPreview: false, needTextbook: true,
-        })
-          .then(({ structIds, latest, year }) => {
-            My.listQuestionAsk(Object.assign({ module: data.tab, questionTypes, structIds, latest, year, startTime, endTime }, this.state.search, {
-              order: Object.keys(data.sortMap).map(key => {
-                if (key === 'title') return 'pid desc, no desc';
-                return `${key} ${data.sortMap[key]}`;
-              }).join(','),
-            })).then(result => {
-              this.setState({ list: result.list, total: result.total });
-            });
-          });
+    refreshQuestionType(this, data.subject, data.questionType, {
+      all: true,
+      needSentence: true,
+      allSubject: true,
+    }).then(({ questionTypes }) => {
+      return refreshStruct(this, data.tab, data.one, data.two, {
+        all: true,
+        needPreview: false,
+        needTextbook: true,
+      }).then(({ structIds, latest, year }) => {
+        My.listQuestionAsk(
+          Object.assign(
+            { module: data.tab, questionTypes, structIds, latest, year, startTime, endTime },
+            this.state.search,
+            {
+              order: Object.keys(data.sortMap)
+                .map(key => {
+                  if (key === 'title') return 'pid desc, no desc';
+                  return `${key} ${data.sortMap[key]}`;
+                })
+                .join(','),
+            },
+          ),
+        ).then(result => {
+          this.setState({ list: result.list, total: result.total });
+        });
       });
+    });
   }
 
   onTabChange(tab) {
@@ -94,6 +106,10 @@ export default class extends Page {
     this.search(value);
   }
 
+  onSearch(value) {
+    console.log(value);
+  }
+
   onSort(value) {
     const keys = Object.keys(value);
     // this.search({ order: keys.length ? keys.join('|') : null, direction: keys.length ? Object.values(value).join('|') : null });
@@ -119,7 +135,7 @@ export default class extends Page {
     }
   }
 
-  onAction() { }
+  onAction() {}
 
   onSelect(selectList) {
     this.setState({ selectList });
@@ -131,7 +147,16 @@ export default class extends Page {
   }
 
   renderTable() {
-    const { tab, questionSubjectSelect, questionSubjectMap = {}, oneSelect, twoSelectMap = {}, filterMap = {}, sortMap = {}, list = [] } = this.state;
+    const {
+      tab,
+      questionSubjectSelect,
+      questionSubjectMap = {},
+      oneSelect,
+      twoSelectMap = {},
+      filterMap = {},
+      sortMap = {},
+      list = [],
+    } = this.state;
     const { selectList = [], allChecked, page, total } = this.state;
     return (
       <div className="table-layout">
@@ -148,36 +173,47 @@ export default class extends Page {
         />
         <UserAction
           search
-          selectList={[{
-            children: [{
-              key: 'subject',
-              placeholder: '学科',
-              select: questionSubjectSelect,
-            }, {
-              placeholder: '题型',
-              key: 'questionType',
-              be: 'subject',
-              selectMap: questionSubjectMap,
-            }],
-          }, {
-            label: '范围',
-            children: [{
-              key: 'one',
-              placeholder: '全部',
-              select: oneSelect,
-            }, {
-              key: 'two',
-              be: 'one',
-              placeholder: '全部',
-              selectMap: twoSelectMap,
-            }],
-          }, {
-            right: true,
-            key: 'timerange',
-            select: TimeRange,
-          }]}
+          selectList={[
+            {
+              children: [
+                {
+                  key: 'subject',
+                  placeholder: '学科',
+                  select: questionSubjectSelect,
+                },
+                {
+                  placeholder: '题型',
+                  key: 'questionType',
+                  be: 'subject',
+                  selectMap: questionSubjectMap,
+                },
+              ],
+            },
+            {
+              label: '范围',
+              children: [
+                {
+                  key: 'one',
+                  placeholder: '全部',
+                  select: oneSelect,
+                },
+                {
+                  key: 'two',
+                  be: 'one',
+                  placeholder: '全部',
+                  selectMap: twoSelectMap,
+                },
+              ],
+            },
+            {
+              right: true,
+              key: 'timerange',
+              select: TimeRange,
+            },
+          ]}
           filterMap={filterMap}
           onFilter={value => this.onFilter(value)}
+          onSearch={value => this.onSearch(value)}
         />
         <UserAction
           allCheckbox
@@ -216,7 +252,7 @@ export default class extends Page {
 
   renderModal() {
     return [
-      <Modal title="操作提示" confirmText="好的,知道了" btnAlign="center" onConfirm={() => { }}>
+      <Modal title="操作提示" confirmText="好的,知道了" btnAlign="center" onConfirm={() => {}}>
         <div className="flex-layout m-b-2">
           <div className="flex-block">
             <div className="t-1 t-s-18">组卷功能</div>
@@ -236,10 +272,10 @@ export default class extends Page {
           查阅以上信息。
         </div>
       </Modal>,
-      <Modal title="组卷练习" confirmText="好的,知道了" btnAlign="center" onConfirm={() => { }}>
+      <Modal title="组卷练习" confirmText="好的,知道了" btnAlign="center" onConfirm={() => {}}>
         <div className="t-2 t-s-18">不可同时选中语文题和数学题,请重新选择。</div>
       </Modal>,
-      <Modal title="组卷练习" confirmText="开始练习" onConfirm={() => { }} onCancel={() => { }}>
+      <Modal title="组卷练习" confirmText="开始练习" onConfirm={() => {}} onCancel={() => {}}>
         <div className="t-2 t-s-18">
           您共选择了 <span className="t-4">50</span> 道题目,是否开始练习?
         </div>
@@ -253,15 +289,15 @@ export default class extends Page {
           次以上的错题
         </div>
       </Modal>,
-      <Modal title="移出" onConfirm={() => { }} onCancel={() => { }}>
+      <Modal title="移出" onConfirm={() => {}} onCancel={() => {}}>
         <div className="t-2 t-s-18">
           当前选中的 <span className="t-4">50</span> 道题即将被移出错题本,移出后无法恢复,是否继续?
         </div>
       </Modal>,
-      <Modal title="导出" confirmText="好的,知道了" btnAlign="center" onConfirm={() => { }}>
+      <Modal title="导出" confirmText="好的,知道了" btnAlign="center" onConfirm={() => {}}>
         <div className="t-2 t-s-18">正在下载中,请不要关闭当前页面!</div>
       </Modal>,
-      <Modal title="导出" confirmText="导出" onConfirm={() => { }} onCancel={() => { }}>
+      <Modal title="导出" confirmText="导出" onConfirm={() => {}} onCancel={() => {}}>
         <div className="t-2 t-s-18 m-b-5">
           当前共选中 <span className="t-4">50</span> 道题,请确认需要导出的内容:
         </div>
@@ -276,7 +312,7 @@ export default class extends Page {
           })}
         </div>
       </Modal>,
-      <Modal title="导出" confirmText="导出" onConfirm={() => { }} onCancel={() => { }}>
+      <Modal title="导出" confirmText="导出" onConfirm={() => {}} onCancel={() => {}}>
         <div className="t-2 t-s-18 m-b-5">
           当前共选中 <span className="t-4">50</span> 道题,请确认需要导出的内容:
         </div>

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

@@ -23,6 +23,7 @@ import { Textbook } from '../../../stores/textbook';
 import { DataType, ServiceKey } from '../../../../Constant';
 import { Main } from '../../../stores/main';
 import { Question } from '../../../stores/question';
+import Select from '../../../components/Select';
 
 const ServiceKeyMap = getMap(ServiceKey, 'value', 'label');
 
@@ -87,38 +88,37 @@ export default class extends Page {
     Main.getService('textbook').then(result => {
       this.setState({ service: result });
     });
-    Textbook.getInfo()
-      .then(result => {
-        const { latest } = result;
-        result.day = parseInt((new Date().getTime() - new Date(result.latest.startDate).getTime()) / 86400000, 10);
+    Textbook.getInfo().then(result => {
+      const { latest } = result;
+      result.day = parseInt((new Date().getTime() - new Date(result.latest.startDate).getTime()) / 86400000, 10);
 
-        result.expireDay = result.expireTime && parseInt((new Date().getTime() - new Date(result.expireTime).getTime()) / 86400000, 10);
+      result.expireDay =
+        result.expireTime && parseInt((new Date().getTime() - new Date(result.expireTime).getTime()) / 86400000, 10);
 
-        const list = [];
+      const list = [];
 
-        list.push({ subject: 'quant', number: latest.quantNumber, time: latest.quantTime, version: latest.quantVersion });
-        list.push({ subject: 'rc', number: latest.rcNumber, time: latest.rcTime, version: latest.rcVersion });
-        list.push({ subject: 'ir', number: latest.irNumber, time: latest.irTime, version: latest.irVersion });
-        this.setState({ data: result, list });
-      });
+      list.push({ subject: 'quant', number: latest.quantNumber, time: latest.quantTime, version: latest.quantVersion });
+      list.push({ subject: 'rc', number: latest.rcNumber, time: latest.rcTime, version: latest.rcVersion });
+      list.push({ subject: 'ir', number: latest.irNumber, time: latest.irTime, version: latest.irVersion });
+      this.setState({ data: result, list });
+    });
   }
 
   textbookHistory({ page, size, subject }) {
-    Textbook.listHistory({ subject })
-      .then(result => {
-        this.setState({
-          updateList: result.map(row => {
-            row.version = row[`${subject}Version`];
-            row.content = row[`${subject}Content`];
-            row.createTime = formatDate(row.createTime, 'YYYY-MM-DD\nHH:mm:ss');
-            return row;
-          }),
-          // 不显示分页
-          updateTotal: 0,
-          updatePage: page,
-          updateData: { page, size, subject, columns: textbookHistoryColumns, type: 'textbook' },
-        });
+    Textbook.listHistory({ subject }).then(result => {
+      this.setState({
+        updateList: result.map(row => {
+          row.version = row[`${subject}Version`];
+          row.content = row[`${subject}Content`];
+          row.createTime = formatDate(row.createTime, 'YYYY-MM-DD\nHH:mm:ss');
+          return row;
+        }),
+        // 不显示分页
+        updateTotal: 0,
+        updatePage: page,
+        updateData: { page, size, subject, columns: textbookHistoryColumns, type: 'textbook' },
       });
+    });
   }
 
   refreshExamination() {
@@ -126,7 +126,8 @@ export default class extends Page {
       this.setState({ service: result });
     });
     Question.getExaminationInfo(result => {
-      result.expireDay = result.expireTime && parseInt((new Date().getTime() - new Date(result.expireTime).getTime()) / 86400000, 10);
+      result.expireDay =
+        result.expireTime && parseInt((new Date().getTime() - new Date(result.expireTime).getTime()) / 86400000, 10);
       this.setState({ data: result });
     });
   }
@@ -138,22 +139,27 @@ export default class extends Page {
   }
 
   recordList({ page, size, service, isUse, isExpire }) {
-    Order.listRecord({ page, size, productType: 'service', service, isUse, isExpire })
-      .then(result => {
-        this.setState({
-          updateList: result.map(row => {
-            row.title = ServiceKeyMap[service];
-            row.handler = <a onClick={() => {
-              this.open(row.id);
-            }}>立即开通</a>;
-            row.endTime = `${formatDate(row.endTime, 'YYYY-MM-DD')} 前`;
-            return row;
-          }),
-          updateTotal: result.length,
-          updatePage: page,
-          updateData: { page, size, service, isUse, columns: isUse ? [] : openColumns, type: 'record' },
-        });
+    Order.listRecord({ page, size, productType: 'service', service, isUse, isExpire }).then(result => {
+      this.setState({
+        updateList: result.map(row => {
+          row.title = ServiceKeyMap[service];
+          row.handler = (
+            <a
+              onClick={() => {
+                this.open(row.id);
+              }}
+            >
+              立即开通
+            </a>
+          );
+          row.endTime = `${formatDate(row.endTime, 'YYYY-MM-DD')} 前`;
+          return row;
+        }),
+        updateTotal: result.length,
+        updatePage: page,
+        updateData: { page, size, service, isUse, columns: isUse ? [] : openColumns, type: 'record' },
       });
+    });
   }
 
   refreshData() {
@@ -168,11 +174,13 @@ export default class extends Page {
     });
     this.setState({ dataTypeSelect });
     Main.dataStruct().then(result => {
-      const structs = result.filter(row => row.level === 1).map(row => {
-        row.title = `${row.titleZh}${row.titleEn}`;
-        row.key = `${row.id}`;
-        return row;
-      });
+      const structs = result
+        .filter(row => row.level === 1)
+        .map(row => {
+          row.title = `${row.titleZh}${row.titleEn}`;
+          row.key = `${row.id}`;
+          return row;
+        });
       structs.unshift({
         title: '全部',
         key: '',
@@ -181,37 +189,42 @@ export default class extends Page {
         structs,
       });
     });
-    My.listData(Object.assign({}, this.state.search))
-      .then(result => {
-        result = {
-          list: [{
+    My.listData(Object.assign({}, this.state.search)).then(result => {
+      result = {
+        list: [
+          {
             title: '123123',
             latestTime: '',
             id: 1,
             number: 10,
             version: '1231',
-          }],
-        };
-        this.setState({
-          list: result.list.map(row => {
-            row.time = formatDate(row.time, 'YYYY-MM-DD HH:mm:ss');
-            return row;
-          }),
-          total: result.total,
-          page: this.state.search.page,
-        });
+          },
+        ],
+      };
+      this.setState({
+        list: result.list.map(row => {
+          row.time = formatDate(row.time, 'YYYY-MM-DD HH:mm:ss');
+          return row;
+        }),
+        total: result.total,
+        page: this.state.search.page,
       });
+    });
   }
 
   dataHistory({ dataId, page, size }) {
-    My.listDataHistory({ page, size, dataId })
-      .then(result => {
-        result.list = result.list.map(row => {
-          row.time = formatDate(row.time, 'YYYY-MM-DD\nHH:mm:ss');
-          return row;
-        });
-        this.setState({ updateList: result.list, updateTotal: result.total, updatePage: page, updateData: { page, size, dataId, columns: dataHistoryColumns, type: 'data' } });
+    My.listDataHistory({ page, size, dataId }).then(result => {
+      result.list = result.list.map(row => {
+        row.time = formatDate(row.time, 'YYYY-MM-DD\nHH:mm:ss');
+        return row;
+      });
+      this.setState({
+        updateList: result.list,
+        updateTotal: result.total,
+        updatePage: page,
+        updateData: { page, size, dataId, columns: dataHistoryColumns, type: 'data' },
       });
+    });
   }
 
   onFilter(value) {
@@ -232,26 +245,29 @@ export default class extends Page {
 
   submitComment() {
     const { comment } = this.state;
-    My.addComment(comment.channel, comment.position, comment.content)
-      .then(() => {
-        this.setState({ showComment: false, showFinish: true, comment: {} });
-      });
+    My.addComment(comment.channel, comment.position, comment.content).then(() => {
+      this.setState({ showComment: false, showFinish: true, comment: {} });
+    });
   }
 
   submitFeedbackError() {
     const { feedbackError } = this.state;
-    My.addFeedbackErrorData(feedbackError.dataId, feedbackError.title, feedbackError.position, feedbackError.originContent, feedbackError.content)
-      .then(() => {
-        this.setState({ showFinish: true, showFeedbackError: false, feedbackError: {} });
-      });
+    My.addFeedbackErrorData(
+      feedbackError.dataId,
+      feedbackError.title,
+      feedbackError.position,
+      feedbackError.originContent,
+      feedbackError.content,
+    ).then(() => {
+      this.setState({ showFinish: true, showFeedbackError: false, feedbackError: {} });
+    });
   }
 
   submitFeedback() {
     const { feedback } = this.state;
-    My.addTextbookFeedback('', feedback.target, feedback.content)
-      .then(() => {
-        this.setState({ showFinish: true, showFeedback: false, feedbackError: {} });
-      });
+    My.addTextbookFeedback('', feedback.target, feedback.content).then(() => {
+      this.setState({ showFinish: true, showFeedback: false, feedbackError: {} });
+    });
   }
 
   subscribe(value) {
@@ -279,7 +295,18 @@ export default class extends Page {
   }
 
   renderDetail() {
-    const { tab, comment = {}, showComment, showFinish, showUpdate, updateList, updateTotal, updateData = {} } = this.state;
+    const {
+      tab,
+      comment = {},
+      feedback = {},
+      showComment,
+      showFinish,
+      showUpdate,
+      showFeedback,
+      updateList,
+      updateTotal,
+      updateData = {},
+    } = this.state;
     return (
       <div className="table-layout">
         <Tabs
@@ -300,13 +327,20 @@ export default class extends Page {
           onChange={key => this.onTabChange(key)}
         />
         {this[`renderTab${tab}`]()}
-        <Modal show={showUpdate} maskClosable close={false} body={false} width={630} onClose={() => this.setState({ showUpdate: false, updateList: [] })} >
+        <Modal
+          show={showUpdate}
+          maskClosable
+          close={false}
+          body={false}
+          width={630}
+          onClose={() => this.setState({ showUpdate: false, updateList: [] })}
+        >
           <UserTable
             size="small"
             columns={updateData.columns}
             data={updateList}
             current={updateData.page}
-            onChange={(page) => {
+            onChange={page => {
               updateData.page = page;
               if (updateData.type === 'data') {
                 this.dataHistory(updateData);
@@ -319,19 +353,78 @@ export default class extends Page {
             total={updateTotal}
           />
         </Modal>
-        <Modal show={showComment} title="评价" onConfirm={() => comment.content && this.submitComment()} onCancel={() => this.setState({ showComment: false, comment: {} })}>
-          <textarea value={comment.content} className="b-c-1 w-10 p-10" rows={6} placeholder="您的看法对我们来说很重要!" onChange={(e) => {
-            comment.content = e.target.value;
-            this.setState({ comment });
-          }} />
+        <Modal
+          show={showComment}
+          title="评价"
+          onConfirm={() => comment.content && this.submitComment()}
+          onCancel={() => this.setState({ showComment: false, comment: {} })}
+        >
+          <textarea
+            value={comment.content}
+            className="b-c-1 w-10 p-10"
+            rows={6}
+            placeholder="您的看法对我们来说很重要!"
+            onChange={e => {
+              comment.content = e.target.value;
+              this.setState({ comment });
+            }}
+          />
           <div className="b-b m-t-2" />
         </Modal>
-        <Modal show={showFinish} title="提交成功" confirmText="好的,知道了" btnAlign="center" onConfirm={() => this.setState({ showFinish: false })} >
+        <Modal
+          show={showFinish}
+          title="提交成功"
+          confirmText="好的,知道了"
+          btnAlign="center"
+          onConfirm={() => this.setState({ showFinish: false })}
+        >
           <div className="t-2 t-s-18">
             <Icon type="check" className="t-5 m-r-5" />
             您的每一次反馈都是千行进步的动力。
           </div>
         </Modal>
+        <Modal
+          show={showFeedback}
+          title="反馈"
+          width={630}
+          onConfirm={() => this.setState({ showFeedback: false })}
+          onCancel={() => this.setState({ showFeedback: false })}
+        >
+          <div className="t-2 t-s-16 m-b-1">
+            机经类别:
+            <Select
+              value={feedback.type}
+              theme="white"
+              list={[{ title: '数学机经', key: '1' }, { title: '逻辑机经', key: '2' }, { title: '阅读机经', key: '3' }]}
+            />
+            反馈类型:
+            <Select
+              value={feedback.cate}
+              theme="white"
+              list={[
+                { title: '纠正解析', key: '1' },
+                { title: '完善已有机经', key: '2' },
+                { title: '提供全新机经', key: '3' },
+              ]}
+            />
+            <span hidden={feedback.cate === 3}>
+              题号是
+              <input style={{ width: 80 }} className="m-l-1 b-c-1 t-c" />
+            </span>
+          </div>
+          <div className="t-2 t-s-16">正确的解析和答案应该是:</div>
+          <textarea
+            value={comment.content}
+            className="b-c-1 w-10 p-10"
+            rows={10}
+            placeholder={{ 1: '正确的解析和答案是:', 2: '补充内容是:', 3: '新机经是:' }[feedback.cate]}
+            onChange={e => {
+              comment.content = e.target.value;
+              this.setState({ comment });
+            }}
+          />
+          <div className="b-b m-t-2" />
+        </Modal>
       </div>
     );
   }
@@ -342,26 +435,35 @@ export default class extends Page {
     return (
       <div className="tab-1-layout">
         <UserAction
-          selectList={[{
-            label: '学科',
-            key: 'structId',
-            select: structs,
-          },
-          {
-            label: '资料形式',
-            key: 'dataType',
-            select: dataTypeSelect,
-          }]}
-          sortList={[{ right: true, label: '销量', key: 'sale_number' }, { right: true, label: '更新时间', key: 'latest_time' }]}
+          selectList={[
+            {
+              label: '学科',
+              key: 'structId',
+              select: structs,
+            },
+            {
+              label: '资料形式',
+              key: 'dataType',
+              select: dataTypeSelect,
+            },
+          ]}
+          sortList={[
+            { right: true, label: '销量', key: 'sale_number' },
+            { right: true, label: '更新时间', key: 'latest_time' },
+          ]}
           sortMap={sortMap}
           filterMap={filterMap}
           onFilter={value => this.onFilter(value)}
           onSort={value => this.onSort(value)}
           right={
             <div className="email">
-              邮箱订阅 <Switch checked={info.dataEmailSubscribe} onChange={() => {
-              this.subscribe(!info.dataEmailSubscribe);
-            }} />
+              邮箱订阅{' '}
+              <Switch
+                checked={info.dataEmailSubscribe}
+                onChange={() => {
+                  this.subscribe(!info.dataEmailSubscribe);
+                }}
+              />
             </div>
           }
         />
@@ -372,14 +474,23 @@ export default class extends Page {
                 <Assets name="sun_blue" src={item.cover} />
                 <div className="fixed">
                   <div className="btns">
-                    <Button size="small" radius onClick={() => {
-                      openLink(item.resource);
-                    }}>
+                    <Button
+                      size="small"
+                      radius
+                      onClick={() => {
+                        openLink(item.resource);
+                      }}
+                    >
                       阅读
                     </Button>
-                    <div className="white" onClick={() => {
-                      openLink(item.resource);
-                    }}>下载</div>
+                    <div
+                      className="white"
+                      onClick={() => {
+                        openLink(item.resource);
+                      }}
+                    >
+                      下载
+                    </div>
                   </div>
                 </div>
                 <div className="title">
@@ -388,8 +499,12 @@ export default class extends Page {
                 </div>
                 <div className="date">{formatDate(item.latestTime, 'YYYY-MM-DD HH:mm:ss')}</div>
                 <More
-                  menu={[{ label: '纠错', key: 'feedback' }, { label: '评价', key: 'comment' }, { label: '更新', key: 'update' }]}
-                  onClick={(value) => {
+                  menu={[
+                    { label: '纠错', key: 'feedback' },
+                    { label: '评价', key: 'comment' },
+                    { label: '更新', key: 'update' },
+                  ]}
+                  onClick={value => {
                     const { key } = value;
                     if (key === 'comment') {
                       this.setState({ showComment: true, comment: { channel: 'course_data', position: item.id } });
@@ -405,7 +520,9 @@ export default class extends Page {
             );
           })}
         </div>
-        {total && list.length > 0 && <UserPagination total={total} current={page} onChange={(p) => this.onChangePage(p)} />}
+        {total && list.length > 0 && (
+          <UserPagination total={total} current={page} onChange={p => this.onChangePage(p)} />
+        )}
       </div>
     );
   }
@@ -425,56 +542,83 @@ export default class extends Page {
               </span>
             </div>
           }
-          right={!data.hasService && data.unUseRecord && <div className="email" onClick={() => {
-            this.recordList({ page: 1, size: 10, service: 'textbook', isUse: false, isExpire: false });
-          }}>待开通</div>}
+          right={
+            !data.hasService &&
+            data.unUseRecord && (
+              <div
+                className="email"
+                onClick={() => {
+                  this.recordList({ page: 1, size: 10, service: 'textbook', isUse: false, isExpire: false });
+                }}
+              >
+                待开通
+              </div>
+            )
+          }
         />
-        {data.hasService && <div className="data-layout">
-          {list.map(item => {
-            return (
-              <div className="data-item">
-                <Assets name="sun_blue" />
-                <div className="title">
-                  已更新至<b>{item.num}</b>题
+        {data.hasService && (
+          <div className="data-layout">
+            {list.map(item => {
+              return (
+                <div className="data-item">
+                  <Assets name="sun_blue" />
+                  <div className="title">
+                    已更新至<b>{item.num}</b>题
+                  </div>
+                  <div className="date">{item.date}</div>
+                  <More
+                    menu={[
+                      { label: '更新', key: 'update' },
+                      { label: '反馈', key: 'feedback' },
+                      { label: '评价', key: 'comment' },
+                    ]}
+                    onClick={value => {
+                      const { key } = value;
+                      if (key === 'comment') {
+                        this.setState({ showComment: true, comment: { channel: 'library' } });
+                      } else if (key === 'update') {
+                        this.setState({ showUpdate: true });
+                        this.textbookHistory({ page: 1, size: 100, subject: item.subject });
+                      } else if (key === 'feedback') {
+                        this.setState({ showFeedback: true });
+                      }
+                    }}
+                  />
                 </div>
-                <div className="date">{item.date}</div>
-                <More
-                  menu={[{ label: '更新', key: 'update' }, { label: '反馈', key: 'feedback' }, { label: '评价', key: 'comment' }]}
-                  onClick={(value) => {
-                    const { key } = value;
-                    if (key === 'comment') {
-                      this.setState({ showComment: true, comment: { channel: 'library' } });
-                    } else if (key === 'update') {
-                      this.setState({ showUpdate: true });
-                      this.textbookHistory({ page: 1, size: 100, subject: item.subject });
-                    } else if (key === 'feedback') {
-                      this.setState({ showFeedback: true });
-                    }
-                  }}
-                />
-              </div>
-            );
-          })}
-        </div>}
-        {!data.hasService && !data.unUseRecord && <div className="tip-layout">
-          <div className="t1">还未购买本月机经</div>
-          <div className="desc">¥ {service && service.package && service.package[0].price}</div>
-          <Button radius size="lager" width={150}>
-            立即购买
-          </Button>
-        </div>}
-        {data.hasService && <div className="tip-layout">
-          <div className="t1">使用中</div>
-          <div className="t2">距离到期还有 {data.expireDay} 天</div>
-        </div>}
-        {!data.hasService && data.unUseRecord && <div className="tip-layout">
-          <div className="t2">请于{formatDate(data.unUseRecord.endTime, 'YYYY-MM-DD')}前开通</div>
-          <Button radius size="lager" width={150} onClick={() => {
-            this.open(data.unUseRecord.id);
-          }}>
-            立即开通
-          </Button>
-        </div>}
+              );
+            })}
+          </div>
+        )}
+        {!data.hasService && !data.unUseRecord && (
+          <div className="tip-layout">
+            <div className="t1">还未购买本月机经</div>
+            <div className="desc">¥ {service && service.package && service.package[0].price}</div>
+            <Button radius size="lager" width={150}>
+              立即购买
+            </Button>
+          </div>
+        )}
+        {data.hasService && (
+          <div className="tip-layout">
+            <div className="t1">使用中</div>
+            <div className="t2">距离到期还有 {data.expireDay} 天</div>
+          </div>
+        )}
+        {!data.hasService && data.unUseRecord && (
+          <div className="tip-layout">
+            <div className="t2">请于{formatDate(data.unUseRecord.endTime, 'YYYY-MM-DD')}前开通</div>
+            <Button
+              radius
+              size="lager"
+              width={150}
+              onClick={() => {
+                this.open(data.unUseRecord.id);
+              }}
+            >
+              立即开通
+            </Button>
+          </div>
+        )}
       </div>
     );
   }
@@ -483,36 +627,63 @@ export default class extends Page {
     const { data = {}, service } = this.state;
     return (
       <div className="tab-3-layout">
-        <UserAction right={!data.hasService && data.unUseRecord && <div className="email" onClick={() => {
-          this.recordList({ page: 1, size: 10, service: 'qx_cat', isUse: false, isExpire: false });
-        }}>待开通</div>} />
-        {!data.hasService && !data.unUseRecord && !data.expireTime && <div className="tip-layout">
-          <div className="t1">未购买</div>
-          <div className="desc">¥ {service && service.package && service.package[0].price}</div>
-          <Button radius size="lager" width={150}>
-            立即购买
-          </Button>
-        </div>}
-        {!data.hasService && data.unUseRecord && <div className="tip-layout">
-          <div className="t2">请于{formatDate(data.unUseRecord.endTime, 'YYYY-MM-DD')}前开通</div>
-          <Button radius size="lager" width={150} onClick={() => {
-            this.open(data.unUseRecord.id);
-          }}>
-            立即开通
-          </Button>
-        </div>}
-        {data.hasService && <div className="tip-layout">
-          <div className="t1">使用中</div>
-          <div className="t2">距离到期还有 {data.expireDay} 天</div>
-        </div>}
-        {!data.hasService && !data.unUseRecord && data.expireTime && <div className="tip-layout">
-          <div className="t3">已过期</div>
-          <div className="date">{formatDate(data.startTime, 'YYYY-MM-DD')} ~ {formatDate(data.expireTime, 'YYYY-MM-DD')}</div>
-          <div className="desc">¥ {service && service.package && service.package[0].price}</div>
-          <Button radius size="lager" width={150}>
-            立即购买
-          </Button>
-        </div>}
+        <UserAction
+          right={
+            !data.hasService &&
+            data.unUseRecord && (
+              <div
+                className="email"
+                onClick={() => {
+                  this.recordList({ page: 1, size: 10, service: 'qx_cat', isUse: false, isExpire: false });
+                }}
+              >
+                待开通
+              </div>
+            )
+          }
+        />
+        {!data.hasService && !data.unUseRecord && !data.expireTime && (
+          <div className="tip-layout">
+            <div className="t1">未购买</div>
+            <div className="desc">¥ {service && service.package && service.package[0].price}</div>
+            <Button radius size="lager" width={150}>
+              立即购买
+            </Button>
+          </div>
+        )}
+        {!data.hasService && data.unUseRecord && (
+          <div className="tip-layout">
+            <div className="t2">请于{formatDate(data.unUseRecord.endTime, 'YYYY-MM-DD')}前开通</div>
+            <Button
+              radius
+              size="lager"
+              width={150}
+              onClick={() => {
+                this.open(data.unUseRecord.id);
+              }}
+            >
+              立即开通
+            </Button>
+          </div>
+        )}
+        {data.hasService && (
+          <div className="tip-layout">
+            <div className="t1">使用中</div>
+            <div className="t2">距离到期还有 {data.expireDay} 天</div>
+          </div>
+        )}
+        {!data.hasService && !data.unUseRecord && data.expireTime && (
+          <div className="tip-layout">
+            <div className="t3">已过期</div>
+            <div className="date">
+              {formatDate(data.startTime, 'YYYY-MM-DD')} ~ {formatDate(data.expireTime, 'YYYY-MM-DD')}
+            </div>
+            <div className="desc">¥ {service && service.package && service.package[0].price}</div>
+            <Button radius size="lager" width={150}>
+              立即购买
+            </Button>
+          </div>
+        )}
       </div>
     );
   }
@@ -521,26 +692,34 @@ export default class extends Page {
     const { data } = this.state;
     return (
       <div className="tab-4-layout">
-        {!data.hasService && !data.unUseRecord && !data.expireTime && <div className="tip-layout">
-          <div className="t2">未购买</div>
-          <Button radius size="lager" width={150}>
-            立即购买
-          </Button>
-        </div>}
-        {data.hasService && <div className="tip-layout">
-          <div className="t1">使用中</div>
-          <div className="desc">{formatDate(data.expireTime, 'YYYY-MM-DD')} 到期</div>
-          <Button radius size="lager" width={150}>
-            续费
-          </Button>
-        </div>}
-        {!data.hasService && !data.unUseRecord && data.expireTime && <div className="tip-layout">
-          <div className="t1">已过期</div>
-          <div className="desc">{formatDate(data.startTime, 'YYYY-MM-DD')} ~ {formatDate(data.expireTime, 'YYYY-MM-DD')}</div>
-          <Button radius size="lager" width={150}>
-            立即购买
-          </Button>
-        </div>}
+        {!data.hasService && !data.unUseRecord && !data.expireTime && (
+          <div className="tip-layout">
+            <div className="t2">未购买</div>
+            <Button radius size="lager" width={150}>
+              立即购买
+            </Button>
+          </div>
+        )}
+        {data.hasService && (
+          <div className="tip-layout">
+            <div className="t1">使用中</div>
+            <div className="desc">{formatDate(data.expireTime, 'YYYY-MM-DD')} 到期</div>
+            <Button radius size="lager" width={150}>
+              续费
+            </Button>
+          </div>
+        )}
+        {!data.hasService && !data.unUseRecord && data.expireTime && (
+          <div className="tip-layout">
+            <div className="t1">已过期</div>
+            <div className="desc">
+              {formatDate(data.startTime, 'YYYY-MM-DD')} ~ {formatDate(data.expireTime, 'YYYY-MM-DD')}
+            </div>
+            <Button radius size="lager" width={150}>
+              立即购买
+            </Button>
+          </div>
+        )}
       </div>
     );
   }
@@ -551,7 +730,7 @@ export default class extends Page {
       <div className="tab-5-layout">
         <TotalSort
           value={data.value || 650}
-          onChange={(value) => {
+          onChange={value => {
             data.value = value;
             this.setState({ data });
           }}

+ 3 - 1
front/src/components/FileUpload/index.js

@@ -73,7 +73,7 @@ class FileUpload extends Component {
   }
 
   render() {
-    const { accept = [] } = this.props;
+    const { accept = [], onDragEnter, onDragLeave } = this.props;
     return (
       <div hidden={this.props.hidden} className={`file-upload type-${this.state.type}`} style={this.props.style}>
         <input
@@ -86,6 +86,8 @@ class FileUpload extends Component {
           multiple={false}
           accept={this.state.type === 'file' ? accept.join(',') : 'image/x-png,image/jpeg'}
           onChange={e => this.onChange(e)}
+          onDragEnter={onDragEnter}
+          onDragLeave={onDragLeave}
         />
         {this.state.type === 'image' ? (
           this.props.value && (!this.state.uploading && !this.props.uploading) ? (

+ 32 - 0
front/src/components/FileUpload/index.less

@@ -1,4 +1,32 @@
 @charset "utf-8";
+
+.file-upload.type-none {
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+  cursor: pointer;
+
+  input {
+    top: 0;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    opacity: 0;
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    cursor: pointer;
+    z-index: 1;
+  }
+
+  i {
+    font-size: 20px;
+    line-height: 100px;
+  }
+}
+
 .file-upload.type-image {
   border: 1px dashed #d9d9d9;
   width: 100px;
@@ -7,6 +35,7 @@
   text-align: center;
   display: inline-block;
   cursor: pointer;
+
   input {
     height: 100%;
     width: 100%;
@@ -15,6 +44,7 @@
     cursor: pointer;
     z-index: 1;
   }
+
   i {
     font-size: 20px;
     line-height: 100px;
@@ -24,6 +54,7 @@
 .file-upload.type-logo {
   position: relative;
   cursor: pointer;
+
   input {
     position: absolute;
     width: 150px;
@@ -39,6 +70,7 @@
   text-align: center;
   display: inline-block;
   cursor: pointer;
+
   input {
     height: 100%;
     width: 100%;