Quellcode durchsuchen

docs(util): 添加 LoginUserUtil 工具类文档和示例代码

- 新增 LOGIN_USER_UTIL_GUIDE.md 详细使用文档
- 新增 LOGIN_USER_UTIL_README.md 快速开始指南
- 添加 LoginUserUtil 工具类实现代码
- 提供完整的使用示例代码 LoginUserUtilExample.java
- 文档涵盖核心方法说明、实际应用场景和性能对比
- 包含常见问题解答和最佳实践建议
wxd vor 1 Monat
Ursprung
Commit
1f29e628a6

+ 815 - 0
alien-store-platform/doc/LOGIN_USER_UTIL_GUIDE.md

@@ -0,0 +1,815 @@
+# LoginUserUtil 工具类使用文档
+
+## 概述
+
+`LoginUserUtil` 是一个用于在web端商户平台(`alien-store-platform`)中获取当前登录用户信息的工具类。它封装了从JWT Token中提取用户信息以及从数据库查询完整用户信息的常用方法。
+
+---
+
+## 核心特性
+
+- ✅ **静态方法**: 所有方法都是静态方法,可直接调用,无需实例化
+- ✅ **自动注入**: 使用`@Autowired`自动注入`StoreUserMapper`
+- ✅ **异常处理**: 所有方法都包含完善的异常处理,确保不会抛出异常
+- ✅ **日志记录**: 详细的日志记录,便于调试和问题排查
+- ✅ **多种获取方式**: 支持从Token获取基本信息,或从数据库查询完整信息
+
+---
+
+## 类结构
+
+```java
+@Slf4j
+@Component
+public class LoginUserUtil {
+    // 核心方法
+    public static Integer getCurrentUserId()           // 获取用户ID
+    public static String getCurrentUserPhone()         // 获取手机号
+    public static String getCurrentUserType()          // 获取用户类型
+    public static JSONObject getCurrentUserInfo()      // 获取Token中的用户信息
+    public static StoreUser getCurrentStoreUser()      // 获取完整用户信息(数据库)
+    public static StoreUser getCurrentStoreUserByPhone() // 根据手机号获取用户信息
+    
+    // 辅助方法
+    public static boolean isCurrentUser(Integer userId)  // 验证是否为当前用户
+    public static boolean isLogin()                      // 验证是否已登录
+    public static boolean isStorePlatformUser()          // 验证是否为商户平台用户
+    
+    // 便捷方法
+    public static Integer getCurrentStoreId()            // 获取门店ID
+    public static String getCurrentNickName()            // 获取昵称
+    public static String getCurrentName()                // 获取真实姓名
+}
+```
+
+---
+
+## 方法详解
+
+### 1. getCurrentUserId()
+
+获取当前登录用户的ID(从Token中获取,无需查询数据库)
+
+```java
+/**
+ * 获取当前登录用户的ID
+ * @return 用户ID,如果未登录返回null
+ */
+public static Integer getCurrentUserId()
+```
+
+**使用示例**:
+```java
+Integer userId = LoginUserUtil.getCurrentUserId();
+if (userId != null) {
+    System.out.println("当前用户ID: " + userId);
+} else {
+    System.out.println("用户未登录");
+}
+```
+
+**返回值**:
+- 成功: 返回用户ID(Integer)
+- 未登录: 返回`null`
+
+**性能**: ⚡ 快速(只解析Token,不查询数据库)
+
+---
+
+### 2. getCurrentUserPhone()
+
+获取当前登录用户的手机号(从Token中获取)
+
+```java
+/**
+ * 获取当前登录用户的手机号
+ * @return 手机号,如果未登录返回null
+ */
+public static String getCurrentUserPhone()
+```
+
+**使用示例**:
+```java
+String phone = LoginUserUtil.getCurrentUserPhone();
+if (phone != null) {
+    System.out.println("当前用户手机号: " + phone);
+}
+```
+
+**返回值**:
+- 成功: 返回手机号(String)
+- 未登录: 返回`null`
+
+**性能**: ⚡ 快速(只解析Token)
+
+---
+
+### 3. getCurrentUserType()
+
+获取当前登录用户的用户类型(从Token中获取)
+
+```java
+/**
+ * 获取当前登录用户的用户类型
+ * @return 用户类型,如果未登录返回null
+ */
+public static String getCurrentUserType()
+```
+
+**使用示例**:
+```java
+String userType = LoginUserUtil.getCurrentUserType();
+if ("storePlatform".equals(userType)) {
+    System.out.println("商户平台用户");
+}
+```
+
+**返回值**:
+- 成功: 返回用户类型(String),如 `"storePlatform"`
+- 未登录: 返回`null`
+
+**性能**: ⚡ 快速(只解析Token)
+
+---
+
+### 4. getCurrentUserInfo()
+
+获取当前登录用户的Token信息(JSONObject格式)
+
+```java
+/**
+ * 获取当前登录用户的Token信息(JSONObject格式)
+ * @return 用户信息JSONObject,包含userId、phone、userType等字段
+ */
+public static JSONObject getCurrentUserInfo()
+```
+
+**使用示例**:
+```java
+JSONObject userInfo = LoginUserUtil.getCurrentUserInfo();
+if (userInfo != null) {
+    Integer userId = userInfo.getInteger("userId");
+    String phone = userInfo.getString("phone");
+    String userType = userInfo.getString("userType");
+    
+    System.out.println("用户ID: " + userId);
+    System.out.println("手机号: " + phone);
+    System.out.println("用户类型: " + userType);
+}
+```
+
+**返回值**:
+- 成功: 返回包含用户信息的`JSONObject`
+- 未登录: 返回`null`
+
+**包含字段**:
+- `userId`: 用户ID
+- `phone`: 手机号
+- `userType`: 用户类型
+
+**性能**: ⚡ 快速(只解析Token)
+
+---
+
+### 5. getCurrentStoreUser()
+
+获取当前登录用户的完整商户用户信息(从数据库查询)
+
+```java
+/**
+ * 获取当前登录用户的完整商户用户信息(从数据库查询)
+ * @return StoreUser对象,如果未登录或查询失败返回null
+ */
+public static StoreUser getCurrentStoreUser()
+```
+
+**使用示例**:
+```java
+StoreUser storeUser = LoginUserUtil.getCurrentStoreUser();
+if (storeUser != null) {
+    System.out.println("用户ID: " + storeUser.getId());
+    System.out.println("手机号: " + storeUser.getPhone());
+    System.out.println("昵称: " + storeUser.getNickName());
+    System.out.println("真实姓名: " + storeUser.getName());
+    System.out.println("门店ID: " + storeUser.getStoreId());
+    System.out.println("账户余额: " + storeUser.getMoney());
+}
+```
+
+**返回值**:
+- 成功: 返回`StoreUser`对象(包含所有字段)
+- 未登录: 返回`null`
+- 查询失败: 返回`null`
+
+**性能**: 🐢 较慢(需要查询数据库)
+
+**注意**: 
+- 适用于需要完整用户信息的场景
+- 会产生数据库查询,建议在需要时才调用
+
+---
+
+### 6. getCurrentStoreUserByPhone()
+
+根据手机号获取商户用户信息(从数据库查询)
+
+```java
+/**
+ * 根据手机号获取商户用户信息
+ * @return StoreUser对象,如果未登录或查询失败返回null
+ */
+public static StoreUser getCurrentStoreUserByPhone()
+```
+
+**使用示例**:
+```java
+StoreUser storeUser = LoginUserUtil.getCurrentStoreUserByPhone();
+if (storeUser != null) {
+    System.out.println("用户信息: " + storeUser);
+}
+```
+
+**返回值**:
+- 成功: 返回`StoreUser`对象
+- 未登录: 返回`null`
+- 查询失败: 返回`null`
+
+**性能**: 🐢 较慢(需要查询数据库)
+
+**与 getCurrentStoreUser() 的区别**:
+- `getCurrentStoreUser()`: 根据用户ID查询(主键查询,更快)
+- `getCurrentStoreUserByPhone()`: 根据手机号查询(索引查询,稍慢)
+
+---
+
+### 7. isCurrentUser(Integer userId)
+
+验证当前登录用户是否为指定用户
+
+```java
+/**
+ * 验证当前登录用户是否为指定用户
+ * @param userId 要验证的用户ID
+ * @return true-是当前用户, false-不是当前用户
+ */
+public static boolean isCurrentUser(Integer userId)
+```
+
+**使用示例**:
+```java
+Integer targetUserId = 12345;
+if (LoginUserUtil.isCurrentUser(targetUserId)) {
+    System.out.println("是当前用户,允许操作");
+} else {
+    System.out.println("不是当前用户,拒绝操作");
+}
+```
+
+**使用场景**:
+- 权限验证:确保用户只能修改自己的信息
+- 安全检查:防止用户操作其他用户的数据
+
+**返回值**:
+- `true`: 是当前登录用户
+- `false`: 不是当前登录用户或未登录
+
+---
+
+### 8. isLogin()
+
+验证当前用户是否已登录
+
+```java
+/**
+ * 验证当前用户是否已登录
+ * @return true-已登录, false-未登录
+ */
+public static boolean isLogin()
+```
+
+**使用示例**:
+```java
+if (LoginUserUtil.isLogin()) {
+    System.out.println("用户已登录");
+} else {
+    System.out.println("用户未登录");
+}
+```
+
+**返回值**:
+- `true`: 已登录
+- `false`: 未登录
+
+---
+
+### 9. isStorePlatformUser()
+
+验证当前用户类型是否为web端商户平台
+
+```java
+/**
+ * 验证当前用户类型是否为web端商户平台
+ * @return true-是商户平台用户, false-不是
+ */
+public static boolean isStorePlatformUser()
+```
+
+**使用示例**:
+```java
+if (LoginUserUtil.isStorePlatformUser()) {
+    System.out.println("商户平台用户,允许访问");
+} else {
+    System.out.println("非商户平台用户,拒绝访问");
+}
+```
+
+**返回值**:
+- `true`: 用户类型为 `storePlatform`
+- `false`: 用户类型不是 `storePlatform` 或未登录
+
+---
+
+### 10. getCurrentStoreId()
+
+获取当前登录用户的门店ID
+
+```java
+/**
+ * 获取当前登录用户的门店ID
+ * @return 门店ID,如果未登录或用户无门店返回null
+ */
+public static Integer getCurrentStoreId()
+```
+
+**使用示例**:
+```java
+Integer storeId = LoginUserUtil.getCurrentStoreId();
+if (storeId != null) {
+    System.out.println("当前用户的门店ID: " + storeId);
+}
+```
+
+**返回值**:
+- 成功: 返回门店ID(Integer)
+- 未登录: 返回`null`
+- 用户无门店: 返回`null`
+
+**性能**: 🐢 较慢(需要查询数据库)
+
+---
+
+### 11. getCurrentNickName()
+
+获取当前登录用户的昵称
+
+```java
+/**
+ * 获取当前登录用户的昵称
+ * @return 昵称,如果未登录返回null
+ */
+public static String getCurrentNickName()
+```
+
+**使用示例**:
+```java
+String nickName = LoginUserUtil.getCurrentNickName();
+if (nickName != null) {
+    System.out.println("欢迎," + nickName);
+}
+```
+
+**返回值**:
+- 成功: 返回昵称(String)
+- 未登录: 返回`null`
+
+**性能**: 🐢 较慢(需要查询数据库)
+
+---
+
+### 12. getCurrentName()
+
+获取当前登录用户的真实姓名
+
+```java
+/**
+ * 获取当前登录用户的真实姓名
+ * @return 真实姓名,如果未登录返回null
+ */
+public static String getCurrentName()
+```
+
+**使用示例**:
+```java
+String name = LoginUserUtil.getCurrentName();
+if (name != null) {
+    System.out.println("真实姓名: " + name);
+}
+```
+
+**返回值**:
+- 成功: 返回真实姓名(String)
+- 未登录: 返回`null`
+
+**性能**: 🐢 较慢(需要查询数据库)
+
+---
+
+## 实际应用场景
+
+### 场景1: 获取当前用户的基本信息
+
+```java
+@RestController
+@RequestMapping("/user")
+public class UserController {
+    
+    @GetMapping("/profile")
+    public R<StoreUser> getUserProfile() {
+        // 获取当前登录用户的完整信息
+        StoreUser storeUser = LoginUserUtil.getCurrentStoreUser();
+        if (storeUser == null) {
+            return R.fail("请先登录");
+        }
+        return R.data(storeUser);
+    }
+}
+```
+
+---
+
+### 场景2: 验证用户权限(只能操作自己的数据)
+
+```java
+@Service
+public class StoreServiceImpl implements StoreService {
+    
+    @Override
+    public boolean updateStore(Integer storeId, StoreInfo storeInfo) {
+        // 获取当前用户的门店ID
+        Integer currentStoreId = LoginUserUtil.getCurrentStoreId();
+        
+        // 验证用户只能修改自己的门店信息
+        if (!storeId.equals(currentStoreId)) {
+            throw new RuntimeException("您只能修改自己的门店信息");
+        }
+        
+        // 执行更新操作
+        return updateStoreInfo(storeInfo);
+    }
+}
+```
+
+---
+
+### 场景3: 自动填充当前用户信息
+
+```java
+@Service
+public class OrderServiceImpl implements OrderService {
+    
+    @Override
+    public boolean createOrder(Order order) {
+        // 自动填充当前用户信息
+        Integer userId = LoginUserUtil.getCurrentUserId();
+        Integer storeId = LoginUserUtil.getCurrentStoreId();
+        
+        order.setUserId(userId);
+        order.setStoreId(storeId);
+        order.setCreateTime(new Date());
+        
+        return orderMapper.insert(order) > 0;
+    }
+}
+```
+
+---
+
+### 场景4: 根据用户类型返回不同数据
+
+```java
+@Service
+public class DashboardServiceImpl implements DashboardService {
+    
+    @Override
+    public JSONObject getDashboardData() {
+        JSONObject result = new JSONObject();
+        
+        // 验证用户类型
+        if (!LoginUserUtil.isStorePlatformUser()) {
+            throw new RuntimeException("只有商户平台用户可以访问");
+        }
+        
+        // 获取用户信息
+        Integer storeId = LoginUserUtil.getCurrentStoreId();
+        
+        // 查询仪表盘数据
+        result.put("todayIncome", getTodayIncome(storeId));
+        result.put("todayOrderCount", getTodayOrderCount(storeId));
+        
+        return result;
+    }
+}
+```
+
+---
+
+### 场景5: 日志记录(记录操作人)
+
+```java
+@Service
+public class AuditLogServiceImpl implements AuditLogService {
+    
+    @Override
+    public void logOperation(String action, String details) {
+        AuditLog log = new AuditLog();
+        
+        // 记录操作人信息
+        log.setUserId(LoginUserUtil.getCurrentUserId());
+        log.setUserPhone(LoginUserUtil.getCurrentUserPhone());
+        log.setUserName(LoginUserUtil.getCurrentName());
+        log.setAction(action);
+        log.setDetails(details);
+        log.setOperateTime(new Date());
+        
+        auditLogMapper.insert(log);
+    }
+}
+```
+
+---
+
+### 场景6: 条件查询(只查询当前用户的数据)
+
+```java
+@Service
+public class OrderServiceImpl implements OrderService {
+    
+    @Override
+    public List<Order> getMyOrders(Integer page, Integer size) {
+        // 获取当前用户ID
+        Integer userId = LoginUserUtil.getCurrentUserId();
+        if (userId == null) {
+            throw new RuntimeException("请先登录");
+        }
+        
+        // 查询当前用户的订单
+        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(Order::getUserId, userId)
+               .orderByDesc(Order::getCreateTime);
+        
+        return orderMapper.selectPage(new Page<>(page, size), wrapper).getRecords();
+    }
+}
+```
+
+---
+
+### 场景7: 简化Controller代码
+
+**之前的写法**:
+```java
+@PostMapping("/updateProfile")
+public R<Boolean> updateProfile(@RequestBody StoreUser storeUser) {
+    // 需要手动获取用户信息
+    JSONObject userInfo = JwtUtil.getCurrentUserInfo();
+    if (userInfo == null) {
+        return R.fail("请先登录");
+    }
+    Integer userId = userInfo.getInteger("userId");
+    storeUser.setId(userId);
+    
+    boolean success = storeUserService.updateById(storeUser);
+    return success ? R.success("修改成功") : R.fail("修改失败");
+}
+```
+
+**使用工具类后**:
+```java
+@PostMapping("/updateProfile")
+public R<Boolean> updateProfile(@RequestBody StoreUser storeUser) {
+    // 直接获取用户ID
+    Integer userId = LoginUserUtil.getCurrentUserId();
+    if (userId == null) {
+        return R.fail("请先登录");
+    }
+    storeUser.setId(userId);
+    
+    boolean success = storeUserService.updateById(storeUser);
+    return success ? R.success("修改成功") : R.fail("修改失败");
+}
+```
+
+---
+
+## 性能对比
+
+| 方法 | 性能 | 是否查询数据库 | 适用场景 |
+|------|------|---------------|----------|
+| `getCurrentUserId()` | ⚡⚡⚡ 极快 | ❌ 否 | 只需要用户ID |
+| `getCurrentUserPhone()` | ⚡⚡⚡ 极快 | ❌ 否 | 只需要手机号 |
+| `getCurrentUserType()` | ⚡⚡⚡ 极快 | ❌ 否 | 验证用户类型 |
+| `getCurrentUserInfo()` | ⚡⚡⚡ 极快 | ❌ 否 | 需要Token中的多个字段 |
+| `getCurrentStoreUser()` | 🐢 较慢 | ✅ 是 | 需要完整用户信息 |
+| `getCurrentStoreUserByPhone()` | 🐢 较慢 | ✅ 是 | 根据手机号查询 |
+| `getCurrentStoreId()` | 🐢 较慢 | ✅ 是 | 只需要门店ID |
+| `getCurrentNickName()` | 🐢 较慢 | ✅ 是 | 只需要昵称 |
+| `getCurrentName()` | 🐢 较慢 | ✅ 是 | 只需要真实姓名 |
+
+**优化建议**:
+- ✅ 优先使用不查询数据库的方法(`getCurrentUserId()`、`getCurrentUserPhone()`等)
+- ✅ 如果需要多个用户字段,使用`getCurrentStoreUser()`一次性获取,避免多次查询
+- ✅ 不要在循环中调用需要查询数据库的方法
+
+---
+
+## 注意事项
+
+### 1. 空值处理
+
+所有方法在获取失败时都返回`null`,使用时需要判空:
+
+```java
+Integer userId = LoginUserUtil.getCurrentUserId();
+if (userId != null) {
+    // 处理业务逻辑
+} else {
+    // 处理未登录情况
+}
+```
+
+### 2. 异常处理
+
+工具类内部已处理所有异常,不会向外抛出异常,确保调用安全。
+
+### 3. 静态方法限制
+
+由于使用静态方法,需要通过`@Autowired`注入`StoreUserMapper`到静态字段。这是通过`@Component`和setter方法实现的。
+
+### 4. 性能考虑
+
+- **频繁调用**: 如果需要频繁获取用户信息,建议在Service层缓存
+- **数据库查询**: 避免在循环中调用需要查询数据库的方法
+
+### 5. 线程安全
+
+工具类是线程安全的,可以在多线程环境下使用。
+
+---
+
+## 与 @LoginRequired 注解配合使用
+
+`LoginUserUtil` 与 `@LoginRequired` 注解配合使用效果更佳:
+
+```java
+@RestController
+@RequestMapping("/store")
+public class StoreController {
+    
+    @LoginRequired  // AOP切面验证登录
+    @GetMapping("/myStore")
+    public R<StoreInfo> getMyStore() {
+        // 登录验证已通过,直接获取门店ID
+        Integer storeId = LoginUserUtil.getCurrentStoreId();
+        StoreInfo storeInfo = storeService.getById(storeId);
+        return R.data(storeInfo);
+    }
+}
+```
+
+---
+
+## 配置要求
+
+### 1. Spring Bean注册
+
+工具类使用`@Component`注解,需要被Spring扫描到:
+
+```java
+@Component  // 必须
+public class LoginUserUtil {
+    // ...
+}
+```
+
+### 2. 包扫描配置
+
+确保`LoginUserUtil`所在的包被Spring Boot扫描:
+
+```java
+@SpringBootApplication
+@ComponentScan(basePackages = {"shop.alien.storeplatform"})
+public class Application {
+    // ...
+}
+```
+
+### 3. Mapper依赖
+
+确保`StoreUserMapper`已注册为Spring Bean:
+
+```java
+@Mapper
+public interface StoreUserMapper extends BaseMapper<StoreUser> {
+}
+```
+
+---
+
+## 常见问题
+
+### Q1: 为什么有时返回null?
+
+**原因**:
+1. 用户未登录(Token不存在或无效)
+2. Token已过期
+3. 用户在数据库中不存在
+4. 网络或数据库异常
+
+**解决方案**:
+- 使用前先判断是否已登录:`LoginUserUtil.isLogin()`
+- 检查日志中的错误信息
+
+---
+
+### Q2: 如何在非Controller层使用?
+
+**答案**: 工具类可以在任何Spring管理的Bean中使用:
+
+```java
+@Service
+public class MyService {
+    
+    public void someMethod() {
+        Integer userId = LoginUserUtil.getCurrentUserId();
+        // 使用userId
+    }
+}
+```
+
+---
+
+### Q3: 性能是否有问题?
+
+**答案**: 
+- Token解析方法(如`getCurrentUserId()`)性能很高,可以频繁调用
+- 数据库查询方法(如`getCurrentStoreUser()`)性能较低,建议缓存结果
+
+---
+
+### Q4: 如何缓存用户信息?
+
+**建议方案**:
+
+```java
+@Service
+public class MyService {
+    
+    private StoreUser currentUser;
+    
+    public void processOrder() {
+        // 第一次获取
+        if (currentUser == null) {
+            currentUser = LoginUserUtil.getCurrentStoreUser();
+        }
+        
+        // 后续使用缓存的数据
+        Integer storeId = currentUser.getStoreId();
+        // ...
+    }
+}
+```
+
+或使用ThreadLocal缓存(适用于同一次请求)。
+
+---
+
+## 更新日志
+
+### 2025-11-17
+
+**新增工具类**:
+- ✅ 创建`LoginUserUtil`工具类
+
+**核心功能**:
+- ✅ 获取当前登录用户ID、手机号、用户类型
+- ✅ 获取Token中的用户信息(JSONObject)
+- ✅ 从数据库查询完整用户信息
+- ✅ 验证用户登录状态
+- ✅ 验证用户类型
+- ✅ 验证是否为当前用户
+- ✅ 获取门店ID、昵称、姓名等便捷方法
+
+**技术特点**:
+- ✅ 静态方法,方便调用
+- ✅ 完善的异常处理
+- ✅ 详细的日志记录
+- ✅ 支持多种获取方式
+
+**开发人员**: ssk
+
+---
+
+**文档版本**: v1.0  
+**最后更新**: 2025-11-17  
+**维护人员**: ssk
+

