34 用户共享状态封装 - udo-bit/naive_admin_pro GitHub Wiki

目标

完成用户共享状态的基础封装。 完成基础登录接口封装。

背景

为了保证登录后的用户信息的存储,我们需要先通过pinia进行封装用户共享状态管理器去管理用户的状态,方便我们后续的使用。

开发

在stores目录下创建一个user.ts的文件,用户存放用户的基本信息。如下:

export interface UserInfo {
  id: number
  username: string
  nickname?: string
  avatar?: string
  email?: string
  mobile?: string
  signature?: string
  gender?: number
  realName?: string
  birthday?: string
  money?: number
}

export const useUserStore = defineStore('user', () => {
  const userInfo = ref<UserInfo>()

  const token = useAuthorization()

  const setUserInfo = (info: UserInfo) => {
    userInfo.value = info
  }

  const setToken = (val: string) => {
    token.value = val
  }

  return {
    userInfo,
    setUserInfo,
    setToken,
  }
})

登录接口封装

接下来我们先来实现一下登录接口的封装,我们会将登录的接口封装到用户状态管理的代码逻辑中,方便我们后面使用和复用 首先我们再src目录下创建一个api的文件夹用于存放我们所有与接口相关的类型和接口信息。 然后我们在api下面创建一个user.ts的文件用于存放我们用户操作的一些接口信息,如下:

  1. 首先将编写的类型放到user.ts的文件中,并从我们的stores/user.ts中采用导入的方式使用。

在 api/user.ts中

export interface UserInfo {
  id: number
  username: string
  nickname?: string
  avatar?: string
  email?: string
  mobile?: string
  signature?: string
  gender?: number
  realName?: string
  birthday?: string
  money?: number
}

在stores/user.ts中

import type { UserInfo } from '~/api/user'

export const useUserStore = defineStore('user', () => {
  const userInfo = ref<UserInfo>()

  const token = useAuthorization()

  const setUserInfo = (info: UserInfo) => {
    userInfo.value = info
  }

  const setToken = (val: string) => {
    token.value = val
  }

  return {
    userInfo,
    setUserInfo,
    setToken,
  }
})
  1. 实现开发全局代理

在我们真实开发的过程中,前后端分离在H5端一般没有特殊处理的话可能会出现跨域的问题,为了防止这种问题的发生我们可以在vite.config.ts中配置代理处理为同源协议,这样就可以避免我们在开发阶段出现跨域的问题。 首先我们在.env.development中添加我们需要做代理的链接(这里使用我们的mock地址作为演示)

VITE_APP_BASE_URL=https://mock.lingyu.org.cn/mock/642b5d1e939061307ed09d1b/example

我们在真正的开发环境中使用的并不是我们mock的接口数据,例如我们生产环境下的api的地址为https://www.baidu.com/api,那么我们在.env.production里面配置如下:

VITE_APP_BASE_URL=https://www.baidu.com/api

然后在types/env.d.ts中添加对应类型

interface ImportMetaEnv {
  readonly VITE_APP_BASE: string
  readonly VITE_APP_BASE_API: string
+  readonly VITE_APP_BASE_URL: string
}

最后我们在vite.config.ts中实现代理的功能

import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd())
  return {
    ...,
     server: {
      proxy: {
        [env.VITE_APP_BASE_API]: {
          target: env.VITE_APP_BASE_URL,
          changeOrigin: true,
          ws: false,
          rewrite: path => path.replace(new RegExp(`^${env.VITE_APP_BASE_API}`), ''),
        },
      },
    },
  }
}
  1. 在api/user.ts中实现登录接口测试代理

前面我们已经配置好对应的mock接口地址,接下来我们来测试一下登录的mock接口

export const userLoginUrl = '/user/login'
export interface UserAccountLoginParams {
  username: string
  password: string
  captcha?: string
}
export interface UserMobileLoginParams {
  mobile: string | number
  captcha: string
}

export interface UserLoginResult {
  token: string
}

export const userLoginApi = (params: UserAccountLoginParams | UserMobileLoginParams) => {
  return usePost<UserMobileLoginParams | UserAccountLoginParams, UserLoginResult>(userLoginUrl, params)
}

在stores/user.ts中注册使用并进行导出

  const login = async (params: UserMobileLoginParams | UserAccountLoginParams) => {
    const { data } = await userLoginApi(params)
    if (data?.token)
      setToken(data.token)
  }

我们在登录页面进行测试是否可用

<script lang="ts" setup>
  const userStore = useUserStore()
  const onConfirmLogin = async () => {
  await userStore.login({
    username: '',
    password: '',
  })
}
</script>
<template>
  <n-button 
    type="primary" 
    block secondary 
    strong @click="onConfirmLogin">
    {{ $t("login.login") }}
  </n-button>
</template>

可以正常请求通数据

⚠️ **GitHub.com Fallback** ⚠️