feat: 初始化 ChatGPT Team 管理后端项目

- 添加用户认证模块 (JWT + 密码管理)
- 添加 ChatGPT 账户管理功能
- 添加卡密管理功能 (创建、批量生成、查询)
- 添加邀请功能
- 配置数据库迁移和路由系统
This commit is contained in:
sar
2026-01-13 14:42:56 +08:00
commit 42c423bd32
29 changed files with 2969 additions and 0 deletions

View File

@@ -0,0 +1,213 @@
package handler
import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"net/http"
"strings"
"time"
"gpt-manager-go/internal/middleware"
"gpt-manager-go/internal/models"
"gpt-manager-go/internal/repository"
)
// CardKeyHandler 卡密处理器
type CardKeyHandler struct {
repo *repository.CardKeyRepository
}
// NewCardKeyHandler 创建处理器
func NewCardKeyHandler(repo *repository.CardKeyRepository) *CardKeyHandler {
return &CardKeyHandler{repo: repo}
}
// CreateCardKeyRequest 创建卡密请求
type CreateCardKeyRequest struct {
ValidityDays int `json:"validity_days"` // 有效期天数默认30
MaxUses int `json:"max_uses"` // 最大使用次数默认1
}
// BatchCreateCardKeyRequest 批量创建卡密请求
type BatchCreateCardKeyRequest struct {
Count int `json:"count"` // 创建数量
ValidityDays int `json:"validity_days"` // 有效期天数默认30
MaxUses int `json:"max_uses"` // 最大使用次数默认1
}
// CardKeyResponse 卡密响应
type CardKeyResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Data *models.CardKey `json:"data,omitempty"`
Keys []*models.CardKey `json:"keys,omitempty"`
}
// Handle 处理卡密接口 (GET: 列表, POST: 创建)
func (h *CardKeyHandler) Handle(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
h.list(w, r)
case http.MethodPost:
h.create(w, r)
default:
respondJSON(w, http.StatusMethodNotAllowed, CardKeyResponse{
Success: false,
Message: "Method not allowed",
})
}
}
// create 创建单个卡密
func (h *CardKeyHandler) create(w http.ResponseWriter, r *http.Request) {
var req CreateCardKeyRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
// 允许空请求体,使用默认值
req = CreateCardKeyRequest{}
}
// 设置默认值
if req.ValidityDays <= 0 {
req.ValidityDays = 30
}
if req.MaxUses <= 0 {
req.MaxUses = 1
}
// 获取当前用户
claims := middleware.GetUserFromContext(r.Context())
// 生成卡密
cardKey := &models.CardKey{
Key: generateCardKey(),
MaxUses: req.MaxUses,
UsedCount: 0,
ValidityType: "custom",
ExpiresAt: time.Now().AddDate(0, 0, req.ValidityDays),
IsActive: true,
CreatedByID: claims.UserID,
CreatedAt: time.Now(),
}
if err := h.repo.Create(cardKey); err != nil {
respondJSON(w, http.StatusInternalServerError, CardKeyResponse{
Success: false,
Message: "Failed to create card key: " + err.Error(),
})
return
}
respondJSON(w, http.StatusCreated, CardKeyResponse{
Success: true,
Message: "Card key created successfully",
Data: cardKey,
})
}
// BatchCreate 批量创建卡密 (POST /api/cardkeys/batch)
func (h *CardKeyHandler) BatchCreate(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
respondJSON(w, http.StatusMethodNotAllowed, CardKeyResponse{
Success: false,
Message: "Method not allowed",
})
return
}
var req BatchCreateCardKeyRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
respondJSON(w, http.StatusBadRequest, CardKeyResponse{
Success: false,
Message: "Invalid request body",
})
return
}
// 验证和设置默认值
if req.Count <= 0 {
respondJSON(w, http.StatusBadRequest, CardKeyResponse{
Success: false,
Message: "Count must be greater than 0",
})
return
}
if req.Count > 100 {
respondJSON(w, http.StatusBadRequest, CardKeyResponse{
Success: false,
Message: "Count cannot exceed 100",
})
return
}
if req.ValidityDays <= 0 {
req.ValidityDays = 30
}
if req.MaxUses <= 0 {
req.MaxUses = 1
}
// 获取当前用户
claims := middleware.GetUserFromContext(r.Context())
// 批量创建
var createdKeys []*models.CardKey
expiresAt := time.Now().AddDate(0, 0, req.ValidityDays)
for i := 0; i < req.Count; i++ {
cardKey := &models.CardKey{
Key: generateCardKey(),
MaxUses: req.MaxUses,
UsedCount: 0,
ValidityType: "custom",
ExpiresAt: expiresAt,
IsActive: true,
CreatedByID: claims.UserID,
CreatedAt: time.Now(),
}
if err := h.repo.Create(cardKey); err != nil {
// 如果创建失败,返回已创建的卡密
respondJSON(w, http.StatusInternalServerError, CardKeyResponse{
Success: false,
Message: "Failed to create some card keys",
Keys: createdKeys,
})
return
}
createdKeys = append(createdKeys, cardKey)
}
respondJSON(w, http.StatusCreated, CardKeyResponse{
Success: true,
Message: "Card keys created successfully",
Keys: createdKeys,
})
}
// list 获取卡密列表
func (h *CardKeyHandler) list(w http.ResponseWriter, r *http.Request) {
cardKeys, err := h.repo.FindAll()
if err != nil {
respondJSON(w, http.StatusInternalServerError, CardKeyResponse{
Success: false,
Message: "Failed to fetch card keys",
})
return
}
respondJSON(w, http.StatusOK, CardKeyResponse{
Success: true,
Message: "OK",
Keys: cardKeys,
})
}
// generateCardKey 生成卡密格式: XXXX-XXXX-XXXX-XXXX
func generateCardKey() string {
bytes := make([]byte, 8)
rand.Read(bytes)
hex := strings.ToUpper(hex.EncodeToString(bytes))
return hex[0:4] + "-" + hex[4:8] + "-" + hex[8:12] + "-" + hex[12:16]
}