+ 127 - 0
alien-store-platform/doc/LOGIN_USER_UTIL_README.md

@@ -0,0 +1,127 @@
+# LoginUserUtil 工具类 - 快速开始
+
+## 简介
+
+`LoginUserUtil` 是一个用于在web端商户平台中快速获取当前登录用户信息的工具类。所有方法都是静态方法,可以直接调用。
+
+---
+
+## 快速使用
+
+### 1. 获取用户ID(最常用)
+
+```java
+Integer userId = LoginUserUtil.getCurrentUserId();
+if (userId != null) {
+    // 用户已登录,使用userId
+} else {
+    // 用户未登录
+}
+```
+
+### 2. 获取完整用户信息
+
+```java
+StoreUser storeUser = LoginUserUtil.getCurrentStoreUser();
+if (storeUser != null) {
+    Integer userId = storeUser.getId();
+    String phone = storeUser.getPhone();
+    Integer storeId = storeUser.getStoreId();
+    // ... 使用其他字段
+}
+```
+
+### 3. 验证用户登录
+
+```java
+if (LoginUserUtil.isLogin()) {
+    // 已登录
+} else {
+    // 未登录
+}
+```
+
+### 4. 权限验证
+
+```java
+Integer targetUserId = 12345;
+if (LoginUserUtil.isCurrentUser(targetUserId)) {
+    // 是当前用户,允许操作
+} else {
+    // 不是当前用户,拒绝操作
+}
+```
+
+---
+
+## 核心方法速查
+
+| 方法 | 返回值 | 说明 | 是否查数据库 |
+|------|--------|------|-------------|
+| `getCurrentUserId()` | Integer | 用户ID | ❌ |
+| `getCurrentUserPhone()` | String | 手机号 | ❌ |
+| `getCurrentUserType()` | String | 用户类型 | ❌ |
+| `getCurrentUserInfo()` | JSONObject | Token中的用户信息 | ❌ |
+| `getCurrentStoreUser()` | StoreUser | 完整用户信息 | ✅ |
+| `getCurrentStoreId()` | Integer | 门店ID | ✅ |
+| `isLogin()` | boolean | 是否已登录 | ❌ |
+| `isCurrentUser(userId)` | boolean | 是否为当前用户 | ❌ |
+
+---
+
+## 实际应用示例
+
+### Service层自动填充
+
+```java
+@Service
+public class OrderServiceImpl {
+    
+    public void createOrder(Order order) {
+        // 自动填充当前用户信息
+        order.setUserId(LoginUserUtil.getCurrentUserId());
+        order.setStoreId(LoginUserUtil.getCurrentStoreId());
+        orderMapper.insert(order);
+    }
+}
+```
+
+### 权限控制
+
+```java
+@Service
+public class StoreServiceImpl {
+    
+    public void updateStore(Integer storeId, StoreInfo info) {
+        Integer currentStoreId = LoginUserUtil.getCurrentStoreId();
+        if (!storeId.equals(currentStoreId)) {
+            throw new RuntimeException("只能修改自己的门店");
+        }
+        // 执行更新
+    }
+}
+```
+
+---
+
+## 注意事项
+
+1. ⚠️ 所有方法失败时返回`null`,使用前需判空
+2. ⚠️ 带数据库查询的方法(如`getCurrentStoreUser()`)性能较慢,避免频繁调用
+3. ⚠️ 如需多个字段,使用`getCurrentStoreUser()`一次性获取,避免多次查询
+4. ⚠️ 需要用户已登录(有有效Token)才能正常工作
+
+---
+
+## 详细文档
+
+请查看完整文档:[LOGIN_USER_UTIL_GUIDE.md](LOGIN_USER_UTIL_GUIDE.md)
+
+使用示例代码:[LoginUserUtilExample.java](../src/main/java/shop/alien/storeplatform/example/LoginUserUtilExample.java)
+
+---
+
+**版本**: v1.0  
+**日期**: 2025-11-17  
+**作者**: ssk
+

