样式修改

在登陆页添加微信登陆

  1. <Form.Item>
  2. 其他登陆方式:<Button onClick={handleWeixinLogin}>微信</Button>
  3. </Form.Item>

扫码页面

  1. // 使用微信扫码登陆
  2. const handleWeixinLogin = async() => {
  3. const origin: string = window.location.origin;
  4. window.location.href= `http://gmall-h5-api.atguigu.cn/api/user/weixin/login?redirect_uri=${origin}`
  5. }

后端会根据redirect_uri,当用户扫码登陆一下,会跳转到login页面,在页面参数中会携带token,

登陆流程处理

最后,在withAuthorization中统一处理登陆逻辑。

  1. import { FC } from "react";
  2. import { useLocation, Navigate } from "react-router-dom";
  3. import { Spin } from "antd";
  4. import { useAppDispatch, useAppSelector } from "@/app/hooks";
  5. import { getUserInfoAsync, selectUser, setToken } from "@/pages/login/slice";
  6. /*
  7. 高阶组件HOC
  8. 本质上是一个函数,接受组件作为参数,返回一个新组件
  9. WrappedComponent 组件是哪个?
  10. 看路由路径(地址)
  11. /login --> EmptyLayout/Login
  12. /syt/dashboard --> Layout/Dashboard
  13. */
  14. function withAuthorization(WrappedComponent: FC) { // FunctionComponent
  15. return () => {
  16. // 读取redux中管理的token和用户名 ==> 只要状态数据发生了改变, 当前组件函数就会自动重新执行
  17. const { token, name } = useAppSelector(selectUser);
  18. // 获取当前请求的路由地址
  19. const { pathname } = useLocation();
  20. const dispatch = useAppDispatch();
  21. // 如果有token, 说明至少登录过
  22. if (token) {
  23. ...
  24. } else { // 没有登录过 => 都得去登陆页面
  25. // 判断是否是微信扫码登陆
  26. const params = new URLSearchParams(document.location.search.substring(1));
  27. const token = params.get('token');
  28. if (token) {
  29. // 微信扫码登陆,获取到token,直接跳转到首页
  30. dispatch(setToken(token))
  31. return <Navigate to="/syt/dashboard" />;
  32. }
  33. // 如果访问的是登陆页面, 直接显示对应的组件
  34. if (pathname === "/login") {
  35. return <WrappedComponent />;
  36. }
  37. // // 如果访问不是登录页面, 自动跳转到登陆页面
  38. return <Navigate to="/login" />;
  39. }
  40. };
  41. }
  42. export default withAuthorization;

在store中定义一个setToken方法,用来保存微信扫码后获取到的token

  1. // 创建当前redux模块的管理对象slice
  2. const userSlice = createSlice({
  3. name: 'user', // 标识名称
  4. initialState, // 初始状态
  5. // 配置同步action对应的reducer => 同步action会自动生成
  6. reducers: {
  7. setToken: (state, action) => {
  8. // 用来保存微信扫码登陆的token
  9. const token = action.payload;
  10. state.token = token
  11. localStorage.setItem('token_key', token)
  12. }
  13. },
  14. })
  15. export const { setToken } = userSlice.actions;

尚品汇扫码登陆功能实现代码分支:https://github.com/zxfjd3g/gshop-client/tree/feature/wx-login