feat: 新增养成管理后台

This commit is contained in:
richjohnrambo
2026-09-19 14:36:30 +08:00
parent 7c8b4d9b7c
commit f6766d3dbd
59 changed files with 3001 additions and 0 deletions
@@ -0,0 +1,149 @@
package sysin
import (
"context"
"strconv"
"strings"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gtime"
"hotgo/internal/model/input/form"
)
type CultivateContentListInp struct {
form.PageReq
ObjectType string `json:"objectType" d:"feed_post"`
AuthorId string `json:"authorId"`
Status string `json:"status"`
Keyword string `json:"keyword"`
CreatedAt []*gtime.Time `json:"createdAt"`
}
func (in *CultivateContentListInp) Filter(context.Context) error {
in.ObjectType = strings.TrimSpace(in.ObjectType)
if in.ObjectType != "feed_post" && in.ObjectType != "feed_comment" {
return gerror.New("内容类型不正确")
}
if in.AuthorId != "" {
if _, err := strconv.ParseUint(in.AuthorId, 10, 64); err != nil {
return gerror.New("作者ID不正确")
}
}
return nil
}
type CultivateContentListModel struct {
Id string `json:"id"`
ObjectType string `json:"objectType"`
PostId string `json:"postId"`
AuthorId string `json:"authorId"`
ContentText string `json:"contentText"`
FlowerCode string `json:"flowerCode"`
Visibility string `json:"visibility"`
Status string `json:"status"`
AuditStatus string `json:"auditStatus"`
RejectReason string `json:"rejectReason"`
LikeCount uint `json:"likeCount"`
CommentCount uint `json:"commentCount"`
CreatedAt *gtime.Time `json:"createdAt"`
UpdatedAt *gtime.Time `json:"updatedAt"`
}
type CultivateContentReviewInp struct {
ObjectType string `json:"objectType" v:"required|in:feed_post,feed_comment#内容类型不能为空|内容类型不正确"`
Id string `json:"id" v:"required#内容ID不能为空"`
Action string `json:"action" v:"required|in:approve,reject,take_down,restore#审核动作不能为空|审核动作不正确"`
Reason string `json:"reason"`
ObjectId uint64 `json:"-"`
}
func (in *CultivateContentReviewInp) Filter(context.Context) error {
id, err := strconv.ParseUint(strings.TrimSpace(in.Id), 10, 64)
if err != nil || id == 0 {
return gerror.New("内容ID不正确")
}
in.ObjectId = id
in.Reason = strings.TrimSpace(in.Reason)
if (in.Action == "reject" || in.Action == "take_down") && in.Reason == "" {
return gerror.New("拒绝或下架时必须填写原因")
}
return nil
}
type CultivateReportListInp struct {
form.PageReq
ObjectType string `json:"objectType"`
Status string `json:"status"`
ReporterId string `json:"reporterId"`
CreatedAt []*gtime.Time `json:"createdAt"`
}
func (in *CultivateReportListInp) Filter(context.Context) error {
if in.ReporterId != "" {
if _, err := strconv.ParseUint(in.ReporterId, 10, 64); err != nil {
return gerror.New("举报人ID不正确")
}
}
return nil
}
type CultivateReportListModel struct {
Id string `json:"id"`
ReporterId string `json:"reporterId"`
ReportedUserId string `json:"reportedUserId"`
ObjectType string `json:"objectType"`
ObjectId string `json:"objectId"`
ReasonCode string `json:"reasonCode"`
Description string `json:"description"`
EvidenceFileIds any `json:"evidenceFileIds"`
SourcePage string `json:"sourcePage"`
Status string `json:"status"`
HandlerId string `json:"handlerId"`
HandleResult string `json:"handleResult"`
HandledAt *gtime.Time `json:"handledAt"`
CreatedAt *gtime.Time `json:"createdAt"`
}
type CultivateReportHandleInp struct {
Id string `json:"id" v:"required#举报ID不能为空"`
Action string `json:"action" v:"required|in:processing,resolve,reject#处理动作不能为空|处理动作不正确"`
HandleResult string `json:"handleResult"`
ReportId uint64 `json:"-"`
}
func (in *CultivateReportHandleInp) Filter(context.Context) error {
id, err := strconv.ParseUint(strings.TrimSpace(in.Id), 10, 64)
if err != nil || id == 0 {
return gerror.New("举报ID不正确")
}
in.ReportId = id
in.HandleResult = strings.TrimSpace(in.HandleResult)
if in.Action != "processing" && in.HandleResult == "" {
return gerror.New("办结举报时必须填写处理结果")
}
return nil
}
type CultivateOperationLogListInp struct {
form.PageReq
OperatorId string `json:"operatorId"`
OperationType string `json:"operationType"`
TargetType string `json:"targetType"`
CreatedAt []*gtime.Time `json:"createdAt"`
}
func (*CultivateOperationLogListInp) Filter(context.Context) error { return nil }
type CultivateOperationLogListModel struct {
Id string `json:"id"`
OperatorId string `json:"operatorId"`
OperationType string `json:"operationType"`
TargetType string `json:"targetType"`
TargetId string `json:"targetId"`
RequestId string `json:"requestId"`
BeforeSnapshot any `json:"beforeSnapshot"`
AfterSnapshot any `json:"afterSnapshot"`
Reason string `json:"reason"`
CreatedAt *gtime.Time `json:"createdAt"`
}
@@ -0,0 +1,155 @@
package sysin
import (
"context"
"strings"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gtime"
"hotgo/internal/model/input/form"
)
type CultivateStageRuleEditInp struct {
Id uint64 `json:"id"`
Stage string `json:"stage"`
NextStage string `json:"nextStage"`
RequiredPoints uint `json:"requiredPoints"`
WaterPoints uint `json:"waterPoints"`
FertilizePoints uint `json:"fertilizePoints"`
AllowedActions []string `json:"allowedActions"`
ImageFileId string `json:"imageFileId"`
AnimationFileId string `json:"animationFileId"`
ProgressTextTemplate string `json:"progressTextTemplate"`
CompletionText string `json:"completionText"`
SortNo int `json:"sortNo"`
}
type CultivateFlowerEditInp struct {
Id uint64 `json:"id"`
FlowerCode string `json:"flowerCode"`
FlowerName string `json:"flowerName"`
FlowerDesc string `json:"flowerDesc"`
IconFileId string `json:"iconFileId"`
Status string `json:"status"`
DailyWaterLimit uint `json:"dailyWaterLimit"`
DailyFertilizeLimit uint `json:"dailyFertilizeLimit"`
ShareConfig *gjson.Json `json:"shareConfig"`
SortNo int `json:"sortNo"`
StageRules []*CultivateStageRuleEditInp `json:"stageRules"`
}
func (in *CultivateFlowerEditInp) Filter(ctx context.Context) error {
in.FlowerCode = strings.TrimSpace(in.FlowerCode)
in.FlowerName = strings.TrimSpace(in.FlowerName)
if in.FlowerCode == "" || in.FlowerName == "" {
return gerror.New("花种编码和名称不能为空")
}
validStatus := map[string]bool{"online": true, "offline": true, "activity_only": true, "maintenance": true}
if !validStatus[in.Status] {
return gerror.New("花种状态不正确")
}
if len(in.StageRules) == 0 {
return gerror.New("至少配置一个成长阶段")
}
validStage := map[string]bool{"seed": true, "sprout": true, "bud": true, "bloom": true}
validAction := map[string]bool{"water": true, "fertilize": true}
seen := map[string]bool{}
for _, rule := range in.StageRules {
if rule == nil || !validStage[rule.Stage] {
return gerror.New("成长阶段不正确")
}
if seen[rule.Stage] {
return gerror.New("成长阶段不能重复")
}
seen[rule.Stage] = true
if rule.Stage != "bloom" && rule.RequiredPoints == 0 {
return gerror.New("非开花阶段升级阈值必须大于0")
}
if rule.NextStage != "" && !validStage[rule.NextStage] {
return gerror.New("下一阶段不正确")
}
if rule.Stage != "bloom" && len(rule.AllowedActions) == 0 {
return gerror.New("非开花阶段至少允许一种成长动作")
}
for _, action := range rule.AllowedActions {
if !validAction[action] {
return gerror.New("成长动作不正确")
}
}
}
stage := "seed"
visited := map[string]bool{}
for stage != "" {
if visited[stage] {
return gerror.New("成长阶段链不能形成循环")
}
visited[stage] = true
var next string
found := false
for _, r := range in.StageRules {
if r.Stage == stage {
next = r.NextStage
found = true
break
}
}
if !found {
return gerror.New("成长阶段链必须从 seed 连续配置")
}
stage = next
}
if !visited["bloom"] {
return gerror.New("成长阶段链必须以 bloom 结束")
}
return nil
}
type CultivateFlowerListInp struct {
form.PageReq
FlowerCode string `json:"flowerCode"`
FlowerName string `json:"flowerName"`
Status string `json:"status"`
ConfigVersion string `json:"configVersion"`
CreatedAt []*gtime.Time `json:"createdAt"`
}
func (*CultivateFlowerListInp) Filter(context.Context) error { return nil }
type CultivateFlowerListModel struct {
Id uint64 `json:"id"`
FlowerCode string `json:"flowerCode"`
FlowerName string `json:"flowerName"`
FlowerDesc string `json:"flowerDesc"`
IconFileId string `json:"iconFileId"`
Status string `json:"status"`
ConfigVersion string `json:"configVersion"`
DailyWaterLimit uint `json:"dailyWaterLimit"`
DailyFertilizeLimit uint `json:"dailyFertilizeLimit"`
SortNo int `json:"sortNo"`
StageCount int `json:"stageCount"`
CreatedAt *gtime.Time `json:"createdAt"`
UpdatedAt *gtime.Time `json:"updatedAt"`
}
type CultivateFlowerViewInp struct {
Id uint64 `json:"id" v:"required#ID不能为空"`
}
func (*CultivateFlowerViewInp) Filter(context.Context) error { return nil }
type CultivateFlowerViewModel struct {
CultivateFlowerEditInp
ConfigVersion string `json:"configVersion"`
CreatedAt *gtime.Time `json:"createdAt"`
UpdatedAt *gtime.Time `json:"updatedAt"`
}
type CultivateFlowerStatusInp struct {
Id uint64 `json:"id" v:"required#ID不能为空"`
Status string `json:"status" v:"required|in:online,offline,activity_only,maintenance#状态不能为空|状态不正确"`
Reason string `json:"reason"`
}
func (*CultivateFlowerStatusInp) Filter(context.Context) error { return nil }