Parcourir la source

Login.Captcha组件支持countDown,onGetCaptcha支持Promise (#1305)

lyingd il y a 7 ans
Parent
commit
2c3214f149

+ 29 - 22
.roadhogrc.mock.js

@@ -1,6 +1,6 @@
 import mockjs from 'mockjs';
 import { getRule, postRule } from './mock/rule';
-import { getActivities, getNotice, getFakeList, postFakeList } from './mock/api';
+import { getActivities, getNotice, getFakeList, postFakeList, getFakeCaptcha } from './mock/api';
 import { getFakeChartData } from './mock/chart';
 import { getProfileBasicData } from './mock/profile';
 import { getProfileAdvancedData } from './mock/profile';
@@ -24,32 +24,38 @@ const proxy = {
     },
     $body: {
       name: 'Serati Ma',
-      avatar:
-        'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png',
+      avatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png',
       userid: '00000001',
       email: 'antdesign@alipay.com',
       signature: '海纳百川,有容乃大',
       title: '交互专家',
       group: '蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED',
-      tags: [{
-        key: '0',
-        label: '很有想法的',
-      }, {
-        key: '1',
-        label: '专注设计',
-      }, {
-        key: '2',
-        label: '辣~',
-      }, {
-        key: '3',
-        label: '大长腿',
-      }, {
-        key: '4',
-        label: '川妹子',
-      }, {
-        key: '5',
-        label: '海纳百川',
-      }],
+      tags: [
+        {
+          key: '0',
+          label: '很有想法的',
+        },
+        {
+          key: '1',
+          label: '专注设计',
+        },
+        {
+          key: '2',
+          label: '辣~',
+        },
+        {
+          key: '3',
+          label: '大长腿',
+        },
+        {
+          key: '4',
+          label: '川妹子',
+        },
+        {
+          key: '5',
+          label: '海纳百川',
+        },
+      ],
       notifyCount: 12,
       country: 'China',
       geographic: {
@@ -176,6 +182,7 @@ const proxy = {
   },
   'GET /api/geographic/province': getProvince,
   'GET /api/geographic/city/:province': getCity,
+  'GET /api/captcha': getFakeCaptcha,
 };
 
 export default (noProxy ? {} : delay(proxy, 1000));

+ 9 - 0
mock/api.js

@@ -332,9 +332,18 @@ export const getActivities = [
   },
 ];
 
+export function getFakeCaptcha(req, res) {
+  if (res && res.json) {
+    res.json('captcha-xxx');
+  } else {
+    return 'captcha-xxx';
+  }
+}
+
 export default {
   getNotice,
   getActivities,
   getFakeList,
   postFakeList,
+  getFakeCaptcha,
 };

+ 20 - 11
src/components/Login/LoginItem.js

@@ -23,18 +23,16 @@ class WarpFormItem extends Component {
     clearInterval(this.interval);
   }
   onGetCaptcha = () => {
-    let count = 59;
-    this.setState({ count });
-    if (this.props.onGetCaptcha) {
-      this.props.onGetCaptcha();
+    const { onGetCaptcha } = this.props;
+    const result = onGetCaptcha ? onGetCaptcha() : null;
+    if (result === false) {
+      return;
+    }
+    if (result instanceof Promise) {
+      result.then(this.runGetCaptchaCountDown);
+    } else {
+      this.runGetCaptchaCountDown();
     }
-    this.interval = setInterval(() => {
-      count -= 1;
-      this.setState({ count });
-      if (count === 0) {
-        clearInterval(this.interval);
-      }
-    }, 1000);
   };
   getFormItemOptions = ({ onChange, defaultValue, rules }) => {
     const options = {
@@ -48,6 +46,17 @@ class WarpFormItem extends Component {
     }
     return options;
   };
+  runGetCaptchaCountDown = () => {
+    let count = this.props.countDown || 59;
+    this.setState({ count });
+    this.interval = setInterval(() => {
+      count -= 1;
+      this.setState({ count });
+      if (count === 0) {
+        clearInterval(this.interval);
+      }
+    }, 1000);
+  };
   render() {
     const { count } = this.state;
 

+ 2 - 1
src/components/Login/index.en-US.md

@@ -38,7 +38,8 @@ Apart from the above properties, Login.Username also support all properties of a
 
 Property | Description | Type | Default
 ----|------|-----|------
-onGetCaptcha | callback on getting a new Captcha | () => void | -
+onGetCaptcha | callback on getting a new Captcha | () => (void \| false \| Promise) | -
+countDown | count down | number |-
 
 Apart from the above properties, _Login.Captcha_ support the same properties with _Login.UserName_.
 

+ 2 - 1
src/components/Login/index.zh-CN.md

@@ -39,7 +39,8 @@ rules | 校验规则,同 Form getFieldDecorator(id, options) 中 [option.rules
 
 参数 | 说明 | 类型 | 默认值
 ----|------|-----|------
-onGetCaptcha | 点击获取校验码的回调 | () => void | -
+onGetCaptcha | 点击获取校验码的回调 | () => (void \| false \| Promise) | -
+countDown | 倒计时 | number |-
 
 除上述属性以外,Login.Captcha 支持的属性与 Login.UserName 相同。
 

+ 4 - 1
src/models/login.js

@@ -1,5 +1,5 @@
 import { routerRedux } from 'dva/router';
-import { fakeAccountLogin } from '../services/api';
+import { fakeAccountLogin, getFakeCaptcha } from '../services/api';
 import { setAuthority } from '../utils/authority';
 import { reloadAuthorized } from '../utils/Authorized';
 
@@ -43,6 +43,9 @@ export default {
         yield put(routerRedux.push('/user/login'));
       }
     },
+    *getCaptcha({ payload }, { call }) {
+      yield call(getFakeCaptcha, payload);
+    },
   },
 
   reducers: {

+ 27 - 2
src/routes/User/Login.js

@@ -21,6 +21,24 @@ export default class LoginPage extends Component {
     this.setState({ type });
   };
 
+  onGetCaptcha = () => {
+    return new Promise((resolve, reject) => {
+      this.loginForm.validateFields(['mobile'], {}, (err, values) => {
+        if (err) {
+          reject(err);
+        } else {
+          this.props
+            .dispatch({
+              type: 'login/getCaptcha',
+              payload: values.mobile,
+            })
+            .then(resolve)
+            .catch(reject);
+        }
+      });
+    });
+  };
+  loginForm;
   handleSubmit = (err, values) => {
     const { type } = this.state;
     if (!err) {
@@ -49,7 +67,14 @@ export default class LoginPage extends Component {
     const { type } = this.state;
     return (
       <div className={styles.main}>
-        <Login defaultActiveKey={type} onTabChange={this.onTabChange} onSubmit={this.handleSubmit}>
+        <Login
+          defaultActiveKey={type}
+          onTabChange={this.onTabChange}
+          onSubmit={this.handleSubmit}
+          ref={form => {
+            this.loginForm = form;
+          }}
+        >
           <Tab key="account" tab="账户密码登录">
             {login.status === 'error' &&
               login.type === 'account' &&
@@ -64,7 +89,7 @@ export default class LoginPage extends Component {
               !login.submitting &&
               this.renderMessage('验证码错误')}
             <Mobile name="mobile" />
-            <Captcha name="captcha" />
+            <Captcha name="captcha" countDown={120} onGetCaptcha={this.onGetCaptcha} />
           </Tab>
           <div>
             <Checkbox checked={this.state.autoLogin} onChange={this.changeAutoLogin}>

+ 4 - 0
src/services/api.js

@@ -120,3 +120,7 @@ export async function fakeRegister(params) {
 export async function queryNotices() {
   return request('/api/notices');
 }
+
+export async function getFakeCaptcha(mobile) {
+  return request(`/api/captcha?mobile=${mobile}`);
+}