Files
mce/internal/repository/energy_repo.go
Victor_Jay 52f4e95414 fix: 修复域能相关数据表缺失及首次查询报错
- AutoMigrate 添加 EnergyLog、PostEnergizeLog、DailyExpSummary 三张表
- GetDailyEnergizeExp 无记录时返回 nil, nil 而非 gorm.ErrRecordNotFound
- 调用方增加 summary nil 检查,防止空指针
2026-06-01 12:40:30 +08:00

150 lines
4.6 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 repository
import (
"errors"
"time"
"metazone.cc/metalab/internal/model"
"metazone.cc/metalab/internal/service"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
// EnergyRepo 域能数据访问
type EnergyRepo struct {
db *gorm.DB
}
// NewEnergyRepo 构造函数
func NewEnergyRepo(db *gorm.DB) *EnergyRepo {
return &EnergyRepo{db: db}
}
// WithTx 基于给定事务连接创建新的 EnergyRepo确保事务内操作原子性
func (r *EnergyRepo) WithTx(tx *gorm.DB) service.EnergyStore {
return &EnergyRepo{db: tx}
}
// FindUserByID 查找用户(获取能量余额等)
func (r *EnergyRepo) FindUserByID(userID uint) (*model.User, error) {
var user model.User
err := r.db.First(&user, userID).Error
if err != nil {
return nil, err
}
return &user, nil
}
// FindPostByID 查找帖子
func (r *EnergyRepo) FindPostByID(postID uint) (*model.Post, error) {
var post model.Post
err := r.db.First(&post, postID).Error
if err != nil {
return nil, err
}
return &post, nil
}
// AddEnergy 原子增减用户域能余额amount 可为正负)
func (r *EnergyRepo) AddEnergy(userID uint, amount int) error {
return r.db.Model(&model.User{}).
Where("uid = ?", userID).
UpdateColumn("energy", gorm.Expr("energy + ?", amount)).Error
}
// IncrPostEnergy 原子增减文章累计被赋能域能
func (r *EnergyRepo) IncrPostEnergy(postID uint, amount int) error {
return r.db.Model(&model.Post{}).
Where("id = ?", postID).
UpdateColumn("total_energy_received", gorm.Expr("total_energy_received + ?", amount)).Error
}
// CreateEnergyLog 创建域能流水
func (r *EnergyRepo) CreateEnergyLog(log *model.EnergyLog) error {
return r.db.Create(log).Error
}
// SumUserPostEnergy 统计某用户对某文章累计赋能总量(用于 ≤ 20 检查)
func (r *EnergyRepo) SumUserPostEnergy(userID, postID uint) (int, error) {
var total int
err := r.db.Model(&model.PostEnergizeLog{}).
Where("user_id = ? AND post_id = ?", userID, postID).
Select("COALESCE(SUM(amount), 0)").
Scan(&total).Error
return total, err
}
// CreateEnergizeLog 创建赋能记录
func (r *EnergyRepo) CreateEnergizeLog(log *model.PostEnergizeLog) error {
return r.db.Create(log).Error
}
// GetDailyEnergizeExp 获取用户当日通过赋能获得的经验值
// 无记录时返回 nil, nil调用方当作 exp=0 处理)
func (r *EnergyRepo) GetDailyEnergizeExp(userID uint, date time.Time) (*model.DailyExpSummary, error) {
var s model.DailyExpSummary
err := r.db.Where("user_id = ? AND date = ?", userID, date).First(&s).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
if err != nil {
return nil, err
}
return &s, nil
}
// UpsertDailyExp 创建或更新每日经验汇总
func (r *EnergyRepo) UpsertDailyExp(summary *model.DailyExpSummary) error {
return r.db.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "user_id"}, {Name: "date"}},
DoUpdates: clause.AssignmentColumns([]string{"exp_earned", "updated_at"}),
}).Create(summary).Error
}
// AddDailyExp 原子增加每日赋能经验值
func (r *EnergyRepo) AddDailyExp(userID uint, date time.Time, delta int) error {
return r.db.Model(&model.DailyExpSummary{}).
Where("user_id = ? AND date = ?", userID, date).
UpdateColumn("exp_earned", gorm.Expr("exp_earned + ?", delta)).Error
}
// ListEnergyLogsByUser 分页查询用户域能流水(近 N 天)
func (r *EnergyRepo) ListEnergyLogsByUser(userID uint, days int, offset, limit int) ([]model.EnergyLog, error) {
var logs []model.EnergyLog
query := r.db.Where("user_id = ?", userID).Order("created_at DESC")
if days > 0 {
since := time.Now().AddDate(0, 0, -days)
query = query.Where("created_at >= ?", since)
}
err := query.Offset(offset).Limit(limit).Find(&logs).Error
return logs, err
}
// CountEnergyLogsByUser 统计用户域能流水总数
func (r *EnergyRepo) CountEnergyLogsByUser(userID uint, days int) (int64, error) {
var count int64
query := r.db.Model(&model.EnergyLog{}).Where("user_id = ?", userID)
if days > 0 {
since := time.Now().AddDate(0, 0, -days)
query = query.Where("created_at >= ?", since)
}
err := query.Count(&count).Error
return count, err
}
// ListAllEnergyLogs 查询全部域能流水(后台,支持筛选)
func (r *EnergyRepo) ListAllEnergyLogs(energyType string, offset, limit int) ([]model.EnergyLog, int64, error) {
query := r.db.Model(&model.EnergyLog{})
if energyType != "" {
query = query.Where("type = ?", energyType)
}
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
var logs []model.EnergyLog
err := query.Order("created_at DESC").Offset(offset).Limit(limit).Find(&logs).Error
return logs, total, err
}