package model const ( UserStatusActive = "active" UserStatusLocked = "locked" UserStatusDisabled = "disabled" JobStatusPending = "pending" JobStatusRunning = "running" JobStatusSucceeded = "succeeded" JobStatusFailed = "failed" JobStatusCanceled = "canceled" ) type User struct { ID uint `gorm:"primaryKey" json:"id"` Username string `gorm:"size:64;uniqueIndex;not null" json:"account"` Name string `gorm:"size:80;not null" json:"name"` PasswordHash string `gorm:"size:255;not null" json:"-"` Team string `gorm:"size:80" json:"team"` Status string `gorm:"size:24;index;not null;default:active" json:"status"` MFAEnabled bool `gorm:"not null;default:false" json:"mfaEnabled"` LastLoginAtMS *int64 `gorm:"column:last_login_at_ms" json:"lastLoginAtMs"` Roles []Role `gorm:"many2many:admin_user_roles;" json:"roles"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (User) TableName() string { return "admin_users" } type Role struct { ID uint `gorm:"primaryKey" json:"id"` Name string `gorm:"size:80;uniqueIndex;not null" json:"name"` Code string `gorm:"size:80;uniqueIndex;not null" json:"code"` Description string `gorm:"size:255" json:"description"` Users []User `gorm:"many2many:admin_user_roles;" json:"-"` Permissions []Permission `gorm:"many2many:admin_role_permissions;" json:"permissions"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (Role) TableName() string { return "admin_roles" } type Permission struct { ID uint `gorm:"primaryKey" json:"id"` Name string `gorm:"size:100;not null" json:"name"` Code string `gorm:"size:100;uniqueIndex;not null" json:"code"` Kind string `gorm:"size:32;index;not null" json:"kind"` Description string `gorm:"size:255" json:"description"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (Permission) TableName() string { return "admin_permissions" } type Menu struct { ID uint `gorm:"primaryKey" json:"id"` ParentID *uint `gorm:"index" json:"parentId"` Title string `gorm:"size:80;not null" json:"label"` Code string `gorm:"size:100;uniqueIndex;not null" json:"code"` Path string `gorm:"size:160" json:"path"` Icon string `gorm:"size:64" json:"icon"` PermissionCode string `gorm:"size:100;index" json:"permissionCode"` Sort int `gorm:"not null;default:0" json:"sort"` Visible bool `gorm:"not null;default:true" json:"visible"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (Menu) TableName() string { return "admin_menus" } type AppConfig struct { ID uint `gorm:"primaryKey" json:"id"` Group string `gorm:"size:64;index:idx_admin_app_config_group_key,unique;not null" json:"group"` Key string `gorm:"size:100;index:idx_admin_app_config_group_key,unique;not null" json:"key"` Value string `gorm:"type:text" json:"value"` Description string `gorm:"size:255" json:"description"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (AppConfig) TableName() string { return "admin_app_configs" } type AppBanner struct { ID uint `gorm:"primaryKey" json:"id"` AppCode string `gorm:"size:32;index:idx_admin_app_banners_app_sort,not null;default:lalu" json:"appCode"` CoverURL string `gorm:"size:1024;not null" json:"coverUrl"` RoomSmallImageURL string `gorm:"column:room_small_image_url;size:1024;not null;default:'';comment:房间内小屏图 URL" json:"roomSmallImageUrl"` BannerType string `gorm:"size:16;not null" json:"bannerType"` DisplayScope string `gorm:"size:128;index:idx_admin_app_banners_display,not null;default:home;comment:显示范围,多选逗号分隔:首页、房间内或充值页" json:"displayScope"` Param string `gorm:"size:2048" json:"param"` Status string `gorm:"size:24;index:idx_admin_app_banners_app_sort,not null;default:active" json:"status"` Platform string `gorm:"size:24;index:idx_admin_app_banners_scope,not null" json:"platform"` SortOrder int `gorm:"index:idx_admin_app_banners_app_sort,not null;default:0" json:"sortOrder"` RegionID int64 `gorm:"index:idx_admin_app_banners_scope,not null;default:0" json:"regionId"` CountryCode string `gorm:"size:8;index:idx_admin_app_banners_scope" json:"countryCode"` Description string `gorm:"size:255" json:"description"` StartsAtMS int64 `gorm:"column:starts_at_ms;not null;default:0;comment:投放开始时间,UTC epoch ms" json:"startsAtMs"` EndsAtMS int64 `gorm:"column:ends_at_ms;not null;default:0;comment:投放结束时间,UTC epoch ms" json:"endsAtMs"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (AppBanner) TableName() string { return "admin_app_banners" } type AppSplashScreen struct { ID uint `gorm:"primaryKey" json:"id"` AppCode string `gorm:"size:32;index:idx_admin_app_splash_screens_app_sort,not null;default:lalu" json:"appCode"` CoverURL string `gorm:"size:1024;not null" json:"coverUrl"` SplashType string `gorm:"size:16;not null" json:"splashType"` Param string `gorm:"size:2048" json:"param"` Status string `gorm:"size:24;index:idx_admin_app_splash_screens_app_sort,not null;default:active" json:"status"` Platform string `gorm:"size:24;index:idx_admin_app_splash_screens_scope,not null" json:"platform"` SortOrder int `gorm:"index:idx_admin_app_splash_screens_app_sort,not null;default:0" json:"sortOrder"` RegionID int64 `gorm:"index:idx_admin_app_splash_screens_scope,not null;default:0" json:"regionId"` CountryCode string `gorm:"size:8;index:idx_admin_app_splash_screens_scope" json:"countryCode"` Description string `gorm:"size:255" json:"description"` DisplayDurationMS int `gorm:"column:display_duration_ms;not null;default:3000;comment:开屏展示时长,毫秒;0 表示客户端默认值" json:"displayDurationMs"` StartsAtMS int64 `gorm:"column:starts_at_ms;not null;default:0;comment:投放开始时间,UTC epoch ms" json:"startsAtMs"` EndsAtMS int64 `gorm:"column:ends_at_ms;not null;default:0;comment:投放结束时间,UTC epoch ms" json:"endsAtMs"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (AppSplashScreen) TableName() string { return "admin_app_splash_screens" } type AppVersion struct { ID uint `gorm:"primaryKey" json:"id"` AppCode string `gorm:"size:32;uniqueIndex:uk_admin_app_versions_build,not null;default:lalu" json:"appCode"` Platform string `gorm:"size:24;uniqueIndex:uk_admin_app_versions_build;index:idx_admin_app_versions_latest,not null" json:"platform"` Version string `gorm:"size:40;not null" json:"version"` BuildNumber int64 `gorm:"uniqueIndex:uk_admin_app_versions_build;index:idx_admin_app_versions_latest,not null" json:"buildNumber"` ForceUpdate bool `gorm:"not null;default:false" json:"forceUpdate"` DownloadURL string `gorm:"size:2048;not null" json:"downloadUrl"` Description string `gorm:"type:text" json:"description"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (AppVersion) TableName() string { return "admin_app_versions" } type AppExploreTab struct { ID uint `gorm:"primaryKey" json:"id"` AppCode string `gorm:"size:32;uniqueIndex:uk_admin_app_explore_tabs_tab;index:idx_admin_app_explore_tabs_app_sort,not null;default:lalu" json:"appCode"` Tab string `gorm:"size:80;uniqueIndex:uk_admin_app_explore_tabs_tab,not null" json:"tab"` H5URL string `gorm:"column:h5_url;size:2048;not null" json:"h5Url"` Enabled bool `gorm:"index:idx_admin_app_explore_tabs_app_sort,not null;default:true" json:"enabled"` SortOrder int `gorm:"index:idx_admin_app_explore_tabs_app_sort,not null;default:0" json:"sortOrder"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (AppExploreTab) TableName() string { return "admin_app_explore_tabs" } type HostAgencySalaryPolicy struct { ID uint `gorm:"primaryKey" json:"id"` AppCode string `gorm:"size:32;uniqueIndex:uk_admin_host_agency_salary_policy_name;index:idx_admin_host_agency_salary_policy_region,not null;default:lalu" json:"appCode"` Name string `gorm:"size:120;uniqueIndex:uk_admin_host_agency_salary_policy_name;not null" json:"name"` // RegionID 是第一阶段的政策适用边界;结算时按用户所属区域命中唯一 active 政策。 RegionID int64 `gorm:"uniqueIndex:uk_admin_host_agency_salary_policy_name;index:idx_admin_host_agency_salary_policy_region,not null" json:"regionId"` Status string `gorm:"size:24;index:idx_admin_host_agency_salary_policy_region,not null;default:disabled" json:"status"` // SettlementMode 只配置结算节奏,等级金额仍按累计值保存,实际发放由后续结算任务计算差额。 SettlementMode string `gorm:"size:24;not null;default:daily" json:"settlementMode"` // SettlementTriggerMode 区分自动任务与后台人工结算;手动政策发布后仍可被查询,但不会被 cron 自动发薪。 SettlementTriggerMode string `gorm:"column:settlement_trigger_mode;size:24;not null;default:automatic" json:"settlementTriggerMode"` // 比例字段使用 decimal 字符串承载,避免金币、钻石、美元换算出现 float 精度误差。 GiftCoinToDiamondRatio string `gorm:"column:gift_coin_to_diamond_ratio;type:decimal(18,6);not null;default:1.000000" json:"giftCoinToDiamondRatio"` ResidualDiamondToUSDRate string `gorm:"column:residual_diamond_to_usd_rate;type:decimal(24,12);not null;default:0.000000000000" json:"residualDiamondToUsdRate"` // 时间范围采用 epoch ms 半开区间,EffectiveToMS=0 表示长期有效。 EffectiveFromMS int64 `gorm:"column:effective_from_ms;index:idx_admin_host_agency_salary_policy_region,not null;default:0" json:"effectiveFromMs"` EffectiveToMS int64 `gorm:"column:effective_to_ms;not null;default:0" json:"effectiveToMs"` Description string `gorm:"size:255;not null;default:''" json:"description"` CreatedByAdminID uint `gorm:"column:created_by_admin_id;not null;default:0" json:"createdByAdminId"` UpdatedByAdminID uint `gorm:"column:updated_by_admin_id;not null;default:0" json:"updatedByAdminId"` // 发布字段只记录 admin 配置同步到 wallet 运行快照的结果;结算仍只读取 wallet-service 自己的运行表。 PublishStatus string `gorm:"column:publish_status;size:24;not null;default:draft" json:"publishStatus"` PublishError string `gorm:"column:publish_error;size:255;not null;default:''" json:"publishError"` PublishedAtMS int64 `gorm:"column:published_at_ms;not null;default:0" json:"publishedAtMs"` PublishedByAdminID uint `gorm:"column:published_by_admin_id;not null;default:0" json:"publishedByAdminId"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` Levels []HostAgencySalaryLevel `gorm:"foreignKey:PolicyID" json:"levels"` } func (HostAgencySalaryPolicy) TableName() string { return "admin_host_agency_salary_policies" } type HostAgencySalaryLevel struct { ID uint `gorm:"primaryKey" json:"id"` PolicyID uint `gorm:"uniqueIndex:uk_admin_host_agency_salary_level;index:idx_admin_host_agency_salary_level_policy,not null" json:"policyId"` // LevelNo 是累计工资差额结算的顺序锚点,必须在同一 policy 下唯一。 LevelNo int32 `gorm:"column:level_no;uniqueIndex:uk_admin_host_agency_salary_level;not null" json:"level"` // RequiredDiamonds 保存主播当月钻石门槛,月底清空逻辑不在 admin-server 第一阶段执行。 RequiredDiamonds int64 `gorm:"column:required_diamonds;index:idx_admin_host_agency_salary_level_policy,not null" json:"requiredDiamonds"` // 三个权益字段保存“达到该等级后的累计值”,结算任务只发本次等级与已结算等级之间的差额。 HostSalaryUSD string `gorm:"column:host_salary_usd;type:decimal(12,2);not null;default:0.00" json:"hostSalaryUsd"` HostCoinReward int64 `gorm:"column:host_coin_reward;not null;default:0" json:"hostCoinReward"` AgencySalaryUSD string `gorm:"column:agency_salary_usd;type:decimal(12,2);not null;default:0.00" json:"agencySalaryUsd"` Status string `gorm:"size:24;not null;default:active" json:"status"` SortOrder int32 `gorm:"column:sort_order;not null;default:0" json:"sortOrder"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (HostAgencySalaryLevel) TableName() string { return "admin_host_agency_salary_policy_levels" } type TeamSalaryPolicy struct { ID uint `gorm:"primaryKey" json:"id"` AppCode string `gorm:"size:32;uniqueIndex:uk_admin_team_salary_policy_name;index:idx_admin_team_salary_policy_scope,not null;default:lalu" json:"appCode"` // PolicyType 当前只允许 bd/admin;拆表会让两类策略后续结算扩展变重,所以用类型字段保持同一套配置 API。 PolicyType string `gorm:"column:policy_type;size:24;uniqueIndex:uk_admin_team_salary_policy_name;index:idx_admin_team_salary_policy_scope,not null" json:"policyType"` Name string `gorm:"size:120;uniqueIndex:uk_admin_team_salary_policy_name;not null" json:"name"` // RegionID 沿用 Host 政策的区域边界,保证同一区域组织链路可以命中同一套工资配置。 RegionID int64 `gorm:"uniqueIndex:uk_admin_team_salary_policy_name;index:idx_admin_team_salary_policy_scope,not null" json:"regionId"` Status string `gorm:"size:24;index:idx_admin_team_salary_policy_scope,not null;default:disabled" json:"status"` // SettlementTriggerMode 决定次月 5 日窗口由自动任务处理还是进入后台人工批量结算池。 SettlementTriggerMode string `gorm:"column:settlement_trigger_mode;size:24;not null;default:automatic" json:"settlementTriggerMode"` // BD/Admin 都按完整自然月统计,结算日期固定为次月 5 日;这里不再提供日结/半月结节奏字段。 EffectiveFromMS int64 `gorm:"column:effective_from_ms;index:idx_admin_team_salary_policy_scope,not null;default:0" json:"effectiveFromMs"` EffectiveToMS int64 `gorm:"column:effective_to_ms;not null;default:0" json:"effectiveToMs"` Description string `gorm:"size:255;not null;default:''" json:"description"` CreatedByAdminID uint `gorm:"column:created_by_admin_id;not null;default:0" json:"createdByAdminId"` UpdatedByAdminID uint `gorm:"column:updated_by_admin_id;not null;default:0" json:"updatedByAdminId"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` Levels []TeamSalaryLevel `gorm:"foreignKey:PolicyID" json:"levels"` } func (TeamSalaryPolicy) TableName() string { return "admin_team_salary_policies" } type TeamSalaryLevel struct { ID uint `gorm:"primaryKey" json:"id"` PolicyID uint `gorm:"uniqueIndex:uk_admin_team_salary_level;index:idx_admin_team_salary_level_policy,not null" json:"policyId"` // LevelNo 是差额结算锚点,当前等级累计工资减去已结算累计工资就是本次应发金额。 LevelNo int32 `gorm:"column:level_no;uniqueIndex:uk_admin_team_salary_level;not null" json:"level"` // ThresholdUSD 对 BD 表示下属 Agency 管理主播 Host Salary 合计门槛,对 Admin 表示下属 BD Salary 合计门槛。 ThresholdUSD string `gorm:"column:threshold_usd;type:decimal(12,2);index:idx_admin_team_salary_level_policy,not null;default:0.00" json:"thresholdUsd"` // RatePercent 保存运营看到的百分比数字,例如 8 表示 8%,结算时再换算成比例。 RatePercent string `gorm:"column:rate_percent;type:decimal(9,4);not null;default:0.0000" json:"ratePercent"` // SalaryUSD 是达到该等级后的累计应得工资,实际入账仍按差额结算。 SalaryUSD string `gorm:"column:salary_usd;type:decimal(12,2);not null;default:0.00" json:"salaryUsd"` Status string `gorm:"size:24;not null;default:active" json:"status"` SortOrder int32 `gorm:"column:sort_order;not null;default:0" json:"sortOrder"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (TeamSalaryLevel) TableName() string { return "admin_team_salary_policy_levels" } type RefreshToken struct { ID uint `gorm:"primaryKey" json:"id"` UserID uint `gorm:"index;not null" json:"userId"` TokenHash string `gorm:"size:128;uniqueIndex;not null" json:"-"` UserAgent string `gorm:"size:255" json:"userAgent"` IP string `gorm:"size:64" json:"ip"` ExpiresAtMS int64 `gorm:"column:expires_at_ms;index;not null" json:"expiresAtMs"` RevokedAtMS *int64 `gorm:"column:revoked_at_ms" json:"revokedAtMs"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (RefreshToken) TableName() string { return "admin_refresh_tokens" } type LoginLog struct { ID uint `gorm:"primaryKey" json:"id"` Username string `gorm:"size:64;index" json:"username"` UserID *uint `gorm:"index" json:"userId"` IP string `gorm:"size:64" json:"ip"` UserAgent string `gorm:"size:255" json:"userAgent"` Status string `gorm:"size:32;index;not null" json:"status"` Message string `gorm:"size:255" json:"message"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` } func (LoginLog) TableName() string { return "admin_login_logs" } type OperationLog struct { ID uint `gorm:"primaryKey" json:"id"` RequestID string `gorm:"size:64;index;not null;default:''" json:"requestId"` UserID uint `gorm:"index;not null" json:"userId"` Username string `gorm:"size:64;index;not null" json:"username"` Action string `gorm:"size:80;index;not null" json:"action"` Resource string `gorm:"size:120;index" json:"resource"` ResourceID string `gorm:"size:80;index;not null;default:''" json:"resourceId"` Method string `gorm:"size:12" json:"method"` Path string `gorm:"size:180" json:"path"` IP string `gorm:"size:64" json:"ip"` UserAgent string `gorm:"size:255;not null;default:''" json:"userAgent"` Status string `gorm:"size:32;index;not null" json:"status"` HTTPStatus int `gorm:"not null;default:0" json:"httpStatus"` RiskLevel string `gorm:"size:24;index;not null;default:normal" json:"riskLevel"` LatencyMS int64 `gorm:"not null;default:0" json:"latencyMs"` Detail string `gorm:"type:text" json:"detail"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` } func (OperationLog) TableName() string { return "admin_operation_logs" } type DataScope struct { ID uint `gorm:"primaryKey" json:"id"` RoleID uint `gorm:"index;not null" json:"roleId"` ScopeType string `gorm:"size:40;index;not null" json:"scopeType"` ScopeValue string `gorm:"size:120;index;not null" json:"scopeValue"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (DataScope) TableName() string { return "admin_data_scopes" } type AdminJob struct { ID uint `gorm:"primaryKey" json:"id"` Type string `gorm:"size:80;index;not null" json:"type"` Status string `gorm:"size:32;index;not null" json:"status"` PayloadJSON string `gorm:"type:text" json:"payload"` ResultJSON string `gorm:"type:text" json:"result"` Error string `gorm:"type:text" json:"error"` Attempt int `gorm:"not null;default:0" json:"attempt"` MaxAttempts int `gorm:"not null;default:3" json:"maxAttempts"` LockedBy string `gorm:"size:120;index;not null;default:''" json:"lockedBy"` LockedUntilMS *int64 `gorm:"column:locked_until_ms;index" json:"lockedUntilMs"` ArtifactPath string `gorm:"size:255;not null;default:''" json:"artifactPath"` CreatedBy uint `gorm:"index;not null" json:"createdBy"` CreatedByName string `gorm:"size:64;index;not null" json:"createdByName"` StartedAtMS *int64 `gorm:"column:started_at_ms" json:"startedAtMs"` FinishedAtMS *int64 `gorm:"column:finished_at_ms" json:"finishedAtMs"` CreatedAtMS int64 `gorm:"column:created_at_ms;autoCreateTime:milli" json:"createdAtMs"` UpdatedAtMS int64 `gorm:"column:updated_at_ms;autoUpdateTime:milli" json:"updatedAtMs"` } func (AdminJob) TableName() string { return "admin_jobs" }