This repository has been archived on 2026-06-21. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MetaLab/internal/repository/energy_repo.go
Victor_Jay 5911cee01c refactor: BaseModel 主键列名统一 uid→id
- BaseModel 移除 gorm column:uid 和 json:uid 标签,统一为 id
- 更新 8 个 repository 文件中 28 处 raw SQL 列引用 (uid→id)
- 更新 3 个前端 JS 文件中 14 处 API 响应字段引用 (uid→id)
- 添加数据库迁移 SQL 脚本 (docs/migrations/001_uid_to_id.sql)
2026-06-02 19:17:57 +08:00

183 lines
6.0 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 (
"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
fundStore service.FundStore // 用于 Transaction 时创建事务范围的 FundStore
}
// NewEnergyRepo 构造函数
func NewEnergyRepo(db *gorm.DB) *EnergyRepo {
return &EnergyRepo{db: db}
}
// SetFundStore 设置公户仓储引用(用于跨仓库事务)
func (r *EnergyRepo) SetFundStore(s service.FundStore) {
r.fundStore = s
}
// WithTx 基于给定事务连接创建新的 EnergyRepo确保事务内操作原子性
func (r *EnergyRepo) WithTx(tx *gorm.DB) service.EnergyStore {
return &EnergyRepo{db: tx}
}
// Transaction 在事务内执行业务逻辑,自动管理 EnergyStore 和 FundStore 的事务范围
func (r *EnergyRepo) Transaction(fn func(txEnergy service.EnergyStore, txFund service.FundStore) error) error {
return r.db.Transaction(func(tx *gorm.DB) error {
txEnergy := r.WithTx(tx)
var txFund service.FundStore
if r.fundStore != nil {
txFund = r.fundStore.WithTx(tx)
}
return fn(txEnergy, txFund)
})
}
// 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("id = ?", 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 summaries []model.DailyExpSummary
err := r.db.Where("user_id = ? AND date = ?", userID, date).Limit(1).Find(&summaries).Error
if err != nil {
return nil, err
}
if len(summaries) == 0 {
return nil, nil
}
return &summaries[0], 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
}
// AggregateEnergyByAuthor 按日期聚合赋能值(作者所有文章在时间段内的赋能记录)
func (r *EnergyRepo) AggregateEnergyByAuthor(userID uint, since string) ([]service.TrendPoint, error) {
var results []service.TrendPoint
err := r.db.Table("post_energize_logs").
Select("TO_CHAR(post_energize_logs.created_at, 'YYYY-MM-DD') AS date, COALESCE(SUM(post_energize_logs.amount), 0) AS value").
Joins("JOIN posts ON posts.id = post_energize_logs.post_id").
Where("posts.user_id = ? AND post_energize_logs.created_at >= ?", userID, since).
Group("TO_CHAR(post_energize_logs.created_at, 'YYYY-MM-DD')").
Order("date ASC").
Scan(&results).Error
if results == nil {
results = []service.TrendPoint{}
}
return results, err
}