+ 254 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/example/LoginUserUtilExample.java

@@ -0,0 +1,254 @@
+package shop.alien.storeplatform.example;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import shop.alien.entity.store.StoreUser;
+import shop.alien.storeplatform.util.LoginUserUtil;
+
+/**
+ * LoginUserUtil 工具类使用示例
+ * 
+ * 本类展示了如何在实际项目中使用 LoginUserUtil 工具类
+ * 注意:这只是一个示例类,实际使用时可以直接在Service或Controller中调用
+ *
+ * @author ssk
+ * @since 2025-11-17
+ */
+@Slf4j
+public class LoginUserUtilExample {
+
+    /**
+     * 示例1: 获取当前用户的基本信息(从Token)
+     */
+    public void example1_GetBasicInfo() {
+        log.info("========== 示例1: 获取基本信息 ==========");
+        
+        // 获取用户ID
+        Integer userId = LoginUserUtil.getCurrentUserId();
+        log.info("用户ID: {}", userId);
+        
+        // 获取手机号
+        String phone = LoginUserUtil.getCurrentUserPhone();
+        log.info("手机号: {}", phone);
+        
+        // 获取用户类型
+        String userType = LoginUserUtil.getCurrentUserType();
+        log.info("用户类型: {}", userType);
+        
+        // 获取完整Token信息
+        JSONObject userInfo = LoginUserUtil.getCurrentUserInfo();
+        log.info("完整用户信息: {}", userInfo);
+    }
+
+    /**
+     * 示例2: 获取完整用户信息(从数据库)
+     */
+    public void example2_GetCompleteInfo() {
+        log.info("========== 示例2: 获取完整用户信息 ==========");
+        
+        StoreUser storeUser = LoginUserUtil.getCurrentStoreUser();
+        if (storeUser != null) {
+            log.info("用户ID: {}", storeUser.getId());
+            log.info("手机号: {}", storeUser.getPhone());
+            log.info("昵称: {}", storeUser.getNickName());
+            log.info("真实姓名: {}", storeUser.getName());
+            log.info("身份证号: {}", storeUser.getIdCard());
+            log.info("门店ID: {}", storeUser.getStoreId());
+            log.info("账户余额: {}", storeUser.getMoney());
+            log.info("头像: {}", storeUser.getHeadImg());
+            log.info("账号简介: {}", storeUser.getAccountBlurb());
+        } else {
+            log.warn("用户未登录或查询失败");
+        }
+    }
+
+    /**
+     * 示例3: 验证用户登录状态
+     */
+    public void example3_CheckLoginStatus() {
+        log.info("========== 示例3: 验证登录状态 ==========");
+        
+        // 检查是否登录
+        if (LoginUserUtil.isLogin()) {
+            log.info("用户已登录");
+        } else {
+            log.info("用户未登录");
+        }
+        
+        // 检查是否为商户平台用户
+        if (LoginUserUtil.isStorePlatformUser()) {
+            log.info("是商户平台用户");
+        } else {
+            log.info("不是商户平台用户");
+        }
+    }
+
+    /**
+     * 示例4: 验证是否为当前用户(权限控制)
+     */
+    public void example4_CheckCurrentUser() {
+        log.info("========== 示例4: 验证是否为当前用户 ==========");
+        
+        Integer targetUserId = 12345; // 要操作的目标用户ID
+        
+        if (LoginUserUtil.isCurrentUser(targetUserId)) {
+            log.info("是当前用户,允许操作");
+            // 执行业务逻辑
+        } else {
+            log.warn("不是当前用户,拒绝操作");
+            // 抛出异常或返回错误
+        }
+    }
+
+    /**
+     * 示例5: 获取便捷字段
+     */
+    public void example5_GetConvenientFields() {
+        log.info("========== 示例5: 获取便捷字段 ==========");
+        
+        // 获取门店ID
+        Integer storeId = LoginUserUtil.getCurrentStoreId();
+        log.info("门店ID: {}", storeId);
+        
+        // 获取昵称
+        String nickName = LoginUserUtil.getCurrentNickName();
+        log.info("昵称: {}", nickName);
+        
+        // 获取真实姓名
+        String name = LoginUserUtil.getCurrentName();
+        log.info("真实姓名: {}", name);
+    }
+
+    /**
+     * 示例6: 在Service中使用(自动填充用户信息)
+     */
+    public void example6_UseInService() {
+        log.info("========== 示例6: 在Service中使用 ==========");
+        
+        // 场景:创建订单时自动填充当前用户信息
+        Integer userId = LoginUserUtil.getCurrentUserId();
+        Integer storeId = LoginUserUtil.getCurrentStoreId();
+        
+        if (userId == null || storeId == null) {
+            log.error("用户未登录或无门店信息");
+            return;
+        }
+        
+        // 模拟创建订单
+        log.info("创建订单 - 用户ID: {}, 门店ID: {}", userId, storeId);
+        // Order order = new Order();
+        // order.setUserId(userId);
+        // order.setStoreId(storeId);
+        // orderService.createOrder(order);
+    }
+
+    /**
+     * 示例7: 安全的空值处理
+     */
+    public void example7_SafeNullHandling() {
+        log.info("========== 示例7: 安全的空值处理 ==========");
+        
+        // 方式1: 直接判空
+        Integer userId = LoginUserUtil.getCurrentUserId();
+        if (userId != null) {
+            log.info("用户ID: {}", userId);
+        } else {
+            log.warn("用户未登录");
+        }
+        
+        // 方式2: 使用 isLogin() 先判断
+        if (LoginUserUtil.isLogin()) {
+            Integer id = LoginUserUtil.getCurrentUserId();
+            log.info("已登录,用户ID: {}", id);
+        } else {
+            log.warn("用户未登录");
+        }
+    }
+
+    /**
+     * 示例8: 权限验证(只能修改自己的数据)
+     */
+    public boolean example8_PermissionCheck(Integer targetUserId) {
+        log.info("========== 示例8: 权限验证 ==========");
+        
+        // 验证用户只能修改自己的数据
+        if (!LoginUserUtil.isCurrentUser(targetUserId)) {
+            log.error("权限不足:用户 {} 尝试修改用户 {} 的数据", 
+                    LoginUserUtil.getCurrentUserId(), targetUserId);
+            throw new RuntimeException("您只能修改自己的信息");
+        }
+        
+        log.info("权限验证通过");
+        return true;
+    }
+
+    /**
+     * 示例9: 记录操作日志
+     */
+    public void example9_LogOperation(String action, String details) {
+        log.info("========== 示例9: 记录操作日志 ==========");
+        
+        // 获取当前用户信息用于日志记录
+        Integer userId = LoginUserUtil.getCurrentUserId();
+        String phone = LoginUserUtil.getCurrentUserPhone();
+        String name = LoginUserUtil.getCurrentName();
+        
+        // 记录操作日志
+        log.info("操作日志 - 用户ID: {}, 手机号: {}, 姓名: {}, 操作: {}, 详情: {}", 
+                userId, phone, name, action, details);
+        
+        // 实际项目中可以保存到数据库
+        // AuditLog auditLog = new AuditLog();
+        // auditLog.setUserId(userId);
+        // auditLog.setUserPhone(phone);
+        // auditLog.setUserName(name);
+        // auditLog.setAction(action);
+        // auditLog.setDetails(details);
+        // auditLog.setOperateTime(new Date());
+        // auditLogMapper.insert(auditLog);
+    }
+
+    /**
+     * 示例10: 性能优化(缓存用户信息)
+     */
+    public void example10_CacheUserInfo() {
+        log.info("========== 示例10: 性能优化 ==========");
+        
+        // 一次性获取完整用户信息并缓存
+        StoreUser storeUser = LoginUserUtil.getCurrentStoreUser();
+        
+        if (storeUser != null) {
+            // 后续使用缓存的对象,避免重复查询数据库
+            Integer userId = storeUser.getId();
+            Integer storeId = storeUser.getStoreId();
+            String nickName = storeUser.getNickName();
+            
+            log.info("使用缓存 - 用户ID: {}, 门店ID: {}, 昵称: {}", 
+                    userId, storeId, nickName);
+            
+            // ❌ 不推荐:多次调用查询数据库的方法
+            // Integer storeId1 = LoginUserUtil.getCurrentStoreId();
+            // String nickName1 = LoginUserUtil.getCurrentNickName();
+            // String name1 = LoginUserUtil.getCurrentName();
+        }
+    }
+
+    /**
+     * 主方法:运行所有示例
+     */
+    public static void main(String[] args) {
+        LoginUserUtilExample example = new LoginUserUtilExample();
+        
+        // 注意:实际运行需要在Spring容器中,且用户已登录
+        example.example1_GetBasicInfo();
+        example.example2_GetCompleteInfo();
+        example.example3_CheckLoginStatus();
+        example.example4_CheckCurrentUser();
+        example.example5_GetConvenientFields();
+        example.example6_UseInService();
+        example.example7_SafeNullHandling();
+        example.example9_LogOperation("更新用户信息", "修改昵称和头���");
+        example.example10_CacheUserInfo();
+    }
+}
+

