Browse Source

用户管理

skyline 3 tháng trước cách đây
mục cha
commit
4c38245b52

+ 174 - 0
haha-admin/src/main/java/com/haha/admin/controller/UserController.java

@@ -0,0 +1,174 @@
+package com.haha.admin.controller;
+
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.haha.common.vo.Result;
+import com.haha.entity.User;
+import com.haha.service.UserService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 客户管理控制器
+ */
+@Slf4j
+@RestController
+@RequestMapping("/users")
+public class UserController {
+
+    @Autowired
+    private UserService userService;
+
+    /**
+     * 分页查询客户列表
+     * @param params 查询参数
+     * @return 客户列表
+     */
+    @GetMapping("/list")
+    public Result<Map<String, Object>> list(@RequestParam Map<String, Object> params) {
+        try {
+            int page = 1;
+            int pageSize = 10;
+
+            Object pageObj = params.get("page");
+            if (pageObj != null && !pageObj.toString().isEmpty()) {
+                page = Integer.parseInt(pageObj.toString());
+            }
+
+            Object pageSizeObj = params.get("pageSize");
+            if (pageSizeObj != null && !pageSizeObj.toString().isEmpty()) {
+                pageSize = Integer.parseInt(pageSizeObj.toString());
+            }
+
+            IPage<User> userPage = userService.getPage(page, pageSize, params);
+
+            // 填充额外字段
+            for (User user : userPage.getRecords()) {
+                fillUserLabels(user);
+            }
+
+            Map<String, Object> data = new HashMap<>();
+            data.put("list", userPage.getRecords());
+            data.put("total", userPage.getTotal());
+            data.put("pageSize", userPage.getSize());
+            data.put("currentPage", userPage.getCurrent());
+
+            return Result.success("查询成功", data);
+
+        } catch (Exception e) {
+            log.error("查询客户列表失败: {}", e.getMessage(), e);
+            return Result.error(500, "查询客户列表失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 获取客户详情
+     * @param id 客户ID
+     * @return 客户详情
+     */
+    @GetMapping("/{id}")
+    public Result<User> getById(@PathVariable Long id) {
+        try {
+            User user = userService.getById(id);
+            if (user == null) {
+                return Result.error(404, "客户不存在");
+            }
+            fillUserLabels(user);
+            return Result.success("查询成功", user);
+        } catch (Exception e) {
+            log.error("查询客户详情失败: id={}, error={}", id, e.getMessage(), e);
+            return Result.error(500, "查询客户详情失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 获取客户统计数据
+     * @return 统计数据
+     */
+    @GetMapping("/statistics")
+    public Result<Map<String, Object>> getStatistics() {
+        try {
+            Map<String, Object> statistics = userService.getStatistics();
+            return Result.success("查询成功", statistics);
+        } catch (Exception e) {
+            log.error("查询客户统计失败: {}", e.getMessage(), e);
+            return Result.error(500, "查询客户统计失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 更新客户状态
+     * @param id 客户ID
+     * @param params 状态参数
+     * @return 操作结果
+     */
+    @PutMapping("/{id}/status")
+    public Result<String> updateStatus(@PathVariable Long id, @RequestBody Map<String, Object> params) {
+        try {
+            Integer status = Integer.valueOf(params.get("status").toString());
+            
+            LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
+            wrapper.eq(User::getId, id).set(User::getStatus, status);
+            
+            boolean result = userService.update(wrapper);
+            if (result) {
+                return Result.success("状态更新成功");
+            } else {
+                return Result.error(500, "状态更新失败");
+            }
+        } catch (Exception e) {
+            log.error("更新客户状态失败: id={}, error={}", id, e.getMessage(), e);
+            return Result.error(500, "更新客户状态失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 更新客户信用分
+     * @param id 客户ID
+     * @param params 信用分参数
+     * @return 操作结果
+     */
+    @PutMapping("/{id}/credit")
+    public Result<String> updateCreditScore(@PathVariable Long id, @RequestBody Map<String, Object> params) {
+        try {
+            Integer creditScore = Integer.valueOf(params.get("creditScore").toString());
+            
+            boolean result = userService.updateCreditScore(id, creditScore);
+            if (result) {
+                return Result.success("信用分更新成功");
+            } else {
+                return Result.error(500, "信用分更新失败");
+            }
+        } catch (Exception e) {
+            log.error("更新客户信用分失败: id={}, error={}", id, e.getMessage(), e);
+            return Result.error(500, "更新客户信用分失败: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 填充客户标签字段
+     * @param user 客户对象
+     */
+    private void fillUserLabels(User user) {
+        // 状态标签
+        if (user.getStatus() != null) {
+            switch (user.getStatus()) {
+                case 1:
+                    user.setStatusLabel("正常");
+                    user.setStatusColor("success");
+                    break;
+                case 0:
+                    user.setStatusLabel("禁用");
+                    user.setStatusColor("danger");
+                    break;
+                default:
+                    user.setStatusLabel("未知");
+                    user.setStatusColor("info");
+            }
+        }
+    }
+}

+ 31 - 0
haha-common/src/main/java/com/haha/common/constant/RedisConstants.java

@@ -0,0 +1,31 @@
+package com.haha.common.constant;
+
+/**
+ * Redis键常量类
+ */
+public class RedisConstants {
+    
+    /**
+     * Sa-Token 用户Token键前缀
+     */
+    public static final String SA_TOKEN_USER_TOKEN_KEY = "sa:token:%s";
+    
+    /**
+     * Sa-Token 用户登录ID键前缀
+     */
+    public static final String SA_TOKEN_USER_LOGIN_ID_KEY = "sa:loginid:%s";
+    
+    /**
+     * 设备状态键前缀
+     */
+    public static final String DEVICE_STATUS_KEY = "device:status:%s";
+    
+    /**
+     * 用户信息键前缀
+     */
+    public static final String USER_INFO_KEY = "user:info:%s";
+    
+    private RedisConstants() {
+        // 私有构造函数,防止实例化
+    }
+}

+ 9 - 0
haha-entity/src/main/java/com/haha/entity/User.java

@@ -1,6 +1,7 @@
 package com.haha.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
@@ -30,4 +31,12 @@ public class User implements Serializable {
     private LocalDateTime createTime;
 
     private LocalDateTime updateTime;
+    
+    // ========== 以下为非数据库字段,用于前端展示 ==========
+    
+    @TableField(exist = false)
+    private String statusLabel;
+    
+    @TableField(exist = false)
+    private String statusColor;
 }

+ 1 - 1
haha-service/src/main/java/com/haha/service/RedisService.java

@@ -1,6 +1,6 @@
 package com.haha.service;
 
-import com.haha.common.RedisConstants;
+import com.haha.common.constant.RedisConstants;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;

+ 12 - 0
haha-service/src/main/java/com/haha/service/UserService.java

@@ -1,12 +1,24 @@
 package com.haha.service;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.haha.entity.User;
 import java.math.BigDecimal;
+import java.util.Map;
 
 public interface UserService extends IService<User> {
     User getUserByOpenId(String openId);
     User getUserByPhone(String phone);
     boolean updateCreditScore(Long userId, Integer score);
     boolean updateBalance(Long userId, BigDecimal amount);
+    
+    /**
+     * 分页查询客户列表
+     */
+    IPage<User> getPage(int page, int pageSize, Map<String, Object> params);
+    
+    /**
+     * 获取客户统计信息
+     */
+    Map<String, Object> getStatistics();
 }

+ 57 - 0
haha-service/src/main/java/com/haha/service/impl/UserServiceImpl.java

@@ -1,5 +1,8 @@
 package com.haha.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.haha.entity.User;
 import com.haha.mapper.UserMapper;
@@ -7,7 +10,11 @@ import com.haha.service.UserService;
 import com.haha.service.AccountService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
 import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
 
 @Service
 public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@@ -34,4 +41,54 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
     public boolean updateBalance(Long userId, BigDecimal amount) {
         return accountService.updateBalance(userId, amount);
     }
+
+    @Override
+    public IPage<User> getPage(int page, int pageSize, Map<String, Object> params) {
+        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
+        
+        // 昵称或手机号搜索
+        String keyword = (String) params.get("keyword");
+        if (StringUtils.hasText(keyword)) {
+            wrapper.and(w -> w
+                .like(User::getNickname, keyword)
+                .or()
+                .like(User::getPhone, keyword)
+            );
+        }
+        
+        // 状态筛选
+        Object statusObj = params.get("status");
+        if (statusObj != null && !statusObj.toString().isEmpty()) {
+            wrapper.eq(User::getStatus, Integer.valueOf(statusObj.toString()));
+        }
+        
+        // 按创建时间倒序
+        wrapper.orderByDesc(User::getCreateTime);
+        
+        Page<User> pageResult = new Page<>(page, pageSize);
+        return page(pageResult, wrapper);
+    }
+
+    @Override
+    public Map<String, Object> getStatistics() {
+        Map<String, Object> stats = new HashMap<>();
+        
+        // 总客户数
+        long total = count();
+        stats.put("total", total);
+        
+        // 正常用户数
+        long active = lambdaQuery().eq(User::getStatus, 1).count();
+        stats.put("active", active);
+        
+        // 禁用用户数
+        long disabled = lambdaQuery().eq(User::getStatus, 0).count();
+        stats.put("disabled", disabled);
+        
+        // 新增用户数(今日)
+        // TODO: 添加今日新增统计
+        stats.put("todayNew", 0);
+        
+        return stats;
+    }
 }