修改用户角色,添加管理员相关逻辑
Some checks failed
构建并部署 Spring Boot 应用 / build-and-deploy (push) Has been cancelled
Some checks failed
构建并部署 Spring Boot 应用 / build-and-deploy (push) Has been cancelled
This commit is contained in:
47
README.md
47
README.md
@@ -35,6 +35,11 @@ Light Delivery 是一个为小程序配送服务设计的后端系统,提供
|
||||
- REST API位置查询接口
|
||||
- 位置过期处理机制
|
||||
|
||||
### 5. 员工管理(新增)
|
||||
- 员工信息维护(仅限管理员)
|
||||
- 员工增删改查功能
|
||||
- 员工角色管理(管理员/配送员)
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
@@ -93,9 +98,20 @@ src
|
||||
- 所有用户首先以游客身份静默登录,创建User记录
|
||||
- 用户签到或注册时,系统根据手机号在Employee表中查找匹配记录
|
||||
- 如果匹配成功,将用户的openid写入Employee表,表示该员工已成为系统用户
|
||||
- 根据Employee中的角色信息更新User的角色
|
||||
- 根据Employee中的角色信息动态确定User的角色
|
||||
- 对于配送员,还会创建或更新DeliveryPerson记录
|
||||
|
||||
### 用户角色管理优化(新增)
|
||||
|
||||
为了解决数据一致性问题,我们对用户角色管理进行了优化:
|
||||
|
||||
1. 移除了User表中的role字段,避免在User表和Employee表中重复维护角色信息
|
||||
2. 用户角色现在完全通过Employee表进行管理
|
||||
3. 当需要获取用户角色时,系统会根据用户的手机号在Employee表中查找对应记录
|
||||
4. 如果用户未注册(没有手机号)或在Employee表中找不到对应记录,则默认为游客角色
|
||||
|
||||
这种设计确保了数据的一致性,避免了在多个表中维护相同信息可能带来的问题。
|
||||
|
||||
## 本地开发与测试
|
||||
|
||||
### 环境配置
|
||||
@@ -103,7 +119,7 @@ src
|
||||
项目支持多种运行环境配置:
|
||||
|
||||
1. **本地开发环境** (`local`)
|
||||
- 端口: 8443
|
||||
- 端口: 8080
|
||||
- 数据库: 远程MySQL (与生产环境相同)
|
||||
- SSL: 禁用
|
||||
- 日志级别: DEBUG
|
||||
@@ -132,7 +148,7 @@ src
|
||||
|
||||
```bash
|
||||
# 使用local配置文件运行
|
||||
mvn spring-boot:run -Dspring-boot.run.profiles=local
|
||||
mvn spring-boot:run -D"spring.profiles.active"="local"
|
||||
|
||||
# 或者使用test配置文件运行(使用内存数据库)
|
||||
mvn spring-boot:run -Dspring-boot.run.profiles=test
|
||||
@@ -158,7 +174,7 @@ java -jar target/light-delivery-1.0.0.jar --spring.profiles.active=test
|
||||
build-local.bat
|
||||
|
||||
# 运行容器
|
||||
docker run -d --name light-delivery -p 8443:8443 light-delivery-app
|
||||
docker run -d --name light-delivery -p 8080:8080 light-delivery-app
|
||||
```
|
||||
|
||||
## 部署说明
|
||||
@@ -234,11 +250,32 @@ deploy.bat
|
||||
- `GET /delivery-persons/{id}` - 获取配送员详情
|
||||
- `PUT /delivery-persons/{id}/location` - 更新配送员位置
|
||||
|
||||
### 员工管理相关(仅限管理员访问)
|
||||
- `GET /employees` - 获取员工列表
|
||||
- `POST /employees` - 添加员工
|
||||
- `PUT /employees/{id}` - 更新员工信息
|
||||
- `DELETE /employees/{id}` - 删除员工
|
||||
|
||||
### 位置同步相关
|
||||
- `GET /location-sync/delivery-persons/locations` - 获取所有配送员位置
|
||||
|
||||
## 最近更新
|
||||
|
||||
### 用户角色管理优化(新增)
|
||||
为解决数据一致性问题,我们优化了用户角色管理机制:
|
||||
- 移除了User表中的role字段
|
||||
- 用户角色现在完全通过Employee表进行管理
|
||||
- 系统会根据用户的手机号在Employee表中动态查找角色信息
|
||||
- 未注册用户默认为游客角色
|
||||
|
||||
### 员工管理功能(新增)
|
||||
为便于管理员维护员工信息,我们新增了员工管理功能:
|
||||
- 新增EmployeeController控制器,提供员工信息的增删改查接口
|
||||
- 新增EmployeeService服务层,处理员工相关的业务逻辑
|
||||
- 新增EmployeeDto数据传输对象,用于前后端数据交互
|
||||
- 添加权限控制,仅管理员可访问员工管理接口
|
||||
- 添加全局异常处理机制
|
||||
|
||||
### 位置历史记录功能移除
|
||||
为了简化系统架构并提高性能,我们移除了位置历史记录功能。具体变更包括:
|
||||
- 删除了`LocationHistory`实体类
|
||||
@@ -254,3 +291,5 @@ deploy.bat
|
||||
2. 所有敏感接口都需要通过JWT Token认证
|
||||
3. 配送员位置信息具有时效性,默认5分钟内有效
|
||||
4. 位置历史记录功能已被移除,如有需要可使用第三方服务进行位置追踪
|
||||
5. 员工管理接口仅限管理员角色访问
|
||||
6. 用户角色信息现在通过员工表动态获取,确保数据一致性
|
@@ -1,13 +1,13 @@
|
||||
package com.light.delivery.controller;
|
||||
|
||||
import com.light.delivery.dto.UserInfoResponse;
|
||||
import com.light.delivery.dto.UserResponse;
|
||||
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.UserService;
|
||||
import com.light.delivery.service.impl.UserServiceImpl;
|
||||
import com.light.delivery.util.JwtUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -40,6 +40,12 @@ public class UserController {
|
||||
@Autowired
|
||||
private JwtUtil jwtUtil;
|
||||
|
||||
/**
|
||||
* UserServiceImpl依赖注入,用于获取用户角色。
|
||||
*/
|
||||
@Autowired
|
||||
private UserServiceImpl userServiceImpl;
|
||||
|
||||
/**
|
||||
* 获取当前用户状态接口。
|
||||
* @param request HTTP请求对象,用于提取认证令牌
|
||||
@@ -60,7 +66,8 @@ public class UserController {
|
||||
|
||||
// 根据用户角色和信息完整性判断状态
|
||||
String status;
|
||||
if (user.getRole() == null || user.getRole() == UserRole.GUEST) {
|
||||
UserRole userRole = userServiceImpl.getUserRole(user);
|
||||
if (userRole == null || userRole == UserRole.GUEST) {
|
||||
// 未注册用户
|
||||
status = "unregistered";
|
||||
} else if ((user.getName() == null || user.getName().isEmpty()) &&
|
||||
@@ -118,7 +125,9 @@ public class UserController {
|
||||
dto.setId(user.getId());
|
||||
dto.setName(user.getName());
|
||||
dto.setPhone(user.getPhone());
|
||||
dto.setRole(user.getRole() != null ? user.getRole().getCode() : null);
|
||||
// 从员工表获取角色信息
|
||||
UserRole userRole = userServiceImpl.getUserRole(user);
|
||||
dto.setRole(userRole != null ? userRole.getCode() : null);
|
||||
dto.setOpenid(user.getOpenid());
|
||||
return dto;
|
||||
}
|
||||
@@ -173,7 +182,6 @@ public class UserController {
|
||||
}
|
||||
|
||||
try {
|
||||
String username = jwtUtil.getUsernameFromToken(token);
|
||||
User user = userService.getUserInfo(token);
|
||||
User updatedUser = userService.signIn(user.getId());
|
||||
UserInfoResponse response = toUserInfoResponse(updatedUser);
|
||||
|
@@ -30,12 +30,6 @@ public class User {
|
||||
@Column(name = "phone")
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* 用户角色(如 ADMIN, DELIVERY_PERSON, GUEST)
|
||||
*/
|
||||
@Enumerated(EnumType.STRING)
|
||||
private UserRole role;
|
||||
|
||||
/**
|
||||
* 微信用户唯一标识
|
||||
*/
|
||||
|
@@ -96,6 +96,7 @@ public class UserServiceImpl implements UserService {
|
||||
if (user == null) {
|
||||
throw new IllegalArgumentException("用户不存在");
|
||||
}
|
||||
|
||||
return user;
|
||||
} catch (Exception e) {
|
||||
// 捕获JWT解析异常等
|
||||
@@ -127,12 +128,10 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
|
||||
// 如果用户是配送员,通知WebSocket处理器清理连接
|
||||
if (UserRole.DELIVERY_PERSON.equals(user.getRole())) {
|
||||
// 注意:这里需要根据实际业务逻辑获取配送员ID
|
||||
// 可能需要通过其他方式关联用户ID和配送员ID
|
||||
// 这里假设用户ID和配送员ID相同(根据项目实际情况调整)
|
||||
// locationWebSocketHandler.removeUserConnection(user.getId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 记录日志但不中断登出流程
|
||||
System.err.println("清理WebSocket连接时出错: " + e.getMessage());
|
||||
@@ -160,24 +159,15 @@ public class UserServiceImpl implements UserService {
|
||||
if (user == null) {
|
||||
// 首次登录,创建新用户,默认为游客角色
|
||||
user = new User();
|
||||
user.setRole(UserRole.GUEST); // 默认为游客角色
|
||||
user.setOpenid(openid);
|
||||
userRepository.save(user);
|
||||
} else {
|
||||
// 检查并修复用户角色
|
||||
if (user.getRole() == null) {
|
||||
// 如果用户角色为空,设置为游客角色
|
||||
user.setRole(UserRole.GUEST);
|
||||
userRepository.save(user);
|
||||
}
|
||||
}
|
||||
|
||||
// 确保用户角色不为空,防止在生成token时出现空指针异常
|
||||
if (user.getRole() == null) {
|
||||
user.setRole(UserRole.GUEST);
|
||||
}
|
||||
// 获取用户角色
|
||||
UserRole userRole = getUserRole(user);
|
||||
|
||||
String token = jwtUtil.generateToken(user.getOpenid(), user.getRole().getCode());
|
||||
String token = jwtUtil.generateToken(user.getOpenid(),
|
||||
userRole != null ? userRole.getCode() : UserRole.GUEST.getCode());
|
||||
LoginResponse response = new LoginResponse();
|
||||
response.setToken(token);
|
||||
response.setUser(toUserInfoResponse(user));
|
||||
@@ -270,14 +260,13 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
|
||||
// 将openid写入employee表,表示该员工已成为系统用户
|
||||
employee.setOpenid(userOptional.get().getOpenid());
|
||||
User user = userOptional.get();
|
||||
employee.setOpenid(user.getOpenid());
|
||||
employeeRepository.save(employee);
|
||||
|
||||
// 更新用户信息
|
||||
User user = userOptional.get();
|
||||
user.setName(name); // 设置用户姓名
|
||||
user.setPhone(phone); // 设置用户手机号
|
||||
user.setRole(UserRole.fromCode(employee.getRole())); // 设置为员工对应的权限角色
|
||||
userRepository.save(user);
|
||||
|
||||
return user;
|
||||
@@ -319,7 +308,17 @@ public class UserServiceImpl implements UserService {
|
||||
dto.setId(user.getId());
|
||||
dto.setName(user.getName());
|
||||
dto.setPhone(user.getPhone());
|
||||
dto.setRole(user.getRole() != null ? user.getRole().getCode() : null);
|
||||
// 从员工表获取角色信息
|
||||
if (user.getPhone() != null && !user.getPhone().isEmpty()) {
|
||||
Optional<Employee> employee = employeeRepository.findByPhone(user.getPhone());
|
||||
if (employee.isPresent()) {
|
||||
dto.setRole(employee.get().getRole());
|
||||
} else {
|
||||
dto.setRole(UserRole.GUEST.getCode());
|
||||
}
|
||||
} else {
|
||||
dto.setRole(UserRole.GUEST.getCode());
|
||||
}
|
||||
dto.setOpenid(user.getOpenid());
|
||||
return dto;
|
||||
}
|
||||
@@ -338,7 +337,9 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
|
||||
User user = userOptional.get();
|
||||
if (user.getRole() != UserRole.DELIVERY_PERSON) {
|
||||
UserRole userRole = getUserRole(user);
|
||||
|
||||
if (userRole != UserRole.DELIVERY_PERSON) {
|
||||
// 非配送员角色没有签到状态概念
|
||||
return false;
|
||||
}
|
||||
@@ -346,4 +347,20 @@ public class UserServiceImpl implements UserService {
|
||||
// 检查WebSocket中的签到状态
|
||||
return locationWebSocketHandler.isDeliveryPersonSignedIn(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户角色
|
||||
* @param user 用户对象
|
||||
* @return 用户角色
|
||||
*/
|
||||
public UserRole getUserRole(User user) {
|
||||
// 从员工表获取角色信息
|
||||
if (user.getPhone() != null && !user.getPhone().isEmpty()) {
|
||||
Optional<Employee> employee = employeeRepository.findByPhone(user.getPhone());
|
||||
if (employee.isPresent()) {
|
||||
return UserRole.fromCode(employee.get().getRole());
|
||||
}
|
||||
}
|
||||
return UserRole.GUEST;
|
||||
}
|
||||
}
|
@@ -1,9 +1,8 @@
|
||||
spring.application.name=Light
|
||||
server.port=443
|
||||
|
||||
server.ssl.key-store-type=JKS
|
||||
server.ssl.key-store=/etc/ssl/certs/www.doubleyin.cn.jks
|
||||
server.ssl.key-store-password=${KEY_STORE_PASSWORD}
|
||||
# 默认禁用SSL,通过profile启用
|
||||
server.ssl.enabled=false
|
||||
|
||||
spring.datasource.url=jdbc:mysql://115.190.121.151:3306/light_delivery?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
spring.datasource.username=double
|
||||
|
Reference in New Issue
Block a user