+ 246 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/util/LoginUserUtil.java

@@ -0,0 +1,246 @@
+package shop.alien.storeplatform.util;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import shop.alien.entity.store.StoreUser;
+import shop.alien.mapper.StoreUserMapper;
+import shop.alien.util.common.JwtUtil;
+
+/**
+ * 登录用户工具类
+ * 用于在web端商户平台中获取当前登录用户的信息
+ *
+ * @author ssk
+ * @since 2025-11-17
+ */
+@Slf4j
+@Component
+public class LoginUserUtil {
+
+    private static StoreUserMapper storeUserMapper;
+
+    @Autowired
+    public void setStoreUserMapper(StoreUserMapper storeUserMapper) {
+        LoginUserUtil.storeUserMapper = storeUserMapper;
+    }
+
+    /**
+     * 获取当前登录用户的ID
+     *
+     * @return 用户ID,如果未登录返回null
+     */
+    public static Integer getCurrentUserId() {
+        try {
+            JSONObject userInfo = JwtUtil.getCurrentUserInfo();
+            if (userInfo != null) {
+                return userInfo.getInteger("userId");
+            }
+        } catch (Exception e) {
+            log.error("LoginUserUtil.getCurrentUserId - 获取用户ID失败: {}", e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /**
+     * 获取当前登录用户的手机号
+     *
+     * @return 手机号,如果未登录返回null
+     */
+    public static String getCurrentUserPhone() {
+        try {
+            JSONObject userInfo = JwtUtil.getCurrentUserInfo();
+            if (userInfo != null) {
+                return userInfo.getString("phone");
+            }
+        } catch (Exception e) {
+            log.error("LoginUserUtil.getCurrentUserPhone - 获取用户手机号失败: {}", e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /**
+     * 获取当前登录用户的用户类型
+     *
+     * @return 用户类型,如果未登录返回null
+     */
+    public static String getCurrentUserType() {
+        try {
+            JSONObject userInfo = JwtUtil.getCurrentUserInfo();
+            if (userInfo != null) {
+                return userInfo.getString("userType");
+            }
+        } catch (Exception e) {
+            log.error("LoginUserUtil.getCurrentUserType - 获取用户类型失败: {}", e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /**
+     * 获取当前登录用户的Token信息(JSONObject格式)
+     *
+     * @return 用户信息JSONObject,包含userId、phone、userType等字段,如果未登录返回null
+     */
+    public static JSONObject getCurrentUserInfo() {
+        try {
+            JSONObject userInfo = JwtUtil.getCurrentUserInfo();
+            if (userInfo != null) {
+                log.debug("LoginUserUtil.getCurrentUserInfo - 获取用户信息成功: userId={}, phone={}", 
+                        userInfo.getString("userId"), userInfo.getString("phone"));
+                return userInfo;
+            }
+        } catch (Exception e) {
+            log.error("LoginUserUtil.getCurrentUserInfo - 获取用户信息失败: {}", e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /**
+     * 获取当前登录用户的完整商户用户信息(从数据库查询)
+     *
+     * @return StoreUser对象,如果未登录或查询失败返回null
+     */
+    public static StoreUser getCurrentStoreUser() {
+        try {
+            Integer userId = getCurrentUserId();
+            if (userId == null) {
+                log.warn("LoginUserUtil.getCurrentStoreUser - 用户未登录");
+                return null;
+            }
+
+            // 从数据库查询完整用户信息
+            StoreUser storeUser = storeUserMapper.selectById(userId);
+            if (storeUser != null) {
+                log.debug("LoginUserUtil.getCurrentStoreUser - 查询用户信息成功: userId={}, phone={}", 
+                        storeUser.getId(), storeUser.getPhone());
+            } else {
+                log.warn("LoginUserUtil.getCurrentStoreUser - 用户不存在: userId={}", userId);
+            }
+            return storeUser;
+        } catch (Exception e) {
+            log.error("LoginUserUtil.getCurrentStoreUser - 查询用户信息失败: {}", e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 根据手机号获取商户用户信息
+     *
+     * @return StoreUser对象,如果未登录或查询失败返回null
+     */
+    public static StoreUser getCurrentStoreUserByPhone() {
+        try {
+            String phone = getCurrentUserPhone();
+            if (phone == null) {
+                log.warn("LoginUserUtil.getCurrentStoreUserByPhone - 用户未登录");
+                return null;
+            }
+
+            // 从数据库根据手机号查询用户信息
+            LambdaQueryWrapper<StoreUser> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(StoreUser::getPhone, phone);
+            StoreUser storeUser = storeUserMapper.selectOne(queryWrapper);
+            
+            if (storeUser != null) {
+                log.debug("LoginUserUtil.getCurrentStoreUserByPhone - 查询用户信息成功: userId={}, phone={}", 
+                        storeUser.getId(), storeUser.getPhone());
+            } else {
+                log.warn("LoginUserUtil.getCurrentStoreUserByPhone - 用户不存在: phone={}", phone);
+            }
+            return storeUser;
+        } catch (Exception e) {
+            log.error("LoginUserUtil.getCurrentStoreUserByPhone - 查询用户信息失败: {}", e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 验证当前登录用户是否为指定用户
+     *
+     * @param userId 要验证的用户ID
+     * @return true-是当前用户, false-不是当前用户
+     */
+    public static boolean isCurrentUser(Integer userId) {
+        if (userId == null) {
+            return false;
+        }
+        Integer currentUserId = getCurrentUserId();
+        return userId.equals(currentUserId);
+    }
+
+    /**
+     * 验证当前用户是否已登录
+     *
+     * @return true-已登录, false-未登录
+     */
+    public static boolean isLogin() {
+        return getCurrentUserId() != null;
+    }
+
+    /**
+     * 验证当前用户类型是否为web端商户平台
+     *
+     * @return true-是商户平台用户, false-不是
+     */
+    public static boolean isStorePlatformUser() {
+        String userType = getCurrentUserType();
+        return "storePlatform".equals(userType);
+    }
+
+    /**
+     * 获取当前登录用户的门店ID
+     * 注意:需要先查询数据库获取完整用户信息
+     *
+     * @return 门店ID,如果未登录或用户无门店返回null
+     */
+    public static Integer getCurrentStoreId() {
+        try {
+            StoreUser storeUser = getCurrentStoreUser();
+            if (storeUser != null) {
+                return storeUser.getStoreId();
+            }
+        } catch (Exception e) {
+            log.error("LoginUserUtil.getCurrentStoreId - 获取门店ID失败: {}", e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /**
+     * 获取当前登录用户的昵称
+     * 注意:需要先查询数据库获取完整用户信息
+     *
+     * @return 昵称,如果未登录返回null
+     */
+    public static String getCurrentNickName() {
+        try {
+            StoreUser storeUser = getCurrentStoreUser();
+            if (storeUser != null) {
+                return storeUser.getNickName();
+            }
+        } catch (Exception e) {
+            log.error("LoginUserUtil.getCurrentNickName - 获取昵称失败: {}", e.getMessage(), e);
+        }
+        return null;
+    }
+
+    /**
+     * 获取当前登录用户的真实姓名
+     * 注意:需要先查询数据库获取完整用户信息
+     *
+     * @return 真实姓名,如果未登录返回null
+     */
+    public static String getCurrentName() {
+        try {
+            StoreUser storeUser = getCurrentStoreUser();
+            if (storeUser != null) {
+                return storeUser.getName();
+            }
+        } catch (Exception e) {
+            log.error("LoginUserUtil.getCurrentName - 获取姓名失败: {}", e.getMessage(), e);
+        }
+        return null;
+    }
+}
+