From ac25cad1db69030241b51a6d0b8477221d1a6f4d Mon Sep 17 00:00:00 2001 From: Doubleyin <953994191@qq.com> Date: Sun, 26 Oct 2025 15:07:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=99=BB=E5=BD=95=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../delivery/controller/UserController.java | 302 ++++++++++-------- .../service/LocationWebSocketHandler.java | 117 +++---- 2 files changed, 237 insertions(+), 182 deletions(-) diff --git a/src/main/java/com/light/delivery/controller/UserController.java b/src/main/java/com/light/delivery/controller/UserController.java index 21c6967..c8c31eb 100644 --- a/src/main/java/com/light/delivery/controller/UserController.java +++ b/src/main/java/com/light/delivery/controller/UserController.java @@ -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 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; + + // 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请求对象,用于提取认证令牌 - * @return 操作结果 - */ - @PostMapping("/logout") - public ResponseEntity logout(HttpServletRequest request) { - String token = extractToken(request); - userService.logout(token); - return ResponseEntity.ok("登出成功"); - } - - /** - * 微信小程序登录接口,接收code,返回openid和token。 - * @param wxLoginRequest 微信登录请求对象 - * @return 登录响应 - */ - @PostMapping("/wxlogin") - public ResponseEntity wxLogin(@RequestBody WxLoginRequest wxLoginRequest) { - System.out.println("[wxLogin] 收到请求参数: code=" + wxLoginRequest.getCode()); - LoginResponse loginResponse = userService.wxLogin(wxLoginRequest.getCode()); - return ResponseEntity.ok(loginResponse); - } - /** * 用户签到接口。 * @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 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请求对象,用于提取认证令牌 diff --git a/src/main/java/com/light/delivery/service/LocationWebSocketHandler.java b/src/main/java/com/light/delivery/service/LocationWebSocketHandler.java index 28acabe..92e66e0 100644 --- a/src/main/java/com/light/delivery/service/LocationWebSocketHandler.java +++ b/src/main/java/com/light/delivery/service/LocationWebSocketHandler.java @@ -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 users; + + // 添加无参构造函数 + public UserLocationListMessage() {} + + public String getType() { return type; } + public void setType(String type) { this.type = type; } + public List getUsers() { return users; } + public void setUsers(List 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 users; - - // 添加无参构造函数 - public UserLocationListMessage() {} - - public String getType() { return type; } - public void setType(String type) { this.type = type; } - public List getUsers() { return users; } - public void setUsers(List users) { this.users = users; } - } } \ No newline at end of file