feat():learning后台管理项目初始化

This commit is contained in:
yuj
2025-12-04 16:23:46 +08:00
parent 39886d50d2
commit 88e048f4d1
154 changed files with 28966 additions and 6 deletions

View 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"`
}

View 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
View 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"
}

View 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"`
}

View 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"`
}

View 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"
)

View 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"`
}

View 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
View 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
View 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"`
}

View 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
View 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"`
}

View 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"`
}

View 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"`
}

View 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"
}