379 lines
10 KiB
Go
379 lines
10 KiB
Go
package mysql
|
||
|
||
import (
|
||
"acquaintances/biz/model"
|
||
"acquaintances/biz/model/user"
|
||
"errors"
|
||
"fmt"
|
||
"github.com/cloudwego/hertz/pkg/common/hlog"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// SaveMomentWithImages 新建动态
|
||
func SaveMomentWithImages(moment *model.Moment, imageURLs []string) error {
|
||
db := DB
|
||
// 使用事务确保数据一致性
|
||
return db.Transaction(func(tx *gorm.DB) error {
|
||
// 保存动态
|
||
if err := tx.Create(moment).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
// 保存图片(如果有)
|
||
if len(imageURLs) > 0 {
|
||
images := make([]model.MomentImage, 0, len(imageURLs))
|
||
for _, url := range imageURLs {
|
||
images = append(images, model.MomentImage{
|
||
MomentID: moment.ID,
|
||
ImageURL: url,
|
||
})
|
||
}
|
||
if err := tx.Create(&images).Error; err != nil {
|
||
return err
|
||
}
|
||
}
|
||
|
||
return nil
|
||
})
|
||
}
|
||
|
||
// CheckUserExists 检查用户是否存在
|
||
func CheckUserExists(userID string) (bool, error) {
|
||
db := DB
|
||
// 实际实现中应查询数据库验证用户是否存在
|
||
// 这里仅为示例
|
||
var count int64
|
||
if err := db.Model(&model.User{}).Where("user_id = ?", userID).Count(&count).Error; err != nil {
|
||
return false, err
|
||
}
|
||
return count > 0, nil
|
||
}
|
||
|
||
// 获取当前用户的好友ID列表
|
||
// 获取当前用户的好友ID列表
|
||
func getFriendUserIDs(userID string) ([]string, error) {
|
||
var friends []model.FriendRelationship
|
||
// 一次查询所有与当前用户相关的已通过好友关系
|
||
err := DB.Model(model.FriendRelationship{}).
|
||
Where("(applicant_id = ? OR target_user_id = ?) AND status = 1", userID, userID).
|
||
Find(&friends).Error
|
||
if err != nil {
|
||
return nil, fmt.Errorf("查询好友列表失败: %w", err)
|
||
}
|
||
|
||
// 使用map去重
|
||
friendMap := make(map[string]struct{})
|
||
for _, rel := range friends {
|
||
// 根据关系方向添加对应的好友ID
|
||
if rel.ApplicantID == userID {
|
||
friendMap[rel.TargetUserID] = struct{}{}
|
||
} else {
|
||
friendMap[rel.ApplicantID] = struct{}{}
|
||
}
|
||
}
|
||
|
||
// 转换map为切片
|
||
friendUserIDs := make([]string, 0, len(friendMap))
|
||
for id := range friendMap {
|
||
friendUserIDs = append(friendUserIDs, id)
|
||
}
|
||
|
||
return friendUserIDs, nil
|
||
}
|
||
|
||
// 将用户模型转换为DTO
|
||
func convertUserModelToDTO(u model.User) user.UserInfoReq {
|
||
userInfo := user.UserInfoReq{
|
||
UserID: u.UserID,
|
||
UserName: u.UserName,
|
||
Gender: u.Gender,
|
||
Age: int64(u.Age),
|
||
Introduce: u.Introduce,
|
||
AvatarImageURL: u.AvatarImageURL,
|
||
}
|
||
|
||
// 可选字段处理
|
||
if u.Birthday != nil {
|
||
userInfo.Birthday = u.Birthday.Format("2006-01-02")
|
||
}
|
||
|
||
return userInfo
|
||
}
|
||
|
||
// GetMomentsImage 获取指定动态的图像列表
|
||
func GetMomentsImage(ids uint) ([]*user.MomentImage, error) {
|
||
db := DB
|
||
var images []model.MomentImage
|
||
var data []*user.MomentImage
|
||
err := db.Model(&model.MomentImage{}).Where("moment_id = ?", ids).Find(&images).Error
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
for _, v := range images {
|
||
data = append(data, &user.MomentImage{
|
||
ID: int64(v.ID),
|
||
MomentID: int64(v.MomentID),
|
||
ImageURL: v.ImageURL,
|
||
})
|
||
}
|
||
return data, nil
|
||
}
|
||
|
||
// GetFriendsMoments 获取好友动态
|
||
func GetFriendsMoments(req user.ListMomentsRequest) ([]*user.Moment, int32, error) {
|
||
db := DB
|
||
//获取好友id列表
|
||
friends, err := getFriendUserIDs(req.UserID)
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
// 校验分页参数
|
||
if req.Page < 1 {
|
||
req.Page = 1
|
||
}
|
||
if req.PageSize < 1 {
|
||
req.PageSize = 10
|
||
}
|
||
|
||
// 查询总数
|
||
var total int64
|
||
query := db.Model(&model.Moment{}).Where("user_id = ?", req.UserID)
|
||
if len(friends) > 0 {
|
||
query = query.Or("user_id IN (?) AND visibility != ?", friends, model.VisibilitySelfOnly)
|
||
}
|
||
if err := query.Count(&total).Error; err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
//获取朋友圈内容信息
|
||
var moments []model.Moment
|
||
query = db.Model(&model.Moment{}).Where("user_id = ?", req.UserID)
|
||
if len(friends) > 0 {
|
||
query = query.Or("user_id IN (?) AND visibility != ?", friends, model.VisibilitySelfOnly)
|
||
}
|
||
err = query.Limit(int(req.PageSize)).Offset(int(req.PageSize * (req.Page - 1))).Find(&moments).Error
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
//批量查询用户信息
|
||
var userIDs []string
|
||
for _, v := range moments {
|
||
userIDs = append(userIDs, v.UserID)
|
||
}
|
||
userInfo, err := GetUsersById(userIDs...) // 自定义批量查询函数
|
||
if err != nil {
|
||
hlog.Errorf("批量查询用户失败: %v", err)
|
||
return nil, 0, err
|
||
}
|
||
|
||
var data []*user.Moment
|
||
query = db.Model(&model.Moment{}).Where("user_id = ?", req.UserID)
|
||
if len(friends) > 0 {
|
||
query = query.Or("user_id IN (?) AND visibility != ?", friends, model.VisibilitySelfOnly)
|
||
}
|
||
err = query.Limit(int(req.PageSize)).Offset(int(req.PageSize * (req.Page - 1))).Find(&moments).Error
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
for k, v := range moments {
|
||
images, err := GetMomentsImage(v.ID)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
data = append(data, &user.Moment{
|
||
ID: int64(v.ID),
|
||
UserID: v.UserID,
|
||
User: userInfo[k],
|
||
Content: v.Content,
|
||
Location: v.Location,
|
||
Status: user.ContentStatus(int64(v.Status)),
|
||
LikeCount: int32(v.LikeCount),
|
||
CommentCount: int32(v.CommentCount),
|
||
Images: images,
|
||
CreatedAt: v.CreatedAt.Format("2006-01-02 15:04"),
|
||
})
|
||
}
|
||
return data, int32(total), nil
|
||
}
|
||
|
||
// GetMomentsAppoint 获取指定好友动态
|
||
func GetMomentsAppoint(req user.ListMomentsAppointRequest) ([]*user.Moment, int32, error) {
|
||
db := DB
|
||
// 校验分页参数
|
||
if req.Page < 1 {
|
||
req.Page = 1
|
||
}
|
||
if req.PageSize < 1 {
|
||
req.PageSize = 10
|
||
}
|
||
|
||
// 查询总数
|
||
var total int64
|
||
query := db.Model(&model.Moment{}).Where("user_id = ?", req.UserID)
|
||
if err := query.Count(&total).Error; err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
//获取朋友圈内容信息
|
||
var moments []model.Moment
|
||
query = db.Model(&model.Moment{}).Where("user_id = ?", req.UserID)
|
||
err := query.Limit(int(req.PageSize)).Offset(int(req.PageSize * (req.Page - 1))).Find(&moments).Error
|
||
if err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
//查询用户信息
|
||
userInfo, err := GetUsersById(req.UserID) // 自定义批量查询函数
|
||
if err != nil || len(userInfo) != 1 {
|
||
hlog.Errorf("批量查询用户失败: %v", err)
|
||
return nil, 0, err
|
||
}
|
||
|
||
var data []*user.Moment
|
||
query = db.Model(&model.Moment{}).Where("user_id = ?", req.UserID).Limit(int(req.PageSize)).Offset(int(req.PageSize * (req.Page - 1))).Find(&moments)
|
||
if db.Error != nil {
|
||
return nil, 0, err
|
||
}
|
||
for _, v := range moments {
|
||
images, err := GetMomentsImage(v.ID)
|
||
if err != nil {
|
||
continue
|
||
}
|
||
data = append(data, &user.Moment{
|
||
ID: int64(v.ID),
|
||
UserID: v.UserID,
|
||
User: userInfo[0],
|
||
Content: v.Content,
|
||
Location: v.Location,
|
||
Status: user.ContentStatus(int64(v.Status)),
|
||
LikeCount: int32(v.LikeCount),
|
||
CommentCount: int32(v.CommentCount),
|
||
Images: images,
|
||
CreatedAt: v.CreatedAt.Format("2006-01-02 15:04"),
|
||
})
|
||
}
|
||
return data, int32(total), nil
|
||
}
|
||
|
||
// DeleteMoment 删除朋友圈动态
|
||
func DeleteMoment(req user.DeleteMomentRequest) error {
|
||
db := DB
|
||
// 使用事务确保数据一致性
|
||
return db.Transaction(func(tx *gorm.DB) error {
|
||
// 保存动态
|
||
if err := tx.Model(&model.Moment{}).Where("id = ?", req.MomentID).Delete(&model.Moment{}).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
// 删除图片
|
||
if err := tx.Model(model.MomentImage{}).Where("moment_id = ?", req.MomentID).Delete(&model.MomentImage{}).Error; err != nil {
|
||
return err
|
||
}
|
||
|
||
//删除评论
|
||
//TODO
|
||
|
||
//删除点赞
|
||
//TODO
|
||
|
||
return nil
|
||
})
|
||
|
||
}
|
||
|
||
// LikeMoment 点赞朋友圈动态
|
||
func LikeMoment(req user.LikeMomentRequest) error {
|
||
db := DB
|
||
// 使用事务确保数据一致性
|
||
return db.Transaction(func(tx *gorm.DB) error {
|
||
// 检查是否已经点赞
|
||
var existingLike model.MomentLike
|
||
err := tx.Model(&model.MomentLike{}).
|
||
Where("user_id = ? AND moment_id = ?", req.UserID, req.MomentID).
|
||
First(&existingLike).Error
|
||
|
||
// 如果不是"未找到"错误,说明查询异常
|
||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return fmt.Errorf("检查点赞记录失败: %w", err)
|
||
}
|
||
|
||
// 如果已经点赞,返回错误
|
||
if err == nil {
|
||
return errors.New("已经点赞过该动态")
|
||
}
|
||
|
||
// 新增点赞记录
|
||
if err := tx.Model(&model.MomentLike{}).Create(&model.MomentLike{
|
||
UserID: req.UserID,
|
||
MomentID: uint(req.MomentID),
|
||
}).Error; err != nil {
|
||
return fmt.Errorf("创建点赞记录失败: %w", err)
|
||
}
|
||
|
||
// 点赞数原子增加1,避免并发问题
|
||
result := tx.Model(model.Moment{}).
|
||
Where("moment_id = ?", req.MomentID).
|
||
Update("like_count", gorm.Expr("like_count + 1"))
|
||
|
||
if result.Error != nil {
|
||
return fmt.Errorf("更新点赞数失败: %w", result.Error)
|
||
}
|
||
|
||
// 检查动态是否存在
|
||
if result.RowsAffected == 0 {
|
||
return errors.New("动态不存在")
|
||
}
|
||
|
||
return nil
|
||
})
|
||
}
|
||
|
||
// UnlikeMoment 取消点赞朋友圈动态
|
||
func UnlikeMoment(req user.UnlikeMomentRequest) error {
|
||
db := DB
|
||
// 使用事务确保数据一致性
|
||
return db.Transaction(func(tx *gorm.DB) error {
|
||
// 检查是否存在点赞记录
|
||
var like model.MomentLike
|
||
err := tx.Model(&model.MomentLike{}).
|
||
Where("user_id = ? AND moment_id = ?", req.UserID, req.MomentID).
|
||
First(&like).Error
|
||
|
||
// 如果不是"未找到"错误,说明查询异常
|
||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return fmt.Errorf("检查点赞记录失败: %w", err)
|
||
}
|
||
|
||
// 如果没有点赞记录,返回错误
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return errors.New("未点赞该动态,无法取消")
|
||
}
|
||
|
||
// 删除点赞记录
|
||
if err := tx.Model(&model.MomentLike{}).
|
||
Where("user_id = ? AND moment_id = ?", req.UserID, req.MomentID).
|
||
Delete(&model.MomentLike{}).Error; err != nil {
|
||
return fmt.Errorf("删除点赞记录失败: %w", err)
|
||
}
|
||
|
||
// 点赞数原子减少1
|
||
result := tx.Model(model.Moment{}).
|
||
Where("moment_id = ? AND like_count > 0", req.MomentID). // 确保点赞数不会小于0
|
||
Update("like_count", gorm.Expr("like_count - 1"))
|
||
|
||
if result.Error != nil {
|
||
return fmt.Errorf("更新点赞数失败: %w", result.Error)
|
||
}
|
||
|
||
// 检查动态是否存在
|
||
if result.RowsAffected == 0 {
|
||
return errors.New("动态不存在或点赞数已为0")
|
||
}
|
||
|
||
return nil
|
||
})
|
||
}
|