946 lines
26 KiB
Go
946 lines
26 KiB
Go
package service
|
||
|
||
import (
|
||
"dianshang/internal/model"
|
||
"dianshang/internal/repository"
|
||
"dianshang/pkg/jwt"
|
||
"errors"
|
||
"fmt"
|
||
"time"
|
||
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// UserService 用户服务
|
||
type UserService struct {
|
||
userRepo *repository.UserRepository
|
||
db *gorm.DB
|
||
}
|
||
|
||
// NewUserService 创建用户服务
|
||
func NewUserService(db *gorm.DB) *UserService {
|
||
return &UserService{
|
||
userRepo: repository.NewUserRepository(db),
|
||
db: db,
|
||
}
|
||
}
|
||
|
||
// WeChatLogin 微信登录
|
||
func (s *UserService) WeChatLogin(code string) (*model.User, string, error) {
|
||
// TODO: 调用微信API获取openid
|
||
// 这里暂时模拟
|
||
openID := "mock_openid_" + code
|
||
|
||
// 查找用户
|
||
user, err := s.userRepo.GetByOpenID(openID)
|
||
if err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
// 用户不存在,创建新用户
|
||
user = &model.User{
|
||
OpenID: openID,
|
||
Nickname: "微信用户",
|
||
Status: 1,
|
||
}
|
||
if err := s.userRepo.Create(user); err != nil {
|
||
return nil, "", err
|
||
}
|
||
} else {
|
||
return nil, "", err
|
||
}
|
||
}
|
||
|
||
// 检查用户状态
|
||
if user.Status == 0 {
|
||
return nil, "", errors.New("用户已被禁用")
|
||
}
|
||
|
||
// 生成JWT token
|
||
token, err := jwt.GenerateToken(user.ID, "user", 7200)
|
||
if err != nil {
|
||
return nil, "", err
|
||
}
|
||
|
||
return user, token, nil
|
||
}
|
||
|
||
// CreateUser 创建用户
|
||
func (s *UserService) CreateUser(user *model.User) error {
|
||
// 检查用户是否已存在
|
||
existingUser, err := s.userRepo.GetByOpenID(user.OpenID)
|
||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return err
|
||
}
|
||
if existingUser != nil {
|
||
return errors.New("用户已存在")
|
||
}
|
||
|
||
return s.userRepo.Create(user)
|
||
}
|
||
|
||
// GetUserByID 根据ID获取用户
|
||
func (s *UserService) GetUserByID(id uint) (*model.User, error) {
|
||
return s.userRepo.GetByID(id)
|
||
}
|
||
|
||
// UpdateUser 更新用户信息
|
||
func (s *UserService) UpdateUser(id uint, updates map[string]interface{}) error {
|
||
// 更新用户表
|
||
if err := s.userRepo.Update(id, updates); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 同步更新微信用户信息表
|
||
wechatUpdates := make(map[string]interface{})
|
||
if nickname, ok := updates["nickname"]; ok {
|
||
wechatUpdates["nick_name"] = nickname
|
||
}
|
||
if avatar, ok := updates["avatar"]; ok {
|
||
wechatUpdates["avatar_url"] = avatar
|
||
}
|
||
if gender, ok := updates["gender"]; ok {
|
||
wechatUpdates["gender"] = gender
|
||
}
|
||
|
||
// 如果有需要更新的微信信息字段
|
||
if len(wechatUpdates) > 0 {
|
||
wechatUpdates["updated_at"] = time.Now()
|
||
|
||
// 更新微信用户信息表
|
||
if err := s.db.Model(&model.User{}).Where("id = ?", id).Updates(wechatUpdates).Error; err != nil {
|
||
// 记录错误但不影响主要更新流程
|
||
fmt.Printf("更新微信用户信息失败: %v\n", err)
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// GetUserAddresses 获取用户地址列表
|
||
func (s *UserService) GetUserAddresses(userID uint) ([]model.UserAddress, error) {
|
||
return s.userRepo.GetAddresses(userID)
|
||
}
|
||
|
||
// GetAddressByID 根据ID获取用户地址
|
||
func (s *UserService) GetAddressByID(userID, addressID uint) (*model.UserAddress, error) {
|
||
address, err := s.userRepo.GetAddressByID(addressID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 检查地址是否属于该用户
|
||
if address.UserID != userID {
|
||
return nil, errors.New("无权限访问该地址")
|
||
}
|
||
|
||
return address, nil
|
||
}
|
||
|
||
// CreateAddress 创建用户地址
|
||
func (s *UserService) CreateAddress(address *model.UserAddress) error {
|
||
// 如果设置为默认地址,先取消其他默认地址
|
||
if address.IsDefault {
|
||
if err := s.userRepo.ClearDefaultAddress(address.UserID); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return s.userRepo.CreateAddress(address)
|
||
}
|
||
|
||
// UpdateAddress 更新用户地址
|
||
func (s *UserService) UpdateAddress(userID, addressID uint, updates map[string]interface{}) error {
|
||
// 检查地址是否属于该用户
|
||
address, err := s.userRepo.GetAddressByID(addressID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if address.UserID != userID {
|
||
return errors.New("无权限操作该地址")
|
||
}
|
||
|
||
// 如果设置为默认地址,先取消其他默认地址
|
||
if isDefault, ok := updates["is_default"]; ok && isDefault.(uint8) == 1 {
|
||
if err := s.userRepo.ClearDefaultAddress(userID); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return s.userRepo.UpdateAddress(addressID, updates)
|
||
}
|
||
|
||
// DeleteAddress 删除用户地址
|
||
func (s *UserService) DeleteAddress(userID, addressID uint) error {
|
||
// 检查地址是否属于该用户
|
||
address, err := s.userRepo.GetAddressByID(addressID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if address.UserID != userID {
|
||
return errors.New("无权限操作该地址")
|
||
}
|
||
|
||
return s.userRepo.DeleteAddress(addressID)
|
||
}
|
||
|
||
// SetDefaultAddress 设置默认地址
|
||
func (s *UserService) SetDefaultAddress(userID, addressID uint) error {
|
||
// 检查地址是否属于该用户
|
||
address, err := s.userRepo.GetAddressByID(addressID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if address.UserID != userID {
|
||
return errors.New("无权限操作该地址")
|
||
}
|
||
|
||
// 先取消其他默认地址
|
||
if err := s.userRepo.ClearDefaultAddress(userID); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 设置为默认地址
|
||
return s.userRepo.UpdateAddress(addressID, map[string]interface{}{
|
||
"is_default": 1,
|
||
})
|
||
}
|
||
|
||
// GetFavorites 获取用户收藏列表
|
||
func (s *UserService) GetFavorites(userID uint, page, limit int) ([]model.UserFavorite, int64, error) {
|
||
offset := (page - 1) * limit
|
||
return s.userRepo.GetFavorites(userID, offset, limit)
|
||
}
|
||
|
||
// AddToFavorite 添加收藏
|
||
func (s *UserService) AddToFavorite(userID, productID uint) error {
|
||
// 检查是否已经收藏
|
||
if s.userRepo.IsFavorite(userID, productID) {
|
||
return errors.New("商品已在收藏列表中")
|
||
}
|
||
|
||
favorite := &model.UserFavorite{
|
||
UserID: userID,
|
||
ProductID: productID,
|
||
}
|
||
return s.userRepo.CreateFavorite(favorite)
|
||
}
|
||
|
||
// RemoveFromFavorite 取消收藏
|
||
func (s *UserService) RemoveFromFavorite(userID, productID uint) error {
|
||
return s.userRepo.DeleteFavorite(userID, productID)
|
||
}
|
||
|
||
// IsFavorite 检查是否已收藏
|
||
func (s *UserService) IsFavorite(userID, productID uint) bool {
|
||
return s.userRepo.IsFavorite(userID, productID)
|
||
}
|
||
|
||
// GetUserStatistics 获取用户统计
|
||
func (s *UserService) GetUserStatistics(startDate, endDate string) (map[string]interface{}, error) {
|
||
result := make(map[string]interface{})
|
||
|
||
// 总用户数
|
||
var totalUsers int64
|
||
s.db.Model(&model.User{}).Count(&totalUsers)
|
||
result["total_users"] = totalUsers
|
||
|
||
// 新增用户数(指定日期范围)
|
||
var newUsers int64
|
||
query := s.db.Model(&model.User{})
|
||
if startDate != "" && endDate != "" {
|
||
query = query.Where("DATE(created_at) BETWEEN ? AND ?", startDate, endDate)
|
||
}
|
||
query.Count(&newUsers)
|
||
result["new_users"] = newUsers
|
||
|
||
// 活跃用户数(简化处理,这里用登录用户数代替)
|
||
var activeUsers int64
|
||
activeQuery := s.db.Model(&model.User{}).Where("status = ?", 1)
|
||
if startDate != "" && endDate != "" {
|
||
activeQuery = activeQuery.Where("DATE(updated_at) BETWEEN ? AND ?", startDate, endDate)
|
||
}
|
||
activeQuery.Count(&activeUsers)
|
||
result["active_users"] = activeUsers
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// GetDailyUserStatistics 获取每日用户统计
|
||
func (s *UserService) GetDailyUserStatistics(startDate, endDate string) ([]map[string]interface{}, error) {
|
||
// 简化实现,返回基础统计数据
|
||
var results []map[string]interface{}
|
||
|
||
// 解析日期
|
||
start, err := time.Parse("2006-01-02", startDate)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
end, err := time.Parse("2006-01-02", endDate)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 遍历日期范围
|
||
for d := start; !d.After(end); d = d.AddDate(0, 0, 1) {
|
||
dateStr := d.Format("2006-01-02")
|
||
|
||
var newUsers int64
|
||
s.db.Model(&model.User{}).
|
||
Where("DATE(created_at) = ?", dateStr).
|
||
Count(&newUsers)
|
||
|
||
results = append(results, map[string]interface{}{
|
||
"date": dateStr,
|
||
"new_users": newUsers,
|
||
})
|
||
}
|
||
|
||
return results, nil
|
||
}
|
||
|
||
// GetUserListForAdmin 获取用户列表(管理后台)
|
||
func (s *UserService) GetUserListForAdmin(page, pageSize int, conditions map[string]interface{}) ([]model.User, map[string]interface{}, error) {
|
||
var users []model.User
|
||
var total int64
|
||
|
||
query := s.db.Model(&model.User{})
|
||
|
||
// 应用查询条件
|
||
if keyword, ok := conditions["keyword"]; ok && keyword != "" {
|
||
query = query.Where("nickname LIKE ? OR email LIKE ? OR phone LIKE ?",
|
||
"%"+keyword.(string)+"%", "%"+keyword.(string)+"%", "%"+keyword.(string)+"%")
|
||
}
|
||
|
||
if status, ok := conditions["status"]; ok && status != "" {
|
||
query = query.Where("status = ?", status)
|
||
}
|
||
|
||
if startDate, ok := conditions["start_date"]; ok && startDate != "" {
|
||
query = query.Where("created_at >= ?", startDate)
|
||
}
|
||
|
||
if endDate, ok := conditions["end_date"]; ok && endDate != "" {
|
||
query = query.Where("created_at <= ?", endDate)
|
||
}
|
||
|
||
// 获取总数
|
||
err := query.Count(&total).Error
|
||
if err != nil {
|
||
return nil, nil, err
|
||
}
|
||
|
||
// 分页查询
|
||
offset := (page - 1) * pageSize
|
||
err = query.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&users).Error
|
||
if err != nil {
|
||
return nil, nil, err
|
||
}
|
||
|
||
// 构建分页信息
|
||
pagination := map[string]interface{}{
|
||
"total": total,
|
||
"page": page,
|
||
"page_size": pageSize,
|
||
"total_pages": (total + int64(pageSize) - 1) / int64(pageSize),
|
||
}
|
||
|
||
return users, pagination, nil
|
||
}
|
||
|
||
// GetUserDetailForAdmin 获取用户详情(管理后台)
|
||
func (s *UserService) GetUserDetailForAdmin(userID uint) (map[string]interface{}, error) {
|
||
var user model.User
|
||
err := s.db.Where("id = ?", userID).First(&user).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 构建返回数据
|
||
result := map[string]interface{}{
|
||
"id": user.ID,
|
||
"openid": user.OpenID,
|
||
"unionid": user.UnionID,
|
||
"nickname": user.Nickname,
|
||
"avatar": user.Avatar,
|
||
"gender": user.Gender,
|
||
"phone": user.Phone,
|
||
"email": user.Email,
|
||
"birthday": user.Birthday,
|
||
"points": user.Points,
|
||
"level": user.Level,
|
||
"status": user.Status,
|
||
"created_at": user.CreatedAt,
|
||
"updated_at": user.UpdatedAt,
|
||
}
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// UpdateUserStatusByAdmin 管理员更新用户状态
|
||
func (s *UserService) UpdateUserStatusByAdmin(userID uint, status uint8, remark string, adminID uint) error {
|
||
return s.db.Model(&model.User{}).Where("id = ?", userID).Update("status", status).Error
|
||
}
|
||
|
||
// UpdateUserProfile 更新用户资料
|
||
func (s *UserService) UpdateUserProfile(userID uint, updates map[string]interface{}) error {
|
||
// 验证更新字段
|
||
allowedFields := map[string]bool{
|
||
"nickname": true,
|
||
"avatar": true,
|
||
"gender": true,
|
||
"phone": true,
|
||
"email": true,
|
||
"birthday": true,
|
||
}
|
||
|
||
filteredUpdates := make(map[string]interface{})
|
||
for key, value := range updates {
|
||
if allowedFields[key] {
|
||
filteredUpdates[key] = value
|
||
}
|
||
}
|
||
|
||
if len(filteredUpdates) == 0 {
|
||
return fmt.Errorf("没有有效的更新字段")
|
||
}
|
||
|
||
filteredUpdates["updated_at"] = time.Now()
|
||
|
||
return s.db.Model(&model.User{}).Where("id = ?", userID).Updates(filteredUpdates).Error
|
||
}
|
||
|
||
// UpdateUserProfileByAdmin 管理员更新用户资料
|
||
func (s *UserService) UpdateUserProfileByAdmin(userID uint, updates map[string]interface{}, adminID uint) error {
|
||
// 验证更新字段
|
||
allowedFields := map[string]bool{
|
||
"nickname": true,
|
||
"avatar": true,
|
||
"gender": true,
|
||
"phone": true,
|
||
"email": true,
|
||
"birthday": true,
|
||
}
|
||
|
||
filteredUpdates := make(map[string]interface{})
|
||
for key, value := range updates {
|
||
if allowedFields[key] {
|
||
filteredUpdates[key] = value
|
||
}
|
||
}
|
||
|
||
if len(filteredUpdates) == 0 {
|
||
return fmt.Errorf("没有有效的更新字段")
|
||
}
|
||
|
||
filteredUpdates["updated_at"] = time.Now()
|
||
|
||
// TODO: 记录操作日志
|
||
// 可以在这里添加操作日志记录,记录管理员修改用户资料的操作
|
||
|
||
return s.db.Model(&model.User{}).Where("id = ?", userID).Updates(filteredUpdates).Error
|
||
}
|
||
|
||
// ResetUserPassword 重置用户密码(管理员操作)
|
||
func (s *UserService) ResetUserPassword(userID uint, newPassword string, adminID uint) error {
|
||
// 这里可以添加密码加密逻辑
|
||
// 由于是微信小程序,通常不需要密码,这里预留接口
|
||
updates := map[string]interface{}{
|
||
"updated_at": time.Now(),
|
||
}
|
||
|
||
return s.db.Model(&model.User{}).Where("id = ?", userID).Updates(updates).Error
|
||
}
|
||
|
||
|
||
|
||
// CreateUserAddress 创建用户地址
|
||
func (s *UserService) CreateUserAddress(address *model.UserAddress) error {
|
||
// 如果设置为默认地址,先取消其他默认地址
|
||
if address.IsDefault {
|
||
s.db.Model(&model.UserAddress{}).Where("user_id = ?", address.UserID).Update("is_default", false)
|
||
}
|
||
|
||
return s.db.Create(address).Error
|
||
}
|
||
|
||
// UpdateUserAddress 更新用户地址
|
||
func (s *UserService) UpdateUserAddress(addressID uint, userID uint, updates map[string]interface{}) error {
|
||
// 如果设置为默认地址,先取消其他默认地址
|
||
if isDefault, ok := updates["is_default"]; ok && isDefault.(bool) {
|
||
s.db.Model(&model.UserAddress{}).Where("user_id = ?", userID).Update("is_default", false)
|
||
}
|
||
|
||
updates["updated_at"] = time.Now()
|
||
|
||
return s.db.Model(&model.UserAddress{}).Where("id = ? AND user_id = ?", addressID, userID).Updates(updates).Error
|
||
}
|
||
|
||
// DeleteUserAddress 删除用户地址
|
||
func (s *UserService) DeleteUserAddress(addressID uint, userID uint) error {
|
||
return s.db.Where("id = ? AND user_id = ?", addressID, userID).Delete(&model.UserAddress{}).Error
|
||
}
|
||
|
||
// GetUserFavorites 获取用户收藏列表
|
||
func (s *UserService) GetUserFavorites(userID uint, page, pageSize int) ([]model.UserFavorite, map[string]interface{}, error) {
|
||
var favorites []model.UserFavorite
|
||
var total int64
|
||
|
||
query := s.db.Model(&model.UserFavorite{}).Where("user_id = ?", userID).Preload("Product")
|
||
|
||
// 获取总数
|
||
err := query.Count(&total).Error
|
||
if err != nil {
|
||
return nil, nil, err
|
||
}
|
||
|
||
// 分页查询
|
||
offset := (page - 1) * pageSize
|
||
err = query.Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&favorites).Error
|
||
if err != nil {
|
||
return nil, nil, err
|
||
}
|
||
|
||
// 构建分页信息
|
||
pagination := map[string]interface{}{
|
||
"total": total,
|
||
"page": page,
|
||
"page_size": pageSize,
|
||
"total_pages": (total + int64(pageSize) - 1) / int64(pageSize),
|
||
}
|
||
|
||
return favorites, pagination, nil
|
||
}
|
||
|
||
// AddUserFavorite 添加用户收藏
|
||
func (s *UserService) AddUserFavorite(userID, productID uint) error {
|
||
// 检查是否已收藏
|
||
var count int64
|
||
s.db.Model(&model.UserFavorite{}).Where("user_id = ? AND product_id = ?", userID, productID).Count(&count)
|
||
if count > 0 {
|
||
return fmt.Errorf("商品已收藏")
|
||
}
|
||
|
||
favorite := &model.UserFavorite{
|
||
UserID: userID,
|
||
ProductID: productID,
|
||
CreatedAt: time.Now(),
|
||
UpdatedAt: time.Now(),
|
||
}
|
||
|
||
return s.db.Create(favorite).Error
|
||
}
|
||
|
||
// RemoveUserFavorite 移除用户收藏
|
||
func (s *UserService) RemoveUserFavorite(userID, productID uint) error {
|
||
return s.db.Where("user_id = ? AND product_id = ?", userID, productID).Delete(&model.UserFavorite{}).Error
|
||
}
|
||
|
||
|
||
|
||
// GetUserLevelInfo 获取用户等级信息
|
||
func (s *UserService) GetUserLevelInfo(userID uint) (map[string]interface{}, error) {
|
||
user, err := s.GetUserByID(userID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 计算用户等级相关信息
|
||
levelInfo := map[string]interface{}{
|
||
"current_level": user.Level,
|
||
"current_points": user.Points,
|
||
"level_name": s.getLevelName(user.Level),
|
||
"next_level": user.Level + 1,
|
||
"next_level_name": s.getLevelName(user.Level + 1),
|
||
"points_to_next": s.getPointsToNextLevel(user.Level, user.Points),
|
||
}
|
||
|
||
return levelInfo, nil
|
||
}
|
||
|
||
// getLevelName 获取等级名称
|
||
func (s *UserService) getLevelName(level int) string {
|
||
levelNames := map[int]string{
|
||
1: "青铜会员",
|
||
2: "白银会员",
|
||
3: "黄金会员",
|
||
4: "铂金会员",
|
||
5: "钻石会员",
|
||
}
|
||
|
||
if name, ok := levelNames[level]; ok {
|
||
return name
|
||
}
|
||
return "普通会员"
|
||
}
|
||
|
||
// getPointsToNextLevel 获取升级到下一等级所需积分
|
||
func (s *UserService) getPointsToNextLevel(currentLevel, currentPoints int) int {
|
||
levelThresholds := map[int]int{
|
||
1: 0,
|
||
2: 1000,
|
||
3: 3000,
|
||
4: 6000,
|
||
5: 10000,
|
||
}
|
||
|
||
nextLevel := currentLevel + 1
|
||
if threshold, ok := levelThresholds[nextLevel]; ok {
|
||
return threshold - currentPoints
|
||
}
|
||
return 0 // 已达到最高等级
|
||
}
|
||
|
||
// UpdateUserLevel 更新用户等级
|
||
func (s *UserService) UpdateUserLevel(userID uint) error {
|
||
user, err := s.GetUserByID(userID)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
newLevel := s.calculateUserLevel(user.Points)
|
||
if newLevel != user.Level {
|
||
return s.db.Model(&model.User{}).Where("id = ?", userID).Update("level", newLevel).Error
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// UpdateUserLevelByAdmin 管理员手动设置用户等级
|
||
func (s *UserService) UpdateUserLevelByAdmin(userID uint, level uint8, remark string, adminID uint) error {
|
||
// 验证等级范围
|
||
if level < 1 || level > 5 {
|
||
return errors.New("用户等级必须在1-5之间")
|
||
}
|
||
|
||
// 更新用户等级
|
||
err := s.db.Model(&model.User{}).Where("id = ?", userID).Update("level", level).Error
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
// TODO: 记录操作日志
|
||
// 可以在这里添加操作日志记录,记录管理员修改用户等级的操作
|
||
|
||
return nil
|
||
}
|
||
|
||
// calculateUserLevel 根据积分计算用户等级
|
||
func (s *UserService) calculateUserLevel(points int) int {
|
||
if points >= 10000 {
|
||
return 5
|
||
} else if points >= 6000 {
|
||
return 4
|
||
} else if points >= 3000 {
|
||
return 3
|
||
} else if points >= 1000 {
|
||
return 2
|
||
}
|
||
return 1
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
// ResetUserPasswordByAdmin 管理员重置用户密码
|
||
func (s *UserService) ResetUserPasswordByAdmin(userID uint, newPassword string, adminID uint) error {
|
||
// 这里应该对密码进行加密处理,暂时简化实现
|
||
// 在实际项目中,用户可能通过微信登录,不需要密码
|
||
// 这里只是为了满足接口需求
|
||
return s.db.Model(&model.User{}).Where("id = ?", userID).Update("updated_at", time.Now()).Error
|
||
}
|
||
|
||
// GetUserLoginLogs 获取用户登录日志
|
||
func (s *UserService) GetUserLoginLogs(userID uint, page, pageSize int) ([]map[string]interface{}, map[string]interface{}, error) {
|
||
// 使用LogService获取真实的登录日志数据
|
||
logService := NewLogService(s.db)
|
||
logs, pagination, err := logService.GetUserLoginLogs(userID, page, pageSize)
|
||
if err != nil {
|
||
return nil, nil, err
|
||
}
|
||
|
||
// 转换为前端需要的格式
|
||
var result []map[string]interface{}
|
||
for _, log := range logs {
|
||
result = append(result, map[string]interface{}{
|
||
"id": log.ID,
|
||
"user_id": log.UserID,
|
||
"login_time": log.LoginTime.Format("2006-01-02 15:04:05"),
|
||
"ip_address": log.LoginIP,
|
||
"device": log.UserAgent,
|
||
"location": "未知", // 可以后续添加IP地址解析功能
|
||
"status": log.Status,
|
||
"remark": log.Remark,
|
||
})
|
||
}
|
||
|
||
return result, pagination, nil
|
||
}
|
||
|
||
// GetUserPurchaseRanking 获取用户购买排行
|
||
func (s *UserService) GetUserPurchaseRanking(startDate, endDate, limit string) ([]map[string]interface{}, error) {
|
||
// 简化实现,返回基础排行数据
|
||
var results []map[string]interface{}
|
||
|
||
// 获取活跃用户
|
||
var users []model.User
|
||
err := s.db.Model(&model.User{}).
|
||
Where("status = ?", 1).
|
||
Limit(10).
|
||
Find(&users).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
for i, user := range users {
|
||
results = append(results, map[string]interface{}{
|
||
"user_id": user.ID,
|
||
"nickname": user.Nickname,
|
||
"purchase_count": 50 - i*3, // 模拟购买次数
|
||
"purchase_amount": float64(5000 - i*200), // 模拟购买金额
|
||
})
|
||
}
|
||
|
||
return results, nil
|
||
}
|
||
|
||
// GetUserGrowthTrend 获取用户增长趋势
|
||
func (s *UserService) GetUserGrowthTrend(days int) ([]map[string]interface{}, error) {
|
||
var results []map[string]interface{}
|
||
|
||
for i := days - 1; i >= 0; i-- {
|
||
date := time.Now().AddDate(0, 0, -i).Format("2006-01-02")
|
||
|
||
// 新增用户数
|
||
var newUsers int64
|
||
s.db.Model(&model.User{}).
|
||
Where("DATE(created_at) = ?", date).
|
||
Count(&newUsers)
|
||
|
||
// 累计用户数
|
||
var totalUsers int64
|
||
s.db.Model(&model.User{}).
|
||
Where("DATE(created_at) <= ?", date).
|
||
Count(&totalUsers)
|
||
|
||
// 活跃用户数(当天有更新记录的用户)
|
||
var activeUsers int64
|
||
s.db.Model(&model.User{}).
|
||
Where("DATE(updated_at) = ? AND status = ?", date, 1).
|
||
Count(&activeUsers)
|
||
|
||
results = append(results, map[string]interface{}{
|
||
"date": date,
|
||
"new_users": newUsers,
|
||
"total_users": totalUsers,
|
||
"active_users": activeUsers,
|
||
})
|
||
}
|
||
|
||
return results, nil
|
||
}
|
||
|
||
// GetUserActivityAnalysis 获取用户活跃度分析
|
||
func (s *UserService) GetUserActivityAnalysis(startDate, endDate string) (map[string]interface{}, error) {
|
||
result := make(map[string]interface{})
|
||
|
||
// 总用户数
|
||
var totalUsers int64
|
||
s.db.Model(&model.User{}).Count(&totalUsers)
|
||
|
||
// 活跃用户数(指定时间范围内有更新的用户)
|
||
var activeUsers int64
|
||
query := s.db.Model(&model.User{}).Where("status = ?", 1)
|
||
if startDate != "" && endDate != "" {
|
||
query = query.Where("DATE(updated_at) BETWEEN ? AND ?", startDate, endDate)
|
||
}
|
||
query.Count(&activeUsers)
|
||
|
||
// 新增用户数
|
||
var newUsers int64
|
||
newQuery := s.db.Model(&model.User{})
|
||
if startDate != "" && endDate != "" {
|
||
newQuery = newQuery.Where("DATE(created_at) BETWEEN ? AND ?", startDate, endDate)
|
||
}
|
||
newQuery.Count(&newUsers)
|
||
|
||
// 沉默用户数(30天内无活动的用户)
|
||
thirtyDaysAgo := time.Now().AddDate(0, 0, -30).Format("2006-01-02")
|
||
var silentUsers int64
|
||
s.db.Model(&model.User{}).
|
||
Where("status = ? AND DATE(updated_at) < ?", 1, thirtyDaysAgo).
|
||
Count(&silentUsers)
|
||
|
||
// 计算活跃率
|
||
var activityRate float64
|
||
if totalUsers > 0 {
|
||
activityRate = float64(activeUsers) / float64(totalUsers) * 100
|
||
}
|
||
|
||
result["total_users"] = totalUsers
|
||
result["active_users"] = activeUsers
|
||
result["new_users"] = newUsers
|
||
result["silent_users"] = silentUsers
|
||
result["activity_rate"] = activityRate
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// GetUserRetentionRate 获取用户留存率
|
||
func (s *UserService) GetUserRetentionRate(days int) ([]map[string]interface{}, error) {
|
||
var results []map[string]interface{}
|
||
|
||
for i := days - 1; i >= 0; i-- {
|
||
date := time.Now().AddDate(0, 0, -i).Format("2006-01-02")
|
||
nextDate := time.Now().AddDate(0, 0, -i+1).Format("2006-01-02")
|
||
|
||
// 当天新增用户数
|
||
var newUsers int64
|
||
s.db.Model(&model.User{}).
|
||
Where("DATE(created_at) = ?", date).
|
||
Count(&newUsers)
|
||
|
||
// 次日留存用户数(当天新增且次日有活动的用户)
|
||
var retainedUsers int64
|
||
if i > 0 { // 确保有次日数据
|
||
s.db.Model(&model.User{}).
|
||
Where("DATE(created_at) = ? AND DATE(updated_at) = ?", date, nextDate).
|
||
Count(&retainedUsers)
|
||
}
|
||
|
||
// 计算留存率
|
||
var retentionRate float64
|
||
if newUsers > 0 {
|
||
retentionRate = float64(retainedUsers) / float64(newUsers) * 100
|
||
}
|
||
|
||
results = append(results, map[string]interface{}{
|
||
"date": date,
|
||
"new_users": newUsers,
|
||
"retained_users": retainedUsers,
|
||
"retention_rate": retentionRate,
|
||
})
|
||
}
|
||
|
||
return results, nil
|
||
}
|
||
|
||
// GetUserLevelDistribution 获取用户等级分布
|
||
func (s *UserService) GetUserLevelDistribution() ([]map[string]interface{}, error) {
|
||
var results []map[string]interface{}
|
||
|
||
// 统计各等级用户数量
|
||
for level := 1; level <= 5; level++ {
|
||
var count int64
|
||
s.db.Model(&model.User{}).
|
||
Where("level = ? AND status = ?", level, 1).
|
||
Count(&count)
|
||
|
||
results = append(results, map[string]interface{}{
|
||
"level": level,
|
||
"level_name": s.getLevelName(level),
|
||
"user_count": count,
|
||
})
|
||
}
|
||
|
||
return results, nil
|
||
}
|
||
|
||
// GetUserGeographicDistribution 获取用户地域分布
|
||
func (s *UserService) GetUserGeographicDistribution() ([]map[string]interface{}, error) {
|
||
// 简化实现,返回模拟的地域分布数据
|
||
// 在实际项目中,可以根据用户地址或IP地址统计
|
||
regions := []map[string]interface{}{
|
||
{"region": "北京", "user_count": 1200},
|
||
{"region": "上海", "user_count": 980},
|
||
{"region": "广州", "user_count": 750},
|
||
{"region": "深圳", "user_count": 680},
|
||
{"region": "杭州", "user_count": 520},
|
||
{"region": "成都", "user_count": 450},
|
||
{"region": "武汉", "user_count": 380},
|
||
{"region": "西安", "user_count": 320},
|
||
{"region": "南京", "user_count": 280},
|
||
{"region": "其他", "user_count": 1430},
|
||
}
|
||
|
||
return regions, nil
|
||
}
|
||
|
||
// GetUserAgeDistribution 获取用户年龄分布
|
||
func (s *UserService) GetUserAgeDistribution() ([]map[string]interface{}, error) {
|
||
// 简化实现,返回模拟的年龄分布数据
|
||
// 在实际项目中,可以根据用户生日计算年龄分布
|
||
ageGroups := []map[string]interface{}{
|
||
{"age_group": "18-25", "user_count": 1500},
|
||
{"age_group": "26-30", "user_count": 2200},
|
||
{"age_group": "31-35", "user_count": 1800},
|
||
{"age_group": "36-40", "user_count": 1200},
|
||
{"age_group": "41-50", "user_count": 800},
|
||
{"age_group": "50+", "user_count": 500},
|
||
}
|
||
|
||
return ageGroups, nil
|
||
}
|
||
|
||
// GetUserEngagementMetrics 获取用户参与度指标
|
||
func (s *UserService) GetUserEngagementMetrics(startDate, endDate string) (map[string]interface{}, error) {
|
||
result := make(map[string]interface{})
|
||
|
||
// 平均会话时长(模拟数据)
|
||
result["avg_session_duration"] = 25.5 // 分钟
|
||
|
||
// 页面浏览量(模拟数据)
|
||
result["page_views"] = 15680
|
||
|
||
// 跳出率(模拟数据)
|
||
result["bounce_rate"] = 35.2 // 百分比
|
||
|
||
// 用户互动次数(收藏、评价等)
|
||
var favoriteCount int64
|
||
query := s.db.Model(&model.UserFavorite{})
|
||
if startDate != "" && endDate != "" {
|
||
query = query.Where("DATE(created_at) BETWEEN ? AND ?", startDate, endDate)
|
||
}
|
||
query.Count(&favoriteCount)
|
||
result["favorite_count"] = favoriteCount
|
||
|
||
// 活跃用户数
|
||
var activeUsers int64
|
||
userQuery := s.db.Model(&model.User{}).Where("status = ?", 1)
|
||
if startDate != "" && endDate != "" {
|
||
userQuery = userQuery.Where("DATE(updated_at) BETWEEN ? AND ?", startDate, endDate)
|
||
}
|
||
userQuery.Count(&activeUsers)
|
||
result["active_users"] = activeUsers
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// DeleteUser 删除用户
|
||
func (s *UserService) DeleteUser(userID uint) error {
|
||
// 软删除用户
|
||
return s.db.Delete(&model.User{}, userID).Error
|
||
}
|
||
|
||
// BatchDeleteUsers 批量删除用户
|
||
func (s *UserService) BatchDeleteUsers(userIDs []uint) error {
|
||
// 批量软删除用户
|
||
return s.db.Delete(&model.User{}, userIDs).Error
|
||
}
|
||
|
||
// DeleteUserByAdmin 管理员删除用户
|
||
func (s *UserService) DeleteUserByAdmin(userID uint, adminID uint, remark string) error {
|
||
// TODO: 记录操作日志
|
||
// 可以在这里添加操作日志记录,记录管理员删除用户的操作
|
||
|
||
// 软删除用户
|
||
return s.db.Delete(&model.User{}, userID).Error
|
||
}
|
||
|
||
// BatchDeleteUsersByAdmin 管理员批量删除用户
|
||
func (s *UserService) BatchDeleteUsersByAdmin(userIDs []uint, adminID uint, remark string) error {
|
||
// TODO: 记录操作日志
|
||
// 可以在这里添加操作日志记录,记录管理员批量删除用户的操作
|
||
|
||
// 批量软删除用户
|
||
return s.db.Delete(&model.User{}, userIDs).Error
|
||
} |