checklogin实现

main
哆哆咯哆哆咯 4 weeks ago
parent c1c6f80ebe
commit 812aa7a798

@ -1,3 +1,4 @@
{
"java.compile.nullAnalysis.mode": "automatic"
"java.compile.nullAnalysis.mode": "automatic",
"java.configuration.updateBuildConfiguration": "interactive"
}

@ -55,13 +55,4 @@
<artifactId>spring-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -18,7 +18,7 @@ public class WebMvcConfig implements WebMvcConfigurer {
"/user/register",
"/user/captcha",
"/user/verify-captcha",
"/user/info/getuserinfo",
"/user/check-login",
"/post/list",
"/post/detail",
"/comment/list",

@ -151,7 +151,7 @@ public final class JWTUtil {
if(ttl < NEED_REFRESH_TTL)
redisUtil.set(redisKey, newRefreshToken, REFRESH_EXPIRATION, TimeUnit.MILLISECONDS);
user.setAccessToken(newAccessToken);
user.setRefreshToken(newRefreshToken);
return user;
}

@ -10,6 +10,7 @@ import java.util.Optional;
public final class UserContext {
private static final ThreadLocal<UserDTO> USER_THREAD_LOCAL = new TransmittableThreadLocal<>();
public static void setUser(UserDTO user) {
USER_THREAD_LOCAL.set(user);
}
@ -39,6 +40,10 @@ public final class UserContext {
return Optional.ofNullable(userInfoDTO).map(UserDTO::getRefreshToken).orElse(null);
}
public static UserDTO getUser() {
return USER_THREAD_LOCAL.get();
}
public static void removeUser() {
USER_THREAD_LOCAL.remove();
}

@ -127,13 +127,4 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -70,6 +70,22 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.luojia_channel.LuojiaChannelApplication</mainClass>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

@ -20,6 +20,7 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.awt.image.BufferedImage;
@ -32,6 +33,7 @@ import java.util.concurrent.TimeUnit;
@RequestMapping("/user")
@RequiredArgsConstructor
@Tag(name = "用户管理", description = "用户登陆注册相关接口")
@Slf4j
public class UserLoginController {
private final UserLoginService userLoginService;
private final RedisUtil redisUtil;
@ -62,10 +64,28 @@ public class UserLoginController {
})
public Result<UserDTO> checkLogin(@RequestHeader(value = "Authorization", required = false) String accessToken,
@RequestHeader(value = "X-Refresh-Token", required = false) String refreshToken) {
if (accessToken != null && accessToken.startsWith("Bearer ")) {
accessToken = accessToken.substring(7);
log.info("检查登录状态 - 接收到的Authorization: {}", accessToken);
log.info("检查登录状态 - 接收到的X-Refresh-Token: {}", refreshToken);
// 检查token是否为空
if (accessToken == null || accessToken.isEmpty()) {
log.error("登录验证失败 - accessToken为空");
return Result.fail("未提供访问令牌");
}
if (refreshToken == null || refreshToken.isEmpty()) {
log.error("登录验证失败 - refreshToken为空");
return Result.fail("未提供刷新令牌");
}
try {
UserDTO userDTO = userLoginService.checkLogin(accessToken, refreshToken);
log.info("登录验证成功 - 用户ID: {}, 用户名: {}", userDTO.getUserId(), userDTO.getUsername());
return Result.success(userDTO);
} catch (Exception e) {
log.error("登录验证失败 - 错误信息: {}", e.getMessage(), e);
return Result.fail(e.getMessage());
}
return Result.success(userLoginService.checkLogin(accessToken, refreshToken));
}
@PostMapping("/register")

@ -16,38 +16,38 @@
# accessKey: forely
# secretKey: Forely123!
lj:
db:
host: 192.168.125.128
password: MySQL@5678
redis:
host: 192.168.125.128
port: 6379
password: Redis@9012
rabbitmq:
host: 192.168.125.128
port: 5672
username: rabbit_admin
password: Rabbit@3456
minio:
endpoint: http://192.168.125.128:9000
accessKey: minio_admin
secretKey: Minio@1234
#lj:
# db:
# host: localhost
# password: 123456
# host: 192.168.125.128
# password: MySQL@5678
# redis:
# host: localhost
# host: 192.168.125.128
# port: 6379
# password: 123456
# password: Redis@9012
# rabbitmq:
# host: localhost
# host: 192.168.125.128
# port: 5672
# username: guest
# password: guest
# username: rabbit_admin
# password: Rabbit@3456
# minio:
# endpoint: http://localhost:9005
# accessKey: leezt
# secretKey: lzt264610
# endpoint: http://192.168.125.128:9000
# accessKey: minio_admin
# secretKey: Minio@1234
lj:
db:
host: localhost
password: 123456
redis:
host: localhost
port: 6379
password: 123456
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
minio:
endpoint: http://localhost:9000
accessKey: root
secretKey: 12345678

@ -72,9 +72,9 @@
}
},
"node_modules/@babel/compat-data": {
"version": "7.27.2",
"resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.27.2.tgz",
"integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==",
"version": "7.27.5",
"resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.27.5.tgz",
"integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==",
"dev": true,
"license": "MIT",
"engines": {
@ -82,22 +82,22 @@
}
},
"node_modules/@babel/core": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.27.1.tgz",
"integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==",
"version": "7.27.4",
"resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.27.4.tgz",
"integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.27.1",
"@babel/helper-compilation-targets": "^7.27.1",
"@babel/helper-module-transforms": "^7.27.1",
"@babel/helpers": "^7.27.1",
"@babel/parser": "^7.27.1",
"@babel/template": "^7.27.1",
"@babel/traverse": "^7.27.1",
"@babel/types": "^7.27.1",
"@babel/generator": "^7.27.3",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-module-transforms": "^7.27.3",
"@babel/helpers": "^7.27.4",
"@babel/parser": "^7.27.4",
"@babel/template": "^7.27.2",
"@babel/traverse": "^7.27.4",
"@babel/types": "^7.27.3",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@ -113,9 +113,9 @@
}
},
"node_modules/@babel/eslint-parser": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/eslint-parser/-/eslint-parser-7.27.1.tgz",
"integrity": "sha512-q8rjOuadH0V6Zo4XLMkJ3RMQ9MSBqwaDByyYB0izsYdaIWGNLmEblbCOf1vyFHICcg16CD7Fsi51vcQnYxmt6Q==",
"version": "7.27.5",
"resolved": "https://registry.npmmirror.com/@babel/eslint-parser/-/eslint-parser-7.27.5.tgz",
"integrity": "sha512-HLkYQfRICudzcOtjGwkPvGc5nF1b4ljLZh1IRDj50lRZ718NAKVgQpIAUX8bfg6u/yuSKY3L7E0YzIV+OxrB8Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -132,14 +132,14 @@
}
},
"node_modules/@babel/generator": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.27.1.tgz",
"integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==",
"version": "7.27.5",
"resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.27.5.tgz",
"integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.27.1",
"@babel/types": "^7.27.1",
"@babel/parser": "^7.27.5",
"@babel/types": "^7.27.3",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^3.0.2"
@ -149,13 +149,13 @@
}
},
"node_modules/@babel/helper-annotate-as-pure": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz",
"integrity": "sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==",
"version": "7.27.3",
"resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz",
"integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.27.1"
"@babel/types": "^7.27.3"
},
"engines": {
"node": ">=6.9.0"
@ -264,15 +264,15 @@
}
},
"node_modules/@babel/helper-module-transforms": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz",
"integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==",
"version": "7.27.3",
"resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz",
"integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1",
"@babel/traverse": "^7.27.1"
"@babel/traverse": "^7.27.3"
},
"engines": {
"node": ">=6.9.0"
@ -398,14 +398,14 @@
}
},
"node_modules/@babel/helpers": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.27.1.tgz",
"integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==",
"version": "7.27.4",
"resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.27.4.tgz",
"integrity": "sha512-Y+bO6U+I7ZKaM5G5rDUZiYfUvQPUibYmAFe7EnKdnKBbVXDZxvp+MWOH5gYciY0EPk4EScsuFMQBbEfpdRKSCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/template": "^7.27.1",
"@babel/types": "^7.27.1"
"@babel/template": "^7.27.2",
"@babel/types": "^7.27.3"
},
"engines": {
"node": ">=6.9.0"
@ -506,12 +506,12 @@
}
},
"node_modules/@babel/parser": {
"version": "7.27.2",
"resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.27.2.tgz",
"integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
"version": "7.27.5",
"resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.27.5.tgz",
"integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==",
"license": "MIT",
"dependencies": {
"@babel/types": "^7.27.1"
"@babel/types": "^7.27.3"
},
"bin": {
"parser": "bin/babel-parser.js"
@ -816,9 +816,9 @@
}
},
"node_modules/@babel/plugin-transform-block-scoping": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.1.tgz",
"integrity": "sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw==",
"version": "7.27.5",
"resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.5.tgz",
"integrity": "sha512-JF6uE2s67f0y2RZcm2kpAUEbD50vH62TyWVebxwHAlbSdM49VqPz8t4a1uIjp4NIOIZ4xzLfjY5emt/RCyC7TQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -904,9 +904,9 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.1.tgz",
"integrity": "sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q==",
"version": "7.27.3",
"resolved": "https://registry.npmmirror.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.3.tgz",
"integrity": "sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1252,15 +1252,15 @@
}
},
"node_modules/@babel/plugin-transform-object-rest-spread": {
"version": "7.27.2",
"resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.2.tgz",
"integrity": "sha512-AIUHD7xJ1mCrj3uPozvtngY3s0xpv7Nu7DoUSnzNY6Xam1Cy4rUznR//pvMHOhQ4AvbCexhbqXCtpxGHOGOO6g==",
"version": "7.27.3",
"resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.3.tgz",
"integrity": "sha512-7ZZtznF9g4l2JCImCo5LNKFHB5eXnN39lLtLY5Tg+VkR0jwOt7TBciMckuiQIOIW7L5tkQOCh3bVGYeXgMx52Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/plugin-transform-destructuring": "^7.27.1",
"@babel/plugin-transform-destructuring": "^7.27.3",
"@babel/plugin-transform-parameters": "^7.27.1"
},
"engines": {
@ -1388,9 +1388,9 @@
}
},
"node_modules/@babel/plugin-transform-regenerator": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.1.tgz",
"integrity": "sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==",
"version": "7.27.5",
"resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.5.tgz",
"integrity": "sha512-uhB8yHerfe3MWnuLAhEbeQ4afVoqv8BQsPqrTv7e/jZ9y00kJL6l9a/f4OWaKxotmjzewfEyXE1vgDJenkQ2/Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1437,9 +1437,9 @@
}
},
"node_modules/@babel/plugin-transform-runtime": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.27.1.tgz",
"integrity": "sha512-TqGF3desVsTcp3WrJGj4HfKokfCXCLcHpt4PJF0D8/iT6LPd9RS82Upw3KPeyr6B22Lfd3DO8MVrmp0oRkUDdw==",
"version": "7.27.4",
"resolved": "https://registry.npmmirror.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.27.4.tgz",
"integrity": "sha512-D68nR5zxU64EUzV8i7T3R5XP0Xhrou/amNnddsRQssx6GrTLdZl1rLxyjtVZBd+v/NVX4AbTPOB5aU8thAZV1A==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1705,9 +1705,9 @@
}
},
"node_modules/@babel/runtime": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.27.1.tgz",
"integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
"version": "7.27.4",
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.27.4.tgz",
"integrity": "sha512-t3yaEOuGu9NlIZ+hIeGbBjFtZT7j2cb2tg0fuaJKeGotchRjjLfrBA9Kwf8quhpP1EUuxModQg04q/mBwyg8uA==",
"dev": true,
"license": "MIT",
"engines": {
@ -1730,17 +1730,17 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.27.1.tgz",
"integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==",
"version": "7.27.4",
"resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.27.4.tgz",
"integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.27.1",
"@babel/parser": "^7.27.1",
"@babel/template": "^7.27.1",
"@babel/types": "^7.27.1",
"@babel/generator": "^7.27.3",
"@babel/parser": "^7.27.4",
"@babel/template": "^7.27.2",
"@babel/types": "^7.27.3",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@ -1749,9 +1749,9 @@
}
},
"node_modules/@babel/types": {
"version": "7.27.1",
"resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.27.1.tgz",
"integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
"version": "7.27.3",
"resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.27.3.tgz",
"integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==",
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
@ -1840,21 +1840,21 @@
}
},
"node_modules/@floating-ui/core": {
"version": "1.7.0",
"resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.0.tgz",
"integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==",
"version": "1.7.1",
"resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.1.tgz",
"integrity": "sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==",
"license": "MIT",
"dependencies": {
"@floating-ui/utils": "^0.2.9"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.7.0",
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.0.tgz",
"integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==",
"version": "1.7.1",
"resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.1.tgz",
"integrity": "sha512-cwsmW/zyw5ltYTUeeYJ60CnQuPqmGwuGVhG9w0PRaRKkAyi38BT5CKrpIbb+jtahSwUl04cWzSx9ZOIxeS6RsQ==",
"license": "MIT",
"dependencies": {
"@floating-ui/core": "^1.7.0",
"@floating-ui/core": "^1.7.1",
"@floating-ui/utils": "^0.2.9"
}
},
@ -2186,9 +2186,9 @@
"license": "MIT"
},
"node_modules/@types/express": {
"version": "4.17.21",
"resolved": "https://registry.npmmirror.com/@types/express/-/express-4.17.21.tgz",
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
"version": "4.17.22",
"resolved": "https://registry.npmmirror.com/@types/express/-/express-4.17.22.tgz",
"integrity": "sha512-eZUmSnhRX9YRSkplpz0N+k6NljUUn5l3EWZIKZvYzhvMphEuNiyyy1viH/ejgt66JWgALwC/gtSUAeQKtSwW/w==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2256,9 +2256,9 @@
"license": "MIT"
},
"node_modules/@types/lodash": {
"version": "4.17.16",
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.16.tgz",
"integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==",
"version": "4.17.17",
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.17.tgz",
"integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==",
"license": "MIT"
},
"node_modules/@types/lodash-es": {
@ -2285,9 +2285,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.15.17",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-22.15.17.tgz",
"integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==",
"version": "22.15.29",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-22.15.29.tgz",
"integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2319,9 +2319,9 @@
"license": "MIT"
},
"node_modules/@types/qs": {
"version": "6.9.18",
"resolved": "https://registry.npmmirror.com/@types/qs/-/qs-6.9.18.tgz",
"integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==",
"version": "6.14.0",
"resolved": "https://registry.npmmirror.com/@types/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
"dev": true,
"license": "MIT"
},
@ -2876,53 +2876,53 @@
"license": "ISC"
},
"node_modules/@vue/compiler-core": {
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.13.tgz",
"integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==",
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.16.tgz",
"integrity": "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.25.3",
"@vue/shared": "3.5.13",
"@babel/parser": "^7.27.2",
"@vue/shared": "3.5.16",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.0"
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
"integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==",
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz",
"integrity": "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==",
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.5.13",
"@vue/shared": "3.5.13"
"@vue/compiler-core": "3.5.16",
"@vue/shared": "3.5.16"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz",
"integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==",
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz",
"integrity": "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.25.3",
"@vue/compiler-core": "3.5.13",
"@vue/compiler-dom": "3.5.13",
"@vue/compiler-ssr": "3.5.13",
"@vue/shared": "3.5.13",
"@babel/parser": "^7.27.2",
"@vue/compiler-core": "3.5.16",
"@vue/compiler-dom": "3.5.16",
"@vue/compiler-ssr": "3.5.16",
"@vue/shared": "3.5.16",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.11",
"postcss": "^8.4.48",
"source-map-js": "^1.2.0"
"magic-string": "^0.30.17",
"postcss": "^8.5.3",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz",
"integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==",
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz",
"integrity": "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.13",
"@vue/shared": "3.5.13"
"@vue/compiler-dom": "3.5.16",
"@vue/shared": "3.5.16"
}
},
"node_modules/@vue/component-compiler-utils": {
@ -3029,53 +3029,53 @@
}
},
"node_modules/@vue/reactivity": {
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.13.tgz",
"integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==",
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.16.tgz",
"integrity": "sha512-FG5Q5ee/kxhIm1p2bykPpPwqiUBV3kFySsHEQha5BJvjXdZTUfmya7wP7zC39dFuZAcf/PD5S4Lni55vGLMhvA==",
"license": "MIT",
"dependencies": {
"@vue/shared": "3.5.13"
"@vue/shared": "3.5.16"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.13.tgz",
"integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==",
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.16.tgz",
"integrity": "sha512-bw5Ykq6+JFHYxrQa7Tjr+VSzw7Dj4ldR/udyBZbq73fCdJmyy5MPIFR9IX/M5Qs+TtTjuyUTCnmK3lWWwpAcFQ==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.13",
"@vue/shared": "3.5.13"
"@vue/reactivity": "3.5.16",
"@vue/shared": "3.5.16"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz",
"integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==",
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.16.tgz",
"integrity": "sha512-T1qqYJsG2xMGhImRUV9y/RseB9d0eCYZQ4CWca9ztCuiPj/XWNNN+lkNBuzVbia5z4/cgxdL28NoQCvC0Xcfww==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "3.5.13",
"@vue/runtime-core": "3.5.13",
"@vue/shared": "3.5.13",
"@vue/reactivity": "3.5.16",
"@vue/runtime-core": "3.5.16",
"@vue/shared": "3.5.16",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.13.tgz",
"integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==",
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.16.tgz",
"integrity": "sha512-BrX0qLiv/WugguGsnQUJiYOE0Fe5mZTwi6b7X/ybGB0vfrPH9z0gD/Y6WOR1sGCgX4gc25L1RYS5eYQKDMoNIg==",
"license": "MIT",
"dependencies": {
"@vue/compiler-ssr": "3.5.13",
"@vue/shared": "3.5.13"
"@vue/compiler-ssr": "3.5.16",
"@vue/shared": "3.5.16"
},
"peerDependencies": {
"vue": "3.5.13"
"vue": "3.5.16"
}
},
"node_modules/@vue/shared": {
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.13.tgz",
"integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==",
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.16.tgz",
"integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==",
"license": "MIT"
},
"node_modules/@vue/vue-loader-v15": {
@ -3998,9 +3998,9 @@
}
},
"node_modules/browserslist": {
"version": "4.24.5",
"resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.24.5.tgz",
"integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==",
"version": "4.25.0",
"resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.25.0.tgz",
"integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==",
"dev": true,
"funding": [
{
@ -4018,8 +4018,8 @@
],
"license": "MIT",
"dependencies": {
"caniuse-lite": "^1.0.30001716",
"electron-to-chromium": "^1.5.149",
"caniuse-lite": "^1.0.30001718",
"electron-to-chromium": "^1.5.160",
"node-releases": "^2.0.19",
"update-browserslist-db": "^1.1.3"
},
@ -4166,9 +4166,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001718",
"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz",
"integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==",
"version": "1.0.30001721",
"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz",
"integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==",
"dev": true,
"funding": [
{
@ -5035,9 +5035,9 @@
"license": "MIT"
},
"node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"version": "4.4.1",
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -5426,16 +5426,16 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.152",
"resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.152.tgz",
"integrity": "sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg==",
"version": "1.5.164",
"resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.164.tgz",
"integrity": "sha512-TXBrF2aZenRjY3wbj5Yc0mZn43lMiSHNkzwPkIxx+vWUB35Kf8Gm/uOYmOJFNQ7SUwWAinbfxX73ANIud65wSA==",
"dev": true,
"license": "ISC"
},
"node_modules/element-plus": {
"version": "2.9.10",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.10.tgz",
"integrity": "sha512-W2v9jWnm1kl/zm4bSvCh8aFCVlxvhG3fmqiDZwyd6WQiWGE595J/mpjcCggEr+49QDgIymhXrpPMOPPSARUbng==",
"version": "2.9.11",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.11.tgz",
"integrity": "sha512-x4L/6YC8de4JtuE3vpaEugJdQIeHQaHtIYKyk67IeF6dTIiVax45aX4nWOygnh+xX+0gTvL6xO+9BZhPA3G82w==",
"license": "MIT",
"dependencies": {
"@ctrl/tinycolor": "^3.4.1",
@ -7616,7 +7616,7 @@
},
"node_modules/jparticles": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/jparticles/-/jparticles-3.5.0.tgz",
"resolved": "https://registry.npmmirror.com/jparticles/-/jparticles-3.5.0.tgz",
"integrity": "sha512-qUKP56Xqh2G7TqFKHMPDYzfZKkvsbLGJu+xJI4dh0YGZL26zOCUVV31MkkPWmfd6SaST23mhSvvvEArFd8yApQ==",
"license": "MIT"
},
@ -9148,9 +9148,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.3",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.3.tgz",
"integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
"version": "8.5.4",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.4.tgz",
"integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==",
"funding": [
{
"type": "opencollective",
@ -9167,7 +9167,7 @@
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.8",
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@ -10661,9 +10661,9 @@
}
},
"node_modules/shell-quote": {
"version": "1.8.2",
"resolved": "https://registry.npmmirror.com/shell-quote/-/shell-quote-1.8.2.tgz",
"integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==",
"version": "1.8.3",
"resolved": "https://registry.npmmirror.com/shell-quote/-/shell-quote-1.8.3.tgz",
"integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
"dev": true,
"license": "MIT",
"engines": {
@ -11179,9 +11179,9 @@
"license": "MIT"
},
"node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.2.1.tgz",
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
"version": "2.2.2",
"resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.2.2.tgz",
"integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==",
"dev": true,
"license": "MIT",
"engines": {
@ -11189,14 +11189,14 @@
}
},
"node_modules/terser": {
"version": "5.39.0",
"resolved": "https://registry.npmmirror.com/terser/-/terser-5.39.0.tgz",
"integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==",
"version": "5.40.0",
"resolved": "https://registry.npmmirror.com/terser/-/terser-5.40.0.tgz",
"integrity": "sha512-cfeKl/jjwSR5ar7d0FGmave9hFGJT8obyo0z+CrQOylLDbk7X81nPU6vq9VORa5jU30SkDnT2FXjLbR8HLP+xA==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
"acorn": "^8.14.0",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
@ -11660,16 +11660,16 @@
}
},
"node_modules/vue": {
"version": "3.5.13",
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.13.tgz",
"integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==",
"version": "3.5.16",
"resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.16.tgz",
"integrity": "sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==",
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.13",
"@vue/compiler-sfc": "3.5.13",
"@vue/runtime-dom": "3.5.13",
"@vue/server-renderer": "3.5.13",
"@vue/shared": "3.5.13"
"@vue/compiler-dom": "3.5.16",
"@vue/compiler-sfc": "3.5.16",
"@vue/runtime-dom": "3.5.16",
"@vue/server-renderer": "3.5.16",
"@vue/shared": "3.5.16"
},
"peerDependencies": {
"typescript": "*"
@ -11870,9 +11870,9 @@
"license": "MIT"
},
"node_modules/watchpack": {
"version": "2.4.2",
"resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.2.tgz",
"integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
"version": "2.4.4",
"resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.4.4.tgz",
"integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -11911,9 +11911,9 @@
"license": "BSD-2-Clause"
},
"node_modules/webpack": {
"version": "5.99.8",
"resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.99.8.tgz",
"integrity": "sha512-lQ3CPiSTpfOnrEGeXDwoq5hIGzSjmwD72GdfVzF7CQAI7t47rJG9eDWvcEkEn3CUQymAElVvDg3YNTlCYj+qUQ==",
"version": "5.99.9",
"resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.99.9.tgz",
"integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -12246,9 +12246,9 @@
}
},
"node_modules/webpack-sources": {
"version": "3.2.3",
"resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz",
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
"version": "3.3.2",
"resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.3.2.tgz",
"integrity": "sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==",
"dev": true,
"license": "MIT",
"engines": {

@ -97,11 +97,18 @@ const defaultAvatar = require("@/assets/default-avatar/boy_1.png");
//
const isLoggedIn = computed(() => userStore.isLoggedIn);
const userInfo = computed(() => {
return userStore.userInfo;
// userStore
const info = userStore.userInfo;
// userStorelocalStorage
if (!info.avatar) {
info.avatar = localStorage.getItem('avatar') || '';
}
return info;
});
const showAdmin = computed(() => {
const isAdmin = userStore.isLoggedIn && (userInfo.value.role >= 2);
console.log('检查管理员权限:', userStore.isLoggedIn, userInfo.value.role, isAdmin);
return isAdmin;
});
@ -153,16 +160,47 @@ const hideDropdown = () => {
}, 400);
};
//
onMounted(() => {
//
onMounted(async () => {
if (userStore.isLoggedIn) {
console.log('Header组件挂载: 检测到用户已登录:', userStore.userInfo.username, '角色:', userStore.userInfo.role);
// token
const accessToken = localStorage.getItem('accessToken');
const refreshToken = localStorage.getItem('refreshToken');
if (!accessToken || !refreshToken) {
console.warn('没有找到token跳过获取用户信息');
return;
}
try {
//
const response = await request.get('/user/info/getuserinfo');
if (response && response.code === 200) {
userStore.updateUserInfo({
userid: response.data.id,
username: response.data.username,
avatar: response.data.avatar,
email: response.data.email,
phone: response.data.phone,
college: response.data.college,
gender: response.data.gender,
role: response.data.role,
status: response.data.status
});
}
} catch (error) {
console.error('获取用户信息失败:', error);
// 401tokentoken
if (error.response && (error.response.status === 401 ||
(error.response.status === 500 && error.response.data?.message?.includes('token')))) {
console.warn('Token可能无效不再尝试获取用户信息');
}
}
}
});
//
watch(() => userStore.userInfo, (newInfo) => {
console.log('用户信息更新:', newInfo.username, '角色:', newInfo.role);
watch(() => userStore.userInfo, () => {
}, { deep: true });
</script>

@ -205,14 +205,47 @@ async function login() {
userData.userName = userData.username;
userData.userid = userData.id;
// storelocalStorage
userStore.login(userData);
window.location.reload(); //
//
try {
const userInfoResponse = await request.get('/user/info/getuserinfo', {
params: { userId: userData.id },
headers: {
'Authorization': `Bearer ${userData.accessToken}`,
'X-Refresh-Token': userData.refreshToken
}
});
if (userInfoResponse && userInfoResponse.code === 200) {
//
userStore.updateUserInfo({
userid: userInfoResponse.data.id || userData.id,
username: userInfoResponse.data.username,
avatar: userInfoResponse.data.avatar,
email: userInfoResponse.data.email,
phone: userInfoResponse.data.phone,
college: userInfoResponse.data.college,
gender: userInfoResponse.data.gender,
role: userInfoResponse.data.role,
status: userInfoResponse.data.status
});
}
} catch (error) {
//
}
ElMessage({
message: '登录成功',
type: 'success',
duration: 500
});
emit('LoginSuccess'); //
// 使
window.location.reload();
} else {
//
ElMessage({

@ -30,7 +30,6 @@ if (userId && username && accessToken && refreshToken) {
accessToken,
refreshToken
});
console.log('从本地存储恢复用户登录状态:', username);
}
app.use(router); // 注册 vue-router
@ -39,13 +38,24 @@ app.use(ELementPlus); // 注册 element-plus
// 挂载应用
app.mount('#app');
// 在应用启动后异步验证登录状态,不阻塞应用启动
setTimeout(() => {
checkLoginStatus()
.then(isLoggedIn => {
// 在应用启动后立即验证登录状态
async function validateLoginStatus() {
try {
const isLoggedIn = await checkLoginStatus();
console.log('登录状态验证完成,用户登录状态:', isLoggedIn ? '已登录' : '未登录');
})
.catch(error => {
console.error('登录状态验证失败,但不影响应用使用:', error);
});
}, 500);
// 如果用户未登录但本地存储中有token清除无效的token
if (!isLoggedIn && (localStorage.getItem('accessToken') || localStorage.getItem('refreshToken'))) {
console.warn('本地存储中的token无效清除token');
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
// 不清除用户基本信息,允许显示用户名等非敏感信息
}
} catch (error) {
console.error('登录状态验证失败:', error);
// 不影响应用使用,只在控制台显示错误
}
}
// 立即执行,但不阻塞应用启动
validateLoginStatus();

@ -142,16 +142,25 @@ router.beforeEach(async (to, from, next) => {
});
console.log('从localStorage恢复用户登录状态:', username);
// 异步验证token有效性但不阻塞导航
setTimeout(() => {
checkLoginStatus().catch(err => {
console.error('Token验证失败但不影响当前导航:', err);
});
}, 100);
// 继续导航
// 立即验证token有效性
try {
console.log('验证恢复的登录状态...');
const isLoggedIn = await checkLoginStatus();
if (!isLoggedIn) {
console.warn('恢复的登录状态无效');
ElMessage.warning('登录已过期,请重新登录');
next({ path: '/user/login', query: { redirect: to.fullPath } });
return;
}
console.log('恢复的登录状态有效,继续导航');
next();
return;
} catch (error) {
console.error('登录状态验证失败:', error);
ElMessage.warning('登录状态验证失败,请重新登录');
next({ path: '/user/login', query: { redirect: to.fullPath } });
return;
}
}
// 如果localStorage中没有用户信息尝试通过token验证登录状态
@ -160,15 +169,29 @@ router.beforeEach(async (to, from, next) => {
const isLoggedIn = await checkLoginStatus();
if (!isLoggedIn) {
ElMessage.warning('请先登录');
next({ path: '/' });
next({ path: '/user/login', query: { redirect: to.fullPath } });
return;
}
} catch (error) {
console.error('登录状态验证失败:', error);
ElMessage.warning('登录状态验证失败,请重新登录');
next({ path: '/' });
next({ path: '/user/login', query: { redirect: to.fullPath } });
return;
}
} else {
// 用户已登录但仍然验证一下token有效性不阻塞导航
setTimeout(async () => {
try {
const isLoggedIn = await checkLoginStatus();
if (!isLoggedIn) {
console.warn('登录状态已失效');
// 不中断用户操作,只显示提示
ElMessage.warning('登录已过期,请重新登录');
}
} catch (error) {
console.error('登录状态验证失败:', error);
}
}, 100);
}
}
@ -177,7 +200,7 @@ router.beforeEach(async (to, from, next) => {
// 检查用户是否登录且是否有管理员权限
if (!userStore.isLoggedIn) {
ElMessage.error('请先登录');
next({ path: '/' });
next({ path: '/user/login', query: { redirect: to.fullPath } });
return;
}

@ -20,12 +20,12 @@ export const useUserStore = defineStore('user', {
this.isLoggedIn = true;
this.userInfo = {
userid: userData.userid || 0,
username: userData.userName || '',
username: userData.userName || userData.username || '',
avatar: userData.avatar || '',
email: userData.email || '',
phone: userData.phone || '',
college: userData.college || '',
gender: userData.gender || 0,
gender: userData.gender !== undefined ? userData.gender : 0,
role: userData.role || 1,
status: userData.status || 1
};
@ -38,19 +38,22 @@ export const useUserStore = defineStore('user', {
localStorage.setItem('refreshToken', userData.refreshToken);
}
// 保存基本用户信息到localStorage用于页面刷新时恢复
// 保存完整用户信息到localStorage用于页面刷新时恢复
localStorage.setItem('userId', this.userInfo.userid);
localStorage.setItem('username', this.userInfo.username);
localStorage.setItem('avatar', this.userInfo.avatar || '');
localStorage.setItem('role', this.userInfo.role);
console.log('用户登录成功,状态已更新:', this.userInfo);
localStorage.setItem('email', this.userInfo.email || '');
localStorage.setItem('phone', this.userInfo.phone || '');
localStorage.setItem('college', this.userInfo.college || '');
localStorage.setItem('gender', this.userInfo.gender !== undefined ? String(this.userInfo.gender) : '0');
},
// 更新用户信息
updateUserInfo(userData) {
this.userInfo = {
...this.userInfo,
userid: userData.userid || this.userInfo.userid,
username: userData.username || this.userInfo.username,
avatar: userData.avatar || this.userInfo.avatar,
email: userData.email || this.userInfo.email,
@ -62,10 +65,14 @@ export const useUserStore = defineStore('user', {
};
// 更新localStorage中的用户信息
localStorage.setItem('userId', this.userInfo.userid);
localStorage.setItem('username', this.userInfo.username);
localStorage.setItem('avatar', this.userInfo.avatar || '');
console.log('用户信息已更新:', this.userInfo);
localStorage.setItem('role', this.userInfo.role);
localStorage.setItem('email', this.userInfo.email || '');
localStorage.setItem('phone', this.userInfo.phone || '');
localStorage.setItem('college', this.userInfo.college || '');
localStorage.setItem('gender', this.userInfo.gender !== undefined ? String(this.userInfo.gender) : '0');
},
logout() {
@ -89,8 +96,10 @@ export const useUserStore = defineStore('user', {
localStorage.removeItem('username');
localStorage.removeItem('avatar');
localStorage.removeItem('role');
console.log('用户已登出');
},
},
localStorage.removeItem('email');
localStorage.removeItem('phone');
localStorage.removeItem('college');
localStorage.removeItem('gender');
}
}
});

@ -13,49 +13,105 @@ export async function checkLoginStatus() {
// 如果没有token直接返回未登录
if (!accessToken || !refreshToken) {
console.log('本地没有找到token无需验证登录状态');
console.log('没有找到token用户未登录');
return false;
}
// 检查token格式是否正确
if (!isValidToken(accessToken) || !isValidToken(refreshToken)) {
console.log('Token格式不正确清除无效token');
console.log('token格式不正确清除token');
clearAuthTokens();
return false;
}
try {
console.log('正在验证登录状态...');
// 确保accessToken有Bearer前缀
const tokenWithPrefix = accessToken.startsWith('Bearer ') ? accessToken : `Bearer ${accessToken}`;
// 使用axios直接发送请求避免request拦截器中可能的循环依赖
const response = await axios.post('/user/check-login', null, {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Authorization': tokenWithPrefix,
'X-Refresh-Token': refreshToken
},
// 设置超时时间,避免长时间等待
timeout: 5000
});
if (response.data && response.data.code === 200 && response.data.data) {
console.log('登录状态有效,用户信息:', response.data.data);
console.log('登录状态有效');
// 获取用户数据
const userData = response.data.data;
// 更新用户状态
const userStore = useUserStore();
// 使用后端返回的用户数据更新前端状态
userStore.login({
userid: response.data.data.userId,
userName: response.data.data.username,
avatar: response.data.data.avatar,
role: response.data.data.role,
accessToken: response.data.data.accessToken || accessToken,
refreshToken: response.data.data.refreshToken || refreshToken
userid: userData.userId,
userName: userData.username,
avatar: userData.avatar,
role: userData.role || 1,
accessToken: userData.accessToken || accessToken,
refreshToken: userData.refreshToken || refreshToken
});
// 如果返回了新的token更新本地存储
if (response.data.data.accessToken) {
localStorage.setItem('accessToken', response.data.data.accessToken);
if (userData.accessToken) {
console.log('更新accessToken');
localStorage.setItem('accessToken', userData.accessToken);
}
if (userData.refreshToken) {
console.log('更新refreshToken');
localStorage.setItem('refreshToken', userData.refreshToken);
}
// 获取完整的用户信息
try {
// 确保使用最新的token
const currentAccessToken = userData.accessToken || accessToken;
const tokenWithPrefix = currentAccessToken.startsWith('Bearer ') ? currentAccessToken : `Bearer ${currentAccessToken}`;
const userInfoResponse = await axios.get('/user/info/getuserinfo', {
headers: {
'Authorization': tokenWithPrefix,
'X-Refresh-Token': userData.refreshToken || refreshToken
}
if (response.data.data.refreshToken) {
localStorage.setItem('refreshToken', response.data.data.refreshToken);
});
if (userInfoResponse.data && userInfoResponse.data.code === 200 && userInfoResponse.data.data) {
const fullUserInfo = userInfoResponse.data.data;
// 更新用户完整信息
userStore.updateUserInfo({
userid: fullUserInfo.id || userData.userId,
username: fullUserInfo.username,
avatar: fullUserInfo.avatar,
email: fullUserInfo.email,
phone: fullUserInfo.phone,
college: fullUserInfo.college,
gender: fullUserInfo.gender,
role: fullUserInfo.role,
status: fullUserInfo.status
});
// 确保localStorage中也有完整的用户信息
localStorage.setItem('userId', fullUserInfo.id || userData.userId);
localStorage.setItem('username', fullUserInfo.username);
localStorage.setItem('avatar', fullUserInfo.avatar || '');
localStorage.setItem('role', fullUserInfo.role);
localStorage.setItem('email', fullUserInfo.email || '');
localStorage.setItem('phone', fullUserInfo.phone || '');
localStorage.setItem('college', fullUserInfo.college || '');
localStorage.setItem('gender', fullUserInfo.gender !== undefined ? String(fullUserInfo.gender) : '0');
}
} catch (infoError) {
console.error('获取用户完整信息失败:', infoError);
// 获取用户完整信息失败,但不影响登录状态
}
return true;
@ -68,11 +124,15 @@ export async function checkLoginStatus() {
return false;
}
} catch (error) {
console.error('验证登录状态失败:', error);
console.error('验证登录状态时发生错误:', error);
if (error.response) {
console.error('错误响应:', error.response.status, error.response.data);
}
// 如果是网络错误、超时或服务器未响应保留token并尝试从localStorage恢复
if (!error.response || error.code === 'ECONNABORTED') {
console.log('网络错误或服务器未响应尝试从localStorage恢复登录状态');
console.log('网络错误或服务器未响应');
// 如果localStorage中有用户信息则维持登录状态
const userId = localStorage.getItem('userId');
@ -88,9 +148,12 @@ export async function checkLoginStatus() {
avatar: avatar || '',
role: role || 1,
accessToken: accessToken,
refreshToken: refreshToken
refreshToken: refreshToken,
email: localStorage.getItem('email') || '',
phone: localStorage.getItem('phone') || '',
college: localStorage.getItem('college') || '',
gender: localStorage.getItem('gender') ? parseInt(localStorage.getItem('gender')) : 0
});
console.log('从localStorage成功恢复用户登录状态:', username);
return true;
}

@ -2,6 +2,7 @@ import axios from 'axios';
import { clearAuthTokens } from './auth';
import { ElMessage } from 'element-plus';
// 创建axios实例
const request = axios.create({
timeout: 5000
});
@ -47,8 +48,6 @@ request.interceptors.response.use(
return Promise.reject(response.data);
},
error => {
console.error('请求错误:', error);
// 如果响应状态码是401或500可能是token过期或格式错误
if (error.response && (error.response.status === 401 ||
(error.response.status === 500 && error.response.data?.message?.includes('token')))) {
@ -59,7 +58,6 @@ request.interceptors.response.use(
// 如果是500错误且与token相关直接清除token并拒绝请求
if (error.response.status === 500 && error.response.data?.message?.includes('token')) {
console.error('Token格式错误:', error.response.data.message);
clearAuthTokens();
if (needAuth) {
ElMessage.warning('登录已失效,请重新登录');
@ -88,21 +86,29 @@ request.interceptors.response.use(
return Promise.reject(error);
}
// 确保accessToken有Bearer前缀
const tokenWithPrefix = accessToken.startsWith('Bearer ') ? accessToken : `Bearer ${accessToken}`;
console.log('尝试刷新token...');
// 调用check-login接口刷新token
return axios.post('/user/check-login', null, {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Authorization': tokenWithPrefix,
'X-Refresh-Token': refreshToken
}
}).then(res => {
if (res.data && res.data.code === 200 && res.data.data) {
console.log('Token刷新成功');
// 更新token
const { accessToken, refreshToken } = res.data.data;
localStorage.setItem('accessToken', accessToken);
localStorage.setItem('refreshToken', refreshToken);
// 确保新token有Bearer前缀
const newTokenWithPrefix = accessToken.startsWith('Bearer ') ? accessToken : `Bearer ${accessToken}`;
// 更新原始请求的Authorization头
originalRequest.headers['Authorization'] = `Bearer ${accessToken}`;
originalRequest.headers['Authorization'] = newTokenWithPrefix;
originalRequest.headers['X-Refresh-Token'] = refreshToken;
// 处理队列中的请求
@ -111,6 +117,7 @@ request.interceptors.response.use(
// 重新发送原始请求
return axios(originalRequest);
} else {
console.warn('Token刷新失败:', res.data);
processQueue(new Error('刷新Token失败'), null);
if (needAuth) {
// 不清除token只提示用户
@ -119,6 +126,7 @@ request.interceptors.response.use(
return Promise.reject(error);
}
}).catch(err => {
console.error('Token刷新出错:', err);
processQueue(err, null);
if (needAuth) {
// 只有在确认token格式错误时才清除
@ -137,7 +145,9 @@ request.interceptors.response.use(
return new Promise((resolve, reject) => {
requestsQueue.push({
resolve: token => {
originalRequest.headers['Authorization'] = `Bearer ${token}`;
// 确保token有Bearer前缀
const tokenWithPrefix = token.startsWith('Bearer ') ? token : `Bearer ${token}`;
originalRequest.headers['Authorization'] = tokenWithPrefix;
resolve(axios(originalRequest));
},
reject: err => {
@ -155,7 +165,6 @@ request.interceptors.response.use(
//请求拦截器
request.interceptors.request.use(
config => {
console.log('Request:', config.url);
// 只对非认证相关的API添加token
if (!config.url.includes('/captcha') && !config.url.includes('/verify-captcha') &&
!config.url.includes('/user/login') && !config.url.includes('/user/register')) {
@ -164,13 +173,14 @@ request.interceptors.request.use(
// 检查token格式是否正确
if (token && refreshToken && typeof token === 'string' && typeof refreshToken === 'string') {
config.headers['Authorization'] = `Bearer ${token}`;
// 确保添加Bearer前缀
config.headers['Authorization'] = token.startsWith('Bearer ') ? token : `Bearer ${token}`;
config.headers['X-Refresh-Token'] = refreshToken;
console.log('添加token到请求头:', config.url);
} else if ((token && typeof token !== 'string') ||
(refreshToken && typeof refreshToken !== 'string')) {
// 只有当token格式明显错误时才清除
console.warn('Token格式不正确清除token');
console.warn('Token格式错误清除token');
clearAuthTokens();
} else if (!token || !refreshToken) {
// 如果没有token但访问需要认证的API尝试从localStorage恢复

@ -226,15 +226,22 @@ const loadUserInfo = async () => {
if (isCurrentUser.value) {
const storedUsername = localStorage.getItem('username');
const storedAvatar = localStorage.getItem('avatar');
const storedEmail = localStorage.getItem('email');
const storedPhone = localStorage.getItem('phone');
const storedCollege = localStorage.getItem('college');
const storedGender = localStorage.getItem('gender');
if (storedUsername) {
userInfo.value = {
username: storedUsername,
avatar: storedAvatar || '',
role: localStorage.getItem('role') || 1,
userId: localStorage.getItem('userId')
userId: localStorage.getItem('userId'),
email: storedEmail || '',
phone: storedPhone || '',
college: storedCollege || '',
gender: storedGender ? parseInt(storedGender) : 0
};
console.log('从localStorage恢复用户基本信息:', storedUsername);
}
}
@ -245,10 +252,24 @@ const loadUserInfo = async () => {
timeout: 5000
});
console.log('获取用户信息响应:', response);
console.log('获取用户信息响应');
if (response && response.code === 200) {
userInfo.value = response.data;
console.log('加载到的用户信息:', userInfo.value);
// userStore
if (isCurrentUser.value && userStore) {
userStore.updateUserInfo({
userid: response.data.id,
username: response.data.username,
avatar: response.data.avatar,
email: response.data.email,
phone: response.data.phone,
college: response.data.college,
gender: response.data.gender,
role: response.data.role,
status: response.data.status
});
}
//
if (isCurrentUser.value) {
@ -260,14 +281,17 @@ const loadUserInfo = async () => {
// localStorage使
if ((!error.response || error.code === 'ECONNABORTED') && userInfo.value.username) {
console.log('网络错误,但已恢复基本用户信息,继续使用');
// 使
} else if (isCurrentUser.value) {
// userStore
userInfo.value = {
username: userStore.userInfo.username || '用户',
avatar: userStore.userInfo.avatar || '',
userId: userStore.userInfo.userid
userId: userStore.userInfo.userid,
email: userStore.userInfo.email || '',
phone: userStore.userInfo.phone || '',
college: userStore.userInfo.college || '',
gender: userStore.userInfo.gender || 0
};
} else {
//
@ -287,7 +311,7 @@ const loadUserPosts = async () => {
...pageParams
}
});
console.log('加载用户帖子响应:', response.data.records);
console.log('加载用户帖子响应');
if (response && response.code === 200) {
const newPosts = response.data.records || [];
userPosts.value = [...userPosts.value, ...newPosts];

Loading…
Cancel
Save