615 lines
19 KiB
Go
615 lines
19 KiB
Go
package resource
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"hyapp-admin-server/internal/appctx"
|
|
"hyapp-admin-server/internal/integration/walletclient"
|
|
"hyapp-admin-server/internal/middleware"
|
|
"hyapp-admin-server/internal/modules/shared"
|
|
"hyapp-admin-server/internal/repository"
|
|
"hyapp-admin-server/internal/response"
|
|
walletv1 "hyapp.local/api/proto/wallet/v1"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type Handler struct {
|
|
wallet walletclient.Client
|
|
store *repository.Store
|
|
userDB *sql.DB
|
|
audit shared.OperationLogger
|
|
}
|
|
|
|
func New(wallet walletclient.Client, store *repository.Store, userDB *sql.DB, audit shared.OperationLogger) *Handler {
|
|
return &Handler{wallet: wallet, store: store, userDB: userDB, audit: audit}
|
|
}
|
|
|
|
func (h *Handler) ListResources(c *gin.Context) {
|
|
options := shared.ListOptions(c)
|
|
resp, err := h.wallet.ListResources(c.Request.Context(), &walletv1.ListResourcesRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
ResourceType: strings.TrimSpace(c.Query("resource_type")),
|
|
Status: options.Status,
|
|
Keyword: options.Keyword,
|
|
Page: int32(options.Page),
|
|
PageSize: int32(options.PageSize),
|
|
})
|
|
if err != nil {
|
|
response.ServerError(c, "获取资源列表失败")
|
|
return
|
|
}
|
|
items := make([]resourceDTO, 0, len(resp.GetResources()))
|
|
for _, item := range resp.GetResources() {
|
|
items = append(items, resourceFromProto(item))
|
|
}
|
|
response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()})
|
|
}
|
|
|
|
func (h *Handler) GetResource(c *gin.Context) {
|
|
resourceID, ok := parseID(c, "resource_id")
|
|
if !ok {
|
|
return
|
|
}
|
|
resp, err := h.wallet.GetResource(c.Request.Context(), &walletv1.GetResourceRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
ResourceId: resourceID,
|
|
})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
response.OK(c, resourceFromProto(resp.GetResource()))
|
|
}
|
|
|
|
func (h *Handler) CreateResource(c *gin.Context) {
|
|
var req resourceRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "资源参数不正确")
|
|
return
|
|
}
|
|
if err := validateResourcePricing(req); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
if err := validateResourceBadgeForm(req); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
resp, err := h.wallet.CreateResource(c.Request.Context(), req.createProto(c))
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
resource := resourceFromProto(resp.GetResource())
|
|
h.auditLog(c, "create-resource", "resources", fmt.Sprintf("%d", resource.ResourceID), "success", resource.ResourceCode)
|
|
response.Created(c, resource)
|
|
}
|
|
|
|
func (h *Handler) ListEmojiPacks(c *gin.Context) {
|
|
options := shared.ListOptions(c)
|
|
resp, err := h.wallet.ListResources(c.Request.Context(), &walletv1.ListResourcesRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
ResourceType: resourceTypeEmojiPack,
|
|
Status: options.Status,
|
|
Keyword: options.Keyword,
|
|
Page: int32(options.Page),
|
|
PageSize: int32(options.PageSize),
|
|
})
|
|
if err != nil {
|
|
response.ServerError(c, "获取表情包列表失败")
|
|
return
|
|
}
|
|
items := make([]emojiPackDTO, 0, len(resp.GetResources()))
|
|
for _, item := range resp.GetResources() {
|
|
items = append(items, emojiPackFromProto(item))
|
|
}
|
|
response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()})
|
|
}
|
|
|
|
func (h *Handler) ListEmojiPackCategories(c *gin.Context) {
|
|
const pageSize int32 = 100
|
|
categories := map[string]struct{}{}
|
|
for page := int32(1); ; page++ {
|
|
resp, err := h.wallet.ListResources(c.Request.Context(), &walletv1.ListResourcesRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
ResourceType: resourceTypeEmojiPack,
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
})
|
|
if err != nil {
|
|
response.ServerError(c, "获取表情包分类失败")
|
|
return
|
|
}
|
|
for _, item := range resp.GetResources() {
|
|
category := emojiPackMetadataFromJSON(item.GetMetadataJson()).Category
|
|
if category != "" {
|
|
categories[category] = struct{}{}
|
|
}
|
|
}
|
|
if len(resp.GetResources()) == 0 || int64(page)*int64(pageSize) >= resp.GetTotal() {
|
|
break
|
|
}
|
|
}
|
|
items := make([]string, 0, len(categories))
|
|
for category := range categories {
|
|
items = append(items, category)
|
|
}
|
|
sort.Strings(items)
|
|
response.OK(c, items)
|
|
}
|
|
|
|
func (h *Handler) CreateEmojiPack(c *gin.Context) {
|
|
var req emojiPackRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "表情包参数不正确")
|
|
return
|
|
}
|
|
protoReq, err := req.createProto(c)
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
resp, err := h.wallet.CreateResource(c.Request.Context(), protoReq)
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
item := emojiPackFromProto(resp.GetResource())
|
|
h.auditLog(c, "create-emoji-pack", "resources", fmt.Sprintf("%d", item.ResourceID), "success", item.ResourceCode)
|
|
response.Created(c, item)
|
|
}
|
|
|
|
func (h *Handler) UpdateResource(c *gin.Context) {
|
|
resourceID, ok := parseID(c, "resource_id")
|
|
if !ok {
|
|
return
|
|
}
|
|
var req resourceRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "资源参数不正确")
|
|
return
|
|
}
|
|
if err := validateResourcePricing(req); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
if err := validateResourceBadgeForm(req); err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
protoReq := req.updateProto(c, resourceID)
|
|
resp, err := h.wallet.UpdateResource(c.Request.Context(), protoReq)
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
resource := resourceFromProto(resp.GetResource())
|
|
h.auditLog(c, "update-resource", "resources", fmt.Sprintf("%d", resource.ResourceID), "success", resource.ResourceCode)
|
|
response.OK(c, resource)
|
|
}
|
|
|
|
func (h *Handler) EnableResource(c *gin.Context) {
|
|
h.setResourceStatus(c, "active")
|
|
}
|
|
|
|
func (h *Handler) DisableResource(c *gin.Context) {
|
|
h.setResourceStatus(c, "disabled")
|
|
}
|
|
|
|
func (h *Handler) ListResourceGroups(c *gin.Context) {
|
|
options := shared.ListOptions(c)
|
|
resp, err := h.wallet.ListResourceGroups(c.Request.Context(), &walletv1.ListResourceGroupsRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
Status: options.Status,
|
|
Keyword: options.Keyword,
|
|
Page: int32(options.Page),
|
|
PageSize: int32(options.PageSize),
|
|
})
|
|
if err != nil {
|
|
response.ServerError(c, "获取资源组列表失败")
|
|
return
|
|
}
|
|
items := make([]resourceGroupDTO, 0, len(resp.GetGroups()))
|
|
for _, item := range resp.GetGroups() {
|
|
items = append(items, resourceGroupFromProto(item))
|
|
}
|
|
response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()})
|
|
}
|
|
|
|
func (h *Handler) GetResourceGroup(c *gin.Context) {
|
|
groupID, ok := parseID(c, "group_id")
|
|
if !ok {
|
|
return
|
|
}
|
|
resp, err := h.wallet.GetResourceGroup(c.Request.Context(), &walletv1.GetResourceGroupRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
GroupId: groupID,
|
|
})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
response.OK(c, resourceGroupFromProto(resp.GetGroup()))
|
|
}
|
|
|
|
func (h *Handler) CreateResourceGroup(c *gin.Context) {
|
|
var req resourceGroupRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "资源组参数不正确")
|
|
return
|
|
}
|
|
resp, err := h.wallet.CreateResourceGroup(c.Request.Context(), req.createProto(c))
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
group := resourceGroupFromProto(resp.GetGroup())
|
|
h.auditLog(c, "create-resource-group", "resource_groups", fmt.Sprintf("%d", group.GroupID), "success", group.GroupCode)
|
|
response.Created(c, group)
|
|
}
|
|
|
|
func (h *Handler) UpdateResourceGroup(c *gin.Context) {
|
|
groupID, ok := parseID(c, "group_id")
|
|
if !ok {
|
|
return
|
|
}
|
|
var req resourceGroupRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "资源组参数不正确")
|
|
return
|
|
}
|
|
resp, err := h.wallet.UpdateResourceGroup(c.Request.Context(), req.updateProto(c, groupID))
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
group := resourceGroupFromProto(resp.GetGroup())
|
|
h.auditLog(c, "update-resource-group", "resource_groups", fmt.Sprintf("%d", group.GroupID), "success", group.GroupCode)
|
|
response.OK(c, group)
|
|
}
|
|
|
|
func (h *Handler) EnableResourceGroup(c *gin.Context) {
|
|
h.setResourceGroupStatus(c, "active")
|
|
}
|
|
|
|
func (h *Handler) DisableResourceGroup(c *gin.Context) {
|
|
h.setResourceGroupStatus(c, "disabled")
|
|
}
|
|
|
|
func (h *Handler) ListGifts(c *gin.Context) {
|
|
options := shared.ListOptions(c)
|
|
regionID, filterRegion, ok := optionalInt64QueryWithPresence(c, "regionId", "region_id")
|
|
if !ok {
|
|
return
|
|
}
|
|
resp, err := h.wallet.ListGiftConfigs(c.Request.Context(), &walletv1.ListGiftConfigsRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
Status: options.Status,
|
|
Keyword: options.Keyword,
|
|
Page: int32(options.Page),
|
|
PageSize: int32(options.PageSize),
|
|
RegionId: regionID,
|
|
FilterRegion: filterRegion,
|
|
})
|
|
if err != nil {
|
|
response.ServerError(c, "获取礼物列表失败")
|
|
return
|
|
}
|
|
items := make([]giftDTO, 0, len(resp.GetGifts()))
|
|
for _, item := range resp.GetGifts() {
|
|
items = append(items, giftFromProto(item))
|
|
}
|
|
response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()})
|
|
}
|
|
|
|
func (h *Handler) ListGiftTypes(c *gin.Context) {
|
|
resp, err := h.wallet.ListGiftTypeConfigs(c.Request.Context(), &walletv1.ListGiftTypeConfigsRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
})
|
|
if err != nil {
|
|
response.ServerError(c, "获取礼物类型失败")
|
|
return
|
|
}
|
|
items := make([]giftTypeDTO, 0, len(resp.GetGiftTypes()))
|
|
for _, item := range resp.GetGiftTypes() {
|
|
items = append(items, giftTypeFromProto(item))
|
|
}
|
|
response.OK(c, items)
|
|
}
|
|
|
|
func (h *Handler) UpdateGiftType(c *gin.Context) {
|
|
typeCode := strings.TrimSpace(c.Param("type_code"))
|
|
if typeCode == "" {
|
|
response.BadRequest(c, "类型编码不正确")
|
|
return
|
|
}
|
|
var req giftTypeRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "礼物类型参数不正确")
|
|
return
|
|
}
|
|
resp, err := h.wallet.UpsertGiftTypeConfig(c.Request.Context(), req.upsertProto(c, typeCode))
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
item := giftTypeFromProto(resp.GetGiftType())
|
|
h.auditLog(c, "update-gift-type", "gift_type_configs", item.TabKey, "success", item.TabName)
|
|
response.OK(c, item)
|
|
}
|
|
|
|
func (h *Handler) UpdateGiftTypes(c *gin.Context) {
|
|
var req giftTypesRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "礼物类型参数不正确")
|
|
return
|
|
}
|
|
if len(req.Items) == 0 {
|
|
response.BadRequest(c, "礼物类型不能为空")
|
|
return
|
|
}
|
|
items := make([]giftTypeDTO, 0, len(req.Items))
|
|
tabKeys := make([]string, 0, len(req.Items))
|
|
for _, requestItem := range req.Items {
|
|
tabKey := strings.TrimSpace(requestItem.TabKey)
|
|
if tabKey == "" {
|
|
response.BadRequest(c, "类型编码不正确")
|
|
return
|
|
}
|
|
resp, err := h.wallet.UpsertGiftTypeConfig(c.Request.Context(), requestItem.upsertProto(c))
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
item := giftTypeFromProto(resp.GetGiftType())
|
|
items = append(items, item)
|
|
tabKeys = append(tabKeys, item.TabKey)
|
|
}
|
|
h.auditLog(c, "update-gift-types", "gift_type_configs", "batch", "success", strings.Join(tabKeys, ","))
|
|
response.OK(c, items)
|
|
}
|
|
|
|
func (h *Handler) CreateGift(c *gin.Context) {
|
|
var req giftRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "礼物参数不正确")
|
|
return
|
|
}
|
|
resp, err := h.wallet.CreateGiftConfig(c.Request.Context(), req.createProto(c))
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
gift := giftFromProto(resp.GetGift())
|
|
h.auditLog(c, "create-gift", "gift_configs", gift.GiftID, "success", gift.Name)
|
|
response.Created(c, gift)
|
|
}
|
|
|
|
func (h *Handler) UpdateGift(c *gin.Context) {
|
|
giftID := strings.TrimSpace(c.Param("gift_id"))
|
|
if giftID == "" {
|
|
response.BadRequest(c, "ID 参数不正确")
|
|
return
|
|
}
|
|
var req giftRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "礼物参数不正确")
|
|
return
|
|
}
|
|
resp, err := h.wallet.UpdateGiftConfig(c.Request.Context(), req.updateProto(c, giftID))
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
gift := giftFromProto(resp.GetGift())
|
|
h.auditLog(c, "update-gift", "gift_configs", gift.GiftID, "success", gift.Name)
|
|
response.OK(c, gift)
|
|
}
|
|
|
|
func (h *Handler) EnableGift(c *gin.Context) {
|
|
h.setGiftStatus(c, "active")
|
|
}
|
|
|
|
func (h *Handler) DisableGift(c *gin.Context) {
|
|
h.setGiftStatus(c, "disabled")
|
|
}
|
|
|
|
func (h *Handler) GrantResource(c *gin.Context) {
|
|
var req grantResourceRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "资源赠送参数不正确")
|
|
return
|
|
}
|
|
resp, err := h.wallet.GrantResource(c.Request.Context(), &walletv1.GrantResourceRequest{
|
|
CommandId: strings.TrimSpace(req.CommandID),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
TargetUserId: req.TargetUserID,
|
|
ResourceId: req.ResourceID,
|
|
Quantity: req.Quantity,
|
|
DurationMs: req.DurationMS,
|
|
Reason: strings.TrimSpace(req.Reason),
|
|
OperatorUserId: actorID(c),
|
|
GrantSource: "admin",
|
|
})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
grant := grantFromProto(resp.GetGrant())
|
|
h.auditLog(c, "grant-resource", "resource_grants", grant.GrantID, "success", fmt.Sprintf("target_user_id=%d", grant.TargetUserID))
|
|
response.Created(c, grant)
|
|
}
|
|
|
|
func (h *Handler) GrantResourceGroup(c *gin.Context) {
|
|
var req grantGroupRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "资源组赠送参数不正确")
|
|
return
|
|
}
|
|
resp, err := h.wallet.GrantResourceGroup(c.Request.Context(), &walletv1.GrantResourceGroupRequest{
|
|
CommandId: strings.TrimSpace(req.CommandID),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
TargetUserId: req.TargetUserID,
|
|
GroupId: req.GroupID,
|
|
Reason: strings.TrimSpace(req.Reason),
|
|
OperatorUserId: actorID(c),
|
|
GrantSource: "admin",
|
|
})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
grant := grantFromProto(resp.GetGrant())
|
|
h.auditLog(c, "grant-resource-group", "resource_grants", grant.GrantID, "success", fmt.Sprintf("target_user_id=%d", grant.TargetUserID))
|
|
response.Created(c, grant)
|
|
}
|
|
|
|
func (h *Handler) ListResourceGrants(c *gin.Context) {
|
|
options := shared.ListOptions(c)
|
|
targetUserID, ok := optionalInt64Query(c, "target_user_id", "targetUserId")
|
|
if !ok {
|
|
return
|
|
}
|
|
resp, err := h.wallet.ListResourceGrants(c.Request.Context(), &walletv1.ListResourceGrantsRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
TargetUserId: targetUserID,
|
|
Status: options.Status,
|
|
Page: int32(options.Page),
|
|
PageSize: int32(options.PageSize),
|
|
})
|
|
if err != nil {
|
|
response.ServerError(c, "获取资源赠送记录失败")
|
|
return
|
|
}
|
|
items := make([]grantDTO, 0, len(resp.GetGrants()))
|
|
for _, item := range resp.GetGrants() {
|
|
items = append(items, grantFromProto(item))
|
|
}
|
|
if err := h.enrichGrantOperators(c.Request.Context(), items); err != nil {
|
|
response.ServerError(c, "获取资源赠送操作人失败")
|
|
return
|
|
}
|
|
if err := h.enrichGrantTargets(c.Request.Context(), items); err != nil {
|
|
response.ServerError(c, "获取资源赠送用户信息失败")
|
|
return
|
|
}
|
|
response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()})
|
|
}
|
|
|
|
func (h *Handler) setResourceStatus(c *gin.Context, status string) {
|
|
resourceID, ok := parseID(c, "resource_id")
|
|
if !ok {
|
|
return
|
|
}
|
|
resp, err := h.wallet.SetResourceStatus(c.Request.Context(), &walletv1.SetResourceStatusRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
ResourceId: resourceID,
|
|
Status: status,
|
|
OperatorUserId: actorID(c),
|
|
})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
resource := resourceFromProto(resp.GetResource())
|
|
h.auditLog(c, "set-resource-status", "resources", fmt.Sprintf("%d", resource.ResourceID), "success", status)
|
|
response.OK(c, resource)
|
|
}
|
|
|
|
func (h *Handler) setResourceGroupStatus(c *gin.Context, status string) {
|
|
groupID, ok := parseID(c, "group_id")
|
|
if !ok {
|
|
return
|
|
}
|
|
resp, err := h.wallet.SetResourceGroupStatus(c.Request.Context(), &walletv1.SetResourceGroupStatusRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
GroupId: groupID,
|
|
Status: status,
|
|
OperatorUserId: actorID(c),
|
|
})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
group := resourceGroupFromProto(resp.GetGroup())
|
|
h.auditLog(c, "set-resource-group-status", "resource_groups", fmt.Sprintf("%d", group.GroupID), "success", status)
|
|
response.OK(c, group)
|
|
}
|
|
|
|
func (h *Handler) setGiftStatus(c *gin.Context, status string) {
|
|
giftID := strings.TrimSpace(c.Param("gift_id"))
|
|
if giftID == "" {
|
|
response.BadRequest(c, "ID 参数不正确")
|
|
return
|
|
}
|
|
resp, err := h.wallet.SetGiftConfigStatus(c.Request.Context(), &walletv1.SetGiftConfigStatusRequest{
|
|
RequestId: middleware.CurrentRequestID(c),
|
|
AppCode: appctx.FromContext(c.Request.Context()),
|
|
GiftId: giftID,
|
|
Status: status,
|
|
OperatorUserId: actorID(c),
|
|
})
|
|
if err != nil {
|
|
response.BadRequest(c, err.Error())
|
|
return
|
|
}
|
|
gift := giftFromProto(resp.GetGift())
|
|
h.auditLog(c, "set-gift-status", "gift_configs", gift.GiftID, "success", status)
|
|
response.OK(c, gift)
|
|
}
|
|
|
|
func (h *Handler) auditLog(c *gin.Context, action string, resource string, resourceID string, status string, detail string) {
|
|
shared.OperationLogWithResourceID(c, h.audit, action, resource, resourceID, status, detail)
|
|
}
|
|
|
|
func actorID(c *gin.Context) int64 {
|
|
return int64(shared.ActorFromContext(c).UserID)
|
|
}
|
|
|
|
func parseID(c *gin.Context, name string) (int64, bool) {
|
|
raw := strings.TrimSpace(c.Param(name))
|
|
value, err := strconv.ParseInt(raw, 10, 64)
|
|
if err != nil || value <= 0 {
|
|
response.BadRequest(c, "ID 参数不正确")
|
|
return 0, false
|
|
}
|
|
return value, true
|
|
}
|
|
|
|
func optionalInt64Query(c *gin.Context, primary string, fallback string) (int64, bool) {
|
|
value, _, ok := optionalInt64QueryWithPresence(c, primary, fallback)
|
|
return value, ok
|
|
}
|
|
|
|
func optionalInt64QueryWithPresence(c *gin.Context, primary string, fallback string) (int64, bool, bool) {
|
|
raw := strings.TrimSpace(c.Query(primary))
|
|
if raw == "" {
|
|
raw = strings.TrimSpace(c.Query(fallback))
|
|
}
|
|
if raw == "" {
|
|
return 0, false, true
|
|
}
|
|
value, err := strconv.ParseInt(raw, 10, 64)
|
|
if err != nil || value < 0 {
|
|
response.BadRequest(c, primary+" 参数不正确")
|
|
return 0, false, false
|
|
}
|
|
return value, true, true
|
|
}
|