全部开发者教程

企业级在线办公系统

首页 慕课教程 企业级在线办公系统 企业级在线办公系统 15-2 微信扫码登陆(前端加载二维码)

上个小节我们在后端生成了二维码图片的Base64字符串,那么这节课我们要在Web页面上切换登陆方式的时候,加载出来这个二维码图片。

一、页面设计

login.vue页面中定义了一个DIV标签,里面包含的就是显示二维码内容。

<div v-if="qrCodeVisible">
    <div class="qrCode-container">
        <img :src="qrCode" height="153" class="qrCode" />
        <img src="../assets/login/phone.png" height="148" />
    </div>
    <div class="row"><a class="link" @click="changeMode">用户名密码登陆</a></div>
</div>

在模型层中声明了跟二维码有关的若干变量。qrCodeVisible变量默认为false,也就是说二维码DIV面板默认是不显示的,需要我们手动进行切换。

data: function() {
    return {
        ……,
        qrCodeVisible: false,
        qrCode: '',
        uuid: null,
        qrCodeTimer: null,
        loginTimer: null
    };
},

在登陆页面上有个文字连接,点击这个连接,自动切换二维码面板上。这个文字连接的标签代码如下,需要我们声明点击事件的回调函数。

<div class="row"><a class="link" @click="changeMode">二维码登陆</a></div>

图片描述

二、切换登陆方式

定义changeMode()函数用来切换登陆面板,其实就是改变qrCodeVisible变量的值。

changeMode: function() {
    let that = this;
    that.qrCodeVisible = !that.qrCodeVisible;
    //加载二维码图片
    if (that.qrCodeVisible) {
        that.loadQRCode();
        //创建刷新二维码定时器,默认为5分钟
        that.qrCodeTimer = setInterval(function() {
            that.loadQRCode();
        }, 5 * 60 * 1000);
        
      	//创建轮询定时器,每隔5秒钟发起Ajax请求,检查Redis中UUID对应的值
        that.loginTimer = setInterval(function() {
            //调用Web方法,检查Redis中UUID对应的值,判定用户是否扫码登陆。该Web方法下面有定义。
            that.$http('user/wechatLogin', 'POST', { uuid: that.uuid }, true, function(resp) {
                if (resp.result) {
                    //判定登陆成功就自动销毁两个定时器
                    clearInterval(that.qrCodeTimer);
                    clearInterval(that.loginTimer);
                    //缓存用户权限
                    let permissions = resp.permissions;
                    localStorage.setItem('permissions', permissions);
                    //跳转页面
                    router.push({ name: 'Home' });
                }
            });
        }, 5000);
    } else {
        //切换回账户密码登陆,销毁刷新二维码定时器
        clearInterval(that.qrCodeTimer);
        clearInterval(that.loginTimer);
    }
},
//加载二维码图片的封装方法
loadQRCode: function() {
    this.$http('user/createQrCode', 'GET', null, true, resp => {
        this.qrCode = resp.pic;
        this.uuid = resp.uuid;
    });
}

三、检查登陆结果

上面浏览器发出的轮询Ajax请求发送给Web方法查询登陆情况,下面咱们把这个Web方法写一下,先从业务层看是写起。在UserService.java接口中声明抽象方法。

public interface UserService {
    ……
    public HashMap wechatLogin(String uuid);
}

UserServiceImpl.java类中实现抽象方法。

@Service
public class UserServiceImpl implements UserService {
    ……
    @Override
    public HashMap wechatLogin(String uuid) {
        HashMap map = new HashMap();
        boolean result = false;
        if (redisTemplate.hasKey(uuid)) {
            String value = redisTemplate.opsForValue().get(uuid).toString();
            //判断Redis缓存的UUID对应的Value是否为非false,就算用户登陆了
            if (!"false".equals(value)) {
                result = true;
                //删除Redis中的UUID,防止二维码被重刷
                redisTemplate.delete(uuid);
                //把Value的字符串转换成整数
                int userId = Integer.parseInt(value);
                map.put("userId", userId);
            }
        }
        map.put("result", result);
        return map;
    }
}

创建WechatLoginForm.java类,封装浏览器提交的Ajax数据。

@Schema(name = "WechatLoginForm", description = "微信小程序登陆Emos系统Form类")
@Data
public class WechatLoginForm {

    @Schema(description = "uuid")
    @NotBlank(message = "uuid不能为空")
    private String uuid;

}

UserController.java类中定义Web方法,可以用Swagger测试一下。

@RestController
@RequestMapping("/user")
@Tag(name = "UserController", description = "用户Web接口")
public class UserController {
    ……
    @PostMapping("/wechatLogin")
    @Operation(summary = "微信小程序登陆")
    public R wechatLogin(@Valid @RequestBody WechatLoginForm form) {
        HashMap map = userService.wechatLogin(form.getUuid());
        boolean result = (boolean) map.get("result");
        if (result) {
            int userId = (int) map.get("userId");
            StpUtil.setLoginId(userId);
            Set<String> permissions = userService.searchUserPermissions(userId);
            map.remove("userId");
            map.put("permissions", permissions);
            String token=StpUtil.getTokenInfo().getTokenValue();
            map.put("token",token);
        }
        return R.ok(map);
    }
}