feat: 赋能溢出截断 + 前端按已赋能量禁用按钮

- 单篇赋能上限由硬拒绝改为溢出截断,类似每日经验处理
- 前端弹窗时查询文章已赋能总量,>=10 禁用重赋,>=20 全部禁用
- GetEnergyInfo 支持 ?post_id= 返回 post_energize_total
- 文案精简为'赋能成功!+N 经验'等短句
This commit is contained in:
2026-06-03 00:13:03 +08:00
parent 4442da31c3
commit 1af9fba291
6 changed files with 90 additions and 30 deletions

View File

@ -9,11 +9,11 @@ import (
)
// Energize 赋能文章
// 返回:获得的经验值、错误
func (s *EnergyService) Energize(energizerID uint, postID uint, amount int) (int, error) {
// 返回:获得的经验值、实际赋能量DB乘10错误
func (s *EnergyService) Energize(energizerID uint, postID uint, amount int) (int, int, error) {
// 验证赋能量
if amount != EnergyEnergize1 && amount != EnergyEnergize2 {
return 0, common.ErrInvalidEnergyAmount
return 0, 0, common.ErrInvalidEnergyAmount
}
var expGained int
@ -21,6 +21,9 @@ func (s *EnergyService) Energize(energizerID uint, postID uint, amount int) (int
var expToday time.Time
var expTotal int
// 实际使用的赋能量(可能因上限被截断)
actualAmount := amount
err := s.repo.Transaction(func(txRepo EnergyStore, txFundRepo FundStore) error {
// 1. 检查帖子存在,获取作者
post, err := txRepo.FindPostByID(postID)
@ -42,14 +45,21 @@ func (s *EnergyService) Energize(energizerID uint, postID uint, amount int) (int
return common.ErrInsufficientEnergy
}
// 4. 检查单用户单文章赋能总量 ≤ MaxEnergizePerPost
// 4. 检查单用户单文章赋能上限,超出部分截断(类似每日经验溢出截断)
total, err := txRepo.SumUserPostEnergy(energizerID, postID)
if err != nil {
return fmt.Errorf("查询赋能记录失败: %w", err)
}
if total+amount > MaxEnergizePerPost {
room := MaxEnergizePerPost - total
if room <= 0 {
return common.ErrEnergizeLimitReached
}
if amount > room {
actualAmount = room // 截断到剩余空间
}
// 重新赋值 amount 用于后续扣域能、写日志等
amount = actualAmount
// 5. 扣赋能者域能
if err := txRepo.AddEnergy(energizerID, -amount); err != nil {
@ -155,14 +165,14 @@ func (s *EnergyService) Energize(energizerID uint, postID uint, amount int) (int
return nil
})
if err != nil {
return 0, err
return 0, 0, err
}
// 12. 事务提交后,在事务外增加经验 + 更新每日汇总
if needExpUpdate {
if s.expSvc != nil {
if _, _, err := s.expSvc.AddExp(energizerID, expGained); err != nil {
return expGained, fmt.Errorf("赋能成功,但增加经验失败: %w", err)
return expGained, actualAmount, fmt.Errorf("赋能成功,但增加经验失败: %w", err)
}
}
newSummary := &model.DailyExpSummary{
@ -171,9 +181,9 @@ func (s *EnergyService) Energize(energizerID uint, postID uint, amount int) (int
ExpEarned: expTotal,
}
if err := s.repo.UpsertDailyExp(newSummary); err != nil {
return expGained, fmt.Errorf("赋能成功,但更新经验汇总失败: %w", err)
return expGained, actualAmount, fmt.Errorf("赋能成功,但更新经验汇总失败: %w", err)
}
}
return expGained, nil
return expGained, actualAmount, nil
}

View File

@ -8,7 +8,8 @@ import (
)
// GetEnergyInfo 获取用户域能余额和每日赋能经验状态
func (s *EnergyService) GetEnergyInfo(userID uint) (*EnergyInfo, error) {
// postID 为 0 时不查文章赋能总量
func (s *EnergyService) GetEnergyInfo(userID uint, postID uint) (*EnergyInfo, error) {
user, err := s.repo.FindUserByID(userID)
if err != nil {
return nil, err
@ -24,12 +25,21 @@ func (s *EnergyService) GetEnergyInfo(userID uint) (*EnergyInfo, error) {
dailyExp = summary.ExpEarned
}
return &EnergyInfo{
info := &EnergyInfo{
Energy: user.Energy,
DailyEnergizeExp: dailyExp,
DailyExpCap: DailyEnergizeExpCap,
DailyExpCapReached: dailyExp >= DailyEnergizeExpCap,
}, nil
}
if postID != 0 {
total, err := s.repo.SumUserPostEnergy(userID, postID)
if err == nil {
info.PostEnergizeTotal = total
}
}
return info, nil
}
// GetEnergyLogs 分页查询用户域能流水(近 N 天)

View File

@ -30,10 +30,11 @@ func (s *EnergyService) SetFundRepo(repo FundStore) {
// EnergyInfo 域能信息(含每日赋能经验状态)
type EnergyInfo struct {
Energy int // 域能余额乘10存储
DailyEnergizeExp int // 当日已通过赋能获得的经验值
DailyExpCap int // 每日赋能经验上限
DailyExpCapReached bool // 是否已达上限
Energy int // 域能余额乘10存储
DailyEnergizeExp int // 当日已通过赋能获得的经验值
DailyExpCap int // 每日赋能经验上限
DailyExpCapReached bool // 是否已达上限
PostEnergizeTotal int // 当前文章已赋能量DB乘10仅在传 postID 时返回)
}
// 域能相关常量乘10存储DB值