前言
首先介绍下用户系统。用户系统是后台管理系统的核心功能之一,它负责处理用户的身份认证、权限控制等关键功能。一个完善的用户系统能够确保系统的安全性和可用性。
### 一、功能
1. **登录注册**
- 用户登录
- 用户注册
- 记住密码
- 验证码功能
2. **用户认证**
- JWT Token 认证
- 用户信息管理
- 登录状态维护
3. **权限控制**
- 角色管理
- 权限验证
- 访问控制
### 二、技术方案
1. **前端实现**
- Vue Router 路由守卫
- Pinia 状态管理
- Element Plus UI 组件
- Axios 请求封装
2. **后端接口**
- 用户认证接口
- 用户信息接口
- 权限验证接口
前置修改
创建工具函数src/utils/auth.js
const TOKEN_KEY = 'token'
export function getToken() {
return localStorage.getItem(TOKEN_KEY)
}
export function setToken(token) {
return localStorage.setItem(TOKEN_KEY, token)
}
export function removeToken() {
return localStorage.removeItem(TOKEN_KEY)
}
状态管理文件修改src/stores/user.js
import { defineStore } from 'pinia'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { login, getUserInfo } from '@/api/user'
export const useUserStore = defineStore('user', {
state: () => ({
token: getToken(),
userInfo: null
}),
actions: {
// 登录
async login(userInfo) {
try {
const { data } = await login(userInfo)
setToken(data.token)
this.token = data.token
return Promise.resolve()
} catch (error) {
return Promise.reject(error)
}
},
// 获取用户信息
async getUserInfo() {
try {
const { data } = await getUserInfo()
this.userInfo = data
return Promise.resolve(data)
} catch (error) {
return Promise.reject(error)
}
},
// 退出登录
logout() {
this.token = null
this.userInfo = null
removeToken()
}
}
})
其他的环境准备阶段在第一章已经写好了。我们暂时不用修改。然后这里我知道很多人是把token操作放到store里面的。说一下改成功工具函数的好处哈。
首先职责不同
stores/user.js 是状态管理,负责:
- 管理用户状态(token、用户信息等)
- 处理用户相关的业务逻辑(登录、获取用户信息等)
- 与后端 API 交互
utils/auth.js 是工具函数,负责:
- 提供 token 的存取方法
- 不涉及业务逻辑
- 可以被其他模块复用
为什么要分离
- 工具函数可以被多个模块使用
- 如果需要修改 token 的存储方式(比如改用 sessionStorage)可以直接修改工具函数。也就是扩展性
- 一个逻辑一个工具函数,各司其职
实现登录功能
登录页面src/views/login/index.vue
,先简单实现一下哈,大家嫌弃的话?自己改!!!
<script setup>
import { ref, reactive } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useUserStore } from '@/stores/user'
import { ElMessage } from 'element-plus'
const router = useRouter()
const route = useRoute()
const userStore = useUserStore()
// 表单数据
const loginForm = reactive({
username: '',
password: '',
remember: false
})
// 表单校验规则
const rules = {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 20, message: '长度在 6 到 20 个字符', trigger: 'blur' }
]
}
// 表单引用
const loginFormRef = ref(null)
// 登录方法
const handleLogin = async () => {
if (!loginFormRef.value) return
try {
// 表单验证
await loginFormRef.value.validate()
// 调用登录接口
await userStore.login(loginForm)
// 获取用户信息
await userStore.getUserInfo()
ElMessage.success('登录成功')
// 跳转到之前的页面或首页
const redirect = route.query.redirect || '/'
router.push(redirect)
} catch (error) {
console.error('登录失败:', error)
}
}
</script>
<template>
<div class="login-container">
<div class="login-box">
<div class="title">
<h2>博客管理系统</h2>
</div>
<el-form
ref="loginFormRef"
:model="loginForm"
:rules="rules"
class="login-form"
>
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
placeholder="用户名"
prefix-icon="User"
/>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
placeholder="密码"
prefix-icon="Lock"
show-password
/>
</el-form-item>
<el-form-item>
<el-checkbox v-model="loginForm.remember">记住密码</el-checkbox>
</el-form-item>
<el-form-item>
<el-button
type="primary"
:loading="loading"
class="login-button"
@click="handleLogin"
>
登录
</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<style lang="scss" scoped>
.login-container {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #f0f2f5;
.login-box {
width: 400px;
padding: 40px;
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
.title {
text-align: center;
margin-bottom: 30px;
h2 {
font-size: 24px;
color: #303133;
}
}
.login-form {
.login-button {
width: 100%;
}
}
}
}
</style>
先发出来。我要测试一下。给一下测试方法
npm run dev
打开浏览器,访问http://localhost:5173/login
OK,说一下我这里遇到的问题
[plugin:vite:import-analysis] Failed to resolve import "@/views/dashboard/index.vue" from "src/router/index.js". Does the file exist?
这个错误是指页面没有创建,那我们创建一下。src/views/dashboard/index.vue
<script setup>
</script>
<template>
<div class="dashboard">
<h1>Dashboard</h1>
</div>
</template>
<style>
</style>
最简单的一个页面。然后我这才发现第一章的token操作全在pinia里,所以我们要去修改一下请求,路由这些地方的代码。嗯,我就不写出来了。我非常相信大家的实力,你们包能自己换的。=.= 给代码太麻烦了,嘻嘻
最后修改你的src/App.vue
<script setup></script>
<template>
<router-view />
</template>
<style></style>
按照测试方法运行,页面显示下列信息,那么前面的步骤算是OK了。我们继续下一步,否则就检查代码,实在不行就留言给我把。
OK,明天在来写了。大家晚安