2026-07-09 18:15:57 +08:00

650 lines
23 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package hostorg
import (
"database/sql"
"fmt"
"strconv"
"strings"
"hyapp-admin-server/internal/integration/userclient"
"hyapp-admin-server/internal/integration/walletclient"
"hyapp-admin-server/internal/middleware"
"hyapp-admin-server/internal/modules/shared"
"hyapp-admin-server/internal/response"
"github.com/gin-gonic/gin"
)
type Handler struct {
service *Service
audit shared.OperationLogger
}
func New(userClient userclient.Client, walletClient walletclient.Client, userDB *sql.DB, walletDB *sql.DB, adminDB *sql.DB, audit shared.OperationLogger) *Handler {
return &Handler{service: NewService(userClient, walletClient, NewReader(userDB, walletDB, adminDB)), audit: audit}
}
func (h *Handler) ListBDLeaders(c *gin.Context) {
query, ok := parseListQuery(c)
if !ok {
return
}
items, total, err := h.service.ListBDLeaders(c.Request.Context(), query)
if err != nil {
response.ServerError(c, "获取 BD Leader 列表失败")
return
}
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
}
func (h *Handler) ListBDs(c *gin.Context) {
query, ok := parseListQuery(c)
if !ok {
return
}
items, total, err := h.service.ListBDs(c.Request.Context(), query)
if err != nil {
response.ServerError(c, "获取 BD 列表失败")
return
}
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
}
func (h *Handler) ListAgencies(c *gin.Context) {
query, ok := parseListQuery(c)
if !ok {
return
}
items, total, err := h.service.ListAgencies(c.Request.Context(), query)
if err != nil {
response.ServerError(c, "获取 Agency 列表失败")
return
}
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
}
func (h *Handler) ListManagers(c *gin.Context) {
query, ok := parseListQuery(c)
if !ok {
return
}
items, total, err := h.service.ListManagers(c.Request.Context(), query)
if err != nil {
response.ServerError(c, "获取经理列表失败")
return
}
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
}
func (h *Handler) CreateManager(c *gin.Context) {
var req createManagerRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "经理参数不正确")
return
}
item, err := h.service.CreateManager(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "create-manager", "manager_profiles", item.UserID,
fmt.Sprintf("user_id=%d contact=%q", item.UserID, strings.TrimSpace(req.Contact)))
response.Created(c, item)
}
func (h *Handler) UpdateManager(c *gin.Context) {
userID, ok := parseInt64ID(c, "user_id")
if !ok {
return
}
var req updateManagerRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "经理参数不正确")
return
}
item, err := h.service.UpdateManager(c.Request.Context(), adminActorID(c), userID, req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
statusDetail := ""
if req.Status != nil && strings.TrimSpace(*req.Status) != "" {
statusDetail = " status=" + strings.ToLower(strings.TrimSpace(*req.Status))
}
writeHostOrgAuditLog(c, h.audit, "update-manager", "manager_profiles", item.UserID,
fmt.Sprintf("user_id=%d permissions_updated=true%s", item.UserID, statusDetail))
response.OK(c, item)
}
func (h *Handler) ListHosts(c *gin.Context) {
query, ok := parseListQuery(c)
if !ok {
return
}
items, total, err := h.service.ListHosts(c.Request.Context(), query)
if err != nil {
response.ServerError(c, "获取主播列表失败")
return
}
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
}
func (h *Handler) ListCoinSellers(c *gin.Context) {
query, ok := parseListQuery(c)
if !ok {
return
}
items, total, err := h.service.ListCoinSellers(c.Request.Context(), query)
if err != nil {
response.ServerError(c, "获取币商列表失败")
return
}
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
}
func (h *Handler) ListCoinSellerSubApplications(c *gin.Context) {
query, ok := parseListQuery(c)
if !ok {
return
}
items, total, err := h.service.ListCoinSellerSubApplications(c.Request.Context(), query)
if err != nil {
response.ServerError(c, "获取子币商申请列表失败")
return
}
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
}
func (h *Handler) ListCoinSellerSubSellers(c *gin.Context) {
parentUserID, ok := parseInt64ID(c, "user_id")
if !ok {
return
}
query, ok := parseListQuery(c)
if !ok {
return
}
items, total, err := h.service.ListCoinSellerSubSellers(c.Request.Context(), parentUserID, query)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
}
func (h *Handler) ApproveCoinSellerSubApplication(c *gin.Context) {
h.reviewCoinSellerSubApplication(c, "approved")
}
func (h *Handler) RejectCoinSellerSubApplication(c *gin.Context) {
h.reviewCoinSellerSubApplication(c, "rejected")
}
func (h *Handler) reviewCoinSellerSubApplication(c *gin.Context, decision string) {
applicationID, ok := parseInt64ID(c, "application_id")
if !ok {
return
}
var req coinSellerSubApplicationReviewRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "子币商申请审核参数不正确")
return
}
result, err := h.service.ReviewCoinSellerSubApplication(c.Request.Context(), adminActorID(c), applicationID, middleware.CurrentRequestID(c), decision, req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "review-coin-seller-sub-application", "coin_seller_sub_applications", applicationID,
fmt.Sprintf("command_id=%s application_id=%d decision=%s reason=%q", strings.TrimSpace(req.CommandID), applicationID, decision, strings.TrimSpace(req.Reason)))
response.OK(c, result)
}
func (h *Handler) ListSalaryWalletHistory(c *gin.Context) {
query, ok := parseSalaryWalletHistoryQuery(c)
if !ok {
return
}
items, total, err := h.service.ListSalaryWalletHistory(c.Request.Context(), query)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total})
}
func (h *Handler) AdjustSalaryWallet(c *gin.Context) {
var req salaryWalletAdjustRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "工资钱包操作参数不正确")
return
}
result, err := h.service.AdjustSalaryWallet(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "salary-wallet-adjust", "wallet_entries", req.TargetUserID.Int64(),
fmt.Sprintf("role=%s target_user_id=%d amount_minor=%d transaction_id=%s reason=%q",
result.Role, req.TargetUserID.Int64(), result.AmountMinor, result.TransactionID, strings.TrimSpace(req.Reason)))
response.Created(c, result)
}
func (h *Handler) CreateBDLeader(c *gin.Context) {
var req createBDLeaderRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "BD Leader 参数不正确")
return
}
profile, err := h.service.CreateBDLeader(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "create-bd-leader", "bd_leader_profiles", profile.UserID,
fmt.Sprintf("command_id=%s user_id=%d region_id=%d position_alias=%q reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.RegionID, strings.TrimSpace(req.PositionAlias), strings.TrimSpace(req.Reason)))
response.Created(c, profile)
}
func (h *Handler) CreateBD(c *gin.Context) {
var req createBDRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "BD 参数不正确")
return
}
profile, err := h.service.CreateBD(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "create-bd", "bd_profiles", profile.UserID,
fmt.Sprintf("command_id=%s user_id=%d parent_leader_user_id=%d reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.ParentLeaderUserID, strings.TrimSpace(req.Reason)))
response.Created(c, profile)
}
func (h *Handler) SetBDStatus(c *gin.Context) {
targetUserID, ok := parseInt64ID(c, "user_id")
if !ok {
return
}
var req bdStatusRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "BD 状态参数不正确")
return
}
role, auditTarget := bdRoleFromStatusRoute(c)
profile, err := h.service.SetBDStatus(c.Request.Context(), adminActorID(c), targetUserID, middleware.CurrentRequestID(c), role, req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "set-bd-status", auditTarget, profile.UserID,
fmt.Sprintf("command_id=%s user_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.Status, strings.TrimSpace(req.Reason)))
response.OK(c, profile)
}
func bdRoleFromStatusRoute(c *gin.Context) (string, string) {
return bdRoleFromStatusPath(c.FullPath())
}
func bdRoleFromStatusPath(fullPath string) (string, string) {
// FullPath 带有外层 /api/v1 分组;只要命中 BD Leader 状态路由片段,就必须走独立的 bd_leader_profiles避免误查普通 bd_profiles。
if strings.Contains(fullPath, "/admin/bd-leaders/") {
return "bd_leader", "bd_leader_profiles"
}
return "bd", "bd_profiles"
}
func (h *Handler) UpdateBDLeaderPositionAlias(c *gin.Context) {
targetUserID, ok := parseInt64ID(c, "user_id")
if !ok {
return
}
var req bdLeaderPositionAliasRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "职位别名参数不正确")
return
}
profile, err := h.service.UpdateBDLeaderPositionAlias(c.Request.Context(), adminActorID(c), targetUserID, req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "set-bd-leader-position-alias", "admin_bd_leader_position_aliases", profile.UserID,
fmt.Sprintf("command_id=%s user_id=%d position_alias=%q reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.PositionAlias, strings.TrimSpace(req.Reason)))
response.OK(c, profile)
}
func (h *Handler) DeleteBDLeader(c *gin.Context) {
targetUserID, ok := parseInt64ID(c, "user_id")
if !ok {
return
}
profile, err := h.service.DeleteBDLeader(c.Request.Context(), targetUserID)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "delete-bd-leader", "bd_leader_profiles", profile.UserID,
fmt.Sprintf("user_id=%d", profile.UserID))
response.OK(c, profile)
}
func (h *Handler) CreateCoinSeller(c *gin.Context) {
var req createCoinSellerRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "币商参数不正确")
return
}
profile, err := h.service.CreateCoinSeller(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "create-coin-seller", "coin_seller_profiles", profile.UserID,
fmt.Sprintf("command_id=%s user_id=%d reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, strings.TrimSpace(req.Reason)))
response.Created(c, profile)
}
func (h *Handler) SetCoinSellerStatus(c *gin.Context) {
targetUserID, ok := parseInt64ID(c, "user_id")
if !ok {
return
}
var req coinSellerStatusRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "币商状态参数不正确")
return
}
profile, err := h.service.SetCoinSellerStatus(c.Request.Context(), adminActorID(c), targetUserID, middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "set-coin-seller-status", "coin_seller_profiles", profile.UserID,
fmt.Sprintf("command_id=%s user_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.Status, strings.TrimSpace(req.Reason)))
response.OK(c, profile)
}
func (h *Handler) CreditCoinSellerStock(c *gin.Context) {
sellerUserID, ok := parseInt64ID(c, "user_id")
if !ok {
return
}
var req coinSellerStockCreditRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "币商进货参数不正确")
return
}
result, err := h.service.CreditCoinSellerStock(c.Request.Context(), adminActorID(c), sellerUserID, middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "coin-seller-stock-credit", "coin_seller_stock_records", sellerUserID,
fmt.Sprintf("command_id=%s seller_user_id=%d stock_type=%s coin_amount=%d paid_currency_code=%s paid_amount_micro=%d transaction_id=%s reason=%q",
strings.TrimSpace(req.CommandID), sellerUserID, result.GetStockType(), result.GetCoinAmount(), result.GetPaidCurrencyCode(), result.GetPaidAmountMicro(), result.GetTransactionId(), strings.TrimSpace(req.Reason)))
response.Created(c, coinSellerStockCreditFromProto(result))
}
func (h *Handler) DebitCoinSellerStock(c *gin.Context) {
sellerUserID, ok := parseInt64ID(c, "user_id")
if !ok {
return
}
var req coinSellerStockDebitRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "币商扣除参数不正确")
return
}
result, err := h.service.DebitCoinSellerStock(c.Request.Context(), adminActorID(c), sellerUserID, middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "coin-seller-stock-debit", "coin_seller_stock_records", sellerUserID,
fmt.Sprintf("command_id=%s seller_user_id=%d stock_type=%s coin_amount=%d paid_currency_code=%s paid_amount_micro=%d transaction_id=%s reason=%q",
strings.TrimSpace(req.CommandID), sellerUserID, result.GetStockType(), result.GetCoinAmount(), result.GetPaidCurrencyCode(), result.GetPaidAmountMicro(), result.GetTransactionId(), strings.TrimSpace(req.Reason)))
response.Created(c, coinSellerStockDebitFromProto(sellerUserID, req.CoinAmount, result))
}
func (h *Handler) GetCoinSellerSalaryRates(c *gin.Context) {
regionID, ok := parseInt64ID(c, "region_id")
if !ok {
return
}
items, err := h.service.GetCoinSellerSalaryRates(c.Request.Context(), regionID)
if err != nil {
response.BadRequest(c, err.Error())
return
}
response.OK(c, gin.H{"regionId": regionID, "tiers": items})
}
func (h *Handler) ReplaceCoinSellerSalaryRates(c *gin.Context) {
regionID, ok := parseInt64ID(c, "region_id")
if !ok {
return
}
var req replaceCoinSellerSalaryRatesRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "币商工资兑换比例参数不正确")
return
}
items, err := h.service.ReplaceCoinSellerSalaryRates(c.Request.Context(), adminActorID(c), regionID, req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "coin-seller-salary-rates", "coin_seller_salary_exchange_rate_tiers", regionID,
fmt.Sprintf("region_id=%d tiers=%d", regionID, len(items)))
response.OK(c, gin.H{"regionId": regionID, "tiers": items})
}
func (h *Handler) CreateAgency(c *gin.Context) {
var req createAgencyRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Agency 参数不正确")
return
}
result, err := h.service.CreateAgency(c.Request.Context(), adminActorID(c), middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "create-agency", "agencies", result.Agency.AgencyID,
fmt.Sprintf("command_id=%s agency_id=%d owner_user_id=%d parent_bd_user_id=%d join_enabled=%t reason=%q",
strings.TrimSpace(req.CommandID), result.Agency.AgencyID, result.Agency.OwnerUserID, result.Agency.ParentBDUserID, result.Agency.JoinEnabled, strings.TrimSpace(req.Reason)))
response.Created(c, result)
}
func (h *Handler) AdminAddAgencyHost(c *gin.Context) {
agencyID, ok := parseInt64ID(c, "agency_id")
if !ok {
return
}
var req agencyHostAddRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "添加 Host 参数不正确")
return
}
result, err := h.service.AdminAddAgencyHost(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "add-agency-host", "agency_memberships", result.Membership.MembershipID,
fmt.Sprintf("command_id=%s agency_id=%d host_user_id=%d reason=%q",
strings.TrimSpace(req.CommandID), agencyID, result.Membership.HostUserID, strings.TrimSpace(req.Reason)))
response.Created(c, result)
}
func (h *Handler) CloseAgency(c *gin.Context) {
agencyID, ok := parseInt64ID(c, "agency_id")
if !ok {
return
}
var req agencyCloseRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "关闭 Agency 参数不正确")
return
}
agency, err := h.service.CloseAgency(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "close-agency", "agencies", agency.AgencyID,
fmt.Sprintf("command_id=%s agency_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), agency.AgencyID, agency.Status, strings.TrimSpace(req.Reason)))
response.OK(c, agency)
}
func (h *Handler) SetAgencyStatus(c *gin.Context) {
agencyID, ok := parseInt64ID(c, "agency_id")
if !ok {
return
}
var req agencyStatusRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Agency 状态参数不正确")
return
}
agency, err := h.service.SetAgencyStatus(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "set-agency-status", "agencies", agency.AgencyID,
fmt.Sprintf("command_id=%s agency_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), agency.AgencyID, agency.Status, strings.TrimSpace(req.Reason)))
response.OK(c, agency)
}
func (h *Handler) DeleteAgency(c *gin.Context) {
agencyID, ok := parseInt64ID(c, "agency_id")
if !ok {
return
}
var req agencyDeleteRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "删除 Agency 参数不正确")
return
}
agency, err := h.service.DeleteAgency(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "delete-agency", "agencies", agency.AgencyID,
fmt.Sprintf("command_id=%s agency_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), agency.AgencyID, agency.Status, strings.TrimSpace(req.Reason)))
response.OK(c, agency)
}
func (h *Handler) SetAgencyJoinEnabled(c *gin.Context) {
agencyID, ok := parseInt64ID(c, "agency_id")
if !ok {
return
}
var req agencyJoinEnabledRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.BadRequest(c, "Agency 入会开关参数不正确")
return
}
agency, err := h.service.SetAgencyJoinEnabled(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req)
if err != nil {
response.BadRequest(c, err.Error())
return
}
writeHostOrgAuditLog(c, h.audit, "set-agency-join-enabled", "agencies", agency.AgencyID,
fmt.Sprintf("command_id=%s agency_id=%d join_enabled=%t reason=%q", strings.TrimSpace(req.CommandID), agency.AgencyID, agency.JoinEnabled, strings.TrimSpace(req.Reason)))
response.OK(c, agency)
}
func adminActorID(c *gin.Context) int64 {
return int64(shared.ActorFromContext(c).UserID)
}
func parseInt64ID(c *gin.Context, name string) (int64, bool) {
id, ok := shared.ParseID(c, name)
if !ok {
return 0, false
}
return int64(id), true
}
func parseListQuery(c *gin.Context) (listQuery, bool) {
options := shared.ListOptions(c)
query := listQuery{
Page: options.Page,
PageSize: options.PageSize,
Keyword: options.Keyword,
UserFilter: shared.UserIdentityFilterFromQuery(c, ""),
OwnerFilter: shared.UserIdentityFilterFromQuery(c, "owner"),
ParentLeaderFilter: shared.UserIdentityFilterFromQuery(c, "parent_leader"),
ParentBDFilter: shared.UserIdentityFilterFromQuery(c, "parent_bd"),
Status: options.Status,
SortBy: firstNonBlank(c.Query("sortBy"), c.Query("sort_by")),
SortDirection: firstNonBlank(c.Query("sortDirection"), c.Query("sort_direction"), c.Query("order")),
}
var ok bool
if query.RegionID, ok = parseOptionalInt64Query(c, "regionId", "region_id"); !ok {
return listQuery{}, false
}
if query.AgencyID, ok = parseOptionalInt64Query(c, "agencyId", "agency_id"); !ok {
return listQuery{}, false
}
if query.ParentBDUserID, ok = parseOptionalInt64Query(c, "parentBdUserId", "parent_bd_user_id"); !ok {
return listQuery{}, false
}
if query.ParentLeaderUserID, ok = parseOptionalInt64Query(c, "parentLeaderUserId", "parent_leader_user_id"); !ok {
return listQuery{}, false
}
if query.ParentUserID, ok = parseOptionalInt64Query(c, "parentUserId", "parent_user_id"); !ok {
return listQuery{}, false
}
if query.TargetUserID, ok = parseOptionalInt64Query(c, "targetUserId", "target_user_id"); !ok {
return listQuery{}, false
}
return normalizeListQuery(query), true
}
func parseSalaryWalletHistoryQuery(c *gin.Context) (salaryWalletHistoryQuery, bool) {
options := shared.ListOptions(c)
userID, ok := parseOptionalInt64Query(c, "userId", "user_id")
if !ok {
return salaryWalletHistoryQuery{}, false
}
if userID <= 0 {
response.BadRequest(c, "user_id 参数不正确")
return salaryWalletHistoryQuery{}, false
}
query := salaryWalletHistoryQuery{
Page: options.Page,
PageSize: options.PageSize,
Role: c.Query("role"),
UserID: userID,
}
return normalizeSalaryWalletHistoryQuery(query), true
}
func parseOptionalInt64Query(c *gin.Context, primary string, fallback string) (int64, bool) {
raw := strings.TrimSpace(c.Query(primary))
if raw == "" {
raw = strings.TrimSpace(c.Query(fallback))
}
if raw == "" {
return 0, true
}
value, err := strconv.ParseInt(raw, 10, 64)
if err != nil || value < 0 {
response.BadRequest(c, primary+" 参数不正确")
return 0, false
}
return value, true
}
func writeHostOrgAuditLog(c *gin.Context, logger shared.OperationLogger, action string, resource string, resourceID int64, detail string) {
// HostOrg 的后台审计只能写 hyapp-admin-server 自己的 admin_operation_logs。
// user-service 只接收业务命令并维护关系事实,不能反向保存后台审计数据。
shared.OperationLogWithResourceID(c, logger, action, resource, fmt.Sprintf("%d", resourceID), "success", detail)
}