超时重新登录实现

1,048 阅读2分钟

背景

产品提出后端判断session过期之后,需要保留当前编辑页面数据,而不是跳转到登录页重新登录

实现思路

在前端请求方法remote中判断返回的数据是否是超时登录(需要和后端商量好),若是,则在当前页面弹出登录框重新登录。

登录框的实现可以在Layout布局中写Modal,然后全局监听redux中的一个控制Modal是显示与隐藏。另一种方式是在remote回调中通过Modal.confirm方法弹出重新登录框。本文使用的方式是后者。

实现及分析

代码初版

// 超时退出方法
export function ReloinFn() {
  const obj = {};
  const reloginFn = () => {
    const promise = new Promise((resolve, reject) => {
      obj.form.handleSubmit(resolve, reject);
    });
    return promise;
  };
  Modal.confirm({
      title: '登陆超时,请重新登陆',
      content: <ReLoginCmp getInstance={(form) => (obj.form = form)} />,
      okText: '登录',
      cancelText: '退出',
      onOk: reloginFn,
      onCancel: () => {
        loginOut(10);
      }
  });
}

在实现过程中发现函数式的实现方式,不存在this,因此引入obj对象,指定obj.form为ReLoginCmp,根据Ant design开发文档中onOk若是promise对象,resolve关闭当前Modal,reject保留当前Modal,因此onOk回调中声明一个promsie对象,将resolve和reject传入ReLoginCmp的submit方法中。

import React, {Component} from 'react';
import {Form, Input, Icon} from 'antd';
import {remote} from 'remote';
const FormItem = Form.Item;

class ReLogin extends Component {
  constructor(props) {
    super(props);
    this.props.getInstance(this);
  }

  handleSubmit = (resolve, reject) => {
    this.props.form.validateFields((err, values) => {
      if (err) {
        reject();
      }
      const postData = {
        userCode: values.username,
        password: values.password
      };
      remote({
        path: '/login',
        method: 'POST',
        postData
      }).then(
        (data) => {
          resolve();
        },
        () => {
          reject();
        }
      );
    });
  };

  render() {
    const {getFieldDecorator} = this.props.form;
    return (
      <Form>
        <FormItem>
          {getFieldDecorator('username', {
            rules: [{required: true, message: '请输入用户名!'}],
            initialValue: localStorage.getItem('username')
          })(
            <Input
              disabled
              placeholder="Username"
              prefix={<Icon style={{color: 'rgba(0,0,0,.25)'}} type="user" />}
            />
          )}
        </FormItem>
        <FormItem>
          {getFieldDecorator('password', {
            rules: [{required: true, message: '请输入密码!'}]
          })(
            <Input
              placeholder="Password"
              prefix={<Icon style={{color: 'rgba(0,0,0,.25)'}} type="lock" />}
              type="password"
            />
          )}
        </FormItem>
      </Form>
    );
  }
}

const ReLoginForm = Form.create()(ReLogin);
export default ReLoginForm;

在实现后联调过程中发现存在超时过程中一次弹出多个登录框的情况,需要引入一个变量记录弹出框的状态,若已经存在弹出框,则不重复弹出。

// 阻止多次弹窗
export const Object = {
  flag: false
};

export function ReloinFn() {
  const obj = {};
  const flag = Object.flag;
  const reloginFn = () => {
    const promise = new Promise((resolve, reject) => {
      obj.form.handleSubmit(resolve, reject);
      Object.flag = false;
    });
    return promise;
  };
  !flag && Modal.confirm({
      title: '登陆超时,请重新登陆',
      content: <ReLoginCmp getInstance={(form) => (obj.form = form)} />,
      okText: '登录',
      cancelText: '退出',
      onOk: reloginFn,
      onCancel: () => {
        loginOut(10);
        Object.flag = false;
      }
  });
  
  Object.flag = true;
}