KaysonCui 5 年 前
コミット
ec7f504872

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

@@ -310,6 +310,10 @@
   color: #515258FF !important;
 }
 
+.t-15 {
+  color: #6E6E78FF !important;
+}
+
 .b-c-1 {
   background: #F7F7F7;
 }
@@ -370,6 +374,10 @@
   font-size: 32px;
 }
 
+.t-s-30 {
+  font-size: 30px;
+}
+
 .l-h-20 {
   line-height: 20px;
 }

+ 2 - 0
front/project/www/components/Header/index.less

@@ -92,6 +92,8 @@
   }
 }
 
+.ready #header,
+.question #header,
 .textbook #header,
 .main #header,
 .course #header {

+ 162 - 99
front/project/www/components/OtherModal/index.js

@@ -428,7 +428,7 @@ export class EditAvatar extends Component {
       };
     } else {
       const img = new Image();
-      img.onload = function () {
+      img.onload = function() {
         const canvas = document.createElement('canvas');
         canvas.height = img.height;
         canvas.width = img.width;
@@ -584,30 +584,51 @@ export class DownloadModal extends Component {
         <div className="download-modal-wrapper">
           <div className="t-2 t-s-18 m-b-1">请选择下载科目</div>
           <div className="m-b-1">
-            {quantVersion > 0 && <div className="t-2 t-s-16">
-              <Checkbox checked={checkMap.quant} onChange={() => {
-                checkMap.quant = !checkMap.quant;
-                this.setState({ checkMap });
-              }} />
-              <span className="m-l-5">数学</span>
-              <span className="t-8">(版本{quantVersion} 最后更新:{formatDate(data.quantTime, 'YYYY-MM-DD HH:mm:ss')})</span>
-            </div>}
-            {irVersion > 0 && <div className="t-2 t-s-16">
-              <Checkbox checked={checkMap.ir} onChange={() => {
-                checkMap.ir = !checkMap.ir;
-                this.setState({ checkMap });
-              }} />
-              <span className="m-l-5">逻辑</span>
-              <span className="t-8">(版本{irVersion} 最后更新:{formatDate(data.irTime, 'YYYY-MM-DD HH:mm:ss')})</span>
-            </div>}
-            {rcVersion > 0 && <div className="t-2 t-s-16">
-              <Checkbox checked={checkMap.rc} onChange={() => {
-                checkMap.rc = !checkMap.rc;
-                this.setState({ checkMap });
-              }} />
-              <span className="m-l-5">阅读</span>
-              <span className="t-8">(版本{rcVersion} 最后更新:{formatDate(data.rcTime, 'YYYY-MM-DD HH:mm:ss')})</span>
-            </div>}
+            {quantVersion > 0 && (
+              <div className="t-2 t-s-16">
+                <Checkbox
+                  checked={checkMap.quant}
+                  onChange={() => {
+                    checkMap.quant = !checkMap.quant;
+                    this.setState({ checkMap });
+                  }}
+                />
+                <span className="m-l-5">数学</span>
+                <span className="t-8">
+                  (版本{quantVersion} 最后更新:{formatDate(data.quantTime, 'YYYY-MM-DD HH:mm:ss')})
+                </span>
+              </div>
+            )}
+            {irVersion > 0 && (
+              <div className="t-2 t-s-16">
+                <Checkbox
+                  checked={checkMap.ir}
+                  onChange={() => {
+                    checkMap.ir = !checkMap.ir;
+                    this.setState({ checkMap });
+                  }}
+                />
+                <span className="m-l-5">逻辑</span>
+                <span className="t-8">
+                  (版本{irVersion} 最后更新:{formatDate(data.irTime, 'YYYY-MM-DD HH:mm:ss')})
+                </span>
+              </div>
+            )}
+            {rcVersion > 0 && (
+              <div className="t-2 t-s-16">
+                <Checkbox
+                  checked={checkMap.rc}
+                  onChange={() => {
+                    checkMap.rc = !checkMap.rc;
+                    this.setState({ checkMap });
+                  }}
+                />
+                <span className="m-l-5">阅读</span>
+                <span className="t-8">
+                  (版本{rcVersion} 最后更新:{formatDate(data.rcTime, 'YYYY-MM-DD HH:mm:ss')})
+                </span>
+              </div>
+            )}
           </div>
         </div>
       </Modal>
@@ -680,16 +701,12 @@ export class FeedbackErrorDataModal extends Component {
     const { onConfirm } = this.props;
     const { data } = this.state;
     if (!data.content || !data.originContent) return;
-    My.addFeedbackErrorData(
-      data.dataId,
-      data.title,
-      data.position.join(','),
-      data.originContent,
-      data.content,
-    ).then(() => {
-      if (onConfirm) onConfirm();
-      this.setState({ data: { position: ['', '', ''] } });
-    });
+    My.addFeedbackErrorData(data.dataId, data.title, data.position.join(','), data.originContent, data.content).then(
+      () => {
+        if (onConfirm) onConfirm();
+        this.setState({ data: { position: ['', '', ''] } });
+      },
+    );
   }
 
   onCancel() {
@@ -786,13 +803,7 @@ export class AskCourseModal extends Component {
     const { course, courseNo, onConfirm } = this.props;
     const { data } = this.state;
     if (!data.position || !data.originContent || !data.content) return;
-    My.addCourseAsk(
-      course.id,
-      courseNo.id,
-      data.position.join(','),
-      data.originContent,
-      data.content,
-    ).then(() => {
+    My.addCourseAsk(course.id, courseNo.id, data.position.join(','), data.originContent, data.content).then(() => {
       if (onConfirm) onConfirm();
       this.setState({ data: { position: [] } });
     });
@@ -818,10 +829,16 @@ export class AskCourseModal extends Component {
         onCancel={() => this.onCancel()}
       >
         <div className="t-2 m-b-1 t-s-16">
-          针对<span className="t-4">课时{courseNo.no}</span>的 <Select value={data.position} theme="white" list={selectList} onChange={(item) => {
-          data.position = item.key;
-          this.setState({ data });
-        }} />
+          针对<span className="t-4">课时{courseNo.no}</span>的{' '}
+          <Select
+            value={data.position}
+            theme="white"
+            list={selectList}
+            onChange={item => {
+              data.position = item.key;
+              this.setState({ data });
+            }}
+          />
           进行提问.
         </div>
         <div className="t-2 t-s-16">老师讲解的内容是:</div>
@@ -868,11 +885,7 @@ export class CourseNoteModal extends Component {
     const { course, onConfirm } = this.props;
     const { data } = this.state;
     if (!data.content) return;
-    My.updateCourseNote(
-      course.id,
-      data.courseNoId,
-      data.content,
-    ).then(() => {
+    My.updateCourseNote(course.id, data.courseNoId, data.content).then(() => {
       if (onConfirm) onConfirm();
       this.setState({ data: {} });
     });
@@ -898,18 +911,23 @@ export class CourseNoteModal extends Component {
       >
         <div className="t-2 m-b-1 t-s-16">
           {course.title}
-          <Select theme="white" value={data.courseNoId} list={courseNos.map(row => {
-            return {
-              title: `课时${row.no}`,
-              key: row.id,
-            };
-          })} onChange={(item) => {
-            if (data.courseNoId !== item.key) {
-              data.courseNoId = item.key;
-              data.content = noteMap[item.key] ? noteMap[item.key].content : '';
-            }
-            this.setState({ data });
-          }} />
+          <Select
+            theme="white"
+            value={data.courseNoId}
+            list={courseNos.map(row => {
+              return {
+                title: `课时${row.no}`,
+                key: row.id,
+              };
+            })}
+            onChange={item => {
+              if (data.courseNoId !== item.key) {
+                data.courseNoId = item.key;
+                data.content = noteMap[item.key] ? noteMap[item.key].content : '';
+              }
+              this.setState({ data });
+            }}
+          />
         </div>
         <textarea
           value={data.content}
@@ -960,36 +978,44 @@ export class TextbookFeedbackModal extends Component {
     const { show } = this.props;
     const { data } = this.state;
     return (
-      <Modal
-        show={show}
-        title="反馈"
-        width={630}
-        onConfirm={() => this.onConfirm()}
-        onCancel={() => this.onCancel()}
-      >
+      <Modal show={show} title="反馈" width={630} onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()}>
         <div className="t-2 t-s-16 m-b-1">
-          机经类别: <Select
+          机经类别:{' '}
+          <Select
             value={data.questionSubject}
             theme="white"
-            list={[{ title: '数学机经', key: 'quant' }, { title: '逻辑机经', key: 'rc' }, { title: '阅读机经', key: 'ir' }]}
-            onChange={(value) => {
+            list={[
+              { title: '数学机经', key: 'quant' },
+              { title: '逻辑机经', key: 'rc' },
+              { title: '阅读机经', key: 'ir' },
+            ]}
+            onChange={value => {
               data.questionSubject = value;
               this.setState({ data });
             }}
           />
-          反馈类型: <Select
+          反馈类型:{' '}
+          <Select
             value={data.target}
             theme="white"
             list={TextbookFeedbackTarget}
-            onChange={(value) => {
+            onChange={value => {
               data.target = value;
               this.setState({ data });
             }}
           />
-          <span hidden={data.target === 'new'}> 题号是 <input value={data.no} style={{ width: 80 }} className="m-l-1 b-c-1 t-c" onChange={e => {
-            data.no = e.target.value;
-            this.setState({ data });
-          }} />
+          <span hidden={data.target === 'new'}>
+            {' '}
+            题号是{' '}
+            <input
+              value={data.no}
+              style={{ width: 80 }}
+              className="m-l-1 b-c-1 t-c"
+              onChange={e => {
+                data.no = e.target.value;
+                this.setState({ data });
+              }}
+            />
           </span>
         </div>
         <div className="t-2 t-s-16">{TextbookFeedbackTargetMap[data.target]}:</div>
@@ -1035,12 +1061,7 @@ export class FaqModal extends Component {
     const { show } = this.props;
     const { data } = this.state;
     return (
-      <Modal
-        show={show}
-        title="咨询"
-        onConfirm={() => this.onConfirm()}
-        onCancel={() => this.onCancel()}
-      >
+      <Modal show={show} title="咨询" onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()}>
         <textarea
           value={data.content}
           className="b-c-1 w-10 p-10"
@@ -1083,12 +1104,7 @@ export class CommentModal extends Component {
     const { show } = this.props;
     const { data } = this.state;
     return (
-      <Modal
-        show={show}
-        title="评价"
-        onConfirm={() => this.onConfirm()}
-        onCancel={() => this.onCancel()}
-      >
+      <Modal show={show} title="评价" onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()}>
         <textarea
           value={data.content}
           className="b-c-1 w-10 p-10"
@@ -1109,17 +1125,64 @@ export class FinishModal extends Component {
   render() {
     const { show, onConfirm } = this.props;
     return (
-      <Modal
-        show={show}
-        title="提交成功"
-        confirmText="好的,知道了"
-        btnAlign="center"
-        onConfirm={() => onConfirm()}
-      >
+      <Modal show={show} title="提交成功" confirmText="好的,知道了" btnAlign="center" onConfirm={() => onConfirm()}>
         <div className="t-2 t-s-18">
           <Icon type="check" className="t-5 m-r-5" />
           您的每一次反馈都是千行进步的动力。
-      </div>
+        </div>
+      </Modal>
+    );
+  }
+}
+
+export class SuppleModal extends Component {
+  constructor(props) {
+    super(props);
+    this.state = { data: {} };
+  }
+
+  onConfirm() {
+    const { onConfirm } = this.props;
+    if (onConfirm) onConfirm();
+  }
+
+  onCancel() {
+    const { onCancel } = this.props;
+    if (onCancel) onCancel();
+    this.setState({ data: {} });
+  }
+
+  render() {
+    const { show } = this.props;
+    const { data } = this.state;
+    return (
+      <Modal show={show} title="考场信息" onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()}>
+        <div className="t-2 t-s-16">考场位置: 中国 上海 XXXXXXXXXXX</div>
+        <div className="t-2 t-s-16">补充内容:</div>
+        <textarea
+          value={data.content}
+          className="b-c-1 w-10 p-10"
+          rows={6}
+          onChange={e => {
+            data.content = e.target.value;
+            this.setState({ data });
+          }}
+        />
+        <div className="b-b m-t-2" />
+      </Modal>
+    );
+  }
+}
+
+export class SuppleFinishModal extends Component {
+  render() {
+    const { show, onConfirm } = this.props;
+    return (
+      <Modal show={show} title="提交成功" confirmText="好的,知道了" btnAlign="center" onConfirm={() => onConfirm()}>
+        <div className="t-2 t-s-18">
+          <Icon type="check" className="t-5 m-r-5" />
+          您的每一次反馈都是千行进步的动力。
+        </div>
       </Modal>
     );
   }

+ 24 - 1
front/project/www/routes/page/export/index.less

@@ -1,3 +1,26 @@
 @charset "utf-8";
 
-#export {}
+#export {
+  border-top: 20px solid #7775CAFF;
+
+  .content {
+    width: 1200px !important;
+  }
+
+  .head-layout {
+    padding: 30px 0;
+    background: #F7F8FCFF;
+  }
+
+  .detail-layout {
+    background: #fff;
+    padding-top: 20px;
+
+    .total-block {
+      border: 1px solid #E4E4E4FF;
+      height: 80px;
+      line-height: 80px;
+      border-radius: 4px;
+    }
+  }
+}

ファイルの差分が大きいため隠しています
+ 287 - 2
front/project/www/routes/page/export/page.js


+ 115 - 1
front/project/www/routes/page/ready/index.less

@@ -1,3 +1,117 @@
 @charset "utf-8";
 
-#ready {}
+#ready {
+  background: #fff;
+
+  .content {
+    padding-top: 50px;
+    width: 1140px !important;
+    position: relative;
+
+    .left {
+      position: absolute;
+
+      .ant-anchor-ink {
+        display: none;
+      }
+
+      .page-item {
+        position: relative;
+        padding-left: 30px;
+
+        .assets {
+          position: absolute;
+          left: 5px;
+          top: 4px;
+        }
+
+        .page-item-title {
+          padding: 5px 0;
+          color: #303036FF;
+          cursor: pointer;
+        }
+
+        .up {
+          display: none;
+        }
+
+        .down {
+          display: block;
+          transform: rotate(-90deg);
+        }
+      }
+
+      .page-item.active {
+        .up {
+          display: block;
+        }
+
+        .down {
+          display: none;
+        }
+
+        .page-item-title {
+          font-weight: 600;
+        }
+      }
+    }
+
+    .center {
+      padding-left: 300px;
+      padding-bottom: 400px;
+
+      word-wrap: break-word;
+      word-break: break-all;
+      overflow: hidden;
+
+
+      .query-layout {
+
+        .search-wrapper {
+          display: inline-block;
+          display: flex;
+          position: relative;
+          margin-bottom: 20px;
+
+          .select {
+            position: absolute;
+          }
+
+          input {
+            flex: 1;
+            width: 780px;
+            line-height: 18px;
+            padding: 18px 20px;
+            padding-left: 100px;
+            font-size: 16px;
+            color: #686872FF;
+            border-left: 1px solid #B9B9B9FF;
+            border-top: 1px solid #B9B9B9FF;
+            border-bottom: 1px solid #B9B9B9FF;
+          }
+
+          input:focus {
+            border-color: #4292F0;
+          }
+
+          .button {
+            line-height: 20px;
+            padding: 18px 20px;
+            font-size: 16px;
+            vertical-align: top;
+          }
+        }
+
+      }
+
+      .data-list {
+        margin: 0 10px;
+
+        .data-item {
+          margin: 10px;
+        }
+      }
+
+    }
+  }
+}

+ 268 - 1
front/project/www/routes/page/ready/page.js

@@ -1,9 +1,276 @@
 import React from 'react';
 import './index.less';
+import { Anchor, Icon } from 'antd';
+import Assets from '@src/components/Assets';
 import Page from '@src/containers/Page';
+import Select from '../../../components/Select';
+import Button from '../../../components/Button';
+import { SuppleModal, SuppleFinishModal } from '../../../components/OtherModal';
 
 export default class extends Page {
+  initState() {
+    return {
+      load: false,
+      list: [
+        {
+          key: '1',
+          title: '了解GMAT',
+          children: true,
+        },
+        { key: '2', title: '推荐阅读' },
+        { key: '3', title: '考场查询' },
+        { key: '4', title: '熟悉备考资料', children: true },
+      ],
+      current: '1',
+      scrollCurrent: '1-1',
+      result: [{}, {}, {}],
+      data: [
+        { key: '1', id: 'data1', title: '官方', children: [{}, {}, {}] },
+        { key: '2', id: 'data2', title: '非官方', children: [{}, {}, {}] },
+      ],
+      page: [
+        {
+          key: '1-1',
+          title: '考试功能',
+          id: '#test1',
+          content:
+            '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
+        },
+        {
+          key: '1-2',
+          title: '出题原理',
+          id: '#test2',
+          content:
+            '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
+        },
+        {
+          key: '1-3',
+          title: '出题原理',
+          id: '#test3',
+          content:
+            '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
+        },
+        {
+          key: '1-4',
+          title: '出题原理',
+          id: '#test4',
+          content:
+            '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
+        },
+        {
+          key: '1-5',
+          title: '出题原理',
+          id: '#test5',
+          content:
+            '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
+        },
+        {
+          key: '1-6',
+          title: '出题原理',
+          id: '#test6',
+          content:
+            '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
+        },
+        {
+          key: '1-7',
+          title: '出题原理',
+          id: '#test7',
+          content:
+            '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
+        },
+        {
+          key: '1-8',
+          title: '出题原理',
+          id: '#test8',
+          content:
+            '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
+        },
+        {
+          key: '1-9',
+          title: '出题原理',
+          id: '#test9',
+          content:
+            '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
+        },
+        {
+          key: '1-10',
+          title: '出题原理',
+          id: '#test10',
+          content:
+            '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
+        },
+        {
+          key: '1-11',
+          title: '出题原理',
+          id: '#test11',
+          content:
+            '11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
+        },
+      ],
+    };
+  }
+
+  initData() {
+    this.initInfo();
+  }
+
+  initInfo() {
+    this.load = false;
+    try {
+      const { page, current, data } = this.state;
+      const _list = current === '4' ? data : page;
+      _list.forEach(item => {
+        item.top = document.getElementById(item.id).offsetTop - 100;
+        return item;
+      });
+      this.load = true;
+    } catch (e) {
+      setTimeout(() => {
+        this.initInfo();
+      }, 500);
+    }
+  }
+
+  inPage() {
+    document.getElementById('root').addEventListener('scroll', e => {
+      if (!this.load) return;
+      this.onScroll(e);
+    });
+  }
+
+  outPage() {
+    document.getElementById('root').removeEventListener('scroll');
+  }
+
+  onScroll(e) {
+    const t = e.target.scrollTop;
+    const { page, data, current, scrollCurrent } = this.state;
+    const _list = current === '4' ? data : page;
+    let _current = null;
+    for (let i = 0; i < _list.length; i += 1) {
+      if (!_current) _current = _list[i].key;
+      if (t < _list[i].top) break;
+      _current = _list[i].key;
+    }
+    if (_current !== scrollCurrent) {
+      this.setState({ scrollCurrent: _current });
+    }
+  }
+
+  scrollTo(top) {
+    document.getElementById('root').scrollTo({ top, behavior: 'smooth' });
+  }
+
+  changePage(key) {
+    this.setState({ current: key });
+    setTimeout(() => {
+      this.initInfo();
+    }, 1);
+  }
+
   renderView() {
-    return <div>1</div>;
+    const { list, current, scrollCurrent, page, data } = this.state;
+    let detail = {};
+    return (
+      <div>
+        <div className="content">
+          <div className="left">
+            <Anchor offsetTop={90} getContainer={() => document.getElementById('root')}>
+              {list.map(item => {
+                if (item.key === current) detail = item;
+                const _list = item.key === '4' ? data : page;
+                return (
+                  <div
+                    className={`page-item ${item.key === current ? 'active' : ''}`}
+                    onClick={() => this.changePage(item.key)}
+                  >
+                    {item.children && <Assets name="dropdown_hover" className="up" />}
+                    {item.children && <Assets name="dropdown_normal" className="down" />}
+                    <div className="page-item-title">{item.title}</div>
+                    {current === item.key &&
+                      item.children &&
+                      _list.map(child => {
+                        return (
+                          <div
+                            style={{ margin: 3 }}
+                            className={`t-s-12 t-2 c-p ${child.key === scrollCurrent ? 't-4' : ''}`}
+                            onClick={() => this.scrollTo(child.top)}
+                            title={child.title}
+                          >
+                            {child.title}
+                          </div>
+                        );
+                      })}
+                  </div>
+                );
+              })}
+            </Anchor>
+          </div>
+          <div className="center">
+            <div className="t-1 t-s-24 m-b-2">{detail.title}</div>
+            {current !== '3' && current !== '4' && this.renderList()}
+            {current === '3' && this.renderQuery()}
+            {current === '4' && this.renderData()}
+          </div>
+        </div>
+      </div>
+    );
+  }
+
+  renderQuery() {
+    const { result } = this.state;
+    return (
+      <div className="query-layout">
+        <div className="search-wrapper">
+          <Select theme="white" list={[{ title: '中国', key: '1' }, { title: '海外', key: '2' }]} />
+          <input />
+          <Button width={150}>
+            <Icon className="m-r-5" type="search" />
+            搜索题目
+          </Button>
+        </div>
+        {result.map(() => {
+          return (
+            <div className="m-b-2">
+              <div className="t-1 t-s-18">1.上海财经大学</div>
+              <div className="t-1">上海市徐汇区天钥桥路333号腾飞大厦8层805室</div>
+              <div className="t-1">
+                温馨提示: 本考场提供听力耳机 <span className="t-4">我要补充</span>
+              </div>
+            </div>
+          );
+        })}
+        <SuppleModal />
+        <SuppleFinishModal />
+      </div>
+    );
+  }
+
+  renderData() {
+    const { data } = this.state;
+    return data.map(item => {
+      return (
+        <div className="p-t-1 m-b-2" id={item.id}>
+          <div className="t-1 t-s-18 m-b-1">{item.title}</div>
+          <div className="data-list">
+            {item.children.map(child => {
+              return <Assets width={240} height={310} src={child} className="data-item" />;
+            })}
+          </div>
+        </div>
+      );
+    });
+  }
+
+  renderList() {
+    const { page } = this.state;
+    return page.map(item => {
+      return (
+        <div className="p-t-1 m-b-2" id={item.id}>
+          <div className="t-1 t-s-18 m-b-1">{item.title}</div>
+          <div className="t-2">{item.content}</div>
+        </div>
+      );
+    });
   }
 }

+ 1 - 1
front/project/www/routes/question/search/index.js

@@ -1,5 +1,5 @@
 export default {
-  path: '/question/search',
+  path: '/question',
   key: 'question-search',
   title: '题库搜索',
   needLogin: false,

+ 97 - 1
front/project/www/routes/question/search/index.less

@@ -1,3 +1,99 @@
 @charset "utf-8";
 
-#question-search {}
+#question-search {
+  background: #fff;
+  min-height: 100%;
+
+  .content {
+    width: 1140px !important;
+  }
+
+  .search-layout {
+    background: #DDE2E9FF;
+    padding: 62px 0;
+    text-align: center;
+
+    .search-wrapper {
+      display: inline-block;
+      position: relative;
+
+      .search-tip-wrapper {
+        position: absolute;
+        top: 56px;
+        width: 780px;
+        max-height: 200px;
+        overflow-y: auto;
+        background: rgba(255, 255, 255, 1);
+        box-shadow: 0px 3px 2px 0px rgba(0, 0, 0, 0.08);
+        border: 1px solid rgba(185, 185, 185, 1);
+        z-index: 1;
+
+        >div {
+          line-height: 40px;
+          height: 40px;
+          padding: 0 10px;
+          text-align: left;
+        }
+
+        >div:hover {
+          background: #f2f2f2;
+        }
+
+        .all-del {
+          height: 30px;
+          line-height: 30px;
+          background: #F9F9F9FF;
+          text-align: right;
+        }
+
+        .all-del:hover {
+          background: #F9F9F9FF;
+        }
+      }
+
+      input {
+        width: 780px;
+        line-height: 18px;
+        padding: 18px 20px;
+        font-size: 16px;
+        color: #686872FF;
+        border-left: 1px solid #B9B9B9FF;
+        border-top: 1px solid #B9B9B9FF;
+        border-bottom: 1px solid #B9B9B9FF;
+      }
+
+      input:focus {
+        border-color: #4292F0;
+      }
+
+      .button {
+        line-height: 20px;
+        padding: 18px 20px;
+        font-size: 16px;
+        vertical-align: top;
+      }
+    }
+  }
+
+  .filter-layout {
+    padding-top: 30px;
+    background: #fff;
+  }
+
+  .result-layout {
+    padding-top: 40px;
+    background: #fff;
+  }
+
+  .search-item {
+    margin-bottom: 20px;
+    background: #FAFAFAFF;
+
+    .search-item-head {
+      padding: 15px 20px;
+      line-height: 20px;
+      height: 50px;
+      border-bottom: 1px solid #eee;
+    }
+  }
+}

+ 186 - 2
front/project/www/routes/question/search/page.js

@@ -1,9 +1,193 @@
-import React from 'react';
+import React, { Component } from 'react';
 import './index.less';
+import { Icon } from 'antd';
 import Page from '@src/containers/Page';
+import Button from '../../../components/Button';
+import Tabs from '../../../components/Tabs';
+import UserAction from '../../../components/UserAction';
+import UserPagination from '../../../components/UserPagination';
 
 export default class extends Page {
+  initState() {
+    return {
+      list: [{}, {}, {}],
+      searchList: [123, 123, 123],
+      historyList: [321, 321, 321],
+      searchValue: '',
+      search: false,
+      tab: '1',
+      filterMap: {},
+      sortMap: {},
+      focus: false,
+    };
+  }
+
+  onTabChange(tab) {
+    this.setState({ tab });
+  }
+
+  onChangeSearch(value) {
+    this.setState({ searchValue: value });
+  }
+
   renderView() {
-    return <div>1</div>;
+    const { search } = this.state;
+    return (
+      <div>
+        {this.renderSearch()}
+        {search ? this.renderResult() : this.renderFilter()}
+      </div>
+    );
+  }
+
+  renderSearch() {
+    const { searchList, searchValue, historyList, focus } = this.state;
+    return (
+      <div className="search-layout">
+        <div className="search-wrapper">
+          <input
+            value={searchValue}
+            onChange={e => this.onChangeSearch(e.target.value)}
+            onFocus={() => this.setState({ focus: true })}
+            onBlur={() => this.setState({ focus: false })}
+          />
+          <Button width={150}>
+            <Icon className="m-r-5" type="search" />
+            搜索题目
+          </Button>
+          {focus && (
+            <div hidden={!searchValue} className="search-tip-wrapper">
+              {searchList.map(item => {
+                return <div className="t-2 t-s-16">{item}</div>;
+              })}
+            </div>
+          )}
+          {focus && (
+            <div hidden={searchValue} className="search-tip-wrapper">
+              {historyList.map(item => {
+                return (
+                  <div className="t-2 t-s-16">
+                    {item}
+                    <div className="f-r t-4 t-s-12 c-p">删除</div>
+                  </div>
+                );
+              })}
+              <div className="all-del t-r">
+                <span className="t-4 t-s-12 c-p">删除历史</span>
+              </div>
+            </div>
+          )}
+        </div>
+      </div>
+    );
+  }
+
+  renderFilter() {
+    const { tab, filterMap, sortMap } = this.state;
+    return (
+      <div className="filter-layout">
+        <div className="content">
+          <Tabs
+            border
+            type="division"
+            theme="theme"
+            size="small"
+            space={5}
+            width={220}
+            active={tab}
+            tabs={[{ key: '1', title: 'Verval' }, { key: '2', title: 'Quant' }, { key: '3', title: 'IR' }]}
+            onChange={key => this.onTabChange(key)}
+          />
+          <UserAction
+            selectList={[
+              {
+                key: 'questionType',
+                placeholder: '题型',
+                select: [],
+              },
+              {
+                label: '范围',
+                children: [
+                  {
+                    key: 'rang1',
+                    placeholder: '全部',
+                    select: [],
+                  },
+                  {
+                    placeholder: '全部',
+                    key: 'rang2',
+                    be: 'rang1',
+                    selectMap: {},
+                  },
+                ],
+              },
+              {
+                right: true,
+                placeholder: '难度',
+                key: 'level',
+                select: [],
+              },
+            ]}
+            sortList={[
+              { key: '1', label: '全站用时', fixed: true, right: true },
+              { key: '2', label: '平均正确率', fixed: true, right: true },
+              { key: '3', label: '收藏人数', fixed: true, right: true },
+            ]}
+            filterMap={filterMap}
+            sortMap={sortMap}
+            onFilter={value => this.onFilter(value)}
+          />
+          {this.renderList()}
+          <UserPagination />
+        </div>
+      </div>
+    );
+  }
+
+  renderResult() {
+    return (
+      <div className="result-layout">
+        <div className="content">
+          <div className="m-b-1">
+            <span className="t-1 t-s-24">搜索结果:</span>
+            <span className="t-2 t-s-18">共12条</span>
+          </div>
+          {this.renderList()}
+          <UserPagination jump />
+        </div>
+      </div>
+    );
+  }
+
+  renderList() {
+    const { list } = this.state;
+    return list.map(item => {
+      return <SearchItem data={item} />;
+    });
+  }
+}
+
+class SearchItem extends Component {
+  render() {
+    return (
+      <div className="search-item">
+        <div className="search-item-head">
+          <span className="t-15 t-s-16 m-r-1">阅读RC</span>
+          <span className="t-1 t-s-16">PREP07#124、PREP08#332、PREP07#124、PREP08#332、PREP07#124</span>
+          <div className="f-r t-15 t-s-14">
+            <span className="m-r-1">Medium</span>
+            <span className="m-r-1">用时: 1m 39s</span>
+            <span className="m-r-1">80% </span>
+            <span>收藏 20313</span>
+          </div>
+        </div>
+        <div className="t-1 p-20">
+          Margaret Mead, the best-known anthropologist of the twentieth century, helped shape public opinion on
+          fundamentally important areas like attitudes toward children and families, along with the relative merits of
+          competition and cooperation. A. shape public opinion on fundamentally important areas like attitudes toward
+          children and families, along with
+        </div>
+      </div>
+    );
   }
 }

+ 3 - 3
front/project/www/routes/question/searchHistory/index.js

@@ -1,8 +1,8 @@
 export default {
-  path: '/question/search',
-  key: 'question-search',
+  path: '/question/search/history',
+  key: 'question-search-history',
   title: '题库搜索历史',
-  needLogin: true,
+  needLogin: false,
   repeat: true,
   tab: 'question',
   component() {

+ 41 - 1
front/project/www/routes/question/searchHistory/index.less

@@ -1,3 +1,43 @@
 @charset "utf-8";
 
-#question-search {}
+#question-search-history {
+  background: #fff;
+  min-height: 100%;
+
+  .content {
+    width: 1140px !important;
+  }
+
+  .top {
+    padding: 8px 0;
+    height: 60px;
+    line-height: 44px;
+  }
+
+  .center {
+    padding-top: 20px;
+
+    .day-list {
+      margin-bottom: 20px;
+
+      .assets {
+        transform: translateY(-1px);
+      }
+
+      .log-item {
+        border-bottom: 1px solid #eee;
+        line-height: 24px;
+        padding: 18px 0;
+
+        .tag {
+          border: 1px solid #DEDEDEFF;
+          border-radius: 3px;
+          color: #DEDEDEFF;
+          display: inline-block;
+          line-height: 12px;
+          padding: 6px 20px;
+        }
+      }
+    }
+  }
+}

+ 54 - 2
front/project/www/routes/question/searchHistory/page.js

@@ -1,9 +1,61 @@
-import React from 'react';
+import React, { Component } from 'react';
 import './index.less';
 import Page from '@src/containers/Page';
+import Assets from '@src/components/Assets';
 
 export default class extends Page {
+  initState() {
+    return {
+      list: [[{}, {}, {}], [{}, {}, {}], [{}, {}, {}]],
+    };
+  }
+
   renderView() {
-    return <div>1</div>;
+    const { list } = this.state;
+    return (
+      <div>
+        <div className="top content t-8">
+          题库 > <span className="t-1">浏览记录</span>
+        </div>
+        <div className="center content">
+          {list.map(item => {
+            return <DayList list={item} />;
+          })}
+        </div>
+      </div>
+    );
+  }
+}
+
+class DayList extends Component {
+  render() {
+    const { list = [] } = this.props;
+    return (
+      <div className="day-list">
+        <div className="m-b-1">
+          <span className="t-1 t-s-18 m-r-1 f-w-b">2019-03-23</span>
+          <span className="c-p t-2 t-s-12">
+            <Assets name="ico_24_restart" svg /> 清空记录
+          </span>
+        </div>
+        {list.map(item => {
+          return <LogItem data={item} />;
+        })}
+      </div>
+    );
+  }
+}
+
+class LogItem extends Component {
+  render() {
+    return (
+      <div className="log-item">
+        <span className="t-6 m-r-1 tag">阅读SC</span>
+        <span className="t-1 m-r-2 f-w-b">OG 19 #678</span>
+        <span className="p-l-1 t-2">
+          GMAT考试由分析写作、推理、数学和语文四部分组成。分别为: a)分析性写作评价(Analytical Writing Assessment)
+        </span>
+      </div>
+    );
   }
 }

+ 1 - 1
front/src/components/Assets/index.js

@@ -3,7 +3,7 @@ import './index.less';
 
 function Assets(props) {
   const { name, src, className = '', svg, width, height, onClick } = props;
-  if (!name && !src) return <img />;
+  if (!name && !src) return <img style={{ width, height }} className={`${className}`} />;
   return (
     <img
       style={{ width, height }}

+ 1 - 1
front/src/stores/core.js

@@ -58,7 +58,7 @@ export default class CoreStore extends Base {
   }
 
   locationChange(location, action) {
-    console.log(location, action);
+    if (location.hash) return;
     if (action === 'POP') {
       this.locationPop(location);
     } else if (action === 'REPLACE') {