修改登录报错
All checks were successful
构建并部署 Spring Boot 应用 / build-and-deploy (push) Successful in 16m1s

This commit is contained in:
2025-10-26 15:07:09 +08:00
parent adb04d34ca
commit ac25cad1db
2 changed files with 237 additions and 182 deletions

View File

@@ -1,117 +1,67 @@
package com.light.delivery.controller;
import com.light.delivery.dto.UserInfoResponse;
import com.light.delivery.dto.SignOutResponse;
import com.light.delivery.dto.SignInResponse;
import com.light.delivery.model.LoginResponse;
import com.light.delivery.model.RegisterRequest;
import com.light.delivery.model.User;
import com.light.delivery.model.UserRole;
import com.light.delivery.model.WxLoginRequest;
import com.light.delivery.service.LocationWebSocketHandler;
import com.light.delivery.service.UserService;
import com.light.delivery.service.impl.UserServiceImpl;
import com.light.delivery.util.JwtUtil;
import com.light.delivery.model.RegisterRequest;
import com.light.delivery.dto.SignInResponse;
import com.light.delivery.dto.SignOutResponse;
import com.light.delivery.model.WxLoginRequest;
import com.light.delivery.model.LoginResponse;
import com.light.delivery.model.UserRole;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.Map;
/**
* 用户相关接口控制器,提供登录、获取用户信息、登出等功能
* 处理用户认证、授权和基本信息管理等相关HTTP请求
* 用户控制器处理用户相关的HTTP请求
* 包括登录、注册、签到、签退等核心功能
*/
@RestController
@RequestMapping("/user")
public class UserController {
/**
* 用户服务层依赖注入。
*/
@Autowired
private UserService userService;
/**
* Jwt工具类依赖注入。
*/
@Autowired
private JwtUtil jwtUtil;
/**
* UserServiceImpl依赖注入用于获取用户角色。
*/
@Autowired
private UserServiceImpl userServiceImpl;
/**
* ApplicationContext依赖注入用于获取其他Bean。
*/
@Autowired
private ApplicationContext applicationContext;
/**
* 获取当前用户状态接口
* @param request HTTP请求对象,用于提取认证令牌
* @return 当前用户状态信息
* 提取请求中的JWT令牌
* @param request HTTP请求对象
* @return JWT令牌字符串如果不存在则返回null
*/
@GetMapping("/status")
public ResponseEntity<?> getUserStatus(HttpServletRequest request) {
String token = extractToken(request);
if (token == null) {
return ResponseEntity.badRequest().body("Authorization token is missing");
}
try {
User user = userService.getUserInfo(token);
// 创建响应对象
Map<String, Object> statusResponse = new HashMap<>();
// 根据用户角色和信息完整性判断状态
String status;
UserRole userRole = userServiceImpl.getUserRole(user);
if (userRole == null || userRole == UserRole.GUEST) {
// 未注册用户
status = "unregistered";
} else {
// 已注册,检查签到状态
if (userService.isUserSignedIn(user.getId())) {
status = "signed_in";
} else {
status = "signed_out";
}
}
statusResponse.put("status", status);
// TODO: 添加最后签到/签退时间(需要在数据库中存储这些信息)
return ResponseEntity.ok(statusResponse);
} catch (Exception e) {
return ResponseEntity.badRequest().body("Invalid token: " + e.getMessage());
private String extractToken(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
/**
* 获取当前用户信息接口。
* 获取用户信息接口。
* @param request HTTP请求对象用于提取认证令牌
* @return 当前用户信息
* @return 用户信息响应对象
*/
@GetMapping("/info")
public ResponseEntity<?> getUserInfo(HttpServletRequest request) {
String token = extractToken(request);
if (token == null) {
return ResponseEntity.badRequest().body("Authorization token is missing");
}
try {
String token = extractToken(request);
if (token == null) {
return ResponseEntity.badRequest().body("Authorization token is missing");
}
User user = userService.getUserInfo(token);
UserInfoResponse response = toUserInfoResponse(user);
return ResponseEntity.ok(response);
@@ -123,73 +73,59 @@ public class UserController {
/**
* 将User实体转换为UserInfoResponse DTO。
* @param user 用户实体
* @return 用户信息响应DTO
* @return 用户信息响应对象
*/
private UserInfoResponse toUserInfoResponse(User user) {
if (user == null) return null;
UserInfoResponse dto = new UserInfoResponse();
dto.setId(user.getId());
dto.setOpenid(user.getOpenid());
if (user == null) {
return null;
}
// 通过UserService获取完整的用户信息
UserInfoResponse response = new UserInfoResponse();
response.setId(user.getId());
response.setOpenid(user.getOpenid());
// 注意UserInfoResponse中没有setEmployeeId方法我们不设置这个字段
// 直接使用UserServiceImpl中的toUserInfoResponse方法获取完整信息
try {
UserInfoResponse fullInfo = userServiceImpl.toUserInfoResponse(user);
dto.setName(fullInfo.getName());
dto.setPhone(fullInfo.getPhone());
dto.setRole(fullInfo.getRole());
if (userService instanceof com.light.delivery.service.impl.UserServiceImpl) {
UserInfoResponse fullInfo = ((com.light.delivery.service.impl.UserServiceImpl) userService).toUserInfoResponse(user);
if (fullInfo != null) {
response.setName(fullInfo.getName());
response.setPhone(fullInfo.getPhone());
response.setRole(fullInfo.getRole());
response.setAvatarPath(fullInfo.getAvatarPath());
}
}
} catch (Exception e) {
System.err.println("获取员工信息时出错: " + e.getMessage());
dto.setRole(UserRole.GUEST.getCode());
System.err.println("获取完整用户信息时出错: " + e.getMessage());
}
return dto;
return response;
}
/**
* 从HTTP请求头中提取JWT令牌。
* @param request HTTP请求对象
* @return JWT令牌字符串
*/
private String extractToken(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
// 内部类,用于接收位置信息的初始数据
public static class InitialLocation {
private Double latitude;
private Double longitude;
private Long timestamp;
/**
* 用户登出接口。
* @param request HTTP请求对象用于提取认证令牌
* @return 操作结果
*/
@PostMapping("/logout")
public ResponseEntity<String> logout(HttpServletRequest request) {
String token = extractToken(request);
userService.logout(token);
return ResponseEntity.ok("登出成功");
}
/**
* 微信小程序登录接口接收code返回openid和token。
* @param wxLoginRequest 微信登录请求对象
* @return 登录响应
*/
@PostMapping("/wxlogin")
public ResponseEntity<LoginResponse> wxLogin(@RequestBody WxLoginRequest wxLoginRequest) {
System.out.println("[wxLogin] 收到请求参数: code=" + wxLoginRequest.getCode());
LoginResponse loginResponse = userService.wxLogin(wxLoginRequest.getCode());
return ResponseEntity.ok(loginResponse);
// Getters and setters
public Double getLatitude() { return latitude; }
public void setLatitude(Double latitude) { this.latitude = latitude; }
public Double getLongitude() { return longitude; }
public void setLongitude(Double longitude) { this.longitude = longitude; }
public Long getTimestamp() { return timestamp; }
public void setTimestamp(Long timestamp) { this.timestamp = timestamp; }
}
/**
* 用户签到接口。
* @param request HTTP请求对象用于提取认证令牌
* @param initialLocation 初始位置信息
* @return 更新后的用户信息
* @return 操作结果
*/
@PostMapping("/signin")
public ResponseEntity<?> signIn(HttpServletRequest request, @RequestBody LocationWebSocketHandler.LocationData initialLocation) {
public ResponseEntity<?> signIn(HttpServletRequest request, @RequestBody InitialLocation initialLocation) {
String token = extractToken(request);
if (token == null) {
return ResponseEntity.badRequest().body(new SignInResponse(false, "Authorization token is missing"));
@@ -213,7 +149,13 @@ public class UserController {
// 通知WebSocket处理器用户已签到并自动订阅
try {
LocationWebSocketHandler handler = applicationContext.getBean(LocationWebSocketHandler.class);
handler.userSignedIn(user.getId(), initialLocation);
// 创建LocationWebSocketHandler中的位置数据对象
LocationWebSocketHandler.LocationData locationData = new LocationWebSocketHandler.LocationData(
initialLocation.getLatitude(),
initialLocation.getLongitude(),
initialLocation.getTimestamp() != null ? initialLocation.getTimestamp() : System.currentTimeMillis()
);
handler.userSignedIn(user.getId(), locationData);
} catch (Exception e) {
System.err.println("通知WebSocket签到状态时出错: " + e.getMessage());
}
@@ -253,6 +195,112 @@ public class UserController {
}
}
/**
* 微信登录接口。
* @param wxLoginRequest 微信登录请求对象包含登录凭证code
* @return 登录响应对象包含JWT令牌和用户信息
*/
@PostMapping("/wxlogin")
public ResponseEntity<?> wxLogin(@RequestBody WxLoginRequest wxLoginRequest) {
try {
System.out.println("收到微信登录请求code: " + wxLoginRequest.getCode());
if (wxLoginRequest.getCode() == null || wxLoginRequest.getCode().trim().isEmpty()) {
return ResponseEntity.badRequest().body("登录code不能为空");
}
LoginResponse response = userService.wxLogin(wxLoginRequest);
System.out.println("微信登录成功,返回用户信息: " + response);
return ResponseEntity.ok(response);
} catch (Exception e) {
System.err.println("微信登录失败: " + e.getMessage());
e.printStackTrace();
return ResponseEntity.status(500).body("登录失败: " + e.getMessage());
}
}
/**
* 用户登出接口。
* @param request HTTP请求对象用于提取认证令牌
* @return 操作结果
*/
@PostMapping("/logout")
public ResponseEntity<?> logout(HttpServletRequest request) {
try {
String token = extractToken(request);
if (token == null) {
return ResponseEntity.badRequest().body("Authorization token is missing");
}
userService.logout(token);
return ResponseEntity.ok().body(Map.of("success", true, "message", "登出成功"));
} catch (Exception e) {
return ResponseEntity.badRequest().body("登出失败: " + e.getMessage());
}
}
/**
* 获取用户状态接口。
* @param request HTTP请求对象用于提取认证令牌
* @return 用户状态信息
*/
@GetMapping("/status")
public ResponseEntity<?> getUserStatus(HttpServletRequest request) {
try {
String token = extractToken(request);
if (token == null) {
return ResponseEntity.badRequest().body(Map.of(
"success", false,
"message", "Authorization token is missing"
));
}
User user = userService.getUserInfo(token);
if (user == null) {
return ResponseEntity.badRequest().body(Map.of(
"success", false,
"message", "用户不存在"
));
}
Map<String, Object> response = new HashMap<>();
response.put("success", true);
// 检查用户是否已注册为员工
if (user.getEmployeeId() != null) {
// 检查用户是否已签到
boolean isSignedIn = userService.isUserSignedIn(user.getId());
if (isSignedIn) {
response.put("status", "signed_in");
// 获取最后更新时间
try {
LocationWebSocketHandler handler = applicationContext.getBean(LocationWebSocketHandler.class);
Long lastUpdateTime = handler.getLastUpdateTime(user.getId());
if (lastUpdateTime != null) {
response.put("lastSignInTime", lastUpdateTime);
}
} catch (Exception e) {
System.err.println("获取最后签到时间时出错: " + e.getMessage());
}
} else {
response.put("status", "registered");
}
} else {
// 用户未注册
response.put("status", "unregistered");
}
return ResponseEntity.ok(response);
} catch (Exception e) {
System.err.println("获取用户状态时出错: " + e.getMessage());
e.printStackTrace();
return ResponseEntity.badRequest().body(Map.of(
"success", false,
"message", "获取用户状态失败: " + e.getMessage()
));
}
}
/**
* 绑定为正式员工接口。
* @param request HTTP请求对象用于提取认证令牌

View File

@@ -93,7 +93,9 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
if (initialLocation != null) {
UserLocation userLocation = new UserLocation();
userLocation.setUserId(userId);
userLocation.setLocationData(initialLocation);
userLocation.setLatitude(initialLocation.getLatitude());
userLocation.setLongitude(initialLocation.getLongitude());
userLocation.setTimestamp(initialLocation.getTimestamp());
userLocations.put(userId, userLocation);
System.out.println("初始位置已存储: " + initialLocation.getLatitude() + ", " + initialLocation.getLongitude());
}
@@ -226,7 +228,7 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
*/
public Double getUserLatitude(Long userId) {
UserLocation userLocation = userLocations.get(userId);
return userLocation != null ? userLocation.getLocationData().getLatitude() : null;
return userLocation != null ? userLocation.getLatitude() : null;
}
/**
@@ -236,7 +238,7 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
*/
public Double getUserLongitude(Long userId) {
UserLocation userLocation = userLocations.get(userId);
return userLocation != null ? userLocation.getLocationData().getLongitude() : null;
return userLocation != null ? userLocation.getLongitude() : null;
}
/**
@@ -381,14 +383,11 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
// 存储用户位置信息
UserLocation userLocation = new UserLocation();
userLocation.setUserId(userId);
LocationData locationData = new LocationData();
locationData.setLatitude(locationMessage.getLatitude());
locationData.setLongitude(locationMessage.getLongitude());
locationData.setTimestamp(locationMessage.getTimestamp() != null ?
userLocation.setLatitude(locationMessage.getLatitude());
userLocation.setLongitude(locationMessage.getLongitude());
userLocation.setTimestamp(locationMessage.getTimestamp() != null ?
locationMessage.getTimestamp() : System.currentTimeMillis());
userLocation.setLocationData(locationData);
userLocations.put(userId, userLocation);
System.out.println("已存储用户 " + userId + " 的位置信息");
@@ -428,7 +427,7 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
.map(userInfo -> {
// 如果有位置信息,也一并发送
UserLocation userLocation = userLocations.get(userInfo.getUserId());
if (userLocation != null && userLocation.getLocationData() != null) {
if (userLocation != null) {
// 创建包含位置信息的用户信息对象
UserInfo userInfoWithLocation = new UserInfo();
userInfoWithLocation.setUserId(userInfo.getUserId());
@@ -437,13 +436,9 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
userInfoWithLocation.setAvatarPath(userInfo.getAvatarPath()); // 设置头像路径
userInfoWithLocation.setUserStatus(userInfo.isUserStatus());
userInfoWithLocation.setLastUpdateTime(userInfo.getLastUpdateTime());
LocationData locationData = new LocationData();
locationData.setLatitude(userLocation.getLocationData().getLatitude());
locationData.setLongitude(userLocation.getLocationData().getLongitude());
locationData.setTimestamp(userLocation.getLocationData().getTimestamp());
userInfoWithLocation.setLocationData(locationData);
userInfoWithLocation.setLatitude(userLocation.getLatitude());
userInfoWithLocation.setLongitude(userLocation.getLongitude());
userInfoWithLocation.setTimestamp(userLocation.getTimestamp());
return userInfoWithLocation;
}
return userInfo;
@@ -477,7 +472,7 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
System.out.println("处理用户: " + userInfo.getUserId() + ", 状态: " + userInfo.isUserStatus());
// 如果有位置信息,也一并发送
UserLocation userLocation = userLocations.get(userInfo.getUserId());
if (userLocation != null && userLocation.getLocationData() != null) {
if (userLocation != null) {
System.out.println("用户 " + userInfo.getUserId() + " 有位置信息");
// 创建包含位置信息的用户信息对象
UserInfo userInfoWithLocation = new UserInfo();
@@ -487,13 +482,9 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
userInfoWithLocation.setAvatarPath(userInfo.getAvatarPath()); // 设置头像路径
userInfoWithLocation.setUserStatus(userInfo.isUserStatus());
userInfoWithLocation.setLastUpdateTime(userInfo.getLastUpdateTime());
LocationData locationData = new LocationData();
locationData.setLatitude(userLocation.getLocationData().getLatitude());
locationData.setLongitude(userLocation.getLocationData().getLongitude());
locationData.setTimestamp(userLocation.getLocationData().getTimestamp());
userInfoWithLocation.setLocationData(locationData);
userInfoWithLocation.setLatitude(userLocation.getLatitude());
userInfoWithLocation.setLongitude(userLocation.getLongitude());
userInfoWithLocation.setTimestamp(userLocation.getTimestamp());
return userInfoWithLocation;
}
System.out.println("用户 " + userInfo.getUserId() + " 没有位置信息");
@@ -561,7 +552,9 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
if (userLocation != null) {
UserLocation broadcastLocation = new UserLocation();
broadcastLocation.setUserId(userId);
broadcastLocation.setLocationData(userLocation.getLocationData());
broadcastLocation.setLatitude(userLocation.getLatitude());
broadcastLocation.setLongitude(userLocation.getLongitude());
broadcastLocation.setTimestamp(userLocation.getTimestamp());
return broadcastLocation;
}
return null;
@@ -796,9 +789,11 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
private String name;
private UserRole role;
private String avatarPath;
private LocationData locationData;
private boolean userStatus;
private Long lastUpdateTime;
private Double latitude;
private Double longitude;
private Long timestamp;
// 添加无参构造函数
public UserInfo() {}
@@ -811,14 +806,52 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
public void setRole(UserRole role) { this.role = role; }
public String getAvatarPath() { return avatarPath; }
public void setAvatarPath(String avatarPath) { this.avatarPath = avatarPath; }
public LocationData getLocationData() { return locationData; }
public void setLocationData(LocationData locationData) { this.locationData = locationData; }
public boolean isUserStatus() { return userStatus; }
public void setUserStatus(boolean userStatus) { this.userStatus = userStatus; }
public Long getLastUpdateTime() { return lastUpdateTime; }
public void setLastUpdateTime(Long lastUpdateTime) { this.lastUpdateTime = lastUpdateTime; }
public Double getLatitude() { return latitude; }
public void setLatitude(Double latitude) { this.latitude = latitude; }
public Double getLongitude() { return longitude; }
public void setLongitude(Double longitude) { this.longitude = longitude; }
public Long getTimestamp() { return timestamp; }
public void setTimestamp(Long timestamp) { this.timestamp = timestamp; }
}
// 删除了LocationData类将字段直接放在UserLocation类中
public static class UserLocation {
private Long userId;
private Double latitude;
private Double longitude;
private Long timestamp;
// 添加无参构造函数
public UserLocation() {}
public Long getUserId() { return userId; }
public void setUserId(Long userId) { this.userId = userId; }
public Double getLatitude() { return latitude; }
public void setLatitude(Double latitude) { this.latitude = latitude; }
public Double getLongitude() { return longitude; }
public void setLongitude(Double longitude) { this.longitude = longitude; }
public Long getTimestamp() { return timestamp; }
public void setTimestamp(Long timestamp) { this.timestamp = timestamp; }
}
public static class UserLocationListMessage {
private String type;
private List<UserLocation> users;
// 添加无参构造函数
public UserLocationListMessage() {}
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public List<UserLocation> getUsers() { return users; }
public void setUsers(List<UserLocation> users) { this.users = users; }
}
// 重新添加LocationData类供外部调用使用
public static class LocationData {
private Double latitude;
private Double longitude;
@@ -841,30 +874,4 @@ public class LocationWebSocketHandler extends TextWebSocketHandler {
public Long getTimestamp() { return timestamp; }
public void setTimestamp(Long timestamp) { this.timestamp = timestamp; }
}
public static class UserLocation {
private Long userId;
private LocationData locationData;
// 添加无参构造函数
public UserLocation() {}
public Long getUserId() { return userId; }
public void setUserId(Long userId) { this.userId = userId; }
public LocationData getLocationData() { return locationData; }
public void setLocationData(LocationData locationData) { this.locationData = locationData; }
}
public static class UserLocationListMessage {
private String type;
private List<UserLocation> users;
// 添加无参构造函数
public UserLocationListMessage() {}
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public List<UserLocation> getUsers() { return users; }
public void setUsers(List<UserLocation> users) { this.users = users; }
}
}