diff --git a/server/config/db.js b/server/config/db-connection.js similarity index 87% rename from server/config/db.js rename to server/config/db-connection.js index 77d89b9..8c94c00 100644 --- a/server/config/db.js +++ b/server/config/db-connection.js @@ -1,4 +1,4 @@ -// 配置模块 +// 配置模块 单链接 const mysql = require("mysql2"); const connection = mysql.createConnection({ @@ -6,7 +6,7 @@ const connection = mysql.createConnection({ user: "root", password: "root", database: "test", - multipleStatements: true + multipleStatements: true, }); const connectDb = () => { diff --git a/server/controllers/userController.js b/server/controllers/userController.js index b5e9ef0..0e80df1 100644 --- a/server/controllers/userController.js +++ b/server/controllers/userController.js @@ -2,7 +2,7 @@ const bcrypt = require("bcrypt"); const jwt = require("jsonwebtoken"); const moment = require("moment"); -const { connection } = require("../config/db.js"); +const { connection } = require("../config/db-connection.js"); const saltRounds = 10; @@ -328,14 +328,12 @@ const restoreUserApi = (req, res) => { }); }; -// 用户登录接口 +// 登录接口 const loginUser = (req, res) => { const { userName, password } = req.body; - if (!userName || !password) { return res.status(400).json({ message: "账号和密码都是必需的" }); } - const findUserQuery = "SELECT * FROM users WHERE userName = ? AND is_delete = 0"; connection.query(findUserQuery, [userName], async (err, results) => { @@ -343,49 +341,72 @@ const loginUser = (req, res) => { console.error(err); return res.status(500).json({ message: "查询用户失败" }); } - if (results.length === 0) { return res.status(404).json({ message: "用户不存在" }); } - const user = results[0]; const hashFromDb = user.password; - // 验证密码 检查密码是否匹配 const passWordMatch = await bcrypt.compare(password, hashFromDb); - if (!passWordMatch) { return res.status(401).json({ message: "用户名或密码错误" }); } - // 生成 JWT const token = jwt.sign( - { userId: user.id, userName: user.userName }, + { id: user.id, userName: user.userName }, "jwt_secret", { expiresIn: "1h" }, ); - // 登录时间 const login_time = moment().format("YYYY-MM-DD HH:mm:ss"); - - // 返回用户信息 - const userInfo = { - userName: user.userName, - account: user.account, - avatar: user.avatar, - description: user.description, - create_time: user.create_time, - update_time: user.update_time, - is_delete: user.is_delete, - nick_name: user.nick_name, - role_ids: user.role_ids, - login_time: login_time, - }; - - res.status(200).json({ message: "登录成功", status: 200, token, userInfo }); + res + .status(200) + .json({ message: "登录成功", status: 200, token, login_time }); }); }; +// 获取用户详情接口 +const getUserDetails = (req, res) => { + const token = req.headers.authorization?.split(" ")[1]; // 从请求头获取 token + if (!token) { + return res.status(401).json({ message: "Token 不存在" }); + } + try { + const decoded = jwt.verify(token, "jwt_secret"); // 解码 JWT + const userId = decoded.id; // 获取解码后的 id + // 使用 id 查询用户详情 + const findUserQuery = "SELECT * FROM users WHERE id = ? AND is_delete = 0"; + connection.query(findUserQuery, [userId], (err, results) => { + if (err) { + console.error(err); + return res.status(500).json({ message: "查询用户失败" }); + } + if (results.length === 0) { + return res.status(404).json({ message: "用户不存在" }); + } + const user = results[0]; + // 返回用户信息 + const userInfo = { + id: user.id, + userName: user.userName, + account: user.account, + avatar: user.avatar, + description: user.description, + create_time: user.create_time, + update_time: user.update_time, + is_delete: user.is_delete, + nick_name: user.nick_name, + role_ids: user.role_ids, + }; + res + .status(200) + .json({ message: "获取用户信息成功", status: 200, userInfo }); + }); + } catch { + return res.status(403).json({ message: "无效的 token" }); + } +}; + // 刷新jwt接口 const refreshToken = (req, res) => { const { refreshToken } = req.body; @@ -491,6 +512,7 @@ module.exports = { permanentDeleteUser, restoreUserApi, loginUser, + getUserDetails, refreshToken, registerUser, }; diff --git a/server/index.js b/server/index.js index dd2984b..4dd161c 100644 --- a/server/index.js +++ b/server/index.js @@ -3,7 +3,7 @@ const express = require("express"); const bodyParserMiddleware = require("./middleware/bodyParserMiddleware"); const corsMiddleware = require("./middleware/corsMiddleware"); const userRoutes = require("./routes/userRoutes"); -const { connectDb } = require("./config/db"); +const { connectDb } = require("./config/db-connection"); // const { hashExistingPasswords } = require("./controllers/userController"); // 创建服务器对象 diff --git a/server/routes/userRoutes.js b/server/routes/userRoutes.js index 09dc34d..b573323 100644 --- a/server/routes/userRoutes.js +++ b/server/routes/userRoutes.js @@ -33,4 +33,7 @@ router.post("/register", userController.registerUser); // 刷新jwt router.post("/refresh-token", userController.refreshToken); +// 获取用户信息 +router.get("/userInfo", userController.getUserDetails); + module.exports = router; diff --git a/src/i18n/package/en.ts b/src/i18n/package/en.ts index ecb233e..0edcdbe 100644 --- a/src/i18n/package/en.ts +++ b/src/i18n/package/en.ts @@ -244,6 +244,7 @@ const en = { multiLevelRouteManagement: "Multi-level route management", clickHereToMultiRouteExample: "Click here to go to the multi-level route management example page", + login_success: "Login success", }; export default en; diff --git a/src/i18n/package/zh.ts b/src/i18n/package/zh.ts index a6a1448..6746a0c 100644 --- a/src/i18n/package/zh.ts +++ b/src/i18n/package/zh.ts @@ -238,6 +238,7 @@ const zh = { clickHereToHookExample: "点击这里跳转到案例页面", multiLevelRouteManagement: "多级路由管理", clickHereToMultiRouteExample: "点击这里跳转到多级路由管理案例页面", + login_success: "登录成功", }; export default zh; diff --git a/src/service/login.ts b/src/service/login.ts index d2c6f81..df23e05 100644 --- a/src/service/login.ts +++ b/src/service/login.ts @@ -46,3 +46,7 @@ export const registerApi = (params: RegisterRequestData) => method: "post", data: params, }); + +// userInfo +export const userInfoApi = () => + request({ url: "/api/users/userInfo", method: "GET" }); diff --git a/src/utils/request.ts b/src/utils/request.ts index 517ce2f..61fe2dd 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -5,14 +5,14 @@ import axios, { } from "axios"; import { ElNotification, ElLoading } from "element-plus"; import i18n from "@/i18n"; -import CACHE_KEY from "@/constants/cache-key"; -import { getToken, setToken } from "@/utils/cache/cookies"; +// import CACHE_KEY from "@/constants/cache-key"; +import { getToken } from "@/utils/cache/cookies"; import { useUserStoreHook } from "@/store/modules/user"; /** 退出登录并强制刷新页面(会重定向到登录页) */ const logout = () => { useUserStoreHook().logout(); - location.reload(); + // location.reload(); }; const { t } = i18n.global; @@ -66,7 +66,9 @@ const hideLoading = () => { // 生成请求 key const generateRequestKey = (config: InternalAxiosRequestConfig) => { const { method, url, params, data } = config; - return `${method}:${url}:${JSON.stringify(params)}:${JSON.stringify(data)}`; + // 使用时间戳确保每次请求 key 唯一 + const timestamp = Date.now(); + return `${method}:${url}:${JSON.stringify(params)}:${JSON.stringify(data)}:${timestamp}`; }; // 添加请求到 pending 中 @@ -143,28 +145,29 @@ request.interceptors.response.use( }, async (error: any) => { hideLoading(); - let errorInfo = ""; const status = error.response ? error.response.status : 0; - const originalRequest = error.config; + // const originalRequest = error.config; // 处理 HTTP 错误状态码 switch (status) { // Token 过期时,尝试刷新 Token case 401: { errorInfo = t("case_401"); - const refreshToken = setToken(CACHE_KEY.REFRESH_TOKEN); - if (refreshToken && !originalRequest._retry) { - originalRequest._retry = true; - // 实现刷新 token 的逻辑 - // const newToken = await refreshAccessToken(refreshToken); - // setToken(newToken); - // originalRequest.headers["Authorization"] = `Bearer ${newToken}`; - // return request(originalRequest); // 重新发起请求 - } else { - // 退出登录 - logout(); - } + // const refreshToken = setToken(CACHE_KEY.REFRESH_TOKEN); + // if (refreshToken && !originalRequest._retry) { + // originalRequest._retry = true; + // // 实现刷新 token 的逻辑 + // const newToken = await refreshAccessToken(refreshToken); + // setToken(newToken); + // originalRequest.headers["Authorization"] = `Bearer ${newToken}`; + // return request(originalRequest); // 重新发起请求 + // } else { + // // 退出登录 + // logout(); + // } + // 退出登录 + logout(); break; } case 403: { diff --git a/src/views/login/index.vue b/src/views/login/index.vue index 15975bf..4912d14 100644 --- a/src/views/login/index.vue +++ b/src/views/login/index.vue @@ -152,7 +152,7 @@ import { setToken } from "@/utils/cache/cookies"; import ThemeSwitch from "@/components/ThemeSwitch/index.vue"; import { ref, reactive } from "vue"; -import { loginApi, registerApi } from "@/service/login"; +import { loginApi, registerApi, userInfoApi } from "@/service/login"; import { useRouter } from "vue-router"; import { ElNotification } from "element-plus"; import type { FormInstance, FormRules } from "element-plus"; @@ -258,18 +258,14 @@ const handleSlideSuccess = () => { // 登录接口请求验证 const handlerExecutiveLogging = () => { // 执行登录操作 - // loading.value = true; + loading.value = true; const params = form; // 登录问候语 const { showGreetingNotification } = useGreeting(t); loginApi(params) .then((res: any) => { if (res.status === 200) { - // 显示问候语 - showGreetingNotification(res.message, res.userInfo.userName); setToken(res.token); - setLocalData(CACHE_KEY.USER_INFO, res.userInfo); - router.push("/"); } else if (res.status === 403) { ElNotification({ message: res.message, @@ -283,9 +279,20 @@ const handlerExecutiveLogging = () => { } loading.value = false; }) + .then(() => { + userInfoApi().then((rest: any) => { + setLocalData(CACHE_KEY.USER_INFO, rest.userInfo); + // 显示问候语 + showGreetingNotification(t("login_success"), rest.userInfo.userName); + router.push("/"); + }); + }) .catch((error: Error) => { console.log("error", error); loading.value = false; + }) + .finally(() => { + loading.value = false; }); };