Files
shangbangbang/internal/handlers/admin_user_handler.go
T
solosw 99b11b04e4 1.0
2026-01-05 14:11:34 +08:00

634 lines
19 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handlers
import (
"awesomeProject/internal/common"
"awesomeProject/internal/middleware"
"awesomeProject/internal/models"
"crypto/md5"
"fmt"
"github.com/google/uuid"
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// AdminUserHandler 管理端用户处理器
type AdminUserHandler struct{}
// GetUsers 获取用户列表
func (h *AdminUserHandler) GetUsers(c *gin.Context) {
currentUser, _ := c.Get("current_user")
user := currentUser.(models.User)
// 分页参数
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 10
}
// 搜索参数
phone := c.Query("phone")
realName := c.Query("real_name")
systemRole := c.Query("system_role")
identityCode := c.Query("identity_code")
db := common.GetDB()
var users []models.User
var total int64
// 构建查询条件
query := db.Model(&models.User{})
// 如果是代理商,只能查看自己邀请的用户
if user.SystemRole == 1 {
query = query.Where("referrer_identity_code = ?", user.IdentityCode)
}
// 添加搜索条件
if phone != "" {
query = query.Where("phone LIKE ?", "%"+phone+"%")
}
if realName != "" {
query = query.Where("real_name LIKE ?", "%"+realName+"%")
}
if systemRole != "" {
query = query.Where("system_role = ?", systemRole)
} else {
query = query.Where("system_role > 0")
}
if identityCode != "" {
query = query.Where("identity_code LIKE ? OR referrer_identity_code LIKE ?", "%"+identityCode+"%", "%"+identityCode+"%")
}
// 获取总数
query.Count(&total)
// 分页查询
offset := (page - 1) * pageSize
err := query.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&users).Error
if err != nil {
c.JSON(http.StatusOK, common.Error(500, "查询用户列表失败"))
return
}
// 构建返回数据
result := map[string]interface{}{
"list": users,
"total": total,
"page": page,
"page_size": pageSize,
}
c.JSON(http.StatusOK, common.Success(result))
}
// GetUser 获取单个用户信息
func (h *AdminUserHandler) GetUser(c *gin.Context) {
userID, err := middleware.GetUserIDFromParam(c, "id")
if err != nil {
c.JSON(http.StatusOK, common.Error(400, err.Error()))
return
}
var user models.User
err = common.GetDB().First(&user, userID).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
c.JSON(http.StatusOK, common.Error(404, "用户不存在"))
} else {
c.JSON(http.StatusOK, common.Error(500, "查询用户信息失败"))
}
return
}
c.JSON(http.StatusOK, common.Success(user))
}
// CreateUser 创建用户(仅管理员)
func (h *AdminUserHandler) CreateUser(c *gin.Context) {
currentUser, _ := c.Get("current_user")
user := currentUser.(models.User)
// 只有管理员可以创建用户
if user.SystemRole != 0 {
c.JSON(http.StatusOK, common.Error(403, "权限不足"))
return
}
var newUser models.User
if err := c.ShouldBindJSON(&newUser); err != nil {
c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error()))
return
}
// 检查手机号是否已存在
var existUser models.User
if err := common.GetDB().Where("phone = ?", newUser.Phone).First(&existUser).Error; err == nil {
c.JSON(http.StatusOK, common.Error(400, "手机号已存在"))
return
}
if newUser.SystemRole == 1 {
newUser.IdentityCode = "T" + uuid.New().String()[:8]
} else {
newUser.IdentityCode = "U" + uuid.New().String()[:8]
}
if newUser.Password != "" {
newUser.Password = fmt.Sprintf("%x", md5.Sum([]byte(newUser.Password)))
}
// 保存用户
if err := common.GetDB().Create(&newUser).Error; err != nil {
c.JSON(http.StatusOK, common.Error(500, "创建用户失败"))
return
}
c.JSON(http.StatusOK, common.Success(newUser))
}
// UpdateUser 更新用户信息(仅管理员)
func (h *AdminUserHandler) UpdateUser(c *gin.Context) {
currentUser, _ := c.Get("current_user")
user := currentUser.(models.User)
// 只有管理员可以更新用户
if user.SystemRole != 0 {
c.JSON(http.StatusOK, common.Error(403, "权限不足"))
return
}
userID, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
c.JSON(http.StatusOK, common.Error(400, "用户ID无效"))
return
}
var updateData models.User
if err := c.ShouldBindJSON(&updateData); err != nil {
c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error()))
return
}
fmt.Println(updateData)
// 检查用户是否存在
var existUser models.User
if err := common.GetDB().First(&existUser, uint(userID)).Error; err != nil {
c.JSON(http.StatusOK, common.Error(404, "用户不存在"))
return
}
// 更新用户信息
updateData.ID = uint(userID)
if updateData.Password != "" {
updateData.Password = fmt.Sprintf("%x", md5.Sum([]byte(updateData.Password)))
}
if err := common.GetDB().Model(&existUser).Updates(&updateData).Error; err != nil {
c.JSON(http.StatusOK, common.Error(500, "更新用户信息失败"))
return
}
if err := common.GetDB().Model(&existUser).Updates(map[string]interface{}{
"status": updateData.Status,
}).Error; err != nil {
c.JSON(http.StatusOK, common.Error(500, "更新用户信息失败"))
return
}
// 返回更新后的用户信息
var updatedUser models.User
common.GetDB().First(&updatedUser, uint(userID))
c.JSON(http.StatusOK, common.Success(updatedUser))
}
// DeleteUser 删除用户(仅管理员)
func (h *AdminUserHandler) DeleteUser(c *gin.Context) {
currentUser, _ := c.Get("current_user")
user := currentUser.(models.User)
// 只有管理员可以删除用户
if user.SystemRole != 0 {
c.JSON(http.StatusOK, common.Error(403, "权限不足"))
return
}
userID, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
c.JSON(http.StatusOK, common.Error(400, "用户ID无效"))
return
}
// 检查用户是否存在
var existUser models.User
if err := common.GetDB().First(&existUser, uint(userID)).Error; err != nil {
c.JSON(http.StatusOK, common.Error(404, "用户不存在"))
return
}
// 删除用户
if err := common.GetDB().Delete(&existUser).Error; err != nil {
c.JSON(http.StatusOK, common.Error(500, "删除用户失败"))
return
}
c.JSON(http.StatusOK, common.Success(nil))
}
// GetUserStats 获取用户统计信息
func (h *AdminUserHandler) GetUserStats(c *gin.Context) {
currentUser, _ := c.Get("current_user")
user := currentUser.(models.User)
db := common.GetDB()
stats := make(map[string]interface{})
// 如果是代理商,只统计自己邀请的用户
baseQuery := db.Model(&models.User{})
if user.SystemRole == 1 {
baseQuery = baseQuery.Where("referrer_identity_code = ?", user.IdentityCode)
}
// 总用户数
var totalUsers int64
baseQuery.Count(&totalUsers)
stats["total_users"] = totalUsers
// 按角色统计
var roleCounts []struct {
SystemRole uint8 `json:"system_role"`
Count int64 `json:"count"`
}
roleQuery := baseQuery
if user.SystemRole == 1 {
roleQuery = roleQuery.Where("referrer_identity_code = ?", user.IdentityCode)
}
roleQuery.Select("system_role, count(*) as count").Group("system_role").Scan(&roleCounts)
stats["role_counts"] = roleCounts
// 今日新增用户
var todayUsers int64
todayQuery := baseQuery
if user.SystemRole == 1 {
todayQuery = todayQuery.Where("referrer_identity_code = ?", user.IdentityCode)
}
todayQuery.Where("DATE(created_at) = CURDATE()").Count(&todayUsers)
stats["today_users"] = todayUsers
c.JSON(http.StatusOK, common.Success(stats))
}
// SetUserExpiryDate 设置用户过期时间(仅管理员)
func (h *AdminUserHandler) SetUserExpiryDate(c *gin.Context) {
currentUser, _ := c.Get("current_user")
user := currentUser.(models.User)
// 只有管理员可以设置用户过期时间
if user.SystemRole != 0 {
c.JSON(http.StatusOK, common.Error(403, "权限不足"))
return
}
userID, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
c.JSON(http.StatusOK, common.Error(400, "用户ID无效"))
return
}
var req struct {
ExpiryDate *string `json:"expiry_date"` // ISO 8601 格式,如 "2024-12-31T23:59:59Z"null表示永不过期
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusOK, common.Error(400, "请求参数错误"))
return
}
db := common.GetDB()
// 检查用户是否存在
var targetUser models.User
if err := db.First(&targetUser, uint(userID)).Error; err != nil {
if err == gorm.ErrRecordNotFound {
c.JSON(http.StatusOK, common.Error(404, "用户不存在"))
} else {
c.JSON(http.StatusOK, common.Error(500, "查询用户失败"))
}
return
}
// 防止设置管理员的过期时间
if targetUser.SystemRole == 0 {
c.JSON(http.StatusOK, common.Error(400, "不能设置管理员的过期时间"))
return
}
// 解析过期时间
var expiryDate *time.Time
if req.ExpiryDate != nil && *req.ExpiryDate != "" {
parsedTime, err := time.Parse(time.RFC3339, *req.ExpiryDate)
if err != nil {
c.JSON(http.StatusOK, common.Error(400, "过期时间格式错误,请使用ISO 8601格式"))
return
}
expiryDate = &parsedTime
}
// 更新用户过期时间
if err := db.Model(&targetUser).Update("expiry_date", expiryDate).Error; err != nil {
c.JSON(http.StatusOK, common.Error(500, "设置用户过期时间失败"))
return
}
var message string
if expiryDate == nil {
message = "用户已设置为永不过期"
} else {
message = fmt.Sprintf("用户过期时间已设置为:%s", expiryDate.Format("2006-01-02 15:04:05"))
}
c.JSON(http.StatusOK, common.Success(map[string]interface{}{
"message": message,
"expiry_date": expiryDate,
}))
}
// SearchUserStats 搜索用户统计信息
func (h *AdminUserHandler) SearchUserStats(c *gin.Context) {
// 获取当前用户信息
currentUser, _ := c.Get("current_user")
currentUseruser := currentUser.(models.User)
// 仅管理员可访问
if currentUseruser.SystemRole > 1 {
c.JSON(http.StatusOK, common.Error(403, "权限不足"))
return
}
query := c.Query("query")
if query == "" {
c.JSON(http.StatusOK, common.Error(400, "搜索条件不能为空"))
return
}
// 获取时间范围参数
startDate := c.Query("start_date")
endDate := c.Query("end_date")
db := common.GetDB()
var user models.User
//err2 := db.Where("id=?", currentUseruser.ID).First(&currentUseruser).Error
//if err2 != nil {
// c.JSON(http.StatusOK, common.Error(403, "权限不足"))
// return
//}
// 按手机号或姓名搜索用户
err := db.Where("phone = ? OR customer_name LIKE ? OR real_name LIKE ?",
query, "%"+query+"%", "%"+query+"%").First(&user).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
c.JSON(http.StatusOK, common.Error(404, "未找到匹配的用户"))
} else {
c.JSON(http.StatusOK, common.Error(500, "查询用户失败"))
}
return
}
if currentUseruser.SystemRole == 1 && user.ReferrerIdentityCode != currentUseruser.IdentityCode {
c.JSON(http.StatusOK, common.Error(403, "权限不足"))
return
}
// 统计该用户的数据
stats := make(map[string]interface{})
// 构建采购订单查询
purchaseQuery := db.Model(&models.PurchaseOrder{}).Where("buyer_id = ? and order_status=?", user.ID, 2)
if startDate != "" && endDate != "" {
purchaseQuery = purchaseQuery.Where("created_at >= ? AND created_at <= ?", startDate+" 00:00:00", endDate+" 23:59:59")
}
// 采购订单统计
var purchaseOrdersCount int64
var totalPurchaseAmount float64
purchaseQuery.Count(&purchaseOrdersCount)
purchaseQuery.Select("COALESCE(SUM(total_amount), 0)").Scan(&totalPurchaseAmount)
// 构建销售订单查询
salesQuery := db.Model(&models.SalesOrder{}).Where("seller_id = ? and order_status=?", user.ID, 2)
if startDate != "" && endDate != "" {
salesQuery = salesQuery.Where("created_at >= ? AND created_at <= ?", startDate+" 00:00:00", endDate+" 23:59:59")
}
// 销售订单统计
var salesOrdersCount int64
var totalSalesAmount float64
salesQuery.Count(&salesOrdersCount)
salesQuery.Select("COALESCE(SUM(total_amount), 0)").Scan(&totalSalesAmount)
// 库存统计
var warehouseItemsCount int64
var totalWarehouseQuantity int64
if startDate != "" && endDate != "" {
db.Model(&models.UserWarehouse{}).Where("user_id = ? and created_at >= ? AND created_at <= ?", user.ID, startDate+" 00:00:00", endDate+" 23:59:59").Count(&warehouseItemsCount)
db.Model(&models.UserWarehouse{}).Where("user_id = ? and created_at >= ? AND created_at <= ?", user.ID, startDate+" 00:00:00", endDate+" 23:59:59").Select("COALESCE(SUM(quantity), 0)").Scan(&totalWarehouseQuantity)
} else {
db.Model(&models.UserWarehouse{}).Where("user_id = ? ", user.ID).Count(&warehouseItemsCount)
db.Model(&models.UserWarehouse{}).Where("user_id = ? ", user.ID).Select("COALESCE(SUM(quantity), 0)").Scan(&totalWarehouseQuantity)
}
// 积分余额
var scoreBalance int
//db.Model(&models.ScoreRecord{}).Where("user_id = ?", user.ID).Select("COALESCE(SUM(score_change), 0)").Scan(&scoreBalance)
scoreBalance = user.CurrentPoints
// 最后活动时间(最近的订单时间)
var lastActivityTime *time.Time
var lastPurchaseTime, lastSalesTime time.Time
// 查找最近的采购订单时间
db.Model(&models.PurchaseOrder{}).Where("user_id = ?", user.ID).
Select("created_at").Order("created_at DESC").Limit(1).Scan(&lastPurchaseTime)
// 查找最近的销售订单时间
db.Model(&models.SalesOrder{}).Where("user_id = ?", user.ID).
Select("created_at").Order("created_at DESC").Limit(1).Scan(&lastSalesTime)
// 取两个时间中的最大值
if !lastPurchaseTime.IsZero() && !lastSalesTime.IsZero() {
if lastPurchaseTime.After(lastSalesTime) {
lastActivityTime = &lastPurchaseTime
} else {
lastActivityTime = &lastSalesTime
}
} else if !lastPurchaseTime.IsZero() {
lastActivityTime = &lastPurchaseTime
} else if !lastSalesTime.IsZero() {
lastActivityTime = &lastSalesTime
}
stats["purchase_orders_count"] = purchaseOrdersCount
stats["total_purchase_amount"] = totalPurchaseAmount
stats["sales_orders_count"] = salesOrdersCount
stats["total_sales_amount"] = totalSalesAmount
stats["warehouse_items_count"] = warehouseItemsCount
stats["total_warehouse_quantity"] = totalWarehouseQuantity
stats["score_balance"] = scoreBalance
stats["last_activity_time"] = lastActivityTime
result := map[string]interface{}{
"user": user,
"stats": stats,
}
c.JSON(http.StatusOK, common.Success(result))
}
// GetAllUserWarehouses 获取所有用户库存汇总(管理员专用)
func (h *AdminUserHandler) GetAllUserWarehouses(c *gin.Context) {
// 获取当前用户信息
currentUser, _ := c.Get("current_user")
currentUseruser := currentUser.(models.User)
// 仅管理员可访问
if currentUseruser.SystemRole > 1 {
c.JSON(http.StatusOK, common.Error(403, "权限不足"))
return
}
// 分页参数
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 10
}
// 搜索参数
searchQuery := c.Query("search") // 搜索手机号或姓名
productType := c.Query("product_type") // 商品类型:1一级商品,2二级商品
status := c.Query("status") // 状态:0已出售,1库存中
db := common.GetDB()
// 构建库存记录查询(带用户信息)
warehouseQuery := db.Model(&models.UserWarehouse{}).
Select("user_warehouse.*, users.phone, users.customer_name, users.real_name").
Joins("JOIN users ON users.id = user_warehouse.user_id")
// 搜索用户(基于手机号或姓名)
if searchQuery != "" {
warehouseQuery = warehouseQuery.Where("users.phone LIKE ? OR users.customer_name LIKE ? OR users.real_name LIKE ?",
"%"+searchQuery+"%", "%"+searchQuery+"%", "%"+searchQuery+"%")
}
// 应用商品类型筛选
if productType != "" {
warehouseQuery = warehouseQuery.Where("user_warehouse.product_type = ?", productType)
}
// 应用状态筛选
if status != "" {
warehouseQuery = warehouseQuery.Where("user_warehouse.status = ?", status)
}
// 获取总数
var total int64
warehouseQuery.Count(&total)
// 分页查询库存记录
var userWarehouses []models.UserWarehouse
offset := (page - 1) * pageSize
err := warehouseQuery.Offset(offset).Limit(pageSize).Order("user_warehouse.created_at DESC").Find(&userWarehouses).Error
if err != nil {
c.JSON(http.StatusOK, common.Error(500, "查询用户库存列表失败"))
return
}
// 转换数据结构以包含用户信息,并按用户ID、商品类型、商品名称、状态聚合
var resultList []struct {
UserID uint `json:"user_id"`
Phone string `json:"phone"`
CustomerName string `json:"customer_name"`
RealName string `json:"real_name"`
ProductType uint8 `json:"product_type"`
ProductName string `json:"product_name"`
TotalQuantity int `json:"total_quantity"`
TotalValue float64 `json:"total_value"`
Status uint8 `json:"status"`
}
// 按用户ID、商品类型、商品名称、状态聚合库存
userWarehouseMap := make(map[string]*struct {
UserID uint `json:"user_id"`
Phone string `json:"phone"`
CustomerName string `json:"customer_name"`
RealName string `json:"real_name"`
ProductType uint8 `json:"product_type"`
ProductName string `json:"product_name"`
TotalQuantity int `json:"total_quantity"`
TotalValue float64 `json:"total_value"`
Status uint8 `json:"status"`
})
for _, warehouse := range userWarehouses {
// 生成唯一键:用户ID_商品类型_商品名称_状态
key := fmt.Sprintf("%d_%d_%s_%d", warehouse.UserID, warehouse.ProductType, warehouse.ProductName, warehouse.Status)
// 获取用户信息(第一次出现时)
var user models.User
db.First(&user, warehouse.UserID)
if item, exists := userWarehouseMap[key]; exists {
// 累加数量和价值
item.TotalQuantity += warehouse.Quantity
item.TotalValue += float64(warehouse.Quantity) * warehouse.WarehousePrice
} else {
// 创建新的聚合记录
userWarehouseMap[key] = &struct {
UserID uint `json:"user_id"`
Phone string `json:"phone"`
CustomerName string `json:"customer_name"`
RealName string `json:"real_name"`
ProductType uint8 `json:"product_type"`
ProductName string `json:"product_name"`
TotalQuantity int `json:"total_quantity"`
TotalValue float64 `json:"total_value"`
Status uint8 `json:"status"`
}{
UserID: warehouse.UserID,
Phone: user.Phone,
CustomerName: user.CustomerName,
RealName: user.RealName,
ProductType: warehouse.ProductType,
ProductName: warehouse.ProductName,
TotalQuantity: warehouse.Quantity,
TotalValue: float64(warehouse.Quantity) * warehouse.WarehousePrice,
Status: warehouse.Status,
}
}
}
// 转换为切片
for _, item := range userWarehouseMap {
resultList = append(resultList, *item)
}
// 构建返回数据
result := map[string]interface{}{
"list": resultList,
"total": total,
"page": page,
"page_size": pageSize,
}
c.JSON(http.StatusOK, common.Success(result))
}