feat: 新增养成管理后台
This commit is contained in:
@@ -0,0 +1,324 @@
|
||||
package sys
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"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"
|
||||
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/imtenant"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
)
|
||||
|
||||
type sSysCultivateContent struct{}
|
||||
|
||||
func NewSysCultivateContent() *sSysCultivateContent { return &sSysCultivateContent{} }
|
||||
func init() { service.RegisterSysCultivateContent(NewSysCultivateContent()) }
|
||||
|
||||
func (s *sSysCultivateContent) List(ctx context.Context, in *sysin.CultivateContentListInp) (list []*sysin.CultivateContentListModel, totalCount int, err error) {
|
||||
tenantID := cultivateTenantID(ctx)
|
||||
if in.ObjectType == "feed_comment" {
|
||||
columns := dao.FeedComment.Columns()
|
||||
mod := dao.FeedComment.Ctx(ctx).Where(columns.TenantId, tenantID)
|
||||
if in.AuthorId != "" {
|
||||
mod = mod.Where(columns.AuthorId, in.AuthorId)
|
||||
}
|
||||
if in.Status != "" {
|
||||
mod = mod.Where(columns.Status, in.Status)
|
||||
}
|
||||
if in.Keyword != "" {
|
||||
mod = mod.WhereLike(columns.ContentText, "%"+strings.TrimSpace(in.Keyword)+"%")
|
||||
}
|
||||
if len(in.CreatedAt) == 2 {
|
||||
mod = mod.WhereBetween(columns.CreatedAt, in.CreatedAt[0], in.CreatedAt[1])
|
||||
}
|
||||
var rows []*entity.FeedComment
|
||||
err = mod.Page(in.Page, in.PerPage).OrderDesc(columns.Id).ScanAndCount(&rows, &totalCount, false)
|
||||
if err != nil {
|
||||
return nil, 0, gerror.Wrap(err, "获取评论审核列表失败")
|
||||
}
|
||||
list = make([]*sysin.CultivateContentListModel, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
list = append(list, &sysin.CultivateContentListModel{Id: strconv.FormatUint(row.Id, 10), ObjectType: "feed_comment", PostId: strconv.FormatUint(row.PostId, 10), AuthorId: strconv.FormatUint(row.AuthorId, 10), ContentText: row.ContentText, Status: row.Status, AuditStatus: row.AuditStatus, CreatedAt: row.CreatedAt, UpdatedAt: row.UpdatedAt})
|
||||
}
|
||||
return
|
||||
}
|
||||
columns := dao.FeedPost.Columns()
|
||||
mod := dao.FeedPost.Ctx(ctx).Where(columns.TenantId, tenantID)
|
||||
if in.AuthorId != "" {
|
||||
mod = mod.Where(columns.AuthorId, in.AuthorId)
|
||||
}
|
||||
if in.Status != "" {
|
||||
mod = mod.Where(columns.Status, in.Status)
|
||||
}
|
||||
if in.Keyword != "" {
|
||||
mod = mod.WhereLike(columns.ContentText, "%"+strings.TrimSpace(in.Keyword)+"%")
|
||||
}
|
||||
if len(in.CreatedAt) == 2 {
|
||||
mod = mod.WhereBetween(columns.CreatedAt, in.CreatedAt[0], in.CreatedAt[1])
|
||||
}
|
||||
var rows []*entity.FeedPost
|
||||
err = mod.Page(in.Page, in.PerPage).OrderDesc(columns.Id).ScanAndCount(&rows, &totalCount, false)
|
||||
if err != nil {
|
||||
return nil, 0, gerror.Wrap(err, "获取动态审核列表失败")
|
||||
}
|
||||
list = make([]*sysin.CultivateContentListModel, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
list = append(list, &sysin.CultivateContentListModel{Id: strconv.FormatUint(row.Id, 10), ObjectType: "feed_post", AuthorId: strconv.FormatUint(row.AuthorId, 10), ContentText: row.ContentText, FlowerCode: row.FlowerCode, Visibility: row.Visibility, Status: row.Status, AuditStatus: row.AuditStatus, RejectReason: row.RejectReasonCode, LikeCount: row.LikeCount, CommentCount: row.CommentCount, CreatedAt: row.CreatedAt, UpdatedAt: row.UpdatedAt})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sSysCultivateContent) Review(ctx context.Context, in *sysin.CultivateContentReviewInp) error {
|
||||
tenantID, operatorID := cultivateTenantID(ctx), contexts.GetUserId(ctx)
|
||||
return dao.FeedPost.Transaction(ctx, func(txCtx context.Context, tx gdb.TX) error {
|
||||
if in.ObjectType == "feed_comment" {
|
||||
return s.reviewComment(txCtx, tx, tenantID, operatorID, in)
|
||||
}
|
||||
return s.reviewPost(txCtx, tx, tenantID, operatorID, in)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *sSysCultivateContent) reviewPost(ctx context.Context, tx gdb.TX, tenantID, operatorID int64, in *sysin.CultivateContentReviewInp) error {
|
||||
columns := dao.FeedPost.Columns()
|
||||
var before entity.FeedPost
|
||||
err := tx.Model(dao.FeedPost.Table()).Where(g.Map{columns.Id: in.ObjectId, columns.TenantId: tenantID}).LockUpdate().Scan(&before)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return err
|
||||
}
|
||||
if before.Id == 0 {
|
||||
return gerror.New("动态不存在")
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
data := g.Map{columns.UpdatedAt: now, columns.Version: gdb.Raw(columns.Version + "+1")}
|
||||
afterStatus := before.Status
|
||||
switch in.Action {
|
||||
case "approve":
|
||||
if before.Status != "reviewing" && before.Status != "rejected" {
|
||||
return gerror.New("仅待审核或已拒绝动态可审核通过")
|
||||
}
|
||||
afterStatus = "published"
|
||||
data[columns.Status] = afterStatus
|
||||
data[columns.AuditStatus] = "approved"
|
||||
data[columns.RejectReasonCode] = ""
|
||||
if before.PublishedAt == nil {
|
||||
data[columns.PublishedAt] = now
|
||||
}
|
||||
case "reject":
|
||||
if before.Status != "reviewing" {
|
||||
return gerror.New("仅待审核动态可拒绝")
|
||||
}
|
||||
afterStatus = "rejected"
|
||||
data[columns.Status] = afterStatus
|
||||
data[columns.AuditStatus] = "rejected"
|
||||
data[columns.RejectReasonCode] = in.Reason
|
||||
case "take_down":
|
||||
if before.Status != "published" {
|
||||
return gerror.New("仅已发布动态可下架")
|
||||
}
|
||||
afterStatus = "taken_down"
|
||||
data[columns.Status] = afterStatus
|
||||
data[columns.TakenDownAt] = now
|
||||
data[columns.RejectReasonCode] = in.Reason
|
||||
case "restore":
|
||||
if before.Status != "taken_down" {
|
||||
return gerror.New("仅已下架动态可恢复")
|
||||
}
|
||||
afterStatus = "published"
|
||||
data[columns.Status] = afterStatus
|
||||
data[columns.TakenDownAt] = nil
|
||||
data[columns.RejectReasonCode] = ""
|
||||
}
|
||||
if _, err = tx.Model(dao.FeedPost.Table()).Where(columns.Id, before.Id).Data(data).Update(); err != nil {
|
||||
return gerror.Wrap(err, "更新动态审核状态失败")
|
||||
}
|
||||
if err = writeContentAudit(ctx, tx, tenantID, operatorID, "feed_post", before.Id, before.Status, afterStatus, in.Action, now); err != nil {
|
||||
return err
|
||||
}
|
||||
return writeCultivateOperation(ctx, tx, tenantID, operatorID, "content."+in.Action, "feed_post", in.Id, before, data, in.Reason, now)
|
||||
}
|
||||
|
||||
func (s *sSysCultivateContent) reviewComment(ctx context.Context, tx gdb.TX, tenantID, operatorID int64, in *sysin.CultivateContentReviewInp) error {
|
||||
columns := dao.FeedComment.Columns()
|
||||
var before entity.FeedComment
|
||||
err := tx.Model(dao.FeedComment.Table()).Where(g.Map{columns.Id: in.ObjectId, columns.TenantId: tenantID}).LockUpdate().Scan(&before)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return err
|
||||
}
|
||||
if before.Id == 0 {
|
||||
return gerror.New("评论不存在")
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
data := g.Map{columns.UpdatedAt: now}
|
||||
afterStatus := before.Status
|
||||
counterDelta := 0
|
||||
switch in.Action {
|
||||
case "approve":
|
||||
if before.Status != "reviewing" && before.Status != "rejected" {
|
||||
return gerror.New("仅待审核或已拒绝评论可审核通过")
|
||||
}
|
||||
afterStatus = "published"
|
||||
data[columns.Status] = afterStatus
|
||||
data[columns.AuditStatus] = "approved"
|
||||
data[columns.PublishedAt] = now
|
||||
counterDelta = 1
|
||||
case "reject":
|
||||
if before.Status != "reviewing" {
|
||||
return gerror.New("仅待审核评论可拒绝")
|
||||
}
|
||||
afterStatus = "rejected"
|
||||
data[columns.Status] = afterStatus
|
||||
data[columns.AuditStatus] = "rejected"
|
||||
data[columns.DeleteReason] = in.Reason
|
||||
case "take_down":
|
||||
if before.Status != "published" {
|
||||
return gerror.New("仅已发布评论可下架")
|
||||
}
|
||||
afterStatus = "taken_down"
|
||||
data[columns.Status] = afterStatus
|
||||
data[columns.DeleteReason] = in.Reason
|
||||
counterDelta = -1
|
||||
case "restore":
|
||||
if before.Status != "taken_down" {
|
||||
return gerror.New("仅已下架评论可恢复")
|
||||
}
|
||||
afterStatus = "published"
|
||||
data[columns.Status] = afterStatus
|
||||
data[columns.DeleteReason] = ""
|
||||
counterDelta = 1
|
||||
}
|
||||
if _, err = tx.Model(dao.FeedComment.Table()).Where(columns.Id, before.Id).Data(data).Update(); err != nil {
|
||||
return gerror.Wrap(err, "更新评论审核状态失败")
|
||||
}
|
||||
if counterDelta != 0 {
|
||||
postColumns := dao.FeedPost.Columns()
|
||||
expression := "`comment_count` + 1"
|
||||
if counterDelta < 0 {
|
||||
expression = "GREATEST(`comment_count` - 1, 0)"
|
||||
}
|
||||
if _, err = tx.Model(dao.FeedPost.Table()).Where(g.Map{postColumns.Id: before.PostId, postColumns.TenantId: tenantID}).Data(g.Map{postColumns.CommentCount: gdb.Raw(expression), postColumns.UpdatedAt: now}).Update(); err != nil {
|
||||
return gerror.Wrap(err, "更新动态评论数失败")
|
||||
}
|
||||
}
|
||||
if err = writeContentAudit(ctx, tx, tenantID, operatorID, "feed_comment", before.Id, before.Status, afterStatus, in.Action, now); err != nil {
|
||||
return err
|
||||
}
|
||||
return writeCultivateOperation(ctx, tx, tenantID, operatorID, "content."+in.Action, "feed_comment", in.Id, before, data, in.Reason, now)
|
||||
}
|
||||
|
||||
func writeContentAudit(ctx context.Context, tx gdb.TX, tenantID, operatorID int64, objectType string, objectID uint64, before, after, result string, now time.Time) error {
|
||||
id, err := imtenant.NextSnowflakeID(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
columns := dao.ContentAuditLog.Columns()
|
||||
_, err = tx.Model(dao.ContentAuditLog.Table()).Data(g.Map{columns.Id: id, columns.TenantId: tenantID, columns.ObjectType: objectType, columns.ObjectId: objectID, columns.AuditSource: "manual", columns.StatusBefore: before, columns.StatusAfter: after, columns.ResultCode: result, columns.RiskLabels: "[]", columns.OperatorId: operatorID, columns.OccurredAt: now, columns.CreatedAt: now}).Insert()
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *sSysCultivateContent) ReportList(ctx context.Context, in *sysin.CultivateReportListInp) (list []*sysin.CultivateReportListModel, totalCount int, err error) {
|
||||
columns := dao.FeedReport.Columns()
|
||||
mod := dao.FeedReport.Ctx(ctx).Where(columns.TenantId, cultivateTenantID(ctx))
|
||||
if in.ObjectType != "" {
|
||||
mod = mod.Where(columns.ObjectType, in.ObjectType)
|
||||
}
|
||||
if in.Status != "" {
|
||||
mod = mod.Where(columns.Status, in.Status)
|
||||
}
|
||||
if in.ReporterId != "" {
|
||||
mod = mod.Where(columns.ReporterId, in.ReporterId)
|
||||
}
|
||||
if len(in.CreatedAt) == 2 {
|
||||
mod = mod.WhereBetween(columns.CreatedAt, in.CreatedAt[0], in.CreatedAt[1])
|
||||
}
|
||||
var rows []*entity.FeedReport
|
||||
if err = mod.Page(in.Page, in.PerPage).OrderDesc(columns.Id).ScanAndCount(&rows, &totalCount, false); err != nil {
|
||||
return nil, 0, gerror.Wrap(err, "获取举报列表失败")
|
||||
}
|
||||
list = make([]*sysin.CultivateReportListModel, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
list = append(list, &sysin.CultivateReportListModel{Id: strconv.FormatUint(row.Id, 10), ReporterId: strconv.FormatUint(row.ReporterId, 10), ReportedUserId: strconv.FormatUint(row.ReportedUserId, 10), ObjectType: row.ObjectType, ObjectId: row.ObjectId, ReasonCode: row.ReasonCode, Description: row.Description, EvidenceFileIds: row.EvidenceFileIds, SourcePage: row.SourcePage, Status: row.Status, HandlerId: optionalUint(row.HandlerId), HandleResult: row.HandleResult, HandledAt: row.HandledAt, CreatedAt: row.CreatedAt})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sSysCultivateContent) ReportHandle(ctx context.Context, in *sysin.CultivateReportHandleInp) error {
|
||||
tenantID, operatorID := cultivateTenantID(ctx), contexts.GetUserId(ctx)
|
||||
return dao.FeedReport.Transaction(ctx, func(txCtx context.Context, tx gdb.TX) error {
|
||||
columns := dao.FeedReport.Columns()
|
||||
var before entity.FeedReport
|
||||
err := tx.Model(dao.FeedReport.Table()).Where(g.Map{columns.Id: in.ReportId, columns.TenantId: tenantID}).LockUpdate().Scan(&before)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return err
|
||||
}
|
||||
if before.Id == 0 {
|
||||
return gerror.New("举报记录不存在")
|
||||
}
|
||||
if before.Status == "resolved" || before.Status == "rejected" {
|
||||
return gerror.New("举报已办结,不能重复处理")
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
status := in.Action
|
||||
if status == "resolve" {
|
||||
status = "resolved"
|
||||
}
|
||||
data := g.Map{columns.Status: status, columns.HandlerId: operatorID, columns.HandleResult: in.HandleResult, columns.UpdatedAt: now}
|
||||
if status == "resolved" || status == "rejected" {
|
||||
data[columns.HandledAt] = now
|
||||
}
|
||||
if _, err = tx.Model(dao.FeedReport.Table()).Where(columns.Id, before.Id).Data(data).Update(); err != nil {
|
||||
return gerror.Wrap(err, "更新举报处理状态失败")
|
||||
}
|
||||
return writeCultivateOperation(txCtx, tx, tenantID, operatorID, "report."+in.Action, "feed_report", in.Id, before, data, in.HandleResult, now)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *sSysCultivateContent) LogList(ctx context.Context, in *sysin.CultivateOperationLogListInp) (list []*sysin.CultivateOperationLogListModel, totalCount int, err error) {
|
||||
columns := dao.AdminOperationLog.Columns()
|
||||
mod := dao.AdminOperationLog.Ctx(ctx).Where(columns.TenantId, cultivateTenantID(ctx))
|
||||
if in.OperatorId != "" {
|
||||
mod = mod.Where(columns.OperatorId, in.OperatorId)
|
||||
}
|
||||
if in.OperationType != "" {
|
||||
mod = mod.WhereLike(columns.OperationType, "%"+strings.TrimSpace(in.OperationType)+"%")
|
||||
}
|
||||
if in.TargetType != "" {
|
||||
mod = mod.Where(columns.TargetType, in.TargetType)
|
||||
}
|
||||
if len(in.CreatedAt) == 2 {
|
||||
mod = mod.WhereBetween(columns.CreatedAt, in.CreatedAt[0], in.CreatedAt[1])
|
||||
}
|
||||
var rows []*entity.AdminOperationLog
|
||||
if err = mod.Page(in.Page, in.PerPage).OrderDesc(columns.Id).ScanAndCount(&rows, &totalCount, false); err != nil {
|
||||
return nil, 0, gerror.Wrap(err, "获取操作日志失败")
|
||||
}
|
||||
list = make([]*sysin.CultivateOperationLogListModel, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
list = append(list, &sysin.CultivateOperationLogListModel{Id: strconv.FormatUint(row.Id, 10), OperatorId: strconv.FormatUint(row.OperatorId, 10), OperationType: row.OperationType, TargetType: row.TargetType, TargetId: row.TargetId, RequestId: row.RequestId, BeforeSnapshot: jsonValue(row.BeforeSnapshot), AfterSnapshot: jsonValue(row.AfterSnapshot), Reason: row.Reason, CreatedAt: row.CreatedAt})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func optionalUint(value uint64) string {
|
||||
if value == 0 {
|
||||
return ""
|
||||
}
|
||||
return strconv.FormatUint(value, 10)
|
||||
}
|
||||
func jsonValue(value *gjson.Json) any {
|
||||
if value == nil {
|
||||
return nil
|
||||
}
|
||||
return value
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
package sys
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"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/os/gctx"
|
||||
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/imtenant"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
)
|
||||
|
||||
type sSysCultivateFlower struct{}
|
||||
|
||||
func NewSysCultivateFlower() *sSysCultivateFlower { return &sSysCultivateFlower{} }
|
||||
func init() { service.RegisterSysCultivateFlower(NewSysCultivateFlower()) }
|
||||
|
||||
func cultivateTenantID(ctx context.Context) int64 {
|
||||
id := contexts.GetTenantId(ctx)
|
||||
if id <= 0 {
|
||||
id = g.Cfg().MustGet(ctx, "cultivate.defaultTenantId", 1).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) {
|
||||
tenantID := cultivateTenantID(ctx)
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
beforeJSON, _ := json.Marshal(before)
|
||||
afterJSON, _ := json.Marshal(after)
|
||||
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: "", c.UserAgent: "", c.CreatedAt: now}).Insert()
|
||||
return e
|
||||
}
|
||||
Reference in New Issue
Block a user