ソースを参照

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

Go 5 年 前
コミット
5ac2c0e570

+ 129 - 13
front/project/www/components/Input/index.js

@@ -1,16 +1,132 @@
-import React from 'react';
+import React, { Component } from 'react';
 import './index.less';
+import { Icon } from 'antd';
 
-function Input(props) {
-  const { className = '', size = 'basic', placeholder, disabled, radius, width, onChange } = props;
-  return (
-    <div
-      style={{ width: width || '' }}
-      className={`input ${className} ${size} ${disabled ? 'disabled' : ''}  ${radius ? 'radius' : ''}`}
-    >
-      <input placeholder={placeholder} disabled={disabled} onChange={() => onChange && onChange()} />
-    </div>
-  );
+export function Input(props) {
+  const { className = '', value, onChange, placeholder, empty } = props;
+  return <input className={`${className} ${empty} ? 'empty' : ''`} value={value} placeholder={placeholder} onChange={data => onChange && onChange(data)} />;
+}
+
+export function Textarea(props) {
+  const { className = '', value, onChange, placeholder, empty } = props;
+  return <textarea className={`${className} ${empty} ? 'empty' : ''`} value={value} placeholder={placeholder} onChange={data => onChange && onChange(data)} />;
+}
+
+export class DefaultInput extends Component {
+  render() {
+    const { className = '', onChange, placeholder, value, error, left, right, empty } = this.props;
+    return (
+      <div className={`g-input-container ${className}`}>
+        <div className={`g-input-wrapper ${error ? 'error' : ''}`}>
+          {left && <div className="g-input-left">{left}</div>}
+          <Input
+            className="g-input"
+            placeholder={placeholder}
+            value={value}
+            empty={empty}
+            onChange={data => onChange && onChange(data)}
+          />
+          {right && <div className="g-input-right">{right}</div>}
+        </div>
+        <div hidden={!error} className="g-input-error">
+          {error}
+        </div>
+      </div>
+    );
+  }
+}
+
+export class SelectInput extends Component {
+  constructor(props) {
+    super(props);
+    this.state = { showSelect: false };
+  }
+
+  render() {
+    const { showSelect } = this.state;
+    const { className = '', onChange, placeholder, value, error, empty, selectValue, select, onSelect } = this.props;
+    return (
+      <DefaultInput
+        className={className}
+        left={
+          <span className="g-input-left-select" onClick={() => this.setState({ showSelect: !showSelect })}>
+            {selectValue}
+            <Icon type={showSelect ? 'up' : 'down'} />
+            {showSelect && (
+              <ul className="select-list">
+                {select.map(row => {
+                  return (
+                    <li
+                      onClick={() => {
+                        this.setState({ showSelect: false });
+                        if (onSelect) onSelect(row.value);
+                      }}
+                    >
+                      {row.label}
+                    </li>
+                  );
+                })}
+              </ul>
+            )}
+          </span>
+        }
+        value={value}
+        placeholder={placeholder}
+        onChange={data => onChange && onChange(data)}
+        error={error}
+        empty={empty}
+      />
+    );
+  }
+}
+
+export class VerificationInput extends Component {
+  constructor(props) {
+    super(props);
+    this.timeKey = null;
+    this.state = { loading: 0 };
+  }
+
+  componentWillUnmount() {
+    if (this.timeKey) clearTimeout(this.timeKey);
+  }
+
+  onSend() {
+    const { onSend, time = 60 } = this.props;
+    if (onSend) {
+      onSend().then(() => {
+        if (this.timeKey) clearTimeout(this.timeKey);
+        this.setTime(time);
+      });
+    }
+  }
+
+  setTime(time) {
+    this.setState({ loading: time });
+    this.timeKey = setTimeout(() => {
+      this.setTime(time - 1);
+    }, 1000);
+  }
+
+  render() {
+    const { loading } = this.state;
+    const { className = '', onChange, placeholder, value, error, empty } = this.props;
+    return (
+      <DefaultInput
+        className={className}
+        right={
+          loading <= 0 ? (
+            <span className="g-input-right-verification" onClick={() => this.onSend()}>
+              获取验证码
+            </span>
+          ) : (<span className="g-input-right-verification-loading">等待{loading}秒</span>)
+        }
+        value={value}
+        error={error}
+        empty={empty}
+        placeholder={placeholder}
+        onChange={data => onChange && onChange(data)}
+      />
+    );
+  }
 }
-Input.propTypes = {};
-export default Input;

+ 150 - 48
front/project/www/components/Input/index.less

@@ -1,76 +1,178 @@
 @import '../../app.less';
 
-.input {
-  display: inline-block;
-  vertical-align: middle;
-  border-radius: 2px;
-
-  input {
-    width: 100%;
-    border: solid 1px rgba(0, 0, 0, 0.1);
-    background: @theme_bg_color;
+.login-modal {
+  .title {
+    font-size: 26px;
+    color: #303036;
+    margin-bottom: 20px;
+    font-weight: 600;
   }
 
-  input:hover {
-    border-color: @theme_color;
-  }
+  .tip {
+    color: #686872;
+    font-size: 12px;
+    margin-bottom: 10px;
+    transform: translateY(-5px);
 
-  input:focus {
-    border-color: @theme_color;
-    background: darken(@theme_bg_color, 2);
+    .assets {
+      margin-right: 3px;
+      transform: translateY(-1px);
+    }
   }
-}
 
-.input.basic {
 
-  input {
-    padding: 4px 15px;
-    line-height: 30px;
-    font-size: 20px;
+  .qr-code {
+    text-align: center;
+
+    .assets {
+      margin-bottom: 10px;
+    }
+
+    .text {
+      margin-bottom: 50px;
+    }
+
+    .jump {
+      display: inline-block;
+      color: #A7A7B7;
+      cursor: pointer;
+      margin-bottom: 10px;
+    }
   }
-}
 
-.input.small {
+  .btn {
+    text-align: center;
+    padding-top: 60px;
+    padding-bottom: 10px;
+
+    .button {
+      width: 150px;
+      height: 45px;
+      line-height: 45px;
+      padding: 0;
+      border-radius: 25px;
+      font-size: 16px;
+    }
+  }
 
-  input {
-    line-height: 18px;
-    font-size: 12px;
-    padding: 2px 8px;
+  .icon.close {
+    position: absolute;
+    top: 15px;
+    right: 15px;
+  }
+
+  .other {
+    position: absolute;
+    bottom: 0;
+    right: 0;
+    width: 40px;
+    height: 80px;
+    cursor: pointer;
+
+    .assets {
+      width: 80px;
+      height: 80px;
+      max-height: none;
+      max-width: none;
+      transform: translateX(-50%);
+    }
   }
 }
 
-.input.lager {
 
-  input {
-    font-size: 18px;
+
+.g-input-container {
+
+  .g-input-wrapper {
+    display: flex;
+    background: #F7F7F7;
+    height: 44px;
+    padding: 8px 0;
     line-height: 28px;
-    padding: 7px 20px;
+    margin-bottom: 25px;
+
+    .g-input {
+      flex: 1;
+      background: transparent;
+      border: none;
+      padding: 10px 20px;
+      height: 28px;
+    }
+
+    .g-input-left {
+      position: relative;
+      cursor: pointer;
+
+      .g-input-left-select {
+        height: 28px;
+        border-right: 1px solid #eee;
+        padding-left: 10px;
+
+        i {
+          margin-left: 5px;
+          font-size: 10px;
+          margin-right: 10px;
+        }
+      }
+    }
+
+    .g-input-right {
+      padding: 0 20px;
+      cursor: pointer;
+
+      .g-input-right-verification {
+        color: #41A6F3;
+      }
+
+      .g-input-right-verification.loading {
+        color: #A7A7B7;
+      }
+    }
   }
-}
 
-.input.disabled {
-  cursor: no-drop;
-}
+  .g-input-wrapper.error {
+    margin-bottom: 0;
+  }
 
-.input.basic.radius {
-  border-radius: 17px;
+  .g-input-error {
+    color: #FF562E;
+    font-size: 12px;
+    height: 25px;
+    line-height: 25px;
+  }
+
+  .select-list {
+    top: 36px;
+    width: 61px;
+    border: 1px solid #EAEDF2;
+    max-height: 200px;
+    overflow-y: auto;
+    list-style: none;
+    margin: 0;
+    padding: 5px 10px;
+    position: absolute;
+    background: #fff;
+  }
 }
 
-.input.small.radius {
-  border-radius: 14px;
+.LOGIN_PHONE .body {
+  padding-bottom: 120px;
 }
 
-.input.lager.radius {
-  border-radius: 36px;
+.REGISTER_PHONE .body {
+  padding-bottom: 80px;
 }
 
-.input.default {
-  background: #fff;
-  color: @holder_color;
-  border: 1px solid @holder_color;
+.LOGIN_WX .body {
+  .qr-code {
+    padding-top: 20px;
+    padding-bottom: 10px;
+  }
 }
 
-.button.default:hover {
-  color: @theme_color;
-  border-color: @theme_color;
+.BIND_WX .body {
+  .qr-code {
+    padding-top: 20px;
+    padding-bottom: 10px;
+  }
 }

+ 16 - 0
front/project/www/components/InputItem/index.js

@@ -0,0 +1,16 @@
+import React from 'react';
+import './index.less';
+
+function InputItem(props) {
+  const { className = '', size = 'basic', placeholder, disabled, radius, width, onChange } = props;
+  return (
+    <div
+      style={{ width: width || '' }}
+      className={`input ${className} ${size} ${disabled ? 'disabled' : ''}  ${radius ? 'radius' : ''}`}
+    >
+      <input placeholder={placeholder} disabled={disabled} onChange={() => onChange && onChange()} />
+    </div>
+  );
+}
+InputItem.propTypes = {};
+export default InputItem;

+ 76 - 0
front/project/www/components/InputItem/index.less

@@ -0,0 +1,76 @@
+@import '../../app.less';
+
+.input {
+  display: inline-block;
+  vertical-align: middle;
+  border-radius: 2px;
+
+  input {
+    width: 100%;
+    border: solid 1px rgba(0, 0, 0, 0.1);
+    background: @theme_bg_color;
+  }
+
+  input:hover {
+    border-color: @theme_color;
+  }
+
+  input:focus {
+    border-color: @theme_color;
+    background: darken(@theme_bg_color, 2);
+  }
+}
+
+.input.basic {
+
+  input {
+    padding: 4px 15px;
+    line-height: 30px;
+    font-size: 20px;
+  }
+}
+
+.input.small {
+
+  input {
+    line-height: 18px;
+    font-size: 12px;
+    padding: 2px 8px;
+  }
+}
+
+.input.lager {
+
+  input {
+    font-size: 18px;
+    line-height: 28px;
+    padding: 7px 20px;
+  }
+}
+
+.input.disabled {
+  cursor: no-drop;
+}
+
+.input.basic.radius {
+  border-radius: 17px;
+}
+
+.input.small.radius {
+  border-radius: 14px;
+}
+
+.input.lager.radius {
+  border-radius: 36px;
+}
+
+.input.default {
+  background: #fff;
+  color: @holder_color;
+  border: 1px solid @holder_color;
+}
+
+.button.default:hover {
+  color: @theme_color;
+  border-color: @theme_color;
+}

+ 2 - 2
front/project/www/components/Invite/index.js

@@ -5,7 +5,7 @@ import Assets from '@src/components/Assets';
 import { asyncSMessage } from '@src/services/AsyncTools';
 import { Icon } from 'antd';
 import Button from '../Button';
-import { Input } from '../Login';
+import { DefaultInput } from '../Input';
 import { Main } from '../../stores/main';
 import { My } from '../../stores/my';
 import { PcUrl, H5Url } from '../../../Constant';
@@ -63,7 +63,7 @@ export default class Invite extends Component {
       </div>
         <div className="input-layout">
           <div className="input-block">
-            <Input
+            <DefaultInput
               placeholder="输入多个邮箱,用';'隔开"
               value={this.state.data.emails || ''}
               error={this.state.error}

+ 4 - 121
front/project/www/components/Login/index.js

@@ -1,6 +1,6 @@
 import React, { Component } from 'react';
 import './index.less';
-import { Modal, Icon, Button, Tooltip } from 'antd';
+import { Modal, Button, Tooltip } from 'antd';
 import Assets from '@src/components/Assets';
 import { asyncSMessage } from '@src/services/AsyncTools';
 import { Icon as GIcon } from '../Icon';
@@ -10,6 +10,7 @@ import { User } from '../../stores/user';
 import { Common } from '../../stores/common';
 import { Main } from '../../stores/main';
 import { MobileArea, WechatPcAppId, PcUrl } from '../../../Constant';
+import { DefaultInput, SelectInput, VerificationInput } from '../Input';
 
 const LOGIN_PHONE = 'LOGIN_PHONE';
 const LOGIN_WX = 'LOGIN_WX';
@@ -314,7 +315,7 @@ export default class Login extends Component {
           }}
         />
         {needEmail && (
-          <Input
+          <DefaultInput
             placeholder="请输入邮箱"
             value={this.state.data.email}
             empty={emptyError.email}
@@ -430,7 +431,7 @@ export default class Login extends Component {
           }}
         />
         {needEmail && (
-          <Input
+          <DefaultInput
             placeholder="请输入邮箱"
             value={this.state.data.email}
             empty={emptyError.email}
@@ -525,121 +526,3 @@ export default class Login extends Component {
     );
   }
 }
-
-export class Input extends Component {
-  render() {
-    const { className = '', onChange, placeholder, value, error, left, right, empty } = this.props;
-    return (
-      <div className={`g-input-container ${className}`}>
-        <div className={`g-input-wrapper ${error ? 'error' : ''}`}>
-          {left && <div className="g-input-left">{left}</div>}
-          <input
-            className={`g-input ${empty ? 'empty' : ''}`}
-            placeholder={placeholder}
-            value={value}
-            onChange={data => onChange && onChange(data)}
-          />
-          {right && <div className="g-input-right">{right}</div>}
-        </div>
-        <div hidden={!error} className="g-input-error">
-          {error}
-        </div>
-      </div>
-    );
-  }
-}
-
-export class SelectInput extends Component {
-  constructor(props) {
-    super(props);
-    this.state = { showSelect: false };
-  }
-
-  render() {
-    const { showSelect } = this.state;
-    const { className = '', onChange, placeholder, value, error, empty, selectValue, select, onSelect } = this.props;
-    return (
-      <Input
-        className={className}
-        left={
-          <span className="g-input-left-select" onClick={() => this.setState({ showSelect: !showSelect })}>
-            {selectValue}
-            <Icon type={showSelect ? 'up' : 'down'} />
-            {showSelect && (
-              <ul className="select-list">
-                {select.map(row => {
-                  return (
-                    <li
-                      onClick={() => {
-                        this.setState({ showSelect: false });
-                        if (onSelect) onSelect(row.value);
-                      }}
-                    >
-                      {row.label}
-                    </li>
-                  );
-                })}
-              </ul>
-            )}
-          </span>
-        }
-        value={value}
-        placeholder={placeholder}
-        onChange={data => onChange && onChange(data)}
-        error={error}
-        empty={empty}
-      />
-    );
-  }
-}
-
-export class VerificationInput extends Component {
-  constructor(props) {
-    super(props);
-    this.timeKey = null;
-    this.state = { loading: 0 };
-  }
-
-  componentWillUnmount() {
-    if (this.timeKey) clearTimeout(this.timeKey);
-  }
-
-  onSend() {
-    const { onSend, time = 60 } = this.props;
-    if (onSend) {
-      onSend().then(() => {
-        if (this.timeKey) clearTimeout(this.timeKey);
-        this.setTime(time);
-      });
-    }
-  }
-
-  setTime(time) {
-    this.setState({ loading: time });
-    this.timeKey = setTimeout(() => {
-      this.setTime(time - 1);
-    }, 1000);
-  }
-
-  render() {
-    const { loading } = this.state;
-    const { className = '', onChange, placeholder, value, error, empty } = this.props;
-    return (
-      <Input
-        className={className}
-        right={
-          loading <= 0 ? (
-            <span className="g-input-right-verification" onClick={() => this.onSend()}>
-              获取验证码
-            </span>
-          ) : (<span className="g-input-right-verification-loading">等待{loading}秒</span>)
-        }
-        value={value}
-        error={error}
-        empty={empty}
-        placeholder={placeholder}
-        onChange={data => onChange && onChange(data)}
-      />
-    );
-  }
-}

+ 17 - 17
front/project/www/components/OtherModal/index.js

@@ -8,7 +8,7 @@ import Assets from '@src/components/Assets';
 import scale from '@src/services/Scale';
 import { asyncSMessage } from '@src/services/AsyncTools';
 import AnswerButton from '../AnswerButton';
-import { SelectInput, VerificationInput, Input } from '../Login';
+import { SelectInput, VerificationInput, DefaultInput, Input, Textarea } from '../Input';
 import { MobileArea, TextbookFeedbackTarget, TextbookSubject, AskTarget } from '../../../Constant';
 import Invite from '../Invite';
 import Modal from '../Modal';
@@ -312,7 +312,7 @@ export class BindEmail extends Component {
       <div className="step-1-layout">
         <div className="label">邮箱地址</div>
         <div className="input-layout">
-          <Input
+          <DefaultInput
             className="w-10"
             placeholder="请输入邮箱"
             value={this.state.data.email}
@@ -463,7 +463,7 @@ export class EditInfo extends Component {
           <div className="edit-info-modal-block">
             <div className="label">用户名</div>
             <div className="input-layout">
-              <Input
+              <DefaultInput
                 className="w-10"
                 placeholder="2-14个字符。"
                 value={this.state.data.nickname || ''}
@@ -890,7 +890,7 @@ export class FeedbackErrorDataModal extends Component {
       >
         <div className="t-2 m-b-1 t-s-16">
           定位:
-          <input
+          <Input
             value={data.position[0]}
             className="t-c b-c-1 m-r-5"
             style={{ width: 56 }}
@@ -900,7 +900,7 @@ export class FeedbackErrorDataModal extends Component {
             }}
           />
           <span className="require">页</span>
-          <input
+          <Input
             value={data.position[1]}
             className="t-c b-c-1 m-r-5"
             style={{ width: 56 }}
@@ -910,7 +910,7 @@ export class FeedbackErrorDataModal extends Component {
             }}
           />
           <span className="require">行</span> , 题号
-          <input
+          <Input
             value={data.position[2]}
             className="t-c b-c-1"
             style={{ width: 56 }}
@@ -921,7 +921,7 @@ export class FeedbackErrorDataModal extends Component {
           />
         </div>
         <div className="t-2 t-s-16">错误内容是:</div>
-        <textarea
+        <Textarea
           value={data.originContent}
           className="b-c-1 w-10 p-10"
           rows={10}
@@ -932,7 +932,7 @@ export class FeedbackErrorDataModal extends Component {
           }}
         />
         <div className="t-2 t-s-16">应该更改为:</div>
-        <textarea
+        <Textarea
           value={data.content}
           className="b-c-1 w-10 p-10"
           rows={10}
@@ -1017,7 +1017,7 @@ export class AskCourseModal extends Component {
           进行提问.
         </div>
         <div className="t-2 t-s-16">老师讲解的内容是:</div>
-        <textarea
+        <Textarea
           value={data.originContent}
           className="b-c-1 w-10 p-10"
           rows={4}
@@ -1028,7 +1028,7 @@ export class AskCourseModal extends Component {
           }}
         />
         <div className="t-2 t-s-16">您的问题是:</div>
-        <textarea
+        <Textarea
           value={data.content}
           className="b-c-1 w-10 p-10"
           rows={4}
@@ -1116,7 +1116,7 @@ export class CourseNoteModal extends Component {
             }}
           />
         </div>
-        <textarea
+        <Textarea
           value={data.content}
           className="b-c-1 w-10 p-10"
           rows={10}
@@ -1223,7 +1223,7 @@ export class TextbookFeedbackModal extends Component {
           <span hidden={data.target === 'new'}>
             {' '}
             题号是{' '}
-            <input
+            <Input
               value={data.no}
               style={{ width: 80 }}
               className="m-l-1 b-c-1 t-c"
@@ -1235,7 +1235,7 @@ export class TextbookFeedbackModal extends Component {
           </span>
         </div>
         <div className="t-2 t-s-16">{TextbookFeedbackTargetMap[data.target]}:</div>
-        <textarea
+        <Textarea
           value={data.content}
           className="b-c-1 w-10 p-10"
           rows={10}
@@ -1296,7 +1296,7 @@ export class FaqModal extends Component {
     const { data, empty = {} } = this.state;
     return (
       <Modal show={show} title="咨询" onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()}>
-        <textarea
+        <Textarea
           className="b-c-1 w-10 p-10"
           value={data.content}
           rows={6}
@@ -1357,7 +1357,7 @@ export class CommentModal extends Component {
     const { data, empty = {} } = this.state;
     return (
       <Modal show={show} title="评价" onConfirm={() => this.onConfirm()} onCancel={() => this.onCancel()}>
-        <textarea
+        <Textarea
           value={data.content}
           className="b-c-1 w-10 p-10"
           rows={6}
@@ -1437,7 +1437,7 @@ export class SuppleModal extends Component {
           {info.area ? ` ${info.area}` : ''} {info.title}
         </div>
         <div className="t-2 t-s-16">补充内容:</div>
-        <textarea
+        <Textarea
           value={data.content}
           className="b-c-1 w-10 p-10"
           empty={empty.content}
@@ -1529,7 +1529,7 @@ export class QuestionNoteModal extends Component {
               })}
             </div>
             <div className="input">
-              <textarea
+              <Textarea
                 className="textarea"
                 value={data[`${noteField}Content`] || ''}
                 placeholder="记下笔记,方便以后复习"

+ 3 - 3
front/project/www/routes/exercise/main/page.js

@@ -12,7 +12,7 @@ import Panel from '../../../components/Panel';
 import List from '../../../components/List';
 import Tabs from '../../../components/Tabs';
 import Module from '../../../components/Module';
-import Input from '../../../components/Input';
+import InputItem from '../../../components/InputItem';
 import Button from '../../../components/Button';
 import AnswerButton from '../../../components/AnswerButton';
 import Division from '../../../components/Division';
@@ -1054,7 +1054,7 @@ export default class extends Page {
       <Module className="code-module">
         <div className="title">输入《千行GMAT长难句》专属 Code,解锁在线练习功能。</div>
         <div className="input-block">
-          <Input
+          <InputItem
             size="lager"
             placeholder="请输入CODE"
             onChange={value => {
@@ -1100,7 +1100,7 @@ export default class extends Page {
         <div className="code-module-modal">
           <div className="title">请输入CODE</div>
           <div className="desc">
-            <Input
+            <InputItem
               onChange={value => {
                 this.code = value;
               }}

+ 6 - 5
front/project/www/routes/paper/question/detail/index.js

@@ -17,6 +17,7 @@ import AnswerList from '../../../../components/AnswerList';
 import AnswerButton from '../../../../components/AnswerButton';
 import AnswerTable from '../../../../components/AnswerTable';
 import OtherAnswer from '../../../../components/OtherAnswer';
+import { Textarea } from '../../../../components/Input';
 import { QuestionNoteModal } from '../../../../components/OtherModal';
 import { AskTarget } from '../../../../../Constant';
 import { Question } from '../../../../stores/question';
@@ -668,7 +669,7 @@ export default class extends Component {
               进行提问
             </div>
             <div className="label">有疑问的具体内容是:</div>
-            <textarea
+            <Textarea
               className="textarea"
               value={ask.originContent}
               placeholder="请复制粘贴有疑问的内容。"
@@ -678,7 +679,7 @@ export default class extends Component {
               }}
             />
             <div className="label">针对以上内容的问题是:</div>
-            <textarea
+            <Textarea
               className="textarea"
               value={ask.content}
               placeholder="提问频率高的问题会被优先回答哦。"
@@ -796,7 +797,7 @@ export default class extends Component {
               进行提问
             </div>
             <div className="label">错误内容是:</div>
-            <textarea
+            <Textarea
               className="textarea"
               value={feedback.originContent}
               placeholder="你可以适当扩大复制范围以使我们准确定位,感谢。"
@@ -806,7 +807,7 @@ export default class extends Component {
               }}
             />
             <div className="label">应该改为:</div>
-            <textarea
+            <Textarea
               className="textarea"
               value={feedback.content}
               placeholder="只需提供正确内容即可"
@@ -900,7 +901,7 @@ export default class extends Component {
               })}
             </div>
             <div className="input">
-              <textarea
+              <Textarea
                 className="textarea"
                 value={note[`${noteField}Content`] || ''}
                 placeholder="记下笔记,方便以后复习"