中后台系统第一个要实现的功能就是登录了,我们通常的逻辑是让用户在登录页面输入用户名和密码,调用后端接口去验证用户的合法性,然后根据接口返回的结果进行进一步的路由。本篇我们就介绍一下用户登录功能的开发过程。
1 创建用户表
用户表的话我们设计两个字段,用户名和密码,建表语句如下
CREATE TABLE `users` ( `id` int(0) NOT NULL AUTO_INCREMENT, `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
2 开发后端接口
后端我们使用express框架,把涉及到用户的接口单独拆分到user.js中。打开后端的工程,新建一个user.js文件
因为需要给密码加密,我们引入一个加密的包,在Terminal里输入安装命令
npm install bcryptjs --save
在验证用户名和密码都正确后,给前端返回一个token,我们需要安装支持token的包
npm install jsonwebtoken --save
后端接口需要解析json数据,需要安装json解析包
npm install body-parser --save
包安装好了之后,在user.js中贴入如下代码,来验证用户名和密码
const express = require('express'); const router = express.Router(); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); // 创建 MySQL 连接池 const pool = require('./database'); // 用户登录 router.post('/login', (req, res) => { const { username, password } = req.body; console.log(username, password) // 检查用户名是否存在 pool.query('SELECT * FROM users WHERE username = ?', [username], (error, results) => { if (error) throw error; console.log(results) if (results.length === 0) { res.status(401).json({ code: 401, message: 'Invalid username or password' }); } else { const user = results[0]; // 验证密码是否匹配 bcrypt.compare(password, user.password, (err, result) => { if (err) throw err; console.log("验证密码", result) if (result) { // 生成 JWT 令牌 const token = jwt.sign({ id: user.id, username: user.username }, 'your_secret_key', { expiresIn: '1h' }); res.status(200).json({ code: 200, message: "登录成功", data: token }); } else { res.status(401).json({ code: 401, message: 'Invalid username or password' }); } }); } }); }); module.exports = router;
然后在index.js里注册用户路由
const express = require('express'); const app = express(); const cors = require('cors'); const menuROuter = require('./menu') const userRoutes = require('./user'); const bodyParser = require('body-parser'); // 定义路由 app.use(bodyParser.json()); app.get('/', (req, res) => { res.send('Hello, World!'); }); app.use(cors({ origin: 'http://localhost:3002', credentials: true })); app.use('/api/get-menu-list',menuROuter); app.use('/api/user',userRoutes); // 启动服务器 app.listen(3000, () => { console.log('Server is running on port 3000'); });
3 测试接口
我们后端接口写好了之后需要进行测试,使用postman测试我们的接口
注意这里我们是post请求,body要选择json然后按照json的语法去构造参数,在Header里要设置我们的格式是json
4 修改登录页面调用后端接口
模板里给的是mock调用,我们需要真实的调用后端接口,找到store文件夹下的user.ts,改造登录方式为调用后端接口
import { defineStore } from 'pinia'; import { usePermissionStore } from '@/store'; import type { UserInfo } from '@/types/interface'; import { login } from '@/api/login'; const InitUserInfo: UserInfo = { name: '', // 用户名,用于展示在页面右上角头像处 roles: [], // 前端权限模型使用 如果使用请配置modules/permission-fe.ts使用 }; export const useUserStore = defineStore('user', { state: () => ({ token: 'main_token', // 默认token不走权限 userInfo: { ...InitUserInfo }, }), getters: { roles: (state) => { return state.userInfo?.roles; }, }, actions: { async login(userInfo: Record<string, unknown>) { const res = await login(userInfo.account.toString(),userInfo.password.toString()); if (res.code === 200) { this.token = res.data; } else { throw res; } }, async getUserInfo() { const mockRemoteUserInfo = async (token: string) => { if (token === 'main_token') { return { name: 'Tencent', roles: ['all'], // 前端权限模型使用 如果使用请配置modules/permission-fe.ts使用 }; } return { name: 'td_dev', roles: ['UserIndex', 'DashboardBase', 'login'], // 前端权限模型使用 如果使用请配置modules/permission-fe.ts使用 }; }; const res = await mockRemoteUserInfo(this.token); this.userInfo = res; }, async logout() { this.token = ''; this.userInfo = { ...InitUserInfo }; }, }, persist: { afterRestore: () => { const permissionStore = usePermissionStore(); permissionStore.initRoutes(); }, key: 'user', paths: ['token'], }, });
这里将调用后端接口的代码单独封装一下,在src/api目录下新建一个login.ts文件,输入如下代码
// store/actions.ts import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; export const login = (username: string, password: string): Promise<any> => { return new Promise((resolve, reject) => { const requestConfig: AxiosRequestConfig = { url: 'http://localhost:3000/api/user/login', method: 'post', data: { username, password, }, headers: { 'Content-Type': 'application/json', }, }; axios(requestConfig) .then((response: AxiosResponse) => { const result = response.data; if (result.code === 200 && result.message === '登录成功') { resolve(result); } else { reject(new Error(result.message)); } }) .catch((error) => { reject(error); }); }); };
我们使用axios库去请求后端接口,需要先安装一下库
npm install axios --save
代码写好之后,启动前后端项目
node index.js //启动后端项目命令 npm run dev //启动前端项目命令
最终效果
总结
我们本篇讲解了TDesign实现登录的过程,需要先创建用户表,然后编写后端登录代码,编写前端代码调用后端接口。
总体上流程并不复杂,主要是要熟悉axios库的用法即可。