index.js 9.77 KB
Newer Older
FE committed
1 2 3
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import classnames from 'classnames';
FE committed
4
import { studentLogin } from '@/store/userAction';
FE committed
5
import { http } from '@/utils';
FE committed
6
import { Formik, Form, Field } from 'formik';
FE committed
7
import { Toast } from "antd-mobile";
zhanghaozhe committed
8
import { HeaderBar, CaptchaAli } from "@/common";
FE committed
9 10 11 12 13 14
import Header from '../common/Header';
import Input from '../common/inputWithCountryCodes';
import VeriCodeInput from '../common/veriCodeInput';

import './index.scss';

FE committed
15 16 17 18 19 20 21 22
@connect(
  state => ({
    country: state.country,
  }),
  {
    studentLogin
  }
)
FE committed
23 24 25 26 27 28 29 30 31
class StudentRoot extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      validate: null,
      captchaInstance: null,
      disabled: false,
      isSchool: false,
      isCollege: false,
FE committed
32 33
      list: [],
      schoolList: [],
FE committed
34
      schoolName: '',
zhanghaozhe committed
35
      validationData: null,
FE committed
36 37 38
    };
  }

FE committed
39 40 41 42 43
  componentDidMount() {
    this.fetchSchoolInfo();
  }

  fetchSchoolInfo = () => {
FE committed
44
    http.get(`${API['home']}/sys/schools `).then(res => {
FE committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58
      const { code, data } = res.data;
      if(code === 200) {
        const schoolList = [];
        data.forEach(item => {
          schoolList.push(item.school);
        });
        this.setState({
          list: data,
          schoolList
        });
      }
    });
  }

FE committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
  handleToLogin = ({ tel, password, code, school, college, uid, name}) => {
    const { validate, captchaInstance } = this.state;
    const { country, studentLogin, location } = this.props;
    const from = location.state && location.state.from;
    studentLogin({
      validate,
      tel,
      password,
      code,
      num: `00${country.num}`,
      school,
      college,
      uid,
      name,
      redirect: from && window.location.origin + from.pathname + from.search + from.hash,
    }).then(res => {
      if (res.hasError) {
zhanghaozhe committed
76
        captchaInstance.reset();
FE committed
77 78 79 80 81 82 83 84 85 86
        Toast.info(res.msg, 2, null, false);
      }
    });
  }

  getCaptchaInstance = instance => {
    this.setState({
      captchaInstance: instance
    });
  }
zhanghaozhe committed
87 88 89 90 91 92

  onVerify = (data) => {
    this.setState({
      validationData: data,
      validate: true
    })
FE committed
93 94 95 96 97 98 99 100
  }

  selectSwitch = (key, value) => {
    let param = {};
    param[key] = value;
    this.setState(param);
  }

FE committed
101
  changeToCollege = (school = '') => {
FE committed
102 103 104 105 106 107 108 109
    this.setState({
      schoolName: school
    });
  }

  fetchCollegeInfo = () => {
    const { list, schoolName } = this.state;
    const data = list.filter(item => item['school'] === schoolName);
FE committed
110
    if(data.length > 0) {
FE committed
111
      return data[0]['colleges']
FE committed
112
    }
FE committed
113
    return [];
FE committed
114 115
  }

