feat: 实现域能系统

- 新增域能完整分层:EnergyLog/PostEnergizeLog/DailyExpSummary 模型、EnergyRepo、EnergyService、EnergyController/AdminEnergyController
- 支持签到获取域能(+1)、帖子赋能(-1/-2)/被赋能(+1/+2)、改名扣能(-6)/退款(+6)、删帖扣能(-2)
- 赋能单人单帖上限20域能,每日赋能获得经验上限50
- 管理员支持批量调整域能(owner)和查询域能日志(admin)
- LV0用户(exp<1)禁止签到和发帖,余额为负可签到/被赋能/删帖但不能赋能/改名
- 首次改名免费(通过HasCompletedTask判重),改名扣能在提交审核时执行
- 移除导航栏手动签到按钮,签到融入域能系统(自动签到)
- 新增个人中心域能TAB展示余额和流水日志(近7天)
- 新增帖子详情页赋能按钮(轻赋/重赋)
- 管理后台新增域能管理和域能日志页面
This commit is contained in:
2026-06-01 03:32:50 +08:00
parent 394989b281
commit e1d7c318ab
31 changed files with 1234 additions and 88 deletions

View File

@ -12,7 +12,8 @@ import (
// StudioController 创作中心控制器SSR 页面 + API
type StudioController struct {
postService studioUseCase
postService studioUseCase
energySvc energyDeducter
}
// NewStudioController 构造函数
@ -20,6 +21,12 @@ func NewStudioController(ps studioUseCase) *StudioController {
return &StudioController{postService: ps}
}
// WithEnergyService 链式注入域能服务
func (ctrl *StudioController) WithEnergyService(svc energyDeducter) *StudioController {
ctrl.energySvc = svc
return ctrl
}
// ==============================
// SSR 页面方法
// ==============================
@ -250,6 +257,14 @@ func (ctrl *StudioController) Create(c *gin.Context) {
return
}
// LV0 用户不允许投稿
if expVal, exists := c.Get("exp"); exists {
if exp, ok := expVal.(int); ok && exp < 1 {
common.Error(c, http.StatusForbidden, "经验不足Lv1 解锁投稿")
return
}
}
var req model.PostCreateRequest
if err := c.ShouldBindJSON(&req); err != nil {
common.Error(c, http.StatusBadRequest, "标题和正文不能为空")
@ -327,11 +342,18 @@ func (ctrl *StudioController) Delete(c *gin.Context) {
return
}
authorID := post.UserID
if err := ctrl.postService.Delete(uint(id)); err != nil {
common.Error(c, http.StatusInternalServerError, "删除失败")
return
}
// 删稿扣作者域能(无视负数,静默失败)
if ctrl.energySvc != nil {
_ = ctrl.energySvc.DeductOnDeletePost(authorID, uint(id))
}
common.OkMessage(c, "删除成功")
}