feat: integrate cultivate admin internal APIs
This commit is contained in:
@@ -3,24 +3,20 @@ package sys
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/imadmin"
|
||||
"hotgo/internal/library/imtenant"
|
||||
"hotgo/internal/library/location"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/library/cultivateadmin"
|
||||
"hotgo/internal/model/input/form"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
)
|
||||
@@ -30,6 +26,39 @@ type sSysCultivateFlower struct{}
|
||||
func NewSysCultivateFlower() *sSysCultivateFlower { return &sSysCultivateFlower{} }
|
||||
func init() { service.RegisterSysCultivateFlower(NewSysCultivateFlower()) }
|
||||
|
||||
type cultivateFlowerDTO struct {
|
||||
ID string `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"`
|
||||
ShareConfig any `json:"shareConfig"`
|
||||
SortNo int `json:"sortNo"`
|
||||
StageCount int `json:"stageCount"`
|
||||
StageRules []*cultivateStageRuleDTO `json:"stageRules"`
|
||||
CreatedAt *gtime.Time `json:"createdAt"`
|
||||
UpdatedAt *gtime.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
type cultivateStageRuleDTO struct {
|
||||
ID string `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"`
|
||||
}
|
||||
|
||||
func cultivateTenantID(ctx context.Context) int64 {
|
||||
id := contexts.GetTenantId(ctx)
|
||||
if id <= 0 {
|
||||
@@ -38,222 +67,212 @@ func cultivateTenantID(ctx context.Context) int64 {
|
||||
return id
|
||||
}
|
||||
|
||||
func (s *sSysCultivateFlower) List(ctx context.Context, in *sysin.CultivateFlowerListInp) (list []*sysin.CultivateFlowerListModel, totalCount int, err error) {
|
||||
c := dao.FlowerCatalog.Columns()
|
||||
mod := dao.FlowerCatalog.Ctx(ctx).Fields("cv_flower_catalog.*, COUNT(cv_flower_stage_rule.id) AS stage_count").LeftJoin(dao.FlowerStageRule.Table(), "cv_flower_stage_rule.flower_catalog_id=cv_flower_catalog.id AND cv_flower_stage_rule.tenant_id=cv_flower_catalog.tenant_id").Where("cv_flower_catalog."+c.TenantId, cultivateTenantID(ctx)).Group("cv_flower_catalog." + c.Id)
|
||||
if in.FlowerCode != "" {
|
||||
mod = mod.WhereLike("cv_flower_catalog."+c.FlowerCode, "%"+strings.TrimSpace(in.FlowerCode)+"%")
|
||||
}
|
||||
if in.FlowerName != "" {
|
||||
mod = mod.WhereLike("cv_flower_catalog."+c.FlowerName, "%"+strings.TrimSpace(in.FlowerName)+"%")
|
||||
}
|
||||
if in.Status != "" {
|
||||
mod = mod.Where("cv_flower_catalog."+c.Status, in.Status)
|
||||
}
|
||||
if in.ConfigVersion != "" {
|
||||
mod = mod.Where("cv_flower_catalog."+c.ConfigVersion, in.ConfigVersion)
|
||||
}
|
||||
if len(in.CreatedAt) == 2 {
|
||||
mod = mod.WhereBetween("cv_flower_catalog."+c.CreatedAt, in.CreatedAt[0], in.CreatedAt[1])
|
||||
}
|
||||
mod = mod.Page(in.Page, in.PerPage).OrderAsc("cv_flower_catalog." + c.SortNo).OrderDesc("cv_flower_catalog." + c.Id)
|
||||
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
|
||||
err = gerror.Wrap(err, "获取花种列表失败")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sSysCultivateFlower) View(ctx context.Context, in *sysin.CultivateFlowerViewInp) (res *sysin.CultivateFlowerViewModel, err error) {
|
||||
c := dao.FlowerCatalog.Columns()
|
||||
var catalog entity.FlowerCatalog
|
||||
if err = dao.FlowerCatalog.Ctx(ctx).Where(g.Map{c.Id: in.Id, c.TenantId: cultivateTenantID(ctx)}).Scan(&catalog); err != nil {
|
||||
return
|
||||
}
|
||||
if catalog.Id == 0 {
|
||||
return nil, gerror.New("花种不存在")
|
||||
}
|
||||
res = &sysin.CultivateFlowerViewModel{CultivateFlowerEditInp: sysin.CultivateFlowerEditInp{Id: catalog.Id, FlowerCode: catalog.FlowerCode, FlowerName: catalog.FlowerName, FlowerDesc: catalog.FlowerDesc, IconFileId: catalog.IconFileId, Status: catalog.Status, DailyWaterLimit: catalog.DailyWaterLimit, DailyFertilizeLimit: catalog.DailyFertilizeLimit, ShareConfig: catalog.ShareConfig, SortNo: catalog.SortNo}, ConfigVersion: catalog.ConfigVersion, CreatedAt: catalog.CreatedAt, UpdatedAt: catalog.UpdatedAt}
|
||||
rc := dao.FlowerStageRule.Columns()
|
||||
var rules []*entity.FlowerStageRule
|
||||
if err = dao.FlowerStageRule.Ctx(ctx).Where(g.Map{rc.TenantId: cultivateTenantID(ctx), rc.FlowerCatalogId: catalog.Id}).OrderAsc(rc.SortNo).OrderAsc(rc.Id).Scan(&rules); err != nil {
|
||||
return
|
||||
}
|
||||
for _, rule := range rules {
|
||||
actions := []string{}
|
||||
if rule.AllowedActions != nil {
|
||||
_ = json.Unmarshal(rule.AllowedActions.MustToJson(), &actions)
|
||||
}
|
||||
res.StageRules = append(res.StageRules, &sysin.CultivateStageRuleEditInp{Id: rule.Id, Stage: rule.Stage, NextStage: rule.NextStage, RequiredPoints: rule.RequiredPoints, WaterPoints: rule.WaterPoints, FertilizePoints: rule.FertilizePoints, AllowedActions: actions, ImageFileId: rule.ImageFileId, AnimationFileId: rule.AnimationFileId, ProgressTextTemplate: rule.ProgressTextTemplate, CompletionText: rule.CompletionText, SortNo: rule.SortNo})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sSysCultivateFlower) Edit(ctx context.Context, in *sysin.CultivateFlowerEditInp) (err error) {
|
||||
if err = in.Filter(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
tenantID := cultivateTenantID(ctx)
|
||||
if err = validateCultivateAssets(ctx, tenantID, in); err != nil {
|
||||
return err
|
||||
func cultivateAdminScope(ctx context.Context) (cultivateadmin.Scope, error) {
|
||||
tenant, err := resolveImAdminTenant(ctx, cultivateTenantID(ctx))
|
||||
if err != nil {
|
||||
return cultivateadmin.Scope{}, err
|
||||
}
|
||||
operatorID := contexts.GetUserId(ctx)
|
||||
now := time.Now().UTC()
|
||||
version := "cat_" + now.Format("20060102_150405")
|
||||
return dao.FlowerCatalog.Transaction(ctx, func(txCtx context.Context, tx gdb.TX) error {
|
||||
c := dao.FlowerCatalog.Columns()
|
||||
var before entity.FlowerCatalog
|
||||
if in.Id > 0 {
|
||||
if e := tx.Model(dao.FlowerCatalog.Table()).Where(g.Map{c.Id: in.Id, c.TenantId: tenantID}).LockUpdate().Scan(&before); e != nil {
|
||||
return e
|
||||
}
|
||||
if before.Id == 0 {
|
||||
return gerror.New("花种不存在")
|
||||
}
|
||||
if before.FlowerCode != in.FlowerCode {
|
||||
return gerror.New("花种编码创建后不可修改")
|
||||
}
|
||||
}
|
||||
shareJSON := "{}"
|
||||
if in.ShareConfig != nil {
|
||||
shareJSON = in.ShareConfig.MustToJsonString()
|
||||
}
|
||||
data := g.Map{c.FlowerName: in.FlowerName, c.FlowerDesc: in.FlowerDesc, c.IconFileId: in.IconFileId, c.Status: in.Status, c.ConfigVersion: version, c.DailyWaterLimit: in.DailyWaterLimit, c.DailyFertilizeLimit: in.DailyFertilizeLimit, c.ShareConfig: shareJSON, c.SortNo: in.SortNo, c.UpdatedAt: now}
|
||||
if in.Status == "online" {
|
||||
data[c.OnlineAt] = now
|
||||
data[c.OfflineAt] = nil
|
||||
} else if in.Status == "offline" {
|
||||
data[c.OfflineAt] = now
|
||||
}
|
||||
if in.Id == 0 {
|
||||
id, e := imtenant.NextSnowflakeID(txCtx)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
in.Id = uint64(id)
|
||||
data[c.Id] = id
|
||||
data[c.TenantId] = tenantID
|
||||
data[c.FlowerCode] = in.FlowerCode
|
||||
data[c.CreatedAt] = now
|
||||
if _, e = tx.Model(dao.FlowerCatalog.Table()).Data(data).Insert(); e != nil {
|
||||
return gerror.Wrap(e, "新增花种失败")
|
||||
}
|
||||
} else {
|
||||
if _, e := tx.Model(dao.FlowerCatalog.Table()).Where(g.Map{c.Id: in.Id, c.TenantId: tenantID}).Data(data).Update(); e != nil {
|
||||
return gerror.Wrap(e, "修改花种失败")
|
||||
}
|
||||
}
|
||||
rc := dao.FlowerStageRule.Columns()
|
||||
if _, e := tx.Model(dao.FlowerStageRule.Table()).Where(g.Map{rc.TenantId: tenantID, rc.FlowerCatalogId: in.Id}).Delete(); e != nil {
|
||||
return e
|
||||
}
|
||||
for _, rule := range in.StageRules {
|
||||
id, e := imtenant.NextSnowflakeID(txCtx)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
actions, _ := json.Marshal(rule.AllowedActions)
|
||||
_, e = tx.Model(dao.FlowerStageRule.Table()).Data(g.Map{rc.Id: id, rc.TenantId: tenantID, rc.FlowerCatalogId: in.Id, rc.Stage: rule.Stage, rc.NextStage: rule.NextStage, rc.RequiredPoints: rule.RequiredPoints, rc.WaterPoints: rule.WaterPoints, rc.FertilizePoints: rule.FertilizePoints, rc.AllowedActions: string(actions), rc.ImageFileId: rule.ImageFileId, rc.AnimationFileId: rule.AnimationFileId, rc.ProgressTextTemplate: rule.ProgressTextTemplate, rc.CompletionText: rule.CompletionText, rc.SortNo: rule.SortNo, rc.CreatedAt: now, rc.UpdatedAt: now}).Insert()
|
||||
if e != nil {
|
||||
return gerror.Wrap(e, "保存成长阶段失败")
|
||||
}
|
||||
}
|
||||
return writeCultivateOperation(txCtx, tx, tenantID, operatorID, map[bool]string{true: "flower.edit", false: "flower.create"}[before.Id > 0], "flower", fmt.Sprint(in.Id), before, in, "", now)
|
||||
})
|
||||
if operatorID <= 0 {
|
||||
return cultivateadmin.Scope{}, gerror.New("当前管理员身份无效")
|
||||
}
|
||||
return cultivateadmin.Scope{
|
||||
TenantID: tenant.Id, TenantCode: tenant.Code, OperatorID: operatorID,
|
||||
RoleKey: contexts.GetRoleKey(ctx), RequestID: gctx.CtxId(ctx),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func validateCultivateAssets(ctx context.Context, tenantID int64, in *sysin.CultivateFlowerEditInp) error {
|
||||
seen := make(map[string]struct{})
|
||||
fileIDs := make([]string, 0, 1+len(in.StageRules)*2)
|
||||
add := func(fileID string) {
|
||||
fileID = strings.TrimSpace(fileID)
|
||||
if fileID == "" {
|
||||
return
|
||||
func (s *sSysCultivateFlower) List(ctx context.Context, in *sysin.CultivateFlowerListInp) (list []*sysin.CultivateFlowerListModel, totalCount int, err error) {
|
||||
if err = in.Filter(ctx); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
scope, err := cultivateAdminScope(ctx)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
normalizeCultivatePage(&in.PageReq)
|
||||
values := cultivatePageValues(in.Page, in.PerPage)
|
||||
cultivateSetQuery(values, "flower_code", in.FlowerCode)
|
||||
cultivateSetQuery(values, "flower_name", in.FlowerName)
|
||||
cultivateSetQuery(values, "status", in.Status)
|
||||
cultivateSetQuery(values, "config_version", in.ConfigVersion)
|
||||
setTimeRange(values, in.CreatedAt)
|
||||
var page cultivateadmin.Page[cultivateFlowerDTO]
|
||||
if err = cultivateadmin.DefaultClient(ctx).Get(ctx, scope, "/flowers", values, &page); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
list = make([]*sysin.CultivateFlowerListModel, 0, len(page.Items))
|
||||
for index := range page.Items {
|
||||
item, convertErr := flowerListModel(&page.Items[index])
|
||||
if convertErr != nil {
|
||||
return nil, 0, convertErr
|
||||
}
|
||||
if _, ok := seen[fileID]; ok {
|
||||
return
|
||||
}
|
||||
seen[fileID] = struct{}{}
|
||||
fileIDs = append(fileIDs, fileID)
|
||||
list = append(list, item)
|
||||
}
|
||||
add(in.IconFileId)
|
||||
for _, rule := range in.StageRules {
|
||||
add(rule.ImageFileId)
|
||||
add(rule.AnimationFileId)
|
||||
return list, page.Total, nil
|
||||
}
|
||||
|
||||
func (s *sSysCultivateFlower) View(ctx context.Context, in *sysin.CultivateFlowerViewInp) (*sysin.CultivateFlowerViewModel, error) {
|
||||
if err := in.Filter(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(fileIDs) == 0 {
|
||||
return nil
|
||||
scope, err := cultivateAdminScope(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tenant, err := resolveImAdminTenant(ctx, tenantID)
|
||||
var item cultivateFlowerDTO
|
||||
if err = cultivateadmin.DefaultClient(ctx).Get(ctx, scope, "/flowers/"+strconv.FormatUint(in.Id, 10), nil, &item); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return flowerViewModel(&item)
|
||||
}
|
||||
|
||||
func (s *sSysCultivateFlower) Edit(ctx context.Context, in *sysin.CultivateFlowerEditInp) error {
|
||||
if err := in.Filter(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
scope, err := cultivateAdminScope(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path := "/internal/cultivate/tenants/" + url.PathEscape(tenant.Code) + "/files/validate"
|
||||
for offset := 0; offset < len(fileIDs); offset += 20 {
|
||||
end := offset + 20
|
||||
if end > len(fileIDs) {
|
||||
end = len(fileIDs)
|
||||
}
|
||||
var out struct {
|
||||
Items []struct {
|
||||
FileId string `json:"file_id"`
|
||||
ReviewStatus string `json:"review_status"`
|
||||
} `json:"items"`
|
||||
}
|
||||
if err = imadmin.DefaultClient(ctx).InternalPost(ctx, path, map[string]any{"user_id": 0, "file_ids": fileIDs[offset:end]}, &out); err != nil {
|
||||
return gerror.Wrap(err, "校验花种素材失败")
|
||||
}
|
||||
for _, item := range out.Items {
|
||||
if item.ReviewStatus == "risky" {
|
||||
return gerror.Newf("素材 %s 审核未通过", item.FileId)
|
||||
}
|
||||
if item.ReviewStatus == "pending" {
|
||||
return gerror.Newf("素材 %s 尚在审核中", item.FileId)
|
||||
}
|
||||
payload := flowerPayload(in)
|
||||
var response struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
if in.Id == 0 {
|
||||
err = cultivateadmin.DefaultClient(ctx).Post(ctx, scope, "/flowers", payload, &response)
|
||||
} else {
|
||||
err = cultivateadmin.DefaultClient(ctx).Put(ctx, scope, "/flowers/"+strconv.FormatUint(in.Id, 10), payload, &response)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Id == 0 && response.ID != "" {
|
||||
in.Id, err = strconv.ParseUint(response.ID, 10, 64)
|
||||
if err != nil {
|
||||
return gerror.Wrap(err, "解析养成服务花种ID失败")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sSysCultivateFlower) Status(ctx context.Context, in *sysin.CultivateFlowerStatusInp) error {
|
||||
tenantID := cultivateTenantID(ctx)
|
||||
operatorID := contexts.GetUserId(ctx)
|
||||
now := time.Now().UTC()
|
||||
return dao.FlowerCatalog.Transaction(ctx, func(txCtx context.Context, tx gdb.TX) error {
|
||||
c := dao.FlowerCatalog.Columns()
|
||||
var before entity.FlowerCatalog
|
||||
if e := tx.Model(dao.FlowerCatalog.Table()).Where(g.Map{c.Id: in.Id, c.TenantId: tenantID}).LockUpdate().Scan(&before); e != nil {
|
||||
return e
|
||||
}
|
||||
if before.Id == 0 {
|
||||
return gerror.New("花种不存在")
|
||||
}
|
||||
data := g.Map{c.Status: in.Status, c.ConfigVersion: "cat_" + now.Format("20060102_150405"), c.UpdatedAt: now}
|
||||
if in.Status == "online" {
|
||||
data[c.OnlineAt] = now
|
||||
data[c.OfflineAt] = nil
|
||||
} else if in.Status == "offline" {
|
||||
data[c.OfflineAt] = now
|
||||
}
|
||||
if _, e := tx.Model(dao.FlowerCatalog.Table()).Where(c.Id, in.Id).Data(data).Update(); e != nil {
|
||||
return e
|
||||
}
|
||||
return writeCultivateOperation(txCtx, tx, tenantID, operatorID, "flower.status", "flower", fmt.Sprint(in.Id), before, data, in.Reason, now)
|
||||
})
|
||||
if err := in.Filter(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
scope, err := cultivateAdminScope(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return cultivateadmin.DefaultClient(ctx).Post(ctx, scope, "/flowers/"+strconv.FormatUint(in.Id, 10)+"/status", map[string]any{
|
||||
"status": in.Status, "reason": strings.TrimSpace(in.Reason),
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func writeCultivateOperation(ctx context.Context, tx gdb.TX, tenantID, operatorID int64, operation, targetType, targetID string, before, after any, reason string, now time.Time) error {
|
||||
id, e := imtenant.NextSnowflakeID(ctx)
|
||||
if e != nil {
|
||||
return e
|
||||
func flowerPayload(in *sysin.CultivateFlowerEditInp) map[string]any {
|
||||
shareConfig := map[string]any{}
|
||||
if in.ShareConfig != nil {
|
||||
_ = json.Unmarshal([]byte(in.ShareConfig.MustToJsonString()), &shareConfig)
|
||||
}
|
||||
beforeJSON, _ := json.Marshal(before)
|
||||
afterJSON, _ := json.Marshal(after)
|
||||
ipAddress, userAgent := "", ""
|
||||
if request := ghttp.RequestFromCtx(ctx); request != nil {
|
||||
ipAddress = location.GetClientIp(request)
|
||||
userAgent = request.UserAgent()
|
||||
rules := make([]map[string]any, 0, len(in.StageRules))
|
||||
for _, rule := range in.StageRules {
|
||||
if rule == nil {
|
||||
continue
|
||||
}
|
||||
rules = append(rules, map[string]any{
|
||||
"id": strconv.FormatUint(rule.Id, 10), "stage": rule.Stage, "next_stage": rule.NextStage,
|
||||
"required_points": rule.RequiredPoints, "water_points": rule.WaterPoints, "fertilize_points": rule.FertilizePoints,
|
||||
"allowed_actions": rule.AllowedActions, "image_file_id": rule.ImageFileId, "animation_file_id": rule.AnimationFileId,
|
||||
"progress_text_template": rule.ProgressTextTemplate, "completion_text": rule.CompletionText, "sort_no": rule.SortNo,
|
||||
})
|
||||
}
|
||||
return map[string]any{
|
||||
"flower_code": in.FlowerCode, "flower_name": in.FlowerName, "flower_desc": in.FlowerDesc,
|
||||
"icon_file_id": in.IconFileId, "status": in.Status, "daily_water_limit": in.DailyWaterLimit,
|
||||
"daily_fertilize_limit": in.DailyFertilizeLimit, "share_config": shareConfig, "sort_no": in.SortNo, "stage_rules": rules,
|
||||
}
|
||||
}
|
||||
|
||||
func flowerListModel(item *cultivateFlowerDTO) (*sysin.CultivateFlowerListModel, error) {
|
||||
id, err := parseCultivateUint(item.ID, "花种ID")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &sysin.CultivateFlowerListModel{
|
||||
Id: id, FlowerCode: item.FlowerCode, FlowerName: item.FlowerName, FlowerDesc: item.FlowerDesc,
|
||||
IconFileId: item.IconFileID, Status: item.Status, ConfigVersion: item.ConfigVersion,
|
||||
DailyWaterLimit: item.DailyWaterLimit, DailyFertilizeLimit: item.DailyFertilizeLimit,
|
||||
SortNo: item.SortNo, StageCount: item.StageCount, CreatedAt: item.CreatedAt, UpdatedAt: item.UpdatedAt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func flowerViewModel(item *cultivateFlowerDTO) (*sysin.CultivateFlowerViewModel, error) {
|
||||
list, err := flowerListModel(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
shareConfig, _ := json.Marshal(item.ShareConfig)
|
||||
result := &sysin.CultivateFlowerViewModel{
|
||||
CultivateFlowerEditInp: sysin.CultivateFlowerEditInp{
|
||||
Id: list.Id, FlowerCode: list.FlowerCode, FlowerName: list.FlowerName, FlowerDesc: list.FlowerDesc,
|
||||
IconFileId: list.IconFileId, Status: list.Status, DailyWaterLimit: list.DailyWaterLimit,
|
||||
DailyFertilizeLimit: list.DailyFertilizeLimit, ShareConfig: gjson.New(string(shareConfig)), SortNo: list.SortNo,
|
||||
},
|
||||
ConfigVersion: list.ConfigVersion, CreatedAt: list.CreatedAt, UpdatedAt: list.UpdatedAt,
|
||||
}
|
||||
for _, rule := range item.StageRules {
|
||||
id, parseErr := parseCultivateUint(rule.ID, "成长阶段ID")
|
||||
if parseErr != nil {
|
||||
return nil, parseErr
|
||||
}
|
||||
result.StageRules = append(result.StageRules, &sysin.CultivateStageRuleEditInp{
|
||||
Id: id, Stage: rule.Stage, NextStage: rule.NextStage, RequiredPoints: rule.RequiredPoints,
|
||||
WaterPoints: rule.WaterPoints, FertilizePoints: rule.FertilizePoints, AllowedActions: rule.AllowedActions,
|
||||
ImageFileId: rule.ImageFileID, AnimationFileId: rule.AnimationFileID,
|
||||
ProgressTextTemplate: rule.ProgressTextTemplate, CompletionText: rule.CompletionText, SortNo: rule.SortNo,
|
||||
})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func parseCultivateUint(value, field string) (uint64, error) {
|
||||
id, err := strconv.ParseUint(strings.TrimSpace(value), 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
return 0, gerror.Newf("养成服务返回的%s不正确", field)
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func normalizeCultivatePage(page *form.PageReq) {
|
||||
if page.Page <= 0 {
|
||||
page.Page = 1
|
||||
}
|
||||
if page.PerPage <= 0 {
|
||||
page.PerPage = 10
|
||||
}
|
||||
if page.PerPage > 100 {
|
||||
page.PerPage = 100
|
||||
}
|
||||
}
|
||||
|
||||
func cultivatePageValues(page, perPage int) url.Values {
|
||||
return url.Values{"page": []string{strconv.Itoa(page)}, "per_page": []string{strconv.Itoa(perPage)}}
|
||||
}
|
||||
|
||||
func cultivateSetQuery(values url.Values, key, value string) {
|
||||
if value = strings.TrimSpace(value); value != "" {
|
||||
values.Set(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
func setTimeRange(values url.Values, value []*gtime.Time) {
|
||||
if len(value) != 2 {
|
||||
return
|
||||
}
|
||||
if value[0] != nil {
|
||||
values.Set("created_from", value[0].Format(time.RFC3339))
|
||||
}
|
||||
if value[1] != nil {
|
||||
values.Set("created_to", value[1].Format(time.RFC3339))
|
||||
}
|
||||
c := dao.AdminOperationLog.Columns()
|
||||
_, e = tx.Model(dao.AdminOperationLog.Table()).Data(g.Map{c.Id: id, c.TenantId: tenantID, c.OperatorId: operatorID, c.OperationType: operation, c.TargetType: targetType, c.TargetId: targetID, c.RequestId: gctx.CtxId(ctx), c.BeforeSnapshot: gjson.New(beforeJSON).MustToJsonString(), c.AfterSnapshot: gjson.New(afterJSON).MustToJsonString(), c.Reason: reason, c.IpAddress: ipAddress, c.UserAgent: userAgent, c.CreatedAt: now}).Insert()
|
||||
return e
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user