feat: 赋能溢出截断 + 前端按已赋能量禁用按钮
- 单篇赋能上限由硬拒绝改为溢出截断,类似每日经验处理 - 前端弹窗时查询文章已赋能总量,>=10 禁用重赋,>=20 全部禁用 - GetEnergyInfo 支持 ?post_id= 返回 post_energize_total - 文案精简为'赋能成功!+N 经验'等短句
This commit is contained in:
@ -37,7 +37,7 @@ func (ec *EnergyController) Energize(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
expGained, err := ec.energySvc.Energize(uid, req.PostID, req.Amount)
|
||||
expGained, actualAmount, err := ec.energySvc.Energize(uid, req.PostID, req.Amount)
|
||||
if err != nil {
|
||||
switch err {
|
||||
case common.ErrPostNotFound:
|
||||
@ -56,21 +56,30 @@ func (ec *EnergyController) Energize(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
truncated := actualAmount != req.Amount
|
||||
common.Ok(c, gin.H{
|
||||
"exp_gained": expGained,
|
||||
"message": buildEnergizeMessage(expGained),
|
||||
"exp_gained": expGained,
|
||||
"actual_amount": actualAmount,
|
||||
"truncated": truncated,
|
||||
"message": buildEnergizeMessage(expGained, truncated),
|
||||
})
|
||||
}
|
||||
|
||||
// buildEnergizeMessage 根据获得的经验生成提示消息
|
||||
func buildEnergizeMessage(expGained int) string {
|
||||
if expGained > 0 {
|
||||
return "赋能成功!" + strconv.Itoa(expGained) + "经验已加入你的旅程。"
|
||||
func buildEnergizeMessage(expGained int, truncated bool) string {
|
||||
if truncated {
|
||||
if expGained > 0 {
|
||||
return "单篇额度已满,实际赋能部分额度,+" + strconv.Itoa(expGained) + " 经验"
|
||||
}
|
||||
return "单篇额度已满,实际赋能部分额度"
|
||||
}
|
||||
return "赋能成功!今日赋能经验奖励已达上限,对方仍会获得激励。"
|
||||
if expGained > 0 {
|
||||
return "赋能成功!+" + strconv.Itoa(expGained) + " 经验"
|
||||
}
|
||||
return "赋能成功!今日经验已满,对方仍获得激励"
|
||||
}
|
||||
|
||||
// GetEnergyInfo 获取域能余额和经验上限状态
|
||||
// GetEnergyInfo 获取域能余额和经验上限状态,支持 ?post_id= 查询文章赋能总量
|
||||
func (ec *EnergyController) GetEnergyInfo(c *gin.Context) {
|
||||
uid, _, ok := common.GetGinUser(c)
|
||||
if !ok {
|
||||
@ -78,7 +87,10 @@ func (ec *EnergyController) GetEnergyInfo(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
info, err := ec.energySvc.GetEnergyInfo(uid)
|
||||
postIDStr := c.DefaultQuery("post_id", "0")
|
||||
postID, _ := strconv.ParseUint(postIDStr, 10, 64)
|
||||
|
||||
info, err := ec.energySvc.GetEnergyInfo(uid, uint(postID))
|
||||
if err != nil {
|
||||
common.Error(c, http.StatusInternalServerError, "获取域能信息失败")
|
||||
return
|
||||
|
||||
@ -85,8 +85,8 @@ type levelUseCase interface {
|
||||
|
||||
// energyUseCase EnergyController 对 EnergyService 的最小依赖(ISP:3 个方法)
|
||||
type energyUseCase interface {
|
||||
Energize(energizerID uint, postID uint, amount int) (int, error)
|
||||
GetEnergyInfo(userID uint) (*service.EnergyInfo, error)
|
||||
Energize(energizerID uint, postID uint, amount int) (int, int, error)
|
||||
GetEnergyInfo(userID uint, postID uint) (*service.EnergyInfo, error)
|
||||
GetEnergyLogs(userID uint, days, page, pageSize int) ([]model.EnergyLog, int64, error)
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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 天)
|
||||
|
||||
@ -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值)
|
||||
|
||||
Reference in New Issue
Block a user