FE committed
116 117
  render() {
    const { country } = this.props;
FE committed
118 119
    const { validate, captchaInstance, isSchool, isCollege, schoolList, schoolName } = this.state;
    const collegeList = this.fetchCollegeInfo();
FE committed
120 121 122 123 124
    return (
      <>
        <HeaderBar title={'助学计划'} arrow={true}/>
        <Header/>
        <Formik
zhanghaozhe committed
125
          initialValues={{
FE committed
126
            tel: '',
FE committed
127
            password: '',
FE committed
128 129 130 131 132 133
            code: '',
            school: '',
            college: '',
            uid: '',
            name: '',
          }}
FE committed
134
          validate={({ tel, password, code, school, college, uid, name }) => {
FE committed
135 136 137 138 139
            let errors = {}
            if (!/\d/.test(tel)) {
              errors.tip = '请填写正确格式的手机号~';
              return errors;
            }
FE committed
140 141 142 143
            if(password.length < 6 || !/[A-Za-z].*[0-9]|[0-9].*[A-Za-z]/.test(password)) {
              errors.tip = '密码需要包含6-16位字母和数字~';
              return errors;
            }
FE committed
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
            if (!/[0-9]{6}/.test(code)) {
              errors.tip = '请填写验证码(先滑块验证呦)~';
              return errors;
            }
            if (!school) {
              errors.tip = '请选择学校~';
              return errors;
            }
            if (!college) {
              errors.tip = '请选择学院~';
              return errors;
            }
            if (!uid) {
              errors.tip = '请填写学号~';
              return errors;
            }
            if (!name) {
              errors.tip = '请填写姓名~';
              return errors;
            }
FE committed
164
            return {};
FE committed
165 166
          }}
          onSubmit={(values, errors) => {
FE committed
167
            this.handleToLogin(values);
FE committed
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
          }}
        >
          {props => {
            const isSubmit =  Object.values(props.values).join('') !== '' && props.errors.tip === undefined;
            return (
              <Form className="student-form">
                <Field
                  name='tel'
                  render={({field}) => (
                    <Input
                      {...field}
                      type={'tel'}
                      placeholder={'手机号快捷登录(免注册)'}
                      wrapperClass={'tel-input'}
                      country={country}
                    />
                  )}
                />
FE committed
186
                <div className="student-form__item">
zhanghaozhe committed
187 188 189 190
                  <Field
                    className="student-form__input"
                    type="password"
                    name="password"
FE committed
191 192 193 194 195
                    minLength="6"
                    maxLength="16"
                    placeholder="密码需要包含6-16位字母和数字"
                  />
                </div>
zhanghaozhe committed
196
                <CaptchaAli getInstance={this.getCaptchaInstance} onVerify={this.onVerify} mb={15}/>
FE committed
197 198 199 200 201 202 203 204 205
                {
                  validate &&
                  <Field
                    type='number'
                    name='code'
                    render={({field}) => (
                      <VeriCodeInput
                        {...field}
                        className={'student-form__code'}
FE committed
206
                        icon={<i className={'iconfont iconduanxin'} style={{fontSize: '20px', left: '12px'}}/>}
FE committed
207
                        tel={props.values.tel}
zhanghaozhe committed
208
                        validationData={this.state.validationData}
FE committed
209 210 211 212 213 214 215 216 217 218
                        errors={props.errors}
                        placeholder={'请输入验证码'}
                        instance={captchaInstance}
                        country={country}
                      />
                    )}
                  />
                }
                <div className="student-form__item">
                  <label className="student-form__label">学校</label>
zhanghaozhe committed
219
                  <StudentSelect
FE committed
220 221
                    name="school"
                    value={props.values.school}
FE committed
222
                    schoolName={schoolName}
FE committed
223 224 225 226
                    data={{
                      key: 'isSchool',
                      val: isSchool
                    }}
FE committed
227
                    options={schoolList}
228
                    placeholder="请选择"
FE committed
229
                    onChange={props.setFieldValue}
FE committed
230 231 232
                    clearToCollege={() => {
                      props.setFieldValue('college', '')
                    }}
FE committed
233
                    selectSwitch={this.selectSwitch}
zhanghaozhe committed
234
                    changeToCollege={this.changeToCollege}
FE committed
235 236 237 238
                  />
                </div>
                <div className="student-form__item">
                  <label className="student-form__label">学院</label>
zhanghaozhe committed
239
                  <StudentSelect
FE committed
240 241 242 243 244 245
                    name="college"
                    value={props.values.college}
                    data={{
                      key: 'isCollege',
                      val: isCollege
                    }}
246
                    isClick={props.values.school !== ''}
FE committed
247
                    options={collegeList}
248
                    placeholder="请先选择学校"
FE committed
249
                    onChange={props.setFieldValue}
zhanghaozhe committed
250
                    selectSwitch={this.selectSwitch}
FE committed
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
                  />
                </div>
                <div className="student-form__item">
                  <label className="student-form__label">学号</label>
                  <Field className="student-form__input" type="text" name="uid" placeholder="不区分大小写"/>
                </div>
                <div className="student-form__item">
                  <label className="student-form__label">姓名</label>
                  <Field className="student-form__input" type="text" name="name" placeholder="请准确填写"/>
                </div>
                <div className="student-form__footer">
                  {
                    props.errors.tip &&
                    <p className="student-form__tip">*{props.errors.tip}</p>
                  }
                  <button className="student-form__submit" type="submit" disabled={!isSubmit}>注册</button>
                </div>
              </Form>
            )
          }}
        </Formik>
      </>
    )
  }
}

const StudentSelect = (props) => {
zhanghaozhe committed
278 279
  const {
    options = [],
FE committed
280
    data: { key = '' , val = false },
FE committed
281
    schoolName,
282
    isClick = true,
FE committed
283 284 285
    name,
    value,
    onChange,
286
    placeholder,
FE committed
287
    selectSwitch,
FE committed
288
    clearToCollege,
FE committed
289
    changeToCollege
FE committed
290 291 292
  } = props;
  return (
    <div className="student-select">
zhanghaozhe committed
293
      <input
FE committed
294 295
        className={classnames({'active': val})}
        value={value}
zhanghaozhe committed
296 297
        type="text"
        placeholder={placeholder}
FE committed
298
        readOnly
299 300
        onClick={() => {
          isClick && selectSwitch(key, true);
zhanghaozhe committed
301
        }}
FE committed
302 303
      />
      {
FE committed
304
        val &&
FE committed
305 306
        <ul className="student-select__list">
          {
FE committed
307
            options.length > 0 && options.map((item, index) => (
zhanghaozhe committed
308 309
              <li
                className="student-select__option"
FE committed
310 311 312 313 314 315 316 317 318 319 320
                key={index}
                onClick={() => {
                  selectSwitch(key, false);
                  onChange(name, item);
                  if(schoolName !== item && typeof clearToCollege === 'function') {
                    clearToCollege();
                  }
                  typeof changeToCollege === 'function' && changeToCollege(item);
                }}
              >{item}</li>
            ))
FE committed
321 322 323 324 325 326 327 328
          }
        </ul>
      }
    </div>
  )
}

export default StudentRoot;