feat():learning后台管理项目初始化
This commit is contained in:
114
internal/models/audit_log.go
Normal file
114
internal/models/audit_log.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 操作类型常量
|
||||
const (
|
||||
OperationTypeBalanceAdjustment = "balance_adjustment" // 余额调整
|
||||
OperationTypeUserLevelChange = "user_level_change" // 用户等级修改
|
||||
OperationTypeUserStatusChange = "user_status_change" // 用户状态变更
|
||||
OperationTypeModelPriceChange = "model_price_change" // 模型价格修改
|
||||
OperationTypePermissionChange = "permission_change" // 权限变更
|
||||
OperationTypeConfigChange = "config_change" // 配置修改
|
||||
)
|
||||
|
||||
// 操作状态常量
|
||||
const (
|
||||
AuditLogStatusSuccess = "success" // 成功
|
||||
AuditLogStatusFailed = "failed" // 失败
|
||||
)
|
||||
|
||||
// 操作对象类型常量
|
||||
const (
|
||||
TargetTypeUser = "user" // 用户
|
||||
TargetTypeModel = "model" // 模型
|
||||
TargetTypeConfig = "config" // 配置
|
||||
)
|
||||
|
||||
// OperationDetails 操作详情JSON结构
|
||||
type OperationDetails map[string]interface{}
|
||||
|
||||
// Value 实现 driver.Valuer 接口
|
||||
func (d OperationDetails) Value() (driver.Value, error) {
|
||||
if d == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return json.Marshal(d)
|
||||
}
|
||||
|
||||
// Scan 实现 sql.Scanner 接口
|
||||
func (d *OperationDetails) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
*d = nil
|
||||
return nil
|
||||
}
|
||||
bytes, ok := value.([]byte)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(bytes, d)
|
||||
}
|
||||
|
||||
// AuditLog 审计日志模型
|
||||
type AuditLog struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;autoIncrement;comment:主键ID"`
|
||||
OperationType string `json:"operation_type" gorm:"type:varchar(50);not null;index:idx_operation_type_time;comment:操作类型"`
|
||||
OperationTime time.Time `json:"operation_time" gorm:"not null;index:idx_operation_type_time;index:idx_operation_time;comment:操作时间"`
|
||||
OperatorID int `json:"operator_id" gorm:"not null;index:idx_operator_time;comment:操作人ID"`
|
||||
OperatorEmail string `json:"operator_email" gorm:"type:varchar(255);not null;index:idx_operator_email;comment:操作人邮箱"`
|
||||
TargetType string `json:"target_type" gorm:"type:varchar(50);comment:操作对象类型"`
|
||||
TargetID *int `json:"target_id" gorm:"comment:操作对象ID"`
|
||||
TargetEmail string `json:"target_email" gorm:"type:varchar(255);index:idx_target_email;comment:操作对象邮箱"`
|
||||
OperationDetails OperationDetails `json:"operation_details" gorm:"type:json;comment:操作详情JSON"`
|
||||
IPAddress string `json:"ip_address" gorm:"type:varchar(45);comment:操作来源IP地址"`
|
||||
UserAgent string `json:"user_agent" gorm:"type:varchar(500);comment:用户代理"`
|
||||
Status string `json:"status" gorm:"type:varchar(20);default:'success';comment:操作状态"`
|
||||
ErrorMessage string `json:"error_message" gorm:"type:text;comment:错误信息"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"not null;comment:记录创建时间"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"not null;comment:记录更新时间"`
|
||||
}
|
||||
|
||||
// TableName 指定数据库表名
|
||||
func (AuditLog) TableName() string {
|
||||
return "admin_audit_logs"
|
||||
}
|
||||
|
||||
// AuditLogListRequest 审计日志列表请求
|
||||
type AuditLogListRequest struct {
|
||||
OperationType string `form:"operation_type"` // 操作类型筛选
|
||||
OperatorEmail string `form:"operator_email"` // 操作人筛选
|
||||
TargetEmail string `form:"target_email"` // 操作对象搜索(模糊匹配)
|
||||
StartTime string `form:"start_time"` // 开始时间
|
||||
EndTime string `form:"end_time"` // 结束时间
|
||||
Page int `form:"page,default=1"` // 页码
|
||||
Size int `form:"size,default=20"` // 每页数量
|
||||
SortBy string `form:"sort_by"` // 排序字段,默认:operation_time
|
||||
SortOrder string `form:"sort_order"` // 排序方向,desc/asc,默认:desc
|
||||
}
|
||||
|
||||
// AuditLogListResponse 审计日志列表响应
|
||||
type AuditLogListResponse struct {
|
||||
List []AuditLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
Page int `json:"page"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
// CreateAuditLogRequest 创建审计日志请求(内部使用)
|
||||
type CreateAuditLogRequest struct {
|
||||
OperationType string `json:"operation_type" binding:"required"`
|
||||
OperatorID int `json:"operator_id" binding:"required"`
|
||||
OperatorEmail string `json:"operator_email" binding:"required"`
|
||||
TargetType string `json:"target_type"`
|
||||
TargetID *int `json:"target_id"`
|
||||
TargetEmail string `json:"target_email"`
|
||||
OperationDetails OperationDetails `json:"operation_details"`
|
||||
IPAddress string `json:"ip_address"`
|
||||
UserAgent string `json:"user_agent"`
|
||||
Status string `json:"status"`
|
||||
ErrorMessage string `json:"error_message"`
|
||||
}
|
||||
28
internal/models/balance_operation_log.go
Normal file
28
internal/models/balance_operation_log.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// 操作类型常量
|
||||
const (
|
||||
OperationTypeAdd = "add"
|
||||
OperationTypeDeduct = "deduct"
|
||||
)
|
||||
|
||||
// BalanceOperationLog 余额操作日志
|
||||
type BalanceOperationLog struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;autoIncrement;comment:主键ID"`
|
||||
UserID int `json:"user_id" gorm:"not null;index:idx_user_id;comment:GoalfyMax用户ID"`
|
||||
OperationType string `json:"operation_type" gorm:"type:varchar(10);not null;comment:操作类型:add/deduct"`
|
||||
Amount float64 `json:"amount" gorm:"type:decimal(15,2);not null;comment:操作金额(美元)"`
|
||||
BalanceBefore float64 `json:"balance_before" gorm:"type:decimal(15,2);not null;comment:操作前余额(美元)"`
|
||||
BalanceAfter float64 `json:"balance_after" gorm:"type:decimal(15,2);not null;comment:操作后余额(美元)"`
|
||||
OperatorID int `json:"operator_id" gorm:"not null;index:idx_operator_id;comment:操作者ID"`
|
||||
OperatorName string `json:"operator_name" gorm:"type:varchar(50);comment:操作者名称"`
|
||||
Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"not null;index:idx_created_at;comment:创建时间"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"not null;comment:更新时间"`
|
||||
}
|
||||
|
||||
func (BalanceOperationLog) TableName() string {
|
||||
return "balance_operation_logs"
|
||||
}
|
||||
104
internal/models/common.go
Normal file
104
internal/models/common.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// BaseModel 基础模型,包含公共字段
|
||||
type BaseModel struct {
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"deletedAt,omitempty"`
|
||||
}
|
||||
|
||||
// User 用户模型
|
||||
type User struct {
|
||||
BaseModel
|
||||
Username string `gorm:"uniqueIndex;size:50;not null" json:"username"`
|
||||
Email string `gorm:"uniqueIndex;size:100;not null" json:"email"`
|
||||
Nickname string `gorm:"size:50" json:"nickname"`
|
||||
Avatar string `gorm:"size:255" json:"avatar"`
|
||||
Status int `gorm:"default:1;comment:状态 1:正常 0:禁用" json:"status"`
|
||||
SSOProvider string `gorm:"size:50;not null;comment:SSO提供商" json:"ssoProvider"`
|
||||
LastLoginAt *time.Time `gorm:"comment:最后登录时间" json:"lastLoginAt"`
|
||||
LoginCount int `gorm:"default:0;comment:登录次数" json:"loginCount"`
|
||||
RoleID uint `gorm:"not null;default:0;comment:角色ID" json:"roleId"`
|
||||
}
|
||||
|
||||
// UserWithRoles 带角色信息的用户模型
|
||||
type UserWithRoles struct {
|
||||
User
|
||||
Role *Role `json:"role,omitempty"`
|
||||
}
|
||||
|
||||
// Role 角色模型
|
||||
type Role struct {
|
||||
BaseModel
|
||||
Name string `gorm:"uniqueIndex;size:50;not null" json:"name"`
|
||||
Level int `gorm:"uniqueIndex;not null" json:"level"`
|
||||
Description string `gorm:"type:text" json:"description"`
|
||||
IsDefault bool `gorm:"default:false" json:"isDefault"`
|
||||
}
|
||||
|
||||
// SystemConfig 系统配置模型
|
||||
type SystemConfig struct {
|
||||
BaseModel
|
||||
Key string `gorm:"uniqueIndex;size:100;not null" json:"key"`
|
||||
Name string `gorm:"size:100;not null" json:"name"`
|
||||
Value string `gorm:"type:text" json:"value"`
|
||||
Type string `gorm:"size:20;default:string" json:"type"` // string, int, bool, json
|
||||
Desc string `gorm:"size:255" json:"desc"`
|
||||
Status int `gorm:"default:1" json:"status"` // 1:启用 0:禁用
|
||||
}
|
||||
|
||||
// LoginLog 登录日志模型
|
||||
type LoginLog struct {
|
||||
BaseModel
|
||||
UserID uint `gorm:"not null" json:"userId"`
|
||||
Username string `gorm:"size:50;not null" json:"username"`
|
||||
IP string `gorm:"size:45" json:"ip"`
|
||||
UserAgent string `gorm:"size:500" json:"userAgent"`
|
||||
Status int `gorm:"default:1" json:"status"` // 1:成功 0:失败
|
||||
Message string `gorm:"size:255" json:"message"`
|
||||
}
|
||||
|
||||
// OperationLog 操作日志模型
|
||||
type OperationLog struct {
|
||||
BaseModel
|
||||
UserID uint `gorm:"not null" json:"userId"`
|
||||
Username string `gorm:"size:50;not null" json:"username"`
|
||||
Module string `gorm:"size:50" json:"module"`
|
||||
Operation string `gorm:"size:50" json:"operation"`
|
||||
Method string `gorm:"size:10" json:"method"`
|
||||
Path string `gorm:"size:255" json:"path"`
|
||||
IP string `gorm:"size:45" json:"ip"`
|
||||
UserAgent string `gorm:"size:500" json:"userAgent"`
|
||||
Request string `gorm:"type:text" json:"request"`
|
||||
Response string `gorm:"type:text" json:"response"`
|
||||
Status int `gorm:"default:1" json:"status"`
|
||||
Duration int64 `json:"duration"` // 毫秒
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (User) TableName() string {
|
||||
return "admin_users"
|
||||
}
|
||||
|
||||
func (Role) TableName() string {
|
||||
return "admin_roles"
|
||||
}
|
||||
|
||||
func (SystemConfig) TableName() string {
|
||||
return "admin_system_configs"
|
||||
}
|
||||
|
||||
func (LoginLog) TableName() string {
|
||||
return "admin_login_logs"
|
||||
}
|
||||
|
||||
func (OperationLog) TableName() string {
|
||||
return "admin_operation_logs"
|
||||
}
|
||||
80
internal/models/goalfymax_user.go
Normal file
80
internal/models/goalfymax_user.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// GoalfyMaxUser 对应 admin_goalfymax_users 表
|
||||
type GoalfyMaxUser struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;autoIncrement;comment:主键ID"`
|
||||
UserID int `json:"user_id" gorm:"not null;uniqueIndex:uk_user_id;comment:SSO用户ID"`
|
||||
Username string `json:"username" gorm:"not null;type:varchar(50);comment:用户名"`
|
||||
Email string `json:"email" gorm:"not null;type:varchar(100);comment:邮箱"`
|
||||
Nickname string `json:"nickname" gorm:"type:varchar(50);comment:昵称"`
|
||||
Avatar string `json:"avatar" gorm:"type:varchar(255);comment:头像URL"`
|
||||
UserLevelCode string `json:"user_level_code" gorm:"type:varchar(50);default:'normal';comment:用户等级代码"`
|
||||
IsBanned bool `json:"is_banned" gorm:"not null;default:false;comment:是否被封禁"`
|
||||
BanReason string `json:"ban_reason" gorm:"type:varchar(255);comment:封禁原因"`
|
||||
BannedAt *time.Time `json:"banned_at" gorm:"comment:封禁时间"`
|
||||
BannedBy int `json:"banned_by" gorm:"comment:封禁操作者ID"`
|
||||
LastLoginAt *time.Time `json:"last_login_at" gorm:"comment:最后登录时间"`
|
||||
GoalfyHubPermission int `json:"goalfy_hub_permission" gorm:"default:0;comment:是否具备GoalfyHub权限 (0: 不具备, 1: 具备)"`
|
||||
Version int `json:"version" gorm:"default:1;comment:1:用户版 2:观察版 3:用户版和观察版"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt *time.Time `json:"-" gorm:"default:null"`
|
||||
// Balance 用户余额(美元),从Redis查询,不存储在数据库中
|
||||
Balance *float64 `json:"balance,omitempty" gorm:"-"`
|
||||
}
|
||||
|
||||
func (GoalfyMaxUser) TableName() string {
|
||||
return "admin_goalfymax_users"
|
||||
}
|
||||
|
||||
// 列表请求
|
||||
type GoalfyMaxUserListRequest struct {
|
||||
Username string `form:"username"`
|
||||
Email string `form:"email"`
|
||||
Status *int `form:"status"` // 1 正常 0 封禁(映射到 IsBanned)
|
||||
Page int `form:"page,default=1"`
|
||||
Size int `form:"size,default=20"`
|
||||
}
|
||||
|
||||
// 更新请求
|
||||
type GoalfyMaxUserUpdateRequest struct {
|
||||
Nickname string `json:"nickname"`
|
||||
Email string `json:"email"`
|
||||
Avatar string `json:"avatar"`
|
||||
UserLevelCode string `json:"user_level_code"`
|
||||
Version *int `json:"version"` // 版本:1-用户版 2-观察版 3-用户版和观察版
|
||||
GoalfyHubPermission *int `json:"goalfy_hub_permission"`
|
||||
}
|
||||
|
||||
// 封禁请求
|
||||
type GoalfyMaxUserBanRequest struct {
|
||||
Reason string `json:"reason" binding:"required"`
|
||||
}
|
||||
|
||||
// 增加余额请求
|
||||
type GoalfyMaxUserAddBalanceRequest struct {
|
||||
Amount float64 `json:"amount" binding:"required,gt=0"` // 美元金额,必须大于0
|
||||
}
|
||||
|
||||
// 新增用户请求
|
||||
type GoalfyMaxUserCreateRequest struct {
|
||||
Username string `json:"username" binding:"required,min=3,max=50"`
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Password string `json:"password" binding:"required,min=8"`
|
||||
Nickname string `json:"nickname"`
|
||||
Avatar string `json:"avatar"`
|
||||
UserLevelCode string `json:"user_level_code"` // 默认为 normal
|
||||
Version int `json:"version"` // 版本:1-用户版 2-观察版 3-用户版和观察版,默认为1
|
||||
}
|
||||
|
||||
// 新增用户请求(支持字符串输入)
|
||||
type GoalfyMaxUserCreateRequestString struct {
|
||||
Username string `json:"username" binding:"required,min=3,max=50"`
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Phone string `json:"phone"`
|
||||
Password string `json:"password"`
|
||||
Nickname string `json:"nickname"`
|
||||
Avatar string `json:"avatar"`
|
||||
}
|
||||
65
internal/models/invite_code.go
Normal file
65
internal/models/invite_code.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// InviteCode 简化版邀请码模型
|
||||
type InviteCode struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;autoIncrement;comment:主键ID"`
|
||||
Code string `json:"code" gorm:"not null;type:varchar(64);uniqueIndex;comment:邀请码"`
|
||||
IsUsed bool `json:"is_used" gorm:"not null;default:0;type:tinyint(1);comment:是否已使用"`
|
||||
ClientID string `json:"client_id" gorm:"type:varchar(64);comment:客户端ID"`
|
||||
Email string `json:"email" gorm:"type:varchar(255);comment:关联邮箱"`
|
||||
UserLevelID *uint `json:"user_level_id" gorm:"type:BIGINT;comment:用户等级ID"`
|
||||
ExpiresAt *time.Time `json:"expires_at" gorm:"comment:过期时间"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"not null;comment:创建时间"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index;comment:软删除时间"`
|
||||
}
|
||||
|
||||
// TableName 指定数据库表名
|
||||
func (InviteCode) TableName() string {
|
||||
return "admin_invite_codes"
|
||||
}
|
||||
|
||||
// 列表请求(简化)
|
||||
type InviteCodeListRequest struct {
|
||||
Code string `form:"code"`
|
||||
IsUsed *bool `form:"is_used"`
|
||||
StartTime string `form:"start_time"`
|
||||
EndTime string `form:"end_time"`
|
||||
Page int `form:"page,default=1"`
|
||||
Size int `form:"size,default=20"`
|
||||
}
|
||||
|
||||
// 创建请求(支持设置过期时间)
|
||||
type InviteCodeCreateRequest struct {
|
||||
Emails []string `json:"emails" form:"emails"` // 邮箱列表,可选
|
||||
UserLevelID *uint `json:"user_level_id" form:"user_level_id"` // 用户等级ID,可选
|
||||
ExpiresAt *time.Time `json:"expires_at" form:"expires_at"` // 过期时间,可选
|
||||
ClientID string `json:"client_id" form:"client_id"` // 客户端ID,可选(保留向后兼容)
|
||||
}
|
||||
|
||||
// 更新请求(支持更新过期时间)
|
||||
type InviteCodeUpdateRequest struct {
|
||||
ClientID string `json:"client_id" form:"client_id"` // 客户端ID,可选
|
||||
Email string `json:"email" form:"email"` // 邮箱,可选
|
||||
UserLevelID *uint `json:"user_level_id" form:"user_level_id"` // 用户等级ID,可选
|
||||
ExpiresAt *time.Time `json:"expires_at" form:"expires_at"` // 过期时间,可选
|
||||
}
|
||||
|
||||
// 统计响应(简化,可选)
|
||||
type InviteCodeStatistics struct {
|
||||
Total int `json:"total"`
|
||||
Used int `json:"used"`
|
||||
Unused int `json:"unused"`
|
||||
TodayCreated int `json:"today_created"`
|
||||
}
|
||||
|
||||
// 列表响应
|
||||
type InviteCodeListResponse struct {
|
||||
List []InviteCode `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
92
internal/models/invite_code_application.go
Normal file
92
internal/models/invite_code_application.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// InviteCodeApplication 邀请码申请模型
|
||||
type InviteCodeApplication struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;autoIncrement;comment:主键ID"`
|
||||
Email string `json:"email" gorm:"not null;type:varchar(255);index;comment:申请邮箱"`
|
||||
Reason string `json:"reason" gorm:"type:text;comment:申请理由"`
|
||||
Language string `json:"language" gorm:"type:varchar(10);default:'zh';comment:语言:zh-中文,en-英文"`
|
||||
Status string `json:"status" gorm:"not null;type:varchar(20);default:'pending';index;comment:申请状态:pending-待处理,approved-已通过,rejected-已拒绝"`
|
||||
InviteCodeID *uint `json:"invite_code_id" gorm:"comment:关联的邀请码ID"`
|
||||
InviteCode *InviteCode `json:"invite_code" gorm:"foreignKey:InviteCodeID;constraint:OnDelete:SET NULL;-:migration"`
|
||||
RejectReason string `json:"reject_reason" gorm:"type:text;comment:拒绝理由"`
|
||||
ApprovedAt *time.Time `json:"approved_at" gorm:"comment:审批时间"`
|
||||
ApprovedBy string `json:"approved_by" gorm:"type:varchar(64);comment:审批人"`
|
||||
EmailSentAt *time.Time `json:"email_sent_at" gorm:"comment:邮件发送时间"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"not null;comment:创建时间"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"not null;comment:更新时间"`
|
||||
DeletedAt gorm.DeletedAt `json:"-" gorm:"index;comment:软删除时间"`
|
||||
}
|
||||
|
||||
// TableName 指定数据库表名
|
||||
func (InviteCodeApplication) TableName() string {
|
||||
return "admin_invite_code_applications"
|
||||
}
|
||||
|
||||
// InviteCodeApplicationListRequest 申请列表请求
|
||||
type InviteCodeApplicationListRequest struct {
|
||||
Email string `form:"email"`
|
||||
Status string `form:"status"` // pending, approved, rejected
|
||||
StartTime string `form:"start_time"`
|
||||
EndTime string `form:"end_time"`
|
||||
Page int `form:"page,default=1"`
|
||||
Size int `form:"size,default=20"`
|
||||
}
|
||||
|
||||
// InviteCodeApplicationCreateRequest 创建申请请求(官网提交)
|
||||
type InviteCodeApplicationCreateRequest struct {
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Reason string `json:"reason"`
|
||||
Language string `json:"language"` // zh 或 en,默认 zh
|
||||
}
|
||||
|
||||
// InviteCodeApplicationApproveRequest 审批通过请求
|
||||
type InviteCodeApplicationApproveRequest struct {
|
||||
ApplicationID uint `json:"application_id" binding:"required"`
|
||||
ValidDays int `json:"valid_days"` // 有效期天数,默认7天
|
||||
}
|
||||
|
||||
// InviteCodeApplicationRejectRequest 审批拒绝请求
|
||||
type InviteCodeApplicationRejectRequest struct {
|
||||
ApplicationID uint `json:"application_id" binding:"required"`
|
||||
RejectReason string `json:"reject_reason"`
|
||||
}
|
||||
|
||||
// InviteCodeApplicationBatchApproveRequest 批量审批通过请求
|
||||
type InviteCodeApplicationBatchApproveRequest struct {
|
||||
ApplicationIDs []uint `json:"application_ids" binding:"required"`
|
||||
ValidDays int `json:"valid_days"` // 有效期天数,默认7天
|
||||
}
|
||||
|
||||
// InviteCodeApplicationBatchRejectRequest 批量审批拒绝请求
|
||||
type InviteCodeApplicationBatchRejectRequest struct {
|
||||
ApplicationIDs []uint `json:"application_ids" binding:"required"`
|
||||
RejectReason string `json:"reject_reason"`
|
||||
}
|
||||
|
||||
// InviteCodeApplicationListResponse 申请列表响应
|
||||
type InviteCodeApplicationListResponse struct {
|
||||
List []InviteCodeApplication `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
// InviteCodeApplicationStatistics 申请统计
|
||||
type InviteCodeApplicationStatistics struct {
|
||||
TotalPending int `json:"total_pending"` // 待处理数量
|
||||
TotalApproved int `json:"total_approved"` // 已通过数量
|
||||
TotalRejected int `json:"total_rejected"` // 已拒绝数量
|
||||
TodayApplied int `json:"today_applied"` // 今日申请数量
|
||||
}
|
||||
|
||||
// 申请状态常量
|
||||
const (
|
||||
ApplicationStatusPending = "pending"
|
||||
ApplicationStatusApproved = "approved"
|
||||
ApplicationStatusRejected = "rejected"
|
||||
)
|
||||
78
internal/models/message_push.go
Normal file
78
internal/models/message_push.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// MessagePushLog 消息推送记录模型
|
||||
type MessagePushLog struct {
|
||||
ID int64 `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||
Title string `gorm:"type:varchar(255);not null;default:'';comment:消息标题" json:"title"`
|
||||
Content string `gorm:"type:text;not null;comment:消息内容" json:"content"`
|
||||
TargetUsers string `gorm:"type:json;not null;comment:目标用户ID列表" json:"target_users"` // 存储JSON字符串
|
||||
SenderID int `gorm:"not null;comment:发送人ID" json:"sender_id"`
|
||||
SenderName string `gorm:"type:varchar(100);not null;comment:发送人姓名" json:"sender_name"`
|
||||
Status int `gorm:"type:tinyint;default:0;comment:发送状态 0=待发送 1=发送中 2=发送成功 3=发送失败" json:"status"`
|
||||
SuccessCount int `gorm:"default:0;comment:成功数量" json:"success_count"`
|
||||
FailCount int `gorm:"default:0;comment:失败数量" json:"fail_count"`
|
||||
ErrorMessage string `gorm:"type:text;comment:错误信息" json:"error_message"`
|
||||
SentAt *time.Time `gorm:"comment:发送时间" json:"sent_at"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
||||
}
|
||||
|
||||
// TableName 指定数据库表名
|
||||
func (MessagePushLog) TableName() string {
|
||||
return "admin_message_push_logs"
|
||||
}
|
||||
|
||||
// MessagePushRequest 消息推送请求
|
||||
type MessagePushRequest struct {
|
||||
Title string `json:"title" validate:"required,min=1,max=100"`
|
||||
Content string `json:"content" validate:"required,min=1,max=2000"`
|
||||
UserIDs []int `json:"user_ids" validate:"required,min=1"`
|
||||
}
|
||||
|
||||
// MessagePushResponse 消息推送响应
|
||||
type MessagePushResponse struct {
|
||||
LogID int64 `json:"log_id"`
|
||||
SuccessCount int `json:"success_count"`
|
||||
FailCount int `json:"fail_count"`
|
||||
}
|
||||
|
||||
// MessagePushListRequest 推送记录列表请求
|
||||
type MessagePushListRequest struct {
|
||||
Page int `form:"page,default=1"`
|
||||
PageSize int `form:"page_size,default=10"`
|
||||
Status *int `form:"status"` // 0=待发送, 1=发送中, 2=发送成功, 3=发送失败
|
||||
SenderID *int `form:"sender_id"`
|
||||
StartTime string `form:"start_time"`
|
||||
EndTime string `form:"end_time"`
|
||||
}
|
||||
|
||||
// MessagePushListResponse 推送记录列表响应
|
||||
type MessagePushListResponse struct {
|
||||
List []MessagePushLog `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
}
|
||||
|
||||
// UserSearchRequest 用户搜索请求
|
||||
type UserSearchRequest struct {
|
||||
Keyword string `form:"keyword" validate:"required,min=1"`
|
||||
Limit int `form:"limit,default=20"`
|
||||
}
|
||||
|
||||
// UserSearchResponse 用户搜索响应
|
||||
type UserSearchResponse struct {
|
||||
Users []UserSearchItem `json:"users"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
// UserSearchItem 用户搜索项
|
||||
type UserSearchItem struct {
|
||||
ID int `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
65
internal/models/quota_models.go
Normal file
65
internal/models/quota_models.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// QuotaHistoryRequest 配额历史查询请求
|
||||
type QuotaHistoryRequest struct {
|
||||
StartDate string `json:"start_date" binding:"required"` // 开始日期 (YYYY-MM-DD)
|
||||
EndDate string `json:"end_date" binding:"required"` // 结束日期 (YYYY-MM-DD)
|
||||
UserID string `json:"user_id"` // 用户ID (可选)
|
||||
ApiGroup string `json:"api_group"` // API组 (可选)
|
||||
ProjectID string `json:"project_id"` // 项目ID (可选)
|
||||
Period string `json:"period"` // 周期: daily, monthly
|
||||
GroupBy []string `json:"group_by"` // 分组维度
|
||||
}
|
||||
|
||||
// QuotaHistoryItem 配额历史数据项
|
||||
//
|
||||
// type QuotaHistoryItem struct {
|
||||
// ID uint `json:"id"`
|
||||
// UserID string `json:"user_id"`
|
||||
// ApiGroup string `json:"api_group"`
|
||||
// ProjectID string `json:"project_id"`
|
||||
// Day string `json:"day"`
|
||||
// Account string `json:"account"`
|
||||
// Model string `json:"model"`
|
||||
// QuotaUsed float64 `json:"quota_used"`
|
||||
// CreatedAt time.Time `json:"created_at"`
|
||||
// }
|
||||
type QuotaHistoryItem struct {
|
||||
ID uint `json:"ID"`
|
||||
UserID string `json:"UserID"`
|
||||
ApiGroup string `json:"ApiGroup"`
|
||||
ProjectID string `json:"ProjectID"`
|
||||
Day string `json:"Day"`
|
||||
Account string `json:"Account"`
|
||||
Model string `json:"Model"`
|
||||
QuotaUsed float64 `json:"QuotaUsed"`
|
||||
CreatedAt time.Time `json:"CreatedAt"`
|
||||
}
|
||||
|
||||
// QuotaHistoryResponse 配额历史查询响应
|
||||
type QuotaHistoryResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Data []QuotaHistoryItem `json:"data"`
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// GatewayConfig 网关配置
|
||||
type GatewayConfig struct {
|
||||
BaseURL string `json:"base_url"`
|
||||
Timeout int `json:"timeout"` // 超时时间(秒)
|
||||
}
|
||||
|
||||
// QuotaRule 透传结构(保持与网关一致,不强约束字段)
|
||||
type QuotaRule map[string]interface{}
|
||||
|
||||
// QuotaRulesResponse 配额规则列表响应(与网关一致,Data透传)
|
||||
type QuotaRulesResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
52
internal/models/rbac.go
Normal file
52
internal/models/rbac.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package models
|
||||
|
||||
// RolePagePermission 角色页面权限关联
|
||||
type RolePagePermission struct {
|
||||
BaseModel
|
||||
RoleID uint `gorm:"not null" json:"roleId"`
|
||||
PageID uint `gorm:"not null" json:"pageId"`
|
||||
Role Role `gorm:"foreignKey:RoleID" json:"role,omitempty"`
|
||||
Page Page `gorm:"foreignKey:PageID" json:"page,omitempty"`
|
||||
}
|
||||
|
||||
// Page 页面模型
|
||||
type Page struct {
|
||||
BaseModel
|
||||
Name string `gorm:"size:50;not null" json:"name"`
|
||||
Path string `gorm:"uniqueIndex;size:100;not null" json:"path"`
|
||||
Icon string `gorm:"size:50" json:"icon"`
|
||||
SortOrder int `gorm:"default:0" json:"sortOrder"`
|
||||
IsActive bool `gorm:"default:true" json:"isActive"`
|
||||
}
|
||||
|
||||
func (RolePagePermission) TableName() string {
|
||||
return "admin_role_page_permissions"
|
||||
}
|
||||
|
||||
func (Page) TableName() string {
|
||||
return "admin_pages"
|
||||
}
|
||||
|
||||
// RBAC请求模型
|
||||
type UserRoleAssignRequest struct {
|
||||
UserID uint `json:"userId" binding:"required"`
|
||||
RoleIDs []uint `json:"roleIds"`
|
||||
}
|
||||
|
||||
type RolePagePermissionAssignRequest struct {
|
||||
RoleID uint `json:"roleId" binding:"required"`
|
||||
PageIDs []uint `json:"pageIds"`
|
||||
}
|
||||
|
||||
// 用户权限响应模型
|
||||
type UserPermissionsResponse struct {
|
||||
User User `json:"user"`
|
||||
Roles []Role `json:"roles"`
|
||||
Pages []Page `json:"pages"`
|
||||
}
|
||||
|
||||
// 角色页面权限响应模型
|
||||
type RolePagePermissionsResponse struct {
|
||||
Role Role `json:"role"`
|
||||
Pages []Page `json:"pages"`
|
||||
}
|
||||
141
internal/models/request.go
Normal file
141
internal/models/request.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package models
|
||||
|
||||
// LoginRequest 登录请求
|
||||
type LoginRequest struct {
|
||||
Username string `json:"username" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
}
|
||||
|
||||
// UserCreateRequest 创建用户请求
|
||||
type UserCreateRequest struct {
|
||||
Username string `json:"username" binding:"required,min=3,max=50"`
|
||||
Email string `json:"email" binding:"required,email"`
|
||||
Nickname string `json:"nickname"`
|
||||
SSOProvider string `json:"ssoProvider" binding:"required"`
|
||||
Password string `json:"password" binding:"required,min=8"`
|
||||
RoleID uint `json:"roleId"`
|
||||
}
|
||||
|
||||
// UserUpdateRequest 更新用户请求
|
||||
type UserUpdateRequest struct {
|
||||
Nickname string `json:"nickname"`
|
||||
Email string `json:"email" binding:"email"`
|
||||
Avatar string `json:"avatar"`
|
||||
Status *int `json:"status"`
|
||||
SSOProvider string `json:"ssoProvider"`
|
||||
RoleID *uint `json:"roleId"`
|
||||
}
|
||||
|
||||
// RoleCreateRequest 创建角色请求
|
||||
type RoleCreateRequest struct {
|
||||
Name string `json:"name" binding:"required,min=2,max=50"`
|
||||
Level int `json:"level" binding:"required,min=1,max=5"`
|
||||
Description string `json:"description"`
|
||||
IsDefault bool `json:"isDefault"`
|
||||
}
|
||||
|
||||
// RoleUpdateRequest 更新角色请求
|
||||
type RoleUpdateRequest struct {
|
||||
Name string `json:"name" binding:"required,min=2,max=50"`
|
||||
Level int `json:"level" binding:"required,min=1,max=5"`
|
||||
Description string `json:"description"`
|
||||
IsDefault bool `json:"isDefault"`
|
||||
}
|
||||
|
||||
// PageCreateRequest 创建页面请求
|
||||
type PageCreateRequest struct {
|
||||
Name string `json:"name" binding:"required,min=2,max=50"`
|
||||
Path string `json:"path" binding:"required"`
|
||||
Icon string `json:"icon"`
|
||||
SortOrder int `json:"sortOrder"`
|
||||
IsActive bool `json:"isActive"`
|
||||
}
|
||||
|
||||
// PageUpdateRequest 更新页面请求
|
||||
type PageUpdateRequest struct {
|
||||
Name string `json:"name" binding:"required,min=2,max=50"`
|
||||
Path string `json:"path" binding:"required"`
|
||||
Icon string `json:"icon"`
|
||||
SortOrder int `json:"sortOrder"`
|
||||
IsActive bool `json:"isActive"`
|
||||
}
|
||||
|
||||
// SystemConfigRequest 系统配置请求
|
||||
type SystemConfigRequest struct {
|
||||
Key string `json:"key" binding:"required"`
|
||||
Name string `json:"name" binding:"required"`
|
||||
Value string `json:"value" binding:"required"`
|
||||
Type string `json:"type"`
|
||||
Desc string `json:"desc"`
|
||||
}
|
||||
|
||||
// SystemConfigListRequest 系统配置列表请求
|
||||
type SystemConfigListRequest struct {
|
||||
PageRequest
|
||||
Key string `form:"key"`
|
||||
Name string `form:"name"`
|
||||
Status *int `form:"status"`
|
||||
}
|
||||
|
||||
// SystemConfigUpdateRequest 系统配置更新请求
|
||||
type SystemConfigUpdateRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Value string `json:"value" binding:"required"`
|
||||
Type string `json:"type"`
|
||||
Desc string `json:"desc"`
|
||||
}
|
||||
|
||||
// SystemConfigUpdateStatusRequest 系统配置状态更新请求
|
||||
type SystemConfigUpdateStatusRequest struct {
|
||||
Status int `json:"status" binding:"required,oneof=0 1"`
|
||||
}
|
||||
|
||||
// PageRequest 分页请求
|
||||
type PageRequest struct {
|
||||
Page int `form:"page" binding:"omitempty,min=1"`
|
||||
Size int `form:"size" binding:"omitempty,min=1,max=100"`
|
||||
}
|
||||
|
||||
// UserListRequest 用户列表请求
|
||||
type UserListRequest struct {
|
||||
PageRequest
|
||||
Username string `form:"username"`
|
||||
Email string `form:"email"`
|
||||
Status *int `form:"status"`
|
||||
}
|
||||
|
||||
// RoleListRequest 角色列表请求
|
||||
type RoleListRequest struct {
|
||||
PageRequest
|
||||
Name string `form:"name"`
|
||||
Status *int `form:"status"`
|
||||
}
|
||||
|
||||
// PageListRequest 页面列表请求
|
||||
type PageListRequest struct {
|
||||
PageRequest
|
||||
Name string `form:"name"`
|
||||
Path string `form:"path"`
|
||||
IsActive *bool `form:"isActive"`
|
||||
}
|
||||
|
||||
// LoginLogListRequest 登录日志列表请求
|
||||
type LoginLogListRequest struct {
|
||||
PageRequest
|
||||
Username string `form:"username"`
|
||||
IP string `form:"ip"`
|
||||
Status *int `form:"status"`
|
||||
StartTime string `form:"startTime"`
|
||||
EndTime string `form:"endTime"`
|
||||
}
|
||||
|
||||
// OperationLogListRequest 操作日志列表请求
|
||||
type OperationLogListRequest struct {
|
||||
PageRequest
|
||||
Username string `form:"username"`
|
||||
Module string `form:"module"`
|
||||
Operation string `form:"operation"`
|
||||
Status *int `form:"status"`
|
||||
StartTime string `form:"startTime"`
|
||||
EndTime string `form:"endTime"`
|
||||
}
|
||||
99
internal/models/response.go
Normal file
99
internal/models/response.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package models
|
||||
|
||||
// Response 统一响应结构
|
||||
type Response struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// PageResponse 分页响应结构
|
||||
type PageResponse struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
Total int64 `json:"total"`
|
||||
Page int `json:"page"`
|
||||
Size int `json:"size"`
|
||||
}
|
||||
|
||||
// LoginResponse 登录响应
|
||||
type LoginResponse struct {
|
||||
Token string `json:"token"`
|
||||
User User `json:"user"`
|
||||
ExpireAt int64 `json:"expireAt"`
|
||||
}
|
||||
|
||||
// UserListResponse 用户列表响应
|
||||
type UserListResponse struct {
|
||||
Users []User `json:"users"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
// PageTreeResponse 页面树响应
|
||||
type PageTreeResponse struct {
|
||||
Pages []Page `json:"pages"`
|
||||
}
|
||||
|
||||
// SystemConfigResponse 系统配置响应
|
||||
type SystemConfigResponse struct {
|
||||
Configs []SystemConfig `json:"configs"`
|
||||
}
|
||||
|
||||
// 响应码常量
|
||||
const (
|
||||
CodeSuccess = 200
|
||||
CodeError = 500
|
||||
CodeInvalid = 400
|
||||
CodeUnauthorized = 401
|
||||
CodeForbidden = 403
|
||||
CodeNotFound = 404
|
||||
)
|
||||
|
||||
// 响应消息常量
|
||||
const (
|
||||
MsgSuccess = "操作成功"
|
||||
MsgError = "操作失败"
|
||||
MsgInvalid = "参数错误"
|
||||
MsgUnauthorized = "未授权"
|
||||
MsgForbidden = "禁止访问"
|
||||
MsgNotFound = "资源不存在"
|
||||
)
|
||||
|
||||
// NewResponse 创建响应
|
||||
func NewResponse(code int, message string, data interface{}) *Response {
|
||||
return &Response{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
// NewSuccessResponse 创建成功响应
|
||||
func NewSuccessResponse(data interface{}) *Response {
|
||||
return &Response{
|
||||
Code: CodeSuccess,
|
||||
Message: MsgSuccess,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
// NewErrorResponse 创建错误响应
|
||||
func NewErrorResponse(message string) *Response {
|
||||
return &Response{
|
||||
Code: CodeError,
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
// NewPageResponse 创建分页响应
|
||||
func NewPageResponse(data interface{}, total int64, page, size int) *PageResponse {
|
||||
return &PageResponse{
|
||||
Code: CodeSuccess,
|
||||
Message: MsgSuccess,
|
||||
Data: data,
|
||||
Total: total,
|
||||
Page: page,
|
||||
Size: size,
|
||||
}
|
||||
}
|
||||
196
internal/models/sso.go
Normal file
196
internal/models/sso.go
Normal file
@@ -0,0 +1,196 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// SSOConfig SSO配置结构体
|
||||
type SSOConfig struct {
|
||||
// SSO服务器地址
|
||||
SSOServerURL string `json:"sso_server_url"`
|
||||
// OAuth客户端ID
|
||||
ClientID string `json:"client_id"`
|
||||
// OAuth客户端密钥
|
||||
ClientSecret string `json:"client_secret"`
|
||||
// 重定向URI
|
||||
RedirectURI string `json:"redirect_uri"`
|
||||
// 请求作用域
|
||||
Scope string `json:"scope"`
|
||||
// 资源受众
|
||||
ResourceAud string `json:"resource_aud"`
|
||||
// HTTP超时时间
|
||||
Timeout time.Duration `json:"timeout"`
|
||||
}
|
||||
|
||||
// TokenResponse OAuth令牌响应
|
||||
type TokenResponse struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
IDToken string `json:"id_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
TokenType string `json:"token_type"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
}
|
||||
|
||||
// SSOUserInfo SSO API 返回的用户信息(用于解析 SSO 响应)
|
||||
type SSOUserInfo struct {
|
||||
Sub string `json:"sub"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
PreferredUsername string `json:"preferred_username,omitempty"`
|
||||
Roles interface{} `json:"roles,omitempty"` // 使用 interface{} 来接受任何类型
|
||||
}
|
||||
|
||||
// UserInfo 用户信息(用于应用程序内部)
|
||||
type UserInfo struct {
|
||||
Sub string `json:"sub"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
PreferredUsername string `json:"preferred_username,omitempty"`
|
||||
Pages []Page `json:"pages,omitempty"`
|
||||
Roles []Role `json:"roles,omitempty"`
|
||||
}
|
||||
|
||||
// OpenIDConfiguration OpenID配置
|
||||
type OpenIDConfiguration struct {
|
||||
Issuer string `json:"issuer"`
|
||||
AuthorizationEndpoint string `json:"authorization_endpoint"`
|
||||
TokenEndpoint string `json:"token_endpoint"`
|
||||
UserinfoEndpoint string `json:"userinfo_endpoint"`
|
||||
JwksURI string `json:"jwks_uri"`
|
||||
ResponseTypesSupported []string `json:"response_types_supported"`
|
||||
SubjectTypesSupported []string `json:"subject_types_supported"`
|
||||
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"`
|
||||
CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported"`
|
||||
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
|
||||
}
|
||||
|
||||
// JWKS JSON Web Key Set
|
||||
type JWKS struct {
|
||||
Keys []map[string]interface{} `json:"keys"`
|
||||
}
|
||||
|
||||
// AuthCodeRequest 授权码请求参数
|
||||
type AuthCodeRequest struct {
|
||||
ClientID string `json:"client_id"`
|
||||
RedirectURI string `json:"redirect_uri"`
|
||||
ResponseType string `json:"response_type"`
|
||||
Scope string `json:"scope"`
|
||||
State string `json:"state"`
|
||||
CodeChallenge string `json:"code_challenge"`
|
||||
CodeChallengeMethod string `json:"code_challenge_method"`
|
||||
Prompt string `json:"prompt"`
|
||||
}
|
||||
|
||||
// TokenRequest 令牌请求参数
|
||||
type TokenRequest struct {
|
||||
GrantType string `json:"grant_type"`
|
||||
Code string `json:"code"`
|
||||
RedirectURI string `json:"redirect_uri"`
|
||||
CodeVerifier string `json:"code_verifier"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
// Session 用户会话信息
|
||||
type Session struct {
|
||||
UserID string `json:"user_id"`
|
||||
UserInfo *UserInfo `json:"user_info"`
|
||||
TokenInfo *TokenResponse `json:"token_info"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
}
|
||||
|
||||
// SSOLoginRequest SSO登录请求
|
||||
type SSOLoginRequest struct {
|
||||
// 可以为空,用于初始化SSO登录流程
|
||||
}
|
||||
|
||||
// SSOLoginResponse SSO登录响应
|
||||
type SSOLoginResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
AuthURL string `json:"auth_url"`
|
||||
State string `json:"state"`
|
||||
CodeVerifier string `json:"code_verifier"`
|
||||
}
|
||||
|
||||
// SSOCallbackRequest SSO回调请求
|
||||
type SSOCallbackRequest struct {
|
||||
Code string `json:"code" binding:"required"`
|
||||
State string `json:"state" binding:"required"`
|
||||
}
|
||||
|
||||
// SSOCallbackResponse SSO回调响应
|
||||
type SSOCallbackResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
AccessToken string `json:"access_token,omitempty"`
|
||||
IDToken string `json:"id_token,omitempty"`
|
||||
RefreshToken string `json:"refresh_token,omitempty"`
|
||||
ExpiresIn int `json:"expires_in,omitempty"`
|
||||
UserInfo *UserInfo `json:"user_info,omitempty"`
|
||||
UUID string `json:"uuid,omitempty"`
|
||||
}
|
||||
|
||||
// RefreshTokenRequest 刷新令牌请求
|
||||
type RefreshTokenRequest struct {
|
||||
RefreshToken string `json:"refresh_token" binding:"required"`
|
||||
}
|
||||
|
||||
// RefreshTokenResponse 刷新令牌响应
|
||||
type RefreshTokenResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
AccessToken string `json:"access_token,omitempty"`
|
||||
IDToken string `json:"id_token,omitempty"`
|
||||
RefreshToken string `json:"refresh_token,omitempty"`
|
||||
ExpiresIn int `json:"expires_in,omitempty"`
|
||||
}
|
||||
|
||||
// LogoutRequest 登出请求
|
||||
type LogoutRequest struct {
|
||||
// AccessToken字段保留用于向后兼容,但实际不再使用
|
||||
AccessToken string `json:"access_token,omitempty"`
|
||||
}
|
||||
|
||||
// LogoutResponse 登出响应
|
||||
type LogoutResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// UserInfoResponse 用户信息响应
|
||||
type UserInfoResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
UserInfo *UserInfo `json:"user_info,omitempty"`
|
||||
}
|
||||
|
||||
// PKCEState PKCE状态信息
|
||||
type PKCEState struct {
|
||||
BaseModel
|
||||
State string `gorm:"size:191;uniqueIndex;column:state" json:"state"`
|
||||
CodeVerifier string `gorm:"column:code_verifier" json:"code_verifier"`
|
||||
}
|
||||
|
||||
func (p *PKCEState) TableName() string {
|
||||
return "admin_pkce_states"
|
||||
}
|
||||
|
||||
// LoginInfo 用户登录信息
|
||||
type LoginInfo struct {
|
||||
BaseModel
|
||||
UserID int `gorm:"column:user_id;not null" json:"user_id"`
|
||||
UserName string `gorm:"column:user_name;size:100;not null" json:"user_name"`
|
||||
Email string `gorm:"column:email;size:255;not null" json:"email"`
|
||||
UUID string `gorm:"column:uuid;size:100;not null" json:"uuid"`
|
||||
IsOnline bool `gorm:"column:is_online;default:false" json:"is_online"`
|
||||
}
|
||||
|
||||
func (l *LoginInfo) TableName() string {
|
||||
return "admin_login_infos"
|
||||
}
|
||||
|
||||
// ErrorResponse 错误响应
|
||||
type ErrorResponse struct {
|
||||
Error string `json:"error"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
63
internal/models/user_feedback.go
Normal file
63
internal/models/user_feedback.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
// UserFeedback 用户反馈模型
|
||||
type UserFeedback struct {
|
||||
ID int64 `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||
UID uint64 `gorm:"column:uid;not null;index;comment:用户ID" json:"user_id"`
|
||||
Content string `gorm:"type:text;not null;comment:反馈内容" json:"content"`
|
||||
FileKeys string `gorm:"column:file_keys;type:json;not null;comment:关联文件Key列表" json:"file_keys"`
|
||||
Status int `gorm:"default:0;comment:0未处理 1已处理" json:"status"`
|
||||
HandledBy *int `gorm:"column:handled_by;comment:处理人" json:"handled_by"`
|
||||
HandledAt *time.Time `gorm:"column:handled_at;comment:处理时间" json:"handled_at"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;index" json:"-"`
|
||||
}
|
||||
|
||||
// TableName 指定数据库表名
|
||||
func (UserFeedback) TableName() string {
|
||||
return "m_problem_feedbacks"
|
||||
}
|
||||
|
||||
// UserFeedbackListRequest 用户反馈列表请求
|
||||
type UserFeedbackListRequest struct {
|
||||
Page int `json:"page" form:"page" binding:"min=1"`
|
||||
PageSize int `json:"page_size" form:"page_size" binding:"min=1,max=100"`
|
||||
Status *int `json:"status" form:"status"`
|
||||
UserID *int `json:"user_id" form:"user_id"`
|
||||
Keyword string `json:"keyword" form:"keyword"`
|
||||
StartTime string `json:"start_time" form:"start_time"`
|
||||
EndTime string `json:"end_time" form:"end_time"`
|
||||
}
|
||||
|
||||
// UserFeedbackListResponse 用户反馈列表响应
|
||||
type UserFeedbackListResponse struct {
|
||||
List []UserFeedbackItem `json:"list"`
|
||||
Total int64 `json:"total"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
}
|
||||
|
||||
// UserFeedbackItem 列表项(扩展返回可访问URL)
|
||||
type UserFeedbackItem struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID uint64 `json:"user_id"`
|
||||
Content string `json:"content"`
|
||||
FileKeys []string `json:"file_keys"`
|
||||
FileContents []string `json:"file_contents"` // Base64编码的图片内容
|
||||
Status int `json:"status"`
|
||||
HandledBy *int `json:"handled_by"`
|
||||
HandledAt *time.Time `json:"handled_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// UserFeedbackMarkRequest 标记处理请求
|
||||
type UserFeedbackMarkRequest struct {
|
||||
Note string `json:"note" form:"note"`
|
||||
}
|
||||
59
internal/models/user_level_config.go
Normal file
59
internal/models/user_level_config.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
// UserLevelConfig 用户等级配置表
|
||||
type UserLevelConfig struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;autoIncrement;comment:主键ID"`
|
||||
LevelName string `json:"level_name" gorm:"not null;uniqueIndex:uk_level_name;type:varchar(50);comment:等级名称"`
|
||||
LevelCode string `json:"level_code" gorm:"not null;uniqueIndex:uk_level_code;type:varchar(50);comment:等级代码"`
|
||||
ProjectLimit int `json:"project_limit" gorm:"not null;default:0;comment:项目数限制,0表示不限"`
|
||||
CoderVMLimit int `json:"coder_vm_limit" gorm:"not null;default:0;comment:Coder VM上限,0表示不限"`
|
||||
BrowserVMLimit int `json:"browser_vm_limit" gorm:"not null;default:0;comment:Browser VM上限,0表示不限"`
|
||||
ProcessLimit int `json:"process_limit" gorm:"not null;default:0;comment:进程上限,0表示不限"`
|
||||
Description string `json:"description" gorm:"type:varchar(255);comment:等级描述"`
|
||||
SortOrder int `json:"sort_order" gorm:"not null;default:0;comment:排序顺序"`
|
||||
Status int `json:"status" gorm:"not null;default:1;comment:状态 1-启用 0-禁用"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (UserLevelConfig) TableName() string {
|
||||
return "admin_user_level_configs"
|
||||
}
|
||||
|
||||
// UserLevelConfigListRequest 列表请求
|
||||
type UserLevelConfigListRequest struct {
|
||||
LevelName string `form:"level_name"`
|
||||
Status *int `form:"status"`
|
||||
Page int `form:"page,default=1"`
|
||||
Size int `form:"size,default=20"`
|
||||
}
|
||||
|
||||
// UserLevelConfigCreateRequest 创建请求
|
||||
type UserLevelConfigCreateRequest struct {
|
||||
LevelName string `json:"level_name" binding:"required,min=1,max=50"`
|
||||
LevelCode string `json:"level_code" binding:"required,min=1,max=50"`
|
||||
ProjectLimit int `json:"project_limit" binding:"min=0"`
|
||||
CoderVMLimit int `json:"coder_vm_limit" binding:"min=0"`
|
||||
BrowserVMLimit int `json:"browser_vm_limit" binding:"min=0"`
|
||||
ProcessLimit int `json:"process_limit" binding:"min=0"`
|
||||
Description string `json:"description" binding:"max=255"`
|
||||
SortOrder int `json:"sort_order"`
|
||||
}
|
||||
|
||||
// UserLevelConfigUpdateRequest 更新请求
|
||||
type UserLevelConfigUpdateRequest struct {
|
||||
LevelName string `json:"level_name" binding:"required,min=1,max=50"`
|
||||
ProjectLimit int `json:"project_limit" binding:"min=0"`
|
||||
CoderVMLimit int `json:"coder_vm_limit" binding:"min=0"`
|
||||
BrowserVMLimit int `json:"browser_vm_limit" binding:"min=0"`
|
||||
ProcessLimit int `json:"process_limit" binding:"min=0"`
|
||||
Description string `json:"description" binding:"max=255"`
|
||||
SortOrder int `json:"sort_order"`
|
||||
}
|
||||
|
||||
// UserLevelConfigUpdateStatusRequest 更新状态请求
|
||||
type UserLevelConfigUpdateStatusRequest struct {
|
||||
Status int `json:"status" binding:"required,oneof=0 1"`
|
||||
}
|
||||
27
internal/models/user_project_quota.go
Normal file
27
internal/models/user_project_quota.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// UserProjectQuota 用户资源配额上限
|
||||
// 仅记录用户在项目/虚拟机/进程三个资源维度的数量上限
|
||||
type UserProjectQuota struct {
|
||||
ID uint `gorm:"primarykey;column:id" json:"id"`
|
||||
UserID string `gorm:"type:varchar(64);uniqueIndex;not null;column:user_id" json:"user_id"`
|
||||
ProjectLimit int `gorm:"not null;default:0;column:project_limit" json:"project_limit"`
|
||||
CoderVMLimit int `gorm:"not null;default:0;column:coder_vm_limit" json:"coder_vm_limit"`
|
||||
BrowserVMLimit int `gorm:"not null;default:0;column:browser_vm_limit" json:"browser_vm_limit"`
|
||||
ProcessLimit int `gorm:"not null;default:0;column:process_limit" json:"process_limit"`
|
||||
Enabled bool `gorm:"not null;default:true;column:enabled" json:"enabled"`
|
||||
Description string `gorm:"type:varchar(255);column:description" json:"description"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index;column:deleted_at" json:"deleted_at"`
|
||||
}
|
||||
|
||||
func (UserProjectQuota) TableName() string {
|
||||
return "user_project_quota"
|
||||
}
|
||||
Reference in New Issue
